Checkpoint
gitea/hedera-web/pipeline/head This commit looks good Details

This commit is contained in:
Juan Ferrer 2022-05-24 12:18:44 +02:00
parent 11ba609144
commit 546e67d6f6
58 changed files with 1176 additions and 1281 deletions

View File

@ -3,39 +3,37 @@ Hedera.AddressList = new Class
({
Extends: Hedera.Form
,activate: function ()
{
this.$('user-model').setInfo ('c', 'myClient', 'hedera');
this.$('addresses').setInfo ('a', 'myAddress', 'hedera');
,activate: function() {
this.$('user-model').setInfo('c', 'myClient', 'hedera');
this.$('addresses').setInfo('a', 'myAddress', 'hedera');
}
,onAddAddressClick: function ()
{
this.hash.set ({
,onAddAddressClick: function() {
this.hash.set({
form: 'account/address',
address: 0
});
}
,onReturnClick: function ()
{
,onReturnClick: function() {
window.history.back();
}
,onSetDefaultClick: function() {
Htk.Toast.showMessage(_('DefaultAddressModified'));
}
,onRemoveAddressClick: function (button, form)
{
if (confirm (_('AreYouSureDeleteAddress')))
{
form.set ('isActive', false);
form.refresh ();
,onRemoveAddressClick: function(button, form) {
if (confirm(_('AreYouSureDeleteAddress'))) {
form.set('isActive', false);
form.refresh();
}
}
,onEditAddressClick: function (button, form)
{
this.hash.set ({
,onEditAddressClick: function(button, form) {
this.hash.set({
form: 'account/address',
address: form.get ('id')
address: form.get('id')
});
}
});

View File

@ -5,3 +5,4 @@ SetAsDefault: Establir com per defecte
RemoveAddress: Esborrar direcció
EditAddress: Modificar direcció
AreYouSureDeleteAddress: Estàs segur de que vols eliminar la direcció?
DefaultAddressModified: Adreça per defecte modificada

View File

@ -5,3 +5,4 @@ SetAsDefault: Set as default
RemoveAddress: Remove address
EditAddress: Edit address
AreYouSureDeleteAddress: Are you sure you want to delete the address?
DefaultAddressModified: Default address modified

View File

@ -5,3 +5,4 @@ SetAsDefault: Establecer como predeterminada
RemoveAddress: Borrar dirección
EditAddress: Modificar dirección
AreYouSureDeleteAddress: ¿Estás seguro de que quieres borrar la dirección?
DefaultAddressModified: Dirección por defecto modificada

View File

@ -5,3 +5,4 @@ SetAsDefault: Définir par défaut
RemoveAddress: Supprimer l'adresse
EditAddress: Changement d'adresse
AreYouSureDeleteAddress: Souhaitez-vous vraiment supprier l'adresse?
DefaultAddressModified: Adresse par défaut modifiée

View File

@ -5,3 +5,4 @@ SetAsDefault: Selecionar como pre-determinado
RemoveAddress: Eliminar Morada
EditAddress: Modificar Morada
AreYouSureDeleteAddress: Tens certeza que queres eliminar esta morada?
DefaultAddressModified: Endereço padrão modificado

View File

@ -1,48 +1,15 @@
.address-list
{
.address-list {
padding: 1em;
}
.address-list .box
{
.address-list .box {
max-width: 30em;
}
.address-list .form
{
.address-list .form {
margin: 0 auto;
max-width: 25em;
padding: 2em;
}
.address
{
padding: 1em;
border-bottom: 1px solid #DDD;
}
.address p
{
margin: 0.2em 0;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.address p.important
{
font-size: 1.2em;
}
.address .actions
{
float: right;
}
.address .actions > .htk-button
{
margin: 0;
}
.address .actions > *
{
display: inline-block;
vertical-align: middle;
}
.address .actions > input
{
margin: .6em;
.address-list .htk-list .side {
padding-right: 16px;
}

View File

@ -33,15 +33,28 @@
id="default-address"
column="defaultAddressFk"
form="user-form"/>
<htk-repeater model="addresses" form-id="iter">
<htk-repeater model="addresses" form-id="iter" class="htk-list">
<custom>
<div class="address">
<div class="actions">
<div class="address item" on-click="onSetDefaultClick">
<div class="side">
<htk-radio
form="iter"
column="id"
radio-group="default-address"
tip="_SetAsDefault"/>
</div>
<div class="content">
<p class="important">
{{iter.nickname}}
</p>
<p>
{{iter.street}}
</p>
<p>
{{iter.postalCode}}, {{iter.city}}
</p>
</div>
<div class="actions">
<htk-button
form="iter"
column="id"
@ -55,16 +68,6 @@
icon="edit"
on-click="onEditAddressClick"/>
</div>
<p class="important">
<htk-text form="iter" column="nickname"/>
</p>
<p>
<htk-text form="iter" column="street"/>
</p>
<p>
<htk-text form="iter" column="postalCode"/>,
<htk-text form="iter" column="city"/>
</p>
</div>
</custom>
</htk-repeater>

View File

@ -43,9 +43,13 @@
}
.new-text {
margin: 1.5em 0;
font-family: 'Open Sans';
line-height: 1.3em;
}
.new-text a {
color: blue;
color: #6a1;
}
.new-text a:hover {
text-decoration: underline;
}
.new-text li {

View File

@ -11,7 +11,7 @@
</div>
<div id="form" class="home">
<div class="column mansonry" id="news-column">
<htk-repeater form-id="new">
<htk-repeater form-id="iter">
<db-model property="model">
<custom>
SELECT title, text, image, id FROM news
@ -25,14 +25,14 @@
<htk-image
directory="news"
subdir="full"
form="new"
form="iter"
column="image"
editable="false"
full-dir="full"/>
<div class="top">
<h2><htk-text form="new" column="title"/></h2>
<h2>{{iter.title}}</h2>
<div class="new-text">
<htk-html form="new" column="text"/>
<htk-html value="{{iter.text}}"/>
</div>
</div>
</div>

View File

@ -3,56 +3,43 @@ Hedera.Basket = new Class
({
Extends: Hedera.Form
,open: function ()
{
this.close ();
,open: function() {
this.close();
this.isOpen = true;
Hedera.BasketChecker.check (this.conn,
this.onBasketCheck.bind (this));
Hedera.BasketChecker.check(this.conn,
this.onBasketCheck.bind(this));
}
,onBasketCheck: function (isOk)
{
,onBasketCheck: function(isOk) {
if (isOk)
this.loadUi ();
this.loadUi();
}
,activate: function ()
{
this.$('items').setInfo ('bi', 'myBasketItem', 'hedera');
,activate: function() {
this.$('items').setInfo('bi', 'myBasketItem', 'hedera');
}
,onConfigureClick: function ()
{
Htk.Toast.showWarning (_('RememberReconfiguringImpact'));
this.hash.set ({form: 'ecomerce/checkout'});
,onConfigureClick: function() {
Htk.Toast.showWarning(_('RememberReconfiguringImpact'));
this.hash.set({form: 'ecomerce/checkout'});
}
,onCatalogClick: function ()
{
this.hash.set ({form: 'ecomerce/catalog'});
,onCatalogClick: function() {
this.hash.set({form: 'ecomerce/catalog'});
}
,onCheckoutClick: function ()
{
this.hash.set ({form: 'ecomerce/confirm'});
,onCheckoutClick: function() {
this.hash.set({form: 'ecomerce/confirm'});
}
,repeaterFunc: function (res, form)
{
res.$('subtotal').value = this.subtotal (form);
,onDeleteClick: function(button, form) {
if (confirm(_('ReallyDelete')))
form.deleteRow();
}
,onDeleteClick: function (button, form)
{
if (confirm (_('ReallyDelete')))
form.deleteRow ();
}
,subtotal: function (form)
{
return form.get ('amount') * form.get ('price');
,subtotal: function(form) {
return form.get('amount') * form.get('price');
}
});

View File

@ -1,28 +1,24 @@
.basket
{
.basket {
padding: 1em;
}
.basket .box
{
.basket .box {
max-width: 30em;
margin: 0 auto;
padding: 0 2em;
padding: 30px;
}
.basket .form > p
{
.basket .form > p {
margin: 0;
font-size: 1.4em;
color: white;
text-align: right;
}
.basket .head
{
padding: 1.8em 0;
.basket .head {
padding-bottom: 30px;
margin: 0;
border-bottom: 1px solid #DDD;
}
.basket .head p
{
.basket .head p {
font-weight: bold;
margin: 0;
padding: 0;
font-size: 1.4em;
@ -31,61 +27,48 @@
/* Lines */
.basket .lines
{
padding: .8em 0;
.basket .line {
display: flex;
gap: 20px;
margin: 24px 0;
height: 65px;
}
.basket .line
{
padding: 1em 0;
.basket .line:last-child {
margin-bottom: 0;
}
.basket .line > .delete
{
margin: -0.5em;
margin-top: 1em;
margin-right: .5em;
float: left;
.basket .line > .delete {
align-self: center;
}
.basket .line > .photo
{
margin-right: 1em;
float: left;
.basket .line > .photo {
flex: none;
border-radius: 50%;
height: 4.25em;
width: 4.25em;
width: 65px;
}
.basket .line > .info
{
margin-left: 7.5em;
.basket .line > .info {
flex: 1;
}
.basket .line > .info > h2
{
.basket .line > .info > h2 {
font-size: 1em;
font-weight: normal;
padding: 0;
padding-bottom: .1em;
}
.basket .line > .info > p
{
.basket .line > .info > p {
margin: 0;
}
.basket .line > .info > .tags
{
.basket .line > .info > .tags {
color: #777;
}
.basket .line .subtotal
{
.basket .line .subtotal {
float: right;
}
/* Fields */
.basket td.available-exceeded input
{
.basket td.available-exceeded input {
background-color: #FCC;
}
.basket .icon > img
{
.basket .icon > img {
border-radius: 50%;
}

View File

@ -27,7 +27,7 @@
</p>
</div>
<div class="lines">
<htk-repeater form-id="iter" renderer="repeaterFunc">
<htk-repeater form-id="iter">
<db-model id="items" property="model" updatable="true">
SELECT bi.id, bi.amount, bi.price, i.longName item,
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
@ -60,19 +60,15 @@
<htk-text form="iter" column="item"/>
</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="amount"/> x
<htk-text form="iter" column="price" format="%.2d€"/>
{{iter.amount}} x {{Vn.Value.format(iter.price, '%.2d€')}}
<span class="subtotal">
<htk-text id="subtotal" format="%.2d€"/>
{{Vn.Value.format(iter.price * iter.amount, '%.2d€')}}
</span>
</p>
</div>
<div class="clear"/>
</div>
</custom>
</htk-repeater>

View File

@ -103,11 +103,6 @@ Hedera.Catalog = new Class({
'form': this.hash.get('form'),
'realm': form.get('id')
});
var img = builder.$('image');
img.src = 'image/family/black/'+ form.get('code') +'.svg';
img.title = form.get('name');
img.alt = img.title;
}
,onRealmChange: function(param, newValue) {

View File

@ -121,7 +121,7 @@
<div
id="item-box"
class="box item-box"
title="_AddToBasket">
title="{{_('AddToBasket')}}">
<htk-image
directory="catalog"
subdir="200x200"
@ -131,34 +131,34 @@
full-dir="1600x900"/>
<div class="item-info">
<h2>
<htk-text form="item" column="item"/>
{{item.item}}
</h2>
<p class="sub-name">
<htk-text form="item" column="subName"/>
{{item.subName}}
</p>
<table class="tags">
<tr>
<td><htk-text form="item" column="tag5"/></td>
<td><htk-text form="item" column="value5"/></td>
<td>{{item.tag5}}</td>
<td>{{item.value5}}</td>
</tr>
<tr>
<td><htk-text form="item" column="tag6"/></td>
<td><htk-text form="item" column="value6"/></td>
<td>{{item.tag6}}</td>
<td>{{item.value6}}</td>
</tr>
<tr>
<td><htk-text form="item" column="tag7"/></td>
<td><htk-text form="item" column="value7"/></td>
<td>{{item.tag7}}</td>
<td>{{item.value7}}</td>
</tr>
</table>
<div class="available-price">
<span class="grouping" title="_MinimalGrouping">
<htk-text form="item" column="grouping" format="x%.0d"/>
{{Vn.Value.format(item.grouping, 'x%.0d')}}
</span>
<span class="available" title="_Available">
<htk-text form="item" column="available"/>
{{item.available}}
</span>
<span class="price" title="_GroupingPrice">
<htk-text form="item" column="price" format="%.2d€"/>
{{Vn.Value.format(item.price, 'x%.0d')}}
</span>
</div>
</div>
@ -185,7 +185,7 @@
<div class="realms">
<htk-repeater
model="realms-model"
form-id="realm-form"
form-id="form"
renderer="realmRenderer"
class="realms-box">
<db-model
@ -199,7 +199,11 @@
</db-model>
<custom>
<a id="link">
<img id="image"/>
<img
id="image"
src="{{`image/family/black/${form.code}.svg`}}"
title="{{form.name}}"
alt="{{form.name}}"/>
</a>
</custom>
</htk-repeater>

View File

@ -11,7 +11,7 @@ AddressQuestion: On vols rebre la comanda?
AddressQuestionPickup: A què direcció vols associar la comanda? (Opcional)
AgencyQuestion: Com vols rebre la comanda?
PickupWarehouseQuestion: En quin magatzem vols recollir la comanda?
ConfirmToAccessCatalog: Confirma les dades per accedir al catàleg
ConfirmData: Confirma les dades
Arrival: Arribada
Pickup: Recollida
Agency: Agència

View File

@ -11,7 +11,7 @@ AddressQuestion: Where do you want to receive the order?
AddressQuestionPickup: To which address do you want to associate the order? (Optional)
AgencyQuestion: How you want to receive the order?
PickupWarehouseQuestion: What store you want to pickup your order?
ConfirmToAccessCatalog: Confirm the data to access the catalog
ConfirmData: Confirm the data
Arrival: Arrival
Pickup: Pickup
Agency: Agency

View File

@ -11,7 +11,7 @@ AddressQuestion: ¿Dónde quieres recibir el pedido?
AddressQuestionPickup: ¿A qué dirección quieres asociar el pedido? (Opcional)
AgencyQuestion: ¿Cómo quieres recibir el pedido?
PickupWarehouseQuestion: ¿En qué almacén quieres recoger el pedido?
ConfirmToAccessCatalog: Confirma los datos para acceder al catálogo
ConfirmData: Confirma los datos
Arrival: Llegada
Pickup: Recogida
Agency: Agencia

View File

@ -11,7 +11,7 @@ AddressQuestion: Adresse livraison?
AddressQuestionPickup: À quelle adresse voulez-vous associer la commande? (Optionnel)
AgencyQuestion: Agence de livraison
PickupWarehouseQuestion: Dans quel magasin vuoulez-vous retirer votre commande?
ConfirmToAccessCatalog: Confirmez les coordonnées pour accéder au catalogue
ConfirmData: Confirmez les coordonnées
Arrival: Arrivée
Pickup: Retrait
Agency: Agence

View File

@ -11,7 +11,7 @@ AddressQuestion: Onde queres receber a encomenda?
AddressQuestionPickup: Para qual endereço deseja associar o pedido? (Opcional)
AgencyQuestion: Como queres receber a encomenda?
PickupWarehouseQuestion: Em qual armazém queres levantar a encomenda?
ConfirmToAccessCatalog: Confirme os dados para entrar no catálogo
ConfirmData: Confirme os dados
Arrival: Chegada
Pickup: Recolhida
Agency: Agência

View File

@ -16,7 +16,7 @@
.answers button,
.answers p,
.radio > div {
font-size: 1.4em;
font-size: 1.2em;
}
.answers .htk-select {
max-width: 10em;
@ -54,13 +54,9 @@
padding: 0.5em;
}
.thin-calendar {
width: inherit;
max-width: 24em;
margin: 0 auto;
box-shadow: .05em .05em .2em rgba(0, 0, 0, .2);
}
.thin-calendar tr > th {
color: white;
box-shadow: none;
}
.htk-assistant .thin {
float: right;

View File

@ -174,7 +174,7 @@
</htk-step>
<htk-step
name="confirm-delivery">
<h2><t>ConfirmToAccessCatalog</t></h2>
<h2><t>ConfirmData</t></h2>
<div class="answers target">
<p>
<t>Arrival</t>
@ -192,7 +192,7 @@
</htk-step>
<htk-step
name="confirm-pickup">
<h2><t>ConfirmToAccessCatalog</t></h2>
<h2><t>ConfirmData</t></h2>
<div class="answers target">
<p>
<t>Pickup</t>

View File

@ -1,72 +1,44 @@
.orders
{
.orders {
padding: 1em;
}
.orders .box
{
.orders .box {
max-width: 25em;
}
/* Balance */
.balance
{
.balance {
margin-right: .5em;
}
.balance > *
{
.balance > * {
vertical-align: middle;
}
.balance > .amount
{
.balance > .amount {
color: white;
padding: 0.3em;
}
.balance > .info
{
.balance > .info {
display: inline;
cursor: pointer;
height: 1.2em;
cursor: pointer;
}
.balance > .negative
{
.balance > .negative {
background-color: #EF5350;
border-radius: 0.1em;
box-shadow: 0 0 0.4em #666;
}
.balance-popup
{
.balance-popup {
width: 25em;
}
.balance-grid
{
.balance-grid {
width: 100%;
margin: auto;
}
/* List */
.orders .item
{
display: block;
padding: 1em;
border-bottom: 1px solid #DDD;
}
.orders .item:hover
{
background-color: rgba(1, 1, 1, 0.05);
}
.orders .item > p
{
margin: .1em 0;
}
.orders .item > p.important
{
font-size: 1.2em;
}
.orders .item > p.total
{
.orders .htk-list .total {
float: right;
}

View File

@ -39,30 +39,25 @@
</div>
<div id="form" class="orders">
<div class="box confirmed">
<htk-repeater form-id="iter" renderer="repeaterFunc">
<htk-repeater form-id="iter" renderer="repeaterFunc" class="htk-list">
<db-model property="model" id="tickets">
<custom>
CALL myTicket_list (NULL, NULL);
</custom>
</db-model>
<custom>
<a id="link" class="item" title="_SeeOrder">
<p class="important total">
<htk-text form="iter" column="total" format="%.2d€"/>
</p>
<p class="important">
<htk-text form="iter" column="landed" format="%D"/>
</p>
<p>
#<htk-text form="iter" column="id"/>
</p>
<p>
<htk-text form="iter" column="nickname"/>
</p>
<p>
<htk-text form="iter" column="agency"/>
</p>
<div class="clear"/>
<a id="link" class="item" title="{{_('SeeOrder')}}">
<div class="content">
<p class="important total">
{{Vn.Value.format(iter.total, '%.2d€')}}
</p>
<p class="important">
{{Vn.Value.format(iter.landed, '%D')}}
</p>
<p>#{{iter.id}}</p>
<p>{{iter.nickname}}</p>
<p>{{iter.agency}}</p>
</div>
</a>
</custom>
</htk-repeater>

View File

@ -1,4 +1,6 @@
OrderDetail: Detall de l'encarrec
ShippingInformation: Dades d'enviament
DeliveryAddress: Adreça de lliurament
Print delivery note: Imprimir albarà
Agency: Agència
Warehouse: Magatzem

View File

@ -1,4 +1,6 @@
OrderDetail: Order detail
ShippingInformation: Shipping information
DeliveryAddress: Delivery address
Print delivery note: Print delivery note
Agency: Agency
Warehouse: Store

View File

@ -1,4 +1,6 @@
OrderDetail: Detalle del pedido
ShippingInformation: Datos de envío
DeliveryAddress: Dirección de entrega
Print delivery note: Imprimir albarán
Agency: Agencia
Warehouse: Almacén

View File

@ -1,4 +1,6 @@
OrderDetail: Détails de la commande
ShippingInformation: Informations sur la livraison
DeliveryAddress: Addresse de livraison
Print delivery note: Imprimer bulletin de livraison
Agency: Agence
Warehouse: Entrepôt

View File

@ -1,4 +1,6 @@
OrderDetail: Detalhes da encomenda
ShippingInformation: Dados de envio
DeliveryAddress: Endereço de entrega
Print delivery note: Imprimir nota de entrega
Agency: Agência
Warehouse: Armazém

View File

@ -1,9 +1,7 @@
.ticket
{
.ticket {
padding: 1em;
}
.ticket .box
{
.ticket .box {
max-width: 30em;
margin: 0 auto;
padding: 2em;
@ -12,36 +10,29 @@
/* Header */
.ticket .head
{
.ticket .head {
padding: 0;
padding-bottom: .2em;
border-bottom: 1px solid #DDD;
margin-bottom: 1em;
}
.ticket .address,
.ticket .total
{
margin-top: .8em;
.ticket .head > div > div {
margin: 15px 0;
}
.ticket .head > div
{
padding-bottom: .8em;
.ticket .head > div > div:first-child {
margin: 0;
}
.ticket .head p
{
margin: .2em;
.ticket .head p {
margin: .2em 0;
}
.ticket .head p.important
{
font-size: 1.4em;
.ticket .head p.important {
font-size: 1.2rem;
font-weight: bold;
}
.ticket .total
{
.ticket .total {
text-align: right;
}
.ticket .packages
{
.ticket .packages {
margin-top: 1em;
padding-top: 1em;
border-top: 1px solid #DDD;
@ -50,47 +41,42 @@
/* Lines */
.ticket .line
{
padding: .5em 0;
.ticket .line {
display: flex;
gap: 20px;
margin: 24px 0;
height: 65px;
}
.ticket .line > .photo
{
margin-right: 1em;
float: left;
.ticket .line:last-child {
margin-bottom: 0;
}
.ticket .line > .photo {
flex: none;
border-radius: 50%;
height: 4.25em;
width: 4.25em;
width: 65px;
}
.ticket .line > .info
{
margin-left: 5.25em;
.ticket .line > .info {
flex: 1;
}
.ticket .line > .info > h2
{
.ticket .line > .info > h2 {
font-size: 1em;
font-weight: normal;
padding: 0;
padding-bottom: .1em;
}
.ticket .line > .info > p
{
.ticket .line > .info > p {
margin: 0;
}
.ticket .line > .info > .tags
{
.ticket .line > .info > .tags {
color: #777;
}
.ticket .line > .info .discount
{
.ticket .line > .info .discount {
color: green;
}
.ticket .line > .info > .amount
{
.ticket .line > .info > .amount {
float: left;
}
.ticket .line > .info > .subtotal
{
.ticket .line > .info > .subtotal {
float: right;
}

View File

@ -29,6 +29,9 @@
<p class="important ticket-id">
#<htk-text column="id" form="ticket"/>
</p>
</div>
<div>
<h3><t>ShippingInformation</t></h3>
<p>
<t>Preparation</t> <htk-text form="ticket" column="shipped" format="%D"/>
</p>
@ -40,6 +43,7 @@
</p>
</div>
<div class="address">
<h3><t>DeliveryAddress</t></h3>
<p>
<htk-text form="ticket" column="nickname"/>
</p>
@ -101,7 +105,6 @@
<htk-text id="subtotal" format="%.2d€"/>
</p>
</div>
<div class="clear"/>
</div>
</custom>
</htk-repeater>

View File

@ -43,15 +43,10 @@
editable="true"
conn="conn"/>
<p class="important">
<htk-text form="iter" column="title"/>
</p>
<p>
<htk-text form="iter" column="nickname"/>
</p>
<p>
<t>Priority</t>
<htk-text form="iter" column="priority"/>
{{iter.title}}
</p>
<p>{{iter.nickname}}</p>
<p>{{iter.priority}}</p>
</div>
</custom>
</htk-repeater>

View File

@ -1,36 +1,30 @@
var Model = require ('./model');
var Model = require('./model');
module.exports = new Class
({
Properties:
{
module.exports = new Class({
Properties: {
/**
* The model associated to this form.
**/
model:
{
*/
model: {
type: Model
},
/**
* The row where the form positioned, has -1 if the row is unselected.
**/
row:
{
*/
row: {
type: Number
},
/**
* The number of rows in the form.
**/
numRows:
{
*/
numRows: {
type: Number
},
/**
* Checks if the form data is ready.
**/
ready:
{
*/
ready: {
type: Boolean
}
}
@ -38,18 +32,16 @@ module.exports = new Class
,_model: null
,_row: -1
,refresh: function ()
{
,refresh: function() {
if (this._model)
this._model.refresh ();
this._model.refresh();
}
/**
* Emits the 'iter-changed' signal on the form.
**/
,iterChanged: function ()
{
this.signalEmit ('iter-changed');
*/
,iterChanged: function() {
this.signalEmit('iter-changed');
}
/**
@ -57,45 +49,49 @@ module.exports = new Class
*
* @param {String} columnName The column name
* @return {integer} The column index or -1 if column not exists
**/
,getColumnIndex: function (columnName)
{
*/
,getColumnIndex: function(columnName) {
if (this._model)
return this._model.getColumnIndex (columnName);
return this._model.getColumnIndex(columnName);
return -1;
}
,insertRow: function ()
{
,insertRow: function() {
if (this._model)
this.row = this._model.insertRow ();
this.row = this._model.insertRow();
}
,performOperations: function ()
{
,performOperations: function() {
if (this._model)
this._model.performOperations ();
this._model.performOperations();
}
/**
* Removes the current row.
**/
,deleteRow: function ()
{
*/
,deleteRow: function() {
if (this._row >= 0)
this._model.deleteRow (this._row);
this._model.deleteRow(this._row);
}
/**
* Gets the row as object.
*
* @return {Object} The row
*/
,getObject: function() {
return this._model.getObject(this._row);
}
/**
* Gets a value from the form.
*
* @param {String} columnName The column name
* @return {Object} The value
**/
,get: function (columnName)
{
return this._model.get (this._row, columnName);
*/
,get: function(columnName) {
return this._model.get(this._row, columnName);
}
/**
@ -103,10 +99,9 @@ module.exports = new Class
*
* @param {String} columnName The column name
* @param {Object} value The new value
**/
,set: function (columnName, value)
{
return this._model.set (this._row, columnName, value);
*/
,set: function(columnName, value) {
return this._model.set(this._row, columnName, value);
}
/**
@ -114,10 +109,9 @@ module.exports = new Class
*
* @param {String} columnName The column index
* @return {Object} The value
**/
,getByIndex: function (column)
{
return this._model.getByIndex (this._row, column);
*/
,getByIndex: function(column) {
return this._model.getByIndex(this._row, column);
}
/**
@ -125,10 +119,9 @@ module.exports = new Class
*
* @param {String} columnName The column index
* @param {Object} value The new value
**/
,setByIndex: function (column, value)
{
return this._model.setByIndex (this._row, column, value);
*/
,setByIndex: function(column, value) {
return this._model.setByIndex(this._row, column, value);
}
});

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,14 @@ var Result = require('./result');
/**
* This class stores the database results.
**/
*/
module.exports = new Class({
results: null
,error: null
/**
* Initilizes the resultset object.
**/
*/
,initialize: function(results, error) {
this.results = results;
this.error = error;
@ -20,7 +20,7 @@ module.exports = new Class({
* Gets the query error.
*
* @return {Db.Err} the error or null if no errors hapened
**/
*/
,getError: function() {
return this.error;
}
@ -40,7 +40,7 @@ module.exports = new Class({
* Fetchs the next result from the resultset.
*
* @return {Db.Result} the result or %null if error or there are no more results
**/
*/
,fetchResult: function() {
var result = this.fetch();
@ -53,12 +53,12 @@ module.exports = new Class({
return null;
}
/**
* Fetchs the first row from the next resultset.
*
* @return {Array} the row if success, %null otherwise
**/
*/
,fetchRow: function() {
var result = this.fetch();
@ -70,6 +70,11 @@ module.exports = new Class({
return null;
}
/**
* Fetchs the first row object from the next resultset.
*
* @return {Array} the row if success, %null otherwise
*/
,fetchObject: function() {
var result = this.fetch();
@ -90,7 +95,7 @@ module.exports = new Class({
* Fetchs the first row and column value from the next resultset.
*
* @return {Object} the value if success, %null otherwise
**/
*/
,fetchValue: function() {
var row = this.fetchRow();

View File

@ -1,54 +1,44 @@
var Iterator = require ('./iterator');
var Model = require ('./model');
var Iterator = require('./iterator');
var Model = require('./model');
/**
* A light iterator for models.
**/
module.exports = new Class
({
*/
module.exports = new Class({
Extends: Vn.Object
,Implements: Iterator
,Properties:
{
,Properties: {
/**
* The model associated to this form.
**/
model:
{
*/
model: {
type: Model
,set: function (x)
{
,set: function(x) {
this._model = x;
}
,get: function ()
{
,get: function() {
return this._model;
}
},
/**
* The row where the form positioned, has -1 if the row is unselected.
**/
row:
{
*/
row: {
type: Number
,set: function (x)
{
,set: function(x) {
this._row = x;
}
,get: function ()
{
,get: function() {
return this._row;
}
},
/**
* The number of rows in the form.
**/
numRows:
{
*/
numRows: {
type: Number
,get: function ()
{
,get: function() {
if (this._model)
return this._model.numRows;
@ -57,12 +47,10 @@ module.exports = new Class
},
/**
* Checks if the form data is ready.
**/
ready:
{
*/
ready: {
type: Boolean
,get: function ()
{
,get: function() {
if (this._model)
return this._model.ready;

View File

@ -6,8 +6,7 @@ module.exports = new Class
,isOpen: false
,uiLoaded: false
,initialize: function (gui, formInfo)
{
,initialize: function(gui, formInfo) {
this.gui = gui;
this.conn = gui.conn;
this.hash = gui.hash;
@ -19,107 +18,98 @@ module.exports = new Class
*
* @param {string} objectId The object identifier
* @return {Object} The object, or %null if not found
**/
,$: function (objectId)
{
*/
,$: function(objectId) {
if (this.builder)
return this.builder.getById (objectId);
return this.builder.getById(objectId);
return null;
}
,loadUi: function ()
{
,loadUi: function() {
if (!this.isOpen)
return;
var builder = new Vn.Builder ();
var builder = new Vn.Builder();
builder.signalData = this;
builder.add ('conn', this.conn);
builder.loadXml ('forms/'+ this.formInfo.path +'/ui.xml');
builder.add('conn', this.conn);
builder.loadXml('forms/'+ this.formInfo.path +'/ui.xml');
var res = this.builder = builder.load ();
var res = this.builder = builder.load();
this.node = res.$('form');
res.link ();
res.link(this);
var models = res.getByTagName ('db-model');
var models = res.getByTagName('db-model');
for (var i = 0; i < models.length; i++)
models[i].conn = this.conn;
var queries = res.getByTagName ('db-query');
var queries = res.getByTagName('db-query');
for (var i = 0; i < queries.length; i++)
queries[i].conn = this.conn;
if (this.node)
{
this.gui.setForm (this.node);
this.gui.setTitle (res.$('title'));
this.gui.setActions (res.$('actions'));
this.activate ();
if (this.node) {
this.gui.setForm(this.node);
this.gui.setTitle(res.$('title'));
this.gui.setActions(res.$('actions'));
this.activate();
}
this.uiLoaded = true;
}
,unloadUi: function ()
{
,unloadUi: function() {
if (!this.uiLoaded)
return;
if (this.node)
{
this.deactivate ();
this.gui.setTitle (null);
this.gui.setActions (null);
Vn.Node.remove (this.node);
this.deactivate ();
if (this.node) {
this.deactivate();
this.gui.setTitle(null);
this.gui.setActions(null);
Vn.Node.remove(this.node);
this.deactivate();
this.node = null;
}
if (this.builder)
{
this.builder.unref ();
if (this.builder) {
this.builder.unref();
this.builder = null;
}
}
/**
* Called when the form is opened.
**/
,open: function ()
{
this.close ();
*/
,open: function() {
this.close();
this.isOpen = true;
this.loadUi ();
this.loadUi();
}
/**
* Called when the form is closed.
**/
,close: function ()
{
*/
,close: function() {
if (!this.isOpen)
return;
this.isOpen = false;
this.unloadUi ();
this.unloadUi();
}
/**
* Called when the form is activated.
**/
,activate: function () {}
*/
,activate: function() {}
/**
* Called when the form is deactivated.
**/
,deactivate: function () {}
*/
,deactivate: function() {}
,_destroy: function ()
{
this.close ();
this.parent ();
,_destroy: function() {
this.close();
this.parent();
}
});

View File

@ -64,25 +64,28 @@
padding: 0;
margin: 0;
height: 100%;
}
.action-bar > div {
padding: 0;
margin: 0;
height: 100%;
display: flex;
align-items: center;
padding: 0 1em;
gap: .5em;
}
.action-bar > div > * {
float: right;
}
.action-bar button {
margin: 0;
padding: .6em;
}
.action-bar button:hover {
background-color: rgba(2550, 255, 255, .2);
& > div {
padding: 0;
margin: 0;
height: 100%;
display: flex;
align-items: center;
padding: 0 1em;
gap: .5em;
& > * {
float: right;
}
}
button {
margin: 0;
padding: 10px 15px;
&:hover {
background-color: rgba(2550, 255, 255, .2);
}
}
}
/* Background */
@ -277,9 +280,14 @@
/* Mobile */
@media (max-width: 960px) {
.action-bar span.label,
.htk-button > .text {
display: none;
.action-bar {
span.label,
.htk-button > .text {
display: none;
}
.htk-button {
padding: 10px;
}
}
& > .navbar {
padding-left: 2.8em;

BIN
js/hedera/opensans.ttf Normal file

Binary file not shown.

View File

@ -1,8 +1,14 @@
@import "../htk/style/classes";
@font-face {
font-family: 'Poppins';
src: url('poppins.ttf') format('truetype');
}
@font-face {
font-family: 'Open Sans';
src: url('opensans.ttf') format('truetype');
}
/* Global */
@ -243,12 +249,6 @@ img.editable {
cursor: pointer;
}
/* Button */
.htk-button img {
height: 1.5em;
}
/* Float */
.clear {
@ -258,11 +258,8 @@ img.editable {
/* Box */
.box {
background-color: white;
@extend %box;
margin: 0 auto;
border-radius: .6em;
box-shadow: .05em .05em .2em rgba(0, 0, 0, .1);
overflow: hidden;
}
.box .header {
padding: 0.6em 0.8em;

View File

@ -1,8 +1,7 @@
var Button = require('./button');
module.exports = new Class
({
module.exports = new Class({
Extends: Button
,Tag: 'htk-bar-button'

View File

@ -7,13 +7,13 @@ module.exports = new Class({
image: {
type: String
,set: function(x) {
this.span.innerText = x;
this.iconNode.name = x;
}
},
icon: {
type: String
,set: function(x) {
this.span.innerText = x;
this.iconNode.name = x;
}
},
tip: {
@ -21,7 +21,7 @@ module.exports = new Class({
,set: function(x) {
if (x) {
this.node.title = _(x);
this.span.title = _(x);
this.iconNode.title = _(x);
}
this.renderContent();
@ -49,9 +49,8 @@ module.exports = new Class({
node.className = 'htk-button';
node.addEventListener('click', this.onClick.bind(this));
this.span = this.createElement('span');
this.span.className = 'material-symbols-rounded icon';
node.appendChild(this.span);
this.iconNode = new Htk.Icon();
node.appendChild(this.iconNode.node);
}
,renderContent: function() {

View File

@ -43,12 +43,17 @@ module.exports = new Class({
thead.appendChild(tr);
var th = this.createElement('th');
th.appendChild(this.createTextNode('<'));
th.className = 'button';
th.addEventListener('click', this.prevMonthClicked.bind(this));
th.className = 'previous';
tr.appendChild(th);
var previousButton = new Htk.Button({
icon: 'arrow_back_ios'
}).node;
previousButton.addEventListener('click', this.prevMonthClicked.bind(this));
th.appendChild(previousButton);
var th = this.createElement('th');
th.className = 'month-year';
th.colSpan = 5;
tr.appendChild(th);
@ -62,12 +67,17 @@ module.exports = new Class({
th.appendChild(yearNode);
var th = this.createElement('th');
th.appendChild(this.createTextNode('>'));
th.className = 'button';
th.addEventListener('click', this.nextMonthClicked.bind(this));
th.className = 'next';
tr.appendChild(th);
var nextButton = new Htk.Button({
icon: 'arrow_forward_ios'
}).node;
nextButton.addEventListener('click', this.nextMonthClicked.bind(this));
th.appendChild(nextButton);
var tr = this.createElement('tr');
tr.className = 'weekdays';
thead.appendChild(tr);
for (var i = 1; i <= len; i++) {

View File

@ -4,13 +4,11 @@ module.exports = new Class
Extends: Htk.Field
,Tag: 'htk-html'
,render: function ()
{
this.createRoot ('div');
,render: function() {
this.createRoot('div');
}
,putValue: function (value)
{
,putValue: function(value) {
this.node.innerHTML = value;
}
});

View File

@ -1,6 +1,7 @@
require('db/db');
require('./style.scss');
require('./style/classes.scss');
require('./style/main.scss');
Htk = module.exports = {
NodeBuilder : require('./node-builder')

View File

@ -42,7 +42,7 @@ module.exports = new Class({
,render: function() {
const node = this.createRoot('span');
node.className = 'material-symbols-rounded icon';
node.className = 'htk-icon material-symbols-rounded';
}
,_setIcon: function() {

View File

@ -96,7 +96,7 @@ module.exports = new Class({
var builder = this._builder = new Vn.Builder();
builder.setParent(builderResult);
builder.loadXmlFromNode(node.firstElementChild);
builder.loadXmlFromNode(node.firstElementChild, null, [this._formId]);
this._onModelChange();
}
@ -121,7 +121,7 @@ module.exports = new Class({
this._builder.add(this._formId, set);
var res = this._builder.load();
res.link();
res.link(null, [set.getObject()]);
this._childsData.push({
builder: res,

20
js/htk/style/classes.scss Normal file
View File

@ -0,0 +1,20 @@
@import "variables";
%box {
border-radius: .6em;
box-shadow: .05em .05em .2em rgba(0, 0, 0, .1);
overflow: hidden;
border: none;
background-color: white;
}
%clickable {
cursor: pointer;
transition: background-color 250ms ease-out;
&:hover,
&:focus {
background-color: $color-hover-cd;
outline: none;
}
}

View File

@ -1,4 +1,7 @@
@import "variables";
@import "classes";
/* Grid */
.htk-grid {
@ -156,8 +159,64 @@ td.cell-image .htk-image {
.htk-select-menu td {
max-width: 11em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Icon */
.htk-icon {}
/* List */
.htk-list {
.item {
@extend %clickable;
padding: 20px;
border-bottom: 1px solid #DDD;
display: flex;
align-items: center;
&:hover {
background-color: rgba(1, 1, 1, 0.05);
}
& > .side {
flex: none;
}
& > .content {
flex: 1;
& > .important {
font-weight: bold;
font-size: 1rem;
margin-bottom: .5em;
}
& > p {
margin: .1em 0;
}
}
& > .actions {
flex: none;
display: none;
& > .htk-button {
margin: 0;
}
& > * {
display: inline-block;
vertical-align: middle;
}
& > input {
margin: .6em;
}
}
}
.item:hover > .actions {
display: block;
}
.item:last-child {
border-bottom: none;
}
}
/* Button */
@ -165,12 +224,12 @@ td.cell-image .htk-image {
.htk-button {
display: flex;
align-items: center;
border-radius: 2em;
border-radius: 22px;
font-weight: bold;
gap: .5em;
padding: 0 .5em;
gap: 8px;
padding: 0 10px;
& > span.icon {
& > .htk-icon {
display: block;
}
}
@ -178,73 +237,91 @@ td.cell-image .htk-image {
/* Calendar */
.htk-calendar {
@extend %box;
width: 20em;
background-color: white;
border: none;
border-radius: .5em;
}
.htk-calendar table {
border-collapse: collapse;
}
.htk-calendar thead tr,
.htk-calendar tfoot tr {
background-color: #888;
color: white;
font-weight: normal;
vertical-align: middle;
text-align: center;
height: 3em;
}
.htk-calendar thead span {
color: white;
}
.htk-calendar thead tr {
border-bottom: none;
}
.htk-calendar tfoot tr {
border-top: none;
}
.htk-calendar th.button {
display: table-cell;
}
.htk-calendar th.button:hover {
cursor: pointer;
background-color: rgba(1, 1, 1, 0.2);
}
.htk-calendar col {
width: 14.2%;
}
.htk-calendar tr {
height: 2em;
}
.htk-calendar tbody td {
text-align: right;
}
.htk-calendar tbody td > div {
height: 2em;
width: 2em;
line-height: 2em;
text-align: center;
border-radius: 2em;
padding: 0.3em;
margin: 0 auto;
color: #555;
}
.htk-calendar div.disabled {
color: #999;
}
.htk-calendar div.today {
font-weight: bold;
color: black;
}
.htk-calendar div.selected {
color: white;
background-color: #8cc63f;
}
.htk-calendar div.enabled:hover {
cursor: pointer;
background-color: rgba(140, 198, 63, 0.8);
color: white;
table {
border-collapse: collapse;
}
thead tr,
tfoot tr {
font-weight: normal;
vertical-align: middle;
text-align: center;
height: 3em;
}
thead > tr {
&.weekdays > th {
font-weight: normal;
color: #999;
text-transform: lowercase;
}
& > th {
&.previous, &.next {
font-size: .8rem;
button {
border-radius: 50%;
padding: 10px;
display: block;
margin: 0 auto;
& > .htk-icon {
font-size: 1rem;
}
}
}
&.month-year {
font-size: 1.2rem;
text-transform: lowercase;
}
}
}
tfoot tr {
border-top: none;
}
th.button {
display: table-cell;
}
th.button:hover {
cursor: pointer;
background-color: rgba(1, 1, 1, 0.2);
}
col {
width: 14.2%;
}
tr {
height: 2em;
}
tbody td {
text-align: right;
}
tbody td > div {
height: 2em;
width: 2em;
line-height: 2em;
text-align: center;
border-radius: 2em;
padding: 0.3em;
margin: 0 auto;
color: #555;
}
div.disabled {
color: #bbb;
}
div.today {
font-weight: bold;
color: black;
}
div.selected {
color: white;
background-color: #8cc63f;
}
div.enabled:hover {
cursor: pointer;
background-color: rgba(140, 198, 63, 0.8);
color: white;
}
}
/* Image */
@ -439,7 +516,7 @@ td.cell-image .htk-image {
& > h2 {
text-align: center;
font-weight: normal;
font-size: 1.5em;
font-size: 1.5rem;
margin: 0;
padding: 0;
margin-bottom: 1em;

View File

@ -0,0 +1,2 @@
$color-hover-cd: rgba(255, 255, 255, .1);

View File

@ -1,35 +1,30 @@
var Object = require ('./object');
var Object = require('./object');
/**
* Creates a object from a XML specification.
**/
module.exports = new Class
({
*/
module.exports = new Class({
Extends: Object
,_addedMap: {}
,_contexts: null
,add: function (id, object)
{
,add: function(id, object) {
this._addedMap[id] = object;
}
,setParent: function (parentResult)
{
,setParent: function(parentResult) {
this._parentResult = parentResult;
if (parentResult && !this.signalData)
this.signalData = parentResult.builder.signalData;
}
,getMain: function (result)
{
,getMain: function(result) {
return result.objects[this._mainContext];
}
,getById: function (result, objectId)
{
,getById: function(result, objectId) {
var index = this._contextMap[objectId];
if (index !== undefined)
@ -41,18 +36,16 @@ module.exports = new Class
return object;
if (this._parentResult)
return this._parentResult.getById (objectId);
return this._parentResult.getById(objectId);
return null;
}
,getByTagName: function (result, tagName)
{
,getByTagName: function(result, tagName) {
var tags = this._tags[tagName];
if (tags)
{
var arr = new Array (tags.length);
if (tags) {
var arr = new Array(tags.length);
for (var i = 0; i < tags.length; i++)
arr[i] = result.objects[tags[i]];
@ -69,32 +62,28 @@ module.exports = new Class
* @path String The XML path
* @dstDocument Document The document used to create the nodes
* @return %true on success, %false othersise
**/
,loadXml: function (path, dstDocument)
{
*/
,loadXml: function(path, dstDocument) {
this._path = path;
return this.loadFromXmlDoc (Vn.getXml (path), dstDocument);
return this.loadFromXmlDoc(Vn.getXml(path), dstDocument);
}
,loadFromString: function (xmlString, dstDocument)
{
var parser = new DOMParser ();
var xmlDoc = parser.parseFromString (xmlString, 'text/xml');
return this.loadFromXmlDoc (xmlDoc, dstDocument);
,loadFromString: function(xmlString, dstDocument) {
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlString, 'text/xml');
return this.loadFromXmlDoc(xmlDoc, dstDocument);
}
,loadFromXmlDoc: function (xmlDoc, dstDocument)
{
,loadFromXmlDoc: function(xmlDoc, dstDocument, scope) {
if (!xmlDoc)
return false;
this._compileInit (dstDocument);
this._compileInit(dstDocument, scope);
var docElement = xmlDoc.documentElement;
if (docElement.tagName !== 'vn')
{
this._showError ('Malformed XML');
if (docElement.tagName !== 'vn') {
this._showError('Malformed XML');
this._contexts = null;
return false;
}
@ -103,9 +92,9 @@ module.exports = new Class
if (childs)
for (var i = 0; i < childs.length; i++)
this._compileNode (childs[i]);
this._compileNode(childs[i]);
this._compileEnd ();
this._compileEnd();
return true;
}
@ -115,75 +104,130 @@ module.exports = new Class
* @path Node The DOM node
* @dstDocument Document The document used to create the nodes
* @return %true on success, %false othersise
**/
,loadXmlFromNode: function (node, dstDocument)
{
this._compileInit (dstDocument);
this._mainContext = this._compileNode (node).id;
this._compileEnd ();
*/
,loadXmlFromNode: function(node, dstDocument, scope) {
this._compileInit(dstDocument, scope);
this._mainContext = this._compileNode(node).id;
this._compileEnd();
return true;
}
,load: function ()
{
,load: function() {
if (this._contexts === null)
return null;
var contexts = this._contexts;
var len = contexts.length;
var objects = new Array (len);
var objects = new Array(len);
for (var i = 0; i < len; i++)
{
for (var i = 0; i < len; i++) {
var context = contexts[i];
if (context.tagName)
objects[i] = this.elementInstantiate (context);
objects[i] = this.elementInstantiate(context);
else if (context.klass)
objects[i] = this.objectInstantiate (context);
objects[i] = this.objectInstantiate(context);
else
objects[i] = this.textInstantiate (context);
objects[i] = this.textInstantiate(context);
}
return new BuilderResult (this, objects);
return new BuilderResult(this, objects);
}
,link: function (result)
{
,link: function(result, self, scope) {
var objects = result.objects;
for (var i = this._links.length - 1; i >= 0; i--)
{
for (var i = this._links.length - 1; i >= 0; i--) {
var l = this._links[i];
var addedObject = this._addedMap[l.objectId];
if (addedObject)
{
if (addedObject) {
if (l.prop)
objects[l.context.id][l.prop] = addedObject;
else
objects[l.context.id].appendChild (addedObject);
}
else
this._showError ('Referenced unexistent object with id \'%s\'',
objects[l.context.id].appendChild(addedObject);
} else
this._showError('Referenced unexistent object with id \'%s\'',
l.objectId);
}
this.linkExpr(result, self, scope);
var contexts = this._contexts;
for (var i = 0; i < contexts.length; i++)
{
for (var i = 0; i < contexts.length; i++) {
var context = contexts[i];
var object = objects[i];
if (context.tagName)
this.elementLink (context, object, objects, result);
this.elementLink(context, object, objects, result);
else if (context.klass)
this.objectLink (context, object, objects, result);
this.objectLink(context, object, objects, result);
}
}
,fnExpr(expr) {
return new Function(this._scopeArgs,
'"use strict"; return ' + expr + ';'
);
}
,_compileInit: function (dstDocument)
{
,matchExpr(value) {
const match = /^{{(.*)}}$/.exec(value);
if (!match) return null;
return this.fnExpr(match[1]);
}
,linkExpr(result, self, scope) {
const contexts = this._contexts;
const objects = result.objects;
let args = [_]
if (scope) args = args.concat(scope);
for (let i = 0; i < contexts.length; i++) {
const context = contexts[i];
const object = objects[i];
if (context.exprs) {
const values = [];
for (expr of context.exprs) {
let value = undefined;
try {
value = expr.apply(self, args);
} catch (e) {
console.warn('Expression error:', e.message);
continue;
}
values.push(value);
}
let k = 0;
const text = context.text.replace(/{{\d+}}/g, function() {
return values[k++];
});
object.textContent = text;
} else {
const dynProps = context.dynProps;
for (const prop in dynProps) {
let value = undefined;
try {
value = dynProps[prop].apply(self, args);
} catch (e) {
console.warn('Expression error:', e.message);
continue;
}
if (context.tagName)
object.setAttribute(prop, value);
else
object[prop] = value;
}
}
}
}
,_compileInit: function(dstDocument, scope) {
this._path = null;
this._tags = {};
this._contexts = [];
@ -191,61 +235,58 @@ module.exports = new Class
this._links = [];
this._mainContext = null;
this._doc = dstDocument ? dstDocument : document;
this._scope = ['_'];
if (scope)
this._scope = this._scope.concat(scope);
this._scopeArgs = this._scope.join(',');
}
,_compileEnd: function ()
{
for (var i = this._links.length - 1; i >= 0; i--)
{
,_compileEnd: function() {
for (var i = this._links.length - 1; i >= 0; i--) {
var l = this._links[i];
var contextId = this._contextMap[l.objectId];
if (contextId != undefined)
{
if (contextId != undefined) {
if (l.prop)
l.context.objectProps[l.prop] = contextId;
else
l.context.childs.push (contextId);
l.context.childs.push(contextId);
this._links.splice (i, 1);
}
else
{
this._links.splice(i, 1);
} else {
var object = this._addedMap[l.objectId];
if (!object && this._parentResult)
object = this._parentResult.getById (l.objectId);
object = this._parentResult.getById(l.objectId);
if (object)
{
if (object) {
l.context.props[l.prop] = object;
this._links.splice (i, 1);
this._links.splice(i, 1);
}
}
}
}
,_compileNode: function (node)
{
,_compileNode: function(node) {
var context = null;
var tagName = null;
if (node.nodeType === Node.ELEMENT_NODE)
tagName = node.tagName.toLowerCase ();
tagName = node.tagName.toLowerCase();
else if (node.nodeType !== Node.TEXT_NODE
|| /^[\n\r\t]*$/.test (node.textContent))
|| /^[\n\r\t]*$/.test(node.textContent))
return null;
var context =
this.textCompile (node, tagName)
|| this.objectCompile (node, tagName)
|| this.elementCompile (node, tagName);
this.textCompile(node, tagName)
|| this.objectCompile(node, tagName)
|| this.elementCompile(node, tagName);
context.id = this._contexts.length;
if (tagName)
{
var nodeId = node.getAttribute ('id');
if (tagName) {
var nodeId = node.getAttribute('id');
if (nodeId)
this._contextMap[nodeId] = context.id;
@ -255,44 +296,53 @@ module.exports = new Class
if (!tags)
this._tags[tagName] = tags = [];
tags.push (context.id);
tags.push(context.id);
}
this._contexts.push (context);
this._contexts.push(context);
return context;
}
/**
* Creates a text node context.
**/
,textCompile: function (node, tagName)
{
if (!tagName)
var text = node.textContent;
else if (tagName === 't')
var text = _(node.firstChild.textContent);
*/
,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;
return {text: text};
}
,textInstantiate: function (context)
{
return this._doc.createTextNode (context.text);
,textInstantiate: function(context) {
return this._doc.createTextNode(context.exprs ? '' : context.text);
}
/**
* Creates a object context.
**/
,objectCompile: function (node, tagName)
{
*/
,objectCompile: function(node, tagName) {
var klass = vnCustomTags[tagName];
if (!klass)
return null;
var props = {};
var dynProps = {};
var objectProps = {};
var childs = [];
var events = {};
@ -300,6 +350,7 @@ module.exports = new Class
var context = {
klass: klass,
props: props,
dynProps: dynProps,
objectProps: objectProps,
childs: childs,
events: events,
@ -308,21 +359,17 @@ module.exports = new Class
var a = node.attributes;
for (var i = 0; i < a.length; i++)
{
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 (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,
events[attribute.substr(3)] = handler;
} else if (!/^(id|property)$/.test(attribute)) {
this.propCompile(context, klass, props, dynProps,
node, attribute, value);
}
}
@ -330,97 +377,89 @@ module.exports = new Class
var childNodes = node.childNodes;
if (childNodes)
for (var i = 0; i < childNodes.length; i++)
{
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 childTagName = isElement ? child.tagName.toLowerCase() : null;
var childContext;
if (childTagName === 'pointer')
{
this._addLink (context, null, child.getAttribute ('object'));
}
else if (childTagName === 'custom')
{
if (childTagName === 'pointer') {
this._addLink(context, null, child.getAttribute('object'));
} else if (childTagName === 'custom') {
context.custom = child;
}
else if (childContext = this._compileNode (child))
{
var prop = isElement ? child.getAttribute ('property') : null;
} else if (childContext = this._compileNode(child)) {
var prop = isElement ? child.getAttribute('property') : null;
if (prop)
{
prop = prop.replace (/-./g, this._replaceFunc);
if (prop) {
prop = prop.replace(/-./g, this._replaceFunc);
objectProps[prop] = childContext.id;
}
else
childs.push (childContext.id);
} else
childs.push(childContext.id);
}
}
return context;
}
,propCompile: function (context, klass, props, node, attribute, value)
{
,propCompile: function(context, klass, props, dynProps, node, attribute, value) {
var isLink = false;
var newValue = null;
var propName = attribute.replace (/-./g, this._replaceFunc);
var propName = attribute.replace(/-./g, this._replaceFunc);
var propInfo = klass.Properties[propName];
if (!propInfo)
{
this._showError ('Attribute \'%s\' not valid for tag \'%s\'',
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\'',
if (!value) {
this._showError('Attribute \'%s\' empty on tag \'%s\'',
attribute, node.tagName);
return;
}
switch (propInfo.type)
{
const expr = this.matchExpr(value);
if (expr) {
dynProps[propName] = expr;
} else {
switch (propInfo.type) {
case Boolean:
newValue = (/^(true|1)$/i).test (value);
newValue = (/^(true|1)$/i).test(value);
break;
case Number:
newValue = 0 + new Number (value);
newValue = 0 + new Number(value);
break;
case String:
newValue = this._translateValue (value);
newValue = this._translateValue(value);
break;
case Function:
var method = this._getMethod (value);
newValue = method ? method.bind (this.signalData) : null;
var method = this._getMethod(value);
newValue = method ? method.bind(this.signalData) : null;
break;
default:
if (propInfo.enumType)
newValue = propInfo.enumType[value];
else if (propInfo.type instanceof Function)
isLink = true;
}
if (isLink)
this._addLink(context, propName, value);
else if (newValue !== null && newValue !== undefined)
props[propName] = newValue;
else
this._showError('Attribute \'%s\' invalid for tag \'%s\'',
attribute, node.tagName);
}
if (isLink)
this._addLink (context, propName, value);
else if (newValue !== null && newValue !== undefined)
props[propName] = newValue;
else
this._showError ('Attribute \'%s\' invalid for tag \'%s\'',
attribute, node.tagName);
}
,objectInstantiate: function (context)
{
return new context.klass ();
,objectInstantiate: function(context) {
return new context.klass();
}
,objectLink: function (context, object, objects, res)
{
object.setProperties (context.props);
,objectLink: function(context, object, objects, res) {
object.setProperties(context.props);
var objectProps = context.objectProps;
for (var prop in objectProps)
@ -428,42 +467,42 @@ module.exports = new Class
var childs = context.childs;
for (var i = 0; i < childs.length; i++)
object.appendChild (objects[childs[i]]);
object.appendChild(objects[childs[i]]);
var events = context.events;
for (var event in events)
object.on (event, events[event], this.signalData);
object.on(event, events[event], this.signalData);
if (context.custom)
object.loadXml (res, context.custom);
object.loadXml(res, context.custom);
}
/**
* Creates a HTML node context.
**/
,elementCompile: function (node, tagName)
{
*/
,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++)
{
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);
const expr = this.matchExpr(value);
if (expr) {
dynProps[attribute] = expr;
} else if (this._isEvent(attribute)) {
var handler = this._getMethod(value);
if (handler)
events[attribute.substr (3)] = handler;
}
else if (attribute !== 'id')
attributes[attribute] = this._translateValue (value);
events[attribute.substr(3)] = handler;
} else if (attribute !== 'id')
attributes[attribute] = this._translateValue(value);
}
var childContext;
@ -471,145 +510,129 @@ module.exports = new Class
if (childNodes)
for (var i = 0; i < childNodes.length; i++)
if (childContext = this._compileNode (childNodes[i]))
childs.push (childContext.id);
if (childContext = this._compileNode(childNodes[i]))
childs.push(childContext.id);
return {
tagName: tagName,
attributes: attributes,
childs: childs,
events: events
tagName,
attributes,
dynProps,
childs,
events
};
}
,elementInstantiate: function (context)
{
return this._doc.createElement (context.tagName);
,elementInstantiate: function(context) {
return this._doc.createElement(context.tagName);
}
,elementLink: function (context, object, objects)
{
,elementLink: function(context, object, objects) {
var attributes = context.attributes;
for (var attribute in attributes)
object.setAttribute (attribute, attributes[attribute]);
object.setAttribute(attribute, attributes[attribute]);
var childs = context.childs;
for (var i = 0; i < childs.length; i++)
{
for (var i = 0; i < childs.length; i++) {
var child = objects[childs[i]];
if (child instanceof Htk.Widget)
child = child.node;
if (child instanceof Node)
object.appendChild (child);
object.appendChild(child);
}
var events = context.events;
for (var event in events)
object.addEventListener (event,
events[event].bind (this.signalData));
object.addEventListener(event,
events[event].bind(this.signalData));
}
,_showError: function (error)
{
,_showError: function(error) {
var path = this._path ? this._path : 'Node';
var logArgs = ['Vn.Builder: %s: '+ error, path];
for (var i = 1; i < arguments.length; i++)
logArgs.push (arguments[i]);
logArgs.push(arguments[i]);
console.warn.apply (null, logArgs);
console.warn.apply(null, logArgs);
}
,_addLink: function (context, prop, objectId)
{
this._links.push ({
,_addLink: function(context, prop, objectId) {
this._links.push({
context: context
,prop: prop
,objectId: objectId
});
}
,_translateValue: function (value)
{
var chr = value.charAt (0);
,_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.substr(1));
else if (chr === '\\' && value.charAt(1) === '_')
return value.substr(1);
return value;
}
,_getMethod: function (value)
{
,_getMethod: function(value) {
if (this.signalData)
var method = this.signalData[value];
else
var method = window[value];
if (method === undefined)
this._showError ('Function \'%s\' not found', value);
this._showError('Function \'%s\' not found', value);
return method;
}
,_isEvent: function (attribute)
{
return /^on-\w+/.test (attribute);
,_isEvent: function(attribute) {
return /^on-\w+/.test(attribute);
}
,_replaceFunc: function (token)
{
return token.charAt(1).toUpperCase ();
,_replaceFunc: function(token) {
return token.charAt(1).toUpperCase();
}
});
var BuilderResult = new Class
({
var BuilderResult = new Class({
Extends: Object
,initialize: function (builder, objects)
{
,initialize: function(builder, objects) {
this.builder = builder;
this.objects = objects;
}
,getMain: function ()
{
return this.builder.getMain (this);
,getMain: function() {
return this.builder.getMain(this);
}
,$: function (objectId)
{
return this.builder.getById (this, objectId);
,$: function(objectId) {
return this.builder.getById(this, objectId);
}
,getById: function (objectId)
{
return this.builder.getById (this, objectId);
,getById: function(objectId) {
return this.builder.getById(this, objectId);
}
,getByTagName: function (tagName)
{
return this.builder.getByTagName (this, tagName);
,getByTagName: function(tagName) {
return this.builder.getByTagName(this, tagName);
}
,link: function ()
{
this.builder.link (this);
,link: function(self, scope) {
this.builder.link(this, self, scope);
}
,_destroy: function ()
{
,_destroy: function() {
var objects = this.objects;
for (var i = 0; i < objects.length; i++)
if (objects[i] instanceof Object)
objects[i].unref ();
objects[i].unref();
this.parent ();
this.parent();
}
});

View File

@ -49,7 +49,7 @@ module.exports =
,'Feb'
,'Mar'
,'Apr'
,'May'
,'AbrMay'
,'Jun'
,'Jul'
,'Ago'

View File

@ -27,6 +27,7 @@ December: Decembre
Jan: Gen
Feb: Febr
Mar: Març
AbrMay: Mai
Apr: Abr
Jun: Juny
Jul: Jul

View File

@ -28,6 +28,7 @@ Jan: Jan
Feb: Feb
Mar: Mar
Apr: Apr
AbrMay: May
Jun: Jun
Jul: Jul
Ago: Ago

View File

@ -16,7 +16,7 @@ January: Enero
February: Febrero
March: Marzo
April: Abril
May: May
May: Mayo
June: Junio
July: Julio
August: Agosto
@ -28,6 +28,7 @@ Jan: Ene
Feb: Feb
Mar: Mar
Apr: Abr
AbrMay: May
Jun: Jun
Jul: Jul
Ago: Ago

View File

@ -28,6 +28,7 @@ Jan: Jan
Feb: Fév
Mar: Mars
Apr: Avr
AbrMay: Mai
Jun: Juin
Jul: Juil
Ago: Août

View File

@ -28,6 +28,7 @@ Jan: оны
Feb: хоё
Mar: Гур
Apr: Дөр
AbrMay: May
Jun: Jun
Jul: Jul
Ago: Най

View File

@ -28,6 +28,7 @@ Jan: Jan
Feb: Fev
Mar: Mar
Apr: Abr
AbrMay: Mai
Jun: Jun
Jul: Jul
Ago: Ago