На случай, если вы ни разу не пользовались, prototype.js — это JavaScript библиотека, написанная Сэмом Стефенсеном (Sam Stephenson).
Этот потрясающе продуманный и написанный в соответствии со стандартам код берет на себя немалую часть работы, связанной с созданием функционально-богатых интерактивных страниц, которые характерны для Web 2.0.
Если вы уже пытались использовать эту библиотеку, наверняка заметили, что документация не является ее сильной стороной. Как и многие разработчики до меня я разобрался с prototype.js путем чтения кода и экспериментов. Я подумал, что неплохо было бы, учась, делать заметки, и потом поделиться ими со всеми.
Так же я предлагаю неофициальную справку по объектам, классам, функциям и расширениям, предоставляемым этой библиотекой.
Вспомогательные функции
Библиотека располагает множеством предопределенных объектов и вспомогательных функций. Очевидная польза этих функций в сокращении необходимости набирать часто повторящиеся куски кода.
Использование функции $()
Функция $() — это короткая запись для очень часто используемой функции DOM document.getElementById(). Как и функция DOM, она возвращает элемент, который имеет id, переданный в агрументе.
Однако, в отличии от функции DOM эта делает чуть больше. Вы можете передать более одного аргумента и $() вернет массив (Array) объектов со всеми соответствующими элементами. Пример ниже демонстрирует это:
Другая примечательная особенность этой функции заключается в том, что вы можете передать ей как строку с id, так и сам элемент, что делает эту функцию очень удобной для создания других функций, принимающих тот или иной тип параметра.
Использование функции $F()
Функция $F() — это еще одно удобное сокращение. Она возвращает значение полей ввода, таких как текстовые поля или выпадающие списки. Функция принимает в качестве параметра как id элемента, так и сам элемент.
Функция Try.these() позволяет легко попробовать вызвать несколько функций, до тех пор пока какая-нибудь из них сработает.Она принимает в качестве параметров несколько функций и вызывает их одну за другой по порядку, пока какая-нибудь не заработает, и возвращает результат сработавшей функции.
В примере, приведенном ниже, функция xmlNode.text работает в одних браузерах,а xmlNode.textContent работает в других. Используя функцию Try.these() мы можем получить результат работающей.
Вспомогательные функции упомянутые здесь хороши, но не слишком сложны, не так ли? Вы, возможно, уже делали это сами и даже имеете похожие функции в своих скриптах. Но эти функции — только верхушка айсберга.
Я уверен, что ваш интерес к prototype.js вызван в основном его возможностями, связанными с AJAX. Давайте выясним, как эта библиотека может облегчить вам жизнь при реализации AJAX логики.
Объект Ajax — это предопределенный объект, созданный библиотекой, для сокрытия и упрощения кода, в котором требуется AJAX функциональность. Этот объект содержит несколько классов, содержащих инкапсулированную AJAX логику. Давайте взглянем на некоторые из них.
Использование класса Ajax.Request
Если вы не используете вспомогательных библиотек, то, вероятно, пишете много кода для создания объекта XMLHttpRequest, потом асинхронно отслеживаете его работу, извлекаете ответ сервера и обрабатываете его. И счастливы, что вам не требуется поддержка нескольких браузеров.
Чтобы помочь с реализацией AJAX функциональности, библиотека определяеткласс Ajax.Request.
Видите второй параметр, переданный конструктору Ajax.Request? Параметр {method: get, parameters: pars, onComplete: showResponse} представляет собой анонимный объект. Это значит, что мы передаем объект, который имеет свойство method, содержащее строку get, свойство parameters, содержащее строку параметров HTTP запроса и свойство/метод onComplete, содержащее функцию showResponse.
Есть еще несколько свойств, которые вы можете определить и использовать в этом объекте, например, свойство asynchronous, которое может принимать значения true или false, и определяет будет ли запрос к серверу асинхронным (значение по умолчанию true.)
Этот параметр определяет опции AJAX запроса. В нашем примере мы запрашиваем URL, указанный в первом аргументе, с помощью HTTP команды GET передавая строку запроса, указанную в переменной pars, и объект Ajax.Request вызовет функцию showResponse, когда получит ответ сервера.
Как вы, возможно, знаете, XMLHttpRequest сообщает о прогрессе во время HTTP запроса. Есть четыре различных состояния: Loading, Loaded, Interactive, или Complete. Вы можете указать объекту Ajax.Request вызывать различные собственные функции на разных стадиях, чаще всего это используется для состояния Complete. Чтобы сообщить объекту о своих функциях, просто передайте свойства/методы onXXXXX в опциях запроса, например onComplete, как в нашем примере. Функция, которую вы передадите, будет вызвана объектом с одним аргументом — объектом XMLHttpRequest. Вы можете использовать этот объект, чтобы получить данные, возвращенные сервером или проверить свойство status, которое содержит HTTP код ответа.
Две других интересных опции могут быть использованы для обработки результата. Свойство onSuccess — это функция, которая будет вызвана, если AJAX запрос выполнится без ошибок, а наоборот свойство onFailure может содержать функцию, которая будет вызвана, если случится ошибка на сервере. Как и опции-функции onXXXXX, эти две также будут вызваны с объектом XMLHttpRequest, который обслуживал запрос, в качестве аргумента.
Наш пример не делал ничего интересного с XML ответом. Мы просто выводили XML в текстовое поле. Типичным использованием ответа, наверное, является нахождение требуемой информации в XML и обновление некоторых элементов страницы, или даже применение XSLT трансформации, чтобы получить HTML на странице.
Для более полного объяснения смотрите справку по Ajax.Request и options.
Использование класса Ajax.Updater
Если ваш сервер может возвращать информацию, уже сформатированную в HTML, библиотека может сделать вашу жизнь еще легче с помощью класса Ajax.Updater. С ним вам надо только указать, в какой элемент должен быть вставлен HTML, возвращенный AJAX запросом. Пример все расскажет лучше, чем я смогу написать.
<script> function getHTML() { var url = http://yourserver/app/getSomeHTML; var pars = someParameter=ABC; <div class=highlite> var myAjax = new Ajax.Updater(placeholder, url, {method: get, parameters: pars}); </div> } </script>
Как видите, код очень похож на код из предыдущего примера, за исключением функции onComplete, которой теперь нет, и id элемента, передаваемого конструктору. Изменим немного код, чтобы показать, как можно в клиенте обрабатывать ошибки сервера.
Мы добавим в запрос несколько опции, указывающих функцию, которая будет обрабатывать ошибочные состояния. Это делается с помощью опции onFailure. Мы также укажем, что элемент placeholder должен обновляться только в случае удачного запроса. Чтобы добиться этого, мы вместо простого id элемента первым параметром укажем объект с двумя свойствами, success (которое будет использовано, если все сработает) и failure (которое будет использовано, если случится ошибка). Мы не будем использовать свойство failure в нашем примере, а только функцию reportError в свойстве onFailure.
<script> function getHTML() { var url = http://yourserver/app/getSomeHTML; var pars = someParameter=ABC; <div class=highlite> var myAjax = new Ajax.Updater( {success: placeholder}, url, {method: get, parameters: pars, onFailure: reportError}); </div> }
function reportError(request) { alert(Sorry. There was an error.); } </script>
Если ваш сервер возвращает JavaScript код вместо HTML Ajax.Updater может его исполнить этот код. Чтобы указать объект, что надо трактовать ответ как JavaScript, просто добавьте evalScripts: true; в список свойств в последнем аргументе конструктора.
Справка по prototype.js
Расширение классов JavaScript
Один из путей, которым библиотека prototype.js добавляет функциональность, — расширение существующих классов JavaScript.
Расширение класса Object
Метод
Доступ
Аргументы
Описание
extend(destination, source)
static
destination: любой объект, source: любой объект
Предоставляет способ реализовать наследование копированием всех полей и методов source в destination.
extend(object)
instance
любой объект
Предоставляет способ реализовать наследование копированием всех полей и методов данного object.
Расширение класса Number
Метод
Доступ
Аргументы
Описание
toColorPart()
instance
(нет)
Возвращает шестнадцатеричное представление числа. Удобно для конвертации RGB компонентов цвета в HTML-представление.
Расширение класса Function
Метод
Доступ
Аргументы
Описание
bind(object)
instance
object: объект, которому должна принадлежать функция
Возвращает экземпляр функции, которая будет принадлежать данному объекту (т. е. будет его методом). Новая функция будет иметь те же аргументы, что и исходная.
bindAsEventListener(object)
instance
object: объект, которому должна принадлежать функция
Возвращает экземпляр функции, которая будет принадлежать данному объекту (т. е. будет его методом). Аргументом новой функции будет текущий объект event.
Давайте посмотрим на одно из этих расширений в действии.
<input type=checkbox value=1 id=myChk /> Test? <script> // Объявляем класс var CheckboxWatcher = Class.create();
// Определяем остальную часть реализации класса CheckboxWatcher.prototype = {
initialize: function(chkBox, message) { this.chkBox = $(chkBox); this.message = message; // присоединяем наш метод к событию <span class=highlite>this.chkBox.onclick = this.showMessage.bindAsEventListener(this);</span> },
var watcher = new CheckboxWatcher(myChk, Changed); </script>
Расширение класса String
Метод
Доступ
Аргументы
Описание
stripTags()
instance
(нет)
Возвращает строку без HTML или XML тегов
escapeHTML()
instance
(нет)
Возвращает строку с корректно экранированной HTML разметкой
unescapeHTML()
instance
(нет)
Метод, обратный escapeHTML()
Расширение класса document DOM object
Метод
Доступ
Аргументы
Описание
getElementsByClassName(className)
instance
className: название CSS класса, ассоциированного с элементами
Возвращает все элементы, у которых указано данное имя класса.
Расширение класса Event object
Свойство
Тип
Описание
KEY_BACKSPACE
Number
8: Константа. Код клавиши Backspace.
KEY_TAB
Number
9: Константа. Код клавиши Tab.
KEY_RETURN
Number
13: Константа. Код клавиши Return.
KEY_ESC
Number
27: Константа. Код клавиши Esc.
KEY_LEFT
Number
37: Константа. Код клавиши «влево».
KEY_UP
Number
38: Константа. Код клавиши «вверх».
KEY_RIGHT
Number
39: Константа. Код клавиши «вправо».
KEY_DOWN
Number
40: Константа. Код клавиши «вниз».
KEY_DELETE
Number
46: Константа. Код клавиши Delete.
observers:
Array
Список закэшированных обозревателей. Часть внутренней реализации объекта.
Метод
Доступ
Аргументы
Описание
element(event)
static
event: объект Event
Возвращает элемент, породивший событие.
isLeftClick(event)
static
event: объект Event
Возвращает true если была нажата левая кнопка мыши.
pointerX(event)
static
event: объект Event
Возвращает координату x указателя мыши на странице.
pointerY(event)
static
event: объект Event
Возвращает координату y указателя мыши на странице.
stop(event)
static
event: объект Event
Используйте эту функцию, чтобы оборвать поведение по умолчанию этого события и запретить его дальнейшее распространение.
findElement(event, tagName)
static
event: объект Event, tagName: название требуемого тега.
Обходит дерево DOM вверх в поисках первого элемента с данным названием тега, начиная с элемента, который породил событие.
observe(element, name, observer, useCapture)
static
element: объект или id, name: название события (например, click, load, и т. д.), observer: функция, которая будет обрабатывать событие, useCapture: если true, обрабатывает событие в фазе capture (возникновения), если false, то в фазе bubbling (распространения).
element: объект или id, name: название события (например, click), observer: функция, которая будет обрабатывать событие, useCapture: если true, обрабатывает событие в фазе capture (возникновения), если false, то в фазе bubbling (распространения).
function showMessage() { alert(Page loaded.); } </script>
Новые объекты и классы, определенные prototype.js
Еще одна полезная возможность библиотеки — предоставление множества объектов, реализующих поддержку объектно-ориентированного дизайна и общей функциональности.
Объект PeriodicalExecuter
Этот объект предоставляет способ периодического вызова функций через заданный интервал.
Метод
Доступ
Аргументы
Описание
[ctor](callback, interval)
конструктор
callback: функция без параметров, interval: количество секунд
Создает один экземпляр данного объекта, который будет периодически вызывать данную функцию.
Свойство
Тип
Описание
callback
Function()
Функция, которая будет вызвана. Без параметров.
frequency
Number
Период вызова функции в секундах.
currentlyExecuting
Boolean
Индикатор того, что функция в данный момент выполняется.
Объект Prototype
Объект Prototype не делает ничего особенного, кроме того, что объявляет используемую версию библиотеки.
Свойство
Тип
Описание
Version
String
Версия библиотеки
emptyFunction
Function()
Пустая функция
Объект Class
Объект Class используется для объявления других классов библиотеки. Использование этого класса гарантирует, что новый класс будет поддерживать метод initialize(), который используется как конструктор.
Смотрите пример ниже.
// Объявляем класс <span class=highlite>var MySampleClass = Class.create();</span>
// определяем остальные детали реализации класса MySampleClass.prototype = {
Устанавливает требуемые опции для данной AJAX операции
responseIsSuccess()
instance
(нет)
Возвращает true, если AJAX операция была выполнена успешно, false в противном случае
responseIsFailure()
instance
(нет)
Функция, обратная responseIsSuccess().
Класс Ajax.Request
Наследуется от Ajax.Base Содержит AJAX операции
Свойство
Тип
Доступ
Описание
Events
Array
static
Список возможных событий/состояний, о которых сообщается во время AJAX операции. Список содержит: Uninitialized, Loading, Loaded, Interactive, и Complete.
transport
XMLHttpRequest
instance
Объект XMLHttpRequest, обслуживающий AJAX операцию
Метод
Доступ
Аргументы
Описание
[ctor](url, options)
конструктор
url: URL, по которому совершается запрос, options: AJAX опции
Создает один экземпляр объекта с данными url и options. Важно: Стоит заметить, что выбранный URL подвергается проверке браузера на безопасность. Во многих случаях браузер не будет совершать запрос, если URL не принадлежит тому же хосту (домену), что и текущая страница. В идеале, вы должны использовать только локальные URL, чтобы избежать настроек или ограничений пользовательских браузеров. (Спасибо Clay.)
request(url)
instance
url: URL, по которому будет совершен AJAX запрос
Этот метод обычно не вызывается снаружи. Он заранее вызван из конструктора.
setRequestHeaders()
instance
(нет)
Этот метод обычно не вызывается снаружи. Он вызывается самим объектом, чтобы установить HTTP заголовки, которые будут отправлены в запросе.
onStateChange()
instance
(нет)
Этот метод обычно не вызывается снаружи. Он вызывается самим объектом, когда меняется AJAX статус.
respondToReadyState(readyState)
instance
readyState: номер состояния (от 1 до 4)
Этот метод обычно не вызывается снаружи. Он вызывается самим объектом, когда меняется AJAX статус.
Класс options argument object
Аргумент options является важной частью AJAX операций. Для этого нет класса options. Любой объект, имеющий требуемые свойства, может быть использован. Обычно используются анонимные объекты, созданные специально для AJAX запросов.
Свойство
Тип
Значение по умолчанию
Описание
method
String
post
Метод HTTP запроса
parameters
String
Список параметров, сформатированный как в URL
asynchronous
Boolean
true
Индикатор того, что AJAX запрос будет асинхронным
postBody
String
undefined
Данные передаваемые в теле HTTP POST запроса
requestHeaders
Array
undefined
Список HTTP заголовков запроса. Этот список должен содержать четное число элементов, каждый нечетный должен быть именем заголовка, следующий за ним четный должен быть значением этого заголовка. Например: [my-header1, this is the value, my-other-header, another value]
onXXXXXXXX
Function(XMLHttpRequest)
undefined
Ваши собственные функции, которые будут вызваны при соответствующем событии или изменении состоянии AJAX запроса. Например: var myOpts = {onComplete: showResponse, onLoaded: registerLoaded};. Функции будет передан один параметр, содержащий объект XMLHttpRequest, который обслуживает данную AJAX операцию.
onSuccess
Function(XMLHttpRequest)
undefined
Ваша функция, которая будет вызвана, если AJAX запрос завершится успешно. Функции будет передан один параметр, содержащий объект XMLHttpRequest, который обслуживает данную AJAX операцию.
onFailure
Function(XMLHttpRequest)
undefined
Ваша функция, которая будет вызвана, если AJAX запрос завершится с ошибкой. Функции будет передан один параметр, содержащий объект XMLHttpRequest, который обслуживает данную AJAX операцию.
insertion
Function(Object, String)
null
Функция, которая будет вызвана, чтобы вставить полученный текст внутрь элемента. Она будет вызвана с двумя аргументами: элементом, который надо обновить и текстом ответа. Применяется только к объектам Ajax.Updater.
evalScripts
Boolean
undefined, false
Определяет, будут ли выполнены скриптовые блоки в ответе. Применяется только к объектам Ajax.Updater.
decay
Number
undefined, 1
Определяет прогрессирующее замедление обновлений в объекте Ajax.PeriodicalUpdater, если ответ совпал с предыдущим. Например, если вы установите 2, то после обновления, получившего тот же результат, что и предыдущее, объект будет ждать в два раза дольше до следующего обновления. Если это повторится еще раз, объект будет ждать в четыре раза дольше и так далее. Оставьте неопределенным или используйте 1, чтобы избежать этого.
Класс Ajax.Updater
Наследуется от Ajax.Request
Используется, когда запрошенный URL возвращает HTML, который вы хотите напрямую вставить в определенный элемент на странице. Вы можете так же использовать этот объект, если URL возвращает блоки
Hello, <span id=person style=color:red;>Wiggum. Hows it going?</span>
Этот объект предоставляет несколько вспомогательных функций, которые используются внутри библиотеки для облегчения извлечения значений элементов форм.
Метод
Доступ
Аргументы
Описание
inputSelector(element)
instance
element: объект или id элемента формы, у которого есть свойство checked, например радио-кнопка или чекбокс.
Возвращает массив (Array) с именем и значением элемента, например: [elementName, elementValue]
textarea(element)
instance
element: объект или id элемента формы, у которого есть свойство value, например, текстовое поле, кнопка или поле ввода пароля.
Возвращает массив (Array) с именем и значением элемента, например: [elementName, elementValue]
select(element)
instance
element: объект или id элемента
Возвращает массив (Array) с именем элемента и всеми выбранными значениями или текстами, например: [elementName, selOpt1 selOpt4 selOpt9]
Класс Abstract.TimedObserver
Этот класс используется как базовый для других классов, которые следят за изменением значения элемента (или любого другого его свойства, которое определяет производный класс). Этот класс используется как абстрактный класс.
Производные классы могут быть созданы для отслеживания таких вещей, как например, изменение значения поля ввода или одного из свойств стиля или количества строк в таблице или чего-либо еще, что вам интересно отслеживать.
Метод
Доступ
Аргументы
Описание
[ctor](element, frequency, callback)
конструктор
element: элемент или id, frequency: период в секундах, callback: функция, которая будет вызвана, когда элемент поменяется
Создает объект, который будет следить за изменениями объекта.
getValue()
instance, abstract
(нет)
Производные классы должны определять этот метод, чтобы он возвращал текущее значение наблюдаемого свойства.
registerCallback()
instance
(нет)
Этот метод обычно не вызывается снаружи. Он вызывается самим объектом, чтобы начать слежение за элементом.
onTimerEvent()
instance
(нет)
Этот метод обычно не вызывается снаружи. Он периодически вызывается самим объектом для проверки элемента.
Свойство
Тип
Описание
element
Object
Отслеживаемый элемент.
frequency
Number
Интервал в секундах между проверками.
callback
Function(Object, String)
Функция, которая должна быть вызвана, если элемент изменится. Ей передается сам элемент и новое значение отслеживаемого свойства.
lastValue
String
Последнее значение элемента.
Класс Form.Element.Observer
Наследуется от Abstract.TimedObserver
Реализация Abstract.TimedObserver, которая отслеживает значения полей ввода. Используйте этот класс, если вы хотите следить за элементом, который не создает события при изменении значения. В противном случае вы можете воспользоваться классом Form.Element.EventObserver.
Метод
Доступ
Аргументы
Описание
[ctor](element, frequency, callback)
конструктор
element: элемент или id, frequency: интервал в секундах, callback: функция, которая должна быть вызвана, когда изменится значение элемента
Наследуется от Abstract.TimedObserver. Создает объект, который будет отслеживать свойство value элемента.
getValue()
instance
(нет)
Возвращает значение элемента.
Класс Form.Observer
Наследуется от Abstract.TimedObserver
Реализация Abstract.TimedObserver, которая отслеживает изменения любого из полей формы. Используйте этот класс, если вы хотите следить за формой, которая содержит элементы, которые не создают события при изменении значения. В противном случае вы можете воспользоваться классом Form.EventObserver.
Метод
Доступ
Аргументы
Описание
[ctor](form, frequency, callback)
конструктор
form: объект формы или id, frequency: интервал в секундах, callback: функция, которая должна быть вызвана, если изменится какое-либо из полей формы
Возвращает все элементы формы в сериализованном виде.
Класс Abstract.EventObserver
Этот класс используется как базовый для других классов, выполняющих функции при возникновении каких-либо событий изменяющих значения элемента.
К одному и тому же элементу можно быть присоединено несколько объектов типа Abstract.EventObserver без помех друг для друга. Они будут вызываться в порядке присоединения.
Событие, на котором срабатывает объект: onclick для радио-кнопок и чекбоксов и onchange для всех текстовых полей и списков.
Метод
Доступ
Аргументы
Описание
[ctor](element, callback)
конструктор
element: элемент или id, callback: функция, которая будет вызвана, когда произойдет событие
Создает объект, следящий за элементом.
getValue()
instance, abstract
(нет)
Производные классы должны определить этот метод, чтобы он возвращал текущее значение отслеживаемого элемента.
registerCallback()
instance
(нет)
Этот метод обычно не вызывается снаружи. Он вызывается внутри объекта, что присоединиться к событию