« Шаблоны на java с помощью Velocity. Часть 2 | Сложные интерфейсы на javascript вместе Yahoo UI. Часть 17 » |
Сложные интерфейсы на javascript вместе Yahoo UI. Часть 16
Я продолжаю рассказ об одном из наиболее полезных и сложных компонентов в библиотеке Yahoo UI. В прошлый раз я показал самые основы работы с компонентом DataTable: мы научились размещать его на странице и наполнять данными из javascript-массива. Также познакомились с методиками настройки внешнего вида колонок таблицы и отдельных ячеек (formatter-ы). Сегодняшняя статья покажет то, как загружать данные для DataTable с сервера (ajax), как реализовать постраничную прокрутку таблицы и управлять ее внешним видом.Итак, сначала мы разберем то, как наполнить DataTable набором данных, не жестко заданных в теле html-страницы в виде массива объектов JSON, но загружаемых с сервера. Какой бы способ “поставки” данных мы не выбрали, но работать придется с классом DataSource. Этот универсальный загрузчик данных нуждается только в указании адреса php-скрипта формирующего данные, и правил того, как эти данные после загрузки нужно интерпретировать. Для следующего примера я создал на html-страничке блок div с идентификатором “tableplaceholder”, именно внутрь этого блока будет помещен сгенерированный YUI компонент таблицы. Что касается кода javascript, то он практически идентичен тому, который был показан в прошлой статье серии (все эти правила создания массива с описаниями колонок, DataSource):
ds = new YAHOO.util.DataSource("load_json.php?");
ds.responseType = YAHOO.util.DataSource.TYPE_JSON;
ds.connXhrMode = "queueRequests";
ds.responseSchema = {
resultsList: "users.user",
fields: ["fio","birthday","sex","salary"]
};
var columns = [
{key:"fio", sortable:true},
{key:"birthday", sortable:true},
{key:"sex", sortable:true},
{key:"salary", sortable:true}
];
table = new YAHOO.widget.DataTable("tableplaceholder", columns, ds,
{ initialRequest:"department=managers&from=10&size=10&format=json"}
);
header ('text/javascript');
// принимаем входные переменные, правда, никаких проверок на предмет их корректности нет, но ведь это только учебный пример
$department = $_REQUEST['department'];
$sort = $_REQUEST[‘sort'];
$from = $_REQUEST['from'];
$size = $_REQUEST['size'];
$format = $_REQUEST['format'];
// начинаем случайным образом формировать массив сотрудников
$rows = array ();
for ($i = $from; $i < $size+$from; $i++){
$fio = "Employee # $i from $department";
$birthday = sprintf("%02d-%02d-%04d", rand(1,30), rand(1,12), rand(1900,2000) );
$sex = rand(0,1) == 1?"male":"female" ;
$rows [] = array ('fio' => $fio, 'birthday' => $birthday, 'sex' => $sex , 'salary' => rand(0,1000) );
}
$final = array ('users' => array ('user' => $rows) );
print json_encode ($final);
и сейчас мы займемся наведением лоска на эту пока еще сырую заготовку. Первое с чем мы разберемся это управление типами данных. На рис. 1 я показал, как выполнил сортировку по полю “birthday” и полученный результат не тот, который я мог бы ожидать: 1942 год, затем 1926, 1995… В прошлой статье мы разобрали то, как настроить параметры сортировки какого-либо из столбцов, как включать или выключать сортировку, как задать начальное направление сортировки, как в особо тяжелых случаях управлять правилами сравнения содержимого полей. Может нам нужно сделать, что-то подобное? Нет: YUI отлично умеет сортировать поля содержащие даты, вот только как бы ему подсказать, что содержимое колонки birthday и есть дата? В YUI каждой из колонок я могу поставить в соответствие специальную функцию, выполняющую преобразование строки (а ведь все данные, загружаемые с сервера в виде JSON – это строки) в “реальный” тип данных, т.е. в число или дату. Никоим образом эти функции не нужно путать с функциями форматирования, т.к. последние отвечают за визуализацию уже подготовленной информации. А то, что информация и ее представление это две совершенно разные вещи – очевидно. Первым шагом я создаю специальную функцию преобразования строки вида “год-месяц-день” в стандартный для javascript объект Date:
function strToDate (str){
fragments = str.split ('-')
return new Date (fragments[2], fragments[1] - 1, fragments[0]);
}
ds.responseSchema = {
resultsList: "users.user",
fields: [
"fio",
{key:"birthday", parser: strToDate},
"sex",
{key:"salary", parser:"number"}
]
};
var columns = [{key:"birthday", sortable:true, formatter:YAHOO.widget.DataTable.formatDate}];
table = new YAHOO.widget.DataTable(
"tableplaceholder", columns, ds,
{
initialRequest:"department=managers&from=10&size=10&format=json",
MSG_LOADING: "Ждите, идет загрузка данных",
MSG_EMPTY: "Данных для отображения нет",
MSG_ERROR: "Ошибка на сервере"
}
);
Идем далее: сейчас табличка DataTable содержит только первые 10 записей. Как нам отобразить оставшиеся? Для реализации paging-а (постраничного отображения записей) есть два подхода: на стороне клиента и на стороне сервера. С выходом YUI версии 2.6 появился новый элемент управления Paginator. Формально он предназначен для отображения длинного перечня записей (картинок галереи, да и чего угодно) на нескольких страницах, с расположенной рядом панелью навигации (кнопки перемещения вперед и назад, к самой первой и последней страничке). На практике быстрого старта в использовании paginator-а не получится т.к. он представляет собой скорее конструктор “собери сам”, чем законченный и готовый к использованию визуальный компонент. Вы отвечаете за все: за формирование внешнего вида самой страницы и области навигации, за загрузку из внешнего источника содержимого страницы. Не знаю даже, что проще использовать Paginator или создать собственный компонент с таким же назначением? С другой стороны, если рассмотреть исходный код Paginator-а, то можно почерпнуть несколько интересных методик к написанию собственных “повторно используемых компонент”. До версии YUI 2.6 компонент DataTable имел встроенную поддержку paging-а, а начиная с 2.6 мы при создании объекта DataTable одним из параметров, наряду с описанными выше MSG_LOADING и другими, можем передать параметр paginator, значением которого и является объект YAHOO.widget.Paginator, например:
// создаем paginator
p = new YAHOO.widget.Paginator(
{rowsPerPage: 10, containers : ['container1','container2']}
);
// и используем его
table = new YAHOO.widget.DataTable("tableplaceholder", columns, ds,
{
initialRequest:"department=managers&from=10&size=100&format=json",
paginator: p
}
);
В примере я решил это переопределить: создал в теле html-страницы два блока div с идентификаторами “container1” и “container2” (они могут находиться где угодно) и указал на них при создании paginator-а. Теперь, стандартные панели навигации были внедрены внутрь именно этих блоков div. Следующий пример показывает многие из настраиваемых параметров внешнего вида paging-а:
p = new YAHOO.widget.Paginator(
{
rowsPerPage: 10,
// надписи на кнопка перемещения по страница
firstPageLinkLabel : "<<",
previousPageLinkLabel : "<",
nextPageLinkLabel : " >",
lastPageLinkLabel : ">>",
// соответствующие им css-классы
firstPageLinkClass : "goto-first",
previousPageLinkClass : "goto-prev",
nextPageLinkClass : "goto-next",
lastPageLinkClass : "goto-last",
pageLinksContainerClass : 'pages-area',
pageLinkClass : 'common-page',
currentPageClass : 'current-page',
pageLinks : YAHOO.widget.Paginator.VALUE_UNLIMITED,
pageLabelBuilder : function (page,paginator) {
r = paginator.getPageRecords(page);
return r[0]+"-"+r[1];
},
template :
'<h3>Сведения об сотрудниках</h3>' +
'<p>{CurrentPageReport}' +
'{FirstPageLink} {PreviousPageLink} ' +
'{NextPageLink} {LastPageLink}' +
'<label>Размер страницы: {RowsPerPageDropdown}</label>' +
'{PageLinks} </p>',
rowsPerPageOptions : [
{ value : 10, text : "10" },
{ value : 50, text : "50" },
{ value : 100000, text : "все" } ],
pageReportTemplate : '(страница {currentPage} из {totalPages})'
}
);
Хотя из сравнения картинки и примера кода ясно, то какие переменные управляют каким аспектом внешнего вида paginatora-а, но все же пару слов сказать стоит. Внешний вид paginator-а прежде всего задается шаблоном “template”. Это произвольный фрагмент html с размеченными с помощью placeholder-ов местами, куда нужно поместить (или не поместить) составляющие paginator части. Первая часть шаблона – это сообщение о том, какая страница из скольких сейчас активна (видима). В шаблоне переменная обозначается как “CurrentPageReport” и в свою очередь управляется шаблоном “pageReportTemplate”. Вторая часть шаблона - это кнопки-ссылки перехода по страницам вперед и назад, а также к первой и последней записи (к примеру, FirstPageLink). В свою очередь, каждая из кнопок управляется двумя переменными: firstPageLinkLabel и firstPageLinkClass – это текст и стилевое оформление кнопки. Следующей частью шаблона является падающий список с вариантами размера страниц “RowsPerPageDropdown”. Само же перечисление вариантов (надпись-подсказка и число с количеством записей на страницу) управляется переменной “rowsPerPageOptions”. Завершает шаблон перечисление самих страниц “PageLinks”. Т.к. страниц может быть очень много и они могут элементарно не умещаться в отведенной для paging-а части html-страницы, то можно ограничить число одновременно показываемых ярлычков страниц с помощью переменной “pageLinks” (в примере она равна специальному значению VALUE_UNLIMITED, т.е. без ограничений). Внешний вид каждой (подчеркиваю) страниц может быть различным и формирует его функция “pageLabelBuilder”.
« Шаблоны на java с помощью Velocity. Часть 2 | Сложные интерфейсы на javascript вместе Yahoo UI. Часть 17 » |