/ext-4.0.7/jsbuilder/src/Template.js

https://bitbucket.org/srogerf/javascript · JavaScript · 275 lines · 129 code · 20 blank · 126 comment · 22 complexity · 258325eecf3db9ff7b63623c8be403b7 MD5 · raw file

  1. /**
  2. * @class Ext.Template
  3. * <p>Represents an HTML fragment template. Templates may be {@link #compile precompiled}
  4. * for greater performance.</p>
  5. * <p>For example usage {@link #Template see the constructor}.</p>
  6. *
  7. * @constructor
  8. * An instance of this class may be created by passing to the constructor either
  9. * a single argument, or multiple arguments:
  10. * <div class="mdetail-params"><ul>
  11. * <li><b>single argument</b> : String/Array
  12. * <div class="sub-desc">
  13. * The single argument may be either a String or an Array:<ul>
  14. * <li><tt>String</tt> : </li><pre><code>
  15. var t = new Ext.Template("&lt;div>Hello {0}.&lt;/div>");
  16. t.{@link #append}('some-element', ['foo']);
  17. </code></pre>
  18. * <li><tt>Array</tt> : </li>
  19. * An Array will be combined with <code>join('')</code>.
  20. <pre><code>
  21. var t = new Ext.Template([
  22. '&lt;div name="{id}"&gt;',
  23. '&lt;span class="{cls}"&gt;{name:trim} {value:ellipsis(10)}&lt;/span&gt;',
  24. '&lt;/div&gt;',
  25. ]);
  26. t.{@link #compile}();
  27. t.{@link #append}('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
  28. </code></pre>
  29. * </ul></div></li>
  30. * <li><b>multiple arguments</b> : String, Object, Array, ...
  31. * <div class="sub-desc">
  32. * Multiple arguments will be combined with <code>join('')</code>.
  33. * <pre><code>
  34. var t = new Ext.Template(
  35. '&lt;div name="{id}"&gt;',
  36. '&lt;span class="{cls}"&gt;{name} {value}&lt;/span&gt;',
  37. '&lt;/div&gt;',
  38. // a configuration object:
  39. {
  40. compiled: true, // {@link #compile} immediately
  41. }
  42. );
  43. </code></pre>
  44. * <p><b>Notes</b>:</p>
  45. * <div class="mdetail-params"><ul>
  46. * <li>Formatting and <code>disableFormats</code> are not applicable for Sencha Touch.</li>
  47. * </ul></div>
  48. * </div></li>
  49. * </ul></div>
  50. * @param {Mixed} config
  51. */
  52. Ext.Template = function(html) {
  53. var me = this,
  54. a = arguments,
  55. buf = [];
  56. if (Ext.isArray(html)) {
  57. html = html.join("");
  58. }
  59. else if (a.length > 1) {
  60. Ext.each(a, function(v) {
  61. if (Ext.isObject(v)) {
  62. Ext.apply(me, v);
  63. } else {
  64. buf.push(v);
  65. }
  66. });
  67. html = buf.join('');
  68. }
  69. // @private
  70. me.html = html;
  71. if (me.compiled) {
  72. me.compile();
  73. }
  74. };
  75. Ext.Template.prototype = {
  76. isTemplate: true,
  77. re: /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
  78. argsRe: /^\s*['"](.*)["']\s*$/,
  79. compileARe: /\\/g,
  80. compileBRe: /(\r\n|\n)/g,
  81. compileCRe: /'/g,
  82. /**
  83. * @cfg {Boolean} disableFormats true to disable format functions in the template. If the template doesn't contain format functions, setting
  84. * disableFormats to true will reduce apply time (defaults to false)
  85. */
  86. disableFormats: false,
  87. /**
  88. * Returns an HTML fragment of this template with the specified values applied.
  89. * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
  90. * @return {String} The HTML fragment
  91. * @hide repeat doc
  92. */
  93. applyTemplate: function(values) {
  94. var me = this,
  95. useF = me.disableFormats !== true,
  96. fm = Ext.util.Format,
  97. tpl = me,
  98. re,
  99. i,
  100. len;
  101. if (me.compiled) {
  102. return me.compiled(values);
  103. }
  104. function fn(m, name, format, args) {
  105. if (format && useF) {
  106. if (format.substr(0, 5) == "this.") {
  107. return tpl.call(format.substr(5), values[name], values);
  108. }
  109. else {
  110. if (args) {
  111. // quoted values are required for strings in compiled templates,
  112. // but for non compiled we need to strip them
  113. // quoted reversed for jsmin
  114. re = me.argsRe;
  115. args = args.split(',');
  116. for (i = 0, len = args.length; i < len; i++) {
  117. args[i] = args[i].replace(re, "$1");
  118. }
  119. args = [values[name]].concat(args);
  120. }
  121. else {
  122. args = [values[name]];
  123. }
  124. return fm[format].apply(fm, args);
  125. }
  126. }
  127. else {
  128. return values[name] !== undefined ? values[name] : "";
  129. }
  130. }
  131. return me.html.replace(me.re, fn);
  132. },
  133. /**
  134. * Sets the HTML used as the template and optionally compiles it.
  135. * @param {String} html
  136. * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
  137. * @return {Ext.Template} this
  138. */
  139. set: function(html, compile) {
  140. var me = this;
  141. me.html = html;
  142. me.compiled = null;
  143. return compile ? me.compile() : me;
  144. },
  145. /**
  146. * Compiles the template into an internal function, eliminating the RegEx overhead.
  147. * @return {Ext.Template} this
  148. * @hide repeat doc
  149. */
  150. compile: function() {
  151. var me = this,
  152. fm = Ext.util.Format,
  153. useF = me.disableFormats !== true,
  154. body;
  155. function fn(m, name, format, args) {
  156. if (format && useF) {
  157. args = args ? ',' + args: "";
  158. if (format.substr(0, 5) != "this.") {
  159. format = "fm." + format + '(';
  160. }
  161. else {
  162. format = 'this.call("' + format.substr(5) + '", ';
  163. args = ", values";
  164. }
  165. }
  166. else {
  167. args = '';
  168. format = "(values['" + name + "'] == undefined ? '' : ";
  169. }
  170. return "'," + format + "values['" + name + "']" + args + ") ,'";
  171. }
  172. body = ["this.compiled = function(values){ return ['"];
  173. body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
  174. body.push("'].join('');};");
  175. body = body.join('');
  176. eval(body);
  177. return me;
  178. },
  179. /**
  180. * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
  181. * @param {Mixed} el The context element
  182. * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
  183. * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
  184. * @return {HTMLElement/Ext.Element} The new node or Element
  185. */
  186. insertFirst: function(el, values, returnElement) {
  187. return this.doInsert('afterBegin', el, values, returnElement);
  188. },
  189. /**
  190. * Applies the supplied values to the template and inserts the new node(s) before el.
  191. * @param {Mixed} el The context element
  192. * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
  193. * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
  194. * @return {HTMLElement/Ext.Element} The new node or Element
  195. */
  196. insertBefore: function(el, values, returnElement) {
  197. return this.doInsert('beforeBegin', el, values, returnElement);
  198. },
  199. /**
  200. * Applies the supplied values to the template and inserts the new node(s) after el.
  201. * @param {Mixed} el The context element
  202. * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
  203. * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
  204. * @return {HTMLElement/Ext.Element} The new node or Element
  205. */
  206. insertAfter: function(el, values, returnElement) {
  207. return this.doInsert('afterEnd', el, values, returnElement);
  208. },
  209. /**
  210. * Applies the supplied <code>values</code> to the template and appends
  211. * the new node(s) to the specified <code>el</code>.
  212. * <p>For example usage {@link #Template see the constructor}.</p>
  213. * @param {Mixed} el The context element
  214. * @param {Object/Array} values
  215. * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
  216. * or an object (i.e. <code>{foo: 'bar'}</code>).
  217. * @param {Boolean} returnElement (optional) true to return an Ext.Element (defaults to undefined)
  218. * @return {HTMLElement/Ext.Element} The new node or Element
  219. */
  220. append: function(el, values, returnElement) {
  221. return this.doInsert('beforeEnd', el, values, returnElement);
  222. },
  223. doInsert: function(where, el, values, returnEl) {
  224. el = Ext.getDom(el);
  225. var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
  226. return returnEl ? Ext.get(newNode, true) : newNode;
  227. },
  228. /**
  229. * Applies the supplied values to the template and overwrites the content of el with the new node(s).
  230. * @param {Mixed} el The context element
  231. * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
  232. * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
  233. * @return {HTMLElement/Ext.Element} The new node or Element
  234. */
  235. overwrite: function(el, values, returnElement) {
  236. el = Ext.getDom(el);
  237. el.innerHTML = this.applyTemplate(values);
  238. return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
  239. },
  240. // private function used to call members
  241. call: function(fnName, value, allValues) {
  242. return this[fnName](value, allValues);
  243. }
  244. };
  245. /**
  246. * Alias for {@link #applyTemplate}
  247. * Returns an HTML fragment of this template with the specified <code>values</code> applied.
  248. * @param {Object/Array} values
  249. * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
  250. * or an object (i.e. <code>{foo: 'bar'}</code>).
  251. * @return {String} The HTML fragment
  252. * @member Ext.Template
  253. * @method apply
  254. */
  255. Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;