2012年4月2日月曜日

grailsとjQuery Mobileでdynamic scaffoldingのshow画面を変更する

grailsとjQuery Mobileでdynamic scaffoldingのshow画面を変更するには、以下の手順を実行します。

1. ApplicationResources.groovyでモジュールを宣言
modules = {
    application {
        resource url:'js/application.js'
    }
    // jQuery mobileのモジュールを宣言
    jquerymobile {
      dependsOn 'jquery'
      resource url: 'js/jquery.mobile-1.1.0-rc.1.min.js', disposition:'head'
      resource url: 'css/jquery.mobile-1.1.0-rc.1.min.css'
    }
}
jquery.mobile-1.1.0-rc.1.min.jsはweb-app/jsに、jquery.mobile-1.1.0-rc.1.min.cssはweb-app/cssに 画像類はweb-app/css/imagesに配置します。

2. web-app/WEB-INF/sitemesh.xmlに以下のようにexcludes要素を追加します。
<sitemesh>
<!-- sitemesh除外 -->
<excludes file="/WEB-INF/sitemesh-excludes.xml" />
    <page-parsers>
        <parser content-type="text/html"
            class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser" />
        <parser content-type="text/html;charset=ISO-8859-1"
            class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser" />
        <parser content-type="text/html;charset=UTF-8"
            class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser" />
    </page-parsers>

    <decorator-mappers>
        <mapper class="org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutDecoratorMapper" />
    </decorator-mappers>
</sitemesh>
3. sitemesh-excludes.xmlを以下のように作成し、web-app/WEB-INF/に配置します。
<?xml version="1.0" encoding="UTF-8"?>
<sitemesh-excludes>
  <excludes>
    <pattern>/*</pattern>
  </excludes>
</sitemesh-excludes>

4. テンプレートをインストールします。
grails install-templates

5. src/templates/scaffolding/show.gspを開き、下記コードのように変更します。
<% import grails.persistence.Event %>
<%=packageName%>
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <g:set var="entityName" value="\${message(code: '${domainClass.propertyName}.label', default: '${className}')}" />
    <title><g:message code="default.show.label" args="[entityName]" /></title>
    <style type="text/css" media="screen">
/* headerが...で省略されるのを防ぐ  */
body .ui-header .ui-title {
  white-space: normal;
  margin-left: 0;
  margin-right: 0;
}
    </style>
    <!-- jquerymobileを使用 -->
    <r:require module="jquerymobile"/>
    <r:layoutResources />
  </head>
  <body>
    <div data-role="page">
      <div data-role="header" data-position="inline">
        <a data-icon="home" href="\${createLink(uri: '/')}"><g:message code="default.home.label"/></a>
        <h1><g:message code="default.show.label" args="[entityName]" /></h1>
        <div data-role="navbar">
          <ul>
            <li><g:link action="list"><g:message code="default.list.label" args="[entityName]" /></g:link></li>
            <li><g:link action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
          </ul>
        </div>
      </div>
      <div data-role="content">

        <g:if test="\${flash.message}">
          <p>\${flash.message}</p>
        </g:if>

      <ol class="property-list ${domainClass.propertyName}">
      <%  excludedProps = Event.allEvents.toList() << 'id' << 'version'
        allowedNames = domainClass.persistentProperties*.name << 'dateCreated' << 'lastUpdated'
        props = domainClass.properties.findAll { allowedNames.contains(it.name) && !excludedProps.contains(it.name) }
        Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
        props.each { p -> %>
        <g:if test="\${${propertyName}?.${p.name}}">
        <li class="fieldcontain">
          <span id="${p.name}-label" class="property-label"><g:message code="${domainClass.propertyName}.${p.name}.label" default="${p.naturalName}" /></span>
          <%  if (p.isEnum()) { %>
            <span class="property-value" aria-labelledby="${p.name}-label"><g:fieldValue bean="\${${propertyName}}" field="${p.name}"/></span>
          <%  } else if (p.oneToMany || p.manyToMany) { %>
            <g:each in="\${${propertyName}.${p.name}}" var="${p.name[0]}">
            <span class="property-value" aria-labelledby="${p.name}-label"><g:link controller="${p.referencedDomainClass?.propertyName}" action="show" id="\${${p.name[0]}.id}">\${${p.name[0]}?.encodeAsHTML()}</g:link></span>
            </g:each>
          <%  } else if (p.manyToOne || p.oneToOne) { %>
            <span class="property-value" aria-labelledby="${p.name}-label"><g:link controller="${p.referencedDomainClass?.propertyName}" action="show" id="\${${propertyName}?.${p.name}?.id}">\${${propertyName}?.${p.name}?.encodeAsHTML()}</g:link></span>
          <%  } else if (p.type == Boolean || p.type == boolean) { %>
            <span class="property-value" aria-labelledby="${p.name}-label"><g:formatBoolean boolean="\${${propertyName}?.${p.name}}" /></span>
          <%  } else if (p.type == Date || p.type == java.sql.Date || p.type == java.sql.Time || p.type == Calendar) { %>
            <span class="property-value" aria-labelledby="${p.name}-label"><g:formatDate date="\${${propertyName}?.${p.name}}" /></span>
          <%  } else if(!p.type.isArray()) { %>
            <span class="property-value" aria-labelledby="${p.name}-label"><g:fieldValue bean="\${${propertyName}}" field="${p.name}"/></span>
          <%  } %>
        </li>
        </g:if>
      <%  } %>
      </ol>
      <g:form>
        <fieldset class="buttons">
          <g:hiddenField name="id" value="\${${propertyName}?.id}" />
          <g:link data-ajax="false" data-role="button" action="edit" id="\${${propertyName}?.id}"><g:message code="default.button.edit.label" default="Edit" /></g:link>
          <g:actionSubmit data-ajax="false" action="delete" value="\${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('\${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" />
        </fieldset>
      </g:form>

    </div>
    <r:layoutResources />
  </body>
</html>
出力画面

動作環境
grails 2.0.1

関連情報
jQuery mobileのホームページ
http://jquerymobile.com/

0 件のコメント:

コメントを投稿