Табы для версии 0.2

Кто-то там помнится хотел табов? Делюсь нашим вариантом, который мы делали для версии 0.2.

Код написан по мотивам класса lsBlockLoaderClass из block_loader.js в новом skine версии 0.3. Чем же они отличаются? Да по большому счету ничем. Может быть разве что более строгим следованием парадигме MooTools. Отличия:

1. Класс следует принципу разделения аргументов и опций, независим от места применения, а значит переносим и расширяем.
2. Класс немного шире использует возможности MooTools.
3. Класс использует куки для сохранения состояния текущего таба.

Так же как и lsBlockLoaderClass наш класс строит табы на базе тегов списков ul и li. Html/Smarty каркас вместе с кодом создания объекта класса выглядит следующим образом:

{literal}
 <script>
  window.addEvent('domready', function() {
  new BlockTabs($('content'),$$('ul.btabs a'),$('tab1'));
  });
 </script>
{/literal}

<ul id="btabs">
 <li id="tab1"><a href="#" id="{$DIR_WEB_ROOT}/include/ajax/backendscript1.php">Tab1</a>
 <li id="tab2"><a href="#" id="{$DIR_WEB_ROOT}/include/ajax/backendscript2.php">Tab2</a>
...
 <li id="tabN"><a href="#" id="{$DIR_WEB_ROOT}/include/ajax/backendscriptN.php">TabN</a>
</ul>

<div id="content" >
</div>


Конструктору класса передается на вход три аргумента:
1. Объект Element div куда выводится содержимое текущего таба, получаемое от бекэнда с использованием ajax.
2. Массив объектов Elemets a — по сути наши переключатели табов.
3. Объект Element li — по сути активный по умолчанию таб.

Uri к ajax-бекенд php-скриптам указываются у нас через аттрибут id тегов а, хотя
можно использовать и href например. В каркасе у тегов все назначенные id участвуют в работе класса.

Ну и сам класс:

var BlockTabs = new Class({

 initialize: function(container,links,active) {
 this.container=$(container);
 this.links=$$(links);
 this.attache($(active));
 },

 attache: function(active) {
  var cli = Cookie.read(this.links[0].getParent('ul').getAttribute('id'));
  if (cli) {
   $(cli).addClass('active');
  } else {
   active.addClass('active');
  }
  this.links.each(function(link){
   link.addEvent('click', function(event){
    if(event) {
     event.stop();
     event.target.getParent('ul').getChildren('li').removeClass('active');
     event.target.getParent().addClass('active');
     Cookie.write(event.target.getParent('ul').getAttribute('id'),event.target.getParent('li').getAttribute('id'),{domain: 'your.domain.name', duration: 0, path: '/'});
    }
    this.progress(this.container);
    JsHttpRequest.query(link.get('id'),null,
    function(result,errors) {
     this.display(result,errors)
    }.bind(this),
    true)
   }.bind(this));

   if(link.getParent().hasClass('active')) {
    link.fireEvent('click');
   }
  },this);
 },

 display: function(result,errors) {
  this.container.set('html','');
  if(result) {
    this.container.set('html',result.content);
  } else {
    this.container.set('html','В настоящее время невозможно получить данные для отображения. Попробуйте еще раз позднее.');
  }
 },

 progress: function(container) {
  var pdiv = new Element('div');
  pdiv.setStyle('text-align','center');
  pdiv.set('html','<img src="'+DIR_STATIC_SKIN+'/img/loader.gif">');
  container.set('html','');
  pdiv.inject(container);
 }

});


В классе четыре функции:

1.Конструктор initialize: Первый аргумент — идентификатор (а лучше объект Element) div'а куда выводится содержимое активного таба. Второй аргумент — идентификатор (а лучше объект Elements) группы ссылок-переключателей табов. Третий — идентификатор (а лучше объект Element) активного «по умолчанию» таба (тег li).
ПРИМЕЧАНИЕ: Активность таба задается через класс тега li class=«active». В списке допускается только один тег li с таким классом в каждый текущий момент.

2.Функция attache: которая вызывается из конструктора и по сути выполняет всю основную работу.

3.Необязательная функция progress: которая показывает крутилку пока мы ждем ответа от бекенда.

4.display: функция, которая вставляет ответ от сервера в наш div с содержимым текущего таба.

Ну и на последок про бэкэнд. PHP-скрипты, выполняемые на стороне сервера следует класть в стандартное место, а именно в {$DIR_WEB_ROOT}/include/ajax. Впрочем дело ваше. Темплата php-скрипта выглядит где-то так:

<?php
set_include_path(get_include_path().PATH_SEPARATOR.dirname(dirname(dirname(__FILE__))));
chdir(dirname(dirname(dirname(__FILE__))));
require_once("./config/config.ajax.php");
$content = "";
// Тут получаем данные и вставляем их в шаблон.


$content=$oEngine->Viewer_Fetch("имя_шаблона.tpl");
$GLOBALS['_RESULT'] = array(
"content" => $content
);
?>


Содержимое $content формируется аналогично обработчикам экшенов за той лишь разницей что нужно использовать конструкцию вида $oEngine->Имя_метода/свойства вместо $this->Имя_метода/свойства. И не забыть в конце заполнить $content через вызов:
$content=$oEngine->Viewer_Fetch(«имя_шаблона.tpl»);

Вот в общем-то и все.

PS
Стилевое оформление у каждого свое.

BUGS
1.Этот класс «условно тестировался» на Opere, Firefoxe и IE последних и не очень :) версий.
2. Для более правильной работы с куки в вызов Cookie.write
необходимо добавить опции в виде
{domain: 'your.domain.name', duration: 0, path: '/'}.

При этом используется только одно значение куки в домене your.domain.name вне зависимости от пути. Куки хранится в течение одной сессии.

4 комментария

avatar
А на реализацию где посмотреть?
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.