Подлипенский Павел

Блог о технологиях и деньгах

ExtJS: События

clock июля 29, 2009 17:00 by author Подлипенский Павел

Сегодня я начинаю цикл статей посвященных фреймворку ExtJs. Это не будут туториалы или мануалы для пошагового изучения библиотеки. Я просто хочу поделиться своим опытом, поэтому начну с чего попало, а именно – с событий.

С изобретением GUI и Мыши, DOM-объекты, подобные кнопкам и текстовым полям стали обладать некими событиями. Например, click, mouseover, keydown и другими. По сути событие – это сообщение, вызов функции, генерируемое одной частью приложения (источником), которое извещает другую часть приложения (приемник или подписчик) о том, что что-то случилось.

   1: <div id="theDiv" onclick="alert('You clicked me')">Click me!</div>

В ExtJs DOM-элементы оборачиваются в Ext.Element, поэтому подписка на тоже событие будет выглядеть так:

   1: Ext.get('theDiv').on('click', function() {alert('You clicked me');});

При разработке сложных пользовательских интерфейсов, отдельные элементы DOMа получают особое назначение. К примеру, банальный div может быть заголовком колонки в таблице (я имею ввиду ExtJs Grid). Следовательно, когда пользователь захочет изменить порядок колонок в гриде и начнет перетягивать колонку за заголовок – в заголовке произойдут некие события (mouseover, mousedown, click, …). Каждый раз отслеживать порядок и детали “низкоуровневых” событий в своем коде рутинно. Поэтому ExtJs поддерживает собственную модель событий. К примеру, GridPanel поддерживает такие события как columnmove, cellclick, headerclick и другие.

Вся магия событий в ExtJs реализована в классе Ext.util.Observable. Чтобы наделить ваш компонент свойствами источника события, вам необходимо “унаследоваться” от Ext.util.Observable.  Если же вы наследуете свой компонент от других компонентов, таких как Panel, Grid, Form, Tree и другие, то дополнительно наследоваться от Ext.util.Observable не обязательно. О принципе паттерна Observable и об особенностях его реализации на javascript можно прочесть на CodeProject.

После того как вы так или иначе унаследовались от Ext.util.Observable, вы можете добавить ваши собственные события примерно таким образом

   1: this.addEvents( 'IAmHappy', 'IAmNotHappy' );

Где, this – это и есть ваш компонент.

Инициировать ваше событие также просто:

   1: this.fireEvent('IAmHappy', this, firstArg, secondArg);

Когда мы вызываем функцию fireEvent, то Observable смотрит, подписывался ли на это событие (в данном случае – ‘IAmHappy’) кто-либо или нет. Если подписывался, то вызывает функцию-обработчик и устанавливает значение переменной this равное текущему объекту (этого мы добились указав this вторым параметром после названия события).

Также в эту функцию будут переданы параметры event и target. Где, event будет объект типа Ext.EventObject, а target – ссылка на HTMLElement. Следом за этими параметрами пойдут наши, собственные параметры firstArg и secondArg, коих может быть любое количество.

   1: function IAmHappyListener(event, target, fristArg, secondArg){
   2: ...
   3: }

Если же Observable не нашел ни одного подписчика, то он, соответственно, ничего и не вызывает.

Простейший способ подписаться на события ExtJs я показал выше, но существуют также некоторые вариации:

Обработчик событий с задержкой (обработчик запуститься через 250 миллисекунд после события)

   1: el.on('click', this.onClick, this, {delay: 250});

Обработчик событий с буферизацией (это означает, обработчик запуститься не чаще, чем раз в 100 миллисекунд и при условии, что событие произошло)

   1: el.on('click', this.onClick, this, {buffer: 100});

Обработчик событий с условием распространения события

   1: // prevent default
   2: el.on('click', this.onClick, this, {preventDefault: true});
   3:  
   4: // only stop propagation
   5: el.on('click', this.onClick, this, {stopPropagation: true});
   6:  
   7: // prevent default and stop propagation
   8: el.on('click', this.onClick, this, {stopEvent: true});

preventDefault и stopPropagation означают тоже самое, что и соответствующие методы родных, джаваскриптовых событий.

Обработчик событий с другими опциями

   1: el.on('click', this.onClick, this, {
   2:     single: true, // удаляет автоматически, после первого запуска
   3:     delegate: 'li.some-class' // автоматическая делегация событий
   4: });

Добавление сразу нескольких обработчиков может выглядеть вот так:

   1: el.on({
   2:     'click' : {
   3:         fn: this.onClick,
   4:     scope: this,
   5:     delay: 100
   6:     }, 
   7:     'mouseover' : {
   8:         fn: this.onMouseOver,
   9:     scope: this
  10:     },
  11:     'mouseout' : {
  12:         fn: this.onMouseOut,
  13:         scope: this
  14:     }
  15: });

Еще стоит упомянуть о такой полезной функции как relayEvents. Она позволяет делегировать события одного компонента – другому компоненту. К примеру, у вас есть панель A, содержащая другую панель B, а та в свою очередь содержит кнопку Save. По нажатию на кнопку Save произойдет ваше собственное событие onSomeSave. К сожалению, ни панель А, ни панель B, обработать это событие не может. Поэтому панели А необходимо генерировать это событие как свое собственное, в надежде, что кто-то сможет его обработать.

clip_image001

“Передать” события панели B в панель A и позволяет relayEvents:

   1: panelA.relayEvents(panelB, ['onSomeSave']);

Фух, что-то длинный пост получился. Устал. А я ведь еще не рассказал об Ext.EventManager, о такой полезной функции как within и о многом другом. Ну чтож, это в другой раз.

Полезные материалы.

Полезные ссылки

Document Object Model Events

Introduction to Events

Tutorial:Events Explained

Tutorial:RelayEvents

Текущий рейтинг: 4.8 (6 голосов)

  • Currently 4,833333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Думаете, вы знаете JavaScript

clock апреля 28, 2009 06:30 by author Подлипенский Павел

Вы бородатый веб разработчик и думаете уже видали всякие чудеса в JavaScript-коде? Хм, чтож тогда следующие задачки для вас. 

1. ++Math.PI
2. (0.1 + 0.2) + 0.3 == 0.1 + (0.2 + 0.3)
3. typeof NaN
4. typeof typeof undefined
5. a = {null:null}; typeof a.null;
6. a = "5"; b = "2"; c = a * b;
7. a = "5"; b = 2; c = a+++b;
8. isNaN(1/null)
9. (16).toString(16)
10. 016 * 2
11. ~null
12. "ab c".match(/\b\w\b/)

Жду ваши варианты в комментариях (просьба не постить по десять одинаковых комментариев, все равно раньше чем я их промодерю они не появятся). До компа я доберусь только завтра, поэтому и ваши комментарии тоже появятся только завтра, а заодно и обновление к этому посту - в виде ответов и объяснений к решениям (да, я их сопру с ваших комментариев, поэтому сначала думайте, а потом пишите!) 

Ответы и решения:

1. 4.141592653589793

С этим надеюсь понятно, в школе все учились.... Я знаю некоторых смутило, что Пи вроде как должно быть константой, но спешу вас разочаровать - в джаваскрипте с константами плохо, а точнее их нет в том понимании, в каком мы видим их, скажем, в C#.

2. false

Такой же ответ получат и Java разработчики, потому как и Java и JavaScript используют IEEE 754 числа с плавающей точкой. Более подробно об операциях с числами с плавающей точкой можно найти тутаньки 

3. "number"

Логического объяснения этому я не нашел, единственное что могу посоветовать, это стараться использовать isNaN вместо typeof SomePotentialNumber, во избежание казусов. 

4. "string" 

Тут все просто - первый оператор typeof вернет тип переменной в виде строки, следовательно второй оператор должен вернуть тип результата первого оператора, т.е. string. 

5. "object"

Мы присвоили переменной а, объект с полем "null", значение которого null, а это в свою очередь, пусть и специфический, но объект. Другими словами мы тут имеем a.null === null.

6. 10

Если в операциях умножение, деление или вычитание один из операторов строка - интерпретатор пытается преобразовать его в число.

7. 7

Порядок выполнения операндов в Javascript  идет слева направо, поэтому мы имеем "а увеличить на 1, а затем сложить с b". 

8. false

С этим тоже, думаю, все понятно. 

9. 10

toString() принимает числовой параметр (необязательный) и toString(16) означает, что число записано в шестнастеричной системе счисления, посему ответ и 10. 

10. 28

016 это восьмеричное представление числа 14 в десятеричной системе счисления. 

11. -1 


12. [ "c" ]

Отдельно стоящий символ в той строке только один - "с", это и ищет указанное регулярное выражение. 

Текущий рейтинг: 5.0 (7 голосов)

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


4 интересных онлайн презентаций для веб-разработчика

clock февраля 25, 2009 17:47 by author Подлипенский Павел

1. Ajax 101 | Workshop
Автор: Bill Scott | This presentation on SlideShare
Введение в программирование с помощью Ajax. Включает XMLHttpRequest, XML, JSON, JavaScript, HTML, CSS, Dom Scripting, Event Handling с небольшими примерами на YUI.


2. Modular CSS
Автор: Russ Weakley | This presentation on Slide Share
Вполне доступно (даже я понял) объясняется механизм построения правильного модульного CSS, что позволяет прятать/показывать отдельные CSS правила для отдельных браузеров, без различного рода уловок и обходных путей.

3. jQuery in 15 minutes
Автор: Simon | This presentation on SlideShare
Небольшое введение в JQuery. Функции, коллекции, работа со значениями и цепочками.

4. JavaScript Library Overview 
Автор Jeresig | This presentation on SlideShare
Интересный обзор популярных JavaScript библиотек (jquery, prototype, Scriptaculous...) для веб-дизайнеров.

Текущий рейтинг: 4.6 (5 голосов)

  • Currently 4,6/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Как не забыть об console.log?

clock февраля 5, 2009 16:05 by author Подлипенский Павел

Одной из моих излюбленных фич в Firebug является console.log. Полагаю, у меня есть единомышленники. И мы (я и мои единомышленники) часто забываем в коде, на продакшин серверах, наши излюбленные console.log. А пользователи, не поставившие себе Firebug, лицезреют некоторые Javascript ошибки... Решением данной проблемы могут быть либо таблетки от склероза (если такие уже придумали) или иммитация console объектов и методов. Выглядит это примерно следующим образом:

if (!window.console || !console.firebug) { var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i) window.console[names[i]] = function() {} }

Этот код можно смело копировать в ваши javacript библиотеки и просто куски кода. Также можно просто сослаться на

<!-- graceful degradation of firebugs console obj --> <script type="text/javascript" src="http://www.getfirebug.com/firebug/firebugx.js"></script>

После чего можно смело писать так

console.error('an error'); console.warn('a warning');  

Или даже так:

console.dir({thanks:'for', reading:'that', cool:function(){ alert('being cool'); }});

P.S.

И все же, если кто-то знает, где можно купить таблетки от склероза - прошу в комментарии.

Полезные ссылки

http://getfirebug.com/console.html

Google Code - Fun with Firebug

Текущий рейтинг: 5.0 (3 голосов)

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


FireUnit: Javascript Unit Testing Extension

clock декабря 19, 2008 09:19 by author Подлипенский Павел

Юнит-тесты это то, на что никогда нет времени. А если есть время, то нет желания. И наконец, если есть время и желание, то обязательно найдется какой-нибудь засранец, который найдет, как забрать твое время и отобьет всякое желание что-либо делать вообще… Да, заказчику тяжело объяснить что такое юнит-тесты и зачем они нужны. Но тем не менее, хочу сделать небольшой обзор нового плагина для Firefox, который позволяет  юнит-тестить ваш джаваскрипт. Если быть совсем точным, то это расширение для Firebug – излюбленного инструмента javascript-разработчиков.

Итак, те кто не  владеет теорией юнит-тестирования идут учить матчасть, а с остальными мы рассмотрим простейшие юнит тесты:
// Простой true/false юнит-тест
fireunit.ok( true, "Тест пройдет успешно!" );
fireunit.ok( false, "Тест будет провален!" );
// Сравниваем две строки и показываем разницу
// если строки отличаются между собой
fireunit.compare(
"Ленивый программист чистит зубной щеткой унитаз.",
"Ленивый программист уронил зубную щетку в унитаз",
"Это одинаковые строки?"
);
// Сравниваем две строки, используя регулярные выражения
fireunit.reCompare(
/Ленивый программист .* унитаз./,
"Ленивый программист уронил зубную щетку в унитаз.",
"Сравниваем две строки, используя регулярные выражения."
);
// Отображаем результаты тестов
fireunit.testDone();

После запуска теста, получаем следующие результаты:

image 

Довольно полезной оказалась фича эмулирования событий браузера:

// FireUnit позволяет эмулировать события браузера
var input = document.getElementsByTagName("input")[0];
fireunit.mouseDown( input );
fireunit.click( input );
fireunit.focus( input );
fireunit.key( input, "a" );

Теперь нет необходимости, сломя голову носится по странице и кликать на все, что кликается или кликалось раньше…

Еще одно удобство, которое не может не тронуть сердце программиста – это разбиение тестов на файлы и запуск тестов батчем(скопом – по русски):

// Запускаем все тесты, расположенные в двух разных файлах
fireunit.runTests("test2.html", "test3.html");
// Эту строку надо положить в конце каждого файла, чтобы тесты 
// в следующем файле запустились. Тесты запускаются последовательно.
fireunit.testDone();

И вот результат:

image

Правда надо сказать о некоторых недороботках в этом плагине. При запуске нескольких тестов из разных файлов, необходимо чтобы эти файлы находились в той же директории, что и файл исполняющий batch-тест. Для запуска тестов у вас должен быть локально развернут Http-сервер. Если вам предыдущее предложение ни о чем не сказало, то смените профессию попробуйте добавить fireunit.forceHttp(), чтобы удостовериться в готовности вашего сервера обработать http-запросы.

if (fireunit.forceHttp())
{
fireunit.runTests( 
"example1.html",
"example2.html" 
);
}

В целом FireUnit довольно удобная в джаваскрипте штука. Пользуйтесь на здоровье.

Полезные ссылки

Примеры использования FireUnit

Блог разработчика

Скачать FireUnit

Текущий рейтинг: 5.0 (3 голосов)

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Быстрые веб-страницы: оптимизируем JQuery

clock ноября 24, 2008 09:20 by author Подлипенский Павел

Начнем с того, что фреймворк JQuery очень быстрая штука. Да, конечно найдутся такие, кто скажет: "Короче, начал юзать джэйквери и у меня все повисло. Ну, я типа решил, что надо писать все самому...". Что ж, идиотов всегда хватало и мы не будем их переубеждать. Тем не менее, существуют некоторые практики и советы по использованию этого мощного (в руках homosapiens) инструмента.

Используйте ID, вместо классов для выборки элемента. Если у вас большой дом(не путать с дорогущим сооружением по соседству), то выборка $(.one-element') приведет к просмотру всего дерева для поиска этого элемента. Помогите ему и себе, предоставьте как можно больше информации о месторасположении объекта: ('.block1 > .block2 > .block3 …), укажите стартовую точку для поиска $('.foo', startObject) или используйте выборку по айдишнику $('#block45').

Читайте подробнее и на английском:

http://www.learningjquery.com/2006/12/quick-tip-optimizing-dom-traversal

http://blog.multitweet.com/2007/09/13/jquery-performance/

http://www.componenthouse.com/article-19

https://www.adaptavist.com/display/%7Egfraser/2008/01/12/Some+quick+tips+for+jQuery+performance

Иногда filter работает быстрее, чем find.

Читайте подробнее и на английском:

http://groups.google.com/group/jquery-en/browse_thread/thread/533451087251c952/9bb31c108c089c4f

http://www.learningjquery.com/2006/12/how-to-get-anything-you-want-part-2

Естественно это зависит от браузера, но объединение нескольких строк в одну таким способом: string1 = string2 + string3 может работать медленнее, чем если бы вы создали массив строк, а затем сделали join. В редких случаях имеет смысл использовать и третье решение - конкатенацию строк.

js-compare

Читайте подробнее и на английском:

http://www.nabble.com/document.write-and-DOm-creation---performance-optimization--td18390436s27240.html

http://www.sitepen.com/blog/2008/06/09/string-performance-getting-good-performance-from-internet-explorer/

Для тех, кто еще не в курсе - javascript это не многопоточный язык. Всю правду, с откровенными фотографиями и отпечатками пальцев можно найти здесь. Также рекомендую почитать о способах иммитации многопоточности в джаваскрипте. Все это означает только одно - пока вы добавляете новые элементы в дом, браузер не сможет их отобразить. Поэтому, стоит разбивать операции вставки новых элементов на небольшие группы, давая браузеру отрисовывать их в промежутках между вставками. Сделать это можно с помощью банального setTimeout.

Недавно открыл для себя, что iterators в джаваскрипте работают медленее, чем generators при больших объемах данных. Будьте бдительны, товарищи!

Старайтесь кэшировать элементы и их коллекции, где это только возможно

   1: var myCachedObjects = $(".find-me");
   2: var anotherObjects = myCachedObjects.filter(".another-object");
   3: var favouriteObjects = myCachedObjects.filter(".favourite-object");

Ухх, за эти выходные мое javascript-мировоззрение перевернулось: xml парсится в четыре раза медленнее, чем json, if(isTrue) работает быстрее, чем if(isTrue == true) и многое другое. Не хочу превращать этот пост в энциклопедию, поэтому добро пожаловать в полезные ссылки.

Полезные ссылки

jQuery: Performance analysis of selectors

IE + JavaScript Performance Recommendations

Evaluate Low Level JavaScript Performance Characteristics

Some more JavaScript performance tips

Текущий рейтинг: 4.9 (7 голосов)

  • Currently 4,857143/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


How To: Вызвать Javascript функцию после обновления UpdatePanel

clock апреля 7, 2008 16:45 by author paul

UpdatePanel - это контрол Microsoft ASP.NET AJAX, который позволяет довольно удобно интегрировать AJAX в ваше приложение. Но именно ввиду его удобства и простоты использования со стороны разработчика, некоторые вещи далеко не очевидны. К примеру как вызвать клиентский JavaScript по завершению очередного обновления этой панели?

Трюк заключается в том, чтобы добавить EndRequestHandler в request manager:

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);

Вот пример формы с двумя TextBox, куда вы вводите текст, а сервер возвращает длину текста и отображает ее во втором TextBox:

<%@ page language="C#" autoeventwireup="true" codebehind="DemoJScriptUpdate.aspx.cs" inherits="CharterWeb.DemoJScriptUpdate" %>
 
 <script runat
="server">
 protected void txtDataOnChange(object sender, EventArgs e) {
 txtLength.Text = txtData.Text.Length.ToString();
 }
 </script>
 <html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>">
 <head id="Head1" runat
="server">
 
 
 <script type="text/javascript">
 function EndRequestHandler(sender, args) {
 if (args.get_error() == undefined)
 alert("Your text has: " + document.getElementById("txtLength").value + " character(s)");
 else
 alert("There was an error" + args.get_error().message);
 }
 function load() {
 Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
 }
 </script>
 
 <form id="form1" runat
="server">
 <?xml:namespace prefix ="" asp /></asp:scriptmanager id="_scriptManager" runat="server">
 
 <asp:updatepanel id="UpdatePanel1" runat
="server">
 <contenttemplate>
 Write something: </asp:textbox id="txtData" runat="server" autopostback="true" ontextchanged="txtDataOnChange">
 <br />
 Server says the length is: </asp:textbox id="txtLength" runat="server" autopostback="true">
 </contenttemplate>
 </asp:updatepanel>
 
 </form> 

Текущий рейтинг: 4.9 (7 голосов)

  • Currently 4,857143/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Search


LinkedIn Profile

Tags

Posts

  • http://tvsh2004.narod.ru/gm03.html
    test

  • конечно это очень дорого, у нас ведь вся страна пользуется только лицензионной windows...
    Славян

  • Алексей: С удовольствием!
    Подлипенский Павел

  • Присоединяйтесь к ЖЖ-коммьюнити http://community.livejournal.com/ua_extjs
    Алексей

  • Поправка насчет генерации самого хтмл-кода для ответа веб метода. Предлагаю сделать проще, не создавая объекта страницы и без тега <form> [WebMethod] public string GetControlHTML(string controlLocation) { HtmlTextWriter tw = new HtmlTextWriter(new StringWriter()); var uc = (UserControl)(new UserControl()).LoadControl(controlLocation); uc.RenderControl(tw); return tw.InnerWriter.ToString(); }
    Anthony

  • @r-jay там же еще ++
    Dima Pasko

Categories

Calendar

<<  Март 2010  >>
воповтсрчепясу
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Archive

© Copyright 2010

Sign in

Ó÷àñòíèê ïëàíåòû Developers.org.ua

Bookmark and Share

Web Developement Blogs - Blog Catalog Blog Directory