Лекция 3: Генерация элементов HTML (класс JHTML)
Цель лекции: Изучить готовые методы Joomla для генерации и отображения элементов XHTML и поведений JavaScript.
Основной метод класса JHTML
Joomla содержит методы для генерации и отображения элементов XHTML и поведений JavaScript. Эти методы вызываются с помощью
mixed _(string $type)
Несмотря на то, что в прототипе метода JHTML::_() указан всего один параметр, на практике их, как правило, бывает больше. Они интерпретируются так: по первому параметру метод _() определяет, какой метод необходимо вызвать, а остальные параметры передаются в этот метод.
Параметр $type может быть трех видов:
- Название метода самого класса JHTML. Например, $type = 'image' приведет к вызову JHTML::image().
- <имя файла>.<имя метода>. Будет вызван метод поддерживающего класса JHTML<Имя файла>.<имя метода>(). В имени поддерживающего класса первая буква <имени файла> станет заглавной. Например, если $type='select.genericlist', то будет вызван метод JHTMLSelect::genericlist().
- <префикс>.<имя файла>.<имя метода> и будет вызван метод <префикс>.<Имя файла>.<имя метода>().
Методы класса 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'"));
Рис. 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, то эта же строка выведет на экран
Обратите внимание, что этот путь мы не задавали, его обнаружил метод 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.

увеличить изображение
Рис. 3.2. Модальное окно
JHTMLEmail
Содержит один метод для скрытия адреса электронной почты в целях его защиты от спам-ботов:
string cloak(string $mail, bool $mailto=1, string $text='', bool $email=1)
где
| - e-mail; | |
| $mailto | - выводить ли e-mail в виде ссылки <a href="mailto:name@server.com">…</a> или в виде текста; |
| $text | - текст этой ссылки; |
| - является ли $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.

увеличить изображение
Рис. 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.

Рис. 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).

Рис. 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).

Рис. 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.

Рис. 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).

Рис. 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.
Рис. 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.
Рис. 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).

Рис. 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).

увеличить изображение
Рис. 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).

Рис. 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 используется для генерации кода списков.
Вопросы
- Каким образом работает метод JHTML::_()?
- Какие элементы могут быть отображены с помощью класса JHTML?
- Для чего используется класс JHTMLBehavior?
- Для чего используется класс JHTMLEmail?
- Для чего используется класс JHTMLForm?
- Код каких элементов генерируют методы класса JHTMLGrid?
- В чем преимущество использования класса JHTMLImage?
- Для чего используются классы JHTMLList и JHTMLSelect?