0
1
Fork 0

Interpolate v2

This commit is contained in:
Juan Ferrer Toribio 2017-10-22 02:25:57 +02:00
parent f0dcd47baf
commit 4d8bd4ad95
32 changed files with 466 additions and 216 deletions

View File

@ -26,14 +26,6 @@ Hedera.Connections = new Class
this.$.sessions.refresh (); this.$.sessions.refresh ();
} }
,repeaterFunc: function (res, form)
{
res.$.link.href = this.hash.make ({
form: 'admin/access-log',
user: form.$.userId
});
}
,onChangeUserClick: function (button, form) ,onChangeUserClick: function (button, form)
{ {
this.gui.supplantUser (form.get ('user'), this.gui.supplantUser (form.get ('user'),

View File

@ -19,7 +19,7 @@
</div> </div>
<div id="main" class="connections"> <div id="main" class="connections">
<div class="card list"> <div class="card list">
<htk-repeater form-id="iter" renderer="repeaterFunc"> <htk-repeater>
<db-model property="model" id="sessions" on-status-changed="onModelStatusChange"> <db-model property="model" id="sessions" on-status-changed="onModelStatusChange">
SELECT vu.user userId, vu.stamp, c.Cliente, s.lastUpdate, SELECT vu.user userId, vu.stamp, c.Cliente, s.lastUpdate,
a.platform, a.browser, a.version, u.name user a.platform, a.browser, a.version, u.name user
@ -33,7 +33,9 @@
ORDER BY lastUpdate DESC ORDER BY lastUpdate DESC
</db-model> </db-model>
<custom> <custom>
<a id="link" class="list-row" title="_Access log"> <a href="#!form=admin/access-log&amp;user={{userId}}"
class="list-row"
title="_Access log">
<div class="actions"> <div class="actions">
<htk-button <htk-button
lot="iter" lot="iter"
@ -43,16 +45,14 @@
on-click="onChangeUserClick"/> on-click="onChangeUserClick"/>
</div> </div>
<p class="important"> <p class="important">
<htk-text lot="iter" name="Cliente"/> {{Cliente}}
</p> </p>
<p> <p>
<htk-text lot="iter" name="stamp" format="%a, %T"/> - <htk-text lot="iter" name="stamp" format="%a, %T"/> -
<htk-text lot="iter" name="lastUpdate" format="%T"/> <htk-text lot="iter" name="lastUpdate" format="%T"/>
</p> </p>
<p> <p>
<htk-text lot="iter" name="platform"/> - {{platform}} - {{browser}} {{version}}
<htk-text lot="iter" name="browser"/>
<htk-text lot="iter" name="version"/>
</p> </p>
</a> </a>
</custom> </custom>

View File

@ -12,8 +12,7 @@
<custom> <custom>
<a class="list-row" href="{{link}}" target="_blank"> <a class="list-row" href="{{link}}" target="_blank">
<htk-image <htk-image
lot="iter" value="{{image}}"
name="image"
directory="link" directory="link"
subdir="full"/> subdir="full"/>
<p class="important"> <p class="important">

View File

@ -24,8 +24,7 @@
title="_AccessLog"> title="_AccessLog">
<div class="actions"> <div class="actions">
<htk-button <htk-button
lot="iter" value="{{id}}"
name="id"
tip="_AccessAsUser" tip="_AccessAsUser"
icon="incognito" icon="incognito"
on-click="onChangeUserClick"/> on-click="onChangeUserClick"/>

View File

@ -42,7 +42,7 @@
</p> </p>
</div> </div>
<div class="card list "> <div class="card list ">
<htk-repeater form-id="iter" empty-message="_Select date interval"> <htk-repeater empty-message="_Select date interval">
<db-model property="model" id="visits" lot="hash"> <db-model property="model" id="visits" lot="hash">
SELECT browser SELECT browser
,MIN(CAST(version AS DECIMAL(4,1))) minVersion ,MIN(CAST(version AS DECIMAL(4,1))) minVersion
@ -61,9 +61,7 @@
<custom> <custom>
<div class="list-row"> <div class="list-row">
<p class="important"> <p class="important">
<htk-text lot="iter" name="browser"/> {{browser}} {{minVersion}} - {{maxVersion}}
<htk-text lot="iter" name="minVersion"/> -
<htk-text lot="iter" name="maxVersion"/>
</p> </p>
<p> <p>
<htk-text lot="iter" name="visits"/> <htk-text lot="iter" name="visits"/>

View File

@ -6,8 +6,8 @@ Hedera.Packages = new Class
,onShowClick: function (column, agencyId) ,onShowClick: function (column, agencyId)
{ {
this.hash.setAll ({ this.hash.setAll ({
'form': 'agencies/provinces', form: 'agencies/provinces',
'agency': agencyId agency: agencyId
}); });
} }
}); });

View File

@ -23,14 +23,13 @@
<div class="top"> <div class="top">
<h2>{{title}}</h2> <h2>{{title}}</h2>
<div class="new-text"> <div class="new-text">
<htk-html lot="iter" name="text"/> <htk-html value="{{text}}"/>
</div> </div>
</div> </div>
<htk-image <htk-image
directory="news" directory="news"
subdir="full" subdir="full"
lot="iter" value="{{image}}"
name="image"
editable="false" editable="false"
full-dir="full"/> full-dir="full"/>
</div> </div>

View File

@ -26,7 +26,7 @@
</htk-text> </htk-text>
</p> </p>
</div> </div>
<htk-repeater form-id="iter" renderer="repeaterFunc"> <htk-repeater renderer="repeaterFunc">
<db-model id="items" property="model" updatable="true"> <db-model id="items" property="model" updatable="true">
SELECT i.id, i.amount, i.price, a.Article, a.Categoria, SELECT i.id, i.amount, i.price, a.Article, a.Categoria,
a.Medida, a.Tallos, a.Color, o.Abreviatura, a.Foto a.Medida, a.Tallos, a.Color, o.Abreviatura, a.Foto
@ -37,26 +37,22 @@
<custom> <custom>
<div class="line"> <div class="line">
<htk-button <htk-button
lot="iter" value="{{ticket_id}}"
name="ticket_id"
class="delete" class="delete"
tip="_Remove" tip="_Remove"
icon="delete" icon="delete"
on-click="onDeleteClick"/> on-click="onDeleteClick"/>
<htk-image <htk-image
lot="iter" value="{{Foto}}"
name="Foto"
class="photo" class="photo"
directory="catalog" directory="catalog"
subdir="200x200" subdir="200x200"
full-dir="900x900"/> full-dir="900x900"/>
<p class="concept"> <p class="concept">
<htk-text lot="iter" name="Article"/> {{Article}} {{Medida}} {{Categoria}}
<htk-text lot="iter" name="Medida"/>
<htk-text lot="iter" name="Categoria"/>
</p> </p>
<p class="amount"> <p class="amount">
<htk-text lot="iter" name="amount"/> x {{amount}} x
<htk-text lot="iter" name="price" format="%.2d€"/> <htk-text lot="iter" name="price" format="%.2d€"/>
<span class="subtotal"> <span class="subtotal">
<htk-text id="subtotal" format="%.2d€"/> <htk-text id="subtotal" format="%.2d€"/>

View File

@ -33,14 +33,6 @@ Hedera.Orders = new Class
this.hash.setAll ({form: 'ecomerce/basket'}); this.hash.setAll ({form: 'ecomerce/basket'});
} }
,repeaterFunc: function (res, form)
{
res.$.link.href = this.hash.make ({
form: 'ecomerce/ticket',
ticket: form.get ('ticket_id')
});
}
// TPV // TPV
,balanceConditionalFunc: function (field, value) ,balanceConditionalFunc: function (field, value)

View File

@ -48,12 +48,14 @@
</div> </div>
</div> </div>
<div class="card list"> <div class="card list">
<htk-repeater form-id="iter" renderer="repeaterFunc"> <htk-repeater form-id="iter">
<db-model property="model" lot="params"> <db-model property="model" lot="params">
CALL clientTicketList (#from, NULL) CALL clientTicketList (#from, NULL)
</db-model> </db-model>
<custom> <custom>
<a id="link" class="list-row" title="_SeeOrder"> <a href="#!form=ecomerce/ticket&amp;ticket={{ticket_id}}"
class="list-row"
title="_SeeOrder">
<p class="important total"> <p class="important total">
<htk-text lot="iter" name="total" format="%.2d€"/> <htk-text lot="iter" name="total" format="%.2d€"/>
</p> </p>

View File

@ -31,11 +31,10 @@ Hedera.Ticket = new Class
,subtotal: function (form) ,subtotal: function (form)
{ {
var price = form.get ('price'); var row = form.$;
var discount = form.get ('discount');
if (price && form.get ('fixed')) if (row.price && row.fixed)
return form.get ('amount') * price * ((100 - discount) / 100); return row.amount * row.price * ((100 - row.discount) / 100);
else else
return null; return null;
} }

View File

@ -2,11 +2,9 @@
<vn-lot-query id="params"> <vn-lot-query id="params">
<vn-spec name="ticket" type="Number"/> <vn-spec name="ticket" type="Number"/>
</vn-lot-query> </vn-lot-query>
<db-form id="ticket"> <db-lot id="ticket" lot="params">
<db-model property="model" lot="params">
CALL clientTicketGet(#ticket) CALL clientTicketGet(#ticket)
</db-model> </db-lot>
</db-form>
<h1 id="title"> <h1 id="title">
_OrderDetail _OrderDetail
</h1> </h1>
@ -21,7 +19,7 @@
<div class="head"> <div class="head">
<div> <div>
<p class="important ticket-id"> <p class="important ticket-id">
@<htk-text name="id" lot="ticket"/> @{{ticket.id}}
</p> </p>
<p> <p>
<htk-text lot="ticket" name="delivery" format="%D"/> <htk-text lot="ticket" name="delivery" format="%D"/>
@ -29,18 +27,16 @@
</div> </div>
<div> <div>
<p> <p>
_Delivery <htk-text lot="ticket" name="Agencia"/> <t>Delivery</t> {{ticket.Agencia}}
</p> </p>
<p> <p>
<htk-text lot="ticket" name="consignee"/> {{ticket.consignee}}
</p> </p>
<p> <p>
<htk-text lot="ticket" name="name"/> {{ticket.name}}
</p> </p>
<p> <p>
<htk-text lot="ticket" name="zip_code"/> {{ticket.consignee}} {{ticket.city}} ({{ticket.province}})
<htk-text lot="ticket" name="city"/>
(<htk-text lot="ticket" name="province"/>)
</p> </p>
</div> </div>
<div> <div>
@ -54,15 +50,14 @@
</p> </p>
</div> </div>
</div> </div>
<htk-repeater form-id="iter" renderer="repeaterFunc"> <htk-repeater renderer="repeaterFunc">
<db-model property="model" id="movements" lot="params"> <db-model property="model" id="movements" lot="params">
CALL clientTicketRowGet(#ticket) CALL clientTicketRowGet(#ticket)
</db-model> </db-model>
<custom> <custom>
<div class="line"> <div class="line">
<htk-image <htk-image
lot="iter" value="{{Foto}}"
name="Foto"
class="photo" class="photo"
directory="catalog" directory="catalog"
subdir="200x200" subdir="200x200"

View File

@ -6,6 +6,7 @@ Db = module.exports = {
,Result : require ('./result') ,Result : require ('./result')
,ResultSet : require ('./result-set') ,ResultSet : require ('./result-set')
,Model : require ('./model') ,Model : require ('./model')
,Lot : require ('./lot')
,Query : require ('./query') ,Query : require ('./query')
,Calc : require ('./calc') ,Calc : require ('./calc')
,CalcSum : require ('./calc-sum') ,CalcSum : require ('./calc-sum')

84
js/db/lot.js Normal file
View File

@ -0,0 +1,84 @@
var Connection = require ('./connection');
var Model = require ('./model');
module.exports = new Class
({
Extends: Vn.Form
,Tag: 'db-lot'
,Properties:
{
/**
* The connection used to execute the statement.
*/
conn:
{
type: Connection
,set: function (x)
{
this.model.conn = x;
}
,get: function ()
{
return this.model.conn;
}
},
/**
* The model query.
*/
query:
{
type: String
,set: function (x)
{
this.model.query = x;
}
,get: function ()
{
return this.model.query;
}
},
/**
* The model select statement.
*/
stmt:
{
type: Sql.Stmt
,set: function (x)
{
this.model.stmt = x;
}
,get: function ()
{
return this.model.stmt;
}
},
/**
* The lot used to execute the statement.
*/
lot:
{
type: Vn.Lot
,set: function (x)
{
this.model.lot = x;
}
,get: function ()
{
return this.model.lot;
}
}
}
,initialize: function (props)
{
this.model = new Model ();
this.parent (props);
}
,appendChild: function (child)
{
if (child.nodeType === Node.TEXT_NODE)
this.query = child.textContent;
}
});

View File

@ -90,7 +90,7 @@ module.exports = new Class
,execute: function () ,execute: function ()
{ {
this._conn.execStmt (this._stmt, this._conn.execStmt (this._stmt,
this.onQueryDone.bind (this), this._batch); this.onQueryDone.bind (this), this._lot ? this._lot.$ : null);
} }
,onQueryDone: function (resultSet) ,onQueryDone: function (resultSet)
@ -100,7 +100,7 @@ module.exports = new Class
,onChange: function () ,onChange: function ()
{ {
if (this.autoLoad && this._conn && this._stmt && this._batch) if (this.autoLoad && this._conn && this._stmt && this._lot)
this.execute (); this.execute ();
} }
}); });

View File

@ -118,8 +118,12 @@ module.exports = new Class
case 'OutdatedVersion': case 'OutdatedVersion':
this._newVersion (); this._newVersion ();
break; break;
default: case 'User':
Htk.Toast.showError (error.message); Htk.Toast.showError (error.message);
break;
default:
Htk.Toast.showError (_('Something went wrong'));
console.error (error.message);
} }
else else
{ {
@ -160,10 +164,10 @@ module.exports = new Class
Htk.Toast.showError (_('Something went wrong')); Htk.Toast.showError (_('Something went wrong'));
var params = { var params = {
'file': error.fileName file: error.fileName
,'line': error.lineNumber ,line: error.lineNumber
,'message': error.message ,message: error.message
,'stack': error.stack ,stack: error.stack
}; };
this._conn.send ('core/log', params); this._conn.send ('core/log', params);
} }

View File

@ -37,11 +37,14 @@ module.exports = new Class
var builder = new Vn.Builder (); var builder = new Vn.Builder ();
builder.compileFile ('forms/'+ this.formInfo.path +'/ui.xml'); builder.compileFile ('forms/'+ this.formInfo.path +'/ui.xml');
var conn = this.conn;
var hash = this.hash;
var extraObjects = { var extraObjects = {
conn: this.conn, conn: conn,
hash: this.hash hash: hash
}; };
var scope = builder.load (this.doc, this, null, extraObjects, this.hash); var scope = builder.load (this.doc, this, null, extraObjects, hash);
this.scope = scope; this.scope = scope;
this.$ = scope.$; this.$ = scope.$;
this._node = this.$.main; this._node = this.$.main;
@ -50,21 +53,22 @@ module.exports = new Class
if (paramsLot) if (paramsLot)
{ {
paramsLot.source = this.hash; paramsLot.source = hash;
this.params = paramsLot; this.params = paramsLot;
} }
scope.link (); scope.link ();
var models = scope.getByTagName ('db-model'); function setConnection (tagName)
{
var objects = scope.getByTagName (tagName);
for (var i = 0; i < objects.length; i++)
objects[i].conn = conn;
}
for (var i = 0; i < models.length; i++) var tags = ['db-model', 'db-query', 'db-lot'];
models[i].conn = this.conn; for (var i = 0; i < tags.length; i++)
setConnection (tags[i]);
var queries = scope.getByTagName ('db-query');
for (var i = 0; i < queries.length; i++)
queries[i].conn = this.conn;
if (this.node) if (this.node)
{ {

View File

@ -57,27 +57,12 @@ module.exports = new Class
this.loadTemplateFromString (Tpl); this.loadTemplateFromString (Tpl);
this.loadingCount = 0; this.loadingCount = 0;
this.$.background.onclick = function () {};
this.$.menuButton.addEventListener ('click', function (event)
{
event.stopPropagation ();
this.showMenu ();
}.bind (this));
this.$.leftPanel.addEventListener ('click', function (event)
{
event.stopPropagation ();
});
this.parent (props); this.parent (props);
this.$.socialBar.conn = this._conn; this.$.socialBar.conn = this._conn;
this.$.user.conn = this._conn;
var sql = 'SELECT name FROM customer_user;' this.$.configQuery.conn = this._conn;
+'SELECT default_form, image_dir, image_host FROM config;' this.$.configQuery.execute ();
+'SELECT production_domain, test_domain FROM config;';
this._conn.execQuery (sql, this.onMainQueryDone.bind (this));
this.loadMenu (); this.loadMenu ();
} }
@ -150,13 +135,8 @@ module.exports = new Class
this.loaderPop (); this.loaderPop ();
} }
,onMainQueryDone: function (resultSet) ,onConfigQueryReady: function (query, resultSet)
{ {
// Retrieving the user name
var userName = resultSet.fetchValue ();
Vn.Node.setText (this.$.userName, userName);
// Retrieving configuration parameters // Retrieving configuration parameters
Object.assign (Vn.Config, resultSet.fetchObject ()); Object.assign (Vn.Config, resultSet.fetchObject ());
@ -178,8 +158,10 @@ module.exports = new Class
var linkField = 'test_domain'; var linkField = 'test_domain';
} }
Vn.Node.setText (this.$.testLink, _(linkText)); this.$.newVersion.assign ({
this.$.testLink.href = '//'+ row[linkField]; text: _(linkText),
link: '//'+ row[linkField]
});
} }
else else
Vn.Node.hide (this.$.testLink); Vn.Node.hide (this.$.testLink);
@ -298,6 +280,17 @@ module.exports = new Class
} }
} }
,onMenuButtonClick: function (event)
{
event.stopPropagation ();
this.showMenu ();
}
,onLeftPanelClick: function (event)
{
event.stopPropagation ();
}
,showMenu: function () ,showMenu: function ()
{ {
this.showBackground (); this.showBackground ();
@ -335,7 +328,7 @@ module.exports = new Class
if (!this._shown) if (!this._shown)
return; return;
var navbar = this.$.topBar; var navbar = this.$.navbar;
var yOffset = window.pageYOffset; var yOffset = window.pageYOffset;
var showNavbar = this._lastYOffset > yOffset || yOffset < navbar.offsetHeight; var showNavbar = this._lastYOffset > yOffset || yOffset < navbar.offsetHeight;
@ -357,6 +350,8 @@ module.exports = new Class
//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Background //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Background
,onBackgroundClick: function () {}
,showBackground: function () ,showBackground: function ()
{ {
Vn.Node.addClass (this.$.background, 'show'); Vn.Node.addClass (this.$.background, 'show');

View File

@ -1,14 +1,22 @@
<vn> <vn>
<vn-lot id="new-version"/>
<db-lot id="user">
SELECT name FROM customer_user
</db-lot>
<db-query id="config-query" on-ready="onConfigQueryReady">
SELECT default_form, image_dir, image_host FROM config;
SELECT production_domain, test_domain FROM config;
</db-query>
<div id="main" class="vn-gui"> <div id="main" class="vn-gui">
<div id="top-bar" class="navbar"> <div id="navbar" class="navbar">
<div id="action-bar" class="action-bar"/> <div id="action-bar" class="action-bar"/>
<button id="menu-button" class="menu-button"> <button class="menu-button" on-click="onMenuButtonClick">
<img src="image/icon/dark/menu.svg" alt="_Menu"/> <img src="image/icon/dark/menu.svg" alt="_Menu"/>
</button> </button>
<div id="title" class="title"/> <div id="title" class="title"/>
<htk-spinner id="loader" class="loader dark"/> <htk-spinner id="loader" class="loader dark"/>
</div> </div>
<div id="left-panel" class="left-panel"> <div id="left-panel" class="left-panel" on-click="onLeftPanelClick">
<div class="menu-overflow"> <div class="menu-overflow">
<div class="menu-header" id="menu-header"> <div class="menu-header" id="menu-header">
<img class="logo" src="image/logo-dark.svg" alt="Verdnatura"/> <img class="logo" src="image/logo-dark.svg" alt="Verdnatura"/>
@ -16,7 +24,7 @@
<button class="logout" on-click="onLogoutClick" title="_Exit"> <button class="logout" on-click="onLogoutClick" title="_Exit">
<img src="image/icon/dark/exit.svg" alt="_Exit"/> <img src="image/icon/dark/exit.svg" alt="_Exit"/>
</button> </button>
<p id="user-name"/> <p>{{user.name}}</p>
</div> </div>
<div id="supplant" class="supplant user-info"> <div id="supplant" class="supplant user-info">
<button class="logout" on-click="onSupplantExitClick" title="_Exit"> <button class="logout" on-click="onSupplantExitClick" title="_Exit">
@ -25,7 +33,9 @@
<p id="supplanted"/> <p id="supplanted"/>
</div> </div>
</div> </div>
<a id="test-link" class="test-link" href="#"/> <a id="test-link" class="test-link" href="{{newVersion.link}}">
{{newVersion.text}}
</a>
<ul id="main-menu" class="main-menu"/> <ul id="main-menu" class="main-menu"/>
</div> </div>
<div class="social"> <div class="social">
@ -35,6 +45,6 @@
<div class="body"> <div class="body">
<div id="form-holder" class="form-holder"/> <div id="form-holder" class="form-holder"/>
</div> </div>
<div id="background" class="background"/> <div id="background" class="background" on-click="onBackgroundClick"/>
</div> </div>
</vn> </vn>

View File

@ -3,7 +3,6 @@ module.exports = new Class
({ ({
Extends: Vn.Component Extends: Vn.Component
,Tag: 'htk-repeater' ,Tag: 'htk-repeater'
,Child: 'model'
,Properties: ,Properties:
{ {
/** /**
@ -119,7 +118,8 @@ module.exports = new Class
var extraObjects = {}; var extraObjects = {};
extraObjects[this._formId] = set; extraObjects[this._formId] = set;
var scope = this._builder.load (this.doc, null, this._parentScope, extraObjects, set); var scope = this._builder.load (
this.doc, null, this._parentScope, extraObjects, set);
scope.link (); scope.link ();
this._childsData.push ({ this._childsData.push ({

View File

@ -6,6 +6,7 @@ var kebabToCamel = require ('./string-util').kebabToCamel;
var CompilerObject = require ('./compiler-object'); var CompilerObject = require ('./compiler-object');
var CompilerElement = require ('./compiler-element'); var CompilerElement = require ('./compiler-element');
var CompilerText = require ('./compiler-text'); var CompilerText = require ('./compiler-text');
var CompilerInterpolable = require ('./compiler-interpolable');
var regCompilers = [ var regCompilers = [
CompilerObject, CompilerObject,
@ -103,6 +104,7 @@ module.exports = new Class
this._contexts = []; this._contexts = [];
this._contextMap = {}; this._contextMap = {};
this._mainContext = null; this._mainContext = null;
this._interpoler = new CompilerInterpolable (this);
var compilers = []; var compilers = [];
this._compilers = compilers; this._compilers = compilers;
@ -169,12 +171,12 @@ module.exports = new Class
* Creates a new scope from a compiled XML tree. * Creates a new scope from a compiled XML tree.
* *
* @param {Document} dstDocument The document used to create the nodes * @param {Document} dstDocument The document used to create the nodes
* @param {Object} signalData The object where to bind methods * @param {Object} thisArg The object where to bind methods
* @param {Scope} parentScope The parent scope or %null for no parent * @param {Scope} parentScope The parent scope or %null for no parent
* @param {Lot} lot The default lot * @param {Lot} lot The default lot
* @return {Scope} The created scope * @return {Scope} The created scope
*/ */
,load: function (dstDocument, signalData, parentScope, extraObjects, lot) ,load: function (dstDocument, thisArg, parentScope, extraObjects, lot)
{ {
if (this._contexts === null) if (this._contexts === null)
return null; return null;
@ -183,7 +185,7 @@ module.exports = new Class
var contexts = this._contexts; var contexts = this._contexts;
var len = contexts.length; var len = contexts.length;
var objects = new Array (len); var objects = new Array (len);
var scope = new Scope (this, objects, signalData, parentScope, lot) var scope = new Scope (this, objects, thisArg, parentScope, lot)
for (var i = 0; i < len; i++) for (var i = 0; i < len; i++)
{ {
@ -204,6 +206,8 @@ module.exports = new Class
var objects = scope.objects; var objects = scope.objects;
var compilers = this._compilers; var compilers = this._compilers;
this._interpoler.preLink (scope);
for (var i = 0; i < compilers.length; i++) for (var i = 0; i < compilers.length; i++)
compilers[i].preLink (scope); compilers[i].preLink (scope);
@ -219,10 +223,24 @@ module.exports = new Class
context.compiler.connect (context, objects[i], objects, scope); context.compiler.connect (context, objects[i], objects, scope);
} }
this._interpoler.postLink (scope);
for (var i = 0; i < compilers.length; i++) for (var i = 0; i < compilers.length; i++)
compilers[i].postLink (scope); compilers[i].postLink (scope);
} }
/**
* Frees all resources allocated by a scope.
*/
,freeScope: function (scope)
{
this._interpoler.free (scope);
var compilers = this._compilers;
for (var i = 0; i < compilers.length; i++)
compilers[i].free (scope);
}
/** /**
* Logs an error parsing the node. * Logs an error parsing the node.
* *

View File

@ -28,6 +28,14 @@ module.exports = new Class
var childs = []; var childs = [];
var events = {}; var events = {};
var context = {
tagName: tagName,
props: props,
objectProps: objectProps,
childs: childs,
events: events
};
var a = node.attributes; var a = node.attributes;
for (var i = 0; i < a.length; i++) for (var i = 0; i < a.length; i++)
@ -40,8 +48,13 @@ module.exports = new Class
else if (objectAttrs[attribute]) else if (objectAttrs[attribute])
objectProps[attribute] = kebabToCamel(value); objectProps[attribute] = kebabToCamel(value);
else if (!specialAttrs[attribute]) else if (!specialAttrs[attribute])
{
value = this.translateValue (value);
if (!this._interpoler.compile (context, attribute, value))
props[attribute] = this.translateValue (value); props[attribute] = this.translateValue (value);
} }
}
var childContext; var childContext;
var childNodes = node.childNodes; var childNodes = node.childNodes;
@ -51,13 +64,7 @@ module.exports = new Class
if (childContext = builder._compile (childNodes[i])) if (childContext = builder._compile (childNodes[i]))
childs.push (childContext.id); childs.push (childContext.id);
return { return context;
tagName: tagName,
props: props,
objectProps: objectProps,
childs: childs,
events: events
};
} }
,instantiate: function (doc, context, scope) ,instantiate: function (doc, context, scope)
@ -66,7 +73,7 @@ module.exports = new Class
var props = context.props; var props = context.props;
for (var prop in props) for (var prop in props)
object.setAttribute (prop, scope.interpolate (props[prop])); object.setAttribute (prop, props[prop]);
if (context.nodeId) if (context.nodeId)
object.setAttribute ('id', scope.getHtmlId (context.nodeId)); object.setAttribute ('id', scope.getHtmlId (context.nodeId));
@ -74,6 +81,11 @@ module.exports = new Class
return object; return object;
} }
,setProperty: function (object, data, value)
{
object.setAttribute (data, value);
}
,link: function (context, object, objects, scope) ,link: function (context, object, objects, scope)
{ {
var props = context.objectProps; var props = context.objectProps;

View File

@ -0,0 +1,144 @@
var VnObject = require ('./object');
var regex = /{{[\w_]+(\.[\w_]+)?}}/g;
/**
* Replaces all ocurrences of {{value}} by it's corresponding value in the
* scope lot.
*/
module.exports = new Class
({
Extends: VnObject
,_lots: {}
,_links: []
,initialize: function (builder)
{
this._builder = builder;
this.parent ();
}
,compile: function (objContext, data, string)
{
var matchs = string.match (regex);
if (!matchs)
return null;
var lots = this._lots;
var links = this._links;
var regLots = {};
var params = [];
var context = {
objContext: objContext,
data: data,
string: string,
params: params
};
for (var i = 0; i < matchs.length; i++)
{
var match = matchs[i];
match = matchs[i].substr (2, match.length - 4);
match = match.split ('.');
var lotId;
var name;
if (match.length > 1)
{
lotId = match[0];
name = match[1];
}
else
{
lotId = null;
name = match[0];
}
params.push ({
lotId: lotId,
name: name
});
if (regLots[lotId] === undefined)
{
if (!lots[lotId])
lots[lotId] = [];
lots[lotId].push (context);
regLots[lotId] = 1;
}
}
links.push (context);
return context;
}
,interpolate: function (link, scope)
{
var i = 0;
var params = link.params;
var $ = scope.$;
return link.string.replace (regex, function () {
var param = params[i++];
var lotId = param.lotId;
var lot = lotId ? $[lotId] : scope.lot;
var value = lot ? lot.$[param.name] : null;
return value != null ? value : '';
});
}
,preLink: function (scope)
{
this._link (this._links, scope);
}
,_link: function (links, scope)
{
for (var i = 0; i < links.length; i++)
{
var link = links[i];
var string = this.interpolate (link, scope);
var object = scope.objects[link.objContext.id];
link.objContext.compiler.setProperty (object, link.data, string);
}
}
,getLot: function (lotId, scope)
{
return lotId == 'null' ? scope.lot : scope.$[lotId];
}
,postLink: function (scope)
{
for (var lotId in this._lots)
{
var lot = this.getLot (lotId, scope);
if (lot)
lot.on ('change', this.onLotChange.bind (this, lotId, scope), scope);
}
}
,free: function (scope)
{
for (var lotId in this._lots)
{
var lot = this.getLot (lotId, scope);
if (lot)
lot.disconnectByInstance (scope);
}
}
,onLotChange: function (lotId, scope)
{
this._link (this._lots[lotId], scope);
}
});

View File

@ -1,4 +1,5 @@
var VnObject = require ('./object');
var Compiler = require ('./compiler'); var Compiler = require ('./compiler');
var Component = require ('./component'); var Component = require ('./component');
var Type = require ('./type'); var Type = require ('./type');
@ -115,6 +116,9 @@ module.exports = new Class
return; return;
} }
if (this._interpoler.compile (context, propName, value))
return;
switch (propInfo.type) switch (propInfo.type)
{ {
case null: case null:
@ -173,6 +177,11 @@ module.exports = new Class
return object; return object;
} }
,setProperty: function (object, data, value)
{
object[data] = value;
}
,preLink: function (scope) ,preLink: function (scope)
{ {
var objects = scope.objects; var objects = scope.objects;
@ -229,7 +238,23 @@ module.exports = new Class
var method = scope.getMethod (events[event]); var method = scope.getMethod (events[event]);
if (method) if (method)
object.on (event, method, scope.signalData); object.on (event, method, scope.thisArg);
}
}
,free: function (scope)
{
var objects = scope.objects;
for (var i = objects.length; i--;)
{
var object = objects[i];
if (object instanceof VnObject)
{
object.disconnectByInstance (scope.thisArg);
object.unref ();
}
} }
} }

View File

@ -28,11 +28,23 @@ module.exports = new Class
else else
return null; return null;
return {text: text}; var context = {text: null};
if (this._interpoler.compile (context, null, text))
context.text = '';
else
context.text = text;
return context;
} }
,instantiate: function (doc, context, scope) ,instantiate: function (doc, context, scope)
{ {
return doc.createTextNode (scope.interpolate (context.text)); return doc.createTextNode (context.text);
}
,setProperty: function (object, data, value)
{
object.textContent = value;
} }
}); });

View File

@ -15,10 +15,13 @@ module.exports = new Class
,link: function () {} ,link: function () {}
,connect: function () {} ,connect: function () {}
,postLink: function () {} ,postLink: function () {}
,setProperty: function () {}
,free: function () {}
,initialize: function (builder) ,initialize: function (builder)
{ {
this._builder = builder; this._builder = builder;
this._interpoler = builder._interpoler;
this.parent (); this.parent ();
} }

View File

@ -58,11 +58,12 @@ module.exports = new Class
} }
} }
,_model: null
,initialize: function (props) ,initialize: function (props)
{ {
Object.assign (this, { Object.assign (this, {
_model: null _row: -1
,_row: -1
,_rowLock: false ,_rowLock: false
}); });
this.parent (props); this.parent (props);

View File

@ -1,6 +1,6 @@
var VnObject = require ('./object'); var VnObject = require ('./object');
var JsonException = require ('./json-exception'); var JsonError = require ('./json-error');
/** /**
* Handler for JSON rest connections. * Handler for JSON rest connections.
@ -125,7 +125,7 @@ module.exports = new Class
*/ */
,supplantUser: function (user, callback) ,supplantUser: function (user, callback)
{ {
var params = {'supplantUser': user}; var params = {supplantUser: user};
this.send ('core/supplant', params, this.send ('core/supplant', params,
this._onUserSupplant.bind (this, callback)); this._onUserSupplant.bind (this, callback));
} }
@ -160,7 +160,7 @@ module.exports = new Class
if (!params) if (!params)
params = {}; params = {};
params['srv'] = 'json:'+ restService; params.srv = 'json:'+ restService;
this.sendWithUrl (params, callback, 'POST', '.'); this.sendWithUrl (params, callback, 'POST', '.');
} }
@ -213,7 +213,7 @@ module.exports = new Class
,sendWithUrl: function (params, callback, method, url) ,sendWithUrl: function (params, callback, method, url)
{ {
if (this.token) if (this.token)
params['token'] = this.token; params.token = this.token;
var request = new XMLHttpRequest (); var request = new XMLHttpRequest ();
request.open (method, url, true); request.open (method, url, true);
@ -255,7 +255,7 @@ module.exports = new Class
throw ex; throw ex;
} }
var contentType = null; var contentType;
try { try {
contentType = request contentType = request
@ -263,7 +263,9 @@ module.exports = new Class
.split (';')[0] .split (';')[0]
.trim (); .trim ();
} }
catch (e) {} catch (e) {
contentType = null;
}
if (contentType != 'application/json') if (contentType != 'application/json')
{ {
@ -291,7 +293,7 @@ module.exports = new Class
.replace (/Exception$/, '') .replace (/Exception$/, '')
.replace (/^Vn\.Web\./, ''); .replace (/^Vn\.Web\./, '');
var ex = new JsonException (); var ex = new JsonError ();
Object.assign (ex, { Object.assign (ex, {
exception: exception, exception: exception,
message: jsData.message, message: jsData.message,
@ -310,15 +312,15 @@ module.exports = new Class
} }
if (callback) if (callback)
// try { try {
callback (data, error); callback (data, error);
/* error = null; error = null;
} }
catch (e) catch (e)
{ {
error = e; error = e;
} }
*/
if (error) if (error)
{ {
if (error.exception == 'SessionExpired') if (error.exception == 'SessionExpired')

View File

@ -3,7 +3,9 @@
*/ */
module.exports = new Class module.exports = new Class
({ ({
exception: null Extends: Error
,exception: null
,message: null ,message: null
,code: null ,code: null
,file: null ,file: null
@ -12,6 +14,8 @@ module.exports = new Class
,initialize: function (exception, message, code, file, line, trace) ,initialize: function (exception, message, code, file, line, trace)
{ {
this.name = 'JsonError'
this.stack = (new Error ()).stack;
this.exception = exception; this.exception = exception;
this.message = message; this.message = message;
this.code = code; this.code = code;

View File

@ -23,7 +23,7 @@ module.exports = new Class
/* /*
* Signal handlers data. * Signal handlers data.
*/ */
,_signalData: null ,_thisArg: null
/** /**
* Initializes the object and sets all properties passed to the class * Initializes the object and sets all properties passed to the class
@ -100,10 +100,10 @@ module.exports = new Class
} }
this._signalInit (); this._signalInit ();
var callbacks = this._signalData.signals[id]; var callbacks = this._thisArg.signals[id];
if (!callbacks) if (!callbacks)
callbacks = this._signalData.signals[id] = []; callbacks = this._thisArg.signals[id] = [];
callbacks.push ({ callbacks.push ({
blocked: false blocked: false
@ -121,10 +121,10 @@ module.exports = new Class
*/ */
,blockSignal: function (id, callback, block, instance) ,blockSignal: function (id, callback, block, instance)
{ {
if (!this._signalData) if (!this._thisArg)
return; return;
var callbacks = this._signalData.signals[id]; var callbacks = this._thisArg.signals[id];
if (!callbacks) if (!callbacks)
return; return;
@ -142,10 +142,10 @@ module.exports = new Class
*/ */
,emit: function (id) ,emit: function (id)
{ {
if (!this._signalData) if (!this._thisArg)
return; return;
var callbacks = this._signalData.signals[id]; var callbacks = this._thisArg.signals[id];
if (!callbacks) if (!callbacks)
return; return;
@ -170,10 +170,10 @@ module.exports = new Class
*/ */
,disconnect: function (id, callback, instance) ,disconnect: function (id, callback, instance)
{ {
if (!this._signalData) if (!this._thisArg)
return; return;
var callbacks = this._signalData.signals[id]; var callbacks = this._thisArg.signals[id];
if (callbacks) if (callbacks)
for (var i = callbacks.length; i--;) for (var i = callbacks.length; i--;)
@ -189,10 +189,10 @@ module.exports = new Class
*/ */
,disconnectByInstance: function (instance) ,disconnectByInstance: function (instance)
{ {
if (!this._signalData) if (!this._thisArg)
return; return;
var signals = this._signalData.signals; var signals = this._thisArg.signals;
for (var signalId in signals) for (var signalId in signals)
{ {
@ -212,15 +212,15 @@ module.exports = new Class
*/ */
,_destroy: function () ,_destroy: function ()
{ {
if (!this._signalData) if (!this._thisArg)
return; return;
var links = this._signalData.links; var links = this._thisArg.links;
for (var key in links) for (var key in links)
this._unlink (links[key]); this._unlink (links[key]);
this._signalData = null; this._thisArg = null;
} }
/** /**
@ -232,7 +232,7 @@ module.exports = new Class
,link: function (prop, handlers) ,link: function (prop, handlers)
{ {
this._signalInit (); this._signalInit ();
var links = this._signalData.links; var links = this._thisArg.links;
for (var key in prop) for (var key in prop)
{ {
@ -264,8 +264,8 @@ module.exports = new Class
,_signalInit: function () ,_signalInit: function ()
{ {
if (!this._signalData) if (!this._thisArg)
this._signalData = { this._thisArg = {
signals: {}, signals: {},
links: {} links: {}
}; };

View File

@ -7,17 +7,17 @@ module.exports = new Class
({ ({
Extends: VnObject Extends: VnObject
,initialize: function (builder, objects, signalData, parentScope, lot) ,initialize: function (builder, objects, thisArg, parentScope, lot)
{ {
this.builder = builder; this.builder = builder;
this.objects = objects; this.objects = objects;
this.signalData = signalData; this.thisArg = thisArg;
this.parentScope = parentScope; this.parentScope = parentScope;
this.uid = ++scopeUid; this.uid = ++scopeUid;
this.lot = lot; this.lot = lot;
if (!signalData && parentScope) if (!thisArg && parentScope)
this.signalData = parentScope.signalData; this.thisArg = parentScope.thisArg;
this.parent (); this.parent ();
} }
@ -58,42 +58,14 @@ module.exports = new Class
this.builder.link (this); this.builder.link (this);
} }
/**
* Replaces all ocurrences of {{value}} by it's corresponding value in the
* scope lot.
*/
,interpolate: function (string)
{
var self = this;
function replaceFunc (token)
{
var key = token.substr (2, token.length - 4);
var value = self.getLotValue (key);
return value ? value : '';
}
return string.replace (/{{[\w_]+}}/g, replaceFunc);
}
,getLotValue: function (key)
{
var value = this.lot.$[key];
if (value === undefined && this.parentScope)
return this.parentScope.getLotValue (key);
return value;
}
,getMethod: function (value, binded) ,getMethod: function (value, binded)
{ {
if (this.signalData) if (this.thisArg)
{ {
var method = this.signalData[value]; var method = this.thisArg[value];
if (method && binded) if (method && binded)
method = method.bind (this.signalData); method = method.bind (this.thisArg);
} }
else else
var method = window[value]; var method = window[value];
@ -111,19 +83,7 @@ module.exports = new Class
,_destroy: function () ,_destroy: function ()
{ {
var objects = this.objects; this.builder.freeScope (this);
for (var i = objects.length; i--;)
{
var object = objects[i];
if (object instanceof VnObject)
{
object.unref ();
object.disconnectByInstance (this.builder.signalData);
}
}
this.parent (); this.parent ();
} }
}); });

View File

@ -31,7 +31,7 @@ Vn = module.exports = {
,NodeBuilder : require ('./node-builder') ,NodeBuilder : require ('./node-builder')
,Builder : require ('./builder') ,Builder : require ('./builder')
,Component : require ('./component') ,Component : require ('./component')
,JsonException : require ('./json-exception') ,JsonException : require ('./json-error')
,JsonConnection : require ('./json-connection') ,JsonConnection : require ('./json-connection')
,Config: {} ,Config: {}