xmlhack.ru logo
>> статьи на xmlhack.ru

Prototype: упрощение работы с AJAX

Автор: Брюс Перри
Опубликовано на XML.com (05.04.2006, англ.): http://www.xml.com/pub/a/2006/04/05/prototype-javascript-ajax.html
Опубликовано на xmlhack.ru (14.04.2006, рус.): http://xmlhack.ru/texts/06/prototype-javascript-ajax/prototype-javascript-ajax.html
В закладки:   Del.icio.us   reddit

Эта статья описывает Prototypе, опенсорсную JavaScript-библиотеку для создания объектов для AJAX-приложений. Тут рассказывается, как использовать Prototype через описание web-приложения, ориентированного на оценку экологических параметров — ежегодного измерения содержания углекислого газа (CO2) в атмосфере. Сначала я укажу на плюсы Prototype и расскажу, как подключить Prototype в ваше приложение. После этого я детально остановлюсь на том, как приложение эффективно использует библиотеку.

Почему стоит использовать Prototype?

Почему бы мне было не создать простой объект JavaScript (POJO) для своего приложения вместо того, чтоб представлять опенсорсную библиотеку? Во-первых, Prototype включает хорошую подборку сокращений JavaScript, которые упрощают набор кода, да и вообще, всё это придумано для того, чтоб заново не изобретать колесо. Одно из постоянно используемых сокращений — это $("mydiv"), которое является функцией Prototype, выдающей элемент Document Object Model (DOM), соответствующий HTML-элементу с id "mydiv". Вот такая вот краткость уже сама по себе является причиной, по которой стоит установить Prototype. Это эквивалент для

document.getElementById("mydiv"); 

Другое полезное сокращение Prototype — это $F("mySelect") для отображения значения HTML-элемента на web-странице, такого, как список выбора. Привыкнув к краткому Перловому стилю Prototype, вы будете использовать эти сокращения постоянно. В Prototype имеется также огромное количество пользовательских объектов, методов и расширений для встроенных JavaScript-объектов, таких как объекты Enumeration and Hash (о которых пойдёт речь ниже).

В конце концов, Prototype также выполняет функции XMLHttpRequest, имея свой Ajax.Request и связанные с ним объекты. Вам уже не нужно писать код для использования этого объекта в разных браузерах.

Установка

Итак, как же установить Prototype? Сперва загрузите библиотеку с prototype.conio.net. Prototype является проектом с открытым исходным код и доступен по лицензии MIT. Загрузка включает в себя файл с названием prototype.js. Это JavaScript файл, в котором определены различные функции и объекты, которые будут использоваться в AJAX-приложении. Добавьте prototype.js файл в приложение, используя HTML-тэг script.

<head>...
<script src="js/prototype.js" type="text/javascript">
</script>
<script src="js/co2.js" type="text/javascript">
</script>
<script src="js/eevpapp.js" type="text/javascript">
</script>...
</head>

Директория, которая содержит HTML-файл приложения, содержит также директорию с именем js. Эта директория содержит prototype.js, код объекта этой статьи в файле co2.js, а так же и остальной код приложения в файле eevapp.js.

Так как приложение импортирует файл Prototype, код JavaScript в других импортированных .js файлах может использовать объекты Prototype и расширения так, если бы они были описаны и определены локально. JavaScript не нуждается в импортировании объектов из других JavaScript файлов, которые обычно импортирует ваш браузер.

Смена климата

Как Prototype может нам помочь в работе с нашими приложениями? Какие требования эти приложения имеют?

User Interface — это браузер, такой как Safari 1.3, Firefox 1.5, Opera 8.5 или Internet Explorer 6. Приложение разработано для того, чтобы отображать небольшие сводки относительно ежегодного измерения содержания углекислого газа (CO2) в атмосфере. Это цифра, к примеру, 377, которая показывает миллионную долю содержания CO2 в воздухе по состоянию на каждый год. Я решил собрать информацию за все годы в JavaScript объекте, который браузер закачивает с приложением. Нет необходимости использовать базу данных для сохранения этих данных, которые небольшие, нисколько не секретны, и не требуют подтверждения права на доступ к ним. Эта информация собрана для представления общественности. Это приложение, тем не менее, позволяет объекту JavaScript добавлять новые данные на лету, если в этом есть необходимость.

CO2 апплет

На изображении 1-1 показан экран браузера для приложения. В верхнем левом углу приложения — апплет, который показывает уровень содержания CO2 в атмосфере в выбранный пользователем год.

Рисунок 1-1
Рисунок 1-1. Элемент select показывает уровень CO2

Эти данные были получены из обсерватории Мауна Лоа в результате исследований, назначенных к проведению правительством США на Гавайях. Измерения произведены на большой высоте в заповедниках. Учёные всего мира используют эту информацию в своих исследованиях климатических изменений.

Имеются различные годовые показатели по 46 годам: с 1959 по 2004 (информацию о состоянии на 2005 год пока получить нельзя). По этой причине имеет смысл держать эту информацию в объекте JavaScript. Даже если мы захотим показывать ежемесячный уровень, для каждого года с помощью этого инструмента (свыше 500 различных цифр), то всё равно будет целесообразнее хранить эту информацию с помощью данного клиента. Тут не требуется ни базы данных, ни обращений к серверу.

Когда Prototype начинает работать

В eevapp.js файле содержится код, который выполняется, когда пользователь выбирает год из списка.


//создание объекта
//опрделено в  co2.js
var co2lev = new CO2Levels();
//выполнение обработчика события onload
//после загрузки браузером всего тела страницы.
window.onload=function(){
                               
$("co2_select").onchange=function(){
    $("co2ppm").innerHTML= 
    co2lev.getYear($F("co2_select")); 
    }
};

Значение "co2_select" — это id списка выбора, по которому кликает пользователь, выбирая год.

<select id="co2_select" .../>

Код:

 $("co2_select")

возвращает ссылку на DOM-элемент. Это эквивалетнно выполнению document.getElementById("co2_select");.

Код, устанавливающий выполнение JavaScript функции для выбранного элемента списка по событию onchange, выглядит следующим образом $("co2_select").onchange=function(){...}.

Простыми словами, когда пользователь выбирает год в годовом меню, браузер выполняет данную функцию. Что выполняет данная функция? Функция получает ссылку на HTML div элемент с id "co2ppm", опять же, используя сокращение Prototype'а. Свойство innerHTML объекта div, показывающего, что видит пользователь в браузере, — есть значение, возвращаемое в результате вызова метода

co2lev.getYear($F("co2_select"));

Объект под названием co2lev описан в верхней части файла eevapp.js.

var co2lev = new CO2Levels();

В этом объекте используется метод под названием getYear(). Благодаря ему появляется меню, в котором можно выбрать год в качестве параметра, например "1999". Этот метод позволяет показывать уровень CO2 соотносящийся с тем годом.

Лаконичный синтаксис

Этот символ доллара снова появляется в синтаксисе: $F("co2_select"). Функция Prototype $F() выдаёт значение элемента в формате HTML. Приложение использует эту функцию для изменения показываемого уровня CO2 каждый раз, когда пользователь выбирает другой год.

Есть один совет относительно $F(): для списка выбора значение выдаётся только если элемент option содержит атрибут value: <option value="1959">1959</option>. Во всяком случае, версия Prototype'а, которую я использовал (1.4.0) не выдавала значения с $F(), если я пропускал часть value="...".

Обзор объекта

Определение объекта CO2Levels появляется в файле co2.js. На изображении 1-2 представлена UML-диаграмма класса, описывающая объект.

UML class diagram
Рисунок 1-2. Диаграмма класса

Вот полный код для объектов CO2Levels. Первая строчка создаёт новый объект, используя базовый синтаксис Prototype, локальная переменная levels — это объект, похожий на ассоциативный массив, который соединяет года с уровнями содержания CO2. Я не написал большую часть годов для того, чтоб сделать это всё читабельным.

var CO2Levels=Class.create();
CO2Levels.prototype = {
/*
Источник: http://cdiac.esd.ornl.gov/ftp/trends/co2/maunaloa.co2
Mauna Loa Observatory, Hawaii
*/
initialize: function(){
    this.levels={ "1959":315.98,"1960":316.91,
    "1961":317.65,"1962":318.45,
    "2003":375.64,"2004":377.38};
    this.levelsHash=$H(this.levels);
    },

getYear: function(year){
    if (! isNaN(year)) {
        return this.levelsHash[year];
    }   else {
        return 377;
    }
    },
    
keys: function(){
    return  this.levelsHash.keys();
},

values: function(){
    return  this.levelsHash.values();
},

inspect: function(){
    alert( this.levelsHash.inspect());
},

add: function(year,level){
    var tmp = new Object();
    tmp[year] = level;
    this.levelsHash=this.levelsHash.merge(tmp);
}

}

Cоздание объектов Prototype

Использование метода Class.create() в Рrototype возвращает объект JavaScript, который автоматически выдаёт экземпляр этого объекта c методом initialize(). Он похож на метод-конструктор Java. Метод initialize() будет вызываться каждый раз, когда код будет создавать новый экземпляр объекта CO2Levels. Остальная часть кода определяет прототип, или копию, для объекта CO2Levels, включая ссылку на метод инициализации. Что делает метод initialize()? Он создаёт локальную переменную, которая называется levels. Этот метод ссылается на объект, который содержит всю информацию: уровни CO2 соотносятся с годами, в которых были сделаны замеры. Далее происходит конвертация этого объекта в объект Prototype Hash, который обеспечивает большую функциональность объекта (например, возможность просматривать содержание объекта и динамически добавлять новые данные).

this.levelsHash=$H(this.levels);

Prototype-объект Hash

Вот снова синтакс: $H(). Эта функция принимает объект JavaScript в качестве параметра и возвращает объект Prototype's Hash. Так же как и хэш-таблицы в других языках, Hash имеет структуру наподобие ассоциативного массива с несколькими методами, которые разработаны для управления этими данными, а также добавления новых в Hash.

К примеру, метод Hash.keys() возвращает массив всех Hash-ключей (таких как все года). Метод values() возвращает массив значений (уровни содержания СО2). Метод merge() добавляет новые ключи и значения в Hash.

Делегатор

Наш объект CO2Levels использует принцип делегирования, по которому он обращается к своим же методам keys(), values(), и add(). Эти методы делегируют работу во встроенный объект Hash, который хранится как локальная переменная: levelsHash.

Давайте посмотрим на getYear().

getYear: function(year){
    if (! isNaN(year)) {
        return this.levelsHash[year];
    }   else {
        return 377;
    }
}

Встроенный метод JavaScript isNaN() возвращается false, если его параметр является числом (таким как "2000"), и true в обратном случае (как в isNaN("hello")). Если параметр getYear() проходит этот тест, тогда код использует обычное выражение JavaScript для того, чтобы вернуть значение ключа или свойство: this.levelsHash[year] (к примеру, this.levelsHash["2004"] равно 377.38). Тогда браузер отображает числовое значение внутри элемента HTML div.

Добавление в существующий хэш

Объект CO2Levels включает метод add(), который может добавлять новые ключи и значения (добавочные года и уровни содержания СO2) к существующей информации.

add: function(year,level){
    var tmp = new Object();
    tmp[year] = level;
    this.levelsHash=this.levelsHash.merge(tmp);
}

Этот метод создаёт новый Object по двум параметрам (представляющих год и уровень содержания CO2), который может иметь следующий вид: {"2005":381}

Код затем передаёт этот объект для обработки методом merge() Prototype-объекта Hash. Этот метод объединяет новый объект с существующей информацией в хэше, соединяя их полностью в одну группу данных или ассоциативный массив.

Метод merge() возвращает существующие данные с новой парой свойство-значение, добавляя её к концу.

С небольшим рефакторингом код может использовать XMLHttpRequest для осуществления выборки любой новой информации об уровнях содержания СО2 от Mauna Loa Observatory, затем добавить её к существующим данным на клиентской стороне.

Проверка

В конце концов, в объекте Prototype Hash есть также метод inspect(). Благодаря ему появляется читабельное отображение содержания хэша, как на изображении 1-3.

alert window shwing hash contents
Рисунок 1-3. Хэш. Как он выглядит.

Объект CO2Levels делегирует задание inspect() метода внутреннему объекту Prototype Hash.

inspect: function(){
    alert( this.levelsHash.inspect());
}

Это очень полезный отладочный инструмент для просмотра содержимого объекта Hash.

Следующая статья расскажет о кешировании AJAX в этом же приложением. Там вводится объект Prototype'а Ajax.Request, который упрощает код, использующий объект XMLHttpRequest. Это важный высокоуровневый объект JavaScript, использующийся в AJAX-приложениях для создания HTTP-соединений с сервером в фоновом режиме.



XML.com Copyright © 1998-2007 O'Reilly Media, Inc.
Перевод: xmlhack.ru Copyright © 2000-2007 xmlhack.ru