Декабрь 19, 2019 Просмотры 4 просмотра

Javascript: примеры работы с объектами

С развитием интернет-технологий JavaScript давно уже стал самостоятельным языком разработки интерактивных элементов в наших веб-приложениях. И если раньше многие разработчики его использовали лишь для скромных операций, к примеру, приветствия пользователя, бегущей строки с последними новостями или проверки правильности заполнения форм, а падающие снежинки на странице какого-нибудь ресурса вызывали восторг у посетителей, то теперь появилась отдельная специальность - разработчик на JavaScript, появились среды для разработки сложных javascript-приложений, появились кросс-браузерные framework'и и библиотеки для ускорения разработки, а сами возможности языка обогатились новыми красками.

Возможно, в одной из статей мы рассмотрим возможности Prototype.js (http://www.prototypejs.org/) или очень понравившейся мне The Yahoo! User Interface (YUI) Library (http://developer.yahoo.com/yui/), но сейчас мы поговорим о более простых, но не менее интересных вещах.

Среда разработки

Начнём со среды - в своих разработках я использую Aptana IDE (http://aptana.com/download_all.php - заходим по ссылке, выбираем инсталлятор для своей ОС, ставим и пробуем). На мой взгляд, очень вменяемый редактор, как бы ни был хорош  встраиваемый в FireFox плагин FireBug (его я обычно использую для отладки), но для написания сложных больших скриптов он все равно неудобен.

Кратко об объектах в JS и манипуляциях с ними

Javascript прекрасен тем, что любая его переменная, независимо от типа, есть объект. Причем в JavaScript имеется всего три типа объектов: встроенные объекты, объекты браузера и объекты, которые программист создает самостоятельно.

Для работы с документами HTML в языке JavaScript имеется отдельный объект с названием document. Этот объект относится к встроенным и всегда создается при загрузке документа HTML в окно браузера.

Попробуем, используя простейший элемент, создать объект и произвести с ним простые действия.

Итак:

<div id="example">Test html element</div>
<script language="Javascript">
//Создаем объект JavaScript
var dv = document.getElementById('example');

//Можно переопределить методы объекта
// попробуйте кликнуть внутрь div'a
dv.onclick = function() {
        dv.style.fontSize = parseInt(dv.style.fontSize) ==  22 ? 14+'px': 22+'px';
}
//Навести мышку
dv.onmouseover = function() {
        dv.style.backgroundColor = '#cccccc';
}
//Или увести её
dv.onmouseout = function() {
        dv.style.backgroundColor = '#ffffff';
}
</script>
Это простейшие примеры действий, производящихся при определенном событии и воздействующих на объект.

Любой объект JavaScript может содержать в себе неограниченное число свойств и методов.

К примеру, если переписать функцию dv.onclick()
dv.onclick = function() {
        dv.setFontSize();
}
сам метод задать setFontSize следующим образом
dv.setFontSize = function() {
        dv.style.fontSize = parseInt(dv.style.fontSize) ==  dv.newFontSize ? dv.defaultFontSize+'px': dv.newFontSize+'px';
}
а свойства defaultFontSize и newFontSize определить как
dv.defaultFontSize = 14;
dv.newFontSize = 22;

Наш код примет вид
var dv = document.getElementById('example');
dv.defaultFontSize = 14;
dv.newFontSize = 22;
dv.setFontSize = function() {
        dv.style.fontSize = parseInt(dv.style.fontSize) ==  dv.newFontSize ? dv.defaultFontSize+'px': dv.newFontSize+'px';
}
dv.onclick = function() {
        dv.setFontSize();
}
... onmouseover()....onmouseout() - останутся такими же, объект dv пополнится двумя свойствами и одним методом всё будет работать, но и это ещё не всё. Поскольку методы и свойства принадлежат объекту dv, мы можем заменить все ссылки на объект dv внутри функций на его указатель this.

Получаем
<script language="Javascript">
var dv = document.getElementById('example');
dv.defaultFontSize = 14;
dv.newFontSize = 22;
dv.setFontSize = function() {
        this.style.fontSize = parseInt(this.style.fontSize) ==  this.newFontSize ? this.defaultFontSize+'px': this.newFontSize+'px';
}
dv.onclick = function() {
        this.setFontSize();
}
dv.onmouseover = function() {
        this.style.backgroundColor = '#cccccc';
}
dv.onmouseout = function() {
        this.style.backgroundColor = '#ffffff';
}
</script>

Но пример с размером шрифта слишком прост. Рассмотрим более сложный пример c использованием методов других объектов.

Сложный пример работы с объектами

Мы попробуем сделать, чтобы при нажатии на какую-то кнопку на странице наш слой менял цвет от одного к другому, причем в градиентной последовательности.

Что для этого нужно?
1. Объект, которым мы будем манипулировать.
2. Цвет, с которого начнем, и цвет, которым закончим.
3. Функция, которая способна проделать такую операцию. Назовем её changeColor. На её примере я постараюсь показать несколько интересных приемов.

Но поскольку одной функции нам будет мало, мы будем использовать прототипы (prototype), заодно посмотрев, как они работают в JavaScript.

<div id="example" style="width:150px; height:150px;">Test html element</div><br><br><input type="button" id="button" value='Запустить изменение цвета'>
<script language="Javascript">
//Если абстрагироваться от того, что в JavaScript нет классов, эту функцию можно считать своего рода конструктором.
//В ней мы определяем один-единственный объект, с фоном которого будем работать.
function changeBgColor(obj) {
        this.elmt = obj;
}
(
function() {
        //Создаем прототип как отдельный объект.
        //Он, если можно так сказать, наследует метод changeBgColor().
        //Соответственно, ему доступен объект this.elmt.
        //Методы, определенные в этом объекте, доступны лишь через новый экземпляр new changeBgColor(),
        //то есть к примеру changeBgColor.run(); вызовет вполне логичную ошибку.
        changeBgColor.prototype = {

                run : function (fromColor, toColor, FramePerSecond, ChangeDuration)
                {
                        //Задаем стартовые параметры
                        //Количество кадров в секунду
                        if (!FramePerSecond)
                                FramePerSecond = 30;
                        //Как долго будем менять цвет - по умолчанию 1 секунда
                        if (!ChangeDuration)
                                ChangeDuration = 1000;
                        //С какого цвета начнем
                        if (!fromColor || fromColor == '#')
                                fromColor = '#FF0000';
                        //каким закончим - по умолчанию заканчиваем тем же цветом, что и начали,
                        //получается эффект вспышки
                        if (!toColor)
                                toColor = this.getStartBgColor();
                               
                        //Считаем колличество кадров
                        var frames = Math.round(FramePerSecond * (ChangeDuration / 1000));
                        //Интервалы между кадрами
                        var intervalValue = ChangeDuration / frames;
                        //Добавляем задержку
                        var delayValue = intervalValue;
                        //Начальный фрейм
                        var StartFrame = 0;
                       
                        //Дальше проверяем, что цвет задан правильно
                        if (fromColor.length < 7)
                                fromColor += fromColor.substr(1,3);
                               
                        if (toColor.length < 7)
                                toColor += toColor.substr(1,3);
                        // Для создания эффекта вспышки и последовательного (градиентного) изменения цвета
                        // необходимо разбить цвета на составляющие коммоненты RGB цвета
                        var redFrom = parseInt(fromColor.substr(1,2),16);
                        var greenfrom = parseInt(fromColor.substr(3,2),16);
                        var blueFrom = parseInt(fromColor.substr(5,2),16);
                        var redTo = parseInt(toColor.substr(1,2),16);
                        var greenTo = parseInt(toColor.substr(3,2),16);
                        var blueTo = parseInt(toColor.substr(5,2),16);
                       
                        var red, green, blue, newColor;
                        //Дальше кадрирование
                        while (StartFrame < frames)
                        {
                                //Алгоритм градиентного изменения был подсмотрен мной на algolist.ru.
                                //К сожалению, ссылку на первоисточник я не нашёл.
                                red = Math.floor(redFrom * ((frames-StartFrame)/frames) + redTo * (StartFrame/frames));
                                green = Math.floor(greenfrom * ((frames-StartFrame)/frames) + greenTo * (StartFrame/frames));
                                blue = Math.floor(blueFrom * ((frames-StartFrame)/frames) + blueTo * (StartFrame/frames));
                                //Собираем составляющие назад в цвет
                                newColor = this.makeColor(red, green, blue);
                               
                                //Запускаем градиентное изменение с задержкой delayValue
                                setTimeout("ColorChanger.setBgColor('"+newColor+"')", delayValue);
       
                                StartFrame++;
                                delayValue = intervalValue * StartFrame;
                        }
                        //Ну и если у нас только один кадр,
                        // задаем цвет и завершаем работу.
                        setTimeout("ColorChanger.setBgColor('"+toColor+"')", delayValue);
                },
               
                makeColor : function (red, green, blue)
                {
                        red = red.toString(16);
                        if (red.length == 1)
                                red = '0' + red;
                               
                        green = green.toString(16);
                        if (green.length == 1)
                                green = '0' + green;
                               
                        blue = blue.toString(16);
                        if (blue.length == 1)
                                blue = '0' + blue;
                               
                        return "#" + red + green + blue;
                },
                setBgColor : function (newColor)
                {
                        this.elmt.style.backgroundColor = newColor;
                },
                getStartBgColor : function() {
                        //Мы не хотим изменять исходный объект, поэтому копируем его
                        var obj = this.elmt;
                        while(obj)
                        {
                                var color;
                                if (window.getComputedStyle)
                                        color = window.getComputedStyle(obj,null).getPropertyValue("background-color");
                                       
                                if (obj.currentStyle)
                                        color = obj.currentStyle.backgroundColor;
                                       
                                if ((color != '' && color != 'transparent') || obj.tagName == 'BODY')
                                        break;
                                       
                                obj = obj.parentNode;
                        }
                        if (color == undefined || color == "" || color == "transparent")
                                color = "#FFFFFF";
                               
                        var rgbValue = color.match(/rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/);
                       
                        if (rgbValue)
                                color = this.makeColor(parseInt(rgbValue[1]),parseInt(rgbValue[2]),parseInt(rgbValue[3]));
                               
                        return color;
                }
        }
})();
</script>
Заставить работать всё это дело можно примерно так:
var dv = document.getElementById('example');
var btn = document.getElementById('button');
btn.onclick=function() {
        ColorChanger = new changeBgColor(dv);
        ColorChanger.run();

Теперь некоторые пояснения:

Конструкция
function changeBgColor(obj) {
        this.elmt = obj;
}
(
function() {
...
})();
действительно необходима. Дело в том, что если написать просто
function changeBgColor(obj) {
        changeBgColor.prototype = {
                ...
        }
}
то при создании объекта ColorChanger метод run() прототипа исходного объекта не будет доступен. Он станет доступен лишь при повторном вызове, поэтому вызовет ошибку.

Ещё одна тонкость: если объявить объект как var ColorChanger = new changeBgColor(dv), то setTimeout("ColorChanger.setBgColor('"+newColor+"')", delayValue) перестанет работать. Это происходит потому, что при объявлении переменной как var она становится локальной переменной метода btn.onclick() и не доступна извне.

На этом всё.

Все исходные коды в рабочем виде можно скачать в присоединенном файле.

Надеюсь, вы узнали для себя что-нибудь новое.


Просмотры 4 просмотра

Статистика просмотров страницы:

  • за последние 3 месяца (Январь 2021 - Март 2021) - 4;
  • за последний год (Апрель 2020 - Март 2021) - 4;

Отзывы

Админ
Отлично!
Март 28 Админ

Статьи и обзоры Все статьи

Современный бизнес вынужден работать в непростых условиях регулярных перегрузок и ...
Разработка веб сайтов – одна из самых востребованных услуг в ...
В прошлом году многие впервые попробовали работать удалённо — такой ...
Уже более 70 десятилетий телевизор является наиболее популярным бытовым прибором ...