В этой статье я покажу один из путей создания в Joomla 1.5 формы с асинхронной валидацией на сервере. Для этого мы создадим компонент, построенный в соответствие с концепцией MVC, реализованной в Joomla 1.5, в качестве JS-фреймворка будет использоваться mootools 1.2.
В этой статье я не буду углубляться в теорию концепции MVC и ее реализацию в Joomla 1.5. Также я предполагаю, что читатель знаком с общим принципом создания компонентов для этой CMS, если же нет, то можно посмотреть, например, вот это. Возможно, я когда-нибудь напишу статью и об этом, но сейчас мне бы хотелось осветить сабж :)
Требуется создать frontend-компонент, который бы реализовывал асинхронную валидацию на сервере введенных в форму данных. Для осуществления асинхронного обращения к серверу мы будем использовать mootools 1.2.x В Joomla 1.5 уже встроен mootools 1.1, однако, просто подменить файлы с кодом не получится – Joomla станет плохо работать. Но как всегда, хочется использовать современные решения, поэтому, мы не будем задействовать доступный в Joomlа mootools, а подключим свой, последней версии. Конечно, существует риск возникновения конфликных ситуаций, но будем считать, что на фронтенде у нас не будет компонентов, использующих встроенный mootools :) Кроме того, данный способ будет полезен тем, кто хочет использовать какой-нибудь другой JS-фреймворк.
Схема работы нашего компонента будет следующей. При нажатии на кнопку отправки (submit) формы, данные из полей будут асинхронно отправляться на сервер, где их будет «принимать» Контроллер, проверять данные и возвращать ответ в формате JSON, в котором будет содержаться информация о валидности введенных данных. Эта информация будет использоваться на клиенте для отображения с помощью CSS результатов проверки.
Перед тем, как перейти непосредственно к коду, необходимо сделать кое-какие пояснения. Согласно концепции MVC все запросы пользователя к компоненту должны обслуживаться Контроллером (Controller). Получив команду, контроллер «решает», как на эту команду реагировать. В классической схеме Контроллером дается команда Модели (Model) для получения/сохранения/обновления данных, а результат этой команды отображается Видом (View), который «знает» как отобразить данные.
В нашем простейшем компоненте Модели не будет, поэтому соответствующий класс будет пустой, он присутствует в этом примере только с целью демонстрации общей организации кода компонента. Задача Вида – включить необходимые стили и скрипты, и вывести форму. В Контроллере же будет реализована функциональность валидации формы на сервере в виде отдельной задачи (task), которую мы будем вызывать асинхронно.
В папке фронтенд-части нашего компонента (который мы назовем AsyncForm), т.е. в папке /components/com_asyncform у нас будет следующая структура папок и файлов:
В методе check() формируется ответ в формате JSON, который состоит из:
Если все таки хочется использовать встроенный mootools, тогда используйте оператор в строке 12 вместо строки 16.
Обратите внимание на обработчик формы. Такой вид обработчика обусловлен тем, что от сервера нам надо получить лишь строку ответа, без всякой дополнительной html-разметки и т.п. В Joomla 1.0.x для того чтобы вернуть только вывод компонента, надо было использовать index2.php, однако в Joomla 1.5 это не пройдет. Для этих целей в ней предусмотрен параметр format, который для того, чтобы вернуть только вывод компонента, должен быть равен raw.
Здесь ответ, полученный от сервера в виде строки преобразуется в js-объект, после чего анализируется его содержимое и выставляются нужные параметры html-элементам в теле компонента.
Вот, собственно, и все. Надеюсь, данный пост будет кому-нибудь полезен. Комменты, советы и предложения, естественно, приветствуются!
Введение
В этой статье я не буду углубляться в теорию концепции MVC и ее реализацию в Joomla 1.5. Также я предполагаю, что читатель знаком с общим принципом создания компонентов для этой CMS, если же нет, то можно посмотреть, например, вот это. Возможно, я когда-нибудь напишу статью и об этом, но сейчас мне бы хотелось осветить сабж :)
Постановка задачи
Требуется создать frontend-компонент, который бы реализовывал асинхронную валидацию на сервере введенных в форму данных. Для осуществления асинхронного обращения к серверу мы будем использовать mootools 1.2.x В Joomla 1.5 уже встроен mootools 1.1, однако, просто подменить файлы с кодом не получится – Joomla станет плохо работать. Но как всегда, хочется использовать современные решения, поэтому, мы не будем задействовать доступный в Joomlа mootools, а подключим свой, последней версии. Конечно, существует риск возникновения конфликных ситуаций, но будем считать, что на фронтенде у нас не будет компонентов, использующих встроенный mootools :) Кроме того, данный способ будет полезен тем, кто хочет использовать какой-нибудь другой JS-фреймворк.
Реализация
Схема работы нашего компонента будет следующей. При нажатии на кнопку отправки (submit) формы, данные из полей будут асинхронно отправляться на сервер, где их будет «принимать» Контроллер, проверять данные и возвращать ответ в формате JSON, в котором будет содержаться информация о валидности введенных данных. Эта информация будет использоваться на клиенте для отображения с помощью CSS результатов проверки.
Перед тем, как перейти непосредственно к коду, необходимо сделать кое-какие пояснения. Согласно концепции MVC все запросы пользователя к компоненту должны обслуживаться Контроллером (Controller). Получив команду, контроллер «решает», как на эту команду реагировать. В классической схеме Контроллером дается команда Модели (Model) для получения/сохранения/обновления данных, а результат этой команды отображается Видом (View), который «знает» как отобразить данные.
В нашем простейшем компоненте Модели не будет, поэтому соответствующий класс будет пустой, он присутствует в этом примере только с целью демонстрации общей организации кода компонента. Задача Вида – включить необходимые стили и скрипты, и вывести форму. В Контроллере же будет реализована функциональность валидации формы на сервере в виде отдельной задачи (task), которую мы будем вызывать асинхронно.
В папке фронтенд-части нашего компонента (который мы назовем AsyncForm), т.е. в папке /components/com_asyncform у нас будет следующая структура папок и файлов:
+com_asyncform +assets +css -common.css +js -common.js -mootools-1.2.1-core.js +controllers -default.php +models -asyncform.php +views +tmpl -default.php -view.html.php -asyncform.php
asyncform.php
- <?php
- defined( '_JEXEC' ) or die( 'Restricted access' );
- if($controller = JRequest::getVar('controller')) {
- require_once(JPATH_COMPONENT.DS . 'controllers' . DS . $controller . '.php');
- require_once(JPATH_COMPONENT.DS . 'models' . DS . 'asyncform.php');
- require_once(JPATH_COMPONENT.DS . 'views' . DS . $controller . DS . 'view.html.php');
- }
- else {
- require_once(JPATH_COMPONENT.DS . 'controllers' . DS . 'default.php');
- require_once(JPATH_COMPONENT.DS . 'models' . DS . 'asyncform.php');
- require_once(JPATH_COMPONENT.DS . 'views' . DS . 'default' . DS . 'view.html.php');
- }
- // Create the controller
- $classname = 'AsyncformController'.$controller;
- $controller = new $classname;
- $controller->execute(JRequest::getVar('task'));
- $controller->redirect();
- ?>
controllers/default.php
- <?php
- jimport( 'joomla.application.component.controller' );
- class AsyncformController extends JController {
- function __construct($default = array()) {
- parent::__construct($default);
- $this->registerDefaultTask('display');
- $this->registerTask('check', 'check');
- }
- function cancel() {
- $this->setRedirect('index.php');
- }
- function display() {
- $view = new AsyncformView();
- $view->display();
- }
- function check() {
- $isValid = false;
- $res['type'] = '';
- $res['msg'] = '';
- $res['items'] = array();
- $name = substr(JRequest::getVar('name'), 0, 50);
- if(ereg('[а-яА-Яa-zA-Z\-]+$', $name)) {
- $res['items'][] = array('name' => 'name', 'status' => 1);
- $isValid = true;
- }
- else {
- $res['items'][] = array('name' => 'name', 'status' => 0);
- $isValid = false;
- }
- $email = strtolower(substr(JRequest::getVar('email'), 0, 50));
- if(ereg('^[^0-9][a-z0-9_\-\.]+@[^0-9][a-z\-\.]+\.[a-z]{2,4}$', $email)) {
- $res['items'][] = array('name' => 'email', 'status' => 1);
- $isValid = true;
- }
- else {
- $res['items'][] = array('name' => 'email', 'status' => 0);
- $isValid = false;
- }
- if($isValid) {
- $res['type'] = 'valid';
- $res['msg'] = 'Форма заполнена правильно';
- }
- else {
- $res['type'] = 'error';
- $res['msg'] = 'Ошибка!';
- }
- echo json_encode($res);
- }
- }
- ?>
В методе check() формируется ответ в формате JSON, который состоит из:
- текстового поля type — результат проверки (valid или error)
- текстового поля msg — сообщение для пользователя
- массива items, элементами которого являются массивы из двух элементов, в которых хранится id поля формы и их статус, эта информация нам понадобится, чтобы отображать, в каких полях ошибка
models/asyncform.php
- <?php
- jimport( 'joomla.application.component.model' );
- class AsyncformModel extends JModel {
- }
- ?>
views/default/view.html.php
- <?php
- jimport( 'joomla.application.component.view' );
- class AsyncformView extends JView {
- public $message;
- function __construct() {
- $this->addTemplatePath(JPATH_COMPONENT . DS . 'views' . DS . 'default' . DS . 'tmpl');
- }
- function display($tpl = null) {
- // JHTML::_('behavior.mootools');
- $document = &JFactory::getDocument();
- $document->addStyleSheet('components/com_asyncform/assets/css/common.css');
- $document->addScript('components/com_asyncform/assets/js/mootools-1.2.1-core.js');
- $document->addScript('components/com_asyncform/assets/js/common.js');
- parent::display($tpl);
- }
- }
- ?>
Если все таки хочется использовать встроенный mootools, тогда используйте оператор в строке 12 вместо строки 16.
views/default/tmpl/default.php
- <?php defined('_JEXEC') or die('Доступ запрещен'); ?>
- <div id="log"></div>
- <form id="frm_asyncform" action="index.php?option=com_asyncform&task=check&format=raw" method="post">
- <table>
- <tr>
- <td>Имя</td>
- <td><input type="text" name="name" id="name" /></td>
- </tr>
- <tr>
- <td>E-mail</td>
- <td><input type="text" name="email" id="email" /></td>
- </tr>
- </table>
- <input type="submit" name="btn_submit" id="btn_submit" value="Отправить" />
- </form>
Обратите внимание на обработчик формы. Такой вид обработчика обусловлен тем, что от сервера нам надо получить лишь строку ответа, без всякой дополнительной html-разметки и т.п. В Joomla 1.0.x для того чтобы вернуть только вывод компонента, надо было использовать index2.php, однако в Joomla 1.5 это не пройдет. Для этих целей в ней предусмотрен параметр format, который для того, чтобы вернуть только вывод компонента, должен быть равен raw.
assets/css/common.css
- .error {
- border: 2px solid #ff0000;
- }
- #log {
- padding: 5px;
- overflow: auto;
- margin-bottom: 5px;
- width: 452px;
- }
- #log.loaded {
- background-color: #ffc0c0;
- }
- #log.loaded-success {
- background-color: #c0ffc0;
- }
assets/js/common.js
- window.addEvent('domready', function() {
- $('frm_asyncform').addEvent('submit', function(e) {
- e.stop();
- var log = $('log').empty();
- this.set('send', {
- method: 'post',
- onComplete: function(response) {
- var res = JSON.decode(response);
- res.items.each(function(field) {
- if(field.status)
- $(field.name).removeClass('error');
- else
- $(field.name).addClass('error');
- });
- if(res.type == 'valid')
- log.addClass('loaded-success');
- else
- log.addClass('loaded');
- log.set('html', res.msg);
- }
- });
- this.send();
- });
- });
Здесь ответ, полученный от сервера в виде строки преобразуется в js-объект, после чего анализируется его содержимое и выставляются нужные параметры html-элементам в теле компонента.
Вот, собственно, и все. Надеюсь, данный пост будет кому-нибудь полезен. Комменты, советы и предложения, естественно, приветствуются!