Refactorización Vn.Builder
This commit is contained in:
parent
f6603ccc13
commit
2e9ea7ac33
|
@ -99,7 +99,7 @@ module.exports = new Class
|
||||||
var error = new Error (message);
|
var error = new Error (message);
|
||||||
error.fileName = file;
|
error.fileName = file;
|
||||||
error.lineNumber = line;
|
error.lineNumber = line;
|
||||||
this._notifyError (error);
|
//this._notifyError (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
,_onConnError: function (conn, error)
|
,_onConnError: function (conn, error)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
var kebabToPascal = require ('../vn/string-util').kebabToPascal;
|
||||||
|
|
||||||
module.exports = new Class
|
module.exports = new Class
|
||||||
({
|
({
|
||||||
basePath: null
|
basePath: null
|
||||||
|
@ -83,7 +85,7 @@ module.exports = new Class
|
||||||
|
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
|
|
||||||
var klassName = this.toCamelCase (this.moduleName);
|
var klassName = kebabToPascal (this.moduleName);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.klass = Hedera[klassName];
|
this.klass = Hedera[klassName];
|
||||||
|
@ -101,15 +103,5 @@ module.exports = new Class
|
||||||
for (var i = 0; i < callbacks.length; i++)
|
for (var i = 0; i < callbacks.length; i++)
|
||||||
callbacks[i] (this);
|
callbacks[i] (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
,toCamelCase: function (dashedName)
|
|
||||||
{
|
|
||||||
var camelCase = dashedName.charAt (0).toUpperCase ();
|
|
||||||
camelCase += dashedName.substr (1).replace (/\w\-\w/g, function (token)
|
|
||||||
{
|
|
||||||
return token.charAt (0) + token.charAt (2).toUpperCase ();
|
|
||||||
});
|
|
||||||
return camelCase;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
647
js/vn/builder.js
647
js/vn/builder.js
|
@ -1,15 +1,16 @@
|
||||||
|
|
||||||
var VnObject = require ('./object');
|
var VnObject = require ('./object');
|
||||||
var Component = require ('./component');
|
var Scope = require ('./scope');
|
||||||
var Type = require ('./type');
|
|
||||||
|
|
||||||
var specialAttrs = {
|
var CompilerObject = require ('./compiler-object');
|
||||||
id : 1,
|
var CompilerElement = require ('./compiler-element');
|
||||||
property : 1
|
var CompilerText = require ('./compiler-text');
|
||||||
};
|
|
||||||
var objectAttrs = {
|
var regCompilers = [
|
||||||
for : 1
|
CompilerObject,
|
||||||
};
|
CompilerElement,
|
||||||
|
CompilerText
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a object from a XML specification.
|
* Creates a object from a XML specification.
|
||||||
|
@ -17,7 +18,7 @@ var objectAttrs = {
|
||||||
module.exports = new Class
|
module.exports = new Class
|
||||||
({
|
({
|
||||||
Extends: VnObject
|
Extends: VnObject
|
||||||
,_addedMap: {}
|
|
||||||
,_contexts: null
|
,_contexts: null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,13 +57,13 @@ module.exports = new Class
|
||||||
if (!doc)
|
if (!doc)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._compileInit ();
|
this._preCompile ();
|
||||||
|
|
||||||
var docElement = doc.documentElement;
|
var docElement = doc.documentElement;
|
||||||
|
|
||||||
if (docElement.tagName !== 'vn')
|
if (docElement.tagName !== 'vn')
|
||||||
{
|
{
|
||||||
this._showError ('The toplevel tag should be named \'vn\'');
|
this.showError ('The toplevel tag should be named \'vn\'');
|
||||||
this._contexts = null;
|
this._contexts = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -71,9 +72,9 @@ module.exports = new Class
|
||||||
|
|
||||||
if (childs)
|
if (childs)
|
||||||
for (var i = 0; i < childs.length; i++)
|
for (var i = 0; i < childs.length; i++)
|
||||||
this._compileNode (childs[i]);
|
this._compile (childs[i]);
|
||||||
|
|
||||||
this._compileEnd ();
|
this._postCompile ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,80 +86,44 @@ module.exports = new Class
|
||||||
*/
|
*/
|
||||||
,compileNode: function (node)
|
,compileNode: function (node)
|
||||||
{
|
{
|
||||||
this._compileInit ();
|
this._preCompile ();
|
||||||
this._mainContext = this._compileNode (node).id;
|
this._mainContext = this._compile (node).id;
|
||||||
this._compileEnd ();
|
this._postCompile ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new scope from a compiled XML tree.
|
* Called before starting to compile nodes.
|
||||||
*
|
|
||||||
* @param {Document} dstDocument The document used to create the nodes
|
|
||||||
* @param {Object} signalData The object where to bind methods
|
|
||||||
* @param {Scope} parentScope The parent scope or %null for no parent
|
|
||||||
* @return {Scope} The created scope
|
|
||||||
*/
|
*/
|
||||||
,load: function (dstDocument, signalData, parentScope, extraObjects)
|
,_preCompile: function ()
|
||||||
{
|
|
||||||
if (this._contexts === null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
this._doc = dstDocument || document;
|
|
||||||
|
|
||||||
var contexts = this._contexts;
|
|
||||||
var len = contexts.length;
|
|
||||||
var objects = new Array (len);
|
|
||||||
var scope = new Scope (this, objects, signalData, parentScope, extraObjects)
|
|
||||||
|
|
||||||
for (var i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
var context = contexts[i];
|
|
||||||
|
|
||||||
if (context.tagName)
|
|
||||||
objects[i] = this.elementInstantiate (context, scope);
|
|
||||||
else if (context.klass)
|
|
||||||
objects[i] = this.objectInstantiate (context, scope);
|
|
||||||
else
|
|
||||||
objects[i] = this.textInstantiate (context, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
,_compileInit: function ()
|
|
||||||
{
|
{
|
||||||
this._path = null;
|
this._path = null;
|
||||||
this._tags = {};
|
this._tags = {};
|
||||||
this._contexts = [];
|
this._contexts = [];
|
||||||
this._contextMap = {};
|
this._contextMap = {};
|
||||||
this._objectLinks = [];
|
|
||||||
this._mainContext = null;
|
this._mainContext = null;
|
||||||
|
|
||||||
|
var compilers = [];
|
||||||
|
this._compilers = compilers;
|
||||||
|
|
||||||
|
for (var i = 0; i < regCompilers.length; i++)
|
||||||
|
compilers.push (new regCompilers[i] (this));
|
||||||
}
|
}
|
||||||
|
|
||||||
,_compileEnd: function ()
|
/**
|
||||||
|
* Called after all nodes have been compiled.
|
||||||
|
*/
|
||||||
|
,_postCompile: function ()
|
||||||
{
|
{
|
||||||
var links = this._objectLinks;
|
var compilers = this._compilers;
|
||||||
|
for (var i = 0; i < compilers.length; i++)
|
||||||
for (var i = links.length - 1; i >= 0; i--)
|
compilers[i].postCompile (this._contextMap);
|
||||||
{
|
|
||||||
var link = links[i];
|
|
||||||
var context = link.context;
|
|
||||||
var contextId = this._contextMap[link.objectId];
|
|
||||||
|
|
||||||
if (contextId == undefined)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (link.prop)
|
|
||||||
context.objectProps[link.prop] = contextId;
|
|
||||||
else
|
|
||||||
context.childs.push (contextId);
|
|
||||||
|
|
||||||
links.splice (i, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
,_compileNode: function (node)
|
/**
|
||||||
|
* Compiles a node.
|
||||||
|
*/
|
||||||
|
,_compile: function (node)
|
||||||
{
|
{
|
||||||
var context = null;
|
var context = null;
|
||||||
var tagName = null;
|
var tagName = null;
|
||||||
|
@ -170,12 +135,12 @@ module.exports = new Class
|
||||||
|| /^[\n\r\t]*$/.test (node.textContent))
|
|| /^[\n\r\t]*$/.test (node.textContent))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var context =
|
var compilers = this._compilers;
|
||||||
this.textCompile (node, tagName)
|
for (var i = 0; i < compilers.length && context === null; i++)
|
||||||
|| this.objectCompile (node, tagName)
|
context = compilers[i].compile (this, node, tagName);
|
||||||
|| this.elementCompile (node, tagName);
|
|
||||||
|
|
||||||
context.id = this._contexts.length;
|
context.id = this._contexts.length;
|
||||||
|
context.compiler = compilers[i - 1];
|
||||||
|
|
||||||
if (isElement)
|
if (isElement)
|
||||||
{
|
{
|
||||||
|
@ -199,373 +164,66 @@ module.exports = new Class
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new scope from a compiled XML tree.
|
||||||
|
*
|
||||||
|
* @param {Document} dstDocument The document used to create the nodes
|
||||||
|
* @param {Object} signalData The object where to bind methods
|
||||||
|
* @param {Scope} parentScope The parent scope or %null for no parent
|
||||||
|
* @return {Scope} The created scope
|
||||||
|
*/
|
||||||
|
,load: function (dstDocument, signalData, parentScope, extraObjects)
|
||||||
|
{
|
||||||
|
if (this._contexts === null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var doc = dstDocument ? dstDocument : document;
|
||||||
|
var contexts = this._contexts;
|
||||||
|
var len = contexts.length;
|
||||||
|
var objects = new Array (len);
|
||||||
|
var scope = new Scope (this, objects, signalData, parentScope, extraObjects)
|
||||||
|
|
||||||
|
for (var i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
var context = contexts[i];
|
||||||
|
objects[i] = context.compiler.instantiate (doc, context, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Links all scope objects and connects it's events.
|
||||||
|
*/
|
||||||
,link: function (scope)
|
,link: function (scope)
|
||||||
{
|
{
|
||||||
var objects = scope.objects;
|
|
||||||
var links = this._objectLinks;
|
|
||||||
|
|
||||||
for (var i = links.length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
var link = links[i];
|
|
||||||
var object = objects[link.context.id];
|
|
||||||
var objectRef = scope.$(link.objectId);
|
|
||||||
|
|
||||||
if (objectRef == null)
|
|
||||||
{
|
|
||||||
this._showError ('Referenced unexistent object with id \'%s\'',
|
|
||||||
link.objectId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (link.prop)
|
|
||||||
object[link.prop] = objectRef;
|
|
||||||
else
|
|
||||||
object.appendChild (objectRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
var contexts = this._contexts;
|
var contexts = this._contexts;
|
||||||
|
var objects = scope.objects;
|
||||||
|
|
||||||
for (var i = 0; i < contexts.length; i++)
|
for (var i = 0; i < contexts.length; i++)
|
||||||
{
|
{
|
||||||
var context = contexts[i];
|
var context = contexts[i];
|
||||||
var object = objects[i];
|
context.compiler.link (context, objects[i], objects, scope);
|
||||||
|
|
||||||
if (context.tagName)
|
|
||||||
this.elementLink (context, object, objects, scope);
|
|
||||||
else if (context.klass)
|
|
||||||
this.objectLink (context, object, objects, scope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < contexts.length; i++)
|
for (var i = 0; i < contexts.length; i++)
|
||||||
{
|
{
|
||||||
var context = contexts[i];
|
var context = contexts[i];
|
||||||
var object = objects[i];
|
context.compiler.connect (context, objects[i], objects, scope);
|
||||||
|
|
||||||
if (context.tagName)
|
|
||||||
this.elementConnect (context, object, objects, scope);
|
|
||||||
else if (context.klass)
|
|
||||||
this.objectConnect (context, object, objects, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a object context.
|
|
||||||
*/
|
|
||||||
,objectCompile: function (node, tagName)
|
|
||||||
{
|
|
||||||
var klass = vnCustomTags[tagName];
|
|
||||||
|
|
||||||
if (!klass)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var props = {};
|
|
||||||
var objectProps = {};
|
|
||||||
var funcProps = {};
|
|
||||||
var childs = [];
|
|
||||||
var events = {};
|
|
||||||
|
|
||||||
var context = {
|
|
||||||
klass: klass,
|
|
||||||
props: props,
|
|
||||||
objectProps: objectProps,
|
|
||||||
funcProps: funcProps,
|
|
||||||
childs: childs,
|
|
||||||
events: events,
|
|
||||||
custom: null
|
|
||||||
};
|
|
||||||
|
|
||||||
var a = node.attributes;
|
|
||||||
|
|
||||||
for (var i = 0; i < a.length; i++)
|
|
||||||
{
|
|
||||||
var attribute = a[i].nodeName;
|
|
||||||
var value = a[i].nodeValue;
|
|
||||||
|
|
||||||
if (this._isEvent (attribute))
|
|
||||||
events[attribute.substr (3)] = value;
|
|
||||||
else if (!specialAttrs[attribute])
|
|
||||||
{
|
|
||||||
this.propCompile (context, klass, props,
|
|
||||||
node, attribute, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var childNodes = node.childNodes;
|
var compilers = this._compilers;
|
||||||
|
for (var i = 0; i < compilers.length; i++)
|
||||||
if (childNodes)
|
compilers[i].postLink (scope);
|
||||||
for (var i = 0; i < childNodes.length; i++)
|
|
||||||
{
|
|
||||||
var child = childNodes[i];
|
|
||||||
var childContext = null;
|
|
||||||
var childTagName = null;
|
|
||||||
|
|
||||||
if (child.nodeType === Node.ELEMENT_NODE)
|
|
||||||
childTagName = child.tagName.toLowerCase ();
|
|
||||||
|
|
||||||
if (childTagName === 'pointer')
|
|
||||||
{
|
|
||||||
this.objectAddLink (context, null, child.getAttribute ('object'));
|
|
||||||
}
|
|
||||||
else if (childTagName === 'custom')
|
|
||||||
{
|
|
||||||
context.custom = child;
|
|
||||||
}
|
|
||||||
else if (childContext = this._compileNode (child))
|
|
||||||
{
|
|
||||||
var prop = null;
|
|
||||||
|
|
||||||
if (childTagName)
|
|
||||||
prop = child.getAttribute ('property');
|
|
||||||
|
|
||||||
if (prop)
|
|
||||||
{
|
|
||||||
prop = prop.replace (/-./g, this._replaceFunc);
|
|
||||||
objectProps[prop] = childContext.id;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
childs.push (childContext.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
,propCompile: function (context, klass, props, node, attribute, value)
|
/**
|
||||||
{
|
* Logs an error parsing the node.
|
||||||
var isLink = false;
|
*
|
||||||
var newValue = null;
|
* @param {String} error The error message template
|
||||||
var propName = attribute.replace (/-./g, this._replaceFunc);
|
* @param {...} varArgs The message template arguments
|
||||||
var propInfo = klass.Properties[propName];
|
*/
|
||||||
|
,showError: function (error)
|
||||||
if (!propInfo)
|
|
||||||
{
|
|
||||||
this._showError ('Attribute \'%s\' not valid for tag \'%s\'',
|
|
||||||
attribute, node.tagName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!value)
|
|
||||||
{
|
|
||||||
this._showError ('Attribute \'%s\' empty on tag \'%s\'',
|
|
||||||
attribute, node.tagName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var propError = false;
|
|
||||||
|
|
||||||
switch (propInfo.type)
|
|
||||||
{
|
|
||||||
case null:
|
|
||||||
newValue = value;
|
|
||||||
break;
|
|
||||||
case Boolean:
|
|
||||||
newValue = (/^(true|1)$/i).test (value);
|
|
||||||
break;
|
|
||||||
case Number:
|
|
||||||
newValue = 0 + new Number (value);
|
|
||||||
break;
|
|
||||||
case String:
|
|
||||||
newValue = this._translateValue (value);
|
|
||||||
break;
|
|
||||||
case Function:
|
|
||||||
context.funcProps[propName] = value;
|
|
||||||
break;
|
|
||||||
case Type:
|
|
||||||
newValue = window[value];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (propInfo.enumType)
|
|
||||||
newValue = propInfo.enumType[value];
|
|
||||||
else if (propInfo.type instanceof Function)
|
|
||||||
isLink = true;
|
|
||||||
else
|
|
||||||
propError = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLink)
|
|
||||||
this.objectAddLink (context, propName, value);
|
|
||||||
else if (newValue != null)
|
|
||||||
props[propName] = newValue;
|
|
||||||
else if (propError)
|
|
||||||
this._showError ('Attribute \'%s\' invalid for tag \'%s\'',
|
|
||||||
attribute, node.tagName);
|
|
||||||
}
|
|
||||||
|
|
||||||
,objectAddLink: function (context, prop, objectId)
|
|
||||||
{
|
|
||||||
this._objectLinks.push ({
|
|
||||||
context: context
|
|
||||||
,prop: prop
|
|
||||||
,objectId: objectId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
,objectInstantiate: function (context, scope)
|
|
||||||
{
|
|
||||||
var object = new context.klass ();
|
|
||||||
object.setProperties (context.props);
|
|
||||||
|
|
||||||
if (context.nodeId && object instanceof Component)
|
|
||||||
object.htmlId = scope.getHtmlId (context.nodeId);
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
,objectLink: function (context, object, objects, scope)
|
|
||||||
{
|
|
||||||
var objectProps = context.objectProps;
|
|
||||||
for (var prop in objectProps)
|
|
||||||
object[prop] = objects[objectProps[prop]];
|
|
||||||
|
|
||||||
var childs = context.childs;
|
|
||||||
for (var i = 0; i < childs.length; i++)
|
|
||||||
object.appendChild (objects[childs[i]]);
|
|
||||||
|
|
||||||
if (context.custom)
|
|
||||||
object.loadXml (scope, context.custom);
|
|
||||||
}
|
|
||||||
|
|
||||||
,objectConnect: function (context, object, objects, scope)
|
|
||||||
{
|
|
||||||
var funcProps = context.funcProps;
|
|
||||||
for (var prop in funcProps)
|
|
||||||
{
|
|
||||||
var method = scope.getMethod (funcProps[prop], true);
|
|
||||||
|
|
||||||
if (method)
|
|
||||||
object[prop] = method;
|
|
||||||
}
|
|
||||||
|
|
||||||
var events = context.events;
|
|
||||||
for (var event in events)
|
|
||||||
{
|
|
||||||
var method = scope.getMethod (events[event]);
|
|
||||||
|
|
||||||
if (method)
|
|
||||||
object.on (event, method, scope.signalData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a HTML node context.
|
|
||||||
*/
|
|
||||||
,elementCompile: function (node, tagName)
|
|
||||||
{
|
|
||||||
var props = {};
|
|
||||||
var objectProps = {};
|
|
||||||
var childs = [];
|
|
||||||
var events = {};
|
|
||||||
|
|
||||||
var a = node.attributes;
|
|
||||||
|
|
||||||
for (var i = 0; i < a.length; i++)
|
|
||||||
{
|
|
||||||
var attribute = a[i].nodeName;
|
|
||||||
var value = a[i].nodeValue;
|
|
||||||
|
|
||||||
if (this._isEvent (attribute))
|
|
||||||
events[attribute.substr (3)] = value;
|
|
||||||
else if (objectAttrs[attribute])
|
|
||||||
objectProps[attribute] = value;
|
|
||||||
else if (!specialAttrs[attribute])
|
|
||||||
props[attribute] = this._translateValue (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
var childContext;
|
|
||||||
var childNodes = node.childNodes;
|
|
||||||
|
|
||||||
if (childNodes)
|
|
||||||
for (var i = 0; i < childNodes.length; i++)
|
|
||||||
if (childContext = this._compileNode (childNodes[i]))
|
|
||||||
childs.push (childContext.id);
|
|
||||||
|
|
||||||
return {
|
|
||||||
tagName: tagName,
|
|
||||||
props: props,
|
|
||||||
objectProps: objectProps,
|
|
||||||
childs: childs,
|
|
||||||
events: events
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
,elementInstantiate: function (context, scope)
|
|
||||||
{
|
|
||||||
var object = this._doc.createElement (context.tagName);
|
|
||||||
|
|
||||||
var props = context.props;
|
|
||||||
for (var prop in props)
|
|
||||||
object.setAttribute (prop, props[prop]);
|
|
||||||
|
|
||||||
if (context.nodeId)
|
|
||||||
object.setAttribute ('id', scope.getHtmlId (context.nodeId));
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
,elementLink: function (context, object, objects, scope)
|
|
||||||
{
|
|
||||||
var props = context.objectProps;
|
|
||||||
for (var prop in props)
|
|
||||||
{
|
|
||||||
var objectValue = scope.$(props[prop]);
|
|
||||||
var htmlId;
|
|
||||||
|
|
||||||
if (objectValue instanceof Component)
|
|
||||||
htmlId = objectValue.htmlId;
|
|
||||||
if (objectValue instanceof Node)
|
|
||||||
htmlId = objectValue.id;
|
|
||||||
|
|
||||||
object.setAttribute (prop, htmlId);
|
|
||||||
}
|
|
||||||
|
|
||||||
var childs = context.childs;
|
|
||||||
for (var i = 0; i < childs.length; i++)
|
|
||||||
{
|
|
||||||
var child = objects[childs[i]];
|
|
||||||
|
|
||||||
if (child instanceof Component)
|
|
||||||
child = child.node;
|
|
||||||
if (child instanceof Node)
|
|
||||||
object.appendChild (child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
,elementConnect: function (context, object, objects, scope)
|
|
||||||
{
|
|
||||||
var events = context.events;
|
|
||||||
for (var event in events)
|
|
||||||
{
|
|
||||||
var method = scope.getMethod (events[event], true);
|
|
||||||
|
|
||||||
if (method)
|
|
||||||
object.addEventListener (event, method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a text node context.
|
|
||||||
*/
|
|
||||||
,textCompile: function (node, tagName)
|
|
||||||
{
|
|
||||||
if (!tagName)
|
|
||||||
{
|
|
||||||
var text = node.textContent;
|
|
||||||
|
|
||||||
if (/^[\s]*\\?_.*/.test (text))
|
|
||||||
text = _(text.trim ().substr (1));
|
|
||||||
}
|
|
||||||
else if (tagName === 't')
|
|
||||||
var text = _(node.firstChild.textContent);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return {text: text};
|
|
||||||
}
|
|
||||||
|
|
||||||
,textInstantiate: function (context)
|
|
||||||
{
|
|
||||||
return this._doc.createTextNode (context.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
,_showError: function (error)
|
|
||||||
{
|
{
|
||||||
var path = this._path ? this._path : 'Node';
|
var path = this._path ? this._path : 'Node';
|
||||||
var logArgs = ['Vn.Builder: %s: '+ error, path];
|
var logArgs = ['Vn.Builder: %s: '+ error, path];
|
||||||
|
@ -576,28 +234,6 @@ module.exports = new Class
|
||||||
console.warn.apply (console, logArgs);
|
console.warn.apply (console, logArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
,_translateValue: function (value)
|
|
||||||
{
|
|
||||||
var chr = value.charAt (0);
|
|
||||||
|
|
||||||
if (chr === '_')
|
|
||||||
return _(value.substr (1));
|
|
||||||
else if (chr === '\\' && value.charAt (1) === '_')
|
|
||||||
return value.substr (1);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
,_isEvent: function (attribute)
|
|
||||||
{
|
|
||||||
return /^on-\w+/.test (attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
,_replaceFunc: function (token)
|
|
||||||
{
|
|
||||||
return token.charAt(1).toUpperCase ();
|
|
||||||
}
|
|
||||||
|
|
||||||
,getMain: function (result)
|
,getMain: function (result)
|
||||||
{
|
{
|
||||||
return result.objects[this._mainContext];
|
return result.objects[this._mainContext];
|
||||||
|
@ -608,7 +244,7 @@ module.exports = new Class
|
||||||
return this._contextMap[objectId];
|
return this._contextMap[objectId];
|
||||||
}
|
}
|
||||||
|
|
||||||
,getByTagName: function (result, tagName)
|
,getByTagName: function (scope, tagName)
|
||||||
{
|
{
|
||||||
var tags = this._tags[tagName];
|
var tags = this._tags[tagName];
|
||||||
|
|
||||||
|
@ -617,7 +253,7 @@ module.exports = new Class
|
||||||
var arr = new Array (tags.length);
|
var arr = new Array (tags.length);
|
||||||
|
|
||||||
for (var i = 0; i < tags.length; i++)
|
for (var i = 0; i < tags.length; i++)
|
||||||
arr[i] = result.objects[tags[i]];
|
arr[i] = scope.objects[tags[i]];
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
@ -625,110 +261,3 @@ module.exports = new Class
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var scopeUid = 0;
|
|
||||||
|
|
||||||
var Scope = new Class
|
|
||||||
({
|
|
||||||
Extends: VnObject
|
|
||||||
|
|
||||||
,initialize: function (builder, objects, signalData, parentScope, extraObjects)
|
|
||||||
{
|
|
||||||
this.builder = builder;
|
|
||||||
this.objects = objects;
|
|
||||||
this.signalData = signalData;
|
|
||||||
this.parentScope = parentScope;
|
|
||||||
this.uid = ++scopeUid;
|
|
||||||
this.extraObjects = extraObjects;
|
|
||||||
|
|
||||||
if (!signalData && parentScope)
|
|
||||||
this.signalData = parentScope.signalData;
|
|
||||||
|
|
||||||
this.parent ();
|
|
||||||
}
|
|
||||||
|
|
||||||
,getMain: function ()
|
|
||||||
{
|
|
||||||
return this.builder.getMain (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetchs an element by it's identifier.
|
|
||||||
*
|
|
||||||
* @param {String} id The node identifier
|
|
||||||
*/
|
|
||||||
,$: function (id)
|
|
||||||
{
|
|
||||||
var object;
|
|
||||||
var index = this.builder.getById (id);
|
|
||||||
|
|
||||||
if (index !== undefined)
|
|
||||||
object = this.objects[index];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
object = this.extraObjects[id];
|
|
||||||
|
|
||||||
if (object === undefined && this.parentScope)
|
|
||||||
object = this.parentScope.getById (id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return object ? object : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetchs an element by it's identifier.
|
|
||||||
*
|
|
||||||
* @param {String} id The node identifier
|
|
||||||
*/
|
|
||||||
,getById: function (id)
|
|
||||||
{
|
|
||||||
return this.$(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
,getByTagName: function (tagName)
|
|
||||||
{
|
|
||||||
return this.builder.getByTagName (this, tagName);
|
|
||||||
}
|
|
||||||
|
|
||||||
,link: function ()
|
|
||||||
{
|
|
||||||
this.builder.link (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
,getMethod: function (value, binded)
|
|
||||||
{
|
|
||||||
if (this.signalData)
|
|
||||||
{
|
|
||||||
var method = this.signalData[value];
|
|
||||||
|
|
||||||
if (method && binded)
|
|
||||||
method = method.bind (this.signalData);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
var method = window[value];
|
|
||||||
|
|
||||||
if (method === undefined)
|
|
||||||
this.builder._showError ('Function \'%s\' not found', value);
|
|
||||||
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
,getHtmlId: function (nodeId)
|
|
||||||
{
|
|
||||||
return 'vn-'+ this.uid +'-'+ nodeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
,_destroy: function ()
|
|
||||||
{
|
|
||||||
var objects = this.objects;
|
|
||||||
|
|
||||||
for (var i = objects.length; i--;)
|
|
||||||
if (objects[i] instanceof VnObject)
|
|
||||||
{
|
|
||||||
objects[i].unref ();
|
|
||||||
objects[i].disconnectByInstance (this.builder.signalData);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.parent ();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
|
||||||
|
var Compiler = require ('./compiler');
|
||||||
|
var Component = require ('./component');
|
||||||
|
|
||||||
|
var specialAttrs = {
|
||||||
|
id : 1,
|
||||||
|
property : 1
|
||||||
|
};
|
||||||
|
var objectAttrs = {
|
||||||
|
for : 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a @HTML.Node from element tag.
|
||||||
|
*/
|
||||||
|
module.exports = new Class
|
||||||
|
({
|
||||||
|
Extends: Compiler
|
||||||
|
|
||||||
|
,compile: function (builder, node, tagName)
|
||||||
|
{
|
||||||
|
if (!tagName)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var props = {};
|
||||||
|
var objectProps = {};
|
||||||
|
var childs = [];
|
||||||
|
var events = {};
|
||||||
|
|
||||||
|
var a = node.attributes;
|
||||||
|
|
||||||
|
for (var i = 0; i < a.length; i++)
|
||||||
|
{
|
||||||
|
var attribute = a[i].nodeName;
|
||||||
|
var value = a[i].nodeValue;
|
||||||
|
|
||||||
|
if (this.isEvent (attribute))
|
||||||
|
events[attribute.substr (3)] = value;
|
||||||
|
else if (objectAttrs[attribute])
|
||||||
|
objectProps[attribute] = value;
|
||||||
|
else if (!specialAttrs[attribute])
|
||||||
|
props[attribute] = this.translateValue (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
var childContext;
|
||||||
|
var childNodes = node.childNodes;
|
||||||
|
|
||||||
|
if (childNodes)
|
||||||
|
for (var i = 0; i < childNodes.length; i++)
|
||||||
|
if (childContext = builder._compile (childNodes[i]))
|
||||||
|
childs.push (childContext.id);
|
||||||
|
|
||||||
|
return {
|
||||||
|
tagName: tagName,
|
||||||
|
props: props,
|
||||||
|
objectProps: objectProps,
|
||||||
|
childs: childs,
|
||||||
|
events: events
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
,instantiate: function (doc, context, scope)
|
||||||
|
{
|
||||||
|
var object = doc.createElement (context.tagName);
|
||||||
|
|
||||||
|
var props = context.props;
|
||||||
|
for (var prop in props)
|
||||||
|
object.setAttribute (prop, props[prop]);
|
||||||
|
|
||||||
|
if (context.nodeId)
|
||||||
|
object.setAttribute ('id', scope.getHtmlId (context.nodeId));
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
,link: function (context, object, objects, scope)
|
||||||
|
{
|
||||||
|
var props = context.objectProps;
|
||||||
|
for (var prop in props)
|
||||||
|
{
|
||||||
|
var objectValue = scope.$(props[prop]);
|
||||||
|
var htmlId;
|
||||||
|
|
||||||
|
if (objectValue instanceof Component)
|
||||||
|
htmlId = objectValue.htmlId;
|
||||||
|
if (objectValue instanceof Node)
|
||||||
|
htmlId = objectValue.id;
|
||||||
|
|
||||||
|
object.setAttribute (prop, htmlId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var childs = context.childs;
|
||||||
|
for (var i = 0; i < childs.length; i++)
|
||||||
|
{
|
||||||
|
var child = objects[childs[i]];
|
||||||
|
|
||||||
|
if (child instanceof Component)
|
||||||
|
child = child.node;
|
||||||
|
if (child instanceof Node)
|
||||||
|
object.appendChild (child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
,connect: function (context, object, objects, scope)
|
||||||
|
{
|
||||||
|
var events = context.events;
|
||||||
|
for (var event in events)
|
||||||
|
{
|
||||||
|
var method = scope.getMethod (events[event], true);
|
||||||
|
|
||||||
|
if (method)
|
||||||
|
object.addEventListener (event, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,262 @@
|
||||||
|
|
||||||
|
var Compiler = require ('./compiler');
|
||||||
|
var Component = require ('./component');
|
||||||
|
var Type = require ('./type');
|
||||||
|
var kebabToCamel = require ('./string-util').kebabToCamel;
|
||||||
|
|
||||||
|
var specialAttrs = {
|
||||||
|
id : 1,
|
||||||
|
property : 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a @Vn.Object from element tag.
|
||||||
|
*/
|
||||||
|
module.exports = new Class
|
||||||
|
({
|
||||||
|
Extends: Compiler
|
||||||
|
|
||||||
|
,_links: []
|
||||||
|
|
||||||
|
,compile: function (builder, node, tagName)
|
||||||
|
{
|
||||||
|
var klass = vnCustomTags[tagName];
|
||||||
|
|
||||||
|
if (!klass)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var props = {};
|
||||||
|
var objectProps = {};
|
||||||
|
var funcProps = {};
|
||||||
|
var childs = [];
|
||||||
|
var events = {};
|
||||||
|
|
||||||
|
var context = {
|
||||||
|
klass: klass,
|
||||||
|
props: props,
|
||||||
|
objectProps: objectProps,
|
||||||
|
funcProps: funcProps,
|
||||||
|
childs: childs,
|
||||||
|
events: events,
|
||||||
|
custom: null
|
||||||
|
};
|
||||||
|
|
||||||
|
var a = node.attributes;
|
||||||
|
|
||||||
|
for (var i = 0; i < a.length; i++)
|
||||||
|
{
|
||||||
|
var attribute = a[i].nodeName;
|
||||||
|
var value = a[i].nodeValue;
|
||||||
|
|
||||||
|
if (this.isEvent (attribute))
|
||||||
|
events[attribute.substr (3)] = value;
|
||||||
|
else if (!specialAttrs[attribute])
|
||||||
|
this.propCompile (context, klass, node, attribute, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
var childNodes = node.childNodes;
|
||||||
|
|
||||||
|
if (childNodes)
|
||||||
|
for (var i = 0; i < childNodes.length; i++)
|
||||||
|
{
|
||||||
|
var child = childNodes[i];
|
||||||
|
var childContext = null;
|
||||||
|
var childTagName = null;
|
||||||
|
|
||||||
|
if (child.nodeType === Node.ELEMENT_NODE)
|
||||||
|
childTagName = child.tagName.toLowerCase ();
|
||||||
|
|
||||||
|
if (childTagName === 'pointer')
|
||||||
|
{
|
||||||
|
this.addLink (context, null, child.getAttribute ('object'));
|
||||||
|
}
|
||||||
|
else if (childTagName === 'custom')
|
||||||
|
{
|
||||||
|
context.custom = child;
|
||||||
|
}
|
||||||
|
else if (childContext = builder._compile (child))
|
||||||
|
{
|
||||||
|
var prop = null;
|
||||||
|
|
||||||
|
if (childTagName)
|
||||||
|
prop = child.getAttribute ('property');
|
||||||
|
|
||||||
|
if (prop)
|
||||||
|
{
|
||||||
|
prop = kebabToCamel (prop);
|
||||||
|
objectProps[prop] = childContext.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
childs.push (childContext.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
,propCompile: function (context, klass, node, attribute, value)
|
||||||
|
{
|
||||||
|
var isLink = false;
|
||||||
|
var propError = false;
|
||||||
|
var newValue = null;
|
||||||
|
var propName = kebabToCamel (attribute);
|
||||||
|
var propInfo = klass.Properties[propName];
|
||||||
|
|
||||||
|
if (!propInfo)
|
||||||
|
{
|
||||||
|
this.showError ('Attribute \'%s\' not valid for tag \'%s\'',
|
||||||
|
attribute, node.tagName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
this.showError ('Attribute \'%s\' empty on tag \'%s\'',
|
||||||
|
attribute, node.tagName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (propInfo.type)
|
||||||
|
{
|
||||||
|
case null:
|
||||||
|
newValue = value;
|
||||||
|
break;
|
||||||
|
case Boolean:
|
||||||
|
newValue = (/^(true|1)$/i).test (value);
|
||||||
|
break;
|
||||||
|
case Number:
|
||||||
|
newValue = 0 + new Number (value);
|
||||||
|
break;
|
||||||
|
case String:
|
||||||
|
newValue = this.translateValue (value);
|
||||||
|
break;
|
||||||
|
case Function:
|
||||||
|
context.funcProps[propName] = value;
|
||||||
|
break;
|
||||||
|
case Type:
|
||||||
|
newValue = window[value];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (propInfo.enumType)
|
||||||
|
newValue = propInfo.enumType[value];
|
||||||
|
else if (propInfo.type instanceof Function)
|
||||||
|
isLink = true;
|
||||||
|
else
|
||||||
|
propError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLink)
|
||||||
|
this.addLink (context, propName, value);
|
||||||
|
else if (newValue != null)
|
||||||
|
context.props[propName] = newValue;
|
||||||
|
else if (propError)
|
||||||
|
this.showError ('Attribute \'%s\' invalid for tag \'%s\'',
|
||||||
|
attribute, node.tagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
,postCompile: function (contextMap)
|
||||||
|
{
|
||||||
|
var links = this._links;
|
||||||
|
|
||||||
|
for (var i = links.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var link = links[i];
|
||||||
|
var context = link.context;
|
||||||
|
var contextId = contextMap[link.objectId];
|
||||||
|
|
||||||
|
if (contextId == undefined)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (link.prop)
|
||||||
|
context.objectProps[link.prop] = contextId;
|
||||||
|
else
|
||||||
|
context.childs.push (contextId);
|
||||||
|
|
||||||
|
links.splice (i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
,addLink: function (context, prop, objectId)
|
||||||
|
{
|
||||||
|
this._links.push ({
|
||||||
|
context: context
|
||||||
|
,prop: prop
|
||||||
|
,objectId: objectId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
,instantiate: function (doc, context, scope)
|
||||||
|
{
|
||||||
|
var object = new context.klass ();
|
||||||
|
object.setProperties (context.props);
|
||||||
|
|
||||||
|
if (context.nodeId && object instanceof Component)
|
||||||
|
object.htmlId = scope.getHtmlId (context.nodeId);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
,preLink: function (scope)
|
||||||
|
{
|
||||||
|
var objects = scope.objects;
|
||||||
|
var links = this._links;
|
||||||
|
|
||||||
|
for (var i = links.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var link = links[i];
|
||||||
|
var object = objects[link.context.id];
|
||||||
|
var objectRef = scope.$(link.objectId);
|
||||||
|
|
||||||
|
if (objectRef == null)
|
||||||
|
{
|
||||||
|
this.showError ('Referenced unexistent object with id \'%s\'',
|
||||||
|
link.objectId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link.prop)
|
||||||
|
object[link.prop] = objectRef;
|
||||||
|
else
|
||||||
|
object.appendChild (objectRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
,link: function (context, object, objects, scope)
|
||||||
|
{
|
||||||
|
var objectProps = context.objectProps;
|
||||||
|
for (var prop in objectProps)
|
||||||
|
object[prop] = objects[objectProps[prop]];
|
||||||
|
|
||||||
|
var childs = context.childs;
|
||||||
|
for (var i = 0; i < childs.length; i++)
|
||||||
|
object.appendChild (objects[childs[i]]);
|
||||||
|
|
||||||
|
if (context.custom)
|
||||||
|
object.loadXml (scope, context.custom);
|
||||||
|
}
|
||||||
|
|
||||||
|
,connect: function (context, object, objects, scope)
|
||||||
|
{
|
||||||
|
var funcProps = context.funcProps;
|
||||||
|
for (var prop in funcProps)
|
||||||
|
{
|
||||||
|
var method = scope.getMethod (funcProps[prop], true);
|
||||||
|
|
||||||
|
if (method)
|
||||||
|
object[prop] = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
var events = context.events;
|
||||||
|
for (var event in events)
|
||||||
|
{
|
||||||
|
var method = scope.getMethod (events[event]);
|
||||||
|
|
||||||
|
if (method)
|
||||||
|
object.on (event, method, scope.signalData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
,_replaceFunc: function (token)
|
||||||
|
{
|
||||||
|
return token.charAt(1).toUpperCase ();
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
var Compiler = require ('./compiler');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a @HTML.TextNode from text node.
|
||||||
|
*/
|
||||||
|
module.exports = new Class
|
||||||
|
({
|
||||||
|
Extends: Compiler
|
||||||
|
|
||||||
|
,compile: function (builder, node, tagName)
|
||||||
|
{
|
||||||
|
if (!tagName)
|
||||||
|
{
|
||||||
|
var text = node.textContent;
|
||||||
|
|
||||||
|
if (/^\s*\\?[_|\\]/.test (text))
|
||||||
|
{
|
||||||
|
var prefix = text.match (/^\s*/)[0];
|
||||||
|
var suffix = text.match (/\s*$/)[0];
|
||||||
|
|
||||||
|
text = text.trim ();
|
||||||
|
text = prefix + this.translateValue(text) + suffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tagName === 't')
|
||||||
|
var text = _(node.firstChild.textContent);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return {text: text};
|
||||||
|
}
|
||||||
|
|
||||||
|
,instantiate: function (doc, context)
|
||||||
|
{
|
||||||
|
return doc.createTextNode (context.text);
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,71 @@
|
||||||
|
|
||||||
|
var VnObject = require ('./object');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for compilers.
|
||||||
|
*/
|
||||||
|
module.exports = new Class
|
||||||
|
({
|
||||||
|
Extends: VnObject
|
||||||
|
|
||||||
|
,compile: function () {}
|
||||||
|
,postCompile: function () {}
|
||||||
|
,instantiate: function () {}
|
||||||
|
,link: function () {}
|
||||||
|
,connect: function () {}
|
||||||
|
,postLink: function () {}
|
||||||
|
|
||||||
|
,initialize: function (builder)
|
||||||
|
{
|
||||||
|
this._builder = builder;
|
||||||
|
this.parent ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates a string if it's a translatable string.
|
||||||
|
*
|
||||||
|
* @param {String} value The string to check and translate
|
||||||
|
* @return {String} The translated string or the same string if it is not translatable
|
||||||
|
*/
|
||||||
|
,translateValue: function (value)
|
||||||
|
{
|
||||||
|
switch (value.charAt (0))
|
||||||
|
{
|
||||||
|
case '_':
|
||||||
|
return _(value.substr (1));
|
||||||
|
case '\\':
|
||||||
|
switch (value.charAt(1))
|
||||||
|
{
|
||||||
|
case '_':
|
||||||
|
case '\\':
|
||||||
|
return value.substr (1);
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the passed attribute name it's an event.
|
||||||
|
*
|
||||||
|
* @param {String} attribute The attribute name
|
||||||
|
* @return {Boolean} %true if it's an event, otherwise %false
|
||||||
|
*/
|
||||||
|
,isEvent: function (attribute)
|
||||||
|
{
|
||||||
|
return /^on-\w+/.test (attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an error parsing the node.
|
||||||
|
*
|
||||||
|
* @param {String} error The error message template
|
||||||
|
* @param {...} varArgs The message template arguments
|
||||||
|
*/
|
||||||
|
,showError: function ()
|
||||||
|
{
|
||||||
|
this._builder.showError.apply (this._builder, arguments);
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,120 @@
|
||||||
|
|
||||||
|
var VnObject = require ('./object');
|
||||||
|
|
||||||
|
var scopeUid = 0;
|
||||||
|
|
||||||
|
module.exports = new Class
|
||||||
|
({
|
||||||
|
Extends: VnObject
|
||||||
|
|
||||||
|
,initialize: function (builder, objects, signalData, parentScope, extraObjects)
|
||||||
|
{
|
||||||
|
this.builder = builder;
|
||||||
|
this.objects = objects;
|
||||||
|
this.signalData = signalData;
|
||||||
|
this.parentScope = parentScope;
|
||||||
|
this.uid = ++scopeUid;
|
||||||
|
this.extraObjects = extraObjects;
|
||||||
|
|
||||||
|
if (!signalData && parentScope)
|
||||||
|
this.signalData = parentScope.signalData;
|
||||||
|
|
||||||
|
this.parent ();
|
||||||
|
}
|
||||||
|
|
||||||
|
,getMain: function ()
|
||||||
|
{
|
||||||
|
return this.builder.getMain (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetchs an element by it's identifier.
|
||||||
|
*
|
||||||
|
* @param {String} id The node identifier
|
||||||
|
* @return {Object} The object or %null if it doesn't exists
|
||||||
|
*/
|
||||||
|
,$: function (id)
|
||||||
|
{
|
||||||
|
var object;
|
||||||
|
var index = this.builder.getById (id);
|
||||||
|
|
||||||
|
if (index !== undefined)
|
||||||
|
object = this.objects[index];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object = this.extraObjects[id];
|
||||||
|
|
||||||
|
if (object === undefined && this.parentScope)
|
||||||
|
object = this.parentScope.getById (id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return object ? object : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetchs an element by it's identifier.
|
||||||
|
*
|
||||||
|
* @param {String} id The node identifier
|
||||||
|
* @return {Object} The object or %null if it doesn't exists
|
||||||
|
*/
|
||||||
|
,getById: function (id)
|
||||||
|
{
|
||||||
|
return this.$(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetchs a set of elements by it's tag name.
|
||||||
|
*
|
||||||
|
* @param {String} tagName The object tag name
|
||||||
|
* @return {Array[Object]} The list of objects or an empty array
|
||||||
|
*/
|
||||||
|
,getByTagName: function (tagName)
|
||||||
|
{
|
||||||
|
return this.builder.getByTagName (this, tagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Links all scope objects and connects it's events.
|
||||||
|
*/
|
||||||
|
,link: function ()
|
||||||
|
{
|
||||||
|
this.builder.link (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
,getMethod: function (value, binded)
|
||||||
|
{
|
||||||
|
if (this.signalData)
|
||||||
|
{
|
||||||
|
var method = this.signalData[value];
|
||||||
|
|
||||||
|
if (method && binded)
|
||||||
|
method = method.bind (this.signalData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
var method = window[value];
|
||||||
|
|
||||||
|
if (method === undefined)
|
||||||
|
this.builder._showError ('Function \'%s\' not found', value);
|
||||||
|
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
,getHtmlId: function (nodeId)
|
||||||
|
{
|
||||||
|
return 'vn-'+ this.uid +'-'+ nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
,_destroy: function ()
|
||||||
|
{
|
||||||
|
var objects = this.objects;
|
||||||
|
|
||||||
|
for (var i = objects.length; i--;)
|
||||||
|
if (objects[i] instanceof VnObject)
|
||||||
|
{
|
||||||
|
objects[i].unref ();
|
||||||
|
objects[i].disconnectByInstance (this.builder.signalData);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parent ();
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
kebabToCamel: kebabToCamel,
|
||||||
|
kebabToPascal: kebabToPascal
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a kebab-case (hyphenized) string to camelCase (lowerCamelCase).
|
||||||
|
*
|
||||||
|
* @param {String} string The kebab-case string
|
||||||
|
* @return {String} The string parsed to camelCase
|
||||||
|
*/
|
||||||
|
function kebabToCamel (string)
|
||||||
|
{
|
||||||
|
function replaceFunc (token)
|
||||||
|
{
|
||||||
|
return token.charAt(1).toUpperCase ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.replace (/-./g, replaceFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a kebab-case (hyphenized) string to PascalCase (UpperCamelCase).
|
||||||
|
*
|
||||||
|
* @param {String} string The kebab-case string
|
||||||
|
* @return {String} The string parsed to PascalCase
|
||||||
|
*/
|
||||||
|
function kebabToPascal (string)
|
||||||
|
{
|
||||||
|
string = string.charAt (0).toUpperCase () + string.substr (1);
|
||||||
|
return kebabToCamel (string);
|
||||||
|
}
|
Loading…
Reference in New Issue