📄 zptemplate-core.js
字号:
/** * @fileoverview Zapatec Template widget. * * <pre> * Copyright (c) 2004-2007 by Zapatec, Inc. * http://www.zapatec.com * 1700 MLK Way, Berkeley, California, * 94709, U.S.A. * All rights reserved. * </pre> *//* $Id: zptemplate-core.js 7780 2007-08-11 09:52:55Z alex $ *//** * Zapatec Template widget class. Extends base Zapatec Widget class * (utils/zpwidget.js). * * <pre> * <strong>Following tags are recognized:</strong> * * Variable: * * #{@var} * * Where @var is template variable. Use {@link Zapatec.Template#assign} method * to set variable value. * * Expression with outputting of result: * * #{@var} * #{(@var1 + @var2) / @var3} * * Where you can use any JavaScript operators. * * Expression without outputting of result: * * #{expr @tempVar = @var} * #{expression @tempVar = @var} * * Where you can use any JavaScript operators. * * Condition: * * #{if @var1 < @var2} * ... * #{elseif @var1 > @var2} * ... * #{else} * ... * #{endif} * * Where you can use any JavaScript operators. Nested conditions are supported. * * Loop: * * #{for @array} * ... * #{endfor} * * Where array must be JavaScript Array object. You can access loop index using * special @@ variable. Nested loops are supported. * * Comments: * * #{rem} * ... * #{endrem} * * JavaScript comments are allowed inside expressions and other tags: * * #{//(@var1 + @var2) / @var3} * #{//expr @tempVar = @var} * * <strong>Supported source types</strong> * * Zapatec Template supports 'html', 'html/text' and 'html/url' source types. * * If 'html' source type is used, you can put source into <i>textarea</i> * element to prevent parsing during page load. See source-html.html demo for * details. * * <strong>In addition to config options defined in base Zapatec.Widget class * provides following config options:</strong> * * <b>tagLeftDelimiter</b> [string] Left delimiter of the tag. Must be single * non-alphanumeric character or combination of non-alphanumeric characters. * Default: '#{'. * * <b>tagRightDelimiter</b> [string] Right delimiter of the tag. Must be single * non-alphanumeric character or combination of non-alphanumeric characters. * Default: '}'. * * <b>varLeftDelimiter</b> [string] Left delimiter of the variable. Must be * single non-alphanumeric character or combination of non-alphanumeric * characters. Default: '@'. * * <b>varRightDelimiter</b> [string] Right delimiter of the variable. Must be * single non-alphanumeric character or combination of non-alphanumeric * characters. Default: none. * * <b>loopIndex</b> [string] Loop index variable. Must be single * non-alphanumeric character or combination of non-alphanumeric characters. * Default: @@. * * <b>syntax</b> [object] Gives ability to extend or redefine default syntax. * See the source code for details. * </pre> * * @constructor * @extends Zapatec.Widget * @param {object} oArg User configuration */Zapatec.Template = function(oArg) { // Call constructor of superclass Zapatec.Template.SUPERconstructor.call(this, oArg);};// Inherit WidgetZapatec.inherit(Zapatec.Template, Zapatec.Widget);/** * Initializes object. * * @param {object} oArg User configuration */Zapatec.Template.prototype.init = function(oArg) { // Call init method of superclass Zapatec.Template.SUPERclass.init.call(this, oArg); // Load data from the specified source this.loadData();};/** * Configures the widget. Gets called from init and reconfigure methods of * superclass. * * @private * @param {object} oArg User configuration */Zapatec.Template.prototype.configure = function(oArg) { var oTemplate = Zapatec.Template; // Themes are not used in this widget this.defineConfigOption('theme', ''); // Define config options this.defineConfigOption('tagLeftDelimiter', '#{'); this.defineConfigOption('tagRightDelimiter', '}'); this.defineConfigOption('varLeftDelimiter', '@'); this.defineConfigOption('varRightDelimiter', ''); this.defineConfigOption('loopIndex', '@@'); this.defineConfigOption('syntax', { '': { parser: oTemplate.parseExprOut }, 'expr': { parser: oTemplate.parseExpr }, 'expression': { parser: oTemplate.parseExpr }, 'if': { parser: oTemplate.parseCond }, 'for': { parser: oTemplate.parseLoop }, 'rem': { parser: oTemplate.parseComment } }); // Call parent method Zapatec.Template.SUPERclass.configure.call(this, oArg); // Tag matching this.tagRegexp = /^\s*([a-zA-Z]*)\s*(.*)\s*$/; // Variable matching var fEsc = Zapatec.Utils.escapeRegExp; var oConf = this.config; this.varRegexp = new RegExp([fEsc(oConf.varLeftDelimiter), '(\\w+)', fEsc(oConf.varRightDelimiter)].join(''), 'g'); this.loopIndexRegexp = new RegExp(fEsc(oConf.loopIndex), 'g'); // Variables this.vars = {}; // Nested templates this.templates = []; // Nested tags this.tags = [];};/** * Loads data from the HTML source. Extracts template source from the element. * To prevent parsing during page load use <i>textarea</i> element. * * @private * @param {object} oSource Source HTMLElement object */Zapatec.Template.prototype.loadDataHtml = function(oSource) { if (oSource.tagName.toLowerCase() == 'textarea') { this.loadDataHtmlText(oSource.value); } else { this.loadDataHtmlText(oSource.innerHTML); }};/** * Loads data from the HTML fragment source. * * @private * @param {string} sSrc Source HTML fragment */Zapatec.Template.prototype.loadDataHtmlText = function(sSrc) { // Parse source Zapatec.Template.parse.call(this, sSrc);};/** * Parses template. Must be called in scope of Template object. * * @private * @param {string} sTxt Template text */Zapatec.Template.parse = function(sTxt) { // Split text into tokens var oConf = this.config; var sLeftDelim = oConf.tagLeftDelimiter; var iLeftDelimLen = sLeftDelim.length; var sRightDelim = oConf.tagRightDelimiter; var iRightDelimLen = sRightDelim.length; var oTagRegexp = this.tagRegexp; var oVarRegexp = this.varRegexp; var oLoopIndexRegexp = this.loopIndexRegexp; var oSyntax = oConf.syntax; var aTokens = []; var fParseTag = Zapatec.Template.parseTag; var sTail, iPos1, iPos2; while (sTxt) { // Extract tag iPos1 = sTxt.indexOf(sLeftDelim); if (iPos1 != -1) { sTail = sTxt.substring(iPos1 + iLeftDelimLen); iPos2 = sTail.indexOf(sRightDelim); if (iPos2 != -1) { aTokens.push(sTxt.substring(0, iPos1)); aTokens.push(fParseTag(sTail.substring(0, iPos2), oTagRegexp, oVarRegexp, oLoopIndexRegexp)); sTxt = sTail.substring(iPos2 + iRightDelimLen); } else { aTokens.push(sTxt); break; } } else { aTokens.push(sTxt); break; } } // Create tree based on the syntax var aTemplates = this.templates = []; var aTags = this.tags = []; var aNewTemplate = []; var aNewTag = []; aTemplates.push(aNewTemplate); aTags.push(aNewTag); var iTokens = aTokens.length; var oToken, oRule; for (var iToken = 0; iToken < iTokens; iToken++) { oToken = aTokens[iToken]; if (typeof oToken == 'object') { // Tag oRule = oSyntax[oToken.tag]; if (oRule) { iToken = oRule.parser.call(this, aNewTemplate, aNewTag, aTokens, iToken); } } else { // String aNewTemplate.push(oToken); // No tag in this position aNewTag.push(null); } }};/** * Parses tag. * * @private * @param {string} sTag Tag text * @param {object} oTagRegexp Tag matching RegExp object * @param {object} oVarRegexp Variable matching RegExp object * @param {object} oLoopIndexRegexp Loop index matching RegExp object */Zapatec.Template.parseTag = function(sTag, oTagRegexp, oVarRegexp, oLoopIndexRegexp) { var aM = sTag.match(oTagRegexp); if (aM) { return { tag: aM[1], args: aM[2].replace(oVarRegexp, 'zpTemplateVars.$1').replace(oLoopIndexRegexp, 'zpTemplateIndex') }; } return {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -