EthnaのフォームにJQueryのvalidateを利用する

EthnaのFormの設定をそのままJavaScriptJQueryに渡してAjaxっぽい入力値チェックを行います。

プロジェクト作成

今回はS2Ethnaでプロジェクトを作成しました。validateにはまったく影響せず(笑)

Smartyのデリミタを変更

Projectname_ViewClass.php

<?php
    function _setDefault(&$renderer)
    {
        //Rendererからテンプレートエンジンを取得
        $smarty =& $renderer->getEngine();

        //Smartyのデリミタを変更
        $smarty->left_delimiter = '<{';
        $smarty->right_delimiter = '}>';
    }

JavaScriptとの相性が悪いので<{}>に変更しました。

Formの設定

<?php
    var $form = array(
		'name' => array(
			'type'        => VAR_TYPE_TEXT,
			'form_type'   => FORM_TYPE_TEXT,
			'name'        => '名前',
			'required'    => true,
			'min'         => 2,
		),
		'url' => array(
			'type'        => VAR_TYPE_TEXT,
			'form_type'   => FORM_TYPE_TEXT,
			'name'        => 'URL',
			'custom' => 'checkURL',
		),
		'email' => array(
			'type'        => VAR_TYPE_TEXT,
			'form_type'   => FORM_TYPE_TEXT,
			'name'        => 'E-Mail',
			'required'    => true,
			'custom' => 'checkMailaddress',
		),
    );

こんな感じのフォームを作成しました。

テンプレート側

<?php
<form id="form-host" name="form-host" action="" method="post">
	名前(必須,2文字以上):<input type="text" name="name" /><br />
	URL:<input type="text" name="url" /><br />
	E-Mail(必須):<input type="text" name="email" /><br />

	<input type="submit" value="登録" />
</form>

内容はJQueryのvalidateのサンプルから持ってきました。

JQueryの準備

jquery.js
http://jquery.com/

jquery.validate.js
http://bassistance.de/jquery-plugins/jquery-plugin-validation/

messages_ja.js
http://www.goodpic.com/mt/archives2/2008/06/jqueryjqueryval.html

上記から持ってきて、projectname/www/js にコピーします。

<script language="javascript" type="text/javascript" src="js/jquery.js"></script> 
<script language="javascript" type="text/javascript" src="js/jquery.validate.js"></script>
<script language="javascript" type="text/javascript" src="js/messages_ja.js"></script>

こんな感じで読み込みます。

EthnaのFORMからJQueryのvalidateのコードを生成

<?php
function getValidateJS( $form = null, $form_name = 'form' ){
	$str = '';
	$str .= '$(document).ready(function(){' . "\n";
	$str .= '$("#'. $form_name .'").validate({' . "\n";

	if( $form ){
		$str .= 'rules: {' . "\n";
		foreach( $form as $key => $item ){
			$str .= '	' . $key . ':';

			$options = array();
			foreach( $item as $key2 => $item2 ){
				switch($key2){
					case 'required':
						if($item2){
							$options[] = 'required: true';
						}
						break;
					case 'min':
						if($item2){
							$options[] = 'minlength: ' . $item2;
						}
						break;
					case 'max':
						if($item2){
							$options[] = 'maxlength: ' . $item2;
						}
						break;
					case 'custom':
						if($item2=='checkURL'){
							$options[] = 'url: true';
						}elseif($item2=='checkMailaddress'){
							$options[] = 'email: true';
						}
						break;
				}
			}

			$str .= '{' . implode( ',', $options ) . '},'. "\n";
		}
		$str .= '}' . "\n";
	}

	$str .= '	})' . "\n";
	$str .= '});' . "\n";

	return $str;
}

こんな感じのコードをコードをprojectname/lib/EthnaJqueryValidate.phpに保存しました。全部をサポートしていませんが、こんな感じで変換していきます。

FORMから変換

<?php
require_once 'EthnaJqueryValidate.php';

class Projectname_View_Index extends Booklist_ViewClass
{
    function preforward()
    {
        $ValidateJS = getValidateJS( $this->af->form, 'form-host' );
        $this->af->setAppNE('ValidateJS', $ValidateJS);
    }
}

こんな感じでviewでformの内容を変換してValidateJSに突っ込みます。

テンプレート側に追加

<script type="text/javascript">
<{ $app_ne.ValidateJS }>
</script>

こんな感じで埋め込みます。

実際の生成されたコード

<script type="text/javascript">
$(document).ready(function(){
$("#form-host").validate({
rules: {
	name:{required: true,minlength: 2},
	url:{url: true},
	email:{required: true,email: true},
}
	})
});
</script>

上記のようなコードが生成されます。これでリアルタイムにEthnaで設定したFORMの制限をJavaScriptにてチェックすることができます。クライアント側とサーバー側の二重チェックで、個別に条件を設定するのって無駄ですからね。

jquery.validate.jsの改造

alert('入力にエラーがあります。値を確認してください');
validator.focusInvalid();
return false;

エラーが発生した場合に標準では一番上のエラーの項目を選択しますが、エラーの表示を追加しました。無言でフォーカスが移動してもわかりにくいですからね。

注意点

emailなどのチェックもjquery側とEthnaで違うので注意してください。対応していない制約やエラー文字の渡し、カスタム関数などは個別に組み込んでいく必要があります。

感想

実験としては結構楽に組み込めるかな? 完璧にEthnaと同じチェックをするjquery.validate.jsを作るか、Ethnaと同じチェックをするカスタム関数をvalidateに読み込ませれば汎用的に流用できる気がします。

お手伝いはしますので、誰か作ってください! THE 人任せ(笑)