<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-33790034</id><updated>2012-02-09T06:39:07.407-08:00</updated><category term='javascript'/><category term='prototype'/><title type='text'>Vadim Makishvili</title><subtitle type='html'>About Javascript in russian:&lt;br&gt;Generic solutions, Prototype Framework, Behaviour etc...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-33790034.post-8330914112746449501</id><published>2006-10-20T02:06:00.000-07:00</published><updated>2006-10-20T02:07:45.957-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Event Handlers on Disabled Inputs by Ryan Campbell [russian translation]</title><content type='html'>&lt;a href="http://particletree.com/notebook/event-handlers-on-disabled-inputs/"&gt;Original article&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Обработчики событий на disabled полях формы&lt;/h3&gt;&lt;br /&gt;Мы попали в интересную ситуацию на прошлой неделе. У нас есть input поля, которые никогда не получают фокус, но которые должны отвечать на события, такие как &lt;code&gt;onclick, onmousedown, и onmouseup&lt;/code&gt;. Чтобы они не получали фокус - мы добавили к ним аттрибут &lt;code&gt;disabled&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;input type="text" disabled="disabled" /&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Как и ожидалось, пользователь больше не мог кликать в поле. Но, о ужас! Это сломало все события, которые мы перед этим повесили на input. Клик над полем больше не вызывал соотвествующий обработчик события. &lt;br /&gt;&lt;br /&gt;Решение оказалось простым: ипсользовать &lt;code&gt;readonly&lt;/code&gt; вместо &lt;code&gt;disabled&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;input type="text" readonly="readonly" /&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h4&gt;Из комментариев к статье&lt;/h4&gt;&lt;br /&gt;Подобная техника работает только с &lt;code&gt;textarea&lt;/code&gt; и &lt;code&gt;input type="text"&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-8330914112746449501?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/8330914112746449501/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=33790034&amp;postID=8330914112746449501' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/8330914112746449501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/8330914112746449501'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/10/event-handlers-on-disabled-inputs-by.html' title='Event Handlers on Disabled Inputs by Ryan Campbell [russian translation]'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-33790034.post-7656967639663028465</id><published>2006-10-19T07:54:00.001-07:00</published><updated>2006-10-20T01:50:12.427-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Introduction to Events by Peter-Paul Koch  [russian translation]</title><content type='html'>&lt;a href="http://www.quirksmode.org/js/introevents.html"&gt;Original article&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;События- это основа приложений на яваскрипте. В этой статье мы рассмотрим что такое обработка событий, какие проблемы с этим связаны и как писать событийные кроссбраузерные скрипты.&lt;br /&gt;&lt;br /&gt;Без событий нет скриптов. Взгляните на любую веб-страницу с яваскриптом на ней: в большинстве случаев вы увидите событие, которое запускает скрипт. Причина очень проста. Яваскрипт предназначен для того, чтобы добавлять интерактивность на ваши страницы: пользователь что-то делает и скрипт реагирует на это.&lt;br /&gt;&lt;br /&gt;Значит нам нужен способ определения действий пользователя. Когда пользователь делает что-либо на странице, происходит событие. Также есть несколько событий, которые возникают не в результате действий пользователя: например, &lt;code&gt;load&lt;/code&gt; событие, которое возникает когда страница загрузилась.&lt;br /&gt;&lt;br /&gt;Яваскрипт может ловить некоторые из этих событий.  Начиная с Netscape 2 стало возможным вешать обработчики событий на некоторые HTML элементы - по больше части на ссылки и поля форм. Обработчик события ждет возникновения определенного события, например клик на ссылку. А когда это происходит - запускается некий явасрипт, который вы определили в  качестве обработчика события.&lt;br /&gt;&lt;br /&gt;Когда пользователь выполняет какое-либо действие на странице - он вызывает событие. Когда ваш скрипт реагирует на это событие - возникает интерактивность.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;История обработки событий&lt;/h3&gt;&lt;br /&gt;Как я говорил, без обработки  событий нет смысла писать яваскрипт для ваших страниц. Лучшие скрипты - те, которые отвечают на действия пользователя. По этой причине, когда Netscape реализовала вторую версию своего браузера с поддержкой яваскрипта, он также поддерживал события.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Модель Netscape&lt;/h4&gt;&lt;br /&gt;Netscape 2 поддерживал только некоторые события. Mouseover and mouseout быстро стали знаменитыми из-за легендарного &lt;a href="http://www.quirksmode.org/js/mouseov.html"&gt;mouseover effect&lt;/a&gt;, который менял изображения. Так же стало возможным отслеживать сабмит или ресет  формы, таким образом возникла клиентская валидация форм. Браузер также мог отслеживать получение или потерю фокуса элементами форм, а также начало и конец загрузки страницы. И хотя сейчас - это стандартное поведение браузеров, в то время это было революционным расширением возможностей веб-страниц.&lt;br /&gt;&lt;br /&gt;В своей самой древней форме обработчик событий выглядел примерно так: когда пользователь сликал на ссылку, обработчик события выполнялся и показывал alert попап:&lt;br /&gt;&lt;code&gt;&amp;lt;a href="somewhere.html" onclick="alert('I\'ve been clicked!')"&amp;gt;&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Очень важно понять, что этот  древний способ обработки событий стал де-факто стандартизирован Нетскейпом. Все остальные браузеры, включая Internet Explorer,  должны были соответствовать способу, придуманному Netscape, и трем обработчикам событий, если они хотели, чтобы пользовательские скрипты в них работали. Поэтому эти древние события и их обработчики работают во всех браузерах с поддержкой яваскрипта.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Современная модель событий&lt;/h4&gt;&lt;br /&gt;Тем не менее, со времен введения этих простых событий обработчики событий очень сильно изменились. В первую очередь увеличилось количество событий. Кроме того, способ регистрации обработчика событий для html элементов был изменен.  Сделать это можно теперь из яваскрипт-кода. Больше не нужно нагромождений обработчиков в html коде - теперь вы можете написать простую яваксрипт функцию и в ней установить обработчики событий для нужных элементов.&lt;br /&gt;&lt;br /&gt;Четвертая версия браузеров предложила больше информации о самих событиях. Где была мышь, когда случилось событие? Какая клавиша была нажата? Наконец, браузер должен был разруливать ситуацию, когда элемент и его родитель - оба имели обработчик одного и того же события. Какой из них запускался первым?&lt;br /&gt;&lt;br /&gt;С тех пор, как эта функциональность была добавлена в разгаре Войны Браузеров, Нетскейп и Майкрософт достигли точки полной несовместимости событийных моделей. Позднее появилась третья модель, когда W3C опубликовала свою &lt;a href="http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/"&gt;DOM Event specification&lt;/a&gt; Несмотря на один &lt;a href="http://evolt.org/article/Mission_Impossible_mouse_position/17/23335/index.html"&gt;серьезный недостаток&lt;/a&gt;, модель W3C, которая основана преимущественно  на  старой модели Netscape, была универсальнее и разностороннее, с добавлением  новых интересных функциональных возможностей и решившая множество проблем старых моделей.&lt;br /&gt;&lt;br /&gt;Естественно, что  существование трех моделей привело к тому, что обработка событий не работает одинаково во всех браузерах.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Проблемы браузерной совместимости&lt;/h3&gt;&lt;br /&gt;Начнем сначала. Как с &lt;a href="http://www.quirksmode.org/js/introdh.html"&gt;DHTML&lt;/a&gt;, &lt;a href="http://www.quirksmode.org/dom/intro.html"&gt;W3C DOM&lt;/a&gt; , так и с любой другой скриптовой техникой,   мы должны заботиться о том, чтобы  наш код работал только в тех браухерах, которые его понимают. Вызов &lt;code&gt;stopPropagation()&lt;/code&gt; в IE или &lt;code&gt;srcElement&lt;/code&gt; в Netscape породит ужасные ошибки. Таким образом, мы в первую очередь должны проверить - поддерживает ли конкретный браузер методы или свойства, которые мы хотим использовать. По типу:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;if (Netscape) {&lt;br /&gt; use Netscape model&lt;br /&gt;}&lt;br /&gt;else if (Explorer) {&lt;br /&gt; use Microsoft model&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Но это только поверхностное решение, которое оставляет за бортом другие браузеры. Другие браузеры каждый сам для себя решали нелегкую задачу - какую из событийной модели поддерживать.  Konqueror/Safari, как всегда, ратовал за стандарты и поддержал W3C модель. Opera и iCab были более осторожны и поддержали большую часть обоих моделей - и старую модель Netscape и модель Microsoft . Я еще не изучал другие малоизвестные браузеры. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Не используйте определения браузера&lt;/h4&gt;&lt;br /&gt;Первое - НИКОГДА не  используйте &lt;a href="http://www.quirksmode.org/js/detect.html"&gt;определение браузера&lt;/a&gt;. Это самый быстрый путь в ад :) Любой скрипт, использующий &lt;code&gt;navigator.userAgent&lt;/code&gt; для определения событийной модели плох тем, что малоюзабелен, и должен быть как можно скорее переписан.&lt;br /&gt;Второе - не путайте DHTML &lt;a href="http://www.quirksmode.org/js/support.html"&gt;object detection&lt;/a&gt; и event object detection. Когда мы пишем DHTML, мы обычно проверяем поддержку DOM таким способом &lt;code&gt;if (document.all) &lt;/code&gt;. Если &lt;code&gt;true&lt;/code&gt;, скрипт использует &lt;code&gt;all&lt;/code&gt; массив от Microsoft .&lt;br /&gt;&lt;br /&gt;Но DHTML и обработка событий имеют разные паттерны совместимости браузеров. Например, Opera 6 поддерживает часть W3C DOM, но поддерживает и W3C Event модель. Следовательно, проверка DHTML объектов приведет к неправильному использованию событий в Opera. Так что использование в скриптах &lt;code&gt;if (document.layers)&lt;/code&gt; и подобных для детекта событийной модели - некорректно!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Правильные вопросы&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Так что же нам делать? Имена &lt;a href="http://www.quirksmode.org/js/events_properties.html"&gt;свойств событий&lt;/a&gt; порождают массу проблем. If we use a lot of specific object detections in this area, we solve 99% of the browser incompatibilities. Only finding the &lt;a href="http://evolt.org/article/Mission_Impossible_mouse_position/17/23335/index.html"&gt;mouse position&lt;/a&gt;, is very hard, accessing other bits of information is simpler.&lt;br /&gt;&lt;br /&gt;Кроме того, лучше не думать о трех событийных моделях вообще. Вместо этого нам надо понять 4 модели регистрации событий, две модели доступа к событию и две модели порядка событий. Рекомендую посмотреть &lt;a href="http://www.quirksmode.org/js/events_compinfo.html"&gt; таблицу совместимости событий&lt;/a&gt; для широкого обзора обработки событий и браузерной совместимости.&lt;br /&gt;&lt;br /&gt;Все вышеизложенное звучит ужасно, но это не так. Фактически, только тогда, когда я обнаружил это, я по-настоящему начал понимать обработку событий. Это все о правильных вопросах. Не спрашивайте:"Как мне написать скрипт для обработки событий?" Несмотря на то, что это тоже правильный вопрос, дать на него ответ очень сложно - ответ на него займет дофига страниц. Вместо этого, вам следует задавать более конкретные вопросы, на которые вы получите конкретные ответы:&lt;br /&gt;&lt;dl&gt;&lt;br /&gt;&lt;dt&gt; Сколько существует событий?&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;&lt;a href="http://www.quirksmode.org/js/events_events.html"&gt;Много.&lt;/a&gt; Конечно, некотороые из них не работают в некоторых браузерах.&lt;br /&gt;&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;Как зарегистрировать обработчик события для HTML элемента?&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Есть четыре способа для этого: &lt;a href="http://www.quirksmode.org/js/events_early.html"&gt; inline&lt;/a&gt;, &lt;a href="http://www.quirksmode.org/js/events_tradmod.html"&gt;traditional&lt;/a&gt;, &lt;a href="http://www.quirksmode.org/js/events_advanced.html"&gt;W3C and Microsoft&lt;/a&gt;.  первый способ работает во &lt;b&gt;всех&lt;/b&gt; браузерах. Никаких проблем с ним.&lt;br /&gt;&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;Как запретить событие по умолчанию у элемента?&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Если вы сделаете &lt;code&gt;return false &lt;/code&gt; из вашего обработчика события, то &lt;a href="http://www.quirksmode.org/js/events_early.html#default"&gt;действие по умолчанию&lt;/a&gt; (редирект по ссылке, сабмит формы) прекратится. Этот способ был стандартизирован Netscape 2 и работает до сих пор.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;Как мне получить доступ к событию, если я хочу получить больше инфрмации?[How do I access the event when I want to obtain more information?]&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Ест два пути сделать это: W3C/Netscape и Microsoft. Чтобы решить проблему совместимости, вам нужна &lt;a href="http://www.quirksmode.org/js/events_access.html"&gt;одна строчка кода&lt;/a&gt;&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;Когда у меня есть доступ к событию, как мне прочитать его свойства?&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Здесь есть проблема совместимости. Все правильно, объяснение на &lt;a href="http://www.quirksmode.org/js/events_properties.html"&gt;этой странице&lt;/a&gt;. Вам нужна &lt;a href="http://www.quirksmode.org/js/events_compinfo.html"&gt;таблица совместимости свойств событий&lt;/a&gt; и some strict object detection.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;Если элемент и один из его предков имеют обрабтчики для одного и того же события, какой запустится первым?&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Я сомневаюсь, что вы когда-нибудь задали бы этот вопрос. Но тем не менее, различные модели дают на него ответ. Есть &lt;a href="http://www.quirksmode.org/js/events_order.html"&gt;два порядка событий&lt;/a&gt;, перехвата и просачивания событий. В ежедневной практике они неважны, за редкими случаями. Вам необходимо беспокоиться в-основном только о том, как их выключить. А это - две строчки кода. &lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;Is Netscape 4’s event handling model up to supporting interesting scripts?&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Not really, though you can execute simple scripts in this browser. See the special &lt;a href="http://www.quirksmode.org/js/events_netscape4.html"&gt;Netscape 4&lt;/a&gt; page for the gory details.&lt;/dd&gt;&lt;br /&gt;&lt;/dl&gt;&lt;br /&gt;&lt;br /&gt;Все вопросы выше ссылаются на отдельные страницы со справочной информацией на тему обработки событий.&lt;br /&gt;&lt;br /&gt;Хитрость написания кроссбраузерного обработчка событий не в том, чтобы использовать проверку объектной модели в целом, а в том, чтобы ответить на эти вопросы по-отдельности. Вы обнаружите, что вам нужно беспокоиться в-основном о совместимости, когда вы читаете свойства событий.&lt;br /&gt;&lt;br /&gt;Сначала выберите модель регистрации событий, затем убедитесь, что событие доступно во всех браузерах, затем убедитесь, что вы можете прочитать свойства события и потом решайте проблемы порядка событий. Таким образом, вы можете решать каждую проблему совместимости по-отдельности и быть уверенными в том, что ваш код будет работать во всех браузерах, ктоторые поддерживают обработку событий.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Продолжение&lt;/h3&gt;&lt;br /&gt;Если вы хотите пройтись через все события на странице по порядку, вам &lt;a href="http://www.quirksmode.org/js/events_events.html"&gt;сюда&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Написание обработчика событий&lt;/h3&gt;&lt;br /&gt;Так как же его написать? Ниже я кратко это опишу для тех, кто не хочет учиться теории и кому нужны быстрые ответы.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Регистрация обработчика&lt;/h4&gt;&lt;br /&gt;Первый шаг - регистрация обработчика события. Вы должны быть уверены, что браузер выполняет ваш скрипт всякий раз, когда происходит нужное вам событие.&lt;br /&gt;&lt;br /&gt;Есть четыре способа для  регистрации обработчика события: &lt;a href="http://www.quirksmode.org/js/events_early.html"&gt; inline&lt;/a&gt;, &lt;a href="http://www.quirksmode.org/js/events_tradmod.html"&gt;traditional&lt;/a&gt;, &lt;a href="http://www.quirksmode.org/js/events_advanced.html"&gt;W3C and Microsoft&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Самый лучший - traditional, поскольку он полностью кроссбраузерный и универсальный. Для регистрации сделайте следующее:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;element.onclick = doSomething;&lt;br /&gt;if (element.captureEvents) element.captureEvents(Event.CLICK);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Сейчас функция &lt;code&gt;doSomething&lt;/code&gt; зарегистрирована как обработчик события &lt;code&gt;click&lt;/code&gt; для html-элемента &lt;code&gt;element&lt;/code&gt;. Это подразумевает, что как только пользователь кликнет левой клавишей мыши на элементе - выполнится функция &lt;code&gt;doSomething&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Доступ к событию&lt;/h4&gt;&lt;br /&gt;Когда вы зарегистрировали ваш обработчик события, вы написали настоящий скрипт. Скорее всего вы захотите получить &lt;a href="http://www.quirksmode.org/js/events_access.html"&gt;доступ к самому событию&lt;/a&gt; и прочитать информацию о самом событии. Для этого всгда начинайте ваш обработчик события так:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function doSomething(e) {&lt;br /&gt; if (!e) var e = window.event&lt;br /&gt; // e refers to the event&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Сейчас &lt;code&gt;e&lt;/code&gt; ссылается на событие во всех браузерах.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Доступ к html элементу&lt;/h4&gt;&lt;br /&gt;Иногда вам также нужно будет получить доступ к html элементу, над которым произошло событие. Есть два способа для этого: использовать ключевое слово &lt;code&gt;this&lt;/code&gt; или использовать свойства &lt;code&gt;target/srcElement&lt;/code&gt;.&lt;br /&gt;Самое правильное решение - использовать &lt;code&gt;this&lt;/code&gt;, которое не всегда  правильно ссылается на html элемент, зато в комбинации с traditional  моделью работает отлично.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function doSomething(e) {&lt;br /&gt; if (!e) var e = window.event&lt;br /&gt; // e refers to the event&lt;br /&gt; // this refers to the HTML element which currently handles the event&lt;br /&gt; // target/srcElement refer to the HTML element the event originally took place on&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Свойства &lt;code&gt;target/srcElement&lt;/code&gt; содержат ссылку на html элемент, непосредственно над которым произошло событие. Эти свойства очень удобны, но когда событие &lt;a href="http://www.quirksmode.org/js/events_order.html"&gt;просачивается или перехватывается&lt;/a&gt;, эти свойства не меняются: это по-прежнему ссылка на элемент, непосредственно над которым произошло событие. (Посмотрите &lt;a href="http://www.quirksmode.org/js/events_properties.html"&gt;Event properties&lt;/a&gt; для &lt;code&gt;target/srcElement&lt;/code&gt; и &lt;a href="http://www.quirksmode.org/js/this.html"&gt;эту страницу&lt;/a&gt; для ключевого слова &lt;code&gt;this&lt;/code&gt;)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Чтение свойств&lt;/h4&gt;&lt;br /&gt;Чтение свойств событий - это самое узкое место в браузерной совместимости. Дела здесь - хуже некуда. Изучите &lt;a href="http://www.quirksmode.org/js/events_compinfo.html"&gt;таблицу совместимости событий&lt;/a&gt; и напишите свой собственный скрипт, чтобы понять, как обстоят с этим дела. &lt;br /&gt;Запомните - всегда первым делом пишите самую детальную проверку объекта. Сначала проверьте - есть ли такое свойство, а уже потом читайте его значение. Например:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function doSomething(e) {&lt;br /&gt; if (!e) var e = window.event&lt;br /&gt; if (e.keyCode) code = e.keyCode;&lt;br /&gt; else if (e.which) code = e.which;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Теперь &lt;code&gt;code&lt;/code&gt; содержит код нажатой клавиши во всех браузерах.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Порядок событий&lt;/h4&gt;&lt;br /&gt;Наконец вы долджны принять решение - разрешать &lt;a href="http://www.quirksmode.org/js/events_order.html"&gt;просачиваться&lt;/a&gt; событию или нет. Если вы не хотите, прекратите распространение события:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function doSomething(e) {&lt;br /&gt; if (!e) var e = window.event&lt;br /&gt; // handle event&lt;br /&gt; e.cancelBubble = true;&lt;br /&gt; if (e.stopPropagation) e.stopPropagation();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Написание скрипта&lt;/h4&gt;&lt;br /&gt;Вот теперь вы можете начать писать скрипт обработки событий. Используйте примеры кода, которые я привел. И помните: итнтерактивность должна быть логичной, иначе пользователь не поймет, что случилось.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-7656967639663028465?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/7656967639663028465/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=33790034&amp;postID=7656967639663028465' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/7656967639663028465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/7656967639663028465'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/10/introduction-to-events-by-peter-paul.html' title='Introduction to Events by Peter-Paul Koch  [russian translation]'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-33790034.post-3887386004429160879</id><published>2006-09-26T07:50:00.000-07:00</published><updated>2006-09-26T07:58:48.296-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Objectifying JavaScript by Jonathan Snook [russian translation]</title><content type='html'>&lt;a href="http://www.digital-web.com/articles/objectifying_javascript/"&gt;Original article.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Когда я только начинал программировать на Javascript я создавал мои переменные и инкапсулировал функциональность, которая мне нужна, в функцию. Так как мои задачи становились более сложными и я начал изучать OOP в других языках, я увидел преимущества использования OOP в Javascript.&lt;br /&gt;&lt;br /&gt;Чем больше становились скрипты, тем больше связей возникало между функциями. Предположим, что у вас есть десять функций на странице, шесть из которых вызывают одна другую для выполнения задачи, а другие четыре делают что-то совершенно другое. Тот, кто впервые увидит этот код, несомненно не получит четкого пердставления о структуре скрипта. Этот как раз тот случай, когда нужен объект. &lt;br /&gt;&lt;br /&gt;В настоящем объектно-ориентированном смысле, объект представляет  "a thing". Это может быть изображение, пользователь, документ - все, что угодно, что представлено именем существительным. Объект содержит свойства, которые его описывают и методы, которые описывают действия этого объекта (или что можно сделать с объектом). Например, array в javascript - это объект. У него есть свойства, такие как length, которые хранят информацию об объекте, и методы, такие как push, которые что-то делают с объектом.&lt;br /&gt;&lt;br /&gt;Главная идея здесь простая - &lt;strong&gt;objects encapsulate related functionality&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;В Javascript-е мы часто выполняем серии задач на существующих объектах. Например, валидация формы: "Когда эта форма сабмитится, проверить что пользователь вввел валидный e-mail, телефон и т.д." Вместо создания функции для проверки каждой формы на странице, почему не собрать связанные задачи в объект FormValidator(tm) , для того чтобы можно было легко использовать его на других страницах и других сайтах? Даже задачи, по типу установки onclick события на коллекцию ссылок лучше вынести в объект. &lt;br /&gt;&lt;br /&gt;Мы установили, что объекты хороши в использовании, но что надо сделать, чтобы создать их? Javascript очень гибкий язык, предлагающий два основных метода для создания объектов, каждый со множеством смыслов и вариаций. Вот они, два метода, о которых мы говорим:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;using the object literal&lt;br /&gt;&lt;/li&gt;&lt;li&gt;using the &lt;code&gt;new&lt;/code&gt; keyword with a function&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Давайте прольем немного света на эти варианты и опишем преимущества и недостатки каждого.&lt;br /&gt;&lt;h3&gt;Using the Object Literal&lt;/h3&gt;&lt;br /&gt;Создание объекта с использованием объектного литерала очень простое. Объектный литерал заключается в фигурные скобки с нулем и больше пар "свойство:значение", разделенных запятой. Каждое свойство и его значение разделяется двоеточием. Именем свойства может быть идентификатор, строка или число. Значением свойства может быть строка, число, функция или другой объект. Имя свойства конвертируется в строку, таким образом строка "25" и число 25 - одно и то же.&lt;br /&gt;&lt;br /&gt;Пример:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;{&lt;br /&gt;    property: value,&lt;br /&gt;    property: value&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h4&gt;Создание объектов:&lt;/h4&gt;&lt;br /&gt;Для демонстранстрации, давайте создадим новый объект, с тремя свойствами, два хранят числовые значения,третье - это анонимная функция( функция без имени )&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;var AnimationManager = &lt;br /&gt;{&lt;br /&gt;    framesPerSecond: 30,&lt;br /&gt;    totalLength: 15,&lt;br /&gt;    startAnimation: function(){ /* code goes here */ }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Важно понять, что объектный литерал - это просто shortcut  для создания объекта, используя встроенный Object-type. Мы изучим этот код более детально позже, а сейчас просто запомним, что мы также можем создать &lt;code&gt;AnimationManager&lt;/code&gt; объект следующим образом:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;var AnimationManager = new Object();&lt;br /&gt;AnimationManager.framesPerSecond = 30;&lt;br /&gt;AnimationManager.totalLength = 15;&lt;br /&gt;AnimationManager.startAnimation = function () { /* code goes here */ };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h4&gt;Доступ к свойствам объекта&lt;/h4&gt;&lt;br /&gt;Мы назначили объектный литерал переменной &lt;code&gt;AnimationManager&lt;/code&gt; и теперь можем получить доступ к свойствам объекта используя точечную нотацию или скобки. Следующие строки идентичны:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;alert(AnimationManager.framesPerSecond); // object.property&lt;br /&gt;alert(AnimationManager['framesPerSecond']); // object['property']&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;В основном мы будем использовать точечную нотацию, но возможность обращаться к объекту, как к hash-массиву - очень удобная возможность. Например, мы можем написать функцию, которая будет устанавливать значения для полей &lt;code&gt;framesPerSecond&lt;/code&gt; or &lt;code&gt;totalLength&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function changeValue(property, value) &lt;br /&gt;{&lt;br /&gt;    if (property == "framesPerSecond")&lt;br /&gt;        AnimationManager.framesPerSecond = value;&lt;br /&gt;    else&lt;br /&gt;        AnimationManager.totalLength = value;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Или можно использовать возможность доступа к свойствам через скобки:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function changeValue(property, value) &lt;br /&gt;{&lt;br /&gt;    AnimationManager[property] = value;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Таким образом мы можем упростить код - одна строка вместо серии if-else&lt;br /&gt;&lt;h4&gt;Добавление свойств или методов&lt;/h4&gt;&lt;br /&gt;Нашему объекту, который теперь связан с переменной, мы можем добавить новые свойства или методы в любое время. Просто создайте новое свойство, используя точечную нотацию или скобки, как если бы вы получали доступ к существующему свойству:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;AnimationManager.stopAnimation = function(){ }&lt;br /&gt;AnimationManager.defaultTween = "sinoidal";&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You’ll recall that is exactly what we did earlier when we discussed the alternate new Object() syntax for the object literal.&lt;br /&gt;&lt;h3&gt;Использование Function&lt;/h3&gt;&lt;br /&gt;В javascript функция - это объект. Создавая функцию - вы создаете объект. Объекты функций более полезны, чем объектные литералы, потому что они могут быть использованы как шаблоны для новых объектов.&lt;br /&gt;Для тех, кто незнаком с OOP, этот объектный шаблон более известен, как класс. В отличие от объектов, которые каждый раз строятся заново,  объект, созданный на основе класса - уже заполнен методами и свойствами. Определяя new function object, мы в результате определяем шаблон (blueprint) для новых объектов, которые мы можем использовать снова и снова.&lt;br /&gt;Например, мы создали &lt;code&gt;AnimationManager&lt;/code&gt; в передыдущем разделе, используя объектный литерал. Нам действительно нужен только один менеджер, таким образом у нас нет необходимости предоставлять второй механизм. Объектный литерал - отличный выбор для этого объекта. Давайте немного расширим пример и представим, что &lt;code&gt;AnimationManager&lt;/code&gt; контролирует множеством объектов &lt;code&gt;Animation&lt;/code&gt;. Если мы объявим &lt;code&gt;Animation&lt;/code&gt;, используя объектный литерал, нам придется писать этот код еще и еще для каждого анимированного объекта. Создание таких объектов на базе шаблона предоставляет нам решение этой проблемы.&lt;br /&gt;&lt;h4&gt;Использование шаблона&lt;/h4&gt;&lt;br /&gt;Чтобы использовать наш шаблон для создания объекта, мы используем ключевое слово &lt;code&gt;new&lt;/code&gt; и вызов шаблона функции, передавая в нее аргументы:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function Animation(element) &lt;br /&gt;{&lt;br /&gt;    this.animationLength = 30;&lt;br /&gt;    this.element = element;&lt;br /&gt;}&lt;br /&gt;var obj = document.getElementById('login');&lt;br /&gt;var animateLogin = new Animation(obj);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Во время выполнения &lt;code&gt;new Animation(obj)&lt;/code&gt;  создается пустой объект и вызывается &lt;code&gt;Animation&lt;/code&gt;, связывая новый объект с его &lt;code&gt;this&lt;/code&gt; ключевым словом. Мы можем связать свойства объекта с  его&lt;code&gt;this&lt;/code&gt; keyword и как результат выполнения функции вернется новый объект со всеми его свойствами. Таким образом новый объект будет имеет два свойства &lt;code&gt;animationLength&lt;/code&gt; и &lt;code&gt;element&lt;/code&gt; и связан с переменной &lt;code&gt;animateLogin&lt;/code&gt; для дальнейшего использования.&lt;br /&gt;Мы также можем создать методы в нашем шаблоне, просто добавляя функции:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function Animation(element) &lt;br /&gt;{&lt;br /&gt;    this.animationLength = 30;&lt;br /&gt;    this.element = element;&lt;br /&gt;    this.onStart = function () &lt;br /&gt;    {&lt;br /&gt;        alert("The animation is starting!");&lt;br /&gt;    };&lt;br /&gt;    this.onEnd = function () &lt;br /&gt;    {&lt;br /&gt;        alert("The animation is ending!");&lt;br /&gt;    };&lt;br /&gt;}&lt;br /&gt;var obj = document.getElementById('login');&lt;br /&gt;var animateLogin = new Animation(obj);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Важно понять, что &lt;strong&gt;мы можем&lt;/strong&gt; в &lt;code&gt;Animation &lt;/code&gt; функцию добавлять свойства как объектные литералы:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function Animate() { }&lt;br /&gt;Animate.animationLength = 30;&lt;br /&gt;Animate.element = element;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;Разница здесь в том, что эти дополнительные свойства не являются частью шаблона&lt;/strong&gt;&lt;br /&gt;Если мы выполним &lt;code&gt;new Animation()&lt;/code&gt; из кода выше, мы получим назад пустой объект - не объект с двумя свойствами. Например:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;var animateLogin = new Animation(loginform);&lt;br /&gt;Animation.animationLength = 30;&lt;br /&gt;alert(animateLogin.element); // the 'loginform' element&lt;br /&gt;alert(animateLogin.animationLength); // undefined!&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h4&gt;Prototype&lt;/h4&gt;&lt;br /&gt;Метод описанный выше  работает замечательно, но он немного непроизводительный. В частности, создание тысячи объектов &lt;code&gt;Animation&lt;/code&gt; создаст тысячу копий каждого метода и свойства, занимая ценную память, которую мы могли бы использовать для других вещей ( и создавая возможную &lt;a href="http://www.quirksmode.org/blog/archives/2005/02/javascript_memo.html"&gt;утечку памяти&lt;/a&gt;). К счастью для нас, есть путь создания шаблонного объекта, который генерит объекты, как ссылки на те же самые методы и свойства: Мы назначаем свойства шаблону через &lt;strong&gt;prototype&lt;/strong&gt;. Поступая таким образом, все объекты, инициализированные из оргинального шаблона могут использовать методы и свойства из прототипа шаблона вместо создания их собственных копий. Короче говоря, вызов свойства объекта в первую очередь проверяет объект на наличие этого свойства, если оно не существует, проверяется прототип шаблона. Таким образом существует только одна версия свойства, сохраненная в памяти, невзирая на то, сколько объектов мы создали.&lt;br /&gt;Синтаксис выглядит почти так же, как  добавление свойства для объекта &lt;code&gt;Animation&lt;/code&gt;. Вместо &lt;code&gt;Animation.onStart&lt;/code&gt; мы добавляем свойство в функцию через свойство объекта prototype: &lt;code&gt;Animation.prototype.onStart&lt;/code&gt;. Давайте перепишем &lt;code&gt;Animation&lt;/code&gt; объект, чтобы быть увереными, что метода ссылаются, а не копируются:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function Animation(element)&lt;br /&gt;{&lt;br /&gt;    this.animationLength = 30;&lt;br /&gt;    this.element = element;&lt;br /&gt;}&lt;br /&gt;Animation.prototype.onStart = function() &lt;br /&gt;{&lt;br /&gt;    alert("The animation is beginning!");&lt;br /&gt;};&lt;br /&gt;Animation.prototype.onEnd = function() &lt;br /&gt;{&lt;br /&gt;    alert("The animation is ending!");&lt;br /&gt;};&lt;br /&gt;var animateLogin = new Animate(loginform);&lt;br /&gt;animateLogin.onStart();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Мы можем добавить в прототип шаблона в любое время и новые свойства будут автоматически доступны, даже если объект был уже создан. Давайте перестроим последний пример для демонстрации:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function Animation(element)&lt;br /&gt;{&lt;br /&gt;   this.animationLength = 30;&lt;br /&gt;   this.element = element;&lt;br /&gt;}&lt;br /&gt;var animateLogin = new Animate(loginform);&lt;br /&gt;Animation.prototype.onStart = function() &lt;br /&gt;{&lt;br /&gt;    alert("The animation is beginning!");&lt;br /&gt;};&lt;br /&gt;Animation.prototype.onEnd = function() &lt;br /&gt;{&lt;br /&gt;    alert("The animation is ending!");&lt;br /&gt;};&lt;br /&gt;animateLogin.onStart();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Даже если мы создали новый &lt;code&gt;Animation&lt;/code&gt; объект &lt;strong&gt;перед&lt;/strong&gt; тем, как объявили &lt;code&gt;onStart &lt;/code&gt; и &lt;code&gt;onEnd &lt;/code&gt; методы, мы можем использовать их! Это огромное преимущество способа, сонованного на прототипе.&lt;br /&gt;&lt;h4&gt;Объект, как результат выполнения конструктора&lt;/h4&gt;&lt;br /&gt;Как вы знаете, функции могут возвращать значения. Что интересно, если вы возвращаете объект, как результат выполнения конструктора (функция вызванная сключевым словом &lt;code&gt;new&lt;/code&gt;),  этот объект будет использован как новый объект вместо пустого только что созданного объекта и назначенного слову &lt;code&gt;this&lt;/code&gt;. Любые свойства, которые вы определите В или ВНЕ функции будут недоступны. Пример объяснит это лучше:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function Animation(element)&lt;br /&gt;{&lt;br /&gt;    this.animationLength = 30;&lt;br /&gt;    return {hello: "Hello, world!"}; // empty object.&lt;br /&gt;}&lt;br /&gt;Animation.prototype.onStart = function() { };&lt;br /&gt;Animation.prototype.onEnd = function() { };&lt;br /&gt; &lt;br /&gt;var animateLogin = new Animation(loginform);&lt;br /&gt; &lt;br /&gt;animateLogin.onStart(); // undefined!&lt;br /&gt;animateLogin.animationLength; // undefined!&lt;br /&gt;alert(animateLogin.hello); // "Hello, world!"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;"В чем фишка", спросите вы? Это позволяет нам создавать &lt;strong&gt;приватные переменные&lt;/strong&gt;, которые доступны внутри нашего объекта, но не доступны снаружи, как только что созданные. Давайте посмотрим на пример с использованием ключевого слова &lt;code&gt;new&lt;/code&gt; в функции:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function Animation(element)&lt;br /&gt;{&lt;br /&gt;    var looped = 0;&lt;br /&gt;    var e = element;&lt;br /&gt; &lt;br /&gt;    function construct() &lt;br /&gt;    {&lt;br /&gt;        this.loopCount = function() &lt;br /&gt;        {&lt;br /&gt;            return looped;&lt;br /&gt;        }&lt;br /&gt;        this.loop = function() &lt;br /&gt;        {&lt;br /&gt;            looped++;&lt;br /&gt;        }&lt;br /&gt;   }&lt;br /&gt;   return new construct();&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;var animateLogin = new Animation();&lt;br /&gt; &lt;br /&gt;animateLogin.loop();&lt;br /&gt; &lt;br /&gt;alert(animateLogin.loopCount()); // it's 1&lt;br /&gt;alert(animateLogin.looped); // undefined!&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We created a new function called construct within our &lt;code&gt;Animation&lt;/code&gt; function. Anytime we create a new&lt;code&gt;Animation&lt;/code&gt; object, we end up returning a new construct object instead.  Это означает, что методы &lt;code&gt;loopCount &lt;/code&gt; и &lt;code&gt;loop &lt;/code&gt; будут единственными, к кому мы будем иметь доступ. Тем не менее, благодаря &lt;a href="http://blog.morrisjohns.com/javascript_closures_for_dummies"&gt;замыканиям&lt;/a&gt; переменная &lt;code&gt;looped&lt;/code&gt; все еще доступна внутри тех функций.&lt;br /&gt;&lt;h4&gt;Singletons with functions&lt;/h4&gt;&lt;br /&gt;Сушествуют ситуации, когда у нас есть центральный объект и нам не нужно предоставлять механизм для создания его новых версий. The &lt;a href="http://en.wikipedia.org/wiki/Singleton_pattern"&gt;singleton&lt;/a&gt; design pattern решает эту проблему. В примере, который мы используем, &lt;code&gt;AnimationManager&lt;/code&gt; - центральный объект, который должен контролировать когда анимация начинается и заканчивается. We only need one of these, as opposed to the individual animations that require separate Animation objects with unique values. Мы создали &lt;code&gt;AnimationManager&lt;/code&gt; с помощью объектного литерала, но вы будете часто встречать singletons implemented with functions. Давайте посмотрим, как это делается:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;var AnimationManager = new function()&lt;br /&gt;{&lt;br /&gt;    this.framesPerSecond = 30;&lt;br /&gt;    this.startAnimation = function(){ /* code goes here*/ }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Мы просто вызываем &lt;code&gt;new&lt;/code&gt; на анонимной функции и используем &lt;code&gt;this&lt;/code&gt; для установки свойств и методов. Создание нового объекта этим путем позволяет избежать  потенциального использования объекта, как шаблона. Вуаля, это функция-одиночка!  Если мы хотим быть очень осторожными в доступе к свойствам объекта, мы можем даже создать приватные переменные для нашего синглтона, используя ту же технику, что и в предыдущем разделе:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;var AnimationManager = new function()&lt;br /&gt;{&lt;br /&gt;    var framesPerSecond = 30;&lt;br /&gt;    function construct()&lt;br /&gt;    {&lt;br /&gt;        this.startAnimation = function() {}&lt;br /&gt;        this.getFPS = function() { return framesPerSecond; }&lt;br /&gt;        this.setFPS = function(fps) { framesPerSecond = fps; }&lt;br /&gt;    }&lt;br /&gt;    return new construct();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Преимущества этой техники над объектным литералом в том, что появляется возможность выполнять задачи в момент создания экземплята синглотона. Ни одна функция не может быть выполнена в момент создания экземпляра, когда мы используем объектный литерал. Для этого требуется дополнительный шаг для создания функции инициализации и запуска ее сразу после создания.&lt;br /&gt;&lt;h4&gt;The Object Factory&lt;/h4&gt;&lt;br /&gt;Другой продвинутый паттерн, который вы можете видеть время от времени - это &lt;a href="http://en.wikipedia.org/wiki/Factory_method_pattern"&gt;factory &lt;/a&gt;паттерн. Не вдаваясь в подробности, мы можем использовать функцию для создания объектов, которые удобны для обработки объектных свойств. Давайте взглянем на пример:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function objectMaker()&lt;br /&gt;{&lt;br /&gt;    return {value:5}&lt;br /&gt;}&lt;br /&gt;var object1 = objectMaker();&lt;br /&gt;var object2 = objectMaker();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Это удобно потому что мы можем выборочно перекрывать значения, распределяя значения одного литерала в другой [by mapping the values of one literal onto another.]&lt;br /&gt;&lt;a href="http://prototype.conio.net/"&gt;The Prototype JavaScript Framework&lt;/a&gt; (не путайте со свойством prototype) поступает именно таким образом со своим Object.extend методом.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-3887386004429160879?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/3887386004429160879/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=33790034&amp;postID=3887386004429160879' title='Комментарии: 4'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/3887386004429160879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/3887386004429160879'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/09/objectifying-javascript-by-jonathan.html' title='Objectifying JavaScript by Jonathan Snook [russian translation]'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-33790034.post-6312564860465310687</id><published>2006-09-18T08:45:00.000-07:00</published><updated>2006-09-18T08:51:08.101-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Mozilla feature. Or bug? Hmm..</title><content type='html'>Сегодня столкнулся со странным поведением Firefox.&lt;br /&gt;&lt;br /&gt;Если на странице объявлена форма, у которой есть id, но нет name - браузер Firefox при парсинге страницы сам добавляет к элементу формы name, значение которого берет из его id.&lt;br /&gt;&lt;br /&gt;Продолбался около 2 часов, пока нашел эту ошибку у себя в коде - я искал форму по его name. И все это время матерился на IE, который почему-то генерил ошибку. Теперь-то я знаю, что в этом отношении IE - честный браузер, не добавляет аттрибут вместо девелопера.&lt;br /&gt;&lt;br /&gt;Блин, медвежья услуга от Mozilla. :(&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-6312564860465310687?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/6312564860465310687/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=33790034&amp;postID=6312564860465310687' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/6312564860465310687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/6312564860465310687'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/09/mozilla-feature-or-bug-hmm.html' title='Mozilla feature. Or bug? Hmm..'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-33790034.post-4838094761625998865</id><published>2006-09-17T08:52:00.000-07:00</published><updated>2006-09-17T09:08:36.639-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Prototype documentation</title><content type='html'>Где, блин, брать качественную документацию?&lt;br /&gt;Конечно, можно смотреть код Сэма Стефенсона и пытаться понять суть методов.&lt;br /&gt;Но, признаюсь, первый раз открыв его - я мало что понял. Меня поразило то, насколько неудобно отструктурирован код - на каждой строчке спотыкались глаза, плюс использовались странные конструкции, которых я никогда не видел в js (несколько позже я узнал, что код написан в руби-стиле, и спустя некоторое время я признался сам себе, что руби-стиль не менее читаем, чем привычный С-подобный структированный код).&lt;br /&gt;&lt;br /&gt;Где же, блин, брать качественную документацию?&lt;br /&gt;Самая первая документация, которую  я нашел, находится &lt;a href="http://wiki.script.aculo.us/scriptaculous/show/Prototype"&gt;здесь&lt;/a&gt;.&lt;br /&gt;Это WIKI скриптакулоса, здесь есть некий перечень часто используемых методов прототипа. Вполне понятно описаны. Там же есть ссылки на другие ресурсы с документацией. &lt;br /&gt;&lt;br /&gt;Рекомендую обратить внимание на ресурс &lt;a href="http://www.sergiopereira.com/articles/prototype.js.html"&gt;Sergio Pereira&lt;/a&gt;. На сегодняшний день - это самая полная документация библиотеки версии 1.4.0.&lt;br /&gt;Там же есть возможность просмотреть этот документ на других языках. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://kropp.spb.ru/docs/prototype/"&gt;Виктор Кропп&lt;/a&gt; перевел документацию к версии 1.3.1, и для знакомства с библиотекой этого перевода более чем достаточно. После прочтения русского перевода настоятельно рекомендую вернуться к ресурсу Сержио Перейра и сделать на него закладку, потому что полнее документации по прототипу в инете нет (если я ошибаюсь, буду рад узнать об этом).&lt;br /&gt;&lt;br /&gt;Но кроме Сержио за развитием прототипа следит не один разработчик. Некоторые из них рассказывают на страницах своих блогов о тонкостях использования библиотеки.&lt;br /&gt;На мой взгляд, сюда стоит заглядывать:&lt;br /&gt;&lt;a href="http://encytemedia.com/blog/"&gt;http://encytemedia.com/blog/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ajaxian.com/by/topic/prototype/"&gt;http://ajaxian.com/by/topic/prototype/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://particletree.com/"&gt;http://particletree.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.snook.ca/jonathan/"&gt;http://www.snook.ca/jonathan/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Кроме этих ссылок, стоит заглядывать на страничку &lt;a href="http://www.prototypedoc.com/"&gt;Ronnie Roller&lt;/a&gt;, на которой он собирает ресурсы, посвященные прототипу.&lt;br /&gt;&lt;br /&gt;Ну, вот, вроде и хватит для вступления. Дальше я хочу пересказывать прочитанные статьи и, возможно, некоторые свои мысли об использовании prototype и других библиотек, основанных на нем.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-4838094761625998865?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/4838094761625998865/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=33790034&amp;postID=4838094761625998865' title='Комментарии: 6'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/4838094761625998865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/4838094761625998865'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/09/prototype-documentation.html' title='Prototype documentation'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-33790034.post-115797902715289275</id><published>2006-09-11T05:50:00.000-07:00</published><updated>2006-09-11T05:52:21.156-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Prototype home and repository</title><content type='html'>Первое, к чему нужно привыкнуть - официальной документации к библиотеке - нет и, скорее всего, не будет. Почему &lt;a href="http://conio.net/"&gt;Sam Stephenson&lt;/a&gt; не документировал код - не понятно. Но теперь это от него никто и не потребует, потому что много энтузиастов документирует возможности библиотеки в своих блогах. Собственно, читая их посты, я и учился пользоваться prototype-вкусняшками.&lt;br /&gt;&lt;br /&gt;На &lt;a href="http://prototype.conio.net/"&gt;сайте библиотеки&lt;/a&gt; последней версией называется 1.4.0. Вероятно, она считается супер-стабильной. Но пользоваться ей я бы не рекомендовал, потому что, во-первых, в ней не исправлена проблема утечки памяти в ИЕ, а во-вторых, в ней только 50% тех вкусняшек, которые делают javascript-разработку простой и вкусной.&lt;br /&gt;&lt;br /&gt;Если внимательно прочитать все 22 строки текста на сайте, то можно заметить маааленьким шрифтом путь к репозиторию библиотеки:&lt;br /&gt;Checkout with &lt;br /&gt;&lt;code&gt;svn co&lt;/code&gt; &lt;a href="http://dev.rubyonrails.org/svn/rails/spinoffs/prototype"&gt;http://dev.rubyonrails.org/svn/rails/spinoffs/prototype&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Там лежат самые свежие исходники библиотеки.&lt;br /&gt;&lt;br /&gt;По тому пути меня интересует только один файлик - &lt;a href="http://dev.rubyonrails.org/svn/rails/spinoffs/prototype/CHANGELOG"&gt;CHANGELOG&lt;/a&gt; - в нем описаны все изменения в текущей версии.&lt;br /&gt;Для того, чтобы получить самую свежую версию библиотеки (а на сегодняшний день это 1.5.0_rc1), я хожу &lt;a href="http://dev.rubyonrails.org/browser/trunk/railties/html/javascripts/"&gt;сюда&lt;/a&gt;, дальше кликаю в ссылку prototype.js, перехожу на страницу, где показан весь код библиотеки в нумерованном списке и внизу этой страницы нахожу ссылки:&lt;br /&gt;Download in other formats: &lt;a href="http://dev.rubyonrails.org/browser/trunk/railties/html/javascripts/prototype.js?format=txt"&gt;Plain Text&lt;/a&gt;, &lt;a href="http://dev.rubyonrails.org/browser/trunk/railties/html/javascripts/prototype.js?format=raw"&gt;Original Format&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Именно здесь всегда &lt;b&gt;свежий&lt;/b&gt; код :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-115797902715289275?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/115797902715289275/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=33790034&amp;postID=115797902715289275' title='Комментарии: 5'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/115797902715289275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/115797902715289275'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/09/prototype-home-and-repository.html' title='Prototype home and repository'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-33790034.post-115792224301587744</id><published>2006-09-10T13:45:00.000-07:00</published><updated>2006-09-10T14:11:10.013-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Prototype's meeting</title><content type='html'>&lt;a href="http://phenixsolutions.com"&gt;Компания&lt;/a&gt;, в которой я работаю, получила заказ на создание веб-приложения с большим количеством нетривиальной логики в юзер-интерфейсе. С возможностью глобального управления DOM структурой приложения на клиентской стороне. Естессно, с ассинхронными запросами на сервер. Куда ж мир теперь без AJAX :)&lt;br /&gt;&lt;br /&gt;Начав писать javascript-интерфейс со &lt;a href="http://svetkina.livejournal.com"&gt;Светой&lt;/a&gt;, мы стали создавать проектные библиотечки, собирая их, то из наших уже действующих проектов, то придумывая заново гениальные решения :)&lt;br /&gt;&lt;br /&gt;Одна из задач от заказчика - показывать юзеру увеличенные изображения по клику на маленькие иконки этих изображений. Тривиально! Но заказчик захотел показывать это...  плавно. Красоты захотел :)&lt;br /&gt;&lt;br /&gt;Света мне дала линку на &lt;a href="http://script.aculo.us"&gt;scriptaculous&lt;/a&gt; - она когда-то видела, что там можно делать какие-то эффекты. Действительно - добавить плавное увеличение любого блочного элемента оказалось элементарно с помощью этой библиотечки. Спасибо &lt;a href="http://mir.aculo.us/"&gt;Томасу Фучу&lt;/a&gt; :)&lt;br /&gt;&lt;br /&gt;Потом уже, копаясь в коде библиотек скриптакулоса, я обнаружил, что они базируются на какой-то странной библиотеке prototype.js. Полез копаться уже в ней и ... прозрел!&lt;br /&gt;&lt;br /&gt;Prototype - это относительно легкая, почти безглючная и аафигенно удобная в использовании библиотека, которую я использую под девизом:"Зачем изобретать велосипед? Он уже создан и тысячи людей УЖЕ ездят на нем!"&lt;br /&gt;&lt;br /&gt;Читайте дальше. Будет интересно :)&lt;br /&gt;&lt;br /&gt;И как говорит Justin Palmer: "Happy prototyping!"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-115792224301587744?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/115792224301587744/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=33790034&amp;postID=115792224301587744' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/115792224301587744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/115792224301587744'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/09/prototypes-meeting.html' title='Prototype&apos;s meeting'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-33790034.post-115782612120459226</id><published>2006-09-09T11:20:00.000-07:00</published><updated>2006-09-11T04:03:47.233-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Prototype library in russian</title><content type='html'>В своей работе я много использую Prototype.js библиотеку.&lt;br /&gt;К сожалению, ее автор не создает документацию к ней.&lt;br /&gt;Но к счастью, другие энтузиасты пишут статьи о возможностях prototype-library.&lt;br /&gt;&lt;br /&gt;Опять же, к некоторому сожалению, 100% статей - на английском.&lt;br /&gt;Но  к счастью, 70% этих статей написаны простым английским (который мне понятен) с примерами кода.&lt;br /&gt;&lt;br /&gt;Я буду в своем блоге публиковать вольные переводы этих статей и свои мысли, дабы распространить знание об этой библиотеке дальше.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-115782612120459226?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/115782612120459226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/115782612120459226'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/09/prototype-library-in-russian.html' title='Prototype library in russian'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-33790034.post-115728245222748924</id><published>2006-09-03T04:20:00.000-07:00</published><updated>2006-09-06T04:10:53.460-07:00</updated><title type='text'>Hello World!</title><content type='html'>Решил сменить LiveJournal на нормальный блог.&lt;br /&gt;Blogger - движок от Google, который как и все гугловкие продукты постоянно развивается и представляет собой отличный продукт. &lt;br /&gt;&lt;br /&gt;Меня только одно смущает - английским письменным я не владею настолько, чтобы вести на нем дневник, поэтому на 99% он будет русским. Оставляю 1% английского - для тех записей, которые бы я хотел, чтобы увидели англоязычные пользователи.&lt;br /&gt;&lt;br /&gt;Hello World! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/33790034-115728245222748924?l=makishvili.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makishvili.blogspot.com/feeds/115728245222748924/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=33790034&amp;postID=115728245222748924' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/115728245222748924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/33790034/posts/default/115728245222748924'/><link rel='alternate' type='text/html' href='http://makishvili.blogspot.com/2006/09/hello-world.html' title='Hello World!'/><author><name>Vadim Makishvili</name><uri>http://www.blogger.com/profile/15724981258328754842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
