пятница, 29 апреля 2011 г.

Пишем свой Javascript Фреймворк (Урок 2)

И так, в прошлом уроке мы подготовили файлы, подключили движок селекторов.
Теперь же мы должны приступить к созданию функции для поиска элементов, ну и непосредственно сам объект нашего фреймворка.
Откройте файл framework.js,  в нем мы и будем писать весь код нашего фреймворка.
Напишите в файле следующее:

(function(window) {

})(window);
Тут мы создаем исполняемую функцию, в которой и будет описываться наш фреймворк.
Далее мы создадим функцию которая будет возвращать объект фреймворка. Назовем ее так же как и в JQuery - $ (знак доллара).

(function(window) {
     function $( selector, context ) {
          return new walik(selector, context);
     }
})(window);
Функция ничего не делает кроме как просто возвращает объект фреймворка (в моем случае объект называется - walik. Вы же можете назвать его по своему)
В объект передается два параметра, это селектор, и контекст в котором нужно искать.
И так давайте создадим наш объект:

function walik(selector, context) {
     this.length = 0;
     if ( !selector ) {
          this.el = [];
          return this;
     }
     if (selector === 'body' && !context && document.body) {
          this.selector = selector;
          this.context = document;
          this.el = document.body;
          this.length = 1;
          return this;
     } else if ( selector.nodeType ) {
          this.context = this.el = selector;
          this.length = 1;
          return this;
     } else if (typeof selector === 'string') {
          this.context = context || document;
          this.selector = selector;
          this.el = Sizzle(selector, this.context);
          this.length = this.el.length;
          if (this.length == 1)
               this.el = this.el[0];
          return this;
     } else if (typeof selector == 'function')
          this.ready(selector);
     else return null;
}
И так, что же мы тут понаписали

В текущем объекте создаем свойство length и присваиваем ему значение ноль. Это свойство будет хранить в себе количество полученных элементов
this.length = 0;

Дальше мы проверяем селектор на наличие,  если селектора нет, то и поиск не делаем. Свойство el будет хранить в себе элемент или массив элементов (если их больше 1-го). Если селектора нет, то свойство будет пустым. И возвращаем пустой объект (без элементов).

if ( !selector ) {
     this.el = [];
     return this;
}

Если же селектор все же есть, проверяем его содержимое, и если оно равно строчке "body" и контекст не указан, и мы так же имеем доступ к объекту документа document.body, то мы возвращаем тело текущего документа.
Свойство selector сохраняет строку по которому был произведен поиск.
Свойство context сохраняет ссылку на document
Свойство el получает само тело документа (то что и выбирали)
И свойство length получает значение - 1 (единицу)  Так как мы получили только один элемент.

if (selector === 'body' && !context && document.body) {
     this.selector = selector;
     this.context = document;
     this.el = document.body;
     this.length = 1;
     return this;
}

Если же в качестве селектора передается HTML объект, то длину объектов указываем - 1 (единицу),  в качестве контекста (context), селектора (selector) и элемента (el) будет передаваемый объект.

else if ( selector.nodeType ) {
     this.context = this.el = selector;
     this.length = 1;
     return this;
}

Если же передается просто строка в качестве селектора, то мы обращаемся к движку Sizzle для получения списка объектов по запросу,  передавая ему строку селектор и контекст поиска.
Sizzle вернет нам массив элементов. Свойству length мы присваиваем количество найденных элементов. Если был найден только один элемент, то мы свойству el  присваиваем найденный объект.

else if (typeof selector === 'string') {
     this.context = context || document;
     this.selector = selector;
     this.el = Sizzle(selector, this.context);
     this.length = this.el.length;
     if (this.length == 1)
          this.el = this.el[0];
     return this;
}

Если в качестве селектора передается функция, то тогда мы обращаемся к методу ready нашего объекта (этот метод мы создадим потом).
Иначе возвращаем пустой объект.

else if (typeof selector == 'function')
     this.ready(selector);
else return null;
Ну вот примерно и все. В этом уроке мы создали объект, который ищет элементы, и возвращает свой экземпляр. В следующих уроках мы начнем пополнять объект своими методами.

Вот текущий листинг файла framework.js:

(function(window) {
     function $( selector, context ) {
          return new walik(selector, context);
     }

     function walik(selector, context) {
          this.length = 0;
          if ( !selector ) {
               this.el = [];
               return this;
          }
          if (selector === 'body' && !context && document.body) {
               this.selector = selector;
               this.context = document;
               this.el = document.body;
               this.length = 1;
               return this;
          } else if ( selector.nodeType ) {
               this.context = this.el = selector;
               this.length = 1;
               return this;
          } else if (typeof selector === 'string') {
               this.context = context || document;
               this.selector = selector;
               this.el = Sizzle(selector, this.context);
               this.length = this.el.length;
               if (this.length == 1)
                    this.el = this.el[0];
               return this;
          } else if (typeof selector == 'function')
               this.ready(selector);
          else return null;
     }
})(window);

четверг, 28 апреля 2011 г.

Пишем свой Javascript Фреймворк.

Здравствуйте,
И так, я не так уж и много статей видел в интернете о том как создать свой фреймворк в Javascript, и поэтому хочу начать свой цикл статей в которых мы будем постепенно создавать свой фреймворк.
Наш фреймворк будет аналогом известного фреймворка JQuery. Конечно же копией JQuery это не будет (не факт даже что будет полностью кроссбраузерный), так как суть будет просто в том что бы представить как можно создать похожий собственный фреймворк. Ну а дальше если у вас будет необходимость в создании собственного фреймворка, то вы уже сами сможете довести его до ума.

Приступим.
1. Как работает поиск элементов в JQuery
Насколько известно JQuery использует движок селекторов под названием Sizzle
Кстати: Движок Sizzle и JQuery имеют одного автора (John Resig)

Мы тоже будем использовать  этот движок. Поэтому перейдите на сайт sizzlejs.com и скачайте себе этот движок. Скачав движок подключите его к вашей странички. Теперь создайте один JS файл и назовите его к примеру framework.js И его тоже подключите к страничке (страничку назовем index.html)

Вот как должна выглядеть index.html:

<html>
<head>
<script type="text/javascript" src="sizzle.js"></script>
<script type="text/javascript" src="framework.js"></script>
</head>
<body>
</body>
</html>

Все, дальше мы будем работать исключительно с файлом framework.js, а index.html нам нужна будет для тестирования функций фреймворка.

На этом первый урок закончен,  в следующем уроке мы создадим функцию для получения элементов, и класс нашего фреймворка.

пятница, 25 февраля 2011 г.

Обращение к элементам объекта как к элементам массива

Здравствуйте, сегодня поговорим о том, как можно обратится к элементам объекта кроме как стандартного варианта:

object = {
   myVar: 'myValue'
}

alert(object.myVar);

Но кроме этого варианта, можно еще и по другому обращаться.
К элементам объекта можно еще обращаться так же как и к элементам массива:

object = {
   myVar: 'myValue'
}

alert(object['myVar']);
Вот так :)

Для чего это может понадобится ?
Часто может быть когда к элементам страницы нужно обратится не зная заранее значение.
Вот пример:

<img name="name1" src="src1" /> <br />
<img name="name2" src="src2" /> <br />
<img name="name3" src="src3" /> <br />
<img name="name4" src="src4" /> <br />
<img name="name5" src="src5" /> <br />
К примеру нужно всем этим картинка изменить параметр src (предполагается что картинок может быть больше).  Мы можем сделать цикл и к имени добавлять цифры: 1, 2, 3, 4, 5 и т.д.

И вот для того что бы обратится к элементу мы и будем к объекту document обращаться как к массиву:

for(i=1;i<=5;i++) {
   name = 'name'+i;
   document[name].src= 'clear.png';
}
Вот так мы можем динамически генерировать имена, и потом к ним обращаться.
Так же про это и написано еще и в статье "Как вызвать функцию по имени или вызов функции используя объект window"


Ну вот примерно и все. Желаю удачи вам в разработке.

среда, 23 февраля 2011 г.

Переменное количество аргументов в функции или что такое arguments

Рано или поздно у новичков появляется задача, создать функцию с переменным количеством аргументов, и они задаются вопросами типа:

  • "Как создать функцию с переменным количеством аргументов"
  • "Как создать функцию с необязательными параметрами"
  • и так далее, и тому подобные вопросы :)
В каждой функции есть переменная под именем arguments. Именно с помощью этой переменной мы можем обратится ко всем аргументам переданных функции.
Вот простой пример:

function myFunc() {
   alert(arguments[0]);
   alert(arguments[1]);
   alert(arguments[2]);
}

myFunc(1, 2, 3);
Мы передали функции 3 аргумента и с помощью переменной arguments отобразили их в alert-сообщении.

При описании функции не обязательно указывать имена аргументам.
Так же переменная arguments содержит метод length. С помощью данного метода мы можем узнать сколько аргументов было передано функции.

Вот пример, функция отображает сумму всех переданных ей аргументов:

function sum() {
   var summa = 0;
   for(i=0; i < arguments.length; i++)
      summa += arguments[i];
   alert('Сумма всех аргументов: '+summa);
}

sum(1, 3, 22, 55, 107, 39);

Ну вот примерно и все.

вторник, 22 февраля 2011 г.

Как отменить переход по ссылке или куда вставить return

Один из вопросов который возникает у новичка это:

  • "Как при клике на ссылку, отменить переход по ней и выполнить функцию"
  • "Как при клике на ссылку выполнить функции и после нее перейти по адресу ссылки"
  • ну и другие такие же вопросы :)

И так начнем с первого вопроса:
1) Как при клике на ссылку, отменить переход по ней и выполнить функцию

У нас есть такая функция:

fucntion click() {
   alert('click');
}

Функция просто выводит alert-сообщение с текстом - "click".

И есть ссылка при клике на которую вызывается данная функция:
<a href="http://google.com/" onclick="click();">Click me</a>

И так, для того что бы не было перехода по ссылке, достаточно добавить после имени функции команду - return false;


Должно получится так:
<a href="http://google.com/" onclick="click(); return false;">Click me</a>
Вот пример:
Click me

Дело в том что команда return false; указывает браузеру прекратить выполнение скрипта (в данном случае не переходить по адресу ссылки).  К примеру если мы вернем значение true то переход будет осуществлен.

2) Как при клике на ссылку выполнить функции и после нее перейти по адресу ссылки
Тут есть два варианта, в зависимости от ситуации нужно выбрать тот который подойдет, а именно:

  • Продолжить переход по ссылке
  • Программно сделать пере адресацию
2.1) Продолжить переход по ссылке
И так, для того что бы выполнить переход по ссылке после выполнения функции, мы должны написать так:
<a href="http://google.com/" onclick="return click();">Click me</a>
То есть, браузеру вернется то что вернет функция, а уже в конце функции мы указываем return true; Получается что браузер будет ждать окончания выполнении функции что бы получить ответ и знать что делать дальше.

Вот как может выглядеть такая функция:

function click() {
   //Тут строчки кода фукнции
   //Тут еще
   //и тут тоже
   return true;
}
После выполнения этой функции, будет выполнен переход по ссылке.

А вот так перехода по ссылке не будет:

function click() {
   //Тут строчки кода фукнции
   //Тут еще
   //и тут тоже
   return false;
}
Так как мы возвращаем ложь (false) что говорит браузеру прервать выполнение.

2.2) Программно сделать пере адресацию
Но иногда бывают ситуации когда необходимо дождаться не окончания выполнения нашей функции, а какой нибудь другой функции.

Вот к примеру такая ситуация:
Мы при клике на ссылку, хотим сделать анимацию (что бы ссылка переместилась) и после этого только сделать пере адресацию:

function click(obj) {
   $(obj).animate({
      marginLeft: '100px'
   }, 2000);
   return true;
}
И ссылка:
<a href="http://google.com/" onclick="return click(this);">Click me</a>
В данном случае функция обратится к animate и не дождавшись окончания вернет значение true
Но нам нужно подождать 2 секунды пока выполнится анимация.
В данном случае мы возвращаем false, а в качестве callback-функции у анимации сделаем пере адресацию сами.

Вот так все должно выглядеть:

function click(obj) {
   var link = obj; // В переменную link сохраняем объект ссылки, так как потом нам нужно узнать ее адрес
   $(obj).animate({
      marginLeft: '100px'
   }, 2000, null, function() {
      location.href = link.href; // тут мы выполняем пере адресацию
   });
   return false; // Указываем браузеру остановить пере адресацию
}

Вот пример кода выше:
Click me

Заключение
Ну вот как то так :)  Если что то не понятно, или хотите подправить меня, пишите в комментариях, и по вашим комментариям буду обновлять статью :)

понедельник, 21 февраля 2011 г.

Как вызвать функцию по имени или вызов функции используя объект window

Многие новички задаются вопросом типа:

  • "Как вызвать функцию по ее имени"
  • "Как вызвать функцию если ее имя хранится в переменной"
  • Ну, и тому подобные вопросы :)
Возьмем пример задачи:


var name = 'myFunc';

function myFunc(text) {
    alert(text);
}
И так, у нас есть функция под именем myFunc и переменная name которая содержит в себе имя функции.


Как можно вызвать функцию, используя переменную ?
Есть 3 варианта решения этой задачи:

  • Использовать объект window
  • Использовать функцию eval()
  • Создать свой объект, в котором описать функцию.

1) Использовать объект window

На мой взгляд самый подходящий вариант.
Делается следующим образом:

window[funcName](params);

funcName - имя вызываемой функции
params - параметры передаваемые функции.

Нашу задачу можно решить следующим образом:


var name = 'myFunc';

function myFunc(text) {
    alert(text);
}

window[name]('bla bla bla'); //Вызываем функцию myFunc и передаем в качестве параметра текст "bla bla bla"

Вот еще примеры:


window['alert']('bla bla bla'); // Выведется Alert с текстом "bla bla bla" 

var myFunc = 'myAlert';
function myAlert(text) {
   alert(text);
}
window[myFunc]('bla bla bla'); // Выведется Alert с текстом "bla bla bla" 



2) Использовать функцию eval()


С помощью функции eval() можно выполнить какую ту часть кода, в том числе и вызвать функцию.
Пример:

function myAlert(text) {
   alert(text);
}

eval('myAlert("bla bla bla");');

Нашу задачу можно решить так:


var name = 'myFunc';

function myFunc(text) {
    alert(text);
}

eval(name+'("bla bla bla");'); //Вызываем функцию myFunc и передаем в качестве параметра текст "bla bla bla"

Но не злоупотребляйте данной функции так как неправильное использование eval():

  • Открывает ваш код для Инъекций
  • Отладка может быть более сложная (без номера строк)
  • Код выполняется медленее

3) Создать свой объект, в котором описать функцию
И так, как вариант мы можем создать свой объект и из него вызвать функцию, по сути получится тоже самое как и использование объекта window.

Пример:

var obj = {
   firstFunc: function(text) {
      alert('first func:  '+text);
   },
   secondFunc: function(text) {
      alert('second func:  '+text);
   }
}

obj['firstFunc']("bla bla bla"); //Вызываем функцию firstFunc
obj['secondFunc']("bla bla bla"); //Вызываем функцию secondFunc

var name = 'first';
obj[name+'Func']("bla bla bla"); //Вызываем функцию firstFunc

Нашу задачу можно решить следующим образом:

var name = 'myFunc';

obj = { // Описываем наш объект
   myFunc: function(text) { //Описываем нашу функцию в объекте
      alert(text);
   }
}

obj[name]("bla bla bla"); //Вызываем функцию myFunc из объекта obj и передаем в качестве параметра текст "bla bla bla"

Заключение
Ну вот примерно и все :)
По моему мнению самый оптимальный вариант это использовать объект window хотя редко бывают ситуации когда имя функции берется из переменной, по сути вам даже стоит избегать таких ситуации и искать другие решения.