原文:http://bbs.javascript.com.cn/simple/index.php?t1022.html
官網:http://code.google.com/p/trimpath/
Trimpath JavaScript 是個輕量級的,基於JavaScript的,跨瀏覽器,採用APL/GPL開放源代碼協議的,可讓你輕鬆進行基於模板編程方式的純JS引擎。新浪的評論系統使用的就是此模板。
它有以下的特色:
一、採用標準的JavaScript編寫,支持跨瀏覽器
二、模板語法相似於:FreeMarker,Velocity,Smarty
三、採用簡易的語言來描述大段的字串以及Dom/DHTML操做
四、能夠很方便的解析XML文件格式的數據到指定模板。
採 用該引擎,可讓它來徹底處理View方面的事情,服務端Module直接輸出Data就能夠。讓你的MVC模式連成一體,並且因爲View由瀏覽器來處 理,大大減小了服務器的負擔,用來構建Ajax技術的網絡信息系統應用是一個很是好的選擇。下面將經過翻譯該站的文章來給你們介紹這個JST引擎的使用。
CODE:
<html>
<head>
<script language="javascript" src="trimpath/template.js"></script>
</head>
<body>
<div id="outputDiv">
</div>
<script language="javascript">
var data = {
products : [ { name: "mac", desc: "computer",
price: 1000, quantity: 100, alert:null },
{ name: "ipod", desc: "music player",
price: 200, quantity: 200, alert:"on sale now!" },
{ name: "cinema display", desc: "screen",
price: 800, quantity: 300, alert:"best deal!" } ],
customer : { first: "John", last: "Public", level: "gold" }
};
</script>
<textarea id="cart_jst" style="display:none;">
Hello ${customer.first} ${customer.last}.<br/>
Your shopping cart has ${products.length} item(s):
<table>
<tr><td>Name</td><td>Description</td>
<td>Price</td><td>Quantity & Alert</td></tr>
{for p in products}
<tr><td>${p.name|capitalize}</td><td>${p.desc}</td>
<td>$${p.price}</td><td>${p.quantity} : ${p.alert|default:""|capitalize}</td>
</tr>
{forelse}
<tr><td colspan="4">No products in your cart.</tr>
{/for}
</table>
{if customer.level == "gold"}
We love you! Please check out our Gold Customer specials!
{else}
Become a Gold Customer by buying more stuff here.
{/if}
</textarea>
<script language="javascript">
// The one line processing call...
var result = TrimPath.processDOMTemplate("cart_jst", data);
// Voila! That's it -- the result variable now holds
// the output of our first rendered JST.
// Alternatively, you may also explicitly parse the template...
var myTemplateObj = TrimPath.parseDOMTemplate("cart_jst");
// Now, calls to myTemplateObj.process() won't have parsing costs...
var result = myTemplateObj.process(data);
// Setting an innerHTML with the result is a common last step...
document.getElementById("outputDiv").innerHTML = result;
// You might also do a document.write() or something similar...
</script>
</body>
</html>
JST十分鐘簡介
JST API
JST Markup Syntax
JST Standard Modifiers
JST Downloads
JST Community Wiki
JST Browser Compatibility
JST Online Demo
一、API
首先到下載頁面下載 template.js
而後在你的JSP/ASP/PHP等文件中引用
CODE:
<script language="javascript" src="trimpath/template.js"></script>
當你引用了template.js文件以後,腳本將建立一個名叫「trimpath"的物件給你使用。
TrimPath Object
這個物件是一個全局的單一變量,也是全部trimpath組件的訪問入口,除了它自身,咱們嘗試創建一個清晰的命名空間給您使用。
下面是 Trimpath 定義的方法:
CODE:
TrimPath.parseDOMTemplate ( elementId, optionalDocument )
獲得頁面中ID爲elementId的Dom組件的InnerHTML,並將其解析成一個模板,這個方法返回一個templateObject對象(下面將詳細描述),解析出錯時將拋出一個異常,下面是這個方法的參數:
elementId DOM組件,其innerhtml將用來作模板
optionalDocument 一個可選參數,在使用iframe,frameset或者默認多文檔時會有用
一般用來作模板的DOM元素是一個隱藏的<textarea>,以下面的例子
CODE:
<textarea id="elementId" style="display:none;"> template body </textarea>
TrimPath.processDOMTemplate ( elementId, contextObject, optionalFlags, optionalDocument )
一 個輔助函數,裏面調用了TrimPath.parseDOMTemplate() 和 then the process() 方法以得到templateObject。輸出的是templateObject.process() 中返回的對象。解析出錯時將拋出一個錯誤。下面是這個方法的參數:
elementId 包含模板內容的DOM元素ID
contextObject 參考templateObject.process()
optionalFlags 參考templateObject.process()
optionalDocument 參考TrimPath.parseDOMTemplate
TrimPath.parseTemplate ( templateContentStr, optionalTemplateName )
解析模板方法,將一個字符串作爲模板解析並返回一個templateObject
參數表:
templateContentStr 符合JST語法的字符串,例如: "Hello ${firstName} ${lastName}"
optionalTemplateName 一個可選的字符串用來指定模板名稱,輔助查錯。
The templateObject
TrimPath.parseTemplate() 和 TrimPath.parseDOMTemplate()的成功運行將產生一個 templateObject 它只有一個主方法
templateObject.process ( contextObject, optionalFlags )
這個方法將模板和數據結合在一塊兒,能夠重複調用,若是沒有從新解析,templateObjects的緩存和重用將得到最好的系統性能。這個函數的返回值是一個通過「渲染」過的模板的字符串。
參數contextObject 必須是一個對象,並將成爲模板的一個訪問域,好比一個模板是:${a},那麼contextObject.a必須是能夠訪問到的。一樣${a.b.c}, contextObject.a.b.c也是能夠訪問到的。
注 意:contextObject 能夠是javascript中的任意對象,包含字符串, 數字, 日期, 對象和函數。因此${groupCalender(new Date())} 能夠這樣來調用contextObject.groupCalender(new Date())。固然,你必須本身編程實現groupCalender() 這個函數。
參數optionalFlags 能夠是空值,也能夠是一個下面列表描述的對象:
throwExceptions 默認是false,當true的時候,process() 方法將從新拋出異常,當false的時候,任何異常將中止解析模板,並在方法返回值包含一個出錯信息。
keepWhitespace 默認是falsel,當值爲true時,模板的空白將保留。當爲false時,空白(換行、空格、TAB)將被截取。
String.prototype.process() 方法
String.prototype.process ( contextObject, optionalFlags )
作爲一個便捷的方式爲string對象加入一個process()的方法,讓它來執行解析模板的動做。參數跟process()同樣。
CODE:
var result = "hello ${firstName}".process(data)
// ...is equivalent to...
var result = TrimPath.parseTemplate("hello ${firstName}").process(data);
添加自定義標識符
若是要採用自定義標識符,你必須把他們放在_MODIFERS 這個對象中,這些標識符集將被添加到contextObject 對象中,而後最終傳給process()解析。每個自定義標識符必須是一個函數而且至少有一個字符串參數輸入和一個字符串輸出。
例子:
CODE:
var myModifiers = {
hello : function(str, greeting) {
if (greeting == null)
greeting = "Hello";
return greeting + ", " + str;
},
zeroSuffix : function(str, totalLength) {
return (str + "000000000000000").substring(0, totalLength);
}
};
var myData = {
firstName : "John",
getCurrentPoints : function() { /* Do something here... */ return 12; }
}
myData._MODIFIERS = myModifiers;
"${firstName}".process(myData) == "John"
"${firstName|hello}".process(myData) == "Hello, John"
"${firstName|hello:"Buenos Dias"}".process(myData) == "Buenos Dias, John"
"${firstName|hello:"Buenos Dias"|capitalize}".process(myData) == "BUENOS DIAS, JOHN"
"${getCurrentPoints()}".process(myData) == "12"
"${getCurrentPoints()|zeroSuffix:4}".process(myData) == "1200"
JST 的語法和語句
語法
CODE:
${expr}
${expr|modifier}
${expr|modifier1|modifier2|...|modifierN}
${expr|modifier1:argExpr1_1}
${expr|modifier1:argExpr1_1,argExpr1_2,...,argExpr1_N}
${expr|modifier1:argExpr1_1,argExpr1_2|...|modifierN:argExprN_1,argExprN_2,...,argExprN_M}
表達式能夠是除了「}」以外的任何合法的javascript字符串
標識符看起來像這種結構:modifierName[:argExpr1[,argExpr2[,argExprN]]]
一個帶參數的表達式例子
CODE:
${customer.firstName}
${customer.firstName|capitalize}
${customer.firstName|default:"no name"|capitalize}
${article.getCreationDate()|default:new Date()|toCalenderControl:"YYYY.MM.DD",true,"Creation Date"}
${(lastQuarter.calcRevenue() - fixedCosts) / 1000000}
一個表達式也能夠像下面同樣經過添加「%」字符來標識,這個能夠避免在你的表達式中出現「}」時出錯的狀況。
好比:
CODE:
Visit our ${% emitLink('Solutions and Products',
{ color: 'red', blink: false }) %} page.
The extra spaces are actually not necessary, like...
${%customer.firstName%}
${%customer.firstName|capitalize%}
語句
JST語句就像是javascript語句同樣,也有if/else/for/function這些句子
分支控制語句
CODE:
{if testExpr}
{elseif testExpr}
{else}
{/if}
上述testExpr 是一個合法的javascript斷定式
例子
CODE:
{if customer != null && customer.balance > 1000}
We love you!
{/if}
{if user.karma > 100}
Welcome to the Black Sun.
{elseif user.isHero}
Sir, yes sir! Welcome!
{if user.lastName == "Yen"}
Fancy some apple pie, sir?
{/if}
{/if}
<a href="/login{if returnURL != null && returnURL != 'main'}?goto=${returnURL}{/if}">Login</a>
*JST引擎還包含一個輔助函數defined(str),這個能夠測試一個變量是否已經被定義。
好比這段代碼判斷管理員發送了消息給你
CODE:
{if defined('adminMessage')}
System Administrator Important NOTICE: ${adminMessage}
{/if}
循環語句
CODE:
{for varName in listExpr}
{/for}
{for varName in listExpr}
...main body of the loop...
{forelse}
...body when listExpr is null or listExpr.length is 0...
{/for}
*varName 必須是一個javascript的合法變量名
*listExpr 能夠是一個數組,對象或者爲空,並且只能被賦值一次
例子
CODE:
Two variables are bound in the main body of the loop:
__LIST__varName - holds the result of evaluating listExpr.
varName_index - this is the key or counter used during iteration.
Examples:
{for x in customer.getRecentOrders()}
${x_index} : ${x.orderNumber} <br/>
{forelse}
You have no recent orders.
{/for}
Converted pseudo-code for the above...
var __LIST__x = customer.getRecentOrders();
if (__LIST__x != null && __LIST__x.length > 0) {
for (var x_index in __LIST__x) {
var x = __LIST__x[x_index];
${x_index} : {$x.orderNumber} <br/>
}
} else {
You have no recent orders.
}
定義變量
{var varName}
{var varName = varInitExpr}
*varName必須是一個合法的javascript變量名
*varInitExpr必須是一個沒有包含"}"的字符串
例子:
CODE:
{var temp = crypto.generateRandomPrime(4096)}
Your prime is ${temp}.
宏定義
{macro macroName(arg1, arg2, ...argN)}
...body of the macro...
{/macro}
*宏相似於一個javascript函數,不一樣點在於宏的主體是另一個包含了諸如控制語句、循環語句的JST模板
*宏的名稱必須是一個合法javascript變量名
*宏的返回值是一個字符創
*使用宏能夠採用這種語法 :${macroName()}
一個使用宏的例子
CODE:
{macro htmlList(list, optionalListType)}
{var listType = optionalListType != null ? optionalListType : "ul"}
<${listType}>
{for item in list}
<li>${item}</li>
{/for}
</${listType}>
{/macro}
Using the macro...
${htmlList([ 1, 2, 3])}
${htmlList([ "Purple State", "Blue State", "Red State" ], "ol")}
{var saved = htmlList([ 100, 200, 300 ])}
${saved} and ${saved}
運行上述語句將出現
QUOTE:
*1
*2
*3
這樣的列表。只需將數據列表賦值給htmlList這個宏,就會幫你把數據經過<li>方式列出來,聰明的你很快就會把它改爲<option><td>等應用了。
從宏的訪問域來講,默認狀況下它是每一個模板私有的,可是若是你想定義
一個宏庫的話,那麼也許你須要在process()以前先定義能夠導出宏:contextObject['exported'] ={};
下面是例子:
CODE:
{macro userName(user)}
{if user.aliasName != null && user.aliasName.length > 0}
${user.aliasName}
{else}
${user.login}
{/if}
{/macro}
${exported.userName = userName |eat}
另外,你也能夠設置 contextObject['exported'] = contextObject;它也能夠正常的工做。
CDATA 文本區段
[code]
{cdata}
...text emitted without JST processing...
{/cdata}
{cdata EOF}
...text emitted without JST processing...
EOFjavascript