Thymeleafのth:replaceを再現しようしたら既にライブラリがあった
【前提条件】
[参考サイト]
Thymol公式サイト
Thymol Home
【経緯】
前回、Thymeleafのth:replaceを静的ページで再現できないものかと
objectタグでやろうしたものの色々と問題がわかりました。
HTML Importsでやるしかないのかなと思っていたら、
「Thymolと言うのがあるみたいだが?」と言う助言をいただいたので
Thymolを試してみました。
【概要】
ThymolはThymleafのJavascript実装で、サードパーティによって提供されています。
Javascript実装なのでGlassfishなどのAPサーバが不要です。
今回はth:replaceが動くところまでを書いていきます。
EL式の部分は公式ドキュメントには載っているもののまだ試せていないです。
次回あたりはその辺を書いてみたいなと思っています・・・
【ソース】
サンプルとして使うソースはほぼ前回と同じです。
前回との違いはth:replaceにEL式でパラメータを渡している箇所を削除していることです。
今回はEL式を動かすところまではできていないので動きません。
[top.html]
<!DOCTYPE html> <html> <head th:include="/common/base/metaInfo :: commonHeader (title='Top Page')" > <title th:text="${title}">テストタイトル</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" th:href="@{/css/normalize.css}" /> <link rel="stylesheet" th:href="@{/css/base.css}" /> </head> <body> <div class="bs-content-area"> <div th:replace="/common/component/topMenu :: topMenu"> </div> <div class="bs-left-menu"> <div th:replace="/genreSearch/genreSearch :: genreSearch"> </div> </div> </div> </body> </html>
[topMenu.html]
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>Top Page</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" href="../../../../css/normalize.css" th:href="@{/css/normalize.css}" /> <link rel="stylesheet" href="../../../../css/base.css" th:href="@{/css/base.css}" /> </head> <body> <div class="bs-top-menu" th:fragment="topMenu"> <ul class="right-menu"> <li><a href="" th:href="@{/top}" >TOP</a></li> <li><a href="../../login/login.html" th:href="@{/login}" >ログイン</a></li> </ul> </div> </body> </html>
[genreSearch.html]
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>ジャンル検索</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" href="../../../css/normalize.css" th:href="@{/css/normalize.css}" /> <link rel="stylesheet" href="../../../css/base.css" th:href="@{/css/base.css}" /> </head> <body> <div class="cp-genre-search" th:fragment="genreSearch"> <h1>ジャンル検索</h1> <ul> <li th:each="genre : ${it.genreSearch.genres}"> <a th:href="@{/genreSearch/id/{id}(id=${genre.id})}" th:text="${genre.title}">テスト</a> </li> <li th:remove="all"> <a href="#">アクション</a> </li> <li th:remove="all"> <a href="#">RPG</a> </li> </ul> </div> </body> </html>
【事前準備】
今回、できればファイルシステム上だけで実現したかったのですが、
Webサーバを経由しないとth:replaceが動作しないようなのでApacheを使っています。
(th:replaceをするのに内部で対象のHTMLをリクエストしているようです)
まずはGlassfish上で動かすソースのファイル階層です。
Apacheのドキュメントルートから上記の階層に対してシンボリックリンクを貼ります。
$ ll 合計 0 lrwxrwxrwx 1 Admin None 10 12月 29 13:52 css -> webapp/css lrwxrwxrwx 1 Admin None 9 12月 29 13:52 js -> webapp/js lrwxrwxrwx 1 Admin None 19 12月 29 13:52 view -> webapp/WEB-INF/view lrwxrwxrwx 1 Admin None 90 12月 29 13:52 webapp -> webappのパス
webappに対してシンボリックリンク貼っているのは文字数の都合です。
【Thymolの設定】
続いてThymolの設定です。
[ダウンロード]
まずはダウンロードするのですが、
今回は「download」ページにある「download distribution」からダウンロードします。
ダウンロードしたファイルを解凍するといくつかJSファイルがありますが、
「thymol.js」、「thymol-full.js」を使用します。
上記の2つのJSファイルをjsディレクトリの下におきます。
今回は「/js/lib/thymol」においています。
[thymol.jsファイルの設定]
続いてthymol.jsの設定を変更します。
設定はthymolConfigurationの中身を変更します。
var thymolConfiguration = { thScriptName: "thymol-full.js", thJQuerySource: "http://code.jquery.com/jquery-1.11.1.min.js", thDefaultPrefix: "th", thDefaultDataPrefix: "data", thDefaultPrecision: 10, thDefaultProtocol: "http://", thDefaultLocale: "ja", thDefaultPrecedence: 2e4, thDefaultMessagePath: "", thDefaultMessagesBaseName: "Messages", thDefaultRelativeRootPath: "", thDefaultExtendedMapping: false, thDefaultLocalMessages: true };
thScriptNameには使用するJSファイルを指定します。
対象となるのはダウンロードで解凍したthymol-full.js、thymol-full.min.js、thymol-lite.js、thymol-lit.min.jsです。
今回はthymol-full.jsを使用しているので、thymol-full.jsを指定します。
続いてthJQuerySourceを指定します。
プロパティ名のとおり、jQueryのパスを指定します。
他に設定した箇所はthDefaultProtocolとthDefaultLocaleです。
[パスの設定]
最後にパスの設定を行います。
Thymolでは 「thRoot + thPath + template-name + ".html" 」が
最終的に参照するテンプレートファイルのパスになります。
thRootを設定するとCSS/Javascriptにも影響があるため、今回はthPathのみを設定します。
var thPath = "localhost/view";
この設定はthymol.jsをロードする前に毎回scriptタグで定義しても良いのですが、
設定用の別JSファイルとして定義します。
サンプルでは「/js/lib/thymol/project-settin.js」と言うパスで保存しました。
[thymol.jsのロード]
tymol.jsファイルをロードするにはtop.htmlに下記のコードを追加します。
<script src="/js/lib/thymol/thymol.js" th:remove="all" data-thymol-load="/js/lib/thymol/project-setting.js"></script>
data-thymol-loadはthymol.jsが実行されるタイミングにロードされるデータ用のJavascriptファイルを指定します。
EL式のデータを設定するファイルなどを指定することができますが、
今回はthPathの設定をしたファイルを読み込んでいます。
また、実際の画面では不要な行なのでth:removeで消すようにしています。
【アクセス】
以上で設定が終わったので、http経由でアクセスします。
アクセスした結果、thymol.jsによって書き換えられたDOMは下記のようになりました。
<html> <head> <title>Top Page</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="/css/normalize.css"> <link rel="stylesheet" href="/css/base.css"> </head> <body> <div class="bs-content-area"> <div class="bs-top-menu"> <ul class="right-menu"> <li><a href="/top">TOP</a></li> <li><a href="/login">ログイン</a></li> </ul> </div> <div class="bs-left-menu"> <div class="cp-genre-search"> <h1>ジャンル検索</h1> <ul> <li th:each="genre : ${it.genreSearch.genres}"> <a th:href="@{/genreSearch/id/{id}(id=${genre.id})}" th:text="${genre.title}">テスト</a> </li> <li th:remove="all"> <a href="#">アクション</a> </li> <li th:remove="all"> <a href="#">RPG</a> </li> </ul> </div> </div> <div class="bs-main-contents"> </div> </div> </body> </html>
EL式がそのまま残っている箇所はありますが、th:replaceした部分は動作しています。
EL式が残っている箇所はデータを設定していないことにより解析がされていないだけだと思います。
データを設定すれば、解析されると予想しています。
【まとめ】
まだまだ調べきれていない箇所も多いですが、
th:replaceはThymolを使えばThymelaefの結果と同じ結果が得られました。
ファイルシステムだけで実現できなかったですが、
Apacheとシンボリックリンクを使えば、APサーバを使用しなくてもth:replaceが動いてくれます。
ローカルにWebサーバを入れる、もしくは、デザイン確認用の環境をつくるということをすれば、
Thymleafの結果をブラウザで確認できそうです。
【追記】
どうやらファイルシステムでもクロスオリジンリクエストができる設定があるようです。
Thymol Browser Constraints