Если вы только начинаете использовать Ext или хотите узнать побольше о этой библиотеке – значит вы попали туда, куда нужно. В этом руководстве мы рассмотрим основные понятия Ext и создадим работающую динамическую страницу. Предполагается, что читатель уже знаком с основами Javascript и имеет некоторый опыт работы с этим языком программирования, а также знает основы HTML и DOM (объектной модели документа).
Для скачайте самую последнюю версию Ext, которую всегда можно найти по адресу http://extjs.com/download.
Существует несколько вариантов загрузки Ext, но начать лучше с последней стабильной версии. После того, как вы скачали и распаковали файл, начните изучение с директории examples, где находятся примеры.
Для начала давайте рассмотрим несколько наиболее типовых задач, выполняемых при помощи Javascript и то, как они решаются при помощи Ext. Сразу скачайте архив с примером приложения, которое мы создаем в этом руководстве – IntroToExt.zip. Архив содержит 3 файла: ExtStart.html, ExtStart.js и ExtStart.css. Распакуйте эти файлы в подпапку в папке куда у вас установлен Ext (например, если вы установили Ext в “C:\code\Ext\v1.0,” создайте в папке “v1.0″ подпапку “tutorial”). Откройте ExtStart.html в браузере, два раза кликнув по нему. Появится окошко с сообщением, что все установлено и настроено правильно. Если вместо окошка с подтверждением появится сообщение об ошибке, следуйте инструкциям на открывшейся странице, чтобы исправить ее.
Теперь, откройте файл ExtStart.js в вашем любимом редакторе. Вот что вы там увидите:
Ext.onReady будет самым первым методом, который вы будете использовать на своих страницах. Этот метод автоматически вызывается, когда полностью загружена в память DOM страницы гарантируя, что все элементы к которым вы можете захотеть обратиться будут уже загружены в память к моменту запуска скрипта. Теперь вы можете удалить строку с командой alert(), так-как далее на ее место мы добавим код, делающий что-нибудь полезное.
Объект Element: сердце Ext
Практически все задачи, что вы решаете при помощи Javascript требуют обращения к отдельным элементам страницы, чтобы иметь возможность что-то с ними сделать. Обычно в Javascript отдельный DOM-узел выбирался по id следующим образом:
Такой подход неплохо работает - проблема в том, что возвращаемый объект (узел DOM) не очень удобен в работе. Чтобы сделать с ним что-то полезное приходится писать кучу дополнительного кода. Кроме того, приходится самостоятельно обрабатывать различия между разными браузерами, что довольно утомительно.
И тут на помощь приходит объект Ext.Element. Element является «сердцем» Ext, и большинство задач, которые вы будете решать предполагает работу с Element-ами. Весь Ext построен на базе Element, и если у вас есть время на то, чтобы как следует разобраться только с одним классом в Ext – пусть это будет класс Element.
Чтобы получить Ext Elemet по его id используйте следующий код (в странице ExtStart.html есть div с id «myDiv», так-что давайте добавим в ExtStart.js следующий код):
Вернемся к объекту Element – чем-же он нам полезен?
Это значит, что множество полезных вещей делаются просто и с минимумом кодирования. Вот несколько простых примеров (полный список вы найдете в документации по API Element). Попробуйте подобавлять эти примеры в ExtStart.js после строки, в которой мы создали переменную myDiv:
В некоторых случаях выбирать узлы DOM по id бывает неудобно или невозможно. Может быть id у элемента отсутствует или вы его не знаете, или вам надо выбрать сразу несколько элементов. Иногда вам может потребоваться выбрать элементы не по id, а на основании какого-то другого признака, например атрибута или класса CSS. Для этих задач в Ext существует библиотека DomQuery для выборок DOM-узлов.
DomQuery можно использовать отдельно, но обычно она используется вместе с Ext. Вы будете использовать ее для выборки элементов чтобы можно было работать с ними как с объектами Element. К счастью, объект Element содержит метод Element.select() для выборки при помощи библиотеки DomQuery. Например в файле ExtStart.html есть несколько параграфов (тегов <p>) у которых нет id. Если вам надо выбрать все параграфы и выполнить со всеми ними некоторые действия, вы можете сделать что-то вроде этого:
Этот пример показывает очень удобную особенность Element.select – он возвращает CompositeElement, который предоставляет доступ ко всем выбранным Element-ам как к единому объекту Element. Это позволяет удобно работать с выбранными элементами без необходимости обращения к каждому из них в цикле.
Библиотека DomQuery поддерживает массу способов выборки, включая большинство селекторов из стандарта W3C CSS3 DOM, основные Xpath запросы, атрибуты HTML и много другого. Детальное описание вы можете посмотреть в API-документации DomQuery.
Пока весь код в примерах мы помещали внутрь функции onReady, и значит код исполнялся сразу после загрузки страницы. Это заметно уменьшает нашу возможность влиять на события – зачастую нужно, чтобы код выполнялся в результате действий пользователя, или наступления какого-то события. Для решения этой задачи нужно создать обработчики событий, которые будут вызывать некие функции при наступлении этих событий.
Вот простой пример. Откройте файл ExtStart.js и поместите в него следующий код:
Этот код будет исполнен после загрузки страницы, но есть одна особенность. Хотя функция, вызывающая alert() и определена, она будет вызвана только после нажатия на кнопку, т.к. Она назначена обработчиком событию «click» для кнопки. Если перевести этот код на русский, он будет звучать следующим образом: «Взять элемент с id ‘myButton’ и назначить для него функцию, которая будет вызываться каждый раз при клике на этот элемент».
Неудивительно, что Element.select позволяет делать то-же с целой группой элементов. Например, если мы хотим чтобы сообщение показывалось при клике на любом параграфе, мы делаем следующее:
В этих примерах мы создавали функцию-обработчик сразу, без присвоения ей имени функции. Такие функции называются «анонимными функциями», т.к. у них отсутствует имя функции. Помимо этого вы можете назначить обработчиком уже имеющуюся, обладающую именем, функцию. Это полезно, когда вы хотите использовать одну и ту-же функцию для обработки нескольких разных событий. Этот пример делает то-же самое, что и предыдущий:
Пока мы исполняли в обработчике простые действия, но как нам узнать, какой конкретно элемент вызвал событие? На самом деле это очень просто – метод Element.on принимает три очень полезных параметра для обработчика событий (здесь мы рассмотрим только первый из них, об остальных вы можете узнать из документации). В предыдущих примерах мы просто игнорировали эти дополнительные параметры, но немного исправив код мы получим дополнительную функциональность. Первый, и наиболее важный параметр – это само произошедшее событие. На самом деле это объект Event, кроссбраузерный и предоставляющий больше информации чем стандартный. Например узел DOM на котором произошло событие может быть получен путем небольшого изменения кода:
Обратите внимание, что target – это DOM-узел, поэтому сначала мы должны получить соответствующий объект Element и уже на нем производить действия. В нашем случае мы по клику подсвечиваем параграф.
В дополнение к основным библиотекам, рассмотренным выше, в Ext содержит один из богатейших на сегодняшний день набор виджетов и компонентов интерфейса. Мы не сможем рассмотреть их все здесь, поэтому давайте остановимся на нескольких наиболее используемых.
Вместо того, чтобы создавать диалог с поднадоевшей надписью «Hello world», поступим хитрее. В прошлом примере мы уже написали код, подсвечивающий параграф, по клику на нем. Давайте сделаем так, чтобы текст параграфа по которому кликнули выводился в окне сообщения. Замените в функции paragraphClicked строку:
на:
Здесь мы использовали несколько новых вещей, давайте рассмотрим их поподробнее. В первой строке мы создаем локальную переменную paragraph которая содержит ссылку на Element, представляющий DOM-узел по которому кликнул пользователь (в этом примере это всегда параграф, так как мы связали обработчик событий только с тегами <p>). Зачем мы создали переменную? Нам понадобится Element чтобы подсветить его, а потом мы используем его-же в качестве одного из параметров окна сообщения. Вообще вызывать одну и ту-же функцию несколько раз чтобы получить одно и то-же значение или ссылку на объект непрактично и считается дурным тоном. Поэтому мы как хорошие ООП-разработчики используем локальную переменную.
Теперь перейдем к самому вызову объекта MessageBox, в котором есть еще несколько новых для нас понятий. На первый взгляд это выглядит как простая передача списка параметров методу, но если присмотреться, сам синтаксис довольно необычен. В данном случае в MessageBox.show() передается только один параметр: объект (object literal), содержащий набор свойств и их значений. В Javascript это динамический объект, создаваемый путем использования фигурных скобок { и } и списка свойство-значение между ними в формате [название свойства]:[значение свойства]. Такая запись активно используется в Ext, поэтому хорошо запомните ее.
Зачем использовать объект? Прежде всего из-за гибкости такого подхода. Объекту можно всегда добавить или убрать свойства, их можно писать в произвольном порядке в отличии параметров метода, порядок и тип которых не должен меняться. Это сильно упрощает жизнь разработчику, особенно при работе с методами, у которых масса необязательных параметров (как в случае с MessageBox.show). Например, представим что метод foo.action принимает четыре параметра, а мы хотим передать только один из них. В этом случае вам может понадобиться написать что-то вроде foo.action(null, null, null, ‘hello’). Однако,если метод принимает объект, этот же код превратится в foo.action({ param4: ‘hello’ }). Гораздо проще в использовании и значительно надежнее.
Грид – это один из самых популярных Ext-виджетов, и зачастую люди начинают именно с него. Давайте посмотрим как нам построить простейший грид. Замените весь имеющийся в код ExtStart.js на:
Выглядит сложновато, но на самом деле здесь всего семь строчек кода! В первой строке создается массив данных, которые будут отображаться в гриде. В реальных проектах вы скорее всего будете брать эти данные динамически, например из базы данных или веб-сервиса. Следующим шагом мы инициализируем хранилище данных, которое отвечает за чтение и форматирование данных. Потом мы создаем схему столбцов, которая позволяет сконфигурировать каждую из колонок грида. И наконец мы создаем сам виджет, передавая ему хранилище данных и схему столбцов, отображаем ее и выделяем первую строчку. Ну как, ничего сложного?
Конечно, сейчас вы вероятно не полностью разобрались в приведенном коде (например, что это за хреновина – MemoryProxy?). Цель этого примера – показать как можно быстро и просто создать сложный элемент интерфейса с богатыми возможностями всего несколькими строками кода. Детали вы можете узнать прочитав и просмотрев другие описания или документацию по API гридов.
На самом деле к настоящему моменту мы видели только верхушку айсберга. В Ext есть множество других полезных компонентов интерфейса и виджетов – автоматическая разбивка страницы, вкладки, меню, панели инструментов, диалоги, «деревья» и многие другие. Смотрите раздел с примерами в документации чтобы познакомиться с полным списком доступных виджетов.
Теперь, когда мы создали страницу, и поработали с ней при помощи Javascript, пора разобраться с тем, как получать данные с удаленного сервера, что обычно означает загрузку и сохранение информации в базу данных. Подход, при котором такое взаимодействие происходит асинхронно и при помощи Javascript обычно называют Ajax, и в Ext встроена прекрасная поддержка этой технологии. Например, типичная задача заключается в обеспечении взаимодействия с пользователем – отправки введенных данных на сервер и обновлении какого-то элемента интерфейса в ответ на его действия. Вот пример простой HTML-формы с одним полем для ввода данных и кнопкой, и div который мы используем для отображения ответа сервера (Обратите внимание – вы можете добавить этот html-код в ExtStart.html, но вам нужен веб-сервер для того, чтобы разместить на нем серверную часть скрипта):
Теперь давайте добавим Javascript-программу, которая будет брать введенные данные и отправлять их на сервер (замените весь код в ExtStart.js на следующий):
Структура кода вам должна быть уже знакома. Мы создаем объект класса Element из кнопки okButton и «подвешиваем» анонимную функцию как обработчик на клик по этой кнопке. Внутри обработчика мы используем специальный класс Ext – UpdateManager, который значительно упрощает задачу отправки Ajax запроса на сервер, получения ответа и обновления элемента. Можно использовать UpdateManager напрямую или, как в этом примере вызывая соответствующий метод Element.load того Element-а который мы хотим обновить (в данном случае это div с id ‘msg’). При использовании Element.load ответ пришедший от сервера автоматически заменяет innerHTML элемента. Просто передадим ему URL программы на сервере, которая обработает наш запрос, параметры, передаваемые этому процессу (в нашем случае – это значение, введенное в поле ‘name’) и текст, который будет отображаться как innerHTML элемента, пока запрос обрабатывается. И наконец делаем div ‘msg’ видимым (т.к. он по-умолчанию скрыт) и готово! Конечно, UpdateManager как и многие другие компоненты Ext обладает гораздо большим числом возможностей и может по-разному работать с Ajax-запросами, но цель данного примера – показать как можно быстро и просто послать и обработать Ajax-запрос.
Последняя часть нашего Ajax-приложения – это программа на веб-сервере, которая обрабатывает полученный запрос и возвращает ответ. Это может быть страница со скриптом, сервлет, HTTP-обработчик, веб-сервис или просто CGI или Perl-скрипт – все что угодно, что может обрабатывать HTTP-запросы на сервере. К сожалению из-за большого числа вариантов нет возможности привести какой-то один «стандартный» пример. Вот несколько примеров на широко используемых языках, которые помогут вам понять принцип (код попросту выводит содержимое поля ‘name’, полученное им от клиента добавляя в начало строку ‘From Server: ‘ и она отображается внутри div-а ‘msg’):
В реальной жизни работа с Ajax включает написание кода, который читает и обрабатывает данные, полученные от сервера. Есть несколько самых распространенных форматов обмена данными, такие как JSON и XML. Также существует множество серверных библиотек, которые помогут проще работать с Ajax-запросами. Все они совместимы с Ext, т.к. Ext не предъявляет никаких специфических требований к северным библиотекам. Ext все равно, что происходит на сервере, если результат обработки отдается в корректном формате!
Скачиваем Ext
Для скачайте самую последнюю версию Ext, которую всегда можно найти по адресу http://extjs.com/download.
Существует несколько вариантов загрузки Ext, но начать лучше с последней стабильной версии. После того, как вы скачали и распаковали файл, начните изучение с директории examples, где находятся примеры.
Начинаем работу!
Для начала давайте рассмотрим несколько наиболее типовых задач, выполняемых при помощи Javascript и то, как они решаются при помощи Ext. Сразу скачайте архив с примером приложения, которое мы создаем в этом руководстве – IntroToExt.zip. Архив содержит 3 файла: ExtStart.html, ExtStart.js и ExtStart.css. Распакуйте эти файлы в подпапку в папке куда у вас установлен Ext (например, если вы установили Ext в “C:\code\Ext\v1.0,” создайте в папке “v1.0″ подпапку “tutorial”). Откройте ExtStart.html в браузере, два раза кликнув по нему. Появится окошко с сообщением, что все установлено и настроено правильно. Если вместо окошка с подтверждением появится сообщение об ошибке, следуйте инструкциям на открывшейся странице, чтобы исправить ее.
Теперь, откройте файл ExtStart.js в вашем любимом редакторе. Вот что вы там увидите:
Ext.onReady(function() { alert("Congratulations! You have Ext configured correctly!"); });
Ext.onReady будет самым первым методом, который вы будете использовать на своих страницах. Этот метод автоматически вызывается, когда полностью загружена в память DOM страницы гарантируя, что все элементы к которым вы можете захотеть обратиться будут уже загружены в память к моменту запуска скрипта. Теперь вы можете удалить строку с командой alert(), так-как далее на ее место мы добавим код, делающий что-нибудь полезное.
Объект Element: сердце Ext
Практически все задачи, что вы решаете при помощи Javascript требуют обращения к отдельным элементам страницы, чтобы иметь возможность что-то с ними сделать. Обычно в Javascript отдельный DOM-узел выбирался по id следующим образом:
var myDiv = document.getElementById('myDiv');
Такой подход неплохо работает - проблема в том, что возвращаемый объект (узел DOM) не очень удобен в работе. Чтобы сделать с ним что-то полезное приходится писать кучу дополнительного кода. Кроме того, приходится самостоятельно обрабатывать различия между разными браузерами, что довольно утомительно.
И тут на помощь приходит объект Ext.Element. Element является «сердцем» Ext, и большинство задач, которые вы будете решать предполагает работу с Element-ами. Весь Ext построен на базе Element, и если у вас есть время на то, чтобы как следует разобраться только с одним классом в Ext – пусть это будет класс Element.
Чтобы получить Ext Elemet по его id используйте следующий код (в странице ExtStart.html есть div с id «myDiv», так-что давайте добавим в ExtStart.js следующий код):
Ext.onReady(function() { var myDiv = Ext.get('myDiv'); });
Вернемся к объекту Element – чем-же он нам полезен?
- Element предоставляет обертки для большинства DOM методов и свойств, которые вам могут понадобиться в работе. Это дает нам удобный, унифицированный и кросс-браузерный DOM-интерфейс (кроме того вы всегда можете обратиться к DOM-элементу напрямую, используя Element.dom)
- Метод Element.get() использует кеширование, поэтому множественные обращения к одному и тому-же элементу происходят очень быстро
- Для наиболее часто используемые действия, производимых над DOM-элементами у Element созданы простые кросс-браузерные методы (добавление/удаление классов CSS, добавление/удаление обработчиков событий, позиционирование, изменение размера, анимация, перетаскивание и т.д.)
Это значит, что множество полезных вещей делаются просто и с минимумом кодирования. Вот несколько простых примеров (полный список вы найдете в документации по API Element). Попробуйте подобавлять эти примеры в ExtStart.js после строки, в которой мы создали переменную myDiv:
myDiv.highlight(); // Заливка элемента станет желтой, а потом постепенно вернется к первоначальному цвету myDiv.addClass('red'); // Добавляем CSS-класс (предопределенный в ExtStart.css) myDiv.center(); // Ставим элемент по центру страницы myDiv.setOpacity(.25); // Делаем элемент полупрозрачным
Выборка узлов DOM
В некоторых случаях выбирать узлы DOM по id бывает неудобно или невозможно. Может быть id у элемента отсутствует или вы его не знаете, или вам надо выбрать сразу несколько элементов. Иногда вам может потребоваться выбрать элементы не по id, а на основании какого-то другого признака, например атрибута или класса CSS. Для этих задач в Ext существует библиотека DomQuery для выборок DOM-узлов.
DomQuery можно использовать отдельно, но обычно она используется вместе с Ext. Вы будете использовать ее для выборки элементов чтобы можно было работать с ними как с объектами Element. К счастью, объект Element содержит метод Element.select() для выборки при помощи библиотеки DomQuery. Например в файле ExtStart.html есть несколько параграфов (тегов <p>) у которых нет id. Если вам надо выбрать все параграфы и выполнить со всеми ними некоторые действия, вы можете сделать что-то вроде этого:
// Подсвечивает все параграфы Ext.select('p').highlight();
Этот пример показывает очень удобную особенность Element.select – он возвращает CompositeElement, который предоставляет доступ ко всем выбранным Element-ам как к единому объекту Element. Это позволяет удобно работать с выбранными элементами без необходимости обращения к каждому из них в цикле.
Библиотека DomQuery поддерживает массу способов выборки, включая большинство селекторов из стандарта W3C CSS3 DOM, основные Xpath запросы, атрибуты HTML и много другого. Детальное описание вы можете посмотреть в API-документации DomQuery.
Реакция на события
Пока весь код в примерах мы помещали внутрь функции onReady, и значит код исполнялся сразу после загрузки страницы. Это заметно уменьшает нашу возможность влиять на события – зачастую нужно, чтобы код выполнялся в результате действий пользователя, или наступления какого-то события. Для решения этой задачи нужно создать обработчики событий, которые будут вызывать некие функции при наступлении этих событий.
Вот простой пример. Откройте файл ExtStart.js и поместите в него следующий код:
Ext.onReady(function() { Ext.get('myButton').on('click', function(){ alert("You clicked the button"); }); });
Этот код будет исполнен после загрузки страницы, но есть одна особенность. Хотя функция, вызывающая alert() и определена, она будет вызвана только после нажатия на кнопку, т.к. Она назначена обработчиком событию «click» для кнопки. Если перевести этот код на русский, он будет звучать следующим образом: «Взять элемент с id ‘myButton’ и назначить для него функцию, которая будет вызываться каждый раз при клике на этот элемент».
Неудивительно, что Element.select позволяет делать то-же с целой группой элементов. Например, если мы хотим чтобы сообщение показывалось при клике на любом параграфе, мы делаем следующее:
Ext.onReady(function() { Ext.select('p').on('click', function() { alert("You clicked a paragraph"); }); });
В этих примерах мы создавали функцию-обработчик сразу, без присвоения ей имени функции. Такие функции называются «анонимными функциями», т.к. у них отсутствует имя функции. Помимо этого вы можете назначить обработчиком уже имеющуюся, обладающую именем, функцию. Это полезно, когда вы хотите использовать одну и ту-же функцию для обработки нескольких разных событий. Этот пример делает то-же самое, что и предыдущий:
Ext.onReady(function() { var paragraphClicked = function() { alert("You clicked a paragraph"); } Ext.select('p').on('click', paragraphClicked); });
Пока мы исполняли в обработчике простые действия, но как нам узнать, какой конкретно элемент вызвал событие? На самом деле это очень просто – метод Element.on принимает три очень полезных параметра для обработчика событий (здесь мы рассмотрим только первый из них, об остальных вы можете узнать из документации). В предыдущих примерах мы просто игнорировали эти дополнительные параметры, но немного исправив код мы получим дополнительную функциональность. Первый, и наиболее важный параметр – это само произошедшее событие. На самом деле это объект Event, кроссбраузерный и предоставляющий больше информации чем стандартный. Например узел DOM на котором произошло событие может быть получен путем небольшого изменения кода:
Ext.onReady(function() { var paragraphClicked = function(e) { Ext.get(e.target).highlight(); } Ext.select('p').on('click', paragraphClicked); });
Обратите внимание, что target – это DOM-узел, поэтому сначала мы должны получить соответствующий объект Element и уже на нем производить действия. В нашем случае мы по клику подсвечиваем параграф.
Использование виджетов
В дополнение к основным библиотекам, рассмотренным выше, в Ext содержит один из богатейших на сегодняшний день набор виджетов и компонентов интерфейса. Мы не сможем рассмотреть их все здесь, поэтому давайте остановимся на нескольких наиболее используемых.
Окно сообщения
Вместо того, чтобы создавать диалог с поднадоевшей надписью «Hello world», поступим хитрее. В прошлом примере мы уже написали код, подсвечивающий параграф, по клику на нем. Давайте сделаем так, чтобы текст параграфа по которому кликнули выводился в окне сообщения. Замените в функции paragraphClicked строку:
Ext.get(e.target).highlight();
на:
var paragraph = Ext.get(e.target); paragraph.highlight(); Ext.MessageBox.show({ title: 'Paragraph Clicked', msg: paragraph.dom.innerHTML, width:400, buttons: Ext.MessageBox.OK, animEl: paragraph });
Здесь мы использовали несколько новых вещей, давайте рассмотрим их поподробнее. В первой строке мы создаем локальную переменную paragraph которая содержит ссылку на Element, представляющий DOM-узел по которому кликнул пользователь (в этом примере это всегда параграф, так как мы связали обработчик событий только с тегами <p>). Зачем мы создали переменную? Нам понадобится Element чтобы подсветить его, а потом мы используем его-же в качестве одного из параметров окна сообщения. Вообще вызывать одну и ту-же функцию несколько раз чтобы получить одно и то-же значение или ссылку на объект непрактично и считается дурным тоном. Поэтому мы как хорошие ООП-разработчики используем локальную переменную.
Теперь перейдем к самому вызову объекта MessageBox, в котором есть еще несколько новых для нас понятий. На первый взгляд это выглядит как простая передача списка параметров методу, но если присмотреться, сам синтаксис довольно необычен. В данном случае в MessageBox.show() передается только один параметр: объект (object literal), содержащий набор свойств и их значений. В Javascript это динамический объект, создаваемый путем использования фигурных скобок { и } и списка свойство-значение между ними в формате [название свойства]:[значение свойства]. Такая запись активно используется в Ext, поэтому хорошо запомните ее.
Зачем использовать объект? Прежде всего из-за гибкости такого подхода. Объекту можно всегда добавить или убрать свойства, их можно писать в произвольном порядке в отличии параметров метода, порядок и тип которых не должен меняться. Это сильно упрощает жизнь разработчику, особенно при работе с методами, у которых масса необязательных параметров (как в случае с MessageBox.show). Например, представим что метод foo.action принимает четыре параметра, а мы хотим передать только один из них. В этом случае вам может понадобиться написать что-то вроде foo.action(null, null, null, ‘hello’). Однако,если метод принимает объект, этот же код превратится в foo.action({ param4: ‘hello’ }). Гораздо проще в использовании и значительно надежнее.
Гриды
Грид – это один из самых популярных Ext-виджетов, и зачастую люди начинают именно с него. Давайте посмотрим как нам построить простейший грид. Замените весь имеющийся в код ExtStart.js на:
Ext.onReady(function() { var myData = [ ['Apple',29.89,0.24,0.81,'9/1 12:00am'], ['Ext',83.81,0.28,0.34,'9/12 12:00am'], ['Google',71.72,0.02,0.03,'10/1 12:00am'], ['Microsoft',52.55,0.01,0.02,'7/4 12:00am'], ['Yahoo!',29.01,0.42,1.47,'5/22 12:00am'] ]; var ds = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(myData), reader: new Ext.data.ArrayReader({id: 0}, [ {name: 'company'}, {name: 'price', type: 'float'}, {name: 'change', type: 'float'}, {name: 'pctChange', type: 'float'}, {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'} ]) }); ds.load(); var colModel = new Ext.grid.ColumnModel([ {header: "Company", width: 120, sortable: true, dataIndex: 'company'}, {header: "Price", width: 90, sortable: true, dataIndex: 'price'}, {header: "Change", width: 90, sortable: true, dataIndex: 'change'}, {header: "% Change", width: 90, sortable: true, dataIndex: 'pctChange'}, {header: "Last Updated", width: 120, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'} ]); var grid = new Ext.grid.Grid('grid-example', {ds: ds, cm: colModel}); grid.render(); grid.getSelectionModel().selectFirstRow(); });
Выглядит сложновато, но на самом деле здесь всего семь строчек кода! В первой строке создается массив данных, которые будут отображаться в гриде. В реальных проектах вы скорее всего будете брать эти данные динамически, например из базы данных или веб-сервиса. Следующим шагом мы инициализируем хранилище данных, которое отвечает за чтение и форматирование данных. Потом мы создаем схему столбцов, которая позволяет сконфигурировать каждую из колонок грида. И наконец мы создаем сам виджет, передавая ему хранилище данных и схему столбцов, отображаем ее и выделяем первую строчку. Ну как, ничего сложного?
Конечно, сейчас вы вероятно не полностью разобрались в приведенном коде (например, что это за хреновина – MemoryProxy?). Цель этого примера – показать как можно быстро и просто создать сложный элемент интерфейса с богатыми возможностями всего несколькими строками кода. Детали вы можете узнать прочитав и просмотрев другие описания или документацию по API гридов.
И еще много всего…
На самом деле к настоящему моменту мы видели только верхушку айсберга. В Ext есть множество других полезных компонентов интерфейса и виджетов – автоматическая разбивка страницы, вкладки, меню, панели инструментов, диалоги, «деревья» и многие другие. Смотрите раздел с примерами в документации чтобы познакомиться с полным списком доступных виджетов.
Использование Ajax
Теперь, когда мы создали страницу, и поработали с ней при помощи Javascript, пора разобраться с тем, как получать данные с удаленного сервера, что обычно означает загрузку и сохранение информации в базу данных. Подход, при котором такое взаимодействие происходит асинхронно и при помощи Javascript обычно называют Ajax, и в Ext встроена прекрасная поддержка этой технологии. Например, типичная задача заключается в обеспечении взаимодействия с пользователем – отправки введенных данных на сервер и обновлении какого-то элемента интерфейса в ответ на его действия. Вот пример простой HTML-формы с одним полем для ввода данных и кнопкой, и div который мы используем для отображения ответа сервера (Обратите внимание – вы можете добавить этот html-код в ExtStart.html, но вам нужен веб-сервер для того, чтобы разместить на нем серверную часть скрипта):
<div id="msg" style="visibility: hidden"</div
Name: <input type="text" id="name" /><br />
<input type="button" id="okButton" value="OK" />
Теперь давайте добавим Javascript-программу, которая будет брать введенные данные и отправлять их на сервер (замените весь код в ExtStart.js на следующий):
Ext.onReady(function(){ Ext.get('okButton').on('click', function(){ var msg = Ext.get("msg"); msg.load({ url: [server url], // <-- замените на ваш url params: "name=" + Ext.get('name').dom.value, text: "Updating..." }); msg.show(); }); });
Структура кода вам должна быть уже знакома. Мы создаем объект класса Element из кнопки okButton и «подвешиваем» анонимную функцию как обработчик на клик по этой кнопке. Внутри обработчика мы используем специальный класс Ext – UpdateManager, который значительно упрощает задачу отправки Ajax запроса на сервер, получения ответа и обновления элемента. Можно использовать UpdateManager напрямую или, как в этом примере вызывая соответствующий метод Element.load того Element-а который мы хотим обновить (в данном случае это div с id ‘msg’). При использовании Element.load ответ пришедший от сервера автоматически заменяет innerHTML элемента. Просто передадим ему URL программы на сервере, которая обработает наш запрос, параметры, передаваемые этому процессу (в нашем случае – это значение, введенное в поле ‘name’) и текст, который будет отображаться как innerHTML элемента, пока запрос обрабатывается. И наконец делаем div ‘msg’ видимым (т.к. он по-умолчанию скрыт) и готово! Конечно, UpdateManager как и многие другие компоненты Ext обладает гораздо большим числом возможностей и может по-разному работать с Ajax-запросами, но цель данного примера – показать как можно быстро и просто послать и обработать Ajax-запрос.
Последняя часть нашего Ajax-приложения – это программа на веб-сервере, которая обрабатывает полученный запрос и возвращает ответ. Это может быть страница со скриптом, сервлет, HTTP-обработчик, веб-сервис или просто CGI или Perl-скрипт – все что угодно, что может обрабатывать HTTP-запросы на сервере. К сожалению из-за большого числа вариантов нет возможности привести какой-то один «стандартный» пример. Вот несколько примеров на широко используемых языках, которые помогут вам понять принцип (код попросту выводит содержимое поля ‘name’, полученное им от клиента добавляя в начало строку ‘From Server: ‘ и она отображается внутри div-а ‘msg’):
PHP
<?php if(isset($_POST['name'])) { echo 'From Server: '.$_POST['name']; } ?>
ASP.Net
protected void Page_Load(object sender, EventArgs e) { if (Request.Form["name"] != null) { Response.Write("From Server: " + Request.Form["name"]); Response.End(); } }
Cold Fusion
<cfif StructKeyExists(form, "name")> <cfoutput>From Server: #form.name#</cfoutput> </cfif>
В реальной жизни работа с Ajax включает написание кода, который читает и обрабатывает данные, полученные от сервера. Есть несколько самых распространенных форматов обмена данными, такие как JSON и XML. Также существует множество серверных библиотек, которые помогут проще работать с Ajax-запросами. Все они совместимы с Ext, т.к. Ext не предъявляет никаких специфических требований к северным библиотекам. Ext все равно, что происходит на сервере, если результат обработки отдается в корректном формате!