Bug 684721 - GCLI templater and devtools templater need to be in sync; f=mratcliffe, r=rcampbell

This commit is contained in:
Joe Walker 2011-10-03 12:05:41 -03:00
Родитель 31a7394182
Коммит 736033156f
1 изменённых файлов: 31 добавлений и 21 удалений

Просмотреть файл

@ -47,6 +47,8 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
var Node = Ci.nsIDOMNode;
/**
* A templater that allows one to quickly template DOM nodes.
*/
@ -56,10 +58,17 @@ function Templater() {
/**
* Recursive function to walk the tree processing the attributes as it goes.
* @param node the node to process.
* @param node the node to process. If you pass a string in instead of a DOM
* element, it is assumed to be an id for use with document.getElementById()
* @param data the data to use for node processing.
*/
Templater.prototype.processNode = function(node, data) {
if (typeof node === 'string') {
node = document.getElementById(node);
}
if (data === null || data === undefined) {
data = {};
}
this.scope.push(node.nodeName + (node.id ? '#' + node.id : ''));
try {
// Process attributes
@ -81,7 +90,7 @@ Templater.prototype.processNode = function(node, data) {
// It's good to clean up the attributes when we've processed them,
// but if we do it straight away, we mess up the array index
var attrs = Array.prototype.slice.call(node.attributes);
for (let i = 0, attLen = attrs.length; i < attLen; i++) {
for (var i = 0; i < attrs.length; i++) {
var value = attrs[i].value;
var name = attrs[i].name;
this.scope.push(name);
@ -107,10 +116,9 @@ Templater.prototype.processNode = function(node, data) {
}
} else {
// Replace references in all other attributes
var self = this;
var newValue = value.replace(/\$\{[^}]*\}/g, function(path) {
return self.envEval(path.slice(2, -1), data, value);
});
return this.envEval(path.slice(2, -1), data, value);
}.bind(this));
// Remove '_' prefix of attribute names so the DOM won't try
// to use them before we've processed the template
if (name.charAt(0) === '_') {
@ -128,12 +136,12 @@ Templater.prototype.processNode = function(node, data) {
// Loop through our children calling processNode. First clone them, so the
// set of nodes that we visit will be unaffected by additions or removals.
var children = Array.prototype.slice.call(node.childNodes);
for (let j = 0, numChildren = children.length; j < numChildren; j++) {
this.processNode(children[j], data);
var childNodes = Array.prototype.slice.call(node.childNodes);
for (var j = 0; j < childNodes.length; j++) {
this.processNode(childNodes[j], data);
}
if (node.nodeType === Ci.nsIDOMNode.TEXT_NODE) {
if (node.nodeType === Node.TEXT_NODE) {
this.processTextNode(node, data);
}
} finally {
@ -196,9 +204,7 @@ Templater.prototype.processForEach = function(node, data) {
try {
var self = this;
// Process a single iteration of a loop
var processSingle = function(member, node, ref) {
var clone = node.cloneNode(true);
clone.removeAttribute('foreach');
var processSingle = function(member, clone, ref) {
ref.parentNode.insertBefore(clone, ref);
data[paramName] = member;
self.processNode(clone, data);
@ -206,29 +212,32 @@ Templater.prototype.processForEach = function(node, data) {
};
// processSingle is no good for <loop> nodes where we want to work on
// the children rather than the node itself
// the childNodes rather than the node itself
var processAll = function(scope, member) {
self.scope.push(scope);
try {
if (node.nodeName === 'loop') {
for (let i = 0, numChildren = node.children.length; i < numChildren; i++) {
processSingle(member, node.children[i], node);
if (node.nodeName.toLowerCase() === 'loop') {
for (var i = 0; i < node.childNodes.length; i++) {
var clone = node.childNodes[i].cloneNode(true);
processSingle(member, clone, node);
}
} else {
processSingle(member, node, node);
var clone = node.cloneNode(true);
clone.removeAttribute('foreach');
processSingle(member, clone, node);
}
} finally {
self.scope.pop();
}
};
let reply = this.envEval(value, data, originalValue);
var reply = this.envEval(value, data, originalValue);
if (Array.isArray(reply)) {
reply.forEach(function(data, i) {
processAll('' + i, data)
processAll('' + i, data);
}, this);
} else {
for (let param in reply) {
for (var param in reply) {
if (reply.hasOwnProperty(param)) {
processAll(param, param);
}
@ -364,7 +373,8 @@ Templater.prototype.envEval = function(script, env, context) {
this.scope.push(context);
return eval(script);
} catch (ex) {
this.handleError('Template error evaluating \'' + script + '\'', ex);
this.handleError('Template error evaluating \'' + script + '\'' +
' environment=' + Object.keys(env).join(', '), ex);
return script;
} finally {
this.scope.pop();