У Web-программистов сложилась добрая традиция - в любую даже самую простейшую страницу по дефолту подключать jquery. Я ничего не имею против этой библиотеки. Она шикарна. Она лучшая в своем роде, и продвинула и продвигает современный web далеко вперед. Повсеместный переход сайтов на ajax также связываю с этой библиотекой.
Однако тут есть одно НО. В простейших проектах: небольшая анимация, баннеры, или любую другую логику, где не требуется работа с DOM или ajax, надобность в лишних 90кб скриптов отпадает. Особенно критично это для мобильных устройств. И дело не столько в лишних килобайтах, а в том, что такие скрипты напрасно грузят и без того занятый процессор.
Сперва я хотел написать все на vanila.js, но кросплатфоменность в среде мобильных приложений та еще головная боль, поэтому решено было выбрать легковесный аналог jquery - jQLite.
По объему jQLite всего 14кб, против 90кб сжатой jQuery. Само собой, в ней не все возможности старшей сестры, а лишь необходимый минимум.
Из доступных по умолчанию методов
.each(function...) .addClass(name) .removeClass(name) .toggleClass(name) .css([name/obj[, value])] .show(callbackFunction...) .hide(callbackFunction...) .hasClass(name) .html(htmltext) .parent([selector)] .parents([selector)] .prev([selector)] .next([selector)] .children([selector)] .eq(index) .first() .last() .index([selector)] .append(obj) .remove([filter)] .empty() .val([value)] .attr([name/obj[, value])] .bind(eventName, function...) .trigger(eventName[, array))] .data(key [, value))] .removeData(key) .find(selector) .end()
Нет ни wrap-ов ни fade, ни даже animate. Однако библиотека все еще отлично ищет по дереву DOM, как классы и идентификаторы, так и более сложные селекторы. Тоже с понятными ограничениями.
Selector Type | Syntax |
Id | #foo |
Element | div or span or table |
Class | .bar or div.baz |
Multiple class | div.button.jq |
Descendant | div.jq span.hotlink |
Multiples | "div.button, div.link" |
Attribute |
input[type=hidden], input[type!=hidden], input[type*=hidden] |
Поиска в контексте другого элемента, тоже нет. Это нужно запомнить. Метод find не работает, как должен. В документации написано, что он умеет искать по тегам, однако мне это так и не удалось.
Поддерживаются несколько удобных методов
jQuery.noop() | Пустое действие |
jQuery.isFunction(obj) :boolean | Определяет, является ли obj функцией |
jQuery.isArray(obj) :boolean | Определяет, является ли obj массивом |
jQuery.isPlainObject(obj) :boolean | Определяет, является ли obj обычным объектом с полями |
jQuery.merge(obj1, obj2) :Object | Соединяет два объекта в один. работает как с массивами, так и с объектами |
jQuery.param(obj) :String | Конвертирует массив или объект в строку запроса вида &a=1&b=3 |
jQuery.makeArray(obj[, results]) :Array | Преобразование объекта в массив. Если вы вторым аргументом подать массив, оба будут объеденены в один |
jQuery.trim(str) :String | Удалить начальные и конечные пробелы из строки |
jQuery.inArray(value, array) :Number | Возвращает индекс значения в массиве, или -1, если не найден |
jQuery.data(elem, key[, data]) :Object | Добавление произвольных данных к элементу DOM, или запрос для данных, связанных с ключом, данные сохраняются, как html5 свойства dataset |
jQuery.removeData(elem, key) | Удаление произвольных данных из элемента DOM |
Есть и убогая работа с ajax. из поддерживаемых методов только GET запрос.
jQuery.ajax.send("http://www.google.com", function(data, status) { alert(data); });
либо подобие метода $.post
jQuery.ajax.send("http://www.google.com",{id:111,s:'поиск'}, function(data, status) { alert(data); });
Помните, такой запрос тоже отправится, как GET, а поданный массив преобразуется в GET строку. В этот же массив можно подать информацию о асинхронности запроса
jQuery.ajax.send("http://www.google.com", {async:false,id:111},function(data, status) { alert(data); });
при таком запросе, скрипт не продолжит работу пока, не завершится запрос.
Обработчики событий, к которым мы привыкли, также ограничены.
.click(function...) .mouseover(function...) .mouseout(function...) .mouseup(function...) .mousedown(function...) .change(function...) .focus(function...) .blur(function...) .submit(function...)
Но метод bind работает с куда большим числом событий
click,dblclick,mouseover,mouseout,mousedown,mouseup,keydown,keypress,keyup,focus,blur,change,select,error,load,unload,scroll,resize,touchstart,touchend,touchmove
Метода unbind нет.
Если изначально писать всю логику на этой библиотеке, то вы скорее всего придете к своей цели. Но, что если подключить ее к готовому проекту, или к стороннему компоненту (календарю, выпадающему меню, и т.д.)
Тут возникнут неизбежные проблемы отсутствия необходимых методов. На выручку придет расширяемость библиотеки по средствам плагинов, такая же, как и у jQuery.
К примеру, некий плагин ругается на то, что у нас нет метода unbind, нет ничего проще. выше пишем
$.fn.unbind = function(){ return this; }
Теперь он есть, хоть и ничего не делает.
А как же анимация? - спросите Вы. К хорошему быстро привыкаешь и анимацию в играх или баннерах, мы не задумываясь делаем методом animate. Великолепный и очень удобный метод. Но его ведь нет, помните?
К слову, анимация в играх - это не что-то эфимерное. Это просто цикл, с некой сменой состояния, каждую итерацию. Берем любую игру с itunes, обычно я покупаю при помощи Игротрек. Любая игра, к примеру гонки - это смена абсолютного состояния объекта (в данном случае автомобиля) по top и left с течением времени.
Все просто, реализуем плагин jQLite.animate.
$.fn.animate = function( options,speed,callback ){ var time_on_tick = 10; return this.each(function(){ var that = this; var ticks = {}, starts = {}; for(var key in options){ starts[key] = parseFloat($(that).css(key)); // текущее положение var arrow = starts[key]<options[key]?1:-1; // направление убывающее или возростающее ticks[key] = arrow*Math.abs(starts[key]-options[key])/(speed/time_on_tick); // расстояние, которое проейдет анимация за один кадр }; (function(){ var do_count = 0; for(var key in options){ // если не достигли точки конца анимации if( Math.abs(starts[key]-options[key])>5 ){ //то сдвигаем элемент на n пикселов $(that).css(key,starts[key]+=ticks[key]); do_count++; }else delete options[key]; } // если не все анимации "отстрелялись" if( do_count ) setTimeout(arguments.callee,time_on_tick); else callback.apply(this); })(1); }); }; $('#execBtn').css('position','absolute').animate({left:100,top:2000},3000,function(){ alert('finish'); });
И пример использования:
Так и строится анимация в играх. Все просто, каждый кадр смещаем положение объекта на n пиксел.
Вот и все, какие-то методы можно просто дописать, чтобы их вызов не вызывал ошибок, какие-то придется функционально повторить. Но оно того стоит. Поверьте!