jquery.template.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /**
  2. * jQuery Templates
  3. *
  4. * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
  5. * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
  6. *
  7. * Written by: Stan Lemon <stanlemon@mac.com>
  8. *
  9. * Based off of the Ext.Template library, available at:
  10. * http://www.extjs.com
  11. *
  12. * This library provides basic templating functionality, allowing for macro-based
  13. * templates within jQuery.
  14. *
  15. * Basic Usage:
  16. *
  17. * var t = $.template('<div id="foo">Hello ${name}, how are you ${question}? I am ${me:substr(0,10)}</div>');
  18. *
  19. * $(selector).append( t , {
  20. * name: 'Stan',
  21. * question: 'feeling',
  22. * me: 'doing quite well myself, thank you very much!'
  23. * });
  24. *
  25. * Requires: jQuery 1.2+
  26. *
  27. *
  28. * @todo Add callbacks to the DOM manipulation methods, so that events can be bound
  29. * to template nodes after creation.
  30. */
  31. (function($){
  32. /**
  33. * Create a New Template
  34. */
  35. $.template = function(html, options) {
  36. return new $.template.instance(html, options);
  37. };
  38. /**
  39. * Template constructor - Creates a new template instance.
  40. *
  41. * @param html The string of HTML to be used for the template.
  42. * @param options An object of configurable options. Currently
  43. * you can toggle compile as a boolean value and set a custom
  44. * template regular expression on the property regx by
  45. * specifying the key of the regx to use from the regx object.
  46. */
  47. $.template.instance = function(html, options) {
  48. // If a custom regular expression has been set, grab it from the regx object
  49. if ( options && options['regx'] ) options.regx = this.regx[ options.regx ];
  50. this.options = $.extend({
  51. compile: false,
  52. regx: this.regx.standard
  53. }, options || {});
  54. this.html = html;
  55. if (this.options.compile) {
  56. this.compile();
  57. }
  58. this.isTemplate = true;
  59. };
  60. /**
  61. * Regular Expression for Finding Variables
  62. *
  63. * The default pattern looks for variables in JSP style, the form of: ${variable}
  64. * There are also regular expressions available for ext-style variables and
  65. * jTemplate style variables.
  66. *
  67. * You can add your own regular expressions for variable ussage by doing.
  68. * $.extend({ $.template.re , {
  69. * myvartype: /...../g
  70. * }
  71. *
  72. * Then when creating a template do:
  73. * var t = $.template("<div>...</div>", { regx: 'myvartype' });
  74. */
  75. $.template.regx = $.template.instance.prototype.regx = {
  76. jsp: /\$\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
  77. ext: /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
  78. jtemplates: /\{\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}\}/g
  79. };
  80. /**
  81. * Set the standard regular expression to be used.
  82. */
  83. $.template.regx.standard = $.template.regx.jsp;
  84. /**
  85. * Variable Helper Methods
  86. *
  87. * This is a collection of methods which can be used within the variable syntax, ie:
  88. * ${variable:substr(0,30)} Which would only print a substring, 30 characters in length
  89. * begining at the first character for the variable named "variable".
  90. *
  91. * A basic substring helper is provided as an example of how you can define helpers.
  92. * To add more helpers simply do:
  93. * $.extend( $.template.helpers , {
  94. * sampleHelper: function() { ... }
  95. * });
  96. */
  97. $.template.helpers = $.template.instance.prototype.helpers = {
  98. substr : function(value, start, length){
  99. return String(value).substr(start, length);
  100. }
  101. };
  102. /**
  103. * Template Instance Methods
  104. */
  105. $.extend( $.template.instance.prototype, {
  106. /**
  107. * Apply Values to a Template
  108. *
  109. * This is the macro-work horse of the library, it receives an object
  110. * and the properties of that objects are assigned to the template, where
  111. * the variables in the template represent keys within the object itself.
  112. *
  113. * @param values An object of properties mapped to template variables
  114. */
  115. apply: function(values) {
  116. if (this.options.compile) {
  117. return this.compiled(values);
  118. } else {
  119. var tpl = this;
  120. var fm = this.helpers;
  121. var fn = function(m, name, format, args) {
  122. if (format) {
  123. if (format.substr(0, 5) == "this."){
  124. return tpl.call(format.substr(5), values[name], values);
  125. } else {
  126. if (args) {
  127. // quoted values are required for strings in compiled templates,
  128. // but for non compiled we need to strip them
  129. // quoted reversed for jsmin
  130. var re = /^\s*['"](.*)["']\s*$/;
  131. args = args.split(',');
  132. for(var i = 0, len = args.length; i < len; i++) {
  133. args[i] = args[i].replace(re, "$1");
  134. }
  135. args = [values[name]].concat(args);
  136. } else {
  137. args = [values[name]];
  138. }
  139. return fm[format].apply(fm, args);
  140. }
  141. } else {
  142. return values[name] !== undefined ? values[name] : "";
  143. }
  144. };
  145. return this.html.replace(this.options.regx, fn);
  146. }
  147. },
  148. /**
  149. * Compile a template for speedier usage
  150. */
  151. compile: function() {
  152. var sep = $.browser.mozilla ? "+" : ",";
  153. var fm = this.helpers;
  154. var fn = function(m, name, format, args){
  155. if (format) {
  156. args = args ? ',' + args : "";
  157. if (format.substr(0, 5) != "this.") {
  158. format = "fm." + format + '(';
  159. } else {
  160. format = 'this.call("'+ format.substr(5) + '", ';
  161. args = ", values";
  162. }
  163. } else {
  164. args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
  165. }
  166. return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
  167. };
  168. var body;
  169. if ($.browser.mozilla) {
  170. body = "this.compiled = function(values){ return '" +
  171. this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.options.regx, fn) +
  172. "';};";
  173. } else {
  174. body = ["this.compiled = function(values){ return ['"];
  175. body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.options.regx, fn));
  176. body.push("'].join('');};");
  177. body = body.join('');
  178. }
  179. eval(body);
  180. return this;
  181. }
  182. });
  183. /**
  184. * Save a reference in this local scope to the original methods which we're
  185. * going to overload.
  186. **/
  187. var $_old = {
  188. domManip: $.fn.domManip,
  189. text: $.fn.text,
  190. html: $.fn.html
  191. };
  192. /**
  193. * Overwrite the domManip method so that we can use things like append() by passing a
  194. * template object and macro parameters.
  195. */
  196. /* $.fn.domManip = function( args, table, reverse, callback ) {
  197. if (args[0].isTemplate) {
  198. // Apply the template and it's arguments...
  199. args[0] = args[0].apply( args[1] );
  200. // Get rid of the arguements, we don't want to pass them on
  201. delete args[1];
  202. }
  203. // Call the original method
  204. var r = $_old.domManip.apply(this, arguments);
  205. return r;
  206. };
  207. */
  208. /*
  209. **
  210. * Overwrite the html() method
  211. *
  212. $.fn.html = function( value , o ) {
  213. if (value && value.isTemplate) var value = value.apply( o );
  214. var r = $_old.html.apply(this, [value]);
  215. return r;
  216. };
  217. **
  218. * Overwrite the text() method
  219. *
  220. $.fn.text = function( value , o ) {
  221. if (value && value.isTemplate) var value = value.apply( o );
  222. var r = $_old.text.apply(this, [value]);
  223. return r;
  224. };
  225. */
  226. })(jQuery);