вторник, 19 декабря 2006 г.

Введение в Prototype

JavaScript продолжает завоевывать популярность во всем интернете, и на сегодняшний день мы можем быть уверены в скорости, надежности и удобстве его использования. Разумным решением было бы использовать некую основу, которая пригодилась бы нам в наших проектах. Именно за это мы благодарны Сэму Стефенсону - человеку, создавшего Prototype.js - потрясающую библиотеку функций, которая упростит нашу работу в JavaScript.

Данное руководство затрагивает только азы этой библиотеки и сопровождается простыми примерами ее использования.

Приступим!

После того как вы скачали нужные файлы и положили их в нужную директорию, все что вам нужно, чтобы включить Prototype в ваш html-код, например так:

<script src="/scripts/prototype.js" type="text/javascript"></script>


Обратите внимание, только что программирование на javascript стало в 10 раз легче! Давайте же поскорее узнаем что за возможности появилось в наших руках!

Функция $()

Наиболее используемая функция, предоставляет простой путь для получения дескриптора DOM элемента. Обычно, если вы хотите получить доступ к DOM элементу, вы делаете что-то вроде:

node = document.getElementById("elementID");


Использование $() поможет делать это проще:

node = $("elementID");


Другая замечательная сторона этой функции - то что она более мощная нежели document.getElementById(), т.к. в функцию встроена возможность получать доступ к нескольким элементам сразу:

allNodes = $("firstDiv", "secondDiv");
for(i = 0; i < allNodes.length; i++) {
alert(allNodes[i].innerHTML);
}


В этом примере мы использовали функцию $() для получения массива элементов, который затем может быть обработан, скажем, в цикле.

Работа с формами

Работа с формами - полное д_рьмо не только со стороны HTML/CSS, но и в JavaScript. Prototype.js предоставляет удобные методы работы с формами, которые сделают вашу жизнь более веселой.

Функция $F() возвращает значение элемента формы по его ID. К примеру возьмем простую форму:

<input type="text" id="textfield" name="textfield" />
<textarea rows="5" cols="5" id="areafield" name="areafield"></textarea>
<select id="selectfield" name="selectfield">
<option value="1" selected>One</option>
<option value="2">Two</option>
</select>
<input type="checkbox" id="checkfield" name="checkfield" value="1" checked />


Для того, чтобы получить значения элементов, воспользуемся $F():

$F("textfield");      // возвращает значение text input
$F("areafield"); // возвращает значение textarea
$F("selectfield"); // возвращает выбранное значение select
$F("checkfield"); // возвращает null если не установлена, иначе значение


В большинстве случаев получать значение элемента формы через эту удобнее, чем напрямую. Но есть пара "заморочек" которые я обнаружил:
- как и прежде, нет простого способа получить значени radio group элемента (только конкретное значение каждого radio элемента)
- нельзя передать сразу несколько ID, как вы это делали в $()

Другая функция, Form.getElements() вернет в массиве значение каждого элемента формы, не обращая внимания на тип элемента:

allNodes = Form.getElements("myform");
for(i = 0; i < allNodes.length; i++) {
//делаем что-то для каждого элемента формы
}


В этом примере мы получили все значения формы c id="myform". Если вы хотите обработать событие onclick для каждого элемента или показать вспывающее окно, вы можете это сделать как указано выше.

Следующий метод, который мы рассмотрим - Form.serialize(). Когда вы строите Ajax запрос, часто вам приходится приводить к нужному формату вашу POST строку, чтобы передать данные. Когда вы жмете submit строка уже построена. serialize() сделал этот процесс удивительно простым:

allNodes = Form.serialize("myform");

// возвращает field1=value1&field2=value2&field3=value3 и т.д...


Построение строки для нас - бесспорно удобно, но что делает эту функцию поистине замечательной, то что она работает со всеми типами элементов. Выше мы видели, что $F() имеет некоторые проблемы с использованием radio groups, но serialize() делает работу с элементами, независимо от типа, полностью корректной.

getElementsByClassName()

Не могу понять, почему до сих пор в JavaScript не реализована эта функция. Но Prototype.js добавляет getElementByClassName(), расширяя объект document. Функция работает практически так же, как document.getElementsByTagName(). Различие в том, что нашей функции как параметр надо передать название класса:

allNodes = document.getElementsByClassName("red");
for(i = 0; i < allNodes.length; i++) {
alert(allNodes[i].innerHTML);
}


В массиве возвращаются все элементы, которые соответствуют указанному классу. Функция работает даже в том случае, если для элемента определено несколько классов. getElementByClassName() используется во многих проектах, в основном для того чтобы задействовать нужное DOM событие. Я верю, что вы найдете ее полезной!

Работа с элементами

Объект Element предоставляет богатый набор вспомогательных функций (возможности которых расширяются с каждым релизом), практика использования которых весьма похожа на практику использования DOM. Некоторые из них не сильно облегчают ваш код, другие позволяют заменить 10 (и более) строк кода в один вызов. Давайте взглянем на несколько примеров.

Получение высоты элемента без дополнительных функций:

$("first").offsetHeight


А теперь воспользуемся ими:

Element.getHeight("first")


В этом примере новая функция не предоставила никаких преимуществ. Но что если мы хотим, скажем, убрать className из элемента? Это обычный путь (взято из Prototype.js):

element = $(element);
if (!element)
return;
var newClassName = '';
var a = element.className.split(' ');
for (var i = 0; i < a.length; i++) {
if (a[i] != className) {
if (i > 0)
newClassName += ' ';
newClassName += a[i];
}
}
element.className = newClassName;


А теперь с помощью вспомогательной функции:

Element.removeClassName("elementID", "red");


Круто, не правда ли? Не беря во внимание первый пример, вспомогательные функции позволяют экономить море времени, делая общие задачи проще. Для простоты и удобства я рекомендую использовать эти функции на протяжении написания всего проекта. Посмотреть полный список функций, и информацию об их использовании вы можете на странице документации Prototype от Sergio (англ. версия).

Функция Try.This()

Try.This() - замечательная функция, которая помогает разработчикам создавать код, работающий независимо от реализации JavaScript в различных браузерах. Чтобы вам не пришлось самостоятельно определять тип объекта или браузера, эта функция будет пробовать выполнять часть кода пока не произойдет ошибка, а затем переходить дальше:

return Try.these(
function() {
alert("первый");
jkgjhgjhg //преднамеренная ошибка
alert("первая ошибка");
return 1;
},
function() {
alert("второй");
return 2;
}
);


В этом примере первая часть кода перестанет выполняться в месте где мы создали преднамеренную ошибку. Зная это, очень важно быть внимательным к нашему коду, т.к. до места ошибки все будет выполнено. Вцелом, Try.This() используется в проектах не часто, но порой весьма полезно знать что такая функция есть и знать, как она работает.

Поддержка Ajax

Сейчас я покажу вам как мы можем создавать Ajax-приложения при помощи Prototypes.js. В соответствии с документацией обычный Ajax-запрос может быть реализован так:

var myAjax = new Ajax.Request(
url,
{method: 'post', parameters: data, onComplete: ajax_response}
);


Где используемый метод post или get, а параметры - пары имя/значение объединенные в строку и onComplete() - функция, которая будет вызвана когда вызов закончится. Один раз разобравшись с работой этого метода легко сделать повторяющиеся Ajax-вызовы путем создания ваших собственных функций. Для начала просто пример, который создает Ajax-запрос:

function ajax_request(url, data) {
var myAjax = new Ajax.Request(
url,
{method: 'post', parameters: data, onComplete: ajax_response}
);
}


И после того как запрос закончится, отправим его ответ в ajax_response().

function ajax_response(originalRequest) {
if(!bHasRedirect) {
//process originalRequest.responseText;
}
else {
bHasRedirect = false;
ajax_request(originalRequest.responseText, "");
}
}


После того как вы создали Ajax-запрос, ответ всегда будет получен в ajax_response(). В дальнейшем будет выполнен другой Ajax-запрос, если bHasRedirect установлен (true), или будет запущен код на основе глобального массива функций и метода originalRequest.responseText() (возвращаемое значение).

PeriodicalExecuter

Этот объект после инициализации повторно вызывает требуемую функцию с заданным интервалом времени. Удобно, когда вы хотите автоматически обновить часть сайта.

function periodicalUpdate() {
new PeriodicalExecuter(refreshNews, 10);
}

function refreshNews() {
//Ajax код для слива новостей и обновления DOM
}


Конструктор PeriodicalExecuter получает название функции для выполнения как первый параметр и интервал выполнения в качестве второго. Обратите внимание, наша функция получает промежуток времени в секундах (стандартная функция setInterval() использует миллисекунды в качестве параметра). Хочу заметить, что этот пример может использоваться для любых целей - не только в связке с Ajax. Для использования вместе с Ajax удобнее пользоваться классом Ajax.PeriodicalUpdater.

В данном руководстве вы найдете все методы или функции, которые предоставляет Prototype.js, но есть некоторые функции, которые тоже хотелось бы упомянуть (Все они могут быть найдены в документации):

observe - функции этого метода подобны addEvent(), но используются для того чтобы аккуратно присоединять события к DOM

User Iteraction - вы можете обнаружить встроенные глобальные значения, такие как KEY_TAB, для того чтобы понять какую клавишу нажал пользователь. Так же вы можете получить координаты мыши и информацию о нажатых на ней кнопках.

Class Creation - зачем останавливаться на функциональности Prototype.js? Используя похожий синтаксис и функции мы можем построить свой собственный класс, чтобы держать все по полочкам. Добавление конструктора и дополнительных методов еще никогда не было столь простым. Смотрите Class.Create() в документации.

Обобщая вышесказанное

Разве допустимо использование публичного кода/библиотек, если вы не знаете автора и досконально не разбираетесь в том, что творится "за кулисами"? Мой ответ - да, до тех пор пока вы более или менее тестируете код и доверяете человеку/сообществу, которые стоят за разработкой всего этого. В случае Prototype.js такая уверенность складывается из двух частей. Во-первых Ruby on Rails интегрировали поддержку Prototype.js. С тех пор как Ruby on Rails имеет надежную команду разработчиков, было найдено и исправлено огромное количество багов, за счет чего Prototype.js стала еще более стабильной. Во-вторых - разработчик работающий на 37signals. Я доверяю не только практике разработки программ какой-либо фирмы, но я верю что в дальнейшем Prototype.js будет и дальше тестироваться и становиться лучше. Вдобавок ко всему, я сам продолжаю тестировать эту библиотеку и теперь уже использую практически во всех своих проектах.

Prototypes.js это намного большее, чем описано в этой статье, и его действительно стоит попробовать! Если вас возмущает размер файла (30 кб, примерно как этот текст), помните, что вы всегда можете убрать классы, которые вы не используете или сжать JavaScript при помощи PHP перед отдачей пользователю. Prototypes.js совсем не сложен при изучении. И не забудьте - это всего лишь вводная статья, если вы хотите узнать побольше информации, посетите неоффициальную документацию Prototype и script.aculo.us wiki-документацию.

Оригинал статьи: http://particletree.com/features/quick-guide-to-prototype

8 комментариев:

greenh комментирует...

приятный обзор

Анонимный комментирует...

Спасибо, классно написано :)

omusatov комментирует...

Блин, неделю рыл сеть в поисках чего-нибудь подобного! Перешел сюда по ссылке на spravkaweb.ru. Спасибо тебе, родной!

2wsdzd@bnfjxg.com комментирует...

Риспект за статью! Отлично написано.

Анонимный комментирует...

Спасибо, отличный текст, очень полезно

Анонимный комментирует...

Спасбо за статью, вот только есть один вопрос, нужен ли какойто параметр для того чтобы подгружаемый php скрипт выполнялся? Т.е. простой html подгружается все ок, а вот результат выполнения php скрипта уже нет, кто-нибудь сталкивался с такой проблемой?

Анонимный комментирует...

Подскажите, у меня движок joomla, один из модулей использует prototype, поставил другой модуль, который использует jquery, в результате тот который на prototype перестал работать. Причем не работает даже если просто подгрузить файл скрипта jquery.js

создание сайтов краснодар создание сайта народ комментирует...
Этот комментарий был удален администратором блога.