Цель лекции: Изучить готовые методы Joomla для генерации и отображения элементов XHTML и поведений JavaScript.

 

Основной метод класса JHTML

Joomla содержит методы для генерации и отображения элементов XHTML и поведений JavaScript. Эти методы вызываются с помощью

mixed _(string $type)

 

Несмотря на то, что в прототипе метода JHTML::_() указан всего один параметр, на практике их, как правило, бывает больше. Они интерпретируются так: по первому параметру метод _() определяет, какой метод необходимо вызвать, а остальные параметры передаются в этот метод.

Параметр $type может быть трех видов:

  1. Название метода самого класса JHTML. Например, $type = 'image' приведет к вызову JHTML::image().
  2. <имя файла>.<имя метода>. Будет вызван метод поддерживающего класса JHTML<Имя файла>.<имя метода>(). В имени поддерживающего класса первая буква <имени файла> станет заглавной. Например, если $type='select.genericlist', то будет вызван метод JHTMLSelect::genericlist().
  3. <префикс>.<имя файла>.<имя метода> и будет вызван метод <префикс>.<Имя файла>.<имя метода>().

Методы класса JHTML

Класс JHTML содержит восемь методов для вывода элементов XHTML.

Поле для ввода даты и пиктограмма, по щелчку на которой появляется календарь
string calendar(string $value, string $name, string $id, 
 string $format = '%Y-%m-%d', array $attribs = null)

 

где:

$value - значение даты;
$name - имя текстового поля;
$id - id текстового поля;
$format - формат даты;
$attribs - дополнительные атрибуты, которые должны быть выведены в теге <input>.

Для примера выведем текущую дату (рис. 3.1):

echo JHTML::_('calendar', date('Y-m-d',time()), 'created', 'created', 
 '%Y-%m-%d', array('size'=>10,'style'=>"class='inputbox'"));

 



03 01


Рис. 3.1.  Поле для ввода даты и пиктограмма для вывода календаря

Строка, содержащая дату в заданном формате и часовом поясе
string date(string $input = 'now', string $format = null, mixed $tz = true, bool $gregorian=false)

 

где:

$input - строка в формате, подходящем для функции date();
$format - формат, к которому необходимо привести дату;
$tz - одна из временных зон, поддерживаемых PHP (их список можно найти на странице http://www.php.net/manual/ru/timezones.php). Кроме того, $tz может иметь логическое значение: при $tz=true временная зона берется из настроек пользователя, при $tz=false - из настроек сервера;
$gregorian - при false для форматирования даты будет использоваться локальный календарь.

Для примера выведем текущую дату:

echo JHTML::_('date',date('Y-m-d',time()), 'Y-m-d h:m', 'Europe/Moscow', false);

 

Элемент <iframe></iframe>
string iframe(string $url, string $name, array $attribs = null, string $noFrames = '')

 

где

$url - относительный URL, будущее значение атрибута src;
$name - название будущего элемента <iframe>;
$attribs - ассоциативный массив атрибутов будущего тега <iframe>;
$noFrames - содержимое будущего тега: текст, который будет показан, если браузер не поддерживает тег <iframe>.

Пример:

echo JHTML::_('iframe','index.php', 'myelement', array('width'=>500,'height'=>300), 
'Ваш браузер не поддерживает плавающие фреймы');

 

Элемент <img></img>
string image(string $file, string $alt, mixed $attribs = null, bool $relative = false, bool $path_only = false)

 

где

$file - абсолютный или относительный URL изображения;
$alt - альтернативный текст;
$attribs - ассоциативный массив атрибутов будущего тега (может быть задан сразу в виде строки, например: "width="100%" height="100%"");
$relative - перебирать ли варианты пути к файлу;
$path_only - возвращать ли только путь к изображению или тег <img> со всеми атрибутами.

Для методов image(), script() и stylesheet() будет выполнена следующая процедура поиска файла. Если $file начинается с "http", то метод просто вернет $file. В противном случае он производит поиск файла, перебирая возможные варианты его названия в зависимости от браузера пользователя. Например, для значения "/pics/pic.png" и браузера Mozilla 5.0 будут перебираться варианты "/pics/pic.png", "/pics/pic_mozilla.png", "/pics/pic_mozilla_5.png", "/pics/pic_mozilla_5_0.png". При $relative=true перебираются также различные варианты пути к файлу в папке текущего шаблона и папке /media. В противном случае метод будет искать файл JPATH_ROOT/<имя файла> для каждого варианта названия файла.

Например, следующий код

echo JHTML::_('image','req.png','Восклицательный знак', array('width'=>25,'height'=>25), true, false);

 

выведет

<img src="/joomla/templates/beez_20/images/req.png" alt="Восклицательный знак" width="25" height="25"/>

 

Если последним параметром указать true, то эта же строка выведет на экран

/joomla/templates/beez_20/images/req.png

Обратите внимание, что этот путь мы не задавали, его обнаружил метод image().

Элемент <a></a>
string link(string $url, string $text, array $attribs = null)

 

где:

$text - текст ссылки;
$attribs - ассоциативный массив атрибутов будущего тега.

Пример:

echo JHTML::_('link','index.php','На главную страницу', array('title'=>'На главную','id'=>'linktomainpage'));

 

Элемент <script></script>
mixed script(string $file, bool $framework = false, bool $relative = false, 
 bool $path_only = false, bool $detect_browser = true)

 

где

$file - путь к файлу;
$framework - загружать ли фреймворк Javascript;
$path_only - возвращать путь к файлу или добавить все найденные файлы к текущему документу;
$detect_browser - определять ли браузер пользователя для включения файлов Javascript для этого браузера.

При $path_only=false метод не возвращает никакого значения.

Пример:

echo JHTML::_('script', 'media/system/js/calendar.js', false, false, true, false);

 

Элемент <link rel="stylesheet" style="text/css"/>
mixed stylesheet(string $file, array $attribs = array(), bool $relative = false, 
 bool $path_only = false, bool $detect_browser = true)

 

Все параметры аналогичны рассмотренным выше.

Пример:

echo JHTML::_('stylesheet', 'media/system/css/system.css', 
array("title"=>"Название стиля","media"=>"screen, print"), false, true, false);

 

Всплывающая подсказка
string tooltip(string $tooltip, mixed $title = '', string $image = 'tooltip.png', string $text = '', string $href = '', 
string $alt = 'Tooltip', string $class = 'hasTip')

 

где

$tooltip - текст подсказки;
$title - название подсказки или ассоциативный массив с ключами title, image, text, href, alt и соответствующими значениями;
$image - изображение, для которого будет выводиться подсказка (если не задано значение $text);
$text - текст, для которого будет выводиться подсказка (если не задано значение $image);
$href - URL, на который будет произведен переход по щелчку на изображение или текст;
$alt - значение атрибута alt тега <img>;
$class - название класса элемента <span>, в который будет заключен тег <img>.


Изображение с подсказкой:

echo JHTML::tooltip('Текст подсказки', 'Заголовок подсказки', 'tooltip.png', '', 'http://www.mysite.ru');

 

Текст с подсказкой:

echo JHTML::tooltip('Текст подсказки', 'Заголовок подсказки', '',
  'Наведите на этот текст курсор мыши, чтобы увидеть подсказку');

 

Поддерживающие классы

Рассмотрим некоторые методы поддерживающих классов. Полный список этих методов можно найти в документации, однако на текущий момент она не достаточно полная и содержит ошибки, поэтому для детальной справки по какому-либо методу вы можете обратиться напрямую к исходным кодам в папке /libraries/joomla/html/html.

JHTMLBehavior

Методы этого класса загружают код Javascript в заголовок документа. Методы JHTMLBehavior позволяют вывести календарь, дерево элементов, файловый загрузчик и некоторые другие элементы управления. Рассмотрим один из методов, позволяющий вывести всплывающее модальное окно без перезагрузки страницы:

void modal(string $selector = 'a.modal', array $params = array())

 

где

$selector - селектор класса;
$params - массив параметров, ключи которого могут быть следующими: ajaxOptions, size, shadow, onOpen, onClose, onUpdate, onResize, onShow, onHide.

В следующем примере выводятся две ссылки. При нажатии на первую из них появляется всплывающее окно с изображением, на вторую - с веб-страницей.

<?php
  JHTML::_('behavior.modal'); 
?>
<a href="/media/system/images/notice-info.png" 
class="modal" rel="{size: {x: 100, y: 100}, 
handler:'iframe'}" >Щелкните, чтобы увидеть изображение</a><br/>
<a href="http://www.mysite.ru" class="modal" 
rel="{size: {x: 700, y: 500}, handler:'iframe'}" >Щелкните, чтобы открылось окно с веб-страницей</a>

 

Первое окно выглядит так, как на рис. 3.2.



03 02sm


увеличить изображение
Рис. 3.2.  Модальное окно

JHTMLEmail

Содержит один метод для скрытия адреса электронной почты в целях его защиты от спам-ботов:

string cloak(string $mail, bool $mailto=1, string $text='', bool $email=1)

 

где

$mail - e-mail;
$mailto - выводить ли e-mail в виде ссылки <a href="mailto:name@server.com">…</a> или в виде текста;
$text - текст этой ссылки;
$email - является ли $text адресом электронной почты.

Пример:

echo JHtml::_('email.cloak', 'admin@mysite.ru', 1, 'Написать администратору', 0);

 

JHTMLForm

Содержит один метод, который возвращает код скрытого поля формы для уменьшения риска CSRF-атак:

string token()

 



Именем получившегося элемента формы станет сгенерированная случайным образом строка, которая используется для проверки того, что запрос был сделан из конкретных формы и сессии.

Для предотвращения CSRF-атак вставляйте в каждую форму своего компонента строку:

<?php echo JHTML::_('form.token');?>

 

JHTMLGrid

Методы данного класса используются для вывода в таблице в панели управления таких элементов, как чекбокс, пиктограмма для переключения состояния "опубликовано"/"не опубликовано", для отображения заголовка столбца как ссылки для сортировки по этому столбцу и др.

Таблица должна располагаться внутри формы под названием adminForm, обязательно включающей два скрытых поля: boxchecked со значением по умолчанию 0 и task.

Для создания чекбокса используется метод

mixed id(int $rowNum, int $recId, bool $checkedOut=false, string $name='cid')

 

где

$rowNum - номер строки в таблице;
$recId - id записи;
$checkedOut - отмечен ли элемент;
$name - имя элемента формы.

Метод возвращает html-код чекбокса, если элемент не отмечен, и пустую строку в противном случае.

Для создания пиктограммы, по щелчку на которой можно изменять значение поля published с 0 на 1 и обратно, используется

string published(mixed $value, int $i, string $img1 = 'tick.png', string $img0 = 'publish_x.png', string $prefix='')

 

где

$value - объект или только значение поля published;
$i - номер строки в таблице;
$img1 - изображение при published = 1;
$img0 - изображение при published = 0;
$prefix - префикс, который будет добавлен к названиям по умолчанию задач publish/unpublish.

Для примера выведем элементы массива $rows как строки таблицы, добавив для каждой записи ячейки с чекбоксом и значком "опубликовано"/"не опубликовано":

$k = 0;
for ($i = 0, $n = count($rows); $i < $n;  $i ++)       
{
  $row = &$rows[$i];
  ?>
  <tr class="<?="row$k"?>">
    <td><?=JHTML::_('grid.id', $i, $row->id)?></td>
    <td><?=$row->name?></td>
    <td align="center"><?=JHTML::_('grid.published', $row, $i)?></td> 
  </tr>
  <?php
  $k = 1 - $k;
}
   

 

Пример результата приведен на рис. 3.3.



03 03sm


увеличить изображение
Рис. 3.3.  Чекбокс и пиктограмма "опубликовано/не опубликовано"Обратите внимание, что методы класса JHTMLGrid лишь отображают какой-либо элемент, но не добавляют код для его обработки. В приведенном выше примере кнопки "опубликовано"/"не опубликовано" отображаются, но не работают. Чтобы это исправить, необходимо зарегистрировать задачи publish и unpublish (если вы не изменили их названия, задав какой-либо префикс) и написать функцию для их обработки, которая будет вызывать метод JTable::publish().

JHTMLImage

Содержит два метода для поиска изображения в фронтенде и бэкенде соответственно. Каждый из них ищет либо изображение из директории images текущего шаблона сайта/панели управления, либо, если файла с заданным именем там нет, изображение из заданной директории.

string site(string $file, string $folder = '/images/system/', int $altFile = null, string $altFolder = '/images/system/', 
string $alt = null, array $attribs = null, bool $asTag = true)
string administrator(string $file, string $folder = '/images/', int $altFile = null, string $altFolder = '/images/', 
string $alt = null, array $attribs = null, bool $asTag = true)

 

где

$file - имя файла;
$folder - путь к файлу. Будет использован, если в директории images текущего шаблона не нашлось файла с заданным именем;
$altFile - если не задано, то используются значения $file и $folder, при $altFile = -1 метод возвращает пустую строку, при других значениях используются $altFile и $altFolder;
$altFolder - другой путь к файлу;
$alt - будущее значение атрибута alt;
$attribs - ассоциативный массив атрибутов;
$asTag - вернуть весь тег <img> с его содержимым или только путь.

Пример:

echo JHTML::_('image.site', 'notice-info.png', '/media/system/images/');

 

JHTMLList

Методы класса JHTMLList используются для создания списков некоторых значений.


Список для выбора одного из существующих в Joomla уровней доступа
string accesslevel(object &$row)

 

где $row - объект, имеющий поле access.

Пример:

$query = 'SELECT id,access FROM #__content WHERE id = 1';
$db = JFactory::getDBO();
$db->setQuery($query);
$article = $db->loadObject();
echo JHTML::_('list.accesslevel', $article);

 

Результат показан на рис. 3.4.



03 04


Рис. 3.4.  Список для выбора уровня доступа


Список для выбора изображения
array images(string $name, string $active = NULL, string $javascript = NULL, 
string $directory = NULL, string $extensions =  "bmp|gif|jpg|png")

 

где

$name - имя поля;
$active - выбранный по умолчанию элемент;
$javascript - дополнительный код Javascript, который будет выведен внутри тега <select>;
$directory - директория, в которой хранятся изображения. Например: components/com_mycomponent/images. Если значение не задано, будет использоваться директория images;
$extensions - список допустимых расширений

Например, вывод на экран JHTML::_('list.images','imglist') приведет к отображению такого списка (рис. 3.5).



03 05


Рис. 3.5.  Список для выбора изображения


Список незаблокированных пользователей
string users(string $name, string $active, int $nouser = 0, string $javascript = NULL, string $order = 'name', string $reg = 1)

 

где

$name - название элемента <select>;
$active - выбранный по умолчанию пользователь;
$nouser - добавлять ли пункт, означающий отсутствие пользователя;
$javascript - дополнительный код Javascript, который будет выведен внутри тега <select>;
$order - имя поля для сортировки списка;
$reg - исключить пользователей из группы "Зарегистрированные".

Например, вывод на экран JHTML::_('list.users','usrlist','42', 1, NULL, 'id', $reg = 1) приведет к отображению такого списка (рис. 3.6).



03 06


Рис. 3.6.  Список для выбора пользователя


Список категорий
string category(string $name, string $extension, string $selected = NULL, string $javascript = NULL, 
string $order = null, int $size = 1, bool $sel_cat = 1)

 

где

$name - название элемента <select>;
$extension - расширение, к которому относятся категории;
$selected - выбранное по умолчанию значение;
$javascript - дополнительный код Javascript, который будет выведен внутри тега <select>;
$size - высота списка (значение атрибута size тега <select>);
$sel_cat - при null строки "Выберите категорию" в списке не будет.

Пример:

echo JHTML::_('list.category', 'catlist', 'com_content', 2, 'onclick="someFunc()"', 'id', 1, 1);

 

Данный код выведет на экран список, представленный на рис. 3.7.



03 07


Рис. 3.7.  Список для выбора категории


JHTMLMenu

Класс используется для отображения элементов меню и не представляет интереса для использования в расширениях.

JHTMLSelect

Класс JHTMLSelect используется для генерации кода списков.

Выпадающий список
string genericlist(array $data, string $name, mixed $attribs = null, string $optKey = 'value', 
string $optText = 'text', mixed $selected = null, mixed $idtag = false, bool $translate = false)

 

где

$data - массив данных для отображения. Каждый элемент может быть сгенерирован с помощью метода JHTMLSelect.option() или другим образом;
$name - имя элемента HTML;
$attribs - дополнительные атрибуты тега <select>. Могут быть заданы как массив атрибутов или массив опций с ключами list.attr, id, list.select и др.;
$optKey - из какого поля объекта, представляющего собой элемент массива $data, брать значение элементов <option>. При $optkey = null будут использованы ключи массива;
$optText - из какого поля объекта, представляющего собой элемент массива $data, брать текст элементов <option>. Тег <option> формируется так: <option value="$optkey">$optText</option>;
$selected - значение выбранного по умолчанию элемента;
$idtag - id тега <select>;
$translate - пропускать ли текст через функцию JText::_().

Пример:

$query = 'SELECT id,title FROM #__content';
$db = JFactory::getDBO();
$db->setQuery($query);
$content = $db->loadObjectList();
echo JHTML::_('select.genericlist', $content, 'genlist', 'size='.count($content), 'id', 'title', 2);

 

Так как мы передали в функцию genericlist() $selected=2, то в сгенерированном списке по умолчанию выделен элемент с id, равным 2 (рис. 3.8).



03 08


Рис. 3.8.  Список для выбора материала


Объект, представляющий элемент <option> выпадающего списка
object option(string $value, string $text = '', mixed $optKey = 'value', string $optText = 'text', bool $disable = false)

 

где

$value - значение элемента <option>;
$text - текст элемента;
$optKey - если это строка, то имя того поля возвращаемого объекта, в котором будет храниться значение элемента <option>. Если массив, то это параметры. Возможные ключи массива: attr, disable, label, option.attr, option.disable, option.key, option.label, option.text;
$optText - имя того поля возвращаемого объекта, в котором будет храниться текст элемента <option>;
$disable - добавлять ли к тегу атрибут disable.

Рассмотрим пример:

$query = 'SELECT id,title FROM #__content';
$db = JFactory::getDBO();
$db->setQuery($query);
$content = $db->loadObjectList();
foreach ($content as $c)
  $data[] = JHTML::_('select.option', $c->id, $c->title, 'my_value', 'my_text');
echo JHTML::_('select.genericlist', $data, 'genlist', 'size='.count($data), 'my_value', 'my_text', 2);

 

В данном примере для каждого материала сайта с помощью метода JHTMLSelect.option() создается объект, представляющий элемент <option>:

JObject Object ([_errors:protected]=>Array () [my_value]=>1 [my_text]=>Материал #1 [disable]=>)

 

Таким образом, значения $optKey и $optText, переданные в функцию option(), стали названиями полей получившегося объекта, а значения $c->id и $c->title - значениями этих полей. Теперь в функцию JHTMLSelect.genericlist() необходимо передать те же названия полей, что и в option(). Если не передать их, то функция genericlist() будет по умолчанию искать в объектах массива $data поля $value и $text, которых там нет.

Результат работы данного примера будет выглядеть так же, как и результат предыдущего.

Список целых чисел
string integerlist(int $start, int $end, int $inc, string $name, mixed $attribs = null, mixed $selected = null, string $format = '')

 

где

$start - первое число последовательности;
$end - последнее число последовательности;
$inc - шаг;
$name - имя тега;
$attribs - массив атрибутов тега;
$selected - значение выбранного по умолчанию элемента;
$format - формат вывода числа для функции printf().

Пример:

echo JHTML::_('select.integerlist', 1, 10, 1, 'intlist', 'size=10', 3, '%02d');

 

Этот код выведет список, представленный на рис. 3.9.



03 09


Рис. 3.9.  Список для выбора числа


Группа переключателей
string radiolist(array $data, string $name, mixed $attribs = null, mixed $optKey = 'value', string $optText = 'text', 
string $selected = null, bool $idtag = false, bool $translate = false)

 

где

$data - массив объектов;
$name - имя, общее для всех переключателей;
$attribs - дополнительные атрибуты тега <input> (могут быть заданы сразу в виде строки);
$optKey - из какого поля объекта, представляющего собой элемент массива $data, брать значения элементов <input>;
$optText - из какого поля объекта, представляющего собой элемент массива $data, брать текст элементов <input>;
$selected - значение выбранного по умолчанию элемента;
$idtag - префикс id сгенерированных тегов. Для каждого тега <input> id станет равным $idtag<key>, где <key> - значение поля под названием $optKey в соответствующем объекте из массива $data. Если $idtag не задан, то вместо него будет использовано значение $name. В Joomla 1.7 в этой функции имеется ошибка: если объекты массива $data содержат поле с названием id, то к каждому элементу <input> добавляется второй id со значением, взятым из этого поля;
$translate - пропускать ли текст через функцию JText::_().

Пример:

$query = 'SELECT id,title FROM #__content';
$db = JFactory::getDBO();
$db->setQuery($query);
$content = $db->loadObjectList();
echo JHTML::_('select.radiolist', $content, 'radlist', 'class="inputbox"', 'id', 'title', 2, 'radlist', false);
                

 

Результат показан на рис. 3.10.



03 10


Рис. 3.10.  Группа переключателей

Практика

Обработка категорий

В единственном вопросе, который хранится в нашей базе, в поле id_cat стоит значение 1. Оно должно означать id категории. Добавим таблицу и код для работы с категориями.

Создание таблицы для категорий

Выполните следующий SQL-запрос, чтобы создать таблицу для хранения категорий:

CREATE TABLE `jos_myquestions_categories`
(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`desc` TEXT NOT NULL DEFAULT ''
)

 

Добавьте записи в эту таблицу:

INSERT INTO `jos_myquestions_categories` VALUES (NULL,'Без категории',''), 
 (NULL,'Риторические вопросы','Вопросы, не требующие ответа')

 

Зайдите в phpMyAdmin и убедитесь, что таблица jos_myquestions_categories содержит две записи (рис. 3.11).



03 11


Рис. 3.11.  Таблица базы данных, хранящая данные о категорияхТаким образом, сейчас все вопросы, для которых в поле id_cat стоит значение 1, относятся к категории "Без категории".

Создание класса таблицы

Создайте файл /administrator/components/com_myquestions/tables/category.php:

<?php
defined('_JEXEC') or die('Restricted access');
class TableCategory extends JTable
{
  var $id = null;
  var $name = null;
  var $desc = null;
  function __construct($db)
  {
    parent::__construct('#__myquestions_categories', 'id', $db);
  }
}
?>

 

Вывод списка категорий

Добавьте в файл admin.myquestions.php функцию showCategories():

function showCategories($option)
{
    $db = JFactory::getDbo();
    $query = "SELECT * FROM #__myquestions_categories";
    $db->setQuery($query);
    $rows = $db->loadObjectList();
    if ($db->getErrorNum())
    {
        echo $db->stderr();
        return false;
    }
    HTML_questions::showCategories($option, $rows);
}

 

Эта функция аналогична функции showQuestions(), рассмотренной ранее.

В файл admin.myquestions.html.php в класс HTML_questions добавьте еще одну функцию:

  function showCategories($option, &$rows) 
{ 
?>
  <form action="index.php" method="post" name="adminForm">
    <table class="adminlist">
      <thead>
        <tr>
          <th width="20">
            <input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count($rows);?>);"/>
          </th>
          <th class="title" width="30%"><?php echo JText::_('COM_MYQUESTIONS_CATEGORY_NAME');?></th>
          <th><?php echo JText::_('COM_MYQUESTIONS_CATEGORY_DESC');?></th>
        </tr>
      </thead> 
      <?php
        jimport('joomla.filter.output');
        $k = 0;       
        for  ($i = 0,  $n = count($rows); $i < $n;  $i ++)       
        {
          $row = &$rows[$i];
          $checked = JHTML::_('grid.id', $i, $row->id);
          $link = JFilterOutput::ampReplace('index.php?option=' .$option . '&task=editcat&cid[]='. $row->id);
      ?>
      <tr class="<?php echo "row$k";?>">
        <td><?=$checked?></td>
        <td><?='<a href="'.$link.'">'.$row->name.'</a>'?></td>
        <td><?=$row->desc?></td>
      </tr>
      <?php
        $k = 1 - $k;
      }
      ?>
    </table>
    <input type="hidden" name="option" value="<?php echo $option;?>"/>
    <input type="hidden" name="task" value=""/>
    <input type= "hidden" name="boxchecked" value="0"/>
  </form>
<?php
}

 

Данная функция также аналогична одноименной функции для отображения списка вопросов.

Добавьте в переключатель switch в файле admin.myquestions.php обработку новой задачи:

case 'showcat':
   showCategories($option);
   break;

 

Добавьте в файл /administrator/language/ru-RU/ru-RU.com_myquestions.ini код:

COM_MYQUESTIONS_CATEGORY_NAME="Название категории"
COM_MYQUESTIONS_CATEGORY_DESC="Описание категории"

 

Перейдя по ссылке http://localhost/joomla/administrator/index.php?option=com_myquestions&task=showcat, вы уже можете увидеть список категорий.

Однако пока над списком будет отображаться старая панель инструментов, которую мы создали для списка вопросов. Поэтому необходимо также создать новые панели инструментов для работы с категориями. Откройте файл toolbar.myquestions.php и добавьте в переключатель switch следующий код:

case 'showcat':
  TOOLBAR_myquestions_categories::_DEFAULT();
  break;

 

Как видите, мы добавили обработку задачи showcat - отображение списка категорий. Соответственно, вызывается функция _DEFAULT() класса TOOLBAR_myquestions_categories. Напишем код этого класса. Добавьте в файл toolbar.myquestions.html.php код:

class TOOLBAR_myquestions_categories
{
  function _DEFAULT()
  {
    JToolBarHelper::title(JText::_('COM_MYQUESTIONS_TOOLBAR_TITLE_CATEGORIES'), 
     'generic.png');
    JToolBarHelper::addNew('addcat');
    JToolBarHelper::editList('editcat');     JToolBarHelper::deleteList
    (JText::_('COM_MYQUESTIONS_TOOLBAR_REMOVE_CATEGORIES_CONFIRMATION'), 
     'removecat');  }
}

 

Таким образом, панель инструментов для списка категорий будет содержать три кнопки: "Создать", "Изменить" и "Удалить".

Добавьте в файл /administrator/language/ru-RU/ru-RU.com_myquestions.ini код:

COM_MYQUESTIONS_TOOLBAR_TITLE_CATEGORIES="Управление категориями вопросов"
COM_MYQUESTIONS_TOOLBAR_REMOVE_CATEGORIES_CONFIRMATION="Вы действительно хотите удалить эти категории?"

 

Теперь по ссылке http://localhost/joomla/administrator/index.php?option=com_myquestions&task=showcat видим список категорий (рис. 3.12).



03 12sm


увеличить изображение
Рис. 3.12.  Список категорий в бэкенде

Создание, редактирование и удаление категорий

При нажатии на кнопки "Создать" или "Изменить", расположенные над списком категорий, должна отображаться другая панель инструментов. Для этого добавьте в класс TOOLBAR_myquestions_categories функцию _NEW():

class TOOLBAR_myquestions_categories
{
  function _NEW()
  {
    JToolBarHelper::title(JText::_('COM_MYQUESTIONS_TOOLBAR_TITLE_CATEGORIES'), 
     'generic.png');
    JToolBarHelper::save('savecat');
    JToolBarHelper::apply('applycat');    
    JToolBarHelper::cancel('showcat');
  }
  function _DEFAULT()
  {
    JToolBarHelper::title(JText::_('COM_MYQUESTIONS_TOOLBAR_TITLE_CATEGORIES'), 
     'generic.png');
    JToolBarHelper::addNew('addcat');
    JToolBarHelper::editList('editcat');
    JToolBarHelper::deleteList(JText::_('COM_MYQUESTIONS_TOOLBAR_REMOVE_CONFIRMATION'),
      'removecat');
  }
}

 

Запишем в файле toolbar.myquestions.php, что при обработке задач addcat и editcat должна отображаться панель инструментов _NEW. Измените код этого файла так:

<?php
defined('_JEXEC') or die('Restricted access');
require_once(JApplicationHelper::getPath('toolbar_html'));
switch($task)
{
  case 'reply':
    TOOLBAR_myquestions::_REPLY();
    break;
  default:
    TOOLBAR_myquestions::_DEFAULT();
    break;
  case 'showcat':
    TOOLBAR_myquestions_categories::_DEFAULT();
    break;
  case 'addcat':
  case 'editcat':
    TOOLBAR_myquestions_categories::_NEW();
    break;
}
?>
   

 

Теперь добавим обработку всех перечисленных в файле toolbar.myquestions.html.php задач. Откройте файл admin.myquestions.php и добавьте в переключатель switch код:

case 'addcat':
case 'editcat':
    editCategory($option);
    break;
case 'savecat':
case 'applycat':
    saveCategory($option, $task);
    break;
case 'removecat':
    removeCategories($option);
    break;

 

Добавьте перечисленные функции в файл admin.myquestions.php:

function editCategory($option)
{
    $row = JTable::getInstance('Category','Table');
    $cid = JRequest::getVar('cid', array(0), '', 'array');
    $id = $cid[0];
    $row->load($id);
    HTML_questions::editCategory($row, $option);
}
function saveCategory($option, $task)
{
    $row = JTable::getInstance('category', 'Table');
    if (!$row->bind(JRequest::get('post')))
    {
        echo "<script> alert('".$row->getError()."');
          window.history.go(-1); </script>\n";
        exit();
    }
    $row->desc = JRequest::getVar('desc', '', 'post', 'string', JREQUEST_ALLOWRAW);
    
    if (!$row->store())
    {
        echo "<script> alert('".$row->getError()."'); 
         window.history.go(-1); </script>\n";
        exit();
    }
    
    global $app;
    if ($task == 'savecat')
        $app->redirect('index.php?option='.$option.'&task=showcat', 
         JText::_('COM_MYQUESTIONS_CATEGORY_SAVED'));
    else
        if ($task == 'applycat')
            $app-
            >redirect('index.php?option='.$option.'&task=editcat&cid[]='.$row-
            >id, JText::_('COM_MYQUESTIONS_CATEGORY_SAVED'));
    }
    function removeCategories($option)
    {
        global $app;
        $cid = JRequest::getVar('cid', array(), '', 'array');
        $db = JFactory::getDbo();
        if(count($cid))
        {
            $cids = implode(',', $cid);
            $query = "DELETE FROM #__myquestions_categories WHERE id IN ($cids)";
            $db->setQuery($query);
            if (!$db->query())
            {
                echo "<script> alert('".$db->getErrorMsg()."'); 
                 window.history.go(-1); </script>\n";
            }
        }
        $app->redirect('index.php?option=' . $option . '&task=showcat', 
         JText::_('COM_MYQUESTIONS_CATEGORY_DELETED'));
    }

 

 Листинг .

Добавьте в файл admin.myquestions.html.php в класс HTML_questions метод editCategory() для отображения формы редактирования категории:

function editCategory ($row, $option)
{
  $editor = JFactory::getEditor();
  ?>
  <form action = "index.php" method="post" name="adminForm"
    id="adminForm">
    <fieldset class="adminform">
      <table class="admintable" width=100%>
        <tr>
          <td width="100" class="key">
              <?php echo JText::_('COM_MYQUESTIONS_CATEGORY_NAME');?>:
          </td>
          <td>
            <input class="text_area" type="text" name="name" id="name" 
             size="50" maxlength="255" value="<?php echo $row->name;?>"/>
          </td>
        </tr>
        <tr>
          <td width="100" class="key">
            <?php echo JText::_('COM_MYQUESTIONS_CATEGORY_DESC');?>:
          </td>
          <td>
            <?php
              echo $editor->display('desc',  $row->desc,'100%', '250', '40', '10');?>
          </td>
        </tr>
      </table>
    </fieldset>
    <input type="hidden" name="id" value="<?php echo $row->id;?>"/>
    <input type="hidden" name="option" value="<?php echo $option;?>"/>
    <input type="hidden" name="task" value=""/>
  </form>
<?php
}

 

Наконец, добавьте в файл /administrator/language/ru-RU/ru-RU.com_myquestions.ini код:

COM_MYQUESTIONS_CATEGORY_SAVED="Категория сохранена"
COM_MYQUESTIONS_CATEGORY_DELETED="Категории успешно удалены"

 

Убедитесь, что все кнопки обеих панелей инструментов работают корректно.

Присвоение вопросу какой-либо категории

Добавим в форму ответа на вопрос выпадающий список для выбора категории.

Откройте файл admin.myquestions.php и измените код функции replyToQuestion() следующим образом:

    function replyToQuestion($option)
{
    $row = JTable::getInstance('Question','Table');
    $cid = JRequest::getVar('cid', array(0), '', 'array');
    $id = $cid[0];
    $row->load($id);
    $db =  JFactory::getDBO();
    $query = 'SELECT name AS text, id AS value FROM #__myquestions_categories';
    $db->setQuery($query);
    $categories = $db->loadObjectList();
    $list_cat = JHTML::_('select.genericlist',  $categories,  'id_cat', 
    ' class="inputbox" ', 'value', 'text', $row->id_cat);
    HTML_questions::replyToQuestion($row, $option, $list_cat);
}

 

В файле admin.myquestions.html.php измените прототип функции HTML_questions::replyToQuestion() так:

function replyToQuestion ($row, $option, $list_cat)

 

Наконец, в коде этой функции измените фрагмент, в котором раньше выводилось текстовое поле с id категории, так:

<tr>
  <td width="100" class="key">
    <?php echo JText::_('COM_MYQUESTIONS_CATEGORY');?>:
    </td>
  <td>
    <?=$list_cat?>
  </td>
</tr>

 

Перейдите к странице ответа на вопрос и убедитесь, что отображается выпадающий список для выбора категории (рис. 3.13).



03 13


Рис. 3.13.  Выбор категории вопроса в бэкенде


Ключевые термины

JHTML - класс для вывода элементов XHTML.
JHTMLBehavior - поддерживающий класс, который позволяет вывести календарь, дерево элементов, файловый загрузчик и некоторые другие элементы управления.
JHTMLEmail - поддерживающий класс, содержащий метод для скрытия адреса электронной почты в целях его защиты от спам-ботов.
JHTMLForm - поддерживающий класс, содержащий метод, который возвращает код скрытого поля формы для уменьшения риска CSRF-атак.
JHTMLGrid - поддерживающий класс, позволяющий вывести в таблице в панели управления такие элементы, как чекбокс, пиктограмма для переключения состояния "опубликовано"/"не опубликовано", отобразить заголовок столбца как ссылки для сортировки по этому столбцу и др.
JHTMLImage - поддерживающий класс, содержащий методы для поиска изображения в фронтенде и бэкенде.
JHTMLList - поддерживающий класс для создания списков некоторых конкретных значений.
JHTMLSelect - поддерживающий класс для генерации кода списков.
Основной метод класса JHTML - метод JHTML::_(), который вызывает метод, определяющийся его первым параметром, и передает ему свои остальные параметры.
Поддерживающие классы - классы для вывода элементов XHTML и поведений Javascript.

Краткие итоги

Joomla содержит методы для генерации и отображения элементов XHTML и поведений JavaScript. Эти методы вызываются с помощью метода JHTML::_(). По первому параметру данный метод определяет, какой метод необходимо вызвать, а остальные параметры передаются в этот метод. Таким образом могут быть вызваны как методы самого класса JHTML, так и методы поддерживающих классов.

Методы класса JHTML позволяют вывести следующие элементы: календарь, форматированную дату, элементы <iframe>, <img>, <a>, <script>, <link> и всплывающую подсказку.

Поддерживающие классы используются следующим образом:

  • JHTMLBehavior позволяет вывести календарь, дерево элементов, файловый загрузчик и некоторые другие элементы управления.
  • JHTMLEmail содержит метод для скрытия адреса электронной почты в целях его защиты от спам-ботов.
  • JHTMLForm содержит метод, который возвращает код скрытого поля формы для уменьшения риска CSRF-атак.
  • JHTMLGrid позволяет вывести в таблице в панели управления такие элементы, как чекбокс, пиктограмма для переключения состояния "опубликовано"/"не опубликовано", отобразить заголовок столбца как ссылки для сортировки по этому столбцу и др.
  • JHTMLImage содержит два метода для поиска изображения в фронтенде и бэкенде соответственно.
  • JHTMLList используется для создания списков некоторых конкретных значений.
  • JHTMLSelect используется для генерации кода списков.

Вопросы

  1. Каким образом работает метод JHTML::_()?
  2. Какие элементы могут быть отображены с помощью класса JHTML?
  3. Для чего используется класс JHTMLBehavior?
  4. Для чего используется класс JHTMLEmail?
  5. Для чего используется класс JHTMLForm?
  6. Код каких элементов генерируют методы класса JHTMLGrid?
  7. В чем преимущество использования класса JHTMLImage?
  8. Для чего используются классы JHTMLList и JHTMLSelect?