Решения и их последствия.

Разрабатывать продукт в недра которого может влезть “чужой” непросто. Мы придумываем всяческие “неймспейсы”, давая файлам, директориям, переменным и классам псевдо-уникальные префиксы, пытаясь предотвратить коллизии с чужеродной средой.

Однажды, много лет назад, ко мне свалилась задача – размещение некой сложной формы на сторонних ресурсах. Очевидное и годами отработанное решение – iframe было забраковано, т.к. опыт и пятая точкашестое чувство подсказывали – как только владелец сайта разместит форму у себя, его светлую голову немедленно посетит мысль – “а как мне приделать перламутровые пуговицы?!”. Это, признаться, пугало – целыми днями верстать и раскрашивать незнакомым дядям и тётям одну и ту же страницу пятью миллионами способов? Нет, пристрелите меня семеро! Второй способ – разработать и задокументировать API, чтобы владелец ресурса сам разрабатывал себе форму, был отвергнут как трудозатратный, но совершенно нежизнеспособный так как рядовой клиент как правило (тут могло бы быть нечто оскорбительное про уровень интеллекта и радиус кривизны передних конечностей, но цензура не пропустит) не готов своими силами что-то создавать, тогда как продукт конкурента был проще в освоении (работал из коробки). Был выбран третий путь – размещение формы в виде html-разметки, которую мы отдаём заказчику, что называется “в руки”, а данные подгружаем через <script src="http://my-resource.example.com/?parameters"></script>, это позволяло владельцу ресурса до определённой степени контролировать внешний вид полученного документа и избавляло нас от трудозатратной кастомизации сотен инсталляций продукта. Но этот способ потенциально создавал много проблем, т.к. находясь в инородной среде наш документ мог “подхватить” незапланированные свойства, “заразится” чужими переменными и вообще рассыпаться в пыль в руках неуклюжего веб-мастера. Необходимо было тщательно изолировать всё и вся. Одним из способов отделить своё “добро” внутри документа было создание уникального “пространства имён”, например создание атрибутов в виде <div rpz:property="value"></div> – это самое rpz: давало надежду на то, что внешний скрипт(движок сайта или сам вебмастер) “случайно” не создаст аналогичный атрибут с другим value (или вовсе без него), развалив всю эту шаткую конструкцию. Решение оказалось рабочим во всех доступных графических браузерах и популяризировалось мной не только в этом продукте, но и повсеместно в других (печатая эти строки пытаюсь понять – зачем вообще нужны были именно атрибуты и почему их нельзя было заменить на переменные в скрипте, но разумного ответа почему-то не нахожу).

Это неоднозначное решение “выстрелило в ногу” только на днях – появился IE9… Невероятно быстр, ангельски красив, дьявольски умён – блеск, а не браузер На вид такой же унылый как все предыдущие В общем обзор новшеств можно наверное найти на сайте разработчиков, ну а я увидел его первый раз два дня назад, ничего хорошего про него сказать не могу, да и речь совсем не о том. Случись такое совпадение – сайт заказчика оказался настолько весь из себя валиден, что IE9 работал со страницей в своём новом document.documentMode. И чтобы вы думали? Точно! Годами отработанная “технология” дала сбой – “самодельные” атрибуты просто-напросто не видны на такой странице, а моя твёрдая уверенность в том, что они есть запретила здравому смыслу проверять их наличие… так и случаются epic fail-ы, так было и со мной.

Один грязный хак удалось временно залатать другим грязным хаком, но урок получен – недокументированная возможность это лишь “возможность”, строить на ней что-то прочное нельзя.

К слову сказать, не так давно вместо атрибута rpz:property="value", я начал использовать “документированную возможность” – атрибут data-rpz-property="value" и соответствующий вызов в js изменился с jQuery(selector).attr("rpz:property") на jQuery(selector).data("rpz-property") , видимо “шестое чувство” о чём-то подозревало…

Всплытие покажет

Предположим у нас есть html-таблица 100×100 ячеек,в каждой ячейке – ссылка. При нажатии на каждую, должно происходить что-либо невероятное.
Мы можем сделать 10 тыс обработчиков onclick и медленно, но верно добиться своей цели.
А можем глупостей не делать. Ведь хватит только одного!


Дело в том, что события в DOM умею “всплывать” – т.е. если представить документ в виде слоёной структуры, где сам document находиться сверху, радуя глаз хрустящей корочкой, а все дочерние элементы под ним, то событие возбуждённое на нижних уровнях, не найдя свой законный обработчик у потревоженного объекта начинает потихоньку лезть наверх, шевеля всё на своём пути, и искать свой обработчик последовательно у всех предков.
Что это собственно даёт? Это может существенно сократить количество обработчиков событий на странице. На идеальной сферической странице вакуумного веб-приложения всего один обработчик!

Перейду к примерам: (more…)

05.05.08  |  ,  | 5 comments

jQuery 1.2.3

.4.5.6.7…

Тихо и незаметно зарелизился jQuery:

jquery-1.2.3.js, jquery-1.2.3.min.js, jquery-1.2.3.pack.js

Поскольку официального анонса пока нету, перечислю “вкусности” сам:
Вот официальный анонс, а ниже мой:
(more…)

07.02.08  |   | 3 comments

jQuery 1.2.2

К своему “второгодию” jQuery решил явиться миру обновлённым.

Много исправлений направленных на ускорение и “устабилизацию”.
Решена крайне досадная проблема с тем, что $(document).ready не срабатывал в IE если, документ находился в [и]фрейме.
Из новшеств – этот самый $(document).ready(func) теперь можно писать в более привычном виде через $.bind – $(document).bind(‘ready’,func);
Появились два новых event-а – mouseenter и mouseleave, которые вероятно скоро пойдут в массы в качестве основы для разнообразных dropdown-менюшек.
В “ajax”-части добавились “умолчальные” заголовки Accept, для разных типов dataType. (зачем это надо? и что из этого выйдет ?)

Перед тем как обновиться не забудьте – некоторые плагины могли “сломаться” – будьте готовы поработать напильником…

15.01.08  |   | 2 comments

Google using jQuery

Вот здесь упомянуто, что в обновлённой версии гуглокода инопланетяне решили использовать распрекрасную jQuery.

Есть ещё сомневающиеся в правильности выбора jQuery? Или даже те, кто и вовсе ещё не выбрал? Задумайтесь! – даже гости из будущего почувствовали Великую Силу, которую даёт jQuery отбирая взамен лишь не многим больше 20кБ трафика.

Но овладеть магией не просто. А очень просто.

jQuery.facts II

Выдам ещё одну порцию фактов, связанных с jQuery.

  • jQuery.get() и jQuery.post() принимают последним четвёртым параметром dataType. Ну принимает и бог с ним, скажут некоторые. А другие смогут этот факт использовать во благо. Вот пример такого “блага”:
    $.post(backend_url,params,callback,’script’); // и вуаля – все вернувшееся с бэкэнда интерпретируется как javascript.Опять-таки внимательный (и просвещённый) читатель скажет “ну и нафига? есть же jQuery.getScript ?”. Тут мне ответить уже нечего. Разве что напомнить о том факте, что getScript передаёт параметры GET-ом, длина которого как мы знаем весьма ограничена.
  • Кстати о jQuery.getScript() – начиная с версии 1.2.1 getScript умеет кросс-доменные запросы (все урлы начинающиеся с http автоматом будут тянуться не через XmlHttpRequest, а посредством добавления тега script). Это открыло нам такие просторы, что ни в сказке сказать, ни трактором убрать… (правда имеется одно досадное недоразумение, но видимо оно беспокоит только меня UPDATE: пофиксили).
  • Не совсем jQuery, но тоже важный факт – расчудесный плагин jQuery.livequery аналог Behaviour – помогающий создавать скрипты работающие “на манер css”.
    $('span.bugaga').livequery('click',function(){
       alert('Бугага');
    });
    $('span.gygygy').livequery(function(){
       $(this).bind('click',function(){
          alert('Надо же - кликнули. Гыгыгы');
       });
       alert('В документе появились span-ы c классом gygygy');
    });
    

    Поясняю – работает это так же как и jQuery.bind, за одним лишь исключением – элементов на странице к моменту вызова функции может и не быть. Когда они появяться – livequery “навесит” на них нужные обработчики. Очень удобно. Но будьте внимательны и осторожны – не стоит увлекаться – чем больше элементов будут переданы в livequery, тем “тормознее” будет система – каждые 20мс проводиться поиск элементов в целью найти и обезвредить навесить нужные эвенты (а также после разнообразных манипуляций с dom).

  • И последний на этот раз факт – как известно jQuery “оборачивается” в функцию $() – уж больно кратко,красиво и удобно в использовании. Но в эту же функцию любят “оборачиваться” многие известные js-фреймворки. И это казалось бы ставит крест на совместном их использовании… Но не в случае с jQuery – его авторы понимают что они не одни на белом свете. jQuery.noConflict(); “отпустит” функцию $(), правда сам код использующий jQuery в этом случае должен содержать либо полное название функции [ jQuery("selector").action(); ] или же должен быть “завёрнут” в анонимную функцию [ (function($) { original_code})(jQuery); ]

jQuery.facts

Расскажу несколько фактов о jQuery, которые как мне видится, не очень понимают “отечественные программеры”

  • при “навешивании” обработчика какого-либо event-а к (например $(‘#element’).click(handler); ) он НЕ заменяет предыдущий обработчик (если таковой имелся), т.е. код:
    $('#element').click(function(){  alert('hello');})
    $('#element').click(function(){  alert('world'); })
    

    Выведет оба alert-а, а не только второй как думается некоторым.

  • Непосредственно из первого вытекает следующий факт – конструкций $(document).ready(blablabla); в коде может быть “бесчисленное” количество раз – все обработчики вызовутся в порядке их добавления.
  • Система событий в jQuery позволяет не ограничиваться теми событиями, которые есть в документации – можно создавать события самостоятельно:
    $('button').click(function(){ jQuery.event.trigger("buttonClicked");});
    $('div').bind('buttonClicked',function(){ $(this).hide();});
    $('span').bind('buttonClicked',function(){ $(this).show();});
    

    Подобная техника позволяет существенно упростить код и сделать его “читабельнее”.

  • Анимационные эффекты в jQuery асинхронны и нередко возникает вопрос – как одну функцию выполнить строго после завершения первой. Все core-функции jQuery связанные с эффектами в качестве последнего параметра принимают callback – функцию, которая вызовется по завершению текущего эффекта:
    $('element-1').fadeOut(3000,function(){
          $('element-2').fadeIn(1500,function() {
          alert('done second effect');
       });
    });
    
  • К ЛЮБОМУ html-элементу можно добавить ЛЮБОЙ атрибут (). По этим “самодельным” атрибутам элементы можно найти с помощью селекторов jQuery:
    var elements_by_attr = $('[@myownattr]');
    var elements_by_attr_with_value = $('[@myownattr="somevalue"]');
    var spans_by_attr = $('span[@myownattr]');
    

    Очень полезное “явление” при создании своих собственных элементов управления (и не только).

Ну и напоследок подкину найденную статейку “jQuery for JavaScript programmers”, прочитать которую стоит тем, кто только начинает осваивать прелести jQuery . Материал изложен на английском.

21.08.07  |   | 4 comments

Performance Optimization WordPress Plugins by W3 EDGE