From 0cf90bb53ee6d029e7aaa4f6e1067a1236077c01 Mon Sep 17 00:00:00 2001
From: Juan Ferrer Toribio
Date: Mon, 9 Nov 2015 18:11:51 +0100
Subject: [PATCH] =?UTF-8?q?Ahora=20Vn.Builder=20preprocesa=20los=20XML=20h?=
=?UTF-8?q?aciendo=20que=20la=20carga=20repetida=20(Ej:=20Htk.Repeater)=20?=
=?UTF-8?q?sea=20m=C3=A1s=20eficiente?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/forms/ecomerce/catalog/catalog.js | 14 +-
web/forms/ecomerce/catalog/ui.xml | 200 ++++----
web/js/htk/repeater.js | 97 ++--
web/js/vn/builder-new.js | 575 ----------------------
web/js/vn/builder.js | 656 +++++++++++++++++---------
web/js/vn/main.js | 1 -
6 files changed, 614 insertions(+), 929 deletions(-)
delete mode 100755 web/js/vn/builder-new.js
diff --git a/web/forms/ecomerce/catalog/catalog.js b/web/forms/ecomerce/catalog/catalog.js
index 6c3517c9..e013f3ec 100755
--- a/web/forms/ecomerce/catalog/catalog.js
+++ b/web/forms/ecomerce/catalog/catalog.js
@@ -114,6 +114,7 @@ Vn.Catalog = new Class
this.hideMenu ();
var realms = this.$('realms-model');
+ return;
if (!realms.ready)
return;
@@ -350,7 +351,7 @@ Vn.Catalog = new Class
Vn.Filter = new Class
({
- Extends: Htk.Widget
+ Extends: Htk.Field
,Tag: 'vn-filter'
,Child: 'model'
,Properties:
@@ -403,8 +404,8 @@ Vn.Filter = new Class
this.node.className = 'vn-filter';
this._select = new Htk.Select ();
- this._select.on ('mousedown', this._onClick.bind (this));
- this._select.on ('changed', this._onChange.bind (this));
+ this._select.on ('mousedown', this._onClick, this);
+ this._select.on ('changed', this._onChange, this);
this.node.appendChild (this._select.getNode ());
this._ul = document.createElement ('ul');
@@ -422,10 +423,11 @@ Vn.Filter = new Class
,_onCloseClick: function (li)
{
Vn.Node.remove (li);
+ this.value = undefined;
}
,_onChange: function ()
- {
+ {
if (this._select.value === null
|| this._select.value === undefined)
return;
@@ -446,7 +448,9 @@ Vn.Filter = new Class
var text = document.createTextNode (label);
li.appendChild (text);
- setTimeout (this._onTimeout.bind (this));
+ setTimeout (this._onTimeout.bind (this));
+
+ this.value = this._select.value;
}
,_onTimeout: function ()
diff --git a/web/forms/ecomerce/catalog/ui.xml b/web/forms/ecomerce/catalog/ui.xml
index 28de2a31..17d17f0e 100755
--- a/web/forms/ecomerce/catalog/ui.xml
+++ b/web/forms/ecomerce/catalog/ui.xml
@@ -1,53 +1,61 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
- SELECT item_id, warehouse_id, SUM(amount) amount
- FROM basket_item
- GROUP BY warehouse_id
+
+ SELECT item_id, warehouse_id, SUM(amount) amount
+ FROM basket_item
+ GROUP BY warehouse_id
+
@@ -57,11 +65,11 @@
SELECT Id_Article item_id FROM vn2008.Articles
WHERE #filter;
CALL bionic_calc ();
- SELECT a.Id_Article item_id, t.available, t.price, p.producer,
+ SELECT a.Id_Article item_id, t.available, t.price, p.name producer,
a.Foto, a.Article, a.Categoria, a.Medida, a.Tallos, a.Color, o.Abreviatura
FROM tmp.bionic_item t
JOIN vn2008.Articles a ON a.Id_Article = t.item_id
- LEFT JOIN vn2008.Articles_producer p ON p.Id_Article = a.Id_Article
+ LEFT JOIN vn2008.producer p ON p.producer_id = a.producer_id
LEFT JOIN vn2008.Origen o ON a.id_origen = o.id
WHERE t.available > 0
ORDER BY a.Article, a.Medida
@@ -177,8 +185,8 @@
-
- from
+
+ from
@@ -226,59 +234,83 @@
-
- CALL item_available ();
- SELECT DISTINCT r.id, r.reino
- FROM vn2008.reinos r
- JOIN vn2008.Tipos t ON t.reino_id = r.id
- JOIN vn2008.Articles a ON a.tipo_id = t.tipo_id
- JOIN tmp.item_available i ON i.item_id = a.Id_Article
- WHERE /*#filter
- AND*/ r.display
- ORDER BY r.reino
+
+
+ SELECT id, reino, color FROM vn2008.reinos
+ WHERE display != FALSE ORDER BY reino
+
-
-
- CALL item_available ();
- SELECT DISTINCT t.tipo_id, LEFT(t.Tipo, 18) type
- FROM vn2008.Tipos t
- JOIN vn2008.Articles a ON a.tipo_id = t.tipo_id
- JOIN tmp.item_available i ON i.item_id = a.Id_Article
- /*WHERE #filter*/
- ORDER BY t.Tipo
+
+
+
+ CALL item_available ();
+ SELECT DISTINCT t.tipo_id, LEFT(t.Tipo, 18) type
+ FROM vn2008.Tipos t
+ JOIN vn2008.Articles a ON a.tipo_id = t.tipo_id
+ JOIN tmp.item_available i ON i.item_id = a.Id_Article
+ /*WHERE #filter*/
+ ORDER BY t.Tipo
+
-
+
- CALL item_available ();
- SELECT DISTINCT c.Id_Tinta, c.name
- FROM vn2008.Tintas c
- JOIN vn2008.Articles a ON a.Color = c.Id_Tinta
- JOIN tmp.item_available i ON i.item_id = a.Id_Article
- /*WHERE #filter*/
- ORDER BY c.name
+
+ CALL item_available ();
+ SELECT DISTINCT c.Id_Tinta, c.name
+ FROM vn2008.Tintas c
+ JOIN vn2008.Articles a ON a.Color = c.Id_Tinta
+ JOIN tmp.item_available i ON i.item_id = a.Id_Article
+ /*WHERE #filter*/
+ ORDER BY c.name
+
-
+
- CALL item_available ();
- SELECT DISTINCT o.id, o.Origen, o.Abreviatura
- FROM vn2008.Origen o
- JOIN vn2008.Articles a ON a.id_origen = o.id
- JOIN tmp.item_available i ON i.item_id = a.Id_Article
- /*WHERE #filter*/
- ORDER BY o.Origen
+
+ CALL item_available ();
+ SELECT DISTINCT o.id, o.Origen, o.Abreviatura
+ FROM vn2008.Origen o
+ JOIN vn2008.Articles a ON a.id_origen = o.id
+ JOIN tmp.item_available i ON i.item_id = a.Id_Article
+ /*WHERE #filter*/
+ ORDER BY o.Origen
+
-
+
- CALL item_available ();
- SELECT DISTINCT a.Categoria, a.Categoria category
- FROM vn2008.Articles a
- JOIN tmp.item_available i ON i.item_id = a.Id_Article
- /*WHERE #filter*/
- ORDER BY a.Categoria
+
+ CALL item_available ();
+ SELECT DISTINCT a.Categoria, a.Categoria category
+ FROM vn2008.Articles a
+ JOIN tmp.item_available i ON i.item_id = a.Id_Article
+ /*WHERE #filter*/
+ ORDER BY a.Categoria
+
+
+
+
+
+
+ CALL item_available ();
+ SELECT DISTINCT p.producer_id, p.name
+ FROM vn2008.producer p
+ JOIN vn2008.Articles a ON a.producer_id = p.producer_id
+ JOIN tmp.item_available i ON i.item_id = a.Id_Article
+ /*WHERE #filter*/
+ ORDER BY p.name
+
diff --git a/web/js/htk/repeater.js b/web/js/htk/repeater.js
index 4da6b1fd..e6e697ee 100755
--- a/web/js/htk/repeater.js
+++ b/web/js/htk/repeater.js
@@ -12,13 +12,13 @@ Htk.Repeater = new Class
{
this.link ({_model: x},
{
- 'status-changed': this.onModelChange
- ,'row-deleted': this.onRowDelete
- ,'row-updated': this.onRowUpdate
- ,'row-inserted': this.onRowInsert
+ 'status-changed': this._onModelChange
+ ,'row-deleted': this._onRowDelete
+ ,'row-updated': this._onRowUpdate
+ ,'row-inserted': this._onRowInsert
});
- this.onModelChange ();
+ this._onModelChange ();
}
,get: function ()
{
@@ -62,7 +62,10 @@ Htk.Repeater = new Class
,initialize: function (props)
{
var div = this.createElement ('div');
- div.className = 'htk-repeater';
+
+ this._container = document.createElement ('div');
+ this._container.className = 'htk-repeater';
+ div.appendChild (this._container);
this.parent (props);
}
@@ -75,25 +78,25 @@ Htk.Repeater = new Class
builder.setParent (builderResult);
builder.loadXmlFromNode (node.firstElementChild);
- this.onModelChange ();
+ this._onModelChange ();
}
,getChild: function (index)
{
- return this.node.childNodes[index];
+ return this._container.childNodes[index];
}
,getBuilder: function (index)
{
- return this.childsData[index].builder;
+ return this._childsData[index].builder;
}
,getForm: function (index)
{
- return this.childsData[index].form;
+ return this._childsData[index].form;
}
- ,buildBox: function (index)
+ ,_buildBox: function (index)
{
var form = new Db.Form ({
model: this._model,
@@ -103,61 +106,64 @@ Htk.Repeater = new Class
this._builder.add (this._formId, form);
var res = this._builder.load ();
- this.childsData.push ({
+ this._childsData.push ({
builder: res,
form: form
});
if (this._renderer)
this._renderer (res, form);
-
- this.node.appendChild (res.getMain ());
+
+ return res.getMain ();
}
- ,onModelChange: function ()
+ ,_onModelChange: function ()
{
if (!this._model || !this._builder)
return;
-
- Vn.Node.removeChilds (this.node);
- this.freeChildsData ();
- this.childsData = [];
+
+ this.node.removeChild (this._container);
+ Vn.Node.removeChilds (this._container);
+
+ this._freeChildsData ();
+ this._childsData = [];
switch (this._model.status)
{
case Db.Model.Status.READY:
{
for (var i = 0; i < this._model.numRows; i++)
- this.buildBox (i);
+ this._container.appendChild (this._buildBox (i));
- this.showNoRecordsFound ();
+ this._showNoRecordsFound ();
break;
}
case Db.Model.Status.LOADING:
- this.showMessage (_('Loading'), 'loader-black.gif');
+ this._showMessage (_('Loading'), 'loader-black.gif');
break;
case Db.Model.Status.CLEAN:
- this.showMessage (this.emptyMessage, 'refresh.svg');
+ this._showMessage (this.emptyMessage, 'refresh.svg');
break;
case Db.Model.Status.ERROR:
- this.showMessage (_('ErrorLoadingData'), 'error.svg');
+ this._showMessage (_('ErrorLoadingData'), 'error.svg');
break;
}
+ this.node.appendChild (this._container);
this.signalEmit ('change');
}
- ,showNoRecordsFound: function (count)
+ ,_showNoRecordsFound: function (count)
{
- if (this._model.numRows == 0)
+ if (this._model.numRows === 0)
this.showMessage (_('EmptyList'), 'clean.svg');
}
- ,showMessage: function (message, src)
+ ,_showMessage: function (message, src)
{
var div = document.createElement ('div');
div.className = 'message';
- this.node.appendChild (div);
+ this._container.appendChild (div);
var img = document.createElement ('img');
img.alt = '';
@@ -167,35 +173,42 @@ Htk.Repeater = new Class
div.appendChild (document.createTextNode (message));
}
- ,onRowDelete: function (model, row)
+ ,_onRowDelete: function (model, row)
{
- Vn.Node.remove (this.node.childNodes[row]);
- this.showNoRecordsFound ();
+ Vn.Node.remove (this._container.childNodes[row]);
+ this._unrefChildData (row);
+ this._showNoRecordsFound ();
}
- ,onRowUpdate: function (model, row, columns)
+ ,_onRowUpdate: function (model, row, columns)
{
// this.form[row].signalEmit ('iter-changed');
}
- ,onRowInsert: function (model, row)
+ ,_onRowInsert: function (model, row)
{
- this.buildBox (row);
+ var box = this._buildBox (row);
+ this._container.appendChild (box);
}
- ,freeChildsData: function ()
+ ,_freeChildsData: function ()
{
- if (this.childsData)
- for (var i = 0; i < this.childsData.length; i++)
- {
- this.childsData[i].form.unref ();
- this.childsData[i].builder.unref ();
- }
+ if (this._childsData)
+ for (var i = 0; i < this._childsData.length; i++)
+ this._unrefChildData (i);
+ }
+
+ ,_unrefChildData: function (index)
+ {
+ var childData = this._childsData[index];
+ childData.form.unref ();
+ childData.builder.unref ();
}
,destroy: function ()
{
- this.freeChildsData ();
+ this._freeChildsData ();
this.parent ();
}
});
+
diff --git a/web/js/vn/builder-new.js b/web/js/vn/builder-new.js
deleted file mode 100755
index 0ec64301..00000000
--- a/web/js/vn/builder-new.js
+++ /dev/null
@@ -1,575 +0,0 @@
-/**
- * Creates a object from a XML specification.
- **/
-Vn.Builder = new Class
-({
- Extends: Vn.Object
- ,addedMap: {}
-
- ,add: function (id, object)
- {
- this.addedMap[id] = object;
- }
-
- ,setParent: function (parentBuilder)
- {
- this.parentBuilder = parentBuilder;
-
- if (parentBuilder && !this.signalData)
- this.signalData = parentBuilder.builder.signalData;
- }
-
- ,getMain: function (result)
- {
- return result.objects[this.mainContext.id];
- }
-
- ,getById: function (objectId, result)
- {
- var index = this.contextMap[objectId];
-
- if (index !== undefined)
- return result.objects[index];
- else if (this.addedMap[objectId])
- return this.addedMap[objectId];
- else if (this.parentBuilder)
- this.parentBuilder.getById (objectId);
-
- return null;
- }
-
- ,getByTagName: function (tagName, result)
- {
- var tags = this.tags[tagName];
-
- if (tags)
- {
- var arr = new Array (tags.length);
-
- for (var i = 0; i < tags.length; i++)
- arr[i] = result.objects[tags[i]];
-
- return arr;
- }
-
- return [];
- }
-
- ,loadXml: function (path, dstDocument)
- {
- var xmlDoc = Vn.getXml (path);
-
- if (!xmlDoc)
- return false;
-
- var docElement = xmlDoc.documentElement;
-
- if (docElement.tagName !== 'vn')
- return false;
-
- this._compileInit (dstDocument);
-
- var childs = docElement.childNodes;
-
- if (childs)
- for (var i = 0; i < childs.length; i++)
- this._compileNode (childs[i]);
-
- this._compileEnd ();
- return true;
- }
-
- ,loadXmlFromNode: function (node, dstDocument)
- {
- this._compileInit (dstDocument);
- this.mainContext = this._compileNode (node);
- this._compileEnd ();
- }
-
- ,load: function ()
- {
- var contexts = this.contexts;
- var len = contexts.length;
- var objects = new Array (len);
-
- for (var i = 0; i < len; i++)
- {
- var context = contexts[i];
- objects[i] =
- this.textInstantiate (context)
- || this.objectInstantiate (context)
- || this.elementInstantiate (context);
- }
-
- var res = new BuilderResult (this, objects);
-
- var addedObject;
-
- for (var i = this.propLinks.length - 1; i >= 0; i--)
- {
- var l = this.propLinks[i];
- if (addedObject = this.addedMap[l.value])
- objects[l.context.id][l.prop] = addedObject;
- }
-
- for (var i = this.childLinks.length - 1; i >= 0; i--)
- {
- var l = this.childLinks[i];
- if (addedObject = this.addedMap[l.value])
- objects[l.context.id].appendChild (addedObject);
- }
-
- for (var i = 0; i < len; i++)
- {
- var context = contexts[i];
- var object = objects[i];
-
- this.objectLink (context, object, objects, res) ||
- this.elementLink (context, object, objects, res);
- }
-
- return res;
- }
-
- ,_compileInit: function (dstDocument)
- {
- this.tags = {};
- this.contexts = [];
- this.contextMap = {};
- this.propLinks = [];
- this.childLinks = [];
- this.mainContext = null;
- this.document = dstDocument ? dstDocument : document;
- }
-
- ,_compileEnd: function (node)
- {
- var contextId;
-
- for (var i = this.propLinks.length - 1; i >= 0; i--)
- {
- var l = this.propLinks[i];
-
- if (contextId = this.contextMap[l.value])
- {
- l.context.objectProps[l.prop] = contextId;
- this.propLinks.splice (i, 1);
- }
- else if (this.parentBuilder)
- {
- var object = this.parentBuilder.getById (l.value);
-
- if (object)
- pl.context.props[pl.prop] = object;
- }
- }
-
- for (var i = this.childLinks.length - 1; i >= 0; i--)
- {
- var l = this.childLinks[i];
-
- if (contextId = this.contextMap[l.value])
- {
- l.context.childs.push (contextId);
- this.childLinks.splice (i, 1);
- }
- }
- }
-
- ,_compileNode: function (node)
- {
- var context = null;
- var tagName = null;
-
- if (node.nodeType === Node.ELEMENT_NODE)
- tagName = node.tagName.toLowerCase ();
- else if (node.nodeType !== Node.TEXT_NODE
- || /^\s*$/.test (node.textContent))
- return null;
-
- var context =
- this.textCompile (node, tagName)
- || this.objectCompile (node, tagName)
- || this.elementCompile (node, tagName);
-
- context.id = this.contexts.length;
-
- if (tagName)
- {
- var nodeId = node.getAttribute ('id');
-
- if (nodeId)
- this.contextMap[nodeId] = context.id;
-
- var tags = this.tags[tagName];
-
- if (!tags)
- this.tags[tagName] = tags = [];
-
- tags.push (context.id);
- }
-
- this.contexts.push (context);
- return context;
- }
-
- /**
- * Creates a text node context.
- **/
- ,textCompile: function (node, tagName)
- {
- if (!tagName)
- var text = node.textContent;
- else if (tagName === 't')
- var text = _(node.firstChild.textContent);
- else
- return null;
-
- return {text: text};
- }
-
- ,textInstantiate: function (context)
- {
- if (!context.text)
- return null;
-
- return this.document.createTextNode (context.text);
- }
-
- /**
- * Creates a object context.
- **/
- ,objectCompile: function (node, tagName)
- {
- var handler;
- var props = {};
- var objectProps = {};
- var childs = [];
- var events = {};
- var klass = Vn.customTags[tagName];
-
- if (!klass)
- return null;
-
- var context = {
- klass: klass,
- props: props,
- events: events,
- objectProps: objectProps,
- childs: childs
- };
-
- var a = node.attributes;
-
- for (var i = 0; i < a.length; i++)
- {
- var attribute = a[i].nodeName;
- var value = a[i].nodeValue;
-
- if ((handler = this._getEventHandler (attribute, value)))
- {
- events[attribute.substr (3)] = handler;
- }
- else if (!/^(id|property)$/.test (attribute))
- {
- this.propCompile (context, klass, props,
- node, attribute, value);
- }
- }
-
- var childNodes = node.childNodes;
-
- if (childNodes)
- for (var i = 0; i < childNodes.length; i++)
- {
- var child = childNodes[i];
- var childTagName = null;
-
- if (child.tagName)
- childTagName = child.tagName.toLowerCase ();
-
- if (childTagName === 'pointer')
- {
- this.childLinks.push ({
- context: context,
- objectId: child.getAttribute ('object')
- });
- }
- else if (childTagName === 'custom')
- {
- context.custom = child;
- }
- else
- {
- var childContext = this._compileNode (child);
-
- if (!childContext)
- continue;
-
- var prop = null;
-
- if (child.getAttribute)
- prop = child.getAttribute ('property');
-
- if (prop)
- objectProps[prop] = childContext.id;
- else
- childs.push (childContext.id);
- }
- }
-
- return context;
- }
-
- ,propCompile: function (context, klass, props, node, attribute, value)
- {
- var newValue = null;
- var propName = attribute.replace (/-./g, this._replaceFunc);
- var propInfo = klass.Properties[propName];
-
- if (!propInfo)
- {
- console.warn ('Vn.Builder: Attribute \'%s\' not valid for tag \'%s\'',
- attribute, node.tagName);
- return;
- }
- if (!value)
- {
- console.warn ('Vn.Builder: Attribute \'%s\' empty on tag \'%s\'',
- attribute, node.tagName);
- return;
- }
-
- switch (propInfo.type)
- {
- 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:
- newValue = this._getMethod (value);
- break;
- default:
- if (propInfo.enumType)
- newValue = propInfo.enumType[value];
- break;
- }
-
- if (newValue !== null && newValue !== undefined)
- {
- props[propName] = newValue;
- }
- else if (propInfo.type instanceof Function)
- {
- this.propLinks.push ({
- context: context,
- prop: attribute,
- value: value
- });
- }
- else
- console.warn ('Vn.Builder: Attribute \'%s\' invalid for tag \'%s\'',
- attribute, node.tagName);
- }
-
- ,objectInstantiate: function (context)
- {
- if (!context.klass)
- return null;
-
- return new context.klass (context.props);
- }
-
- ,objectLink: function (context, object, objects, res)
- {
- if (!context.klass)
- return null;
-
- 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]]);
-
- var events = context.events;
- for (var event in events)
- object.on (event,
- events[event].bind (this.signalData));
-
- if (context.custom)
- object.loadXml (res, context.custom);
- }
-
- /**
- * Creates a HTML node context.
- **/
- ,elementCompile: function (node, tagName)
- {
- var handler;
- var events = {};
- var childs = [];
- var htmlNode = this.document.createElement (tagName);
-
- var a = node.attributes;
-
- for (var i = 0; i < a.length; i++)
- {
- var attribute = a[i].nodeName;
- var value = a[i].nodeValue;
-
- if ((handler = this._getEventHandler (attribute, value)))
- {
- events[attribute.substr (3)] = handler;
- }
- else if (attribute !== 'id')
- htmlNode.setAttribute (attribute,
- this._translateValue (value));
- }
-
- var childNodes = node.childNodes;
-
- if (childNodes)
- for (var i = 0; i < childNodes.length; i++)
- {
- var childContext = this._compileNode (childNodes[i]);
-
- if (childContext)
- childs.push (childContext.id);
- }
-
- return {
- node: htmlNode,
- events: events,
- childs: childs
- };
- }
-
- ,elementInstantiate: function (context)
- {
- if (!context.node)
- return null;
-
- return context.node.cloneNode (false);
- }
-
- ,elementLink: function (context, object, objects)
- {
- if (!context.node)
- return null;
-
- var childs = context.childs;
- for (var i = 0; i < childs.length; i++)
- {
- var child = objects[childs[i]];
-
- if (child instanceof Htk.Widget)
- object.appendChild (child.getNode ());
- else if (child instanceof Node)
- object.appendChild (child);
- }
-
- var events = context.events;
- for (var event in events)
- object.addEventListener (event,
- events[event].bind (this.signalData));
- }
-
- ,_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;
- }
-
- ,_getMethod: function (value)
- {
- if (this.signalData)
- var methodName = 'this.signalData.'+ value;
- else
- var methodName = value;
-
- var method;
-
- try {
- method = eval (methodName);
- }
- catch (e)
- {
- method = null;
- }
-
- if (method == null)
- console.warn ('Vn.Builder: Function \'%s\' not found',
- value);
-
- return method;
- }
-
- ,_getEventHandler: function (attribute, value)
- {
- if (!(/^on-\w+/.test (attribute)))
- return null;
-
- return this._getMethod (value);
- }
-
- ,_replaceFunc: function (token)
- {
- return token.charAt(1).toUpperCase ();
- }
-});
-
-var BuilderResult = new Class
-({
- Extends: Vn.Object
-
- ,initialize: function (builder, objects)
- {
- this.builder = builder;
- this.objects = objects;
- }
-
- ,getMain: function ()
- {
- return this.builder.getMain (this);
- }
-
- ,$: function (objectId)
- {
- return this.builder.getById (objectId, this);
- }
-
- ,getById: function (objectId)
- {
- return this.builder.getById (objectId, this);
- }
-
- ,getByTagName: function (tagName)
- {
- return this.builder.getByTagName (tagName, this);
- }
-
- ,_destroy: function ()
- {
- var objects = this.objects;
-
- for (var i = 0; i < objects.length; i++)
- if (objects[i].unref)
- objects[i].unref ();
-
- this.parent ();
- }
-});
-
diff --git a/web/js/vn/builder.js b/web/js/vn/builder.js
index 95a9f227..162240cd 100755
--- a/web/js/vn/builder.js
+++ b/web/js/vn/builder.js
@@ -1,274 +1,491 @@
/**
* Creates a object from a XML specification.
**/
-Vn.BuilderOld = new Class
+Vn.Builder = new Class
({
Extends: Vn.Object
- ,objectMap: {}
- ,tags: {}
+ ,_addedMap: {}
+ ,_contexts: null
- ,load: function ()
+ ,add: function (id, object)
{
- return this;
+ this._addedMap[id] = object;
+ }
+
+ ,setParent: function (parentResult)
+ {
+ this._parentResult = parentResult;
+
+ if (parentResult && !this.signalData)
+ this.signalData = parentResult.builder.signalData;
+ }
+
+ ,getMain: function (result)
+ {
+ return result.objects[this._mainContext];
+ }
+
+ ,getById: function (objectId, result)
+ {
+ var index = this._contextMap[objectId];
+
+ if (index !== undefined)
+ return result.objects[index];
+ else if (this._parentResult)
+ return this._parentResult.getById (objectId);
+
+ return null;
+ }
+
+ ,getByTagName: function (tagName, result)
+ {
+ var tags = this._tags[tagName];
+
+ if (tags)
+ {
+ var arr = new Array (tags.length);
+
+ for (var i = 0; i < tags.length; i++)
+ arr[i] = result.objects[tags[i]];
+
+ return arr;
+ }
+
+ return [];
}
- ,loadXml: function (xmlDoc)
+ ,loadXml: function (path, dstDocument)
{
+ var xmlDoc = Vn.getXml (path);
+
if (!xmlDoc)
return false;
+ this._compileInit (dstDocument);
+ this._path = path;
+
var docElement = xmlDoc.documentElement;
if (docElement.tagName !== 'vn')
+ {
+ this._showError ('Malformed XML');
+ this._contexts = null;
return false;
+ }
- this.contexts = [];
var childs = docElement.childNodes;
if (childs)
for (var i = 0; i < childs.length; i++)
- this.loadNode (childs[i], null);
+ this._compileNode (childs[i]);
- this.resolveProperties ();
- delete this.contexts;
+ this._compileEnd ();
return true;
}
- ,loadXmlFromNode: function (node)
+ ,loadXmlFromNode: function (node, dstDocument)
{
- this.contexts = [];
- var mainNode = this.loadNode (node);
- this.resolveProperties ();
- delete this.contexts;
- return mainNode;
+ this._compileInit (dstDocument);
+ this._mainContext = this._compileNode (node).id;
+ this._compileEnd ();
}
- ,add: function (id, object)
+ ,load: function ()
{
- this.objectMap[id] = object;
+ if (this._contexts === null)
+ return null;
+
+ var contexts = this._contexts;
+ var len = contexts.length;
+ var objects = new Array (len);
+
+ for (var i = 0; i < len; i++)
+ {
+ var context = contexts[i];
+
+ if (context.tagName)
+ objects[i] = this.elementInstantiate (context);
+ else if (context.klass)
+ objects[i] = this.objectInstantiate (context);
+ else
+ objects[i] = this.textInstantiate (context);
+ }
+
+ var res = new BuilderResult (this, objects);
+
+ for (var i = this._links.length - 1; i >= 0; i--)
+ {
+ var l = this._links[i];
+ var addedObject = this._addedMap[l.objectId];
+
+ if (addedObject)
+ if (l.prop)
+ objects[l.context.id][l.prop] = addedObject;
+ else
+ objects[l.context.id].appendChild (addedObject);
+ else
+ this._showError ('Referenced unexistent object with id \'%s\'',
+ l.objectId);
+ }
+
+ for (var i = 0; i < len; i++)
+ {
+ var context = contexts[i];
+ var object = objects[i];
+
+ if (context.tagName)
+ this.elementLink (context, object, objects, res);
+ else if (context.klass)
+ this.objectLink (context, object, objects, res);
+ }
+
+ return res;
+ }
+
+ ,_compileInit: function (dstDocument)
+ {
+ this._path = null;
+ this._tags = {};
+ this._contexts = [];
+ this._contextMap = {};
+ this._links = [];
+ this._mainContext = null;
+ this._document = dstDocument ? dstDocument : document;
+ }
+
+ ,_compileEnd: function (node)
+ {
+ for (var i = this._links.length - 1; i >= 0; i--)
+ {
+ var l = this._links[i];
+ var contextId = this._contextMap[l.objectId]
+
+ if (contextId)
+ {
+ if (l.prop)
+ l.context.objectProps[l.prop] = contextId;
+ else
+ l.context.childs.push (contextId);
+
+ this._links.splice (i, 1);
+ }
+ else if (this._parentResult)
+ {
+ var object = this._parentResult.getById (l.objectId);
+
+ if (object)
+ pl.context.props[pl.prop] = object;
+ }
+ }
}
- ,loadNode: function (node)
+ ,_compileNode: function (node)
{
- var customNode;
- var htmlNode = null;
+ var context = null;
var tagName = null;
- if (node.tagName)
+ if (node.nodeType === Node.ELEMENT_NODE)
tagName = node.tagName.toLowerCase ();
+ else if (node.nodeType !== Node.TEXT_NODE
+ || /^[\n\r\t]*$/.test (node.textContent))
+ return null;
+
+ var context =
+ this.textCompile (node, tagName)
+ || this.objectCompile (node, tagName)
+ || this.elementCompile (node, tagName);
+
+ context.id = this._contexts.length;
+
+ if (tagName)
+ {
+ var nodeId = node.getAttribute ('id');
+
+ if (nodeId)
+ this._contextMap[nodeId] = context.id;
+
+ var tags = this._tags[tagName];
- if (tagName === 't')
- {
- htmlNode = document.createTextNode (_(node.firstChild.textContent));
- }
- else if (!tagName)
- {
- htmlNode = document.importNode (node, false);
- }
- else if ((customNode = this.loadCustomNode (node, tagName, null)))
- {
- if (customNode instanceof Htk.Widget)
- htmlNode = customNode.getNode ();
- }
- else
- {
- htmlNode = document.createElement (tagName);
-
- var a = node.attributes;
-
- for (var i = 0; i < a.length; i++)
- {
- var nodeName = a[i].nodeName;
- var nodeValue = a[i].nodeValue;
-
- if (/^on-\w+/.test (nodeName))
- {
- var method = this.getMethod (nodeValue);
- htmlNode.addEventListener (
- nodeName.substr (3), method.bind (this.signalData));
- }
- else if (nodeName === 'id')
- {
- this.objectMap[nodeValue] = htmlNode;
- }
- else
- htmlNode.setAttribute (nodeName,
- this.translateValue (nodeValue));
- }
-
- var childs = node.childNodes;
-
- if (childs)
- for (var i = 0; i < childs.length; i++)
- {
- var htmlChild = this.loadNode (childs[i]);
-
- if (htmlChild)
- htmlNode.appendChild (htmlChild);
- }
+ if (!tags)
+ this._tags[tagName] = tags = [];
+
+ tags.push (context.id);
}
- return htmlNode;
+ this._contexts.push (context);
+ return context;
}
-
- ,loadCustomNode: function (node, tagName, parentContext)
+
+ /**
+ * Creates a text node context.
+ **/
+ ,textCompile: function (node, tagName)
{
if (!tagName)
+ var text = node.textContent;
+ else if (tagName === 't')
+ var text = _(node.firstChild.textContent);
+ else
return null;
+ return {text: text};
+ }
+
+ ,textInstantiate: function (context)
+ {
+ return this._document.createTextNode (context.text);
+ }
+
+ /**
+ * Creates a object context.
+ **/
+ ,objectCompile: function (node, tagName)
+ {
var klass = Vn.customTags[tagName];
if (!klass)
return null;
- var customNode = new klass ();
-
- if (!this.tags[tagName])
- this.tags[tagName] = [];
-
- this.tags[tagName].push (customNode);
-
+ var props = {};
+ var objectProps = {};
+ var childs = [];
+ var events = {};
+ var handler;
+
var context = {
- node: node
- ,parent: parentContext
- ,object: customNode
- ,klass: klass
- ,custom: null
+ klass: klass,
+ props: props,
+ objectProps: objectProps,
+ childs: childs,
+ events: events,
+ custom: null
};
- this.contexts.push (context);
-
- var nodeId = node.getAttribute ('id');
-
- if (nodeId)
- this.objectMap[nodeId] = customNode;
-
- var childs = node.childNodes;
-
- if (childs)
- for (var i = 0; i < childs.length; i++)
+
+ var a = node.attributes;
+
+ for (var i = 0; i < a.length; i++)
{
- var childTagName = childs[i].tagName;
-
- if (!childTagName)
- continue;
+ var attribute = a[i].nodeName;
+ var value = a[i].nodeValue;
- childTagName = childTagName.toLowerCase ();
-
- var customChild = this.loadCustomNode (
- childs[i], childTagName, context);
-
- if (!customChild && childTagName === 'custom')
- context.custom = childs[i];
- }
-
- return customNode;
- }
-
- ,resolveProperties: function ()
- {
- for (var i = 0; i < this.contexts.length; i++)
- {
- var c = this.contexts[i];
- var a = c.node.attributes;
-
- for (var j = 0; j < a.length; j++)
- this.setAttribute (c, a[j].nodeName, a[j].nodeValue);
-
- if (c.custom)
- c.object.loadXml (this, c.custom);
-
- if (c.parent)
+ if (handler = this._getEventHandler (attribute, value))
{
- var parentProperty = c.node.getAttribute ('property');
-
- if (parentProperty)
- this.setProperty (c.parent, parentProperty, c.object);
- else
- c.parent.object.appendChild (c.object);
+ events[attribute.substr (3)] = handler;
+ }
+ else if (!/^(id|property)$/.test (attribute))
+ {
+ this.propCompile (context, klass, props,
+ node, attribute, value);
}
}
- }
-
- ,setAttribute: function (c, attribute, value)
- {
- if (/^on-\w+/.test (attribute))
+
+ var childNodes = node.childNodes;
+
+ if (childNodes)
+ for (var i = 0; i < childNodes.length; i++)
{
- var method = this.getMethod (value);
+ var child = childNodes[i];
- if (method)
- c.object.on (attribute.substr (3), method, this.signalData);
- }
- else if (!/^(id|property)$/.test (attribute))
- {
- this.setProperty (c, attribute, value)
+ if (child.nodeType !== Node.ELEMENT_NODE)
+ continue;
+
+ var childContext;
+ var childTagName = child.tagName.toLowerCase ();
+
+ if (childTagName === 'pointer')
+ {
+ this._addLink (context, null, child.getAttribute ('object'));
+ }
+ else if (childTagName === 'custom')
+ {
+ context.custom = child;
+ }
+ else if (childContext = this._compileNode (child))
+ {
+ var prop = child.getAttribute ('property');
+
+ if (prop)
+ objectProps[prop] = childContext.id;
+ else
+ childs.push (childContext.id);
+ }
}
+
+ return context;
}
- ,setProperty: function (c, attribute, value)
+ ,propCompile: function (context, klass, props, node, attribute, value)
{
- var propName = attribute.replace (/-./g, this.replaceFunc);
- var prop = c.klass.Properties[propName];
+ var newValue = null;
+ var propName = attribute.replace (/-./g, this._replaceFunc);
+ var propInfo = klass.Properties[propName];
- if (!prop)
+ if (!propInfo)
{
- console.warn ('Vn.Builder: Attribute \'%s\' not valid for tag \'%s\'',
- attribute, c.node.tagName);
+ this._showError ('Attribute \'%s\' not valid for tag \'%s\'',
+ attribute, node.tagName);
return;
}
if (!value)
- return;
-
- switch (prop.type)
{
- case Boolean:
- value = (/^(true|1)$/i).test (value);
- break;
- case Number:
- value = 0 + new Number (value);
- break;
- case String:
- value = this.translateValue (value);
- break;
- case Function:
- {
- var method = this.getMethod (value);
- value = method ? method.bind (this.signalData) : null;
- break;
- }
- default:
- if (prop.type instanceof Function)
- {
- if (typeof value == 'string')
- value = this.get (value);
- if (!(value instanceof prop.type))
- return;
- }
- else if (prop.enumType)
- value = prop.enumType[value];
+ this._showError ('Attribute \'%s\' empty on tag \'%s\'',
+ attribute, node.tagName);
+ return;
}
- if (value !== undefined)
- c.object[propName] = value;
+ switch (propInfo.type)
+ {
+ 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:
+ newValue = this._getMethod (value);
+ break;
+ default:
+ if (propInfo.enumType)
+ newValue = propInfo.enumType[value];
+ break;
+ }
+
+ if (newValue !== null && newValue !== undefined)
+ props[propName] = newValue;
+ else if (propInfo.type instanceof Function)
+ this._addLink (context, attribute, value);
else
- console.warn ('Vn.Builder: Empty attribute \'%s\' on tag \'%s\'',
- attribute, c.node.tagName);
+ this._showError ('Attribute \'%s\' invalid for tag \'%s\'',
+ attribute, node.tagName);
+ }
+
+ ,objectInstantiate: function (context)
+ {
+ return new context.klass (context.props);
+ }
+
+ ,objectLink: function (context, object, objects, res)
+ {
+ 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]]);
+
+ var events = context.events;
+ for (var event in events)
+ object.on (event,
+ events[event].bind (this.signalData));
+
+ if (context.custom)
+ object.loadXml (res, context.custom);
+ }
+
+ /**
+ * Creates a HTML node context.
+ **/
+ ,elementCompile: function (node, tagName)
+ {
+ var attributes = {};
+ var childs = [];
+ var events = {};
+ var handler;
+
+ var a = node.attributes;
+
+ for (var i = 0; i < a.length; i++)
+ {
+ var attribute = a[i].nodeName;
+ var value = a[i].nodeValue;
+
+ if (handler = this._getEventHandler (attribute, value))
+ events[attribute.substr (3)] = handler;
+ else if (attribute !== 'id')
+ attributes[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,
+ attributes: attributes,
+ childs: childs,
+ events: events
+ };
+ }
+
+ ,elementInstantiate: function (context)
+ {
+ return this._document.createElement (context.tagName);
+ }
+
+ ,elementLink: function (context, object, objects)
+ {
+ var attributes = context.attributes;
+ for (var attribute in attributes)
+ object.setAttribute (attribute, attributes[attribute]);
+
+ var childs = context.childs;
+ for (var i = 0; i < childs.length; i++)
+ {
+ var child = objects[childs[i]];
+
+ if (child instanceof Htk.Widget)
+ object.appendChild (child.getNode ());
+ else if (child instanceof Node)
+ object.appendChild (child);
+ }
+
+ var events = context.events;
+ for (var event in events)
+ object.addEventListener (event,
+ events[event].bind (this.signalData));
+ }
+
+ ,_showError: function (error)
+ {
+ var path = this._path ? this._path : 'Node';
+ var logArgs = ['Vn.Builder: %s: '+ error, path];
+
+ for (var i = 1; i < arguments.length; i++)
+ logArgs.push (arguments[i]);
+
+ console.warn.apply (null, logArgs);
+ }
+
+ ,_addLink: function (context, prop, objectId)
+ {
+ this._links.push ({
+ context: context
+ ,prop: prop
+ ,objectId: objectId
+ });
}
-//+++++++++++++++++++++++++++++++++++++++++++ Utilities
-
- ,translateValue: function (value)
+ ,_translateValue: function (value)
{
var chr = value.charAt (0);
- if (chr == '_')
+ if (chr === '_')
return _(value.substr (1));
- else if (chr == '\\' && value.charAt (1) == '_')
+ else if (chr === '\\' && value.charAt (1) === '_')
return value.substr (1);
return value;
}
- ,getMethod: function (value)
+ ,_getMethod: function (value)
{
if (this.signalData)
var methodName = 'this.signalData.'+ value;
@@ -285,69 +502,64 @@ Vn.BuilderOld = new Class
method = null;
}
- if (method == null)
- console.warn ('Vn.Builder: Function \'%s\' not found',
- value);
+ if (method === null)
+ this._showError ('Function \'%s\' not found', value);
return method;
}
- ,getEventHandler: function (attribute, value)
+ ,_getEventHandler: function (attribute, value)
{
if (!(/^on-\w+/.test (attribute)))
return null;
- return this.getMethod (value);
+ return this._getMethod (value);
}
- ,replaceFunc: function (token)
+ ,_replaceFunc: function (token)
{
return token.charAt(1).toUpperCase ();
}
-
- ,setParent: function (parentBuilder)
+});
+
+var BuilderResult = new Class
+({
+ Extends: Vn.Object
+
+ ,initialize: function (builder, objects)
{
- this.parentBuilder = parentBuilder;
-
- if (parentBuilder)
- this.signalData = parentBuilder.signalData;
+ this.builder = builder;
+ this.objects = objects;
+ }
+
+ ,getMain: function ()
+ {
+ return this.builder.getMain (this);
}
,$: function (objectId)
{
- return this.getById (objectId);
+ return this.builder.getById (objectId, this);
}
-
+
,getById: function (objectId)
{
- var object = this.objectMap[objectId];
-
- if (object)
- return object;
- if (this.parentBuilder)
- return this.parentBuilder.get (objectId);
-
- return null;
+ return this.builder.getById (objectId, this);
}
,getByTagName: function (tagName)
{
- if (this.tags[tagName])
- return this.tags[tagName];
-
- return [];
+ return this.builder.getByTagName (tagName, this);
}
,_destroy: function ()
{
- for (var tag in this.tags)
- {
- var objects = this.tags[tag];
+ var objects = this.objects;
+
+ for (var i = 0; i < objects.length; i++)
+ if (objects[i] instanceof Vn.Object)
+ objects[i].unref ();
- for (var i = 0; i < objects.length; i++)
- objects[i].unref ();
- }
-
this.parent ();
}
});
diff --git a/web/js/vn/main.js b/web/js/vn/main.js
index 9dcac47e..0a650f28 100644
--- a/web/js/vn/main.js
+++ b/web/js/vn/main.js
@@ -16,7 +16,6 @@ Vn.includeLib ('vn',
,'hash-param'
,'node'
,'builder'
- ,'builder-new'
,'http-request'
]);