次はWebまわり

prototype.jsって何なんだろうーと思ったので、自分が使いそうなところだけ勉強。


でも、まずはS2Strutsの復習から。
いろいろとそろえるのが大変だから、s2struts-exampleに追加する形でつくることにしよー。



POJOのActionを利用するからActionのInterfaceを作成

/**
 * @org.seasar.struts.action.StrutsAction(name="storeForm", validate=false)
 */
public interface StoreEditAction {
    final String SUCCESS = "success";

    String execute();
}

実装はとりあえず、JSPを表示するのみってことでこんな風に単純。

public class StoreEditActionImpl implements StoreEditAction {
    public String execute() {
        return SUCCESS;
    }
}

ActionFormを作るんだけど、これってどうすればいいのわからないなー。
とりあえずって事で下のようにして作ってみる。

/**
 * @org.seasar.struts.form.StrutsActionForm(name="storeForm")
 */
public class StoreForm extends Store {

    /**
     * @org.seasar.struts.validator.Required
     * @org.seasar.struts.validator.Args(keys="form.store.name")
     */
    public void setName(String name) {
        super.setName(name);
    }
    
    /**
     * @org.seasar.struts.validator.Required
     * @org.seasar.struts.validator.Args(keys="form.store.address")
     */
    public void setAddress(String address) {
        super.setAddress(address);
    }

}

この作り方は本番ではしないだろうなー。

そしてdiconファイルを作って、app.diconに追加

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
	"http://www.seasar.org/dtd/components21.dtd">
<components>
	<include path="examples/dicon/alldao.dicon"/>
	<include path="examples/dicon/allaop.dicon"/>

    <!-- action -->
	<component class="org.seasar.framework.container.auto.FileSystemComponentAutoRegister">
		<initMethod name="addClassPattern">
			<arg>"examples.store.action.impl"</arg>
			<arg>".*ActionImpl"</arg>
		</initMethod>
		<initMethod name="registAll"></initMethod>
	</component>
	<component class="org.seasar.framework.container.auto.InterceptorAutoRegister">
		<property name="interceptorName">"actionInterceptorChain"</property>
		<initMethod name="addClassPattern">
			<arg>"examples.store.action.impl"</arg>
			<arg>".*ActionImpl"</arg>
		</initMethod>
		<initMethod name="registAll"></initMethod>
	</component>

</components>


やっとメインのJSPの作成。
ちょっと思ったんだけど、編集画面と確認画面の2つを用意するのはたいぎーなーと思ってたので、一緒にしてみた。
しかも、これって別にprototype.jsとか使う必要ないし・・・
でも、勉強だからrico.jsを使ってみよー。

<%@ page contentType="text/html;charset=Windows-31j" language="java" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>

<bean:define id="title" value="title.store.store.edit" />

<html:html>
<head>
<link href="<html:rewrite forward='globalStyle'/>" rel="stylesheet" type="text/css"></link>
<script type="text/javascript" src="<html:rewrite forward='executeJs'/>"></script>
<script type="text/javascript" src="<html:rewrite forward='prototypeJs'/>"></script>
<script type="text/javascript" src="<html:rewrite forward='ricoJs'/>"></script>
<script type="text/javascript">
<!--
function confirm(form) {
    copyForm(form);
    effectEdit();
    return false;
}

function backEdit() {
    effectConfirm();
    return false;
}

function copyForm(form) {
    for (var i = 0; i < form.elements.length; i++) {
        var element = form.elements[i];
        var label = $('form-' + element.name);
        if (label != null) {
            label.innerHTML = element.value;
        }
    }
}

function effectEdit() {
    new Effect.FadeTo('editArea', 0, 200, 4, {
        complete:function() {
            var editArea = $('editArea');
            editArea.style.display = "none";
            var confirmArea = $('confirmArea');
            confirmArea.style.display = "block";
        }
    } );
    new Effect.FadeTo('confirmArea', 1, 200, 4);
}

function effectConfirm() {

    new Effect.FadeTo('confirmArea', 0, 200, 4, {
        complete:function() {
            var editArea = $('editArea');
            editArea.style.display = "block";
            var confirmArea = $('confirmArea');
            confirmArea.style.display = "none";
        }
    } );
    new Effect.FadeTo('editArea', 1, 200, 4);
}
  
//-->
</script>
<title>
    <bean:message name="title" /> - <bean:message key="title.store" />
</title>
</head>

<body>
  
<h2><bean:message name="title" /></h2>

<div id="errorMessages">
  <html:errors />
</div>

<html:form action="/storeEditValidate" method="POST">

<div id="editArea">
  <table class="tablebg">
    <tr>
      <td class="label"><bean:message key="form.store.name" /></td>
      <td>
        <html:text property="name" styleClass="text" />
      </td>
    </tr>
    <tr>
      <td class="label"><bean:message key="form.store.address" /></td>
      <td>
        <html:text property="address" styleClass="text" />
      </td>
    </tr>
  </table>
  <html:button property="goConfirm" onclick="return confirm(this.form);">
    <bean:message key="button.confirm" />
  </html:button>
</div>
<div id="confirmArea" style="display:none;">
  <table class="tablebg">
    <tr>
      <td class="label"><bean:message key="form.store.name" /></td>
      <td>
        <span id="form-name">名前</span>
      </td>
    </tr>
    <tr>
      <td class="label"><bean:message key="form.store.address" /></td>
      <td>
        <span id="form-address">住所</span>
      </td>
    </tr>
  </table>
  <html:button property="goBack" onclick="return backEdit();">
    <bean:message key="button.back" />
  </html:button>
  <html:submit property="goStore">
    <bean:message key="button.store" />
  </html:submit>
</div>


</html:form>

</body>

</html:html>

って感じで「confirm」ボタンを押したらフェードアウト、フェードインっぽくしてみたりして。サンプルを真似たらできた。



うーん。
Firefoxではうまくいくけど、IEではうまくいかないなー。
そんなもんかなー。



次はAjax.Requestを使ってみよーっと。
どっかで、JavaScriptの入力パラメータチェックとサーバーでの入力パラメータチェックの2つの記述を解消するためにAjaxをってのを見たけど、どこでだったか思い出せない。。。


まずは、パラメータ検証のみのAction Interface

/**
 * @org.seasar.struts.action.StrutsAction(name="storeForm", input="/pages/inputError.jsp")
 */
public interface StoreEditValidateAction {
    
    /**
     * @org.seasar.struts.action.StrutsActionForward(path="/pages/inputSuccess.jsp")
     */
    final String SUCCESS = "success";

    String execute();

}

こんな感じで実装はStoreEditActionImplと一緒でSUCCESSを返すのみ。

public class StoreEditValidationActionImpl implements StoreEditValidateAction {
    public String execute() {
        return SUCCESS;
    }
}

これって、wildcardのaction-mappingをstruts-config.xmlに記述するべきかも

inputSuccess.jspとinputError.jspは単純に

<?xml version="1.0" encoding="Windows-31j" ?> 
<%@ page contentType="text/xml;charset=Windows-31j" language="java" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<response>
    <result>SUCCESS</result>
</response>
<?xml version="1.0" encoding="Windows-31j" ?> 
<%@ page contentType="text/xml;charset=Windows-31j" language="java" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<response>
    <result>ERROR</result>
    <messages><![CDATA[
        <html:errors />
    ]]></messages>
</response>

これは単純すぎるかも。。。。あとでなおそう。
JavaScriptのconfirm関数をちょっとなおして

function confirm(form) {
    copyForm(form);
    new Ajax.Request(
            form.action, 
            {
                 method: 'post',
                 parameters: Form.serialize(form),
                 onComplete: validateComplete
            }
    );
    return false;
}

function validateComplete(request) {
    var xml = request.responseXML;
    var result = xml.getElementsByTagName("result")[0].firstChild.data;
    if (result == "ERROR") {
        $('errorMessages').innerHTML = xml.getElementsByTagName("messages")[0].firstChild.data;
    } else if (result == "SUCCESS") {
        $('errorMessages').innerHTML = "";
        effectEdit();
    } else {
        alert("Error!!");
    }
}

Firefoxで試してみる。
一応動いてる。


うーむ。真似ばかりして勉強になってない気がしてきた。


IEでも試してみよー
「オブジェクトがありません」だって。
動かないのかー。
真似のみで作ってるからこういうときに困るなー。


勉強することがたくさんあるなー。