Category Archives: Programming
Очередь на js
Нужно было сделать простенькую очередь, чтобы добавить много колбэков, а потом выполнить последний из очереди по таймауту, отсчитываемому от времени последнего добавления. Очередь получилась простенькая (за полчаса много и не сделаешь). Использование:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//опциональное время в милисекундах - таймаут от последнего события var queue = queueFactory( 5000 ); // у меня дёргается скрипт по определённому событию, в нём написано $( window ).bind( 'event1', function( Event, Data ) { if ( ! queue.length() ) { showLoader(); } queue.add( function() { console.log( 'event1' ); } ); } ); $( window ).bind( 'event2', function( Event, Data ) { if ( ! queue.length() ) { showLoader(); } queue.add( function() { console.log( 'event2' ); } ); } ); |
В итоге через 5 секунд после наступления последнего из событий в консоль выведется соответствующее сообщение.
Как настроить Smarty для удобной работы (+наследование)
Smarty — странноватый и глючноватый шаблонизатор, если сравнивать с Django. Но под php ничего под руку не попалось, чтобы работало из коробки, было просто в настройке, и, к тому же, когда-то давно я его уже ковырял. В общем, нужно было срочно прикрутить шаблонизатор — сделал следующее. В классе, ответственном за вывод:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
private static function getSmarty( array $Params ) { require_once( SMARTY . 'Smarty.class.php' ); $smarty = new Smarty(); $smarty->error_reporting = E_ALL & ~E_NOTICE; $smarty->force_compile = true; $smarty->left_delimiter = '{{'; $smarty->right_delimiter = '}}'; $smarty->template_dir = TEMPLATE; foreach ( $Params as $key => $value ) { $smarty->assign( $key, $value ); } return $smarty; } public function renderToView( rController $Controller, $Debug = false ) { $contentType = $Controller->getContentType(); self::setHeaders( $contentType ); switch ( $contentType ) { case self::CONTENT_TYPE_JSON : echo json_encode( $Controller->getTemplateData() ); break; case self::CONTENT_TYPE_HTML : default : $templatePath = $Controller->getTemplatePath(); if ( ! $templatePath ) { $templatePath = $this->generateTemplatePath( $Controller ); } if ( ! file_exists( TEMPLATE . $templatePath ) ) { if ( $Debug ) { echo 'tried ' . TEMPLATE . $templatePath; } $templatePath = $this->defaultTemplatePath; } self::getSmarty( $Controller->getTemplateData() )->display( $templatePath ); } } |
Во вьюхе:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// layout.tpl <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <head> <title>{{if isset( $title )}}{{$title}}{{else}}{{$defaultTitle}}{{/if}}</title> <script type="text/javascript" src="/js/main.js"></script> {{block name="head"}}{{/block}} </head> <body> {{block name="content"}}{{/block}} </body> // index.tpl {{extends 'layout.tpl'}} {{block name="content"}} {{assign 'myparamm' 'Bob'}} myparamm {{$myparamm}} {{/block}} |
…
jQuery.deferred
В jQuery 1.5 была полностью переработана модель асинхронных запросов. Теперь они возвращают deferred-объект, содержащий promise-объект, который содержит методы, позволяющие узнать состояние запроса или навесить дополнительные обработчики. promise-Объект содержит методы then, done, fail, isResolved и isRejected. Суть нового подхода состоит в следующем:
1 2 3 4 5 6 7 |
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){ // a1 и a2 - аргументы, отвечающие соответственно за запросы к страницам page1 и page2 var jqXHR = a1[2]; /* массив состоит из [ "success", statusText, jqXHR ] */ if ( /Оппа!/.test(jqXHR.responseText) ) { alert("Где-то на первой странице есть 'Оппа!'."); } }); |
$.when принимает deferred-объект или объекты и возвращает promise-объект. Можно делать и так:
1 2 3 4 5 6 7 8 9 10 11 12 |
var $promise; if ( tt == 1 ) { $promise = $.when( $.getJSON( ... ) ); } else if ( tt == 2 ) { $promise = $.when( $.getJSON( ... ), $.getJSON( ... ), $.post( ... ) ); } else { $promise = $.when( console.log( 'else' ) ); } $promise. then( function() { console.log( 'done', data ) } ); |
…
jQuery.delegate
jQuery.delegate и jQuery.undelegate появились в jQuery 1.4.2. Это аналоги .live и .die(). У .live и .die() есть проблемы с, к примеру, вложенными объектами, с встраиванием в цепочки и много ещё. Синтаксис .delegate отличается от .live и, соответственно, .click и т.п. Пример использования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Using .live() $("table").each(function(){ $("td", this).live("hover", function(){ $(this).toggleClass("hover"); }); }); // Using .die() $("table").each(function(){ $("td", this).die("hover"); }); // Using .delegate() $("table").delegate("td", "hover", function(){ $(this).toggleClass("hover"); }); // Using .undelegate() $("table").undelegate("td", "hover"); |
http://api.jquery.com/delegate/ Работа с событиями в jQuery 1.7+
Работа с событиями в jQuery-ui
Если нужно из виджета стриггерить событие, это сделать это можно двумя способами:
1 |
this.element.trigger( 'my_event_element', { option1: true } ); |
1 |
this._trigger( '_my_event_widget', null, { option1: true } ); |
Допустим, что наш виджет называется MyCoolWidget. Тогда поймать наши события можно так:
1 2 3 4 |
$( '#div' ).MyCoolWidget(); $( '#div' ). bind( 'my_event_element', function( Event, Ui ) { console.dir( Ui ) } ). bind( 'mycoolwidget_my_event_widget', function( Event, Ui ) { console.dir( Ui ) } ); |
Обратите внимание на второй bind — префиксом к событию в этом случае явлется название виджета в нижнем регистре. Кстати, есть ещё один способ обработать событие от this._trigger — …
Способ узнать, какие события забиндены на элементе в jQuery
1 |
console.log( $( selector ).data('events') ); |
Выдаст все события, которые слушаются обработчиками на элементе.
Организация очередей на PHP
Решили использовать Pheanstalk, который представляет собой PHP-клиента для Beanstalk. Простой, чётко работает, всё построено на иерархии исключений, т.е. легко применять. Всё сводится к следующему:
1 2 3 4 |
$this->queueManager = new Pheanstalk( '127.0.0.1' ); $this->queueManager->useTube('my_jobs_1')->put( $JobData ); $this->job = $this->queueManager->watch('my_jobs_1')->ignore('default')->reserve( 0 ); // 0 - чтобы не ждать, когда появятся новые джобы (чтобы запускать php-скрипт кроном, а не требовать висения в памяти демоном) $this->queueManager->delete( $this->job ); |
Для работы должен быть запущен демон Beanstalk:
1 |
$ beanstalkd -d |
Ещё почитать. Интересный пример использования Pheanstalk, менее интересный пример.
Что почитать, чтобы повысить свой уровень JavaScript
От переводчика: Я думаю многие читали статью Rey Bango — What to Read to Get Up to Speed in JavaScript, но до хабра обсуждение так и не докатилось. Предлагаю закрыть этот пробел и поговорить о хороших книгах, блогах, тренингах и конференциях, посвященных в первую очередь клиентскому JavaScript и клиентской веб-разработке. Чтобы не копипастить оформляю статью в …
Регулярные выражения — особенности
Как работает регулярное выражение (regexp): сначала оно пытается найти максимально возможное совпадение для текущей группы символов, затем посимвольно откатываясь к началу совпавшей подстроки (backtracking), в попытке найти совпадение для последующей группы символов регулярного выражения. Это верно для «жадных» (greedy) типов групп (по умолчанию, к примеру [\w]*). Если группа «ленивая» (lazy), то откатывание производится от начала …
jQuery templates (расширение jQuery, шаблонизатор)
Всё достаточно просто.
1 2 3 4 5 6 |
$.getJSON( me.options.urlMoreResults ) .success( function( Answer ) { $( '#my-tmpl' ).tmpl( Answer ); } ); |
Шаблон:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<script id="my-tmpl" type="text/x-jquery-tmpl"> <div> {{if songs}} <ul class="song-list"> {{each songs}} <li> <a class="play js-play" href="javascript:void(0);" data-song="${$value.id}"></a> </li> {{/each}} </ul> {{/if}} {{if description}} <div class="description"> <a href="${url}/about" target="_blank"> ${description} </a> </div> {{/if}} </div> </script> |
http://api.jquery.com/category/plugins/templates/ http://habrahabr.ru/blogs/jquery/112843/ http://habrahabr.ru/blogs/jquery/113672/