This commit is contained in:
Juan Ferrer Toribio 2015-11-09 09:14:33 +01:00
parent 5779a5bfa6
commit 7b4ff3b815
44 changed files with 968 additions and 673 deletions

View File

@ -1,17 +1,22 @@
<vn> <vn>
<vn-group> <vn-group>
<db-form id="user-form"> <db-form id="user-form">
<db-model id="user-model" updatable="true"> <db-model property="model" id="user-model" updatable="true">
SELECT user_id, default_address <custom>
FROM customer_view c SELECT user_id, default_address
FROM customer_view c
</custom>
</db-model> </db-model>
</db-form> </db-form>
<db-model id="addresses" updatable="true"> <db-model id="addresses" updatable="true">
SELECT a.id, a.consignee, p.name province, a.zip_code, a.city, a.name, a.active, c.Pais country <custom>
FROM address_view a SELECT a.id, a.consignee, p.name province, a.zip_code,
LEFT JOIN vn2008.province p ON a.province_id = p.province_id a.city, a.name, a.active, c.Pais country
JOIN vn2008.Paises c ON c.Id = p.Paises_Id FROM address_view a
WHERE active != FALSE LEFT JOIN vn2008.province p ON a.province_id = p.province_id
JOIN vn2008.Paises c ON c.Id = p.Paises_Id
WHERE active != FALSE
</custom>
</db-model> </db-model>
</vn-group> </vn-group>
<div id="title"> <div id="title">
@ -32,39 +37,39 @@
column="default_address" column="default_address"
form="user-form"/> form="user-form"/>
<htk-repeater model="addresses" form-id="iter"> <htk-repeater model="addresses" form-id="iter">
<template> <custom>
<div class="address"> <div class="address">
<p class="consignee"> <p class="consignee">
<htk-text form="iter" column="consignee"/> <htk-text form="iter" column="consignee"/>
</p> </p>
<p> <p>
<htk-text form="iter" column="name"/> <htk-text form="iter" column="name"/>
</p> </p>
<p> <p>
<htk-text form="iter" column="zip_code"/>, <htk-text form="iter" column="zip_code"/>,
<htk-text form="iter" column="city"/> <htk-text form="iter" column="city"/>
</p> </p>
<div class="actions"> <div class="actions">
<htk-radio <htk-radio
form="iter" form="iter"
column="id" column="id"
radio-group="default-address" radio-group="default-address"
tip="_SetAsDefault"/> tip="_SetAsDefault"/>
<htk-button <htk-button
form="iter" form="iter"
column="id" column="id"
tip="_RemoveAddress" tip="_RemoveAddress"
image="image/delete.svg" image="image/delete.svg"
on-click="onRemoveAddressClick"/> on-click="onRemoveAddressClick"/>
<htk-button <htk-button
form="iter" form="iter"
column="id" column="id"
tip="_EditAddress" tip="_EditAddress"
image="image/edit.svg" image="image/edit.svg"
on-click="onEditAddressClick"/> on-click="onEditAddressClick"/>
</div>
</div> </div>
</template> </div>
</custom>
</htk-repeater> </htk-repeater>
</div> </div>
</div> </div>

View File

@ -1,18 +1,20 @@
<vn> <vn>
<vn-group> <vn-group>
<vn-hash-param key="address"> <vn-param id="address"/>
<vn-param id="address"/> <vn-hash-param key="address" param="address"/>
</vn-hash-param>
<db-form id="iter" on-status-changed="onStatusChange"> <db-form id="iter" on-status-changed="onStatusChange">
<db-param id="country" one-way="true" column="country_id"/> <db-model property="model" id="model" updatable="true" mode="ON_DEMAND" on-operations-done="onOperationsDone">
<db-model id="model" updatable="true" mode="ON_DEMAND" on-operations-done="onOperationsDone"> <custom>
SELECT a.id, a.name, a.consignee, a.city, a.zip_code, a.province_id, c.Id country_id SELECT a.id, a.name, a.consignee, a.city, a.zip_code, a.province_id, c.Id country_id
FROM address_view a FROM address_view a
LEFT JOIN vn2008.province p ON p.province_id = a.province_id LEFT JOIN vn2008.province p ON p.province_id = a.province_id
JOIN vn2008.Paises c ON c.Id = p.Paises_Id JOIN vn2008.Paises c ON c.Id = p.Paises_Id
WHERE active != FALSE AND a.id = #address WHERE active != FALSE AND a.id = #address
</custom>
<sql-batch property="batch"> <sql-batch property="batch">
<item name="address" param="address"/> <custom>
<item name="address" param="address"/>
</custom>
</sql-batch> </sql-batch>
</db-model> </db-model>
</db-form> </db-form>
@ -53,10 +55,17 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>Country</t></label> <label><t>Country</t></label>
<htk-combo param="country"> <htk-combo>
<db-param
property="param"
form="iter"
column="country_id"
one-way="true"/>
<db-model property="model"> <db-model property="model">
SELECT Id, Pais FROM vn2008.Paises <custom>
ORDER BY Pais SELECT Id, Pais FROM vn2008.Paises
ORDER BY Pais
</custom>
</db-model> </db-model>
</htk-combo> </htk-combo>
</div> </div>
@ -64,11 +73,15 @@
<label><t>Province</t></label> <label><t>Province</t></label>
<htk-combo column="province_id" form="iter"> <htk-combo column="province_id" form="iter">
<db-model property="model"> <db-model property="model">
SELECT province_id, name FROM vn2008.province <custom>
WHERE Paises_Id = #country SELECT province_id, name FROM vn2008.province
ORDER BY name WHERE Paises_Id = #country
ORDER BY name
</custom>
<sql-batch property="batch"> <sql-batch property="batch">
<item name="country" param="country"/> <custom>
<item name="country" param="country"/>
</custom>
</sql-batch> </sql-batch>
</db-model> </db-model>
</htk-combo> </htk-combo>

View File

@ -5,12 +5,14 @@
<div id="form" class="home"> <div id="form" class="home">
<div class="column mansonry" id="news-column"> <div class="column mansonry" id="news-column">
<htk-repeater form-id="new"> <htk-repeater form-id="new">
<db-model> <db-model property="model">
SELECT title, date_time, text, image, id FROM news <custom>
WHERE tag != 'course' SELECT title, date_time, text, image, id FROM news
ORDER BY priority, date_time DESC WHERE tag != 'course'
ORDER BY priority, date_time DESC
</custom>
</db-model> </db-model>
<template> <custom>
<div class="masonry-box"> <div class="masonry-box">
<div class="new"> <div class="new">
<div class="top"> <div class="top">
@ -25,7 +27,7 @@
<htk-image directory="news/full" form="new" column="image"/> <htk-image directory="news/full" form="new" column="image"/>
</div> </div>
</div> </div>
</template> </custom>
</htk-repeater> </htk-repeater>
</div> </div>
</div> </div>

View File

@ -5,12 +5,14 @@
<div id="form" class="training"> <div id="form" class="training">
<div class="column masonry" id="news-column"> <div class="column masonry" id="news-column">
<htk-repeater form-id="new"> <htk-repeater form-id="new">
<db-model id="news"> <db-model property="model">
SELECT title, date_time, text, image, id FROM news <custom>
WHERE tag = 'course' SELECT title, date_time, text, image, id FROM news
ORDER BY priority, date_time DESC WHERE tag = 'course'
ORDER BY priority, date_time DESC
</custom>
</db-model> </db-model>
<template> <custom>
<div class="masonry-box"> <div class="masonry-box">
<div class="new"> <div class="new">
<div class="top"> <div class="top">
@ -25,7 +27,7 @@
<htk-image directory="news/full" form="new" column="image"/> <htk-image directory="news/full" form="new" column="image"/>
</div> </div>
</div> </div>
</template> </custom>
</htk-repeater> </htk-repeater>
</div> </div>
</div> </div>

View File

@ -399,8 +399,6 @@ Vn.Filter = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('div'); this.createElement ('div');
this.node.className = 'vn-filter'; this.node.className = 'vn-filter';
@ -411,6 +409,8 @@ Vn.Filter = new Class
this._ul = document.createElement ('ul'); this._ul = document.createElement ('ul');
this.node.appendChild (this._ul); this.node.appendChild (this._ul);
this.parent (props);
} }
,_onClick: function () ,_onClick: function ()

View File

@ -24,13 +24,11 @@
--> -->
</vn-group> </vn-group>
<vn-group> <vn-group>
<vn-hash-param key="realm">
<vn-param id="realm" on-changed="onTypeChange"/>
</vn-hash-param>
<vn-hash-param key="type">
<vn-param id="type" on-changed="onTypeChange"/>
</vn-hash-param>
<vn-param id="search"/> <vn-param id="search"/>
<vn-param id="realm" on-changed="onTypeChange"/>
<vn-param id="type" on-changed="onTypeChange"/>
<vn-hash-param key="realm" param="realm"/>
<vn-hash-param key="type" param="type"/>
<sql-filter type="AND" id="filter"> <sql-filter type="AND" id="filter">
<sql-filter-item type="LIKE" id="op-name"> <sql-filter-item type="LIKE" id="op-name">
<sql-field name="Article"/> <sql-field name="Article"/>
@ -52,32 +50,38 @@
GROUP BY warehouse_id GROUP BY warehouse_id
</db-query> </db-query>
<db-model result-index="2" id="items-model"> <db-model result-index="2" id="items-model">
CREATE TEMPORARY TABLE tmp.bionic_calc <custom>
(INDEX (item_id)) CREATE TEMPORARY TABLE tmp.bionic_calc
ENGINE=MEMORY (INDEX (item_id))
SELECT Id_Article item_id FROM vn2008.Articles ENGINE=MEMORY
WHERE #filter; SELECT Id_Article item_id FROM vn2008.Articles
CALL bionic_calc (); WHERE #filter;
SELECT a.Id_Article item_id, t.available, t.price, p.producer, CALL bionic_calc ();
a.Foto, a.Article, a.Categoria, a.Medida, a.Tallos, a.Color, o.Abreviatura SELECT a.Id_Article item_id, t.available, t.price, p.producer,
FROM tmp.bionic_item t a.Foto, a.Article, a.Categoria, a.Medida, a.Tallos, a.Color, o.Abreviatura
JOIN vn2008.Articles a ON a.Id_Article = t.item_id FROM tmp.bionic_item t
LEFT JOIN vn2008.Articles_producer p ON p.Id_Article = a.Id_Article JOIN vn2008.Articles a ON a.Id_Article = t.item_id
LEFT JOIN vn2008.Origen o ON a.id_origen = o.id LEFT JOIN vn2008.Articles_producer p ON p.Id_Article = a.Id_Article
WHERE t.available > 0 LEFT JOIN vn2008.Origen o ON a.id_origen = o.id
ORDER BY a.Article, a.Medida WHERE t.available > 0
LIMIT 400; ORDER BY a.Article, a.Medida
LIMIT 400;
</custom>
<sql-batch property="batch" id="batch"> <sql-batch property="batch" id="batch">
<item name="filter" object="filter"/> <custom>
<item name="filter" object="filter"/>
</custom>
</sql-batch> </sql-batch>
</db-model> </db-model>
<db-model id="item-lots" result-index="1" on-status-changed-after="onStatusChange"> <db-model id="item-lots" result-index="1" on-status-changed-after="onStatusChange">
CALL bionic_from_item (#item); <custom>
SELECT p.warehouse_id, p.grouping, p.price, p.rate, l.available CALL bionic_from_item (#item);
FROM tmp.bionic_lot l SELECT p.warehouse_id, p.grouping, p.price, p.rate, l.available
JOIN tmp.bionic_price p FROM tmp.bionic_lot l
ON p.warehouse_id = l.warehouse_id JOIN tmp.bionic_price p
ORDER BY warehouse_id, grouping; ON p.warehouse_id = l.warehouse_id
ORDER BY warehouse_id, grouping;
</custom>
<sql-batch property="batch" id="lots-batch"/> <sql-batch property="batch" id="lots-batch"/>
</db-model> </db-model>
</vn-group> </vn-group>
@ -148,7 +152,7 @@
</div> </div>
</div> </div>
<htk-repeater id="grid-view" class="grid-view" empty-message="_SelectSubtype" form-id="item"> <htk-repeater id="grid-view" class="grid-view" empty-message="_SelectSubtype" form-id="item">
<template> <custom>
<div class="box item-box"> <div class="box item-box">
<div class="image"> <div class="image">
<htk-image <htk-image
@ -188,7 +192,7 @@
class="add-button"/> class="add-button"/>
<div class="clear"/> <div class="clear"/>
</div> </div>
</template> </custom>
</htk-repeater> </htk-repeater>
<div id="right-panel" class="right-panel" on-click="onRightPanelClick"> <div id="right-panel" class="right-panel" on-click="onRightPanelClick">
<div class="body"> <div class="body">
@ -222,7 +226,7 @@
</option> </option>
</select> </select>
<vn-filter placeholder="_Realm"> <vn-filter placeholder="_Realm">
<db-model auto-load="false" result-index="1"> <db-model property="model" auto-load="false" result-index="1">
CALL item_available (); CALL item_available ();
SELECT DISTINCT r.id, r.reino SELECT DISTINCT r.id, r.reino
FROM vn2008.reinos r FROM vn2008.reinos r
@ -235,7 +239,7 @@
</db-model> </db-model>
</vn-filter> </vn-filter>
<vn-filter placeholder="_Subtype"> <vn-filter placeholder="_Subtype">
<db-model auto-load="false" result-index="1"> <db-model property="model" auto-load="false" result-index="1">
CALL item_available (); CALL item_available ();
SELECT DISTINCT t.tipo_id, LEFT(t.Tipo, 18) type SELECT DISTINCT t.tipo_id, LEFT(t.Tipo, 18) type
FROM vn2008.Tipos t FROM vn2008.Tipos t
@ -246,7 +250,7 @@
</db-model> </db-model>
</vn-filter> </vn-filter>
<vn-filter placeholder="_Color"> <vn-filter placeholder="_Color">
<db-model auto-load="false" result-index="1"> <db-model property="model" auto-load="false" result-index="1">
CALL item_available (); CALL item_available ();
SELECT DISTINCT c.Id_Tinta, c.name SELECT DISTINCT c.Id_Tinta, c.name
FROM vn2008.Tintas c FROM vn2008.Tintas c
@ -257,7 +261,7 @@
</db-model> </db-model>
</vn-filter> </vn-filter>
<vn-filter placeholder="_Origin"> <vn-filter placeholder="_Origin">
<db-model auto-load="false" result-index="1"> <db-model property="model" auto-load="false" result-index="1">
CALL item_available (); CALL item_available ();
SELECT DISTINCT o.id, o.Origen, o.Abreviatura SELECT DISTINCT o.id, o.Origen, o.Abreviatura
FROM vn2008.Origen o FROM vn2008.Origen o
@ -268,7 +272,7 @@
</db-model> </db-model>
</vn-filter> </vn-filter>
<vn-filter placeholder="_Category"> <vn-filter placeholder="_Category">
<db-model auto-load="false" result-index="1"> <db-model property="model" auto-load="false" result-index="1">
CALL item_available (); CALL item_available ();
SELECT DISTINCT a.Categoria, a.Categoria category SELECT DISTINCT a.Categoria, a.Categoria category
FROM vn2008.Articles a FROM vn2008.Articles a

View File

@ -5,46 +5,58 @@
<vn-param id="agency"/> <vn-param id="agency"/>
<vn-param id="address" on-changed="onAddressChange"/> <vn-param id="address" on-changed="onAddressChange"/>
<db-form id="defaults" on-ready="onValuesReady"> <db-form id="defaults" on-ready="onValuesReady">
<db-model> <db-model property="model">
SELECT delivery_method, agency_id, address_id <custom>
FROM basket_defaults SELECT delivery_method, agency_id, address_id
FROM basket_defaults
</custom>
</db-model> </db-model>
</db-form> </db-form>
<db-form id="order-form" on-ready="onValuesReady"> <db-form id="order-form" on-ready="onValuesReady">
<db-model> <db-model property="model">
SELECT v.code delivery_method, o.date_send, o.agency_id, o.address_id <custom>
FROM basket o SELECT v.code delivery_method, o.date_send, o.agency_id, o.address_id
JOIN vn2008.Vistas v ON o.delivery_method_id = v.vista_id FROM basket o
JOIN vn2008.Vistas v ON o.delivery_method_id = v.vista_id
</custom>
</db-model> </db-model>
</db-form> </db-form>
<db-model property="model" id="agencies" auto-load="false" result-index="1" on-status-changed="onAgenciesReady"> <db-model id="agencies" auto-load="false" result-index="1" on-status-changed="onAgenciesReady">
CALL agency_list_from_date (#date, #address); <custom>
SELECT a.Id_Agencia, a.description CALL agency_list_from_date (#date, #address);
FROM t_agency t SELECT a.Id_Agencia, a.description
JOIN vn2008.Agencias a ON a.Id_Agencia = t.agency_id FROM t_agency t
JOIN vn2008.Vistas v ON a.Vista = v.vista_id JOIN vn2008.Agencias a ON a.Id_Agencia = t.agency_id
WHERE a.web != FALSE JOIN vn2008.Vistas v ON a.Vista = v.vista_id
AND v.code = 'AGENCY' WHERE a.web != FALSE
ORDER BY a.description; AND v.code = 'AGENCY'
DROP TEMPORARY TABLE t_agency; ORDER BY a.description;
DROP TEMPORARY TABLE t_agency;
</custom>
<sql-batch property="batch"> <sql-batch property="batch">
<item name="address" param="address"/> <custom>
<item name="date" param="date"/> <item name="address" param="address"/>
<item name="date" param="date"/>
</custom>
</sql-batch> </sql-batch>
</db-model> </db-model>
<db-model property="model" id="warehouses" auto-load="false" result-index="1" on-status-changed="onWarehousesReady"> <db-model id="warehouses" auto-load="false" result-index="1" on-status-changed="onWarehousesReady">
CALL agency_list_from_date (#date, #address); <custom>
SELECT a.Id_Agencia, SUBSTR(a.description, 5) description CALL agency_list_from_date (#date, #address);
FROM t_agency t SELECT a.Id_Agencia, SUBSTR(a.description, 5) description
JOIN vn2008.Agencias a ON a.Id_Agencia = t.agency_id FROM t_agency t
JOIN vn2008.Vistas v ON a.Vista = v.vista_id JOIN vn2008.Agencias a ON a.Id_Agencia = t.agency_id
WHERE a.web != FALSE JOIN vn2008.Vistas v ON a.Vista = v.vista_id
AND v.code = 'PICKUP' WHERE a.web != FALSE
ORDER BY a.description; AND v.code = 'PICKUP'
DROP TEMPORARY TABLE t_agency; ORDER BY a.description;
DROP TEMPORARY TABLE t_agency;
</custom>
<sql-batch property="batch"> <sql-batch property="batch">
<item name="address" param="address"/> <custom>
<item name="date" param="date"/> <item name="address" param="address"/>
<item name="date" param="date"/>
</custom>
</sql-batch> </sql-batch>
</db-model> </db-model>
</vn-group> </vn-group>
@ -108,14 +120,16 @@
form-id="iter" form-id="iter"
on-change="onAddressChange" on-change="onAddressChange"
renderer="addressRenderer"> renderer="addressRenderer">
<db-model id="addresses"> <db-model property="model" id="addresses">
SELECT a.id, a.consignee, p.name province, a.zip_code, a.city, a.name, a.active, c.Pais country <custom>
FROM address_view a SELECT a.id, a.consignee, p.name province, a.zip_code, a.city, a.name, a.active, c.Pais country
LEFT JOIN vn2008.province p ON a.province_id = p.province_id FROM address_view a
JOIN vn2008.Paises c ON c.Id = p.Paises_Id LEFT JOIN vn2008.province p ON a.province_id = p.province_id
WHERE active != FALSE JOIN vn2008.Paises c ON c.Id = p.Paises_Id
WHERE active != FALSE
</custom>
</db-model> </db-model>
<template> <custom>
<div class="address" id="address"> <div class="address" id="address">
<p class="consignee"> <p class="consignee">
<htk-text form="iter" column="consignee"/> <htk-text form="iter" column="consignee"/>
@ -124,7 +138,7 @@
<htk-text form="iter" column="name"/> <htk-text form="iter" column="name"/>
</p> </p>
</div> </div>
</template> </custom>
</htk-repeater> </htk-repeater>
</div> </div>
</div> </div>

View File

@ -1,9 +1,11 @@
<vn> <vn>
<vn-group> <vn-group>
<db-model id="debt-model" result-index="1"> <db-model id="debt-model" result-index="1">
CALL customer_get_debt_by_company (); <custom>
SELECT * FROM t_customer_debt; CALL customer_get_debt_by_company ();
DROP TEMPORARY TABLE t_customer_debt; SELECT * FROM t_customer_debt;
DROP TEMPORARY TABLE t_customer_debt;
</custom>
</db-model> </db-model>
</vn-group> </vn-group>
<div id="title"> <div id="title">
@ -31,8 +33,10 @@
<div class="box confirmed"> <div class="box confirmed">
<div> <div>
<htk-grid show-header="false"> <htk-grid show-header="false">
<db-model id="tickets"> <db-model property="model" id="tickets">
CALL ticket_list (); <custom>
CALL ticket_list ();
</custom>
</db-model> </db-model>
<htk-column-date column="date" format="%A, %e of %B"/> <htk-column-date column="date" format="%A, %e of %B"/>
<htk-column-text title="_SendMethod" column="type"/> <htk-column-text title="_SendMethod" column="type"/>

View File

@ -206,6 +206,7 @@ Db.Model.implement
} }
} }
,_conn: null
,_resultIndex: 0 ,_resultIndex: 0
,_batch: null ,_batch: null
,_stmt: null ,_stmt: null

View File

@ -1,7 +1,9 @@
Vn.App = new Class Vn.App = new Class
({ ({
initialize: function () Extends: Vn.Object
,initialize: function ()
{ {
window.onerror = this.onWindowError.bind (this); window.onerror = this.onWindowError.bind (this);
Vn.Hash.initialize (); Vn.Hash.initialize ();

View File

@ -12,8 +12,7 @@
<div class="logo"> <div class="logo">
<img src="image/logo.svg" alt=""/> <img src="image/logo.svg" alt=""/>
</div> </div>
<div class="version-code"> <div class="version-code"/>
</div>
<div class="form-inputs"> <div class="form-inputs">
<div class="form-group"> <div class="form-group">
<label for="user"><t>User</t></label> <label for="user"><t>User</t></label>

View File

@ -20,7 +20,7 @@ Vn.Module = new Class
,$: function (objectId) ,$: function (objectId)
{ {
if (this.builder) if (this.builder)
return this.builder.get (objectId); return this.builder.getById (objectId);
return null; return null;
} }
@ -32,24 +32,26 @@ Vn.Module = new Class
{ {
this.close (); this.close ();
this.builder = new Vn.Builder (); var builder = new Vn.Builder ();
this.builder.signalData = this; builder.signalData = this;
this.builder.loadXml (Vn.getXml ('forms/'+ this.formInfo.path +'/ui.xml')); builder.loadXml ('forms/'+ this.formInfo.path +'/ui.xml');
this.node = this.builder.get ('form');
var models = this.builder.getObjects ('db-model'); var res = this.builder = builder.load ();
this.node = res.$('form');
var models = res.getByTagName ('db-model');
for (var i = 0; i < models.length; i++) for (var i = 0; i < models.length; i++)
models[i].conn = this.conn; models[i].conn = this.conn;
var queries = this.builder.getObjects ('db-query'); var queries = res.getByTagName ('db-query');
for (var i = 0; i < queries.length; i++) for (var i = 0; i < queries.length; i++)
queries[i].conn = this.conn; queries[i].conn = this.conn;
this.gui.formHolder.appendChild (this.node); this.gui.formHolder.appendChild (this.node);
this.gui.setTitle (this.builder.$('title')); this.gui.setTitle (res.$('title'));
this.gui.setActions (this.builder.$('actions')); this.gui.setActions (res.$('actions'));
} }
/** /**

View File

@ -40,8 +40,6 @@ Htk.AssitantBar = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
var bar = this.createElement ('div'); var bar = this.createElement ('div');
bar.className = 'htk-assistant-bar'; bar.className = 'htk-assistant-bar';
@ -65,6 +63,7 @@ Htk.AssitantBar = new Class
this._steps = steps; this._steps = steps;
this._previousButton = previousButton; this._previousButton = previousButton;
this._nextButton = nextButton; this._nextButton = nextButton;
this.parent (props);
} }
,movePrevious: function () ,movePrevious: function ()

View File

@ -6,7 +6,6 @@ Htk.Column = new Class
({ ({
Extends: Vn.Object Extends: Vn.Object
,Tag: 'htk-column' ,Tag: 'htk-column'
,Parent: 'grid'
,Properties: ,Properties:
{ {
value: value:
@ -50,15 +49,6 @@ Htk.Column = new Class
{ {
return this._class; return this._class;
} }
},
grid:
{
type: Htk.Grid
,set: function (x)
{
if (x)
x.appendColumn (this);
}
} }
} }
@ -67,8 +57,8 @@ Htk.Column = new Class
**/ **/
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.td = document.createElement ('td'); this.td = document.createElement ('td');
this.parent (props);
} }
/** /**

View File

@ -50,13 +50,14 @@ Htk.Button = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('button'); this.createElement ('button');
this.node.className = 'htk-button'; this.node.className = 'htk-button';
this.node.addEventListener ('click', this.onClick.bind (this)); this.node.addEventListener ('click', this.onClick.bind (this));
this.img = document.createElement ('img'); this.img = document.createElement ('img');
this.node.appendChild (this.img); this.node.appendChild (this.img);
this.parent (props);
} }
,render: function () ,render: function ()

View File

@ -25,7 +25,6 @@ Htk.Calendar = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
var len = Vn.Date.WDays.length; var len = Vn.Date.WDays.length;
this.createElement ('div'); this.createElement ('div');
@ -133,6 +132,7 @@ Htk.Calendar = new Class
this.monthNode = monthNode; this.monthNode = monthNode;
this.yearNode = yearNode; this.yearNode = yearNode;
this.goToCurrentMonth (); this.goToCurrentMonth ();
this.parent (props);
} }
,getMonthDays: function () ,getMonthDays: function ()

View File

@ -5,10 +5,11 @@ Htk.Check = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('input'); this.createElement ('input');
this.node.type = 'checkbox'; this.node.type = 'checkbox';
this.node.addEventListener ('change', this.changed.bind (this)); this.node.addEventListener ('change', this.changed.bind (this));
this.parent (props);
} }
,changed: function () ,changed: function ()

View File

@ -10,7 +10,6 @@ Htk.DateChooser = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('div'); this.createElement ('div');
this.node.className = 'htk-date-chooser'; this.node.className = 'htk-date-chooser';
@ -18,6 +17,7 @@ Htk.DateChooser = new Class
this.node.appendChild (this.label); this.node.appendChild (this.label);
this.setEditable (this._editable); this.setEditable (this._editable);
this.parent (props);
} }
,putValue: function (value) ,putValue: function (value)

View File

@ -5,10 +5,11 @@ Htk.Entry = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('input'); this.createElement ('input');
this.node.type = 'text'; this.node.type = 'text';
this.node.addEventListener ('change', this.onChange.bind (this)); this.node.addEventListener ('change', this.onChange.bind (this));
this.parent (props);
} }
,onChange: function (event) ,onChange: function (event)

View File

@ -5,8 +5,8 @@ Htk.Html = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('div'); this.createElement ('div');
this.parent (props);
} }
,putValue: function (value) ,putValue: function (value)

View File

@ -5,7 +5,7 @@ var fullImage = null;
Htk.Image = new Class Htk.Image = new Class
({ ({
Extends: Htk.Entry Extends: Htk.Field
,Tag: 'htk-image' ,Tag: 'htk-image'
,Properties: ,Properties:
{ {
@ -93,12 +93,13 @@ Htk.Image = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('img'); this.createElement ('img');
// this.node.addEventListener ('error', this.onImageError.bind (this)); // this.node.addEventListener ('error', this._onImageError.bind (this));
this.parent (props);
} }
,onImageError: function () ,_onImageError: function ()
{ {
if (!this._empty) if (!this._empty)
{ {

View File

@ -26,8 +26,8 @@ Htk.Label = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('label'); this.createElement ('label');
this.parent (props);
} }
,putValue: function (value) ,putValue: function (value)

View File

@ -7,9 +7,9 @@ Htk.RadioGroup = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.clear (); this.clear ();
this.on ('changed', this.onRadioGroupChange, this); this.on ('changed', this.onRadioGroupChange, this);
this.parent (props);
} }
,clear: function () ,clear: function ()

View File

@ -33,12 +33,12 @@ Htk.Radio = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
var radio = Vn.Browser.createRadio (''); var radio = Vn.Browser.createRadio ('');
radio.checked = false; radio.checked = false;
radio.addEventListener ('change', this.onChange.bind (this)); radio.addEventListener ('change', this.onChange.bind (this));
this.node = radio; this.node = radio;
this.parent (props);
} }
,onChange: function () ,onChange: function ()

View File

@ -96,10 +96,11 @@ Htk.Select = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('select'); this.createElement ('select');
this.node.addEventListener ('change', this._onChange.bind (this)); this.node.addEventListener ('change', this._onChange.bind (this));
this._addPlaceholder (this._placeholder); this._addPlaceholder (this._placeholder);
this.parent (props);
} }
,on: function (id, callback, instance) ,on: function (id, callback, instance)

View File

@ -5,9 +5,9 @@ Htk.Spin = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.unit = null; this.unit = null;
this.digits = 0; this.digits = 0;
this.parent (props);
} }
,changed: function () ,changed: function ()

View File

@ -5,8 +5,6 @@ Htk.Table = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
var tv = new Htk.TreeView (); var tv = new Htk.TreeView ();
this.node.appendChild (tv.getNode ()); this.node.appendChild (tv.getNode ());
@ -18,6 +16,7 @@ Htk.Table = new Class
this.treeview = tv; this.treeview = tv;
this.rbGroup = rbGroup; this.rbGroup = rbGroup;
this.parent (props);
} }
,setModel: function (model) ,setModel: function (model)

View File

@ -5,9 +5,10 @@ Htk.TextArea = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.createElement ('textarea'); this.createElement ('textarea');
this.node.addEventListener ('change', this.changed.bind (this)); this.node.addEventListener ('change', this.changed.bind (this));
this.parent (props);
} }
,changed: function (event) ,changed: function (event)

View File

@ -26,8 +26,8 @@ Htk.Text = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.node = document.createTextNode (''); this.node = document.createTextNode ('');
this.parent (props);
} }
,putValue: function (value) ,putValue: function (value)

View File

@ -12,8 +12,6 @@ Htk.FullImage = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
var div = document.createElement ('div'); var div = document.createElement ('div');
div.className = 'htk-full-image'; div.className = 'htk-full-image';
div.addEventListener ('mouseover', this.cancelHide.bind (this)); div.addEventListener ('mouseover', this.cancelHide.bind (this));
@ -30,6 +28,7 @@ Htk.FullImage = new Class
this.div = div; this.div = div;
this.loadingBox = loadingBox; this.loadingBox = loadingBox;
this.loadingImg = loadingImg; this.loadingImg = loadingImg;
this.parent (props);
} }
,getLeft: function (width) ,getLeft: function (width)

View File

@ -61,8 +61,6 @@ Htk.Grid = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
this.table = this.createElement ('table'); this.table = this.createElement ('table');
this.table.className = 'htk-grid'; this.table.className = 'htk-grid';
@ -74,6 +72,13 @@ Htk.Grid = new Class
this.tbody = document.createElement ('tbody'); this.tbody = document.createElement ('tbody');
this.table.appendChild (this.tbody); this.table.appendChild (this.tbody);
this.parent (props);
}
,appendChild: function (child)
{
this.appendColumn (child);
} }
,removeClicked: function (column, value, row) ,removeClicked: function (column, value, row)

View File

@ -11,12 +11,13 @@ Htk.ImageEditor = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props)
this.builderInit (this.constructor.Xml); this.builderInit (this.constructor.Xml);
this.$('max-size').value = 10 /* MB */ * 1048576; this.$('max-size').value = 10 /* MB */ * 1048576;
this.$('form').action = this.$('form').action =
'//'+ Vn.Config['image_host'] +'/rest.php?action=image' '//'+ Vn.Config['image_host'] +'/rest.php?action=image';
this.parent (props);
} }
,onNameChange: function () ,onNameChange: function ()

View File

@ -5,8 +5,9 @@ Htk.Loader = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.parent (props);
var loader = this.createElement ('div'); var loader = this.createElement ('div');
loader.className = 'htk-loader'; loader.className = 'htk-loader';
this.parent (props);
} }
}); });

View File

@ -6,13 +6,14 @@ Htk.Popup = new Class
Extends: Htk.Widget Extends: Htk.Widget
,Tag: 'htk-popup' ,Tag: 'htk-popup'
,child: null ,_parent: null
,parent: null
,initialize: function () ,initialize: function (props)
{ {
this.createElement ('div'); var div = this.createElement ('div');
this.node.className = 'htk-popup'; div.className = 'htk-popup';
this.parent (props);
} }
,setChild: function (child) ,setChild: function (child)
@ -35,27 +36,27 @@ Htk.Popup = new Class
this.hideHandler = this.hide.bind (this); this.hideHandler = this.hide.bind (this);
document.addEventListener ('mousedown', this.hideHandler); document.addEventListener ('mousedown', this.hideHandler);
this.parent = parent; this._parent = parent;
this.reset (); this.reset ();
} }
,reset: function () ,reset: function ()
{ {
if (!this.parent) if (!this._parent)
return; return;
var spacing = 5; var spacing = 5;
var rect = this.parent.getBoundingClientRect (); var rect = this._parent.getBoundingClientRect ();
var left = rect.left; var left = rect.left;
var top = rect.top + spacing + this.parent.offsetHeight; var top = rect.top + spacing + this._parent.offsetHeight;
var width = this.node.offsetWidth; var width = this.node.offsetWidth;
var height = this.node.offsetHeight; var height = this.node.offsetHeight;
if (left + width > Vn.Browser.getInnerWidth ()) if (left + width > Vn.Browser.getInnerWidth ())
left -= width - this.parent.offsetWidth; left -= width - this._parent.offsetWidth;
if (top + height > Vn.Browser.getInnerHeight ()) if (top + height > Vn.Browser.getInnerHeight ())
top -= height + this.parent.offsetHeight + spacing * 2; top -= height + this._parent.offsetHeight + spacing * 2;
if (left < 0) if (left < 0)
left = 0; left = 0;
@ -68,7 +69,7 @@ Htk.Popup = new Class
,showCenter: function () ,showCenter: function ()
{ {
this.parent = null; this._parent = null;
this.background = document.createElement ('div'); this.background = document.createElement ('div');
this.background.className = 'htk-background'; this.background.className = 'htk-background';
@ -94,7 +95,7 @@ Htk.Popup = new Class
this.node.removeEventListener ('mousedown', this.stopEvent) this.node.removeEventListener ('mousedown', this.stopEvent)
document.removeEventListener ('mousedown', this.hideHandler); document.removeEventListener ('mousedown', this.hideHandler);
Vn.Node.remove (this.node); Vn.Node.remove (this.node);
this.parent = null; this._parent = null;
this.signalEmit ('closed'); this.signalEmit ('closed');
} }

View File

@ -30,11 +30,11 @@ Htk.Repeater = new Class
type: String type: String
,set: function (x) ,set: function (x)
{ {
this._alias = x; this._formId = x;
} }
,get: function () ,get: function ()
{ {
this._alias; this._formId;
} }
} }
,renderer: ,renderer:
@ -56,29 +56,26 @@ Htk.Repeater = new Class
} }
} }
,xml: null ,_builder: null
,parentBuilder: null ,_formId: 'form'
,_alias: 'form'
,initialize: function () ,initialize: function (props)
{ {
this.createElement ('div'); var div = this.createElement ('div');
this.node.className = 'htk-repeater'; div.className = 'htk-repeater';
this.parent (props);
} }
,loadXml: function (builder, node) ,loadXml: function (builderResult, node)
{ {
this.parent (builder, node); this.parent (builderResult, node);
var template = node.getElementsByTagName ('template')[0];
//var template = node.querySelector ('template:first-of-type');
if (template) var builder = this._builder = new Vn.Builder ();
{ builder.setParent (builderResult);
this.xml = template.firstElementChild; builder.loadXmlFromNode (node.firstElementChild);
this.parentBuilder = builder;
this.onModelChange (); this.onModelChange ();
}
} }
,getChild: function (index) ,getChild: function (index)
@ -98,30 +95,28 @@ Htk.Repeater = new Class
,buildBox: function (index) ,buildBox: function (index)
{ {
var builder = new Vn.Builder (); var form = new Db.Form ({
builder.setParent (this.parentBuilder); model: this._model,
row: index
var form = new Db.Form (); });
form.model = this._model;
form.row = index; this._builder.add (this._formId, form);
builder.add (this._alias, form); var res = this._builder.load ();
this.childsData.push ({ this.childsData.push ({
builder: builder, builder: res,
form: form form: form
}); });
var mainNode = builder.loadXmlFromNode (this.xml);
if (this._renderer) if (this._renderer)
this._renderer (builder, form); this._renderer (res, form);
this.node.appendChild (mainNode); this.node.appendChild (res.getMain ());
} }
,onModelChange: function () ,onModelChange: function ()
{ {
if (!this._model || !this.xml) if (!this._model || !this._builder)
return; return;
Vn.Node.removeChilds (this.node); Vn.Node.removeChilds (this.node);

View File

@ -23,10 +23,12 @@ Htk.Widget = new Class
,builderInit: function (path) ,builderInit: function (path)
{ {
this.builder = new Vn.Builder (); var builder = new Vn.Builder ();
this.builder.signalData = this; builder.signalData = this;
this.builder.loadXml (Vn.getXml (path)); builder.loadXml (path);
this.node = this.builder.get ('main');
var res = this.builder = builder.load ();
this.node = res.$('main');
} }
,createElement: function (tagName) ,createElement: function (tagName)
@ -43,7 +45,7 @@ Htk.Widget = new Class
,$: function (id) ,$: function (id)
{ {
if (this.builder) if (this.builder)
return this.builder.get (id); return this.builder.getById (id);
return null; return null;
} }

View File

@ -38,9 +38,9 @@ Sql.Batch = new Class
if (id) if (id)
{ {
if (object = builder.get (childs[i].getAttribute ('param'))) if (object = builder.getById (childs[i].getAttribute ('param')))
this.addParam (id, object); this.addParam (id, object);
else if (object = builder.get (childs[i].getAttribute ('object'))) else if (object = builder.getById (childs[i].getAttribute ('object')))
this.addObject (id, object); this.addObject (id, object);
} }
} }

View File

@ -5,17 +5,5 @@ Sql.Expr = new Class
({ ({
Extends: Sql.Object Extends: Sql.Object
,Tag: 'sql-expr' ,Tag: 'sql-expr'
,Parent: 'operation'
,Properties:
{
operation:
{
type: Sql.Operation
,set: function (x)
{
x.exprs.add (this);
}
}
}
}); });

View File

@ -42,6 +42,11 @@ Sql.Operation.implement
this.parent (props); this.parent (props);
this.link ({exprs: new Sql.List ()}, {'changed': this.onListChange}); this.link ({exprs: new Sql.List ()}, {'changed': this.onListChange});
} }
,appendChild: function (child)
{
this.exprs.add (child);
}
,onListChange: function () ,onListChange: function ()
{ {

575
web/js/vn/builder-new.js Executable file
View File

@ -0,0 +1,575 @@
/**
* 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 ();
}
});

View File

@ -1,13 +1,16 @@
/** /**
* Creates a object from a XML specification. * Creates a object from a XML specification.
**/ **/
Vn.Builder = new Class Vn.BuilderOld = new Class
({ ({
Extends: Vn.Object Extends: Vn.Object
,objectMap: {} ,objectMap: {}
,tags: {} ,tags: {}
//+++++++++++++++++++++++++++++++++++++++++++ Deprecated ,load: function ()
{
return this;
}
,loadXml: function (xmlDoc) ,loadXml: function (xmlDoc)
{ {
@ -62,7 +65,7 @@ Vn.Builder = new Class
{ {
htmlNode = document.importNode (node, false); htmlNode = document.importNode (node, false);
} }
else if ((customNode = this.loadCustomNode (node, null))) else if ((customNode = this.loadCustomNode (node, tagName, null)))
{ {
if (customNode instanceof Htk.Widget) if (customNode instanceof Htk.Widget)
htmlNode = customNode.getNode (); htmlNode = customNode.getNode ();
@ -108,12 +111,11 @@ Vn.Builder = new Class
return htmlNode; return htmlNode;
} }
,loadCustomNode: function (node, parentContext) ,loadCustomNode: function (node, tagName, parentContext)
{ {
if (!node.tagName) if (!tagName)
return null; return null;
var tagName = node.tagName.toLowerCase ();
var klass = Vn.customTags[tagName]; var klass = Vn.customTags[tagName];
if (!klass) if (!klass)
@ -131,6 +133,7 @@ Vn.Builder = new Class
,parent: parentContext ,parent: parentContext
,object: customNode ,object: customNode
,klass: klass ,klass: klass
,custom: null
}; };
this.contexts.push (context); this.contexts.push (context);
@ -143,8 +146,21 @@ Vn.Builder = new Class
if (childs) if (childs)
for (var i = 0; i < childs.length; i++) for (var i = 0; i < childs.length; i++)
this.loadCustomNode (childs[i], context); {
var childTagName = childs[i].tagName;
if (!childTagName)
continue;
childTagName = childTagName.toLowerCase ();
var customChild = this.loadCustomNode (
childs[i], childTagName, context);
if (!customChild && childTagName === 'custom')
context.custom = childs[i];
}
return customNode; return customNode;
} }
@ -158,21 +174,18 @@ Vn.Builder = new Class
for (var j = 0; j < a.length; j++) for (var j = 0; j < a.length; j++)
this.setAttribute (c, a[j].nodeName, a[j].nodeValue); this.setAttribute (c, a[j].nodeName, a[j].nodeValue);
if (c.custom)
c.object.loadXml (this, c.custom);
if (c.parent) if (c.parent)
{ {
var parentProperty = c.node.getAttribute ('property'); var parentProperty = c.node.getAttribute ('property');
if (!parentProperty)
parentProperty = c.parent.klass.Child;
if (parentProperty) if (parentProperty)
this.setProperty (c.parent, parentProperty, c.object); this.setProperty (c.parent, parentProperty, c.object);
else
if (c.klass.Parent) c.parent.object.appendChild (c.object);
this.setProperty (c, c.klass.Parent, c.parent.object);
} }
c.object.loadXml (this, c.node);
} }
} }
@ -240,368 +253,7 @@ Vn.Builder = new Class
console.warn ('Vn.Builder: Empty attribute \'%s\' on tag \'%s\'', console.warn ('Vn.Builder: Empty attribute \'%s\' on tag \'%s\'',
attribute, c.node.tagName); attribute, c.node.tagName);
} }
//+++++++++++++++++++++++++++++++++++++++++++ Alpha
,compile: function (node, dstDocument)
{
this.contexts = [];
this.contextMap = {};
this.propLinks = [];
this.childLinks = [];
this.document = dstDocument ? dstDocument : document;
this.compileRec (node, null);
for (var i = 0; i < this.propLinks.length; i++)
{
var pl = this.propLinks[i];
var contextId = this.contextMap[pl.value];
if (contextId)
{
pl.context.objectProps[pl.prop] = contextId;
continue;
}
var object = this.parentBuilder.get (pl.value);
if (object)
{
pl.context.props[pl.prop] = object;
continue;
}
console.warn ('Vn.Builder: Referenced unexistent object with id \'%s\'',
pl.value);
}
delete this.propLinks;
for (var i = 0; i < this.childLinks.length; i++)
{
var cl = this.childLinks[i];
var contextId = this.contextMap[pl.value];
if (contextId)
pl.context.childs.push (contextId);
else
console.warn ('Vn.Builder: Referenced unexistent object with id \'%s\'',
pl.value);
}
delete this.childLinks;
}
,compileRec: function (node)
{
var tagName = null;
if (node.tagName)
tagName = node.tagName.toLowerCase ();
var nextId = this.contexts.length;
var context =
createTextTemplate (nextId, node, tagName)
|| createObjectTemplate (nextId, node, tagName)
|| createHtmlTemplate (nextId, node, tagName);
this.contexts.push (context);
return context;
}
,load: function (thisData)
{
var contexts = this.contexts;
var objects = new Array (contexts.length);
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
if (context.func)
objects[i] = context.func (context);
}
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
if (context.linkFunc)
context.linkFunc (context, objects[i]);
}
}
/**
* Creates a text node template.
**/
,createTextTemplate: function (contextId, node, tagName)
{
if (tagName === 't')
var text = _(node.firstChild.textContent);
else if (!tagName)
var text = node.textContent;
else
return null;
return {
id: contextId,
text: text,
func: this.createTextInstance
};
}
,createTextInstance: function (context)
{
return this.document.createTextNode (context.text);
}
/**
* Creates a object template.
**/
,createObjectTemplate: function (contextId, node, tagName)
{
var id = null;
var handler;
var props = {};
var objectProps = {};
var childs = [];
var events = null;
var klass = Vn.customTags[tagName];
if (!klass)
return null;
var a = node.attributes;
for (var i = 0; i < a.length; i++)
{
var attribute = a[i].nodeName;
var value = a[i].nodeValue;
if (attribute === 'id')
{
this.contextMap[value] = contextId;
}
else if ((handler = this.getEventHandler (attribute, value)))
{
if (!events)
events = {};
events[attribute.substr (3)] = handler;
}
else if (attribute !== 'property')
{
this.createPropTemplate (context, klass, props,
node, attribute, value);
}
}
var context = {
id: contextId,
func: this.createObjectInstance,
linkFunc: this.createObjectLink,
klass: klass,
props: props,
events: events,
objectProps: objectProps,
childs: childs
};
var childs = node.childNodes;
if (childs)
for (var i = 0; i < childs.length; i++)
{
var child = childs[i];
var childTagName = child.tagName.toLowerCase ();
if (childTagName === 'pointer')
{
this.childLinks.push ({
context: context,
objectId: child.getAttribute ('object')
});
}
else if (childTagName === 'custom')
{
context.custom = child.firstElementChild;
}
else
{
var childContext = this.compileRec (child);
var prop = child.getAttribute ('property');
if (prop)
objectProps[prop] = childContext.id;
else
childs.push (childContext.id);
}
}
return context;
}
,createPropTemplate: 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;
case Vn.Enum:
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);
}
,createObjectInstance: function (context)
{
var object = new context.klass (context.props);
var events = context.events;
for (var event in events)
object.on (event,
events[event].bind (this.signalData));
return object;
}
,createObjectLink: function (context, object)
{
var objectProps = context.objectProps;
if (objectProps)
for (var prop in objectProps)
object[prop] = this.objects[objectProps[prop].id];
var childs = context.childs;
if (childs)
for (var i = 0; i < childs.length; i++)
object.appendChild (childs[i]);
if (context.custom)
object.loadXml (context.custom);
}
/**
* Creates a HTML node template.
**/
,createHtmlTemplate: function (contextId, node, tagName)
{
var handler;
var events = null;
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 (attribute === 'id')
{
this.contextMap[value] = contextId;
}
else if ((handler = this.getEventHandler (attribute, value)))
{
if (!events)
events = {};
events[attribute.substr (3)] = handler;
}
else
htmlNode.setAttribute (nodeName,
this.translateValue (nodeValue));
}
var childNodes = node.childNodes;
if (childNodes)
for (var i = 0; i < childNodes.length; i++)
{
var childContext = this.compileRec (childNodes[i]);
childs.push (childContext.id);
}
return {
id: contextId,
func: this.createHtmlInstance,
linkFunc: this.createHtmlLink,
node: htmlNode,
events: events,
childs: childs
};
}
,createHtmlInstance: function (context)
{
var object = new context.node.cloneNode (false);
var events = context.events;
for (var event in events)
object.addEventListener (event,
events[event].bind (this.signalData));
return object;
}
,createHtmlLink: function (context, object)
{
var childs = context.childs;
if (childs)
for (var i = 0; i < childs.length; i++)
object.appendChild (this.objects[childs[i]]);
}
//+++++++++++++++++++++++++++++++++++++++++++ Utilities //+++++++++++++++++++++++++++++++++++++++++++ Utilities
,translateValue: function (value) ,translateValue: function (value)
@ -663,10 +315,10 @@ Vn.Builder = new Class
,$: function (objectId) ,$: function (objectId)
{ {
return this.get (objectId); return this.getById (objectId);
} }
,get: function (objectId) ,getById: function (objectId)
{ {
var object = this.objectMap[objectId]; var object = this.objectMap[objectId];
@ -678,7 +330,7 @@ Vn.Builder = new Class
return null; return null;
} }
,getObjects: function (tagName) ,getByTagName: function (tagName)
{ {
if (this.tags[tagName]) if (this.tags[tagName])
return this.tags[tagName]; return this.tags[tagName];

View File

@ -16,6 +16,7 @@ Vn.includeLib ('vn',
,'hash-param' ,'hash-param'
,'node' ,'node'
,'builder' ,'builder'
,'builder-new'
,'http-request' ,'http-request'
]); ]);

View File

@ -11,7 +11,7 @@ Vn.Node =
} }
,remove: function (node) ,remove: function (node)
{ {
if (node.parentNode) if (node.parentNode)
node.parentNode.removeChild (node); node.parentNode.removeChild (node);
} }

View File

@ -8,9 +8,8 @@ Vn.Object = new Class
Tag: 'vn-object' Tag: 'vn-object'
,Properties: {} ,Properties: {}
,signals: {} ,_refCount: 1
,links: {} ,_signalData: null
,refCount: 1
,initialize: function (props) ,initialize: function (props)
{ {
@ -20,21 +19,28 @@ Vn.Object = new Class
,ref: function () ,ref: function ()
{ {
this.refCount++; this._refCount++;
return this; return this;
} }
,unref: function () ,unref: function ()
{ {
this.refCount--; this._refCount--;
if (this.refCount === 0) if (this._refCount === 0)
this._destroy (); this._destroy ();
} }
,loadXml: function (builder, node) ,loadXml: function (builder, node) {}
,appendChild: function (child) {}
,_signalInit: function ()
{ {
return null; if (!this._signalData)
this._signalData = {
signals: {},
links: {}
};
} }
/** /**
@ -50,12 +56,15 @@ Vn.Object = new Class
{ {
console.warn ('Vn.Object: Invalid callback for signal \'%s\'', id); console.warn ('Vn.Object: Invalid callback for signal \'%s\'', id);
return; return;
} }
if (!this.signals[id]) this._signalInit ();
this.signals[id] = []; var callbacks = this._signalData.signals[id];
if (!callbacks)
callbacks = this._signalData.signals[id] = [];
this.signals[id].push callbacks.push
({ ({
blocked: false blocked: false
,callback: callback ,callback: callback
@ -72,7 +81,10 @@ Vn.Object = new Class
**/ **/
,blockSignal: function (id, callback, block, instance) ,blockSignal: function (id, callback, block, instance)
{ {
var callbacks = this.signals[id]; if (!this._signalData)
return;
var callbacks = this._signalData.signals[id];
if (!callbacks) if (!callbacks)
return; return;
@ -90,7 +102,10 @@ Vn.Object = new Class
**/ **/
,signalEmit: function (id) ,signalEmit: function (id)
{ {
var callbacks = this.signals[id]; if (!this._signalData)
return;
var callbacks = this._signalData.signals[id];
if (!callbacks) if (!callbacks)
return; return;
@ -115,7 +130,10 @@ Vn.Object = new Class
**/ **/
,disconnect: function (id, callback, instance) ,disconnect: function (id, callback, instance)
{ {
var callbacks = this.signals[id]; if (!this._signalData)
return;
var callbacks = this._signalData.signals[id];
if (!callbacks) if (!callbacks)
return; return;
@ -133,9 +151,14 @@ Vn.Object = new Class
**/ **/
,disconnectByInstance: function (instance) ,disconnectByInstance: function (instance)
{ {
for (var signalId in this.signals) if (!this._signalData)
return;
var signals = this._signalData.signals;
for (var signalId in signals)
{ {
var callbacks = this.signals[signalId]; var callbacks = signals[signalId];
for (var i = 0; i < callbacks.length; i++) for (var i = 0; i < callbacks.length; i++)
if (callbacks[i].instance == instance) if (callbacks[i].instance == instance)
@ -149,17 +172,22 @@ Vn.Object = new Class
**/ **/
,_destroy: function () ,_destroy: function ()
{ {
var links = this.links; if (!this._signalData)
return;
var links = this._signalData.links;
for (var key in links) for (var key in links)
links[key].disconnectByInstance (this); links[key].disconnectByInstance (this);
delete this.links; this._signalData = null;
delete this.signals;
} }
,link: function (prop, handlers) ,link: function (prop, handlers)
{ {
this._signalInit ();
var links = this._signalData.links;
for (var key in prop) for (var key in prop)
{ {
var newObject = prop[key]; var newObject = prop[key];
@ -175,13 +203,13 @@ Vn.Object = new Class
if (newObject) if (newObject)
{ {
this.links[key] = newObject.ref (); links[key] = newObject.ref ();
for (var signal in handlers) for (var signal in handlers)
newObject.on (signal, handlers[signal], this); newObject.on (signal, handlers[signal], this);
} }
else if (oldObject) else if (oldObject)
delete this.links[key]; delete links[key];
} }
} }
}); });