X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/7a654f8d43fdb43d78b63d90528bed6e86b608cc..3789b528d8dd8aad4558e38e22d775bcab1cbd36:/jsbuilder/src/Template.js diff --git a/jsbuilder/src/Template.js b/jsbuilder/src/Template.js new file mode 100644 index 00000000..9bb5ff14 --- /dev/null +++ b/jsbuilder/src/Template.js @@ -0,0 +1,275 @@ +/** + * @class Ext.Template + *

Represents an HTML fragment template. Templates may be {@link #compile precompiled} + * for greater performance.

+ *

For example usage {@link #Template see the constructor}.

+ * + * @constructor + * An instance of this class may be created by passing to the constructor either + * a single argument, or multiple arguments: + *
+ * @param {Mixed} config + */ +Ext.Template = function(html) { + var me = this, + a = arguments, + buf = []; + + if (Ext.isArray(html)) { + html = html.join(""); + } + else if (a.length > 1) { + Ext.each(a, function(v) { + if (Ext.isObject(v)) { + Ext.apply(me, v); + } else { + buf.push(v); + } + }); + html = buf.join(''); + } + + // @private + me.html = html; + + if (me.compiled) { + me.compile(); + } +}; + +Ext.Template.prototype = { + isTemplate: true, + + re: /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g, + argsRe: /^\s*['"](.*)["']\s*$/, + compileARe: /\\/g, + compileBRe: /(\r\n|\n)/g, + compileCRe: /'/g, + + /** + * @cfg {Boolean} disableFormats true to disable format functions in the template. If the template doesn't contain format functions, setting + * disableFormats to true will reduce apply time (defaults to false) + */ + disableFormats: false, + + /** + * Returns an HTML fragment of this template with the specified values applied. + * @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'}) + * @return {String} The HTML fragment + * @hide repeat doc + */ + applyTemplate: function(values) { + var me = this, + useF = me.disableFormats !== true, + fm = Ext.util.Format, + tpl = me, + re, + i, + len; + + if (me.compiled) { + return me.compiled(values); + } + function fn(m, name, format, args) { + if (format && useF) { + if (format.substr(0, 5) == "this.") { + return tpl.call(format.substr(5), values[name], values); + } + else { + if (args) { + // quoted values are required for strings in compiled templates, + // but for non compiled we need to strip them + // quoted reversed for jsmin + re = me.argsRe; + args = args.split(','); + for (i = 0, len = args.length; i < len; i++) { + args[i] = args[i].replace(re, "$1"); + } + args = [values[name]].concat(args); + } + else { + args = [values[name]]; + } + return fm[format].apply(fm, args); + } + } + else { + return values[name] !== undefined ? values[name] : ""; + } + } + return me.html.replace(me.re, fn); + }, + + /** + * Sets the HTML used as the template and optionally compiles it. + * @param {String} html + * @param {Boolean} compile (optional) True to compile the template (defaults to undefined) + * @return {Ext.Template} this + */ + set: function(html, compile) { + var me = this; + me.html = html; + me.compiled = null; + return compile ? me.compile() : me; + }, + + /** + * Compiles the template into an internal function, eliminating the RegEx overhead. + * @return {Ext.Template} this + * @hide repeat doc + */ + compile: function() { + var me = this, + fm = Ext.util.Format, + useF = me.disableFormats !== true, + body; + + function fn(m, name, format, args) { + if (format && useF) { + args = args ? ',' + args: ""; + if (format.substr(0, 5) != "this.") { + format = "fm." + format + '('; + } + else { + format = 'this.call("' + format.substr(5) + '", '; + args = ", values"; + } + } + else { + args = ''; + format = "(values['" + name + "'] == undefined ? '' : "; + } + return "'," + format + "values['" + name + "']" + args + ") ,'"; + } + + + body = ["this.compiled = function(values){ return ['"]; + body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn)); + body.push("'].join('');};"); + body = body.join(''); + eval(body); + return me; + }, + + /** + * Applies the supplied values to the template and inserts the new node(s) as the first child of el. + * @param {Mixed} el The context element + * @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'}) + * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined) + * @return {HTMLElement/Ext.Element} The new node or Element + */ + insertFirst: function(el, values, returnElement) { + return this.doInsert('afterBegin', el, values, returnElement); + }, + + /** + * Applies the supplied values to the template and inserts the new node(s) before el. + * @param {Mixed} el The context element + * @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'}) + * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined) + * @return {HTMLElement/Ext.Element} The new node or Element + */ + insertBefore: function(el, values, returnElement) { + return this.doInsert('beforeBegin', el, values, returnElement); + }, + + /** + * Applies the supplied values to the template and inserts the new node(s) after el. + * @param {Mixed} el The context element + * @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'}) + * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined) + * @return {HTMLElement/Ext.Element} The new node or Element + */ + insertAfter: function(el, values, returnElement) { + return this.doInsert('afterEnd', el, values, returnElement); + }, + + /** + * Applies the supplied values to the template and appends + * the new node(s) to the specified el. + *

For example usage {@link #Template see the constructor}.

+ * @param {Mixed} el The context element + * @param {Object/Array} values + * The template values. Can be an array if the params are numeric (i.e. {0}) + * or an object (i.e. {foo: 'bar'}). + * @param {Boolean} returnElement (optional) true to return an Ext.Element (defaults to undefined) + * @return {HTMLElement/Ext.Element} The new node or Element + */ + append: function(el, values, returnElement) { + return this.doInsert('beforeEnd', el, values, returnElement); + }, + + doInsert: function(where, el, values, returnEl) { + el = Ext.getDom(el); + var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values)); + return returnEl ? Ext.get(newNode, true) : newNode; + }, + + /** + * Applies the supplied values to the template and overwrites the content of el with the new node(s). + * @param {Mixed} el The context element + * @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'}) + * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined) + * @return {HTMLElement/Ext.Element} The new node or Element + */ + overwrite: function(el, values, returnElement) { + el = Ext.getDom(el); + el.innerHTML = this.applyTemplate(values); + return returnElement ? Ext.get(el.firstChild, true) : el.firstChild; + }, + + // private function used to call members + call: function(fnName, value, allValues) { + return this[fnName](value, allValues); + } +}; +/** + * Alias for {@link #applyTemplate} + * Returns an HTML fragment of this template with the specified values applied. + * @param {Object/Array} values + * The template values. Can be an array if the params are numeric (i.e. {0}) + * or an object (i.e. {foo: 'bar'}). + * @return {String} The HTML fragment + * @member Ext.Template + * @method apply + */ +Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate; \ No newline at end of file