зеркало из https://github.com/mozilla/pjs.git
Bug 684721 - GCLI templater and devtools templater need to be in sync; f=mratcliffe, r=rcampbell
This commit is contained in:
Родитель
31a7394182
Коммит
736033156f
|
@ -47,6 +47,8 @@ const Cu = Components.utils;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
var Node = Ci.nsIDOMNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A templater that allows one to quickly template DOM nodes.
|
* 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.
|
* 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.
|
* @param data the data to use for node processing.
|
||||||
*/
|
*/
|
||||||
Templater.prototype.processNode = function(node, data) {
|
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 : ''));
|
this.scope.push(node.nodeName + (node.id ? '#' + node.id : ''));
|
||||||
try {
|
try {
|
||||||
// Process attributes
|
// 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,
|
// 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
|
// but if we do it straight away, we mess up the array index
|
||||||
var attrs = Array.prototype.slice.call(node.attributes);
|
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 value = attrs[i].value;
|
||||||
var name = attrs[i].name;
|
var name = attrs[i].name;
|
||||||
this.scope.push(name);
|
this.scope.push(name);
|
||||||
|
@ -107,10 +116,9 @@ Templater.prototype.processNode = function(node, data) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Replace references in all other attributes
|
// Replace references in all other attributes
|
||||||
var self = this;
|
|
||||||
var newValue = value.replace(/\$\{[^}]*\}/g, function(path) {
|
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
|
// Remove '_' prefix of attribute names so the DOM won't try
|
||||||
// to use them before we've processed the template
|
// to use them before we've processed the template
|
||||||
if (name.charAt(0) === '_') {
|
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
|
// Loop through our children calling processNode. First clone them, so the
|
||||||
// set of nodes that we visit will be unaffected by additions or removals.
|
// set of nodes that we visit will be unaffected by additions or removals.
|
||||||
var children = Array.prototype.slice.call(node.childNodes);
|
var childNodes = Array.prototype.slice.call(node.childNodes);
|
||||||
for (let j = 0, numChildren = children.length; j < numChildren; j++) {
|
for (var j = 0; j < childNodes.length; j++) {
|
||||||
this.processNode(children[j], data);
|
this.processNode(childNodes[j], data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.nodeType === Ci.nsIDOMNode.TEXT_NODE) {
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
this.processTextNode(node, data);
|
this.processTextNode(node, data);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -196,9 +204,7 @@ Templater.prototype.processForEach = function(node, data) {
|
||||||
try {
|
try {
|
||||||
var self = this;
|
var self = this;
|
||||||
// Process a single iteration of a loop
|
// Process a single iteration of a loop
|
||||||
var processSingle = function(member, node, ref) {
|
var processSingle = function(member, clone, ref) {
|
||||||
var clone = node.cloneNode(true);
|
|
||||||
clone.removeAttribute('foreach');
|
|
||||||
ref.parentNode.insertBefore(clone, ref);
|
ref.parentNode.insertBefore(clone, ref);
|
||||||
data[paramName] = member;
|
data[paramName] = member;
|
||||||
self.processNode(clone, data);
|
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
|
// 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) {
|
var processAll = function(scope, member) {
|
||||||
self.scope.push(scope);
|
self.scope.push(scope);
|
||||||
try {
|
try {
|
||||||
if (node.nodeName === 'loop') {
|
if (node.nodeName.toLowerCase() === 'loop') {
|
||||||
for (let i = 0, numChildren = node.children.length; i < numChildren; i++) {
|
for (var i = 0; i < node.childNodes.length; i++) {
|
||||||
processSingle(member, node.children[i], node);
|
var clone = node.childNodes[i].cloneNode(true);
|
||||||
|
processSingle(member, clone, node);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
processSingle(member, node, node);
|
var clone = node.cloneNode(true);
|
||||||
|
clone.removeAttribute('foreach');
|
||||||
|
processSingle(member, clone, node);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
self.scope.pop();
|
self.scope.pop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let reply = this.envEval(value, data, originalValue);
|
var reply = this.envEval(value, data, originalValue);
|
||||||
if (Array.isArray(reply)) {
|
if (Array.isArray(reply)) {
|
||||||
reply.forEach(function(data, i) {
|
reply.forEach(function(data, i) {
|
||||||
processAll('' + i, data)
|
processAll('' + i, data);
|
||||||
}, this);
|
}, this);
|
||||||
} else {
|
} else {
|
||||||
for (let param in reply) {
|
for (var param in reply) {
|
||||||
if (reply.hasOwnProperty(param)) {
|
if (reply.hasOwnProperty(param)) {
|
||||||
processAll(param, param);
|
processAll(param, param);
|
||||||
}
|
}
|
||||||
|
@ -364,7 +373,8 @@ Templater.prototype.envEval = function(script, env, context) {
|
||||||
this.scope.push(context);
|
this.scope.push(context);
|
||||||
return eval(script);
|
return eval(script);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
this.handleError('Template error evaluating \'' + script + '\'', ex);
|
this.handleError('Template error evaluating \'' + script + '\'' +
|
||||||
|
' environment=' + Object.keys(env).join(', '), ex);
|
||||||
return script;
|
return script;
|
||||||
} finally {
|
} finally {
|
||||||
this.scope.pop();
|
this.scope.pop();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче