dojo.provide("dojox.dtl._base"); dojo.require("dojox.string.Builder"); dojo.require("dojox.string.tokenize"); dojo.experimental("dojox.dtl"); (function(){ var dd = dojox.dtl; dd.TOKEN_BLOCK = -1; dd.TOKEN_VAR = -2; dd.TOKEN_COMMENT = -3; dd.TOKEN_TEXT = 3; dd._Context = dojo.extend(function(dict){ // summary: Pass one of these when rendering a template to tell the template what values to use. dojo._mixin(this, dict || {}); this._dicts = []; }, { push: function(){ var last = this; var context = dojo.delegate(this); context.pop = function(){ return last; } return context; }, pop: function(){ throw new Error("pop() called on empty Context"); }, get: function(key, otherwise){ if(typeof this[key] != "undefined"){ return this._normalize(this[key]); } for(var i = 0, dict; dict = this._dicts[i]; i++){ if(typeof dict[key] != "undefined"){ return this._normalize(dict[key]); } } return otherwise; }, _normalize: function(value){ if(value instanceof Date){ value.year = value.getFullYear(); value.month = value.getMonth() + 1; value.day = value.getDate(); value.date = value.year + "-" + ("0" + value.month).slice(-2) + "-" + ("0" + value.day).slice(-2); value.hour = value.getHours(); value.minute = value.getMinutes(); value.second = value.getSeconds(); value.microsecond = value.getMilliseconds(); } return value; }, update: function(dict){ var context = this.push(); if(dict){ dojo._mixin(this, dict); } return context; } }); var smart_split_re = /("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g; var split_re = /\s+/g; var split = function(/*String|RegExp?*/ splitter, /*Integer?*/ limit){ splitter = splitter || split_re; if(!(splitter instanceof RegExp)){ splitter = new RegExp(splitter, "g"); } if(!splitter.global){ throw new Error("You must use a globally flagged RegExp with split " + splitter); } splitter.exec(""); // Reset the global var part, parts = [], lastIndex = 0, i = 0; while(part = splitter.exec(this)){ parts.push(this.slice(lastIndex, splitter.lastIndex - part[0].length)); lastIndex = splitter.lastIndex; if(limit && (++i > limit - 1)){ break; } } parts.push(this.slice(lastIndex)); return parts; } dd.Token = function(token_type, contents){ this.token_type = token_type; this.contents = new String(dojo.trim(contents)); this.contents.split = split; this.split = function(){ return String.prototype.split.apply(this.contents, arguments); } } dd.Token.prototype.split_contents = function(/*Integer?*/ limit){ var bit, bits = [], i = 0; limit = limit || 999; while(i++ < limit && (bit = smart_split_re.exec(this.contents))){ bit = bit[0]; if(bit.charAt(0) == '"' && bit.slice(-1) == '"'){ bits.push('"' + bit.slice(1, -1).replace('\\"', '"').replace('\\\\', '\\') + '"'); }else if(bit.charAt(0) == "'" && bit.slice(-1) == "'"){ bits.push("'" + bit.slice(1, -1).replace("\\'", "'").replace('\\\\', '\\') + "'"); }else{ bits.push(bit); } } return bits; } var ddt = dd.text = { _get: function(module, name, errorless){ // summary: Used to find both tags and filters var params = dd.register.get(module, name.toLowerCase(), errorless); if(!params){ if(!errorless){ throw new Error("No tag found for " + name); } return null; } var fn = params[1]; var require = params[2]; var parts; if(fn.indexOf(":") != -1){ parts = fn.split(":"); fn = parts.pop(); } dojo["require"](require); var parent = dojo.getObject(require); return parent[fn || name] || parent[name + "_"] || parent[fn + "_"]; }, getTag: function(name, errorless){ return ddt._get("tag", name, errorless); }, getFilter: function(name, errorless){ return ddt._get("filter", name, errorless); }, getTemplate: function(file){ return new dd.Template(ddt.getTemplateString(file)); }, getTemplateString: function(file){ return dojo._getText(file.toString()) || ""; }, _resolveLazy: function(location, sync, json){ if(sync){ if(json){ return dojo.fromJson(dojo._getText(location)) || {}; }else{ return dd.text.getTemplateString(location); } }else{ return dojo.xhrGet({ handleAs: (json) ? "json" : "text", url: location }); } }, _resolveTemplateArg: function(arg, sync){ if(ddt._isTemplate(arg)){ if(!sync){ var d = new dojo.Deferred(); d.callback(arg); return d; } return arg; } return ddt._resolveLazy(arg, sync); }, _isTemplate: function(arg){ return (typeof arg == "undefined") || (typeof arg == "string" && (arg.match(/^\s*[<{]/) || arg.indexOf(" ") != -1)); }, _resolveContextArg: function(arg, sync){ if(arg.constructor == Object){ if(!sync){ var d = new dojo.Deferred; d.callback(arg); return d; } return arg; } return ddt._resolveLazy(arg, sync, true); }, _re: /(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g, tokenize: function(str){ return dojox.string.tokenize(str, ddt._re, ddt._parseDelims); }, _parseDelims: function(varr, load, tag){ if(varr){ return [dd.TOKEN_VAR, varr]; }else if(load){ var parts = dojo.trim(tag).split(/\s+/g); for(var i = 0, part; part = parts[i]; i++){ dojo["require"](part); } }else{ return [dd.TOKEN_BLOCK, tag]; } } } dd.Template = dojo.extend(function(/*String|dojo._Url*/ template, /*Boolean*/ isString){ // template: // The string or location of the string to // use as a template var str = isString ? template : ddt._resolveTemplateArg(template, true) || ""; var tokens = ddt.tokenize(str); var parser = new dd._Parser(tokens); this.nodelist = parser.parse(); }, { update: function(node, context){ // node: DOMNode|String|dojo.NodeList // A node reference or set of nodes // context: dojo._Url|String|Object // The context object or location return ddt._resolveContextArg(context).addCallback(this, function(contextObject){ var content = this.render(new dd._Context(contextObject)); if(node.forEach){ node.forEach(function(item){ item.innerHTML = content; }); }else{ dojo.byId(node).innerHTML = content; } return this; }); }, render: function(context, /*concatenatable?*/ buffer){ buffer = buffer || this.getBuffer(); context = context || new dd._Context({}); return this.nodelist.render(context, buffer) + ""; }, getBuffer: function(){ dojo.require("dojox.string.Builder"); return new dojox.string.Builder(); } }); var qfRe = /\{\{\s*(.+?)\s*\}\}/g; dd.quickFilter = function(str){ if(!str){ return new dd._NodeList(); } if(str.indexOf("{%") == -1){ return new dd._QuickNodeList(dojox.string.tokenize(str, qfRe, function(token){ return new dd._Filter(token); })); } } dd._QuickNodeList = dojo.extend(function(contents){ this.contents = contents; }, { render: function(context, buffer){ for(var i=0, l=this.contents.length; i/g; var escapeqt = /'/g; var escapedblqt = /"/g; dd._base.escape = function(value){ // summary: Escapes a string's HTML return dd.mark_safe(value.replace(escapeamp, '&').replace(escapelt, '<').replace(escapegt, '>').replace(escapedblqt, '"').replace(escapeqt, ''')); } dd._base.safe = function(value){ if(typeof value == "string"){ value = new String(value); } if(typeof value == "object"){ value.safe = true; } return value; } dd.mark_safe = dd._base.safe; dd.register.tags("dojox.dtl.tag", { "date": ["now"], "logic": ["if", "for", "ifequal", "ifnotequal"], "loader": ["extends", "block", "include", "load", "ssi"], "misc": ["comment", "debug", "filter", "firstof", "spaceless", "templatetag", "widthratio", "with"], "loop": ["cycle", "ifchanged", "regroup"] }); dd.register.filters("dojox.dtl.filter", { "dates": ["date", "time", "timesince", "timeuntil"], "htmlstrings": ["linebreaks", "linebreaksbr", "removetags", "striptags"], "integers": ["add", "get_digit"], "lists": ["dictsort", "dictsortreversed", "first", "join", "length", "length_is", "random", "slice", "unordered_list"], "logic": ["default", "default_if_none", "divisibleby", "yesno"], "misc": ["filesizeformat", "pluralize", "phone2numeric", "pprint"], "strings": ["addslashes", "capfirst", "center", "cut", "fix_ampersands", "floatformat", "iriencode", "linenumbers", "ljust", "lower", "make_list", "rjust", "slugify", "stringformat", "title", "truncatewords", "truncatewords_html", "upper", "urlencode", "urlize", "urlizetrunc", "wordcount", "wordwrap"] }); dd.register.filters("dojox.dtl", { "_base": ["escape", "safe"] }); })();