Builder refactor, various fixes
gitea/hedera-web/pipeline/head This commit looks good
Details
gitea/hedera-web/pipeline/head This commit looks good
Details
This commit is contained in:
parent
d1819118d8
commit
fd6f39371a
|
@ -1,4 +1,4 @@
|
|||
hedera-web (1.407.79) stable; urgency=low
|
||||
hedera-web (1.407.80) stable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<htk-button
|
||||
icon="delete"
|
||||
tip="_RemoveAddress"
|
||||
on-click="this.onRemoveAddressClick($.address)"/>
|
||||
on-click="this.onRemoveAddressClick($iter)"/>
|
||||
<htk-button
|
||||
icon="edit"
|
||||
tip="_EditAddress"
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<htk-bar-button
|
||||
icon="check"
|
||||
tip="_Accept"
|
||||
on-click="$.iter.performOperations()"/>
|
||||
on-click="iter.performOperations()"/>
|
||||
</div>
|
||||
<div id="form" class="address">
|
||||
<div class="form box vn-w-sm vn-pa-lg">
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
<vn>
|
||||
<vn-group>
|
||||
<db-form id="password-form">
|
||||
<db-form v-model="passwordForm">
|
||||
<db-model property="model">
|
||||
<custom>
|
||||
SELECT length, nAlpha, nUpper, nDigits, nPunct
|
||||
FROM account.userPassword
|
||||
</custom>
|
||||
</db-model>
|
||||
</db-form>
|
||||
<db-form id="user-form">
|
||||
<db-model property="model" id="user-model" updatable="true">
|
||||
<custom>
|
||||
SELECT u.id, u.name, u.email, u.nickname,
|
||||
u.lang, c.isToBeMailed, c.id clientFk
|
||||
FROM account.myUser u
|
||||
LEFT JOIN myClient c
|
||||
ON u.id = c.id
|
||||
</custom>
|
||||
</db-model>
|
||||
</db-form>
|
||||
</vn-group>
|
||||
|
@ -27,7 +23,7 @@
|
|||
<htk-bar-button
|
||||
icon="place"
|
||||
tip="_Addresses"
|
||||
on-click="$.hash.setAll({form: 'account/address-list'})"/>
|
||||
on-click="hash.setAll({form: 'account/address-list'})"/>
|
||||
<htk-bar-button
|
||||
icon="lock_reset"
|
||||
tip="_Change password"
|
||||
|
@ -119,24 +115,19 @@
|
|||
</h5>
|
||||
<ul>
|
||||
<li>
|
||||
<htk-text form="password-form" column="length"/>
|
||||
<t>characters long</t>
|
||||
{{passwordForm.length}} <t>characters long</t>
|
||||
</li>
|
||||
<li>
|
||||
<htk-text form="password-form" column="nAlpha"/>
|
||||
<t>alphabetic characters</t>
|
||||
{{passwordForm.nAlpha}} <t>alphabetic characters</t>
|
||||
</li>
|
||||
<li>
|
||||
<htk-text form="password-form" column="nUpper"/>
|
||||
<t>capital letters</t>
|
||||
{{passwordForm.nUpper}} <t>capital letters</t>
|
||||
</li>
|
||||
<li>
|
||||
<htk-text form="password-form" column="nDigits"/>
|
||||
<t>digits</t>
|
||||
{{passwordForm.nDigits}} <t>digits</t>
|
||||
</li>
|
||||
<li>
|
||||
<htk-text form="password-form" column="nPunct"/>
|
||||
<t>symbols</t>
|
||||
{{passwordForm.nPunct}} <t>symbols</t>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<vn>
|
||||
<vn-group>
|
||||
<db-form id="user">
|
||||
<db-form v-model="user">
|
||||
<db-model property="model" lot="hash">
|
||||
SELECT u.id, u.name user, u.nickname, u.email, c.phone, r.name role
|
||||
FROM account.user u
|
||||
|
@ -16,11 +16,11 @@
|
|||
<div id="form" class="access-log">
|
||||
<div class="box vn-w-xs vn-pa-lg">
|
||||
<div class="form">
|
||||
<h4><htk-text form="user" column="nickname"/></h4>
|
||||
<p>#<htk-text form="user" column="id"/> - <htk-text form="user" column="user"/></p>
|
||||
<p><htk-text form="user" column="role"/></p>
|
||||
<p><htk-text form="user" column="email"/></p>
|
||||
<p><htk-text form="user" column="phone"/></p>
|
||||
<h4>{{user.nickname}}</h4>
|
||||
<p>#{{user.id}} - {{user.user}}</p>
|
||||
<p>{{user.role}}</p>
|
||||
<p>{{user.email}}</p>
|
||||
<p>{{user.phone}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<htk-repeater form-id="iter" class="box vn-w-xs htk-list vn-mt-md">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<htk-bar-button
|
||||
icon="refresh"
|
||||
tip="_Refresh"
|
||||
on-click="$.sessions.refresh()"/>
|
||||
on-click="sessions.refresh()"/>
|
||||
<div class="connections-sum">
|
||||
<htk-text>
|
||||
<db-calc-sum
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<div class="item">
|
||||
<div class="side vn-mr-md">
|
||||
<htk-image
|
||||
form="iter"
|
||||
form="$iter"
|
||||
column="image"
|
||||
stamp-column="updated"
|
||||
class="photo"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<htk-bar-button
|
||||
icon="refresh"
|
||||
tip="_Refresh"
|
||||
on-click="$.visits.refresh()"/>
|
||||
on-click="visits.refresh()"/>
|
||||
<htk-bar-button
|
||||
icon="visibility"
|
||||
tip="_Connections"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
class="start-order"
|
||||
icon="add_shopping_cart"
|
||||
tip="_Start order"
|
||||
on-click="$.hash.setAll({form: 'ecomerce/catalog'})"/>
|
||||
on-click="hash.setAll({form: 'ecomerce/catalog'})"/>
|
||||
</div>
|
||||
<div id="form" class="home">
|
||||
<div class="column mansonry" id="news-column">
|
||||
|
|
|
@ -44,19 +44,16 @@
|
|||
class="delete"
|
||||
tip="_Remove"
|
||||
icon="delete"
|
||||
on-click="this.onDeleteClick($.iter)"/>
|
||||
on-click="this.onDeleteClick($iter)"/>
|
||||
<htk-image
|
||||
form="iter"
|
||||
column="image"
|
||||
value="{{iter.image}}"
|
||||
stamp-column="updated"
|
||||
class="photo"
|
||||
directory="catalog"
|
||||
subdir="200x200"
|
||||
full-dir="1600x900"/>
|
||||
<div class="info">
|
||||
<h2>
|
||||
<htk-text form="iter" column="item"/>
|
||||
</h2>
|
||||
<h2>{{iter.item}}</h2>
|
||||
<p class="tags">
|
||||
{{iter.value5}} {{iter.value6}} {{iter.value7}}
|
||||
</p>
|
||||
|
|
|
@ -169,13 +169,6 @@ Hedera.Catalog = new Class({
|
|||
Hedera.Catalog.View.GRID : Hedera.Catalog.View.LIST);
|
||||
}
|
||||
|
||||
,onBasketReady: function(form) {
|
||||
if (form.$.method != 'PICKUP')
|
||||
Vn.Node.setText(this.$.method, _('Agency'));
|
||||
else
|
||||
Vn.Node.setText(this.$.method, _('Warehouse'));
|
||||
}
|
||||
|
||||
,onItemsChange: function(model, status) {
|
||||
if (status !== Db.Model.Status.CLEAN)
|
||||
this.$.order.style.display = 'block';
|
||||
|
@ -255,7 +248,7 @@ Hedera.Catalog = new Class({
|
|||
if (this.isGuest()) return;
|
||||
|
||||
this.onEraseClick();
|
||||
this.$.card.row = form.row;
|
||||
this.$.$card.row = form.row;
|
||||
this.$.cardLot.assign({item: form.$.id});
|
||||
this.$.cardPopup.show(event.currentTarget);
|
||||
}
|
||||
|
@ -303,7 +296,7 @@ Hedera.Catalog = new Class({
|
|||
if (amountSum > 0) {
|
||||
this.conn.execQuery(sql);
|
||||
|
||||
var itemName = this.$.card.get('item');
|
||||
var itemName = this.$.$card.get('item');
|
||||
Htk.Toast.showMessage(
|
||||
Vn.Value.sprintf(_('Added%dOf%s'), amountSum, itemName));
|
||||
}
|
||||
|
@ -318,7 +311,7 @@ Hedera.Catalog = new Class({
|
|||
|
||||
,onPopupClose: function() {
|
||||
this.onEraseClick();
|
||||
this.$.card.row = -1;
|
||||
this.$.$card.row = -1;
|
||||
this.$.cardLot.value = undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
param="producer"/>
|
||||
</vn-group>
|
||||
<vn-group>
|
||||
<db-form id="basket" on-ready="onBasketReady">
|
||||
<db-form v-model="basket">
|
||||
<db-model property="model">
|
||||
SELECT b.id, b.sent, a.description agency, m.code method
|
||||
FROM myBasket b
|
||||
|
@ -108,7 +108,7 @@
|
|||
JOIN vn.itemType t ON t.id = i.typeFk
|
||||
WHERE #filter;
|
||||
CALL myBasket_calcCatalogFull;
|
||||
SELECT i.id, i.description, i.longName item, i.subName,
|
||||
SELECT i.id, i.longName item, i.subName,
|
||||
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
|
||||
i.relevancy, i.size, i.category,
|
||||
k.name ink, p.name producer, o.name origin,
|
||||
|
@ -126,7 +126,7 @@
|
|||
ORDER BY i.relevancy DESC, i.name, i.size
|
||||
LIMIT 5000;
|
||||
</db-model>
|
||||
<db-form id="card" model="items"/>
|
||||
<db-form id="$card" v-model="card" model="items"/>
|
||||
<vn-lot id="card-lot"/>
|
||||
</vn-group>
|
||||
<div id="form" class="catalog">
|
||||
|
@ -135,17 +135,17 @@
|
|||
id="grid-view"
|
||||
empty-message="_Choose filter from right menu"
|
||||
form-id="item"
|
||||
model="items" >
|
||||
model="items">
|
||||
<custom>
|
||||
<div
|
||||
id="item-box"
|
||||
class="item-box clickable"
|
||||
title="{{_('AddToBasket')}}"
|
||||
on-click="this.onAddItemClick($event, $.item)">
|
||||
on-click="this.onAddItemClick($event, $iter)">
|
||||
<htk-image
|
||||
directory="catalog"
|
||||
subdir="200x200"
|
||||
form="item"
|
||||
form="$iter"
|
||||
column="image"
|
||||
stamp-column="updated"
|
||||
full-dir="1600x900"
|
||||
|
@ -193,12 +193,10 @@
|
|||
</div>
|
||||
<div id="right-panel" class="right-panel" on-click="onRightPanelClick">
|
||||
<div class="basket-info">
|
||||
<p>{{Vn.Value.format(basket.sent, '%D')}}</p>
|
||||
<p>
|
||||
<htk-text form="basket" column="sent" format="%D"/>
|
||||
</p>
|
||||
<p>
|
||||
<span id="method"/>
|
||||
<htk-text form="basket" column="agency"/>
|
||||
{{_(basket.method != 'PICKUP' ? 'Agency' : 'Warehouse')}}
|
||||
{{basket.agency}}
|
||||
</p>
|
||||
<button class="thin" on-click="this.onConfigureClick()">
|
||||
<t>Modify</t>
|
||||
|
@ -266,7 +264,7 @@
|
|||
placeholder="_Color"
|
||||
form="params"
|
||||
column="color"
|
||||
on-mousedown="$.colors.lazyRefresh()">
|
||||
on-mousedown="colors.lazyRefresh()">
|
||||
<db-model
|
||||
id="colors"
|
||||
property="model"
|
||||
|
@ -286,7 +284,7 @@
|
|||
placeholder="_Producer"
|
||||
form="params"
|
||||
column="producer"
|
||||
on-mousedown="$.producers.lazyRefresh()">
|
||||
on-mousedown="producers.lazyRefresh()">
|
||||
<db-model
|
||||
id="producers"
|
||||
property="model"
|
||||
|
@ -306,7 +304,7 @@
|
|||
placeholder="_Origin"
|
||||
form="params"
|
||||
column="origin"
|
||||
on-mousedown="$.origins.lazyRefresh()">
|
||||
on-mousedown="origins.lazyRefresh()">
|
||||
<db-model
|
||||
id="origins"
|
||||
property="model"
|
||||
|
@ -327,7 +325,7 @@
|
|||
placeholder="_Category"
|
||||
form="params"
|
||||
column="category"
|
||||
on-mousedown="$.categorys.lazyRefresh()">
|
||||
on-mousedown="categorys.lazyRefresh()">
|
||||
<db-model
|
||||
id="categorys"
|
||||
property="model"
|
||||
|
@ -395,7 +393,7 @@
|
|||
modal="true"
|
||||
on-closed="onPopupClose">
|
||||
<div property="child-node" class="item-card">
|
||||
<db-form id="card-extend">
|
||||
<db-form vModel="extendedCard">
|
||||
<db-model
|
||||
property="model"
|
||||
lot="card-lot"
|
||||
|
@ -410,29 +408,19 @@
|
|||
<htk-image
|
||||
directory="catalog"
|
||||
subdir="200x200"
|
||||
form="card"
|
||||
form="$card"
|
||||
column="image"
|
||||
stamp-column="updated"
|
||||
full-dir="1600x900"
|
||||
conn="conn"
|
||||
editable="true"/>
|
||||
<div class="item-info">
|
||||
<h2>
|
||||
<htk-text form="card" column="item"/>
|
||||
</h2>
|
||||
<p class="sub-name">
|
||||
<htk-text form="card" column="subName"/>
|
||||
</p>
|
||||
<p>
|
||||
#<htk-text form="card" column="id"/>
|
||||
</p>
|
||||
<p>
|
||||
<htk-text form="card" column="stems" format="_%.0d Units"/>
|
||||
</p>
|
||||
<h2>{{card.item}}</h2>
|
||||
<p class="sub-name">{{card.subname}}</p>
|
||||
<p>#{{card.id}}</p>
|
||||
<p>{{Vn.Value.format(card.stems, _('%.0d Units'))}}</p>
|
||||
</div>
|
||||
<p class="desc">
|
||||
<htk-text form="card-extend" column="description" id="desc"/>
|
||||
</p>
|
||||
<p class="desc">{{extendedCard.description}}</p>
|
||||
<htk-repeater show-status="false" form-id="tag" class="tags">
|
||||
<db-model
|
||||
property="model"
|
||||
|
@ -448,8 +436,8 @@
|
|||
</db-model>
|
||||
<custom>
|
||||
<tr>
|
||||
<td><htk-text form="tag" column="name"/></td>
|
||||
<td><htk-text form="tag" column="value"/></td>
|
||||
<td>{{tag.name}}</td>
|
||||
<td>{{tag.value}}</td>
|
||||
</tr>
|
||||
</custom>
|
||||
</htk-repeater>
|
||||
|
|
|
@ -14,9 +14,7 @@
|
|||
column="debt">
|
||||
<db-form property="form">
|
||||
<db-model property="model">
|
||||
<custom>
|
||||
SELECT -myClient_getDebt(NULL) debt
|
||||
</custom>
|
||||
</db-model>
|
||||
</db-form>
|
||||
</htk-text>
|
||||
|
@ -42,9 +40,7 @@
|
|||
form-id="iter"
|
||||
renderer="repeaterFunc">
|
||||
<db-model property="model" id="tickets">
|
||||
<custom>
|
||||
CALL myTicket_list (NULL, NULL);
|
||||
</custom>
|
||||
CALL myTicket_list(NULL, NULL);
|
||||
</db-model>
|
||||
<custom>
|
||||
<a id="link" class="item" title="{{_('SeeOrder')}}">
|
||||
|
|
|
@ -10,13 +10,6 @@ Hedera.Ticket = new Class({
|
|||
this.conn.execQuery('CALL myTicket_logAccess(#ticket)', null, params);
|
||||
},
|
||||
|
||||
onTicketReady: function(form) {
|
||||
if (form.$.method != 'PICKUP')
|
||||
Vn.Node.setText(this.$.method, _('Agency'));
|
||||
else
|
||||
Vn.Node.setText(this.$.method, _('Warehouse'));
|
||||
},
|
||||
|
||||
onPrintClick: function() {
|
||||
let params = Vn.Url.makeUri({
|
||||
authorization: this.conn.token,
|
||||
|
@ -27,24 +20,17 @@ Hedera.Ticket = new Class({
|
|||
window.open(`/api/report/delivery-note?${params}`);
|
||||
},
|
||||
|
||||
repeaterFunc: function(res, form) {
|
||||
var discount = res.$.discount;
|
||||
discount.style.display = form.$.discount ? 'inline' : 'none';
|
||||
res.$.discountSubtotal.value = this.discountSubtotal(form);
|
||||
res.$.subtotal.value = this.subtotal(form);
|
||||
repeaterFunc: function(scope, form) {
|
||||
scope.$.discount.style.display = form.$.discount ? 'inline' : 'none';
|
||||
},
|
||||
|
||||
discountSubtotal: function(form) {
|
||||
return form.$.quantity * form.$.price;
|
||||
discountSubtotal: function(line) {
|
||||
return line.quantity * line.price;
|
||||
},
|
||||
|
||||
subtotal: function(form) {
|
||||
var discount = form.$.discount;
|
||||
return this.discountSubtotal(form) * ((100 - discount) / 100);
|
||||
},
|
||||
|
||||
servicesFunc: function(res, form) {
|
||||
res.$.subtotal.value = form.$.quantity * form.$.price;
|
||||
subtotal: function(line) {
|
||||
var discount = line.discount;
|
||||
return this.discountSubtotal(line) * ((100 - discount) / 100);
|
||||
},
|
||||
|
||||
onServicesChanged: function(model) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<vn-lot-query id="params">
|
||||
<vn-spec name="ticket" type="Number"/>
|
||||
</vn-lot-query>
|
||||
<db-lot id="ticket" lot="params" on-ready="onTicketReady">
|
||||
<db-lot id="ticket-form" lot="params" v-model="ticket">
|
||||
CALL myTicket_get(#ticket)
|
||||
</db-lot>
|
||||
<div id="title">
|
||||
|
@ -16,42 +16,32 @@
|
|||
</div>
|
||||
<div id="form" class="ticket">
|
||||
<div class="box vn-w-sm vn-pa-lg">
|
||||
<htk-loader class="head" form="ticket">
|
||||
<h5>#<htk-text column="id" form="ticket"/></h5>
|
||||
<htk-loader class="head" form="ticket-form">
|
||||
<h5>#{{ticket.id}}</h5>
|
||||
<div>
|
||||
<h6><t>ShippingInformation</t></h6>
|
||||
<p>
|
||||
<t>Preparation</t> <htk-text form="ticket" column="shipped" format="%D"/>
|
||||
<t>Preparation</t> {{Vn.Value.format(ticket.shipped, '%D')}}
|
||||
</p>
|
||||
<p>
|
||||
<t>Delivery</t> <htk-text form="ticket" column="landed" format="%D"/>
|
||||
<t>Delivery</t> {{Vn.Value.format(ticket.landed, '%D')}}
|
||||
</p>
|
||||
<p>
|
||||
<span id="method"></span> <htk-text form="ticket" column="agency"/>
|
||||
{{_(ticket.method != 'PICKUP' ? 'Agency' : 'Warehouse')}} {{ticket.agency}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="address">
|
||||
<h6><t>DeliveryAddress</t></h6>
|
||||
<p>
|
||||
<htk-text form="ticket" column="nickname"/>
|
||||
</p>
|
||||
<p>
|
||||
<htk-text form="ticket" column="street"/>
|
||||
</p>
|
||||
<p>
|
||||
<htk-text form="ticket" column="postalCode"/>
|
||||
<htk-text form="ticket" column="city"/>
|
||||
(<htk-text form="ticket" column="province"/>)
|
||||
</p>
|
||||
<p>{{ticket.nickname}}</p>
|
||||
<p>{{ticket.street}}</p>
|
||||
<p>{{ticket.postalCode}} {{ticket.city}} ({{ticket.province}})</p>
|
||||
</div>
|
||||
<div class="total">
|
||||
<p class="important total">
|
||||
<t>Total</t>
|
||||
<htk-text format="%.2d€" form="ticket" column="taxBase"/>
|
||||
<t>Total</t> {{Vn.Value.format(ticket.taxBase, '%.2d€')}}
|
||||
</p>
|
||||
<p class="important total">
|
||||
<t>Total + tax</t>
|
||||
<htk-text format="%.2d€" form="ticket" column="total"/>
|
||||
<t>Total + tax</t> {{Vn.Value.format(ticket.total, '%.2d€')}}
|
||||
</p>
|
||||
</div>
|
||||
</htk-loader>
|
||||
|
@ -65,38 +55,32 @@
|
|||
<custom>
|
||||
<div class="line">
|
||||
<htk-image
|
||||
form="iter"
|
||||
column="image"
|
||||
value="{{iter.image}}"
|
||||
stamp-column="updated"
|
||||
class="photo"
|
||||
directory="catalog"
|
||||
subdir="200x200"
|
||||
full-dir="1600x900"/>
|
||||
<div class="info">
|
||||
<h2>
|
||||
<htk-text form="iter" column="concept"/>
|
||||
</h2>
|
||||
<h2>{{iter.concept}}</h2>
|
||||
<p class="tags">
|
||||
<htk-text form="iter" column="value5"/>
|
||||
<htk-text form="iter" column="value6"/>
|
||||
<htk-text form="iter" column="value7"/>
|
||||
{{iter.value5}} {{iter.value6}} {{iter.value7}}
|
||||
</p>
|
||||
<p class="amount">
|
||||
<htk-text form="iter" column="quantity"/> x
|
||||
<htk-text form="iter" column="price" format="%.2d€"/>
|
||||
{{iter.quantity}} x {{Vn.Value.format(iter.price, '%.2d€')}}
|
||||
</p>
|
||||
<p class="subtotal">
|
||||
<span class="discount" id="discount">
|
||||
<htk-text id="discount-subtotal" format="%.2d€"/> -
|
||||
<htk-text form="iter" column="discount" format="%.0d%"/> =
|
||||
{{Vn.Value.format(this.discountSubtotal(iter), '%.2d€')}} -
|
||||
{{Vn.Value.format(iter.discount, '%.0d%')}} =
|
||||
</span>
|
||||
<htk-text id="subtotal" format="%.2d€"/>
|
||||
{{Vn.Value.format(this.subtotal(iter), '%.2d€')}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</custom>
|
||||
</htk-repeater>
|
||||
<htk-repeater form-id="iter" id="services" class="packages" renderer="servicesFunc">
|
||||
<htk-repeater form-id="iter" id="services" class="packages">
|
||||
<db-model
|
||||
property="model"
|
||||
on-status-changed="onServicesChanged"
|
||||
|
@ -106,15 +90,12 @@
|
|||
<custom>
|
||||
<div class="line">
|
||||
<div class="info">
|
||||
<h2>
|
||||
<htk-text form="iter" column="description"/>
|
||||
</h2>
|
||||
<h2>{{iter.description}}</h2>
|
||||
<p class="amount">
|
||||
<htk-text form="iter" column="quantity"/> x
|
||||
<htk-text form="iter" column="price" format="%.2d€"/>
|
||||
{{iter.quantity}} x {{Vn.Value.format(iter.price, '%.2d€')}}
|
||||
</p>
|
||||
<p class="subtotal">
|
||||
<htk-text id="subtotal" format="%.2d€"/>
|
||||
{{Vn.Value.format(iter.quantity * iter.price, '%.2d€')}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="clear"/>
|
||||
|
@ -131,22 +112,15 @@
|
|||
<custom>
|
||||
<div class="line">
|
||||
<htk-image
|
||||
form="iter"
|
||||
column="image"
|
||||
value="{{iter.image}}"
|
||||
class="photo"
|
||||
directory="catalog"
|
||||
subdir="200x200"
|
||||
full-dir="1600x900"/>
|
||||
<div class="info">
|
||||
<h2>
|
||||
<htk-text form="iter" column="name"/>
|
||||
</h2>
|
||||
<p>
|
||||
#<htk-text form="iter" column="id"/>
|
||||
</p>
|
||||
<p class="amount">
|
||||
<htk-text form="iter" column="quantity"/>
|
||||
</p>
|
||||
<h2>{{iter.name}}</h2>
|
||||
<p>#{{iter.id}}</p>
|
||||
<p class="amount">{{iter.quantity}}</p>
|
||||
</div>
|
||||
<div class="clear"/>
|
||||
</div>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
title="_EditNew">
|
||||
<div class="side vn-mr-md">
|
||||
<htk-image
|
||||
form="iter"
|
||||
form="$iter"
|
||||
column="image"
|
||||
class="photo"
|
||||
directory="news"
|
||||
|
@ -46,7 +46,7 @@
|
|||
<htk-button
|
||||
tip="_Remove"
|
||||
icon="delete"
|
||||
on-click="this.onDeleteClick($.iter)"/>
|
||||
on-click="this.onDeleteClick($iter)"/>
|
||||
</div>
|
||||
</a>
|
||||
</custom>
|
||||
|
|
|
@ -844,6 +844,7 @@ Model.implement({
|
|||
|
||||
if (!(op.type & Operation.DELETE
|
||||
&& op.type & Operation.INSERT))
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
isOperation = true;
|
||||
|
||||
if (op.type & Operation.DELETE) {
|
||||
|
|
|
@ -20,11 +20,11 @@ module.exports = new Class({
|
|||
const hash = this.hash;
|
||||
|
||||
const builder = new Vn.Builder();
|
||||
builder.compileFile('forms/'+ this.formInfo.path +'/ui.xml');
|
||||
builder.compileFile(`forms/${this.formInfo.path}/ui.xml`);
|
||||
|
||||
const scope = this.builder = builder.load(null, this);
|
||||
this.$ = scope.$;
|
||||
scope.link(null, {conn, hash});
|
||||
scope.link({conn, hash});
|
||||
this.node = scope.$.form;
|
||||
|
||||
const paramsLot = this.$.params;
|
||||
|
|
|
@ -69,7 +69,7 @@ module.exports = new Class({
|
|||
builder.compileFile('reports/'+ this.info.path +'/ui.xml');
|
||||
|
||||
var scope = this.scope = builder.load(this.doc, this);
|
||||
scope.link(null, {
|
||||
scope.link({
|
||||
lot: this.lot,
|
||||
conn: this.conn
|
||||
});
|
||||
|
|
|
@ -12,6 +12,8 @@ td.cell-button {
|
|||
width: 44px;
|
||||
margin: 0 auto;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
padding: 10px;
|
||||
background-color: transparent;
|
||||
box-sizing: border-box;
|
||||
|
||||
|
|
|
@ -5,13 +5,11 @@ module.exports = new Class({
|
|||
Extends: Component
|
||||
,Tag: 'htk-repeater'
|
||||
,Child: 'model'
|
||||
,Properties:
|
||||
{
|
||||
,Properties: {
|
||||
/**
|
||||
* The source data model.
|
||||
*/
|
||||
model:
|
||||
{
|
||||
model: {
|
||||
type: Db.Model
|
||||
,set: function(x) {
|
||||
this.link({_model: x}, {
|
||||
|
@ -30,8 +28,7 @@ module.exports = new Class({
|
|||
/**
|
||||
* The identifier for internal iterator.
|
||||
*/
|
||||
,formId:
|
||||
{
|
||||
,formId: {
|
||||
type: String
|
||||
,set: function(x) {
|
||||
this._formId = x;
|
||||
|
@ -44,8 +41,7 @@ module.exports = new Class({
|
|||
* {Function (Vn.BuilderResult, Db.Form)} Function to call after every
|
||||
* box rendering.
|
||||
*/
|
||||
,renderer:
|
||||
{
|
||||
,renderer: {
|
||||
type: Function
|
||||
,set: function(x) {
|
||||
this._renderer = x;
|
||||
|
@ -57,8 +53,7 @@ module.exports = new Class({
|
|||
/**
|
||||
* Wether to show the model status.
|
||||
*/
|
||||
,showStatus:
|
||||
{
|
||||
,showStatus: {
|
||||
type: Boolean
|
||||
,set: function(x) {
|
||||
this._showStatus = x;
|
||||
|
@ -71,8 +66,7 @@ module.exports = new Class({
|
|||
/**
|
||||
* Message that should be displayed when source model is not ready.
|
||||
*/
|
||||
,emptyMessage:
|
||||
{
|
||||
,emptyMessage: {
|
||||
type: String
|
||||
,value: null
|
||||
}
|
||||
|
@ -105,7 +99,7 @@ module.exports = new Class({
|
|||
}
|
||||
|
||||
,getBuilder: function(index) {
|
||||
return this._childsData[index].builder;
|
||||
return this._childsData[index].scope;
|
||||
}
|
||||
|
||||
,getForm: function(index) {
|
||||
|
@ -119,14 +113,12 @@ module.exports = new Class({
|
|||
});
|
||||
|
||||
var scope = this._builder.load(this.doc, null, this._parentScope);
|
||||
scope.link([set.getObject()], {
|
||||
[this._formId]: set
|
||||
scope.link({
|
||||
$iter: set,
|
||||
[this._formId]: set.getObject()
|
||||
});
|
||||
|
||||
this._childsData.push({
|
||||
builder: scope,
|
||||
set: set
|
||||
});
|
||||
this._childsData.push({scope, set});
|
||||
|
||||
if (this._renderer)
|
||||
this._renderer(scope, set);
|
||||
|
@ -228,7 +220,7 @@ module.exports = new Class({
|
|||
,_unrefChildData: function(index) {
|
||||
var childData = this._childsData[index];
|
||||
childData.set.unref();
|
||||
childData.builder.unref();
|
||||
childData.scope.unref();
|
||||
}
|
||||
|
||||
,destroy: function() {
|
||||
|
|
595
js/vn/builder.js
595
js/vn/builder.js
|
@ -1,16 +1,22 @@
|
|||
const VnObject = require('./object');
|
||||
const Component = require('./component');
|
||||
const VnNode = require('./node');
|
||||
const Scope = require('./scope');
|
||||
const Type = require('./type');
|
||||
const kebabToCamel = require('./string-util').kebabToCamel;
|
||||
|
||||
const CompilerObject = require('./compiler-object');
|
||||
const CompilerElement = require('./compiler-element');
|
||||
const CompilerText = require('./compiler-text');
|
||||
|
||||
const regCompilers = [
|
||||
CompilerText,
|
||||
CompilerObject,
|
||||
CompilerElement
|
||||
];
|
||||
|
||||
/**
|
||||
* Creates a object from a XML specification.
|
||||
*/
|
||||
module.exports = new Class({
|
||||
Extends: VnObject
|
||||
,_contexts: null
|
||||
|
||||
/**
|
||||
* Compiles an XML file.
|
||||
|
@ -30,8 +36,8 @@ module.exports = new Class({
|
|||
* @return {Boolean} %true on success, %false othersise
|
||||
*/
|
||||
,compileString: function(xmlString) {
|
||||
var parser = new DOMParser();
|
||||
var doc = parser.parseFromString(xmlString, 'text/xml');
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(xmlString, 'text/xml');
|
||||
return this.compileDocument(doc);
|
||||
}
|
||||
|
||||
|
@ -41,12 +47,12 @@ module.exports = new Class({
|
|||
* @param {Document} doc The DOM document
|
||||
* @return {Boolean} %true on success, %false othersise
|
||||
*/
|
||||
,compileDocument: function(doc, exprArgs) {
|
||||
,compileDocument: function(doc) {
|
||||
if (!doc)
|
||||
return false;
|
||||
|
||||
this._preCompile(exprArgs);
|
||||
var docElement = doc.documentElement;
|
||||
this._preCompile();
|
||||
const docElement = doc.documentElement;
|
||||
|
||||
if (docElement.tagName !== 'vn') {
|
||||
this.showError('The toplevel tag should be named \'vn\'');
|
||||
|
@ -54,9 +60,9 @@ module.exports = new Class({
|
|||
return false;
|
||||
}
|
||||
|
||||
var childs = docElement.childNodes;
|
||||
const childs = docElement.childNodes;
|
||||
if (childs)
|
||||
for (var i = 0; i < childs.length; i++)
|
||||
for (let i = 0; i < childs.length; i++)
|
||||
this._compile(childs[i]);
|
||||
|
||||
this._postCompile();
|
||||
|
@ -69,8 +75,8 @@ module.exports = new Class({
|
|||
* @path Node The DOM node
|
||||
* @return %true on success, %false othersise
|
||||
*/
|
||||
,compileNode: function(node, exprArgs) {
|
||||
this._preCompile(exprArgs);
|
||||
,compileNode: function(node) {
|
||||
this._preCompile();
|
||||
this._mainContext = this._compile(node).id;
|
||||
this._postCompile();
|
||||
return true;
|
||||
|
@ -79,28 +85,27 @@ module.exports = new Class({
|
|||
/**
|
||||
* Called before starting to compile nodes.
|
||||
*/
|
||||
,_preCompile: function(exprArgs) {
|
||||
,_preCompile: function() {
|
||||
this._path = null;
|
||||
this._tags = {};
|
||||
this._contexts = [];
|
||||
this._exprContexts = [];
|
||||
this._contextMap = {};
|
||||
this._links = [];
|
||||
this._mainContext = null;
|
||||
|
||||
this._baseExprArgs = ['_', '$'];
|
||||
if (exprArgs)
|
||||
this._baseExprArgs = this._baseExprArgs.concat(exprArgs);
|
||||
|
||||
this._baseEventArgs = this._baseExprArgs.concat(['$event']);
|
||||
|
||||
this._exprArgs = this._baseExprArgs.join(',');
|
||||
this._eventArgs = this._baseEventArgs.join(',');
|
||||
this._compilers = [];
|
||||
for (regCompiler of regCompilers)
|
||||
this._compilers.push(new regCompiler(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after all nodes have been compiled.
|
||||
*/
|
||||
,_postCompile: function() {}
|
||||
,_postCompile: function() {
|
||||
for (const compiler of this._compilers)
|
||||
compiler.postCompile(this._contextMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a node.
|
||||
|
@ -116,23 +121,23 @@ module.exports = new Class({
|
|||
|| /^[\n\r\t]*$/.test(node.textContent))
|
||||
return null;
|
||||
|
||||
context =
|
||||
this.textCompile(node, tagName)
|
||||
|| this.objectCompile(node, tagName)
|
||||
|| this.elementCompile(node, tagName);
|
||||
let i;
|
||||
const compilers = this._compilers;
|
||||
for (i = 0; i < compilers.length && context === null; i++)
|
||||
context = compilers[i].compile(this, node, tagName);
|
||||
|
||||
context.id = this._contexts.length;
|
||||
context.compiler = compilers[i - 1];
|
||||
|
||||
if (isElement) {
|
||||
var nodeId = node.getAttribute('id');
|
||||
const nodeId = node.getAttribute('id');
|
||||
|
||||
if (nodeId) {
|
||||
this._contextMap[kebabToCamel(nodeId)] = context.id;
|
||||
context.nodeId = nodeId;
|
||||
}
|
||||
|
||||
var tags = this._tags[tagName];
|
||||
|
||||
let tags = this._tags[tagName];
|
||||
if (!tags)
|
||||
this._tags[tagName] = tags = [];
|
||||
|
||||
|
@ -143,537 +148,21 @@ module.exports = new Class({
|
|||
return context;
|
||||
}
|
||||
|
||||
,getMain: function(scope) {
|
||||
return scope.objects[this._mainContext];
|
||||
}
|
||||
|
||||
,getByTagName: function(scope, tagName) {
|
||||
var tags = this._tags[tagName];
|
||||
|
||||
if (tags) {
|
||||
var arr = new Array(tags.length);
|
||||
|
||||
for (var i = 0; i < tags.length; i++)
|
||||
arr[i] = scope.objects[tags[i]];
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
,load: function(dstDocument, thisArg, parentScope) {
|
||||
if (this._contexts === null)
|
||||
return null;
|
||||
|
||||
if (!this._contexts) return null;
|
||||
const doc = dstDocument ? dstDocument : document;
|
||||
const contexts = this._contexts;
|
||||
const len = contexts.length;
|
||||
const objects = new Array(len);
|
||||
const scope = new Scope(this, objects, thisArg, parentScope);
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
var context = contexts[i];
|
||||
|
||||
if (context.tagName)
|
||||
objects[i] = this.elementInstantiate(doc, context, scope);
|
||||
else if (context.klass)
|
||||
objects[i] = this.objectInstantiate(doc, context, scope);
|
||||
else
|
||||
objects[i] = this.textInstantiate(doc, context, scope);
|
||||
}
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
,link: function(scope) {
|
||||
const objects = scope.objects;
|
||||
const links = this._links;
|
||||
|
||||
// Pre-link
|
||||
|
||||
for (var i = links.length - 1; i >= 0; i--) {
|
||||
const link = links[i];
|
||||
const object = objects[link.context.id];
|
||||
const objectRef = scope.$[link.objectId];
|
||||
|
||||
if (objectRef === undefined) {
|
||||
this.showError('Referenced unexistent object with id \'%s\'',
|
||||
link.objectId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (link.prop)
|
||||
object[link.prop] = objectRef;
|
||||
else
|
||||
object.appendChild(objectRef);
|
||||
}
|
||||
|
||||
// Post-link
|
||||
|
||||
const contexts = this._contexts;
|
||||
for (var i = 0; i < contexts.length; i++) {
|
||||
const context = contexts[i];
|
||||
const object = objects[i];
|
||||
|
||||
if (context.tagName)
|
||||
this.elementLink(context, object, objects, scope);
|
||||
else if (context.klass)
|
||||
this.objectLink(context, object, objects, scope);
|
||||
}
|
||||
}
|
||||
|
||||
,digest(scope) {
|
||||
const contexts = this._contexts;
|
||||
const objects = scope.objects;
|
||||
const exprScope = scope.exprScope;
|
||||
|
||||
for (let i = 0; i < contexts.length; i++) {
|
||||
const context = contexts[i];
|
||||
const object = objects[i];
|
||||
|
||||
if (context.exprs) {
|
||||
const values = [];
|
||||
let isEmpty = false;
|
||||
|
||||
for (expr of context.exprs) {
|
||||
let value = undefined;
|
||||
try {
|
||||
value = expr.apply(scope.thisArg, exprScope);
|
||||
if (value == null) {
|
||||
isEmpty = true;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Expression error:', e.message);
|
||||
continue;
|
||||
}
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
let text;
|
||||
|
||||
if (!isEmpty) {
|
||||
let k = 0;
|
||||
text = context.text.replace(/{{\d+}}/g, function() {
|
||||
return values[k++];
|
||||
});
|
||||
} else
|
||||
text = '';
|
||||
|
||||
object.textContent = text;
|
||||
} else {
|
||||
const dynProps = context.dynProps;
|
||||
|
||||
for (const prop in dynProps) {
|
||||
let value = undefined;
|
||||
try {
|
||||
value = dynProps[prop].apply(scope.thisArg, exprScope);
|
||||
} catch (e) {
|
||||
console.warn('Expression error:', e.message);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (context.tagName)
|
||||
object.setAttribute(prop, value);
|
||||
else
|
||||
object[prop] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
const objects = new Array(this._contexts.length);
|
||||
const exprValues = new Array(this._exprContexts.length);
|
||||
return new Scope(this, doc, objects, exprValues, thisArg, parentScope);
|
||||
}
|
||||
|
||||
,showError: function(error) {
|
||||
var path = this._path ? this._path : 'Node';
|
||||
var logArgs = ['Vn.Builder: %s: '+ error, path];
|
||||
const path = this._path ? this._path : 'Node';
|
||||
const logArgs = ['Vn.Builder: %s: '+ error, path];
|
||||
|
||||
for (var i = 1; i < arguments.length; i++)
|
||||
for (let i = 1; i < arguments.length; i++)
|
||||
logArgs.push(arguments[i]);
|
||||
|
||||
console.warn.apply(null, logArgs);
|
||||
}
|
||||
|
||||
,_addLink: function(context, prop, objectId) {
|
||||
this._links.push({
|
||||
context
|
||||
,prop
|
||||
,objectId: kebabToCamel(objectId)
|
||||
});
|
||||
}
|
||||
|
||||
,fnExpr(expr) {
|
||||
return new Function(this._exprArgs,
|
||||
'"use strict"; return ' + expr + ';'
|
||||
);
|
||||
}
|
||||
|
||||
,matchExpr(value) {
|
||||
const match = /^{{(.*)}}$/.exec(value);
|
||||
if (!match) return null;
|
||||
return this.fnExpr(match[1]);
|
||||
}
|
||||
|
||||
,_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) {
|
||||
let method;
|
||||
|
||||
if (this.isIdentifier(value)) {
|
||||
// XXX: Compatibility with old events
|
||||
method = value;
|
||||
} else {
|
||||
try {
|
||||
method = new Function(this._eventArgs,
|
||||
'"use strict"; return ' + value + ';'
|
||||
);
|
||||
} catch (err) {
|
||||
this.showError(`Method: ${err.message}: ${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
,_isEvent: function(attribute) {
|
||||
return /^on-\w+/.test(attribute);
|
||||
}
|
||||
|
||||
,isIdentifier: function(value) {
|
||||
return /^[a-zA-Z_$][\w$]*$/.test(value);
|
||||
}
|
||||
|
||||
,_replaceFunc: function(token) {
|
||||
return token.charAt(1).toUpperCase();
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TextNode
|
||||
|
||||
/**
|
||||
* Creates a text node context.
|
||||
*/
|
||||
,textCompile: function(node, tagName) {
|
||||
if (!tagName) {
|
||||
let text = node.textContent;
|
||||
|
||||
if (/{{.*}}/.test(text)) {
|
||||
let i = 0;
|
||||
const self = this;
|
||||
const exprs = [];
|
||||
text = text.replace(/{{((?:(?!}}).)*)}}/g, function(match, capture) {
|
||||
exprs.push(self.fnExpr(capture));
|
||||
return `{{${i++}}}`;
|
||||
});
|
||||
|
||||
return {text, exprs};
|
||||
} else
|
||||
return {text};
|
||||
} else if (tagName === 't')
|
||||
return {text: _(node.firstChild.textContent)};
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
,textInstantiate: function(doc, context) {
|
||||
return doc.createTextNode(context.exprs ? '' : context.text);
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Vn.Object
|
||||
|
||||
/**
|
||||
* Creates a object context.
|
||||
*/
|
||||
,objectCompile: function(node, tagName) {
|
||||
var klass = vnCustomTags[tagName];
|
||||
|
||||
if (!klass)
|
||||
return null;
|
||||
|
||||
var props = {};
|
||||
var objectProps = {};
|
||||
var childs = [];
|
||||
var events = {};
|
||||
|
||||
var context = {
|
||||
klass: klass,
|
||||
props: props,
|
||||
dynProps: {},
|
||||
funcProps: {},
|
||||
objectProps: objectProps,
|
||||
childs: childs,
|
||||
events: events,
|
||||
custom: null
|
||||
};
|
||||
|
||||
var a = node.attributes;
|
||||
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var attribute = a[i].nodeName;
|
||||
var value = a[i].nodeValue;
|
||||
|
||||
if (this._isEvent(attribute)) {
|
||||
var handler = this._getMethod(value)
|
||||
|
||||
if (handler)
|
||||
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 isElement = child.nodeType === Node.ELEMENT_NODE;
|
||||
var childTagName = isElement ? child.tagName.toLowerCase() : null;
|
||||
var childContext;
|
||||
|
||||
if (childTagName === 'pointer') {
|
||||
this._addLink(context, null, child.getAttribute('object'));
|
||||
} else if (childTagName === 'custom') {
|
||||
context.custom = child;
|
||||
} else if (childContext = this._compile(child)) {
|
||||
var prop = isElement ? child.getAttribute('property') : null;
|
||||
|
||||
if (prop) {
|
||||
prop = prop.replace(/-./g, this._replaceFunc);
|
||||
objectProps[prop] = childContext.id;
|
||||
} else
|
||||
childs.push(childContext.id);
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
,propCompile: function(context, klass, props, node, attribute, value) {
|
||||
let isLink = false;
|
||||
let propError = false;
|
||||
let newValue = null;
|
||||
const propName = attribute.replace(/-./g, this._replaceFunc);
|
||||
const propInfo = klass.Properties[propName];
|
||||
|
||||
if (!propInfo) {
|
||||
this.showError('Attribute \'%s\' not valid for tag \'%s\'',
|
||||
attribute, node.tagName);
|
||||
return;
|
||||
}
|
||||
if (!value) {
|
||||
this.showError('Attribute \'%s\' empty on tag \'%s\'',
|
||||
attribute, node.tagName);
|
||||
return;
|
||||
}
|
||||
|
||||
const expr = this.matchExpr(value);
|
||||
|
||||
if (expr) {
|
||||
context.dynProps[propName] = expr;
|
||||
} else {
|
||||
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:
|
||||
context.funcProps[propName] = this._getMethod(value);
|
||||
break;
|
||||
case Type:
|
||||
newValue = window[value];
|
||||
break;
|
||||
default:
|
||||
if (propInfo.enumType)
|
||||
newValue = propInfo.enumType[value];
|
||||
else if (propInfo.type instanceof Function)
|
||||
isLink = true;
|
||||
else
|
||||
propError = true;
|
||||
}
|
||||
|
||||
if (isLink)
|
||||
this._addLink(context, propName, value);
|
||||
else if (newValue !== null && newValue !== undefined)
|
||||
props[propName] = newValue;
|
||||
else if (propError)
|
||||
this.showError('Attribute \'%s\' invalid for tag \'%s\'',
|
||||
attribute, node.tagName);
|
||||
}
|
||||
}
|
||||
|
||||
,objectInstantiate: function(doc, context, scope) {
|
||||
const object = new context.klass();
|
||||
object.setProperties(context.props);
|
||||
|
||||
if (context.nodeId && object instanceof Component) {
|
||||
var id = context.nodeId;
|
||||
object.htmlId = scope.getHtmlId(id);
|
||||
object.className = '_'+ id +' '+ (object.className || '');
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
,objectLink: function(context, object, objects, scope) {
|
||||
const objectProps = context.objectProps;
|
||||
for (const prop in objectProps)
|
||||
object[prop] = objects[objectProps[prop]];
|
||||
|
||||
const childs = context.childs;
|
||||
for (let i = 0; i < childs.length; i++)
|
||||
object.appendChild(objects[childs[i]]);
|
||||
|
||||
const funcProps = context.funcProps;
|
||||
for (const prop in funcProps) {
|
||||
let method;
|
||||
const handler = funcProps[prop];
|
||||
|
||||
if (typeof handler === 'string') {
|
||||
// XXX: Compatibility with old expressions
|
||||
method = scope.thisArg[handler];
|
||||
if (!method)
|
||||
this.showError(`Function '${handler}' not found`);
|
||||
method = method.bind(scope.thisArg);
|
||||
} else {
|
||||
method = function() {
|
||||
handler.apply(scope.thisArg, scope.exprScope);
|
||||
};
|
||||
}
|
||||
|
||||
if (method)
|
||||
object[prop] = method;
|
||||
}
|
||||
|
||||
const events = context.events;
|
||||
for (const event in events) {
|
||||
let listener;
|
||||
const handler = events[event];
|
||||
|
||||
if (typeof handler === 'string') {
|
||||
// XXX: Compatibility with old expressions
|
||||
listener = scope.thisArg[handler];
|
||||
if (!listener)
|
||||
this.showError(`Function '${handler}' not found`);
|
||||
} else {
|
||||
listener = function() {
|
||||
handler.apply(scope.thisArg, scope.exprScope.concat(arguments));
|
||||
};
|
||||
}
|
||||
|
||||
if (listener)
|
||||
object.on(event, listener, scope.thisArg);
|
||||
}
|
||||
|
||||
if (context.custom)
|
||||
object.loadXml(scope, context.custom);
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Element
|
||||
|
||||
/**
|
||||
* Creates a HTML node context.
|
||||
*/
|
||||
,elementCompile: function(node, tagName) {
|
||||
var attributes = {};
|
||||
var dynProps = {};
|
||||
var childs = [];
|
||||
var events = {};
|
||||
var handler;
|
||||
|
||||
var a = node.attributes;
|
||||
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var attribute = a[i].nodeName;
|
||||
var value = a[i].nodeValue;
|
||||
|
||||
if (this._isEvent(attribute)) {
|
||||
var handler = this._getMethod(value);
|
||||
if (handler) events[attribute.substr(3)] = handler;
|
||||
} else if (attribute !== 'id') {
|
||||
const expr = this.matchExpr(value);
|
||||
if (expr)
|
||||
dynProps[attribute] = expr;
|
||||
else
|
||||
attributes[attribute] = this._translateValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
var childContext;
|
||||
var childNodes = node.childNodes;
|
||||
|
||||
if (childNodes)
|
||||
for (var i = 0; i < childNodes.length; i++)
|
||||
if (childContext = this._compile(childNodes[i]))
|
||||
childs.push(childContext.id);
|
||||
|
||||
return {
|
||||
tagName,
|
||||
attributes,
|
||||
dynProps,
|
||||
childs,
|
||||
events
|
||||
};
|
||||
}
|
||||
|
||||
,elementInstantiate: function(doc, context, scope) {
|
||||
var object = doc.createElement(context.tagName);
|
||||
|
||||
const attributes = context.attributes;
|
||||
for (const attribute in attributes)
|
||||
object.setAttribute(attribute, attributes[attribute]);
|
||||
|
||||
if (context.nodeId) {
|
||||
const id = context.nodeId;
|
||||
object.setAttribute('id', scope.getHtmlId(id));
|
||||
VnNode.addClass(object, '_'+ id);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
,elementLink: function(context, object, objects, scope) {
|
||||
const childs = context.childs;
|
||||
for (var i = 0; i < childs.length; i++) {
|
||||
let child = objects[childs[i]];
|
||||
|
||||
if (child instanceof Component)
|
||||
child = child.node;
|
||||
if (child instanceof Node)
|
||||
object.appendChild(child);
|
||||
}
|
||||
|
||||
const events = context.events;
|
||||
for (const event in events) {
|
||||
let listener;
|
||||
const handler = events[event];
|
||||
if (typeof handler === 'string') {
|
||||
// XXX: Compatibility with old expressions
|
||||
listener = scope.thisArg[handler];
|
||||
if (!listener)
|
||||
this.showError(`Function '${handler}' not found`);
|
||||
listener = listener.bind(scope.thisArg);
|
||||
} else {
|
||||
listener = function(e) {
|
||||
handler.apply(scope.thisArg, scope.exprScope.concat(e));
|
||||
};
|
||||
}
|
||||
|
||||
if (listener)
|
||||
object.addEventListener(event, listener);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
const Compiler = require('./compiler');
|
||||
const Component = require('./component');
|
||||
const VnNode = require('./node');
|
||||
|
||||
/**
|
||||
* Compiles a @HTMLElement from element tag.
|
||||
*/
|
||||
module.exports = new Class({
|
||||
Extends: Compiler
|
||||
|
||||
,compile: function(builder, node, tagName) {
|
||||
const context = {
|
||||
tagName,
|
||||
attributes: {},
|
||||
childs: [],
|
||||
events: {}
|
||||
};
|
||||
const {attributes} = context;
|
||||
|
||||
const a = node.attributes;
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
const attribute = a[i].nodeName;
|
||||
const value = a[i].nodeValue;
|
||||
|
||||
if (this.isEvent(attribute)) {
|
||||
const handler = this._getMethod(value);
|
||||
if (handler) context.events[attribute.substr(3)] = handler;
|
||||
} else if (!/^(id|property)$/.test(attribute)) {
|
||||
if (this.isExpr(value))
|
||||
this.compileExpr(context, attribute, value);
|
||||
else
|
||||
attributes[attribute] = this._translateValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
let childContext;
|
||||
const childNodes = node.childNodes;
|
||||
|
||||
if (childNodes)
|
||||
for (let i = 0; i < childNodes.length; i++)
|
||||
if (childContext = builder._compile(childNodes[i]))
|
||||
context.childs.push(childContext.id);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
,instantiate: function(doc, context, scope) {
|
||||
const object = doc.createElement(context.tagName);
|
||||
|
||||
const attributes = context.attributes;
|
||||
for (const attribute in attributes)
|
||||
object.setAttribute(attribute, attributes[attribute]);
|
||||
|
||||
if (context.nodeId) {
|
||||
const id = context.nodeId;
|
||||
object.setAttribute('id', scope.getHtmlId(id));
|
||||
VnNode.addClass(object, '_'+ id);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
,setProperty(object, property, value) {
|
||||
object.setAttribute(property, value);
|
||||
}
|
||||
|
||||
,link: function(context, object, objects, scope) {
|
||||
const childs = context.childs;
|
||||
for (let i = 0; i < childs.length; i++) {
|
||||
let child = objects[childs[i]];
|
||||
|
||||
if (child instanceof Component)
|
||||
child = child.node;
|
||||
if (child instanceof Node)
|
||||
object.appendChild(child);
|
||||
}
|
||||
|
||||
const events = context.events;
|
||||
for (const event in events) {
|
||||
const listener = this.bindMethod(events[event], scope, true);
|
||||
if (listener)
|
||||
object.addEventListener(event, listener);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,216 @@
|
|||
const Compiler = require('./compiler');
|
||||
const Component = require('./component');
|
||||
const Type = require('./type');
|
||||
const kebabToCamel = require('./string-util').kebabToCamel;
|
||||
|
||||
/**
|
||||
* Compiles a @Vn.Object from element tag.
|
||||
*/
|
||||
module.exports = new Class({
|
||||
Extends: Compiler
|
||||
|
||||
,_links: []
|
||||
|
||||
/**
|
||||
* Creates a object context.
|
||||
*/
|
||||
,compile: function(builder, node, tagName) {
|
||||
const klass = vnCustomTags[tagName];
|
||||
if (!klass) return null;
|
||||
|
||||
const context = {
|
||||
klass,
|
||||
props: {},
|
||||
funcProps: {},
|
||||
objectProps: {},
|
||||
childs: [],
|
||||
events: {},
|
||||
custom: null
|
||||
};
|
||||
|
||||
const a = node.attributes;
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
const attribute = a[i].nodeName;
|
||||
const value = a[i].nodeValue;
|
||||
|
||||
if (this.isEvent(attribute)) {
|
||||
const handler = this._getMethod(value)
|
||||
if (handler) context.events[attribute.substr(3)] = handler;
|
||||
} else if (!/^(id|property)$/.test(attribute)) {
|
||||
this.propCompile(context, node, attribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
const childNodes = node.childNodes;
|
||||
|
||||
if (childNodes)
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const child = childNodes[i];
|
||||
const isElement = child.nodeType === Node.ELEMENT_NODE;
|
||||
const childTagName = isElement ? child.tagName.toLowerCase() : null;
|
||||
let childContext;
|
||||
|
||||
if (childTagName === 'pointer') {
|
||||
this._addLink(context, null, child.getAttribute('object'));
|
||||
} else if (childTagName === 'custom') {
|
||||
context.custom = child;
|
||||
} else if (childContext = builder._compile(child)) {
|
||||
let prop = isElement ? child.getAttribute('property') : null;
|
||||
|
||||
if (prop) {
|
||||
prop = kebabToCamel(prop);
|
||||
context.objectProps[prop] = childContext.id;
|
||||
} else
|
||||
context.childs.push(childContext.id);
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
,propCompile: function(context, node, attribute, value) {
|
||||
const tagName = node.tagName;
|
||||
const propName = kebabToCamel(attribute);
|
||||
const propInfo = context.klass.Properties[propName];
|
||||
|
||||
if (!value) {
|
||||
this.showError('Attribute \'%s\' empty on tag \'%s\'',
|
||||
attribute, tagName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == 'vModel') {
|
||||
context.vModel = this.modelExpr(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!propInfo) {
|
||||
this.showError('Attribute \'%s\' not valid for tag \'%s\'',
|
||||
attribute, tagName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isExpr(value)) {
|
||||
this.compileExpr(context, propName, value);
|
||||
} else {
|
||||
let isLink = false;
|
||||
let propError = false;
|
||||
let newValue = null;
|
||||
|
||||
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:
|
||||
context.funcProps[propName] = this._getMethod(value);
|
||||
break;
|
||||
case Type:
|
||||
newValue = window[value];
|
||||
break;
|
||||
default:
|
||||
if (propInfo.enumType)
|
||||
newValue = propInfo.enumType[value];
|
||||
else if (propInfo.type instanceof Function)
|
||||
isLink = true;
|
||||
else
|
||||
propError = true;
|
||||
}
|
||||
|
||||
if (isLink)
|
||||
this._addLink(context, propName, value);
|
||||
else if (newValue !== null && newValue !== undefined)
|
||||
context.props[propName] = newValue;
|
||||
else if (propError)
|
||||
this.showError('Attribute \'%s\' invalid for tag \'%s\'',
|
||||
attribute, tagName);
|
||||
}
|
||||
}
|
||||
|
||||
,instantiate: function(doc, context, scope) {
|
||||
const object = new context.klass();
|
||||
object.setProperties(context.props);
|
||||
|
||||
if (context.nodeId && object instanceof Component) {
|
||||
const id = context.nodeId;
|
||||
object.htmlId = scope.getHtmlId(id);
|
||||
object.className = '_'+ id +' '+ (object.className || '');
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
,setProperty(object, property, value) {
|
||||
object[property] = value;
|
||||
}
|
||||
|
||||
,preLink(scope) {
|
||||
const objects = scope.objects;
|
||||
const links = this._links;
|
||||
|
||||
for (let i = links.length - 1; i >= 0; i--) {
|
||||
const link = links[i];
|
||||
const object = objects[link.context.id];
|
||||
const objectRef = scope.$[link.objectId];
|
||||
|
||||
if (objectRef === undefined) {
|
||||
this.showError('Referenced unexistent object with id \'%s\'',
|
||||
link.objectId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (link.prop)
|
||||
object[link.prop] = objectRef;
|
||||
else
|
||||
object.appendChild(objectRef);
|
||||
}
|
||||
}
|
||||
|
||||
,link: function(context, object, objects, scope) {
|
||||
const objectProps = context.objectProps;
|
||||
for (const prop in objectProps)
|
||||
object[prop] = objects[objectProps[prop]];
|
||||
|
||||
const childs = context.childs;
|
||||
for (let i = 0; i < childs.length; i++)
|
||||
object.appendChild(objects[childs[i]]);
|
||||
|
||||
const funcProps = context.funcProps;
|
||||
for (const prop in funcProps)
|
||||
object[prop] = this.bindMethod(funcProps[prop], scope);
|
||||
|
||||
const events = context.events;
|
||||
for (const event in events) {
|
||||
const listener = this.bindMethod(events[event], scope);
|
||||
if (listener)
|
||||
object.on(event, listener, scope.thisArg);
|
||||
}
|
||||
|
||||
if (context.vModel) {
|
||||
object.on('change', function(lot) {
|
||||
context.vModel.call(scope.thisArg, scope.$, lot.$);
|
||||
scope.digest();
|
||||
}, scope);
|
||||
}
|
||||
|
||||
if (context.custom)
|
||||
object.loadXml(scope, context.custom);
|
||||
}
|
||||
|
||||
,_addLink: function(context, prop, objectId) {
|
||||
this._links.push({
|
||||
context
|
||||
,prop
|
||||
,objectId: kebabToCamel(objectId)
|
||||
});
|
||||
}
|
||||
|
||||
,_replaceFunc: function(token) {
|
||||
return token.charAt(1).toUpperCase();
|
||||
}
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
const Compiler = require('./compiler');
|
||||
|
||||
/**
|
||||
* Compiles a @Text from text node.
|
||||
*/
|
||||
module.exports = new Class({
|
||||
Extends: Compiler
|
||||
|
||||
,compile: function(builder, node, tagName) {
|
||||
if (tagName && tagName != 't')
|
||||
return null;
|
||||
|
||||
const text = node.textContent;
|
||||
const context = {text};
|
||||
|
||||
if (tagName === 't') {
|
||||
context.text = _(node.firstChild.textContent);
|
||||
} else if (this.isExpr(text, true)) {
|
||||
context.text = '';
|
||||
this.compileExpr(context, null, text, true);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
,instantiate: function(doc, context) {
|
||||
return doc.createTextNode(context.text);
|
||||
}
|
||||
|
||||
,setProperty(object, property, value) {
|
||||
object.textContent = value;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,150 @@
|
|||
|
||||
var VnObject = require('./object');
|
||||
|
||||
/**
|
||||
* Base class for compilers.
|
||||
*/
|
||||
module.exports = new Class({
|
||||
Extends: VnObject
|
||||
|
||||
,compile: function() {}
|
||||
,postCompile: function() {}
|
||||
,instantiate: function() {}
|
||||
,preLink: function() {}
|
||||
,link: function() {}
|
||||
,connect: function() {}
|
||||
,postLink: function() {}
|
||||
,setProperty: function() {}
|
||||
,free: function() {}
|
||||
|
||||
,initialize: function(builder) {
|
||||
this._builder = builder;
|
||||
this._interpoler = builder._interpoler;
|
||||
this.parent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the passed attribute name it's an event.
|
||||
*
|
||||
* @param {String} attribute The attribute name
|
||||
* @return {Boolean} %true if it's an event, otherwise %false
|
||||
*/
|
||||
,isEvent: function(attribute) {
|
||||
return /^on-\w+/.test(attribute);
|
||||
}
|
||||
|
||||
,isIdentifier: function(value) {
|
||||
return /^[a-zA-Z_$][\w$]*$/.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error parsing the node.
|
||||
*
|
||||
* @param {String} error The error message template
|
||||
* @param {...} varArgs The message template arguments
|
||||
*/
|
||||
,showError: function() {
|
||||
this._builder.showError.apply(this._builder, arguments);
|
||||
}
|
||||
|
||||
,_getMethod: function(value) {
|
||||
// XXX: Compatibility with old methods
|
||||
return this.isIdentifier(value)
|
||||
? value
|
||||
: this.fnExpr(value);
|
||||
}
|
||||
|
||||
,bindMethod(handler, scope, isEvent) {
|
||||
// XXX: Compatibility with old methods
|
||||
if (typeof handler === 'string') {
|
||||
const method = scope.thisArg[handler];
|
||||
if (!method) {
|
||||
this.showError(`Function '${handler}' not found`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return method.bind(scope.thisArg);
|
||||
}
|
||||
|
||||
return function($event) {
|
||||
let handlerScope;
|
||||
if (isEvent) {
|
||||
handlerScope = Object.create(scope.$);
|
||||
Object.assign(handlerScope, {$event});
|
||||
} else
|
||||
handlerScope = scope.$;
|
||||
|
||||
handler.call(this, handlerScope);
|
||||
}.bind(scope.thisArg);
|
||||
}
|
||||
|
||||
,matchExpr(value) {
|
||||
const match = /^{{(.*)}}$/.exec(value);
|
||||
if (!match) return null;
|
||||
return this.fnExpr(match[1]);
|
||||
}
|
||||
|
||||
,modelExpr(expr) {
|
||||
try {
|
||||
return new Function('$scope', '$value',
|
||||
`"use strict"; $scope.${expr} = $value;`
|
||||
);
|
||||
} catch (err) {
|
||||
this.showError(`${err.message}:`, expr);
|
||||
}
|
||||
}
|
||||
|
||||
,exprRegex: /^{{((?:(?!}}).)*)}}$/
|
||||
,exprRegexMulti: /{{((?:(?!}}).)*)}}/g
|
||||
|
||||
,isExpr(expr, isMulti) {
|
||||
return isMulti
|
||||
? this.exprRegexMulti.test(expr)
|
||||
: this.exprRegex.test(expr);
|
||||
}
|
||||
|
||||
,compileExpr(context, property, value, isMulti) {
|
||||
const exprContext = {
|
||||
context,
|
||||
property,
|
||||
value
|
||||
};
|
||||
|
||||
if (isMulti) {
|
||||
let i = 0;
|
||||
const self = this;
|
||||
exprContext.exprs = [];
|
||||
exprContext.template = value.replace(this.exprRegexMulti,
|
||||
function(match, capture) {
|
||||
exprContext.exprs.push(self.fnExpr(capture));
|
||||
return `{{${i++}}}`;
|
||||
});
|
||||
} else {
|
||||
const match = this.exprRegex.exec(value);
|
||||
exprContext.expr = this.fnExpr(match[1]);
|
||||
}
|
||||
|
||||
this._builder._exprContexts.push(exprContext);
|
||||
}
|
||||
|
||||
,fnExpr(expr) {
|
||||
try {
|
||||
return new Function('$scope',
|
||||
`with($scope) { return ${expr}; }`
|
||||
);
|
||||
} catch (err) {
|
||||
this.showError(`${err.message}:`, expr);
|
||||
}
|
||||
}
|
||||
|
||||
,_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;
|
||||
}
|
||||
});
|
|
@ -29,7 +29,11 @@ module.exports = new Class({
|
|||
}
|
||||
|
||||
,initialize: function(props) {
|
||||
this._params = {};
|
||||
this._params = new Proxy({}, {
|
||||
set(obj, prop, value) {
|
||||
return Reflect.set(obj, prop, value);
|
||||
}
|
||||
});
|
||||
VnObject.prototype.initialize.call(this, props);
|
||||
}
|
||||
|
||||
|
|
112
js/vn/scope.js
112
js/vn/scope.js
|
@ -6,21 +6,30 @@ let scopeUid = 0;
|
|||
module.exports = new Class({
|
||||
Extends: VnObject
|
||||
|
||||
,initialize: function(builder, objects, thisArg, parent) {
|
||||
,initialize: function(builder, doc, objects, exprValues, thisArg, parent) {
|
||||
this.builder = builder;
|
||||
this.objects = objects;
|
||||
this.exprValues = exprValues;
|
||||
this.thisArg = thisArg;
|
||||
this.parent = parent;
|
||||
this.uid = ++scopeUid;
|
||||
this.$ = parent ? Object.create(parent.$) : {};
|
||||
|
||||
if (parent) {
|
||||
parent.on('lot-change', this.onLotChange, this);
|
||||
parent.ref();
|
||||
// XXX: Keep commented until optimized
|
||||
//parent.on('change', this.onChange, this);
|
||||
if (!thisArg) this.thisArg = parent.thisArg;
|
||||
}
|
||||
|
||||
const contexts = builder._contexts;
|
||||
for (let i = 0; i < contexts.length; i++) {
|
||||
const context = contexts[i];
|
||||
objects[i] = context.compiler.instantiate(doc, context, this);
|
||||
}
|
||||
}
|
||||
|
||||
,link: function(exprScope, extraObjects) {
|
||||
,link: function(extraObjects) {
|
||||
var contextMap = this.builder._contextMap;
|
||||
|
||||
for (var id in extraObjects)
|
||||
|
@ -28,26 +37,88 @@ module.exports = new Class({
|
|||
for (var id in contextMap)
|
||||
this.$[id] = this.objects[contextMap[id]];
|
||||
|
||||
this.exprScope = [
|
||||
_,
|
||||
this.$
|
||||
].concat(exprScope);
|
||||
const builder = this.builder;
|
||||
const contexts = builder._contexts;
|
||||
const objects = this.objects;
|
||||
|
||||
this.builder.link(this);
|
||||
this.builder.digest(this);
|
||||
for (const compiler of builder._compilers)
|
||||
compiler.preLink(this);
|
||||
|
||||
for (let i = 0; i < contexts.length; i++) {
|
||||
const context = contexts[i];
|
||||
context.compiler.link(context, objects[i], objects, this);
|
||||
}
|
||||
|
||||
for (let i = 0; i < contexts.length; i++) {
|
||||
const context = contexts[i];
|
||||
context.compiler.connect(context, objects[i], objects, this);
|
||||
}
|
||||
|
||||
for (const compiler of builder._compilers)
|
||||
compiler.postLink(this);
|
||||
|
||||
this.digest();
|
||||
|
||||
for (const object of this.objects)
|
||||
if (object.assignLot)
|
||||
object.on('change', this.onLotChange, this);
|
||||
object.on('change', this.onChange, this);
|
||||
}
|
||||
|
||||
,onLotChange() {
|
||||
this.emit('lot-change');
|
||||
this.builder.digest(this);
|
||||
,digest() {
|
||||
const exprContexts = this.builder._exprContexts;
|
||||
const exprValues = this.exprValues;
|
||||
const objects = this.objects;
|
||||
|
||||
for (let i = 0; i < exprContexts.length; i++) {
|
||||
const exprContext = exprContexts[i];
|
||||
let newValue;
|
||||
|
||||
if (exprContext.template) {
|
||||
const values = [];
|
||||
let isEmpty = false;
|
||||
|
||||
for (expr of exprContext.exprs) {
|
||||
const value = this.execExpr(expr);
|
||||
if (value == null) {
|
||||
isEmpty = true;
|
||||
break;
|
||||
}
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
if (!isEmpty) {
|
||||
let k = 0;
|
||||
newValue = exprContext.template.replace(/{{\d+}}/g, function() {
|
||||
return values[k++];
|
||||
});
|
||||
} else
|
||||
newValue = '';
|
||||
} else
|
||||
newValue = this.execExpr(exprContext.expr);
|
||||
|
||||
if (newValue !== exprValues[i]) {
|
||||
const context = exprContext.context;
|
||||
context.compiler.setProperty(objects[context.id],
|
||||
exprContext.property, newValue);
|
||||
exprValues[i] = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
,execExpr(expr) {
|
||||
try {
|
||||
return expr.call(this.thisArg, this.$);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
,onChange() {
|
||||
this.emit('change');
|
||||
this.digest();
|
||||
}
|
||||
|
||||
,getMain: function() {
|
||||
return this.builder.getMain(this);
|
||||
return this.objects[this.builder._mainContext];
|
||||
}
|
||||
|
||||
,getById: function(objectId) {
|
||||
|
@ -56,7 +127,18 @@ module.exports = new Class({
|
|||
}
|
||||
|
||||
,getByTagName: function(tagName) {
|
||||
return this.builder.getByTagName(this, tagName);
|
||||
const tags = this.builder._tags[tagName];
|
||||
|
||||
if (tags) {
|
||||
const arr = new Array(tags.length);
|
||||
|
||||
for (let i = 0; i < tags.length; i++)
|
||||
arr[i] = this.objects[tags[i]];
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
,getHtmlId: function(nodeId) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "hedera-web",
|
||||
"version": "1.407.79",
|
||||
"version": "1.407.80",
|
||||
"description": "Verdnatura web page",
|
||||
"license": "GPL-3.0",
|
||||
"repository": {
|
||||
|
|
|
@ -66,7 +66,7 @@ class HtmlService extends Service {
|
|||
|
||||
// Setting the version
|
||||
|
||||
setcookie('vnVersion', $this->getVersion());
|
||||
setcookie('vnVersion', $this->getVersion(), ['samesite' => 'Lax']);
|
||||
|
||||
// Loading the requested page
|
||||
|
||||
|
|
|
@ -124,7 +124,10 @@ abstract class Service {
|
|||
);
|
||||
|
||||
if (isset($row['access'])) {
|
||||
setcookie('vnVisit', $row['visit'], time() + 31536000); // 1 Year
|
||||
setcookie('vnVisit', $row['visit'], [
|
||||
'expires' => time() + 31536000, // 1 Year
|
||||
'samesite' => 'Lax'
|
||||
]);
|
||||
$_SESSION['access'] = $row['access'];
|
||||
} else
|
||||
$_SESSION['skipVisit'] = TRUE;
|
||||
|
|
Loading…
Reference in New Issue