Archive for the ‘javascript’ tag
Explain to me what JavaScript is…
Одно из самых литературных объяснений – “что такое JavaScript и причем тут Java”.
Here is something else you should know about Javascript that seems like it was almost designed to be confusing as possible:
- There is a programming language called Javascript.
- There is a programming language called Java.
- There is an interpreter (‘thing that makes it go’) for the programming language Javascript built into most web browsers
- There is an interpreter for the programming language Java that is sort of built in to most web browsers, or was.
- THESE TWO PROGRAMMING LANGUAGES HAVE ALMOST NOTHING TO DO WITH EACH OTHER
Кратко и ёмко. Затрагивается даже история создания JavaScript…
So Netscape said to a guy named Brendan, who worked at Netscape, “Please make us a programming language.
Also, you have to call it Javascript.
Also, if you can make some of it kind-of sort-of look a bit like Java, that would be even better.
Also, you have only 10 days to do this so get cracking!”
В общем почитайте.
ɹoןoɔןıu
`!` в имени события
Следующий код довольно часто можно видеть, если используется библиотека jQuery:
$('#foo')
.bind('click', function(){ console.log('click event') })
.bind('click.my', function(){ console.log('click.my event') }); //namespaced event
//потом это обработчики могут вызываться...
console.log('step 1');
$('#foo').trigger('click');
console.log('step 2');
$('#foo').trigger('click.my');
Результатом этих вызовов будет вывод в консоль следующего:
step 1
click event
click.my event
step 2
click.my event
Это хорошо известно, про это написано в доках по jQuery и это понятно. А вот про что там не написано, это про то, что можно написать так:
console.log('step 3');
$('#foo').trigger('click!');
(обратите внимание на восклицательный знак в имени ивента). И вот тогда в консоле мы увидем такое:
step 2
click event
И все. Т.е. вывода click.my event мы не увидим. Если посмотерть в исходники jQuery, то там это выглядит так:
...
if ( type.indexOf("!") >= 0 ) {
event.type = type = type.slice(0, -1);
event.exclusive = true;
}
...
т.е. это некий вариант exclusive событий. И этим, в частности, пользуется плагин DataLink, изучение исходников которого (на предмет “переделать для себя”) и всплыло это странное exclusive.
jQueryUI custom widget
Куда ж еще записать, как не сюда?
Итак, есть идея – сделать свой виджет для jQueryUI. Почему именно эта библиотека? А не важно. Просто мне она нравится. Итак, виджет. Вот “скелет” для виджета плюс несколько забавностей, на которые я набрел:
(function($, window, document, undefined){
//handy log function
window.log = function(){
log.history = log.history || [];
log.history.push(arguments);
if(this.console)
console.log( Array.prototype.slice.call(arguments) );
};
$.extend($.expr[':'], {
lookup: function(a){return a.getAttribute('t2-ui-role') === 'lookup';}
});
var Lookup = {
options: {
version: '0',
icon: 'search'
},
currentlyActiveLookup: null,
_create: function(){
var self = this,
el = self.element;
self.options.icons.primary = self.icon;
//log('element IS'+(el.jquery?'':' NOT')+' jQuery object');
$.ui.button.prototype._create.apply(self);
self._setOption('icons', {
primary:'ui-icon-'+self.options.icon,
secondary:null
});
el.bind('click', function(e){
e.preventDefault();
e.stopPropagation();
$(e.target).trigger('lookup.t2', {lookup:this});
self._trigger('activated', null, {lookup:this});
return false;
});
},
_init: function(){ log('_init'); },
boom: function(){ log('nice, you boom me!'); }
};
$.widget('t2.lookup', $.ui.button, Lookup);//NS doesn't mean something yet
//====================== RUN CODE HERE ======================
$('#id_ref_button').button({icons:{primary: "ui-icon-search"}});
var l1 = $(':lookup').lookup({
activated: function(e, data){ //tightly coupled
log('activated callback fired');
log(' '+data, data.lookup);
}
});
// a-la Observer Pattern
$('body').bind('lookup.t2', function(e, data){ //loosely coupled v.1
log('lookup.t2 event catched');
log(' '+data, data ? data.lookup : 'nope');
});
$('body').bind('lookupactivated', function(e, data){ //loosely coupled v.2
log('lookupactivated event catched'); //why not activated.lookup?
log(' '+data, data.lookup);
});
l1.lookup('boom');
})(jQuery, window, window.document)
Самое странное – это то, как виджет может общаться с внешним миром… Итак, есть конечно стандартный (для пользователей jQuery) способ .trigger(). Ловить такие события можно тоже стандартным способом – .bind(). Тут вроде все просто и все понятно. Далее, jQueryUI предлагает свой способ: this._trigger(type, event, data). Где первый параметр это имя события, второй – это jQuery.Even object. Третий – это что-то, что вы еще хотите передать в это событие. Учтите, что третий параметр передается используя .apply(), так что если там будет массив — он развернется в список аргументов. Это влияет на то, как писать сигнатуру колбэка и обсервера событий
А вот такие события уже можно ловить 2мя способами:
- callback —
.lookup({ activated: function(){} }) - observer —
.bind('lookupactivated', function(){} )
Мне больше нравится второй вариант. Во-первых, Event Bubbling позволяет навесить обработчик на контейнер, где эти виджеты появляются и убрать код из инициализации этих виджетов при получении данных с помощью AJAX. Во-вторых это просто красиво.
Единственный тут минус – это название этого события… Оно строится самим jQueryUI и представляет собой widget_name + event_nameбез точек и пробелов… Ну… зато плюсы хороши и приятны. Среди плюсов также то, что третий параметр для данного способа не развернется (в случае, если это массив) в аргументы.
Кстати, в данном примере я “наследовался” от уже существующего виджета $.ui.button, но если без этого – просто не указывайте второй параметр при регистрации виджета $.widget('t2.lookup', $.ui.button, Lookup);. Кстати, namespace, указываемый при регистрации ничего не значит. По крайней мере пока ничего. Так что можно делать свой или использовать тот, что использует сама jQueryUI ($.widget('ui.lookup', Lookup);) — выбирайте сами.
Как это все работает и вообще попробовать самому можно на мега полезном ресурсе JSBin.
P.S.
Надо бы кстати написать про мега удобный кусок кода… В след. раз.
(function($, window, document, undefined){
//code goes here
})(jQuery, window, window.document)
(:
Userscript для Fluid(ium) + GMail
Обновился Fluid.app. Теперь он сделан на базе Fluidium. Пока это бета, но я ей пользуюсь. Минус один – бадж количества не прочитанных писем перестал показываться. Для этого нужен userscript. Вот тот, что я написал для себя:
(function () {
setInterval(update, 5000);
function update() {
var links = document.getElementById('canvas_frame')
.contentDocument.getElementsByTagName('a');
var len = links.length;
for (var i=0; i < len; i++) {
var str = links[i].getAttribute('href');
if (/#inbox$/.test(str)) {
var matches = links[i].textContent.match(/\(([0-9]+)\)/),
str = '';
if (matches && matches.length > 1) {
str = matches[1];
}
window.fluid.dockBadge = str;
}
}
}
})();
Пробуйте, если что не так – дайте знать ;)
Решил поменять тему блога
Ну в смысле тему как оформление. Зачем? Не знаю. Просто попалась на глаза красивая и простая тема.
Есть в ней пара минусов, но может быть когда нибудь я до них доберусь и поправлю.
А пока буду дальше читать Secrets of the JavaScript Ninja.
JavaScript import
В JavaScript нет директивы import. Хотя она есть даже в css (@import). Но если надо, очень надо, то можно воспользоваться следующей “заменой”
function import (url) {
var xhr;
if(window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
if(xhr){
xhr.open("GET",url,false);
xhr.send(null);
eval(xhr.responseText);
} else {
return false;
}
}
Пользоваться довольно просто
import('/path/to/js/file.js');
call_function_from_file_js();
То, что код функции call_function_from_file_js будет доступен, гарантировано синхронностью XMLHttpRequest (3-й параметр). У данного решения есть маленький минус – загруженный код проходит через eval(), его многие считают злом и т.д…. Еще могу возникнуть сложности, если в загружаемом коде есть объявления типа
function foo() {
//some code
}
Если нарветесь — попробуйте изменить определение функции на
foo = function () {
//some code
}
Должно помочь.
JavaScript… какой он?
Есть такая модная штука в наше время — AJAX/JSON/XML/WEB20 и иже с ними… Мне они тоже нравятся. И нравятся настолько, что я и сам этим балуюсь ;) Например сейчас в одном из проектов, небольшом, но очень гордом, я занят тем, что пробую сделать ему, проекту, модное UI, не в смысле дизайна – тут я пас, а в смысле “все ajax-запросам”, json туда, json обратно…
А самое веселое в этом знаете что? Это весело! Это оказалось реально интересно… Придумывать, как же рисовать все это на клиенте, где хранить шаблоны и как их заполнять… Битвы за скорость (вообще отдельная песнь)… Борьба с обработчиками событий, которые по вине их писавшего рвут even bubbling и это аукается где-то: то ссылки перестают кликаться, то в поле ввода ничего нельзя ввести ;)
Сейчас у меня стоит задача придумать, как же быть с шаблонами… Как только будет что-то — расскажу. Пока самая интересная идея это хранить их прям в коде ввиде блоков
<script type="text/html" charset="utf-8" id="tmpl-block-a">
<div>
...
</div>
</script>
Да да, тут нет ошибки ;) если вдруг вы кинулись писать это в коменте. Способ интересен, хорош и удобен. Но для мелких шаблонов. А если они большие?
Google Playground
Хотите попробовать jQuery? Или может MooTools или Prototype? Может быть хотели попробовать сделать что-то с Google Maps? В общем есть много интересного и любопытного. И для этого есть такая штука на гуглокоде – AJAX APIs Playground. Что же там можно? Можно в очень компактном и понятном виде посмотреть на примеры использования выше перечисленного, можно самому попробовать, поэкспериментировать… И самое приятное — для этого ничего не надо кроме браузера и желания собственно пробовать!
Дерзайте, это очень интересно. Даже полезно. И может навести на мысль что-то сделать… Как у меня ;)
JavaScript Database Programming
Мой RSS-поток вынес мне тут одну интересную статейку про использование баз данных
The HTML 5 specification provides a new mechanism for client-side data storage: JavaScript database support. HTML 5 is currently in development by the Web Hypertext Application Technology Working Group (WHATWG).
JavaScript database support is available in Safari 3.1 and later, and in iPhone OS 2.0 and later.
You should read this documentation if you are a web developer who wants to store data locally on a user’s computer in amounts beyond what can reasonably be stored in an HTTP cookie.
Очень мне это показалось интересным. Какие возможность это открывает! Осталось дело за малы: что-бы IE8 начал поддерживать HTML5 (как, все еще, самый поп. бродильщик) и что-бы этот самый HTML5 уже наконец пришел в массы.
Ну а ежели вам интересно почитать и попробовать как это работает — милости прошу, Safari JavaScript Database Programming Guide к вашим услугам.
P.S.
Этак CoachDB в пролете останется ;)
Session variables without cookies
Session variables without cookies – заметка (и библиотека на javascript) о том, как можно сохранять данные пользователя в сессии не используя для этого cookie. Минус – это и правда сессия. После закрытия окна все пропадет (т.е. не сделать функцию типа “Remember Me”). Плюсы тоже есть – для каждого свои.
В любом случае статья интересна оригинальностью идем — она [идея], как мне показалось, из разряда “как же я сам об этом не подумал?! этого очевидно!”.


