﻿(function (jQuery, undefined) { var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = []; function newTmplItem(options, parentItem, fn, data) { var newItem = { data: data || (parentItem ? parentItem.data : {}), _wrap: parentItem ? parentItem._wrap : null, tmpl: null, parent: parentItem || null, nodes: [], calls: tiCalls, nest: tiNest, wrap: tiWrap, html: tiHtml, update: tiUpdate }; if (options) { jQuery.extend(newItem, options, { nodes: [], parent: parentItem }) } if (fn) { newItem.tmpl = fn; newItem._ctnt = newItem._ctnt || newItem.tmpl(jQuery, newItem); newItem.key = ++itemKey; (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem } return newItem } jQuery.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function (name, original) { jQuery.fn[name] = function (selector) { var ret = [], insert = jQuery(selector), elems, i, l, tmplItems, parent = this.length === 1 && this[0].parentNode; appendToTmplItems = newTmplItems || {}; if (parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1) { insert[original](this[0]); ret = this } else { for (i = 0, l = insert.length; i < l; i++) { cloneIndex = i; elems = (i > 0 ? this.clone(true) : this).get(); jQuery.fn[original].apply(jQuery(insert[i]), elems); ret = ret.concat(elems) } cloneIndex = 0; ret = this.pushStack(ret, name, insert.selector) } tmplItems = appendToTmplItems; appendToTmplItems = null; jQuery.tmpl.complete(tmplItems); return ret } }); jQuery.fn.extend({ tmpl: function (data, options, parentItem) { return jQuery.tmpl(this[0], data, options, parentItem) }, tmplItem: function () { return jQuery.tmplItem(this[0]) }, template: function (name) { return jQuery.template(name, this[0]) }, domManip: function (args, table, callback, options) { if (args[0] && args[0].nodeType) { var dmArgs = jQuery.makeArray(arguments), argsLength = args.length, i = 0, tmplItem; while (i < argsLength && !(tmplItem = jQuery.data(args[i++], "tmplItem"))) { } if (argsLength > 1) { dmArgs[0] = [jQuery.makeArray(args)] } if (tmplItem && cloneIndex) { dmArgs[2] = function (fragClone) { jQuery.tmpl.afterManip(this, fragClone, callback) } } oldManip.apply(this, dmArgs) } else { oldManip.apply(this, arguments) } cloneIndex = 0; if (!appendToTmplItems) { jQuery.tmpl.complete(newTmplItems) } return this } }); jQuery.extend({ tmpl: function (tmpl, data, options, parentItem) { var ret, topLevel = !parentItem; if (topLevel) { parentItem = topTmplItem; tmpl = jQuery.template[tmpl] || jQuery.template(null, tmpl); wrappedItems = {} } else if (!tmpl) { tmpl = parentItem.tmpl; newTmplItems[parentItem.key] = parentItem; parentItem.nodes = []; if (parentItem.wrapped) { updateWrapped(parentItem, parentItem.wrapped) } return jQuery(build(parentItem, null, parentItem.tmpl(jQuery, parentItem))) } if (!tmpl) { return [] } if (typeof data === "function") { data = data.call(parentItem || {}) } if (options && options.wrapped) { updateWrapped(options, options.wrapped) } ret = jQuery.isArray(data) ? jQuery.map(data, function (dataItem) { return dataItem ? newTmplItem(options, parentItem, tmpl, dataItem) : null }) : [newTmplItem(options, parentItem, tmpl, data)]; return topLevel ? jQuery(build(parentItem, null, ret)) : ret }, tmplItem: function (elem) { var tmplItem; if (elem instanceof jQuery) { elem = elem[0] } while (elem && elem.nodeType === 1 && !(tmplItem = jQuery.data(elem, "tmplItem")) && (elem = elem.parentNode)) { } return tmplItem || topTmplItem }, template: function (name, tmpl) { if (tmpl) { if (typeof tmpl === "string") { tmpl = buildTmplFn(tmpl) } else if (tmpl instanceof jQuery) { tmpl = tmpl[0] || {} } if (tmpl.nodeType) { tmpl = jQuery.data(tmpl, "tmpl") || jQuery.data(tmpl, "tmpl", buildTmplFn(tmpl.innerHTML)) } return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl } return name ? (typeof name !== "string" ? jQuery.template(null, name) : (jQuery.template[name] || jQuery.template(null, htmlExpr.test(name) ? name : jQuery(name)))) : null }, encode: function (text) { return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;") } }); jQuery.extend(jQuery.tmpl, { tag: { "tmpl": { _default: { $2: "null" }, open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" }, "wrap": { _default: { $2: "null" }, open: "$item.calls(_,$1,$2);_=[];", close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" }, "each": { _default: { $2: "$index, $value" }, open: "if($notnull_1){$.each($1a,function($2){with(this){", close: "}});}" }, "if": { open: "if(($notnull_1) && $1a){", close: "}" }, "else": { _default: { $1: "true" }, open: "}else if(($notnull_1) && $1a){" }, "html": { open: "if($notnull_1){_.push($1a);}" }, "=": { _default: { $1: "$data" }, open: "if($notnull_1){_.push($.encode($1a));}" }, "!": { open: ""} }, complete: function (items) { newTmplItems = {} }, afterManip: function afterManip(elem, fragClone, callback) { var content = fragClone.nodeType === 11 ? jQuery.makeArray(fragClone.childNodes) : fragClone.nodeType === 1 ? [fragClone] : []; callback.call(elem, fragClone); storeTmplItems(content); cloneIndex++ } }); function build(tmplItem, nested, content) { var frag, ret = content ? jQuery.map(content, function (item) { return (typeof item === "string") ? (tmplItem.key ? item.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2") : item) : build(item, tmplItem, item._ctnt) }) : tmplItem; if (nested) { return ret } ret = ret.join(""); ret.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function (all, before, middle, after) { frag = jQuery(middle).get(); storeTmplItems(frag); if (before) { frag = unencode(before).concat(frag) } if (after) { frag = frag.concat(unencode(after)) } }); return frag ? frag : unencode(ret) } function unencode(text) { var el = document.createElement("div"); el.innerHTML = text; return jQuery.makeArray(el.childNodes) } function buildTmplFn(markup) { return new Function("jQuery", "$item", "var $=jQuery,call,_=[],$data=$item.data;" + "with($data){_.push('" + jQuery.trim(markup).replace(/([\\'])/g, "\\$1").replace(/[\r\t\n]/g, " ").replace(/\$\{([^\}]*)\}/g, "{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g, function (all, slash, type, fnargs, target, parens, args) { var tag = jQuery.tmpl.tag[type], def, expr, exprAutoFnDetect; if (!tag) { throw "Template command not found: " + type } def = tag._default || []; if (parens && !/\w$/.test(target)) { target += parens; parens = "" } if (target) { target = unescape(target); args = args ? ("," + unescape(args) + ")") : (parens ? ")" : ""); expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target; exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))" } else { exprAutoFnDetect = expr = def.$1 || "null" } fnargs = unescape(fnargs); return "');" + tag[slash ? "close" : "open"].split("$notnull_1").join(target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true").split("$1a").join(exprAutoFnDetect).split("$1").join(expr).split("$2").join(fnargs ? fnargs.replace(/\s*([^\(]+)\s*(\((.*?)\))?/g, function (all, name, parens, params) { params = params ? ("," + params + ")") : (parens ? ")" : ""); return params ? ("(" + name + ").call($item" + params) : all }) : (def.$2 || "")) + "_.push('" }) + "');}return _;") } function updateWrapped(options, wrapped) { options._wrap = build(options, true, jQuery.isArray(wrapped) ? wrapped : [htmlExpr.test(wrapped) ? wrapped : jQuery(wrapped).html()]).join("") } function unescape(args) { return args ? args.replace(/\\'/g, "'").replace(/\\\\/g, "\\") : null } function outerHtml(elem) { var div = document.createElement("div"); div.appendChild(elem.cloneNode(true)); return div.innerHTML } function storeTmplItems(content) { var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m; for (i = 0, l = content.length; i < l; i++) { if ((elem = content[i]).nodeType !== 1) { continue } elems = elem.getElementsByTagName("*"); for (m = elems.length - 1; m >= 0; m--) { processItemKey(elems[m]) } processItemKey(elem) } function processItemKey(el) { var pntKey, pntNode = el, pntItem, tmplItem, key; if ((key = el.getAttribute(tmplItmAtt))) { while (pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute(tmplItmAtt))) { } if (pntKey !== key) { pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute(tmplItmAtt) || 0)) : 0; if (!(tmplItem = newTmplItems[key])) { tmplItem = wrappedItems[key]; tmplItem = newTmplItem(tmplItem, newTmplItems[pntNode] || wrappedItems[pntNode], null, true); tmplItem.key = ++itemKey; newTmplItems[itemKey] = tmplItem } if (cloneIndex) { cloneTmplItem(key) } } el.removeAttribute(tmplItmAtt) } else if (cloneIndex && (tmplItem = jQuery.data(el, "tmplItem"))) { cloneTmplItem(tmplItem.key); newTmplItems[tmplItem.key] = tmplItem; pntNode = jQuery.data(el.parentNode, "tmplItem"); pntNode = pntNode ? pntNode.key : 0 } if (tmplItem) { pntItem = tmplItem; while (pntItem && pntItem.key != pntNode) { pntItem.nodes.push(el); pntItem = pntItem.parent } delete tmplItem._ctnt; delete tmplItem._wrap; jQuery.data(el, "tmplItem", tmplItem) } function cloneTmplItem(key) { key = key + keySuffix; tmplItem = newClonedItems[key] = (newClonedItems[key] || newTmplItem(tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true)) } } } function tiCalls(content, tmpl, data, options) { if (!content) { return stack.pop() } stack.push({ _: content, tmpl: tmpl, item: this, data: data, options: options }) } function tiNest(tmpl, data, options) { return jQuery.tmpl(jQuery.template(tmpl), data, options, this) } function tiWrap(call, wrapped) { var options = call.options || {}; options.wrapped = wrapped; return jQuery.tmpl(jQuery.template(call.tmpl), call.data, options, call.item) } function tiHtml(filter, textOnly) { var wrapped = this._wrap; return jQuery.map(jQuery(jQuery.isArray(wrapped) ? wrapped.join("") : wrapped).filter(filter || "*"), function (e) { return textOnly ? e.innerText || e.textContent : e.outerHTML || outerHtml(e) }) } function tiUpdate() { var coll = this.nodes; jQuery.tmpl(null, null, null, this).insertBefore(coll[0]); jQuery(coll).remove() } })(jQuery);
