From e44a7e37b6c7b5961adaffc62b9042b8d442938e Mon Sep 17 00:00:00 2001 From: mensonge Date: Thu, 13 Nov 2008 09:49:11 +0000 Subject: New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f --- includes/js/dojox/dtl/_base.js | 570 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100644 includes/js/dojox/dtl/_base.js (limited to 'includes/js/dojox/dtl/_base.js') diff --git a/includes/js/dojox/dtl/_base.js b/includes/js/dojox/dtl/_base.js new file mode 100644 index 0000000..f42f245 --- /dev/null +++ b/includes/js/dojox/dtl/_base.js @@ -0,0 +1,570 @@ +if(!dojo._hasResource["dojox.dtl._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.dtl._base"] = true; +dojo.provide("dojox.dtl._base"); + +dojo.require("dojox.string.Builder"); +dojo.require("dojox.string.tokenize"); + +(function(){ + var dd = dojox.dtl; + + 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 dict = {}; + var keys = this.getKeys(); + for(var i = 0, key; key = keys[i]; i++){ + dict[key] = this[key]; + delete this[key]; + } + this._dicts.unshift(dict); + }, + pop: function(){ + if(!this._dicts.length){ + throw new Error("pop() called on empty Context"); + } + var dict = this._dicts.shift(); + dojo.mixin(this, dict); + }, + getKeys: function(){ + var keys = []; + for(var key in this){ + if(this.hasOwnProperty(key) && key != "_dicts" && key != "_this"){ + keys.push(key); + } + } + return keys; + }, + 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){ + this.push(); + if(dict){ + dojo.mixin(this, dict); + } + } + }); + + var ddt = dd.text = { + types: {tag: -1, varr: -2, text: 3}, + pySplit: function(str){ + // summary: Split a string according to Python's split function + str = dojo.trim(str); + return (!str.length) ? [] : str.split(/\s+/g); + }, + _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 + "_"]; + }, + 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(dd.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") || (dojo.isString(arg) && (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){ + var types = ddt.types; + if(varr){ + return [types.varr, varr]; + }else if(load){ + var parts = dd.text.pySplit(tag); + for(var i = 0, part; part = parts[i]; i++){ + dojo["require"](part); + } + }else{ + return [types.tag, tag]; + } + } + } + + dd.Template = dojo.extend(function(/*String|dojo._Url*/ template){ + // template: + // The string or location of the string to + // use as a template + var str = 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(); + } + }); + + dd._Filter = dojo.extend(function(token){ + // summary: Uses a string to find (and manipulate) a variable + if(!token) throw new Error("Filter must be called with variable name"); + this.contents = token; + + var cache = this._cache[token]; + if(cache){ + this.key = cache[0]; + this.filters = cache[1]; + }else{ + this.filters = []; + dojox.string.tokenize(token, this._re, this._tokenize, this); + this._cache[token] = [this.key, this.filters]; + } + }, + { + _cache: {}, + _re: /(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g, + _values: { + 0: '"', // _("text") + 1: '"', // "text" + 2: "", // variable + 8: '"' // 'text' + }, + _args: { + 4: '"', // :_("text") + 5: '"', // :"text" + 6: "", // :variable + 7: "'"// :'text' + }, + _tokenize: function(){ + var pos, arg; + + for(var i = 0, has = []; i < arguments.length; i++){ + has[i] = (typeof arguments[i] != "undefined" && dojo.isString(arguments[i]) && arguments[i]); + } + + if(!this.key){ + for(pos in this._values){ + if(has[pos]){ + this.key = this._values[pos] + arguments[pos] + this._values[pos]; + break; + } + } + }else{ + for(pos in this._args){ + if(has[pos]){ + var value = arguments[pos]; + if(this._args[pos] == "'"){ + value = value.replace(/\\'/g, "'"); + }else if(this._args[pos] == '"'){ + value = value.replace(/\\"/g, '"'); + } + arg = [!this._args[pos], value]; + break; + } + } + // Get a named filter + var fn = ddt.getFilter(arguments[3]); + if(!dojo.isFunction(fn)) throw new Error(arguments[3] + " is not registered as a filter"); + this.filters.push([fn, arg]); + } + }, + getExpression: function(){ + return this.contents; + }, + resolve: function(context){ + var str = this.resolvePath(this.key, context); + for(var i = 0, filter; filter = this.filters[i]; i++){ + // Each filter has the function in [0], a boolean in [1][0] of whether it's a variable or a string + // and [1][1] is either the variable name of the string content. + if(filter[1]){ + if(filter[1][0]){ + str = filter[0](str, this.resolvePath(filter[1][1], context)); + }else{ + str = filter[0](str, filter[1][1]); + } + }else{ + str = filter[0](str); + } + } + return str; + }, + resolvePath: function(path, context){ + var current, parts; + var first = path.charAt(0); + var last = path.slice(-1); + if(!isNaN(parseInt(first))){ + current = (path.indexOf(".") == -1) ? parseInt(path) : parseFloat(path); + }else if(first == '"' && first == last){ + current = path.slice(1, -1); + }else{ + if(path == "true"){ return true; } + if(path == "false"){ return false; } + if(path == "null" || path == "None"){ return null; } + parts = path.split("."); + current = context.get(parts[0]); + for(var i = 1; i < parts.length; i++){ + var part = parts[i]; + if(current){ + if(dojo.isObject(current) && part == "items" && typeof current[part] == "undefined"){ + var items = []; + for(var key in current){ + items.push([key, current[key]]); + } + current = items; + continue; + } + + if(current.get && dojo.isFunction(current.get)){ + current = current.get(part); + }else if(typeof current[part] == "undefined"){ + current = current[part]; + break; + }else{ + current = current[part]; + } + + if(dojo.isFunction(current)){ + if(current.alters_data){ + current = ""; + }else{ + current = current(); + } + } + }else{ + return ""; + } + } + } + return current; + } + }); + + dd._TextNode = dd._Node = dojo.extend(function(/*Object*/ obj){ + // summary: Basic catch-all node + this.contents = obj; + }, + { + set: function(data){ + this.contents = data; + }, + render: function(context, buffer){ + // summary: Adds content onto the buffer + return buffer.concat(this.contents); + } + }); + + dd._NodeList = dojo.extend(function(/*Node[]*/ nodes){ + // summary: Allows us to render a group of nodes + this.contents = nodes || []; + this.last = ""; + }, + { + push: function(node){ + // summary: Add a new node to the list + this.contents.push(node); + }, + render: function(context, buffer){ + // summary: Adds all content onto the buffer + for(var i = 0; i < this.contents.length; i++){ + buffer = this.contents[i].render(context, buffer); + if(!buffer) throw new Error("Template must return buffer"); + } + return buffer; + }, + dummyRender: function(context){ + return this.render(context, dd.Template.prototype.getBuffer()).toString(); + }, + unrender: function(){ return arguments[1]; }, + clone: function(){ return this; } + }); + + dd._VarNode = dojo.extend(function(str){ + // summary: A node to be processed as a variable + this.contents = new dd._Filter(str); + }, + { + render: function(context, buffer){ + var str = this.contents.resolve(context); + return buffer.concat(str); + } + }); + + dd._noOpNode = new function(){ + // summary: Adds a no-op node. Useful in custom tags + this.render = this.unrender = function(){ return arguments[1]; } + this.clone = function(){ return this; } + } + + dd._Parser = dojo.extend(function(tokens){ + // summary: Parser used during initialization and for tag groups. + this.contents = tokens; + }, + { + i: 0, + parse: function(/*Array?*/ stop_at){ + // summary: Turns tokens into nodes + // description: Steps into tags are they're found. Blocks use the parse object + // to find their closing tag (the stop_at array). stop_at is inclusive, it + // returns the node that matched. + var types = ddt.types; + var terminators = {}; + stop_at = stop_at || []; + for(var i = 0; i < stop_at.length; i++){ + terminators[stop_at[i]] = true; + } + + var nodelist = new dd._NodeList(); + while(this.i < this.contents.length){ + token = this.contents[this.i++]; + if(dojo.isString(token)){ + nodelist.push(new dd._TextNode(token)); + }else{ + var type = token[0]; + var text = token[1]; + if(type == types.varr){ + nodelist.push(new dd._VarNode(text)); + }else if(type == types.tag){ + if(terminators[text]){ + --this.i; + return nodelist; + } + var cmd = text.split(/\s+/g); + if(cmd.length){ + cmd = cmd[0]; + var fn = ddt.getTag(cmd); + if(fn){ + nodelist.push(fn(this, text)); + } + } + } + } + } + + if(stop_at.length){ + throw new Error("Could not find closing tag(s): " + stop_at.toString()); + } + + this.contents.length = 0; + return nodelist; + }, + next: function(){ + // summary: Returns the next token in the list. + var token = this.contents[this.i++]; + return {type: token[0], text: token[1]}; + }, + skipPast: function(endtag){ + var types = ddt.types; + while(this.i < this.contents.length){ + var token = this.contents[this.i++]; + if(token[0] == types.tag && token[1] == endtag){ + return; + } + } + throw new Error("Unclosed tag found when looking for " + endtag); + }, + getVarNodeConstructor: function(){ + return dd._VarNode; + }, + getTextNodeConstructor: function(){ + return dd._TextNode; + }, + getTemplate: function(file){ + return new dd.Template(file); + } + }); + + dd.register = { + _registry: { + attributes: [], + tags: [], + filters: [] + }, + get: function(/*String*/ module, /*String*/ name){ + var registry = dd.register._registry[module + "s"]; + for(var i = 0, entry; entry = registry[i]; i++){ + if(dojo.isString(entry[0])){ + if(entry[0] == name){ + return entry; + } + }else if(name.match(entry[0])){ + return entry; + } + } + }, + getAttributeTags: function(){ + var tags = []; + var registry = dd.register._registry.attributes; + for(var i = 0, entry; entry = registry[i]; i++){ + if(entry.length == 3){ + tags.push(entry); + }else{ + var fn = dojo.getObject(entry[1]); + if(fn && dojo.isFunction(fn)){ + entry.push(fn); + tags.push(entry); + } + } + } + return tags; + }, + _any: function(type, base, locations){ + for(var path in locations){ + for(var i = 0, fn; fn = locations[path][i]; i++){ + var key = fn; + if(dojo.isArray(fn)){ + key = fn[0]; + fn = fn[1]; + } + if(dojo.isString(key)){ + if(key.substr(0, 5) == "attr:"){ + var attr = fn; + if(attr.substr(0, 5) == "attr:"){ + attr = attr.slice(5); + } + dd.register._registry.attributes.push([attr, base + "." + path + "." + attr]); + } + key = key.toLowerCase(); + } + dd.register._registry[type].push([ + key, + fn, + base + "." + path + ]); + } + } + }, + tags: function(/*String*/ base, /*Object*/ locations){ + dd.register._any("tags", base, locations); + }, + filters: function(/*String*/ base, /*Object*/ locations){ + dd.register._any("filters", base, locations); + } + } + + 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": ["escape", "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"] + }); +})(); + +} -- cgit v1.2.3