0
1
Fork 0
This commit is contained in:
Juan Ferrer Toribio 2017-04-24 09:47:56 +02:00
parent adb651fe69
commit 1e43aead46
9 changed files with 241 additions and 245 deletions

View File

@ -4,14 +4,10 @@ var Model = require ('./model');
module.exports = new Class module.exports = new Class
({ ({
Extends: Vn.Object Extends: Iterator
,Implements: Iterator
,Tag: 'db-form' ,Tag: 'db-form'
,Properties: ,Properties:
{ {
/**
* The model associated to this form.
*/
model: model:
{ {
type: Model type: Model
@ -42,78 +38,42 @@ module.exports = new Class
return; return;
this._row = x; this._row = x;
this._rowChanged ();
this.changed (); this.changed ();
} }
,get: function () ,get: function ()
{ {
return this._row; return this._row;
} }
},
/**
* The number of rows in the form.
*/
numRows:
{
type: Number
,get: function ()
{
return this._model ?
this._model.numRows : 0;
}
},
/**
* Checks if the form data is ready.
*/
ready:
{
type: Boolean
,get: function ()
{
return this._model ?
this._model.ready : false;
}
},
/**
* The current row parameters.
*/
params:
{
type: Object
,set: function (x)
{
this.assign (x);
}
,get: function ()
{
return this.getParams ();
}
} }
} }
,lastRow: 0 ,initialize: function (props)
,_model: null {
,_row: -1 Object.assign (this, {
,_ready: false _lastRow: 0
,_lastReady: false
});
this.parent (props);
}
,onModelChange: function () ,onModelChange: function ()
{ {
var ready = this._model && this._model.ready; var ready = this._model && this._model.ready;
if (ready != this._ready) if (ready != this._lastReady)
{ {
if (this._row != -1) if (this._row != -1)
this.lastRow = this._row; this._lastRow = this._row;
this._ready = ready; this._lastReady = ready;
this.emit ('status-changed'); this.emit ('status-changed');
if (this._row == -1) if (this._row == -1)
this.row = this.lastRow; this.row = this._lastRow;
if (ready) if (ready)
this.emit ('ready'); this.emit ('ready');
this.changed ();
} }
} }

View File

@ -27,13 +27,6 @@ module.exports = new Class
{ {
type: Number type: Number
}, },
/**
* The current row parameters.
*/
params:
{
type: Object
},
/** /**
* Checks if the form data is ready. * Checks if the form data is ready.
*/ */
@ -43,9 +36,6 @@ module.exports = new Class
} }
} }
,_model: null
,_row: -1
,refresh: function () ,refresh: function ()
{ {
if (this._model) if (this._model)

View File

@ -3,17 +3,15 @@ var IteratorIface = require ('./iterator-iface');
var Model = require ('./model'); var Model = require ('./model');
/** /**
* A light iterator for models. * A light iterator for models. It assumes that its row and model properties
* are always valid.
*/ */
module.exports = new Class module.exports = new Class
({ ({
Extends: Vn.Object Extends: Vn.Lot
,Implements: IteratorIface ,Implements: IteratorIface
,Properties: ,Properties:
{ {
/**
* The model associated to this form.
*/
model: model:
{ {
type: Model type: Model
@ -26,24 +24,19 @@ module.exports = new Class
return this._model; return this._model;
} }
}, },
/**
* The row where the form positioned, has -1 if the row is unselected.
*/
row: row:
{ {
type: Number type: Number
,set: function (x) ,set: function (x)
{ {
this._row = x; this._row = x;
this.updateParams ();
} }
,get: function () ,get: function ()
{ {
return this._row; return this._row;
} }
}, },
/**
* The number of rows in the form.
*/
numRows: numRows:
{ {
type: Number type: Number
@ -53,9 +46,6 @@ module.exports = new Class
this._model.numRows : 0; this._model.numRows : 0;
} }
}, },
/**
* Checks if the form data is ready.
*/
ready: ready:
{ {
type: Boolean type: Boolean
@ -64,21 +54,26 @@ module.exports = new Class
return this._model ? return this._model ?
this._model.ready : false; this._model.ready : false;
} }
},
/**
* The current row parameters.
*/
params:
{
type: Object
,set: function (x)
{
this.assign (x);
}
,get: function ()
{
return this.getParams ();
} }
} }
,initialize: function (props)
{
Object.assign (this, {
_model: null
,_row: -1
});
this.parent (props);
}
,_paramsChanged: function (diff)
{
for (var key in diff)
this._model.set (this._row, key, diff[key]);
}
,updateParams: function ()
{
this.params = this._model.getObject (this._row);
} }
}); });

View File

@ -7,7 +7,7 @@ require ('./gui.css');
/** /**
* The main screen component. It has a left menu, a navbar with configurable * The main screen component. It has a left menu, a navbar with configurable
* action buttons and the body where @Db.Form childs can be displayed. * action buttons and the body where @Form childs can be displayed.
*/ */
module.exports = new Class module.exports = new Class
({ ({

View File

@ -47,8 +47,8 @@ module.exports = new Class
} }
} }
/** /**
* {Function (Vn.BuilderResult, Db.Form)} Function to call after every * {Function (Vn.BuilderResult, Db.Iterator)} Function to call after
* box rendering. * every box rendering.
*/ */
,renderer: ,renderer:
{ {

View File

@ -1,19 +1,18 @@
var VnObject = require ('./object');
var VnDate = require ('./date'); var VnDate = require ('./date');
var LotIface = require ('./lot-iface'); var Lot = require ('./lot');
var Value = require ('./value');
/** /**
* Class to handle the hash part of the URL as a key-value * Class to handle the hash part of the URL as a key-value javascript object.
* javascript object. It also handles dates and objects as * It also handles dates and objects as a value.
* a value.
*/ */
module.exports = new Class module.exports = new Class
({ ({
Extends: VnObject Extends: Lot
,Implements: LotIface
,Properties: { ,Properties: {
/**
* The main window object.
*/
window: window:
{ {
type: Window type: Window
@ -27,120 +26,110 @@ module.exports = new Class
{ {
return this._window; return this._window;
} }
},
params:
{
type: Object
,set: function (x)
{
this.setAll (x);
}
,get: function ()
{
return this._hashMap;
}
} }
} }
,initialize: function (props) ,initialize: function (props)
{ {
this._hash = null; Object.assign (this, {
this._hashMap = null; _hash: null
this._window = null; ,_hashLock: false
this._hashChangedHandler = this._hashChanged.bind (this); ,_window: null
,_hashChangedHandler: this._hashChanged.bind (this)
});
this.parent (props); this.parent (props);
} }
,get: function (key) ,_paramsChanged: function ()
{ {
return this._hashMap[key]; this._updateHash ();
}
,set: function (key, value)
{
var object = {};
object[key] = value;
this.assign (object);
}
,assign: function (object)
{
var newObject = {};
for (var key in this._hashMap)
newObject[key] = this._hashMap[key];
for (var key in object)
newObject[key] = object[key];
this.setAll (newObject);
}
/**
* Sets the hash part of the URL.
*
* @param {Object} object A key-value object
*/
,setAll: function (object)
{
if (object)
for (var key in object)
if (object[key] === null || object[key] === undefined)
delete object[key];
var newHash = this.make (object);
if (!object)
object = {};
if (!Value.equals (this._hashMap, object))
{
this._hashMap = object;
this._hash = newHash;
this._blockChanged = true;
location.hash = newHash;
this._blockChanged = false;
this.changed ();
}
} }
/** /**
* Creates a URL with the given hash data. * Creates a URL with the given hash data.
* *
* @param {Object} object A key-value object * @param {Object} params A key-value object
* @param {boolean} add %true to combine with the current params, %false otherwise * @param {boolean} add %true to combine with the current params, %false otherwise
* @return {string} The URL * @return {string} The URL
*/ */
,make: function (object, add) ,make: function (params, add)
{
if (add)
{
params = Object.assign ({}, params);
for (var key in this._params)
if (!params[key])
params[key] = this._params[key];
}
return this.renderHash (object);
}
/**
* Updates the window hash with current params.
*/
,updateHash: function ()
{
if (this._hashLock)
return;
this._hash = this.renderHash (this._params);
this._hashLock = true;
location.hash = this._hash;
this._hashLock = false;
}
/*
* Called when window hash changes.
*/
,_hashChanged: function ()
{
var newHash = location.hash;
if (this._hashLock || this._hash === newHash)
return;
this._hash = newHash;
this._hashLock = true;
this.params = this.parseHash (newHash);
this._hashLock = false;
}
/**
* Creates a URL with the given hash data.
*
* @param {Object} params The key-value object
* @return {string} The URL
*/
,renderHash: function (params)
{ {
var hash = '#!'; var hash = '#!';
if (add && object) for (var key in params)
for (var key in this._hashMap) if (params[key] !== undefined)
if (!object[key])
object[key] = this._hashMap[key];
for (var key in object)
{ {
if (hash.length > 2) if (hash.length > 2)
hash += '&'; hash += '&';
hash += encodeURIComponent (key) +'='+ this.renderValue (object[key]); hash += encodeURIComponent (key) +'='+ this.renderValue (params[key]);
} }
return hash; return hash;
} }
,_hashChanged: function () /**
* Parses a hash string to a key-value object.
*
* @param {string} hashString The hash string
* @return {Object} The key-value object
*/
,parseHash: function (hashString)
{ {
var newHash = location.hash;
if (this._blockChanged || this._hash == newHash)
return;
var newMap = hashMap = {}; var newMap = hashMap = {};
var kvPairs = newHash.substr(2).split ('&'); var kvPairs = hashString.substr(2).split ('&');
for (var i = 0; i < kvPairs.length; i++) for (var i = 0; i < kvPairs.length; i++)
{ {
@ -149,17 +138,13 @@ module.exports = new Class
if (kvPair[0]) if (kvPair[0])
newMap[decodeURIComponent (kvPair[0])] = this.parseValue (kvPair[1]); newMap[decodeURIComponent (kvPair[0])] = this.parseValue (kvPair[1]);
} }
if (!Value.equals (this._hashMap, newMap))
{
this._hashMap = newMap;
this._hash = newHash;
this.changed ();
}
} }
,renderValue: function (v) ,renderValue: function (v)
{ {
if (v == null)
return '';
switch (typeof v) switch (typeof v)
{ {
case 'number': case 'number':

View File

@ -1,19 +1,26 @@
/** /**
* Holds a plain key-value javascript object and monitorizes * Holds a plain key-value javascript object and monitorizes changes over it.
* changes over it.
*/ */
module.exports = new Class module.exports = new Class
({ ({
Properties: Properties:
{ {
/** /**
* The internal object with the params. * The internal object with the params, this is the lot internal object
* and should be used for read-only purposes.
*/ */
params: params:
{ {
type: Object type: Object
} }
/**
* Shortcut for params property.
*/
,$:
{
type: Object
}
} }
/** /**
@ -22,7 +29,10 @@ module.exports = new Class
* @param {string} field The field name * @param {string} field The field name
* @return {*} The field value * @return {*} The field value
*/ */
,get: function () {} ,get: function (field)
{
return this.params[field];
}
/** /**
* Sets a value on the set. * Sets a value on the set.
@ -30,7 +40,12 @@ module.exports = new Class
* @param {string} field The field name * @param {string} field The field name
* @param {*} value The new field value * @param {*} value The new field value
*/ */
,set: function () {} ,set: function (field, value)
{
var params = {};
params[field] = value;
this.assign (param);
}
/** /**
* Returns an array with the set keys. * Returns an array with the set keys.
@ -54,13 +69,7 @@ module.exports = new Class
* *
* @param {Object} object The source object * @param {Object} object The source object
*/ */
,assign: function (object) ,assign: function () {}
{
for (var key in object)
this.set (key, object[key]);
this.changed ();
}
/** /**
* Copies all values from another lot. * Copies all values from another lot.
@ -71,4 +80,12 @@ module.exports = new Class
{ {
this.assign (lot.params); this.assign (lot.params);
} }
/**
* Resets all values.
*/
,reset: function ()
{
this.params = {};
}
}); });

View File

@ -1,6 +1,7 @@
var VnObject = require ('./object'); var VnObject = require ('./object');
var LotIface = require ('./lot-iface'); var LotIface = require ('./lot-iface');
var Value = require ('./value');
module.exports = new Class module.exports = new Class
({ ({
@ -14,8 +15,19 @@ module.exports = new Class
type: Object type: Object
,set: function (x) ,set: function (x)
{ {
this._params = x; this._setAll (x);
this.changed (); }
,get: function ()
{
return this._params;
}
}
,$:
{
type: Object
,set: function (x)
{
this._setAll (x);
} }
,get: function () ,get: function ()
{ {
@ -24,32 +36,15 @@ module.exports = new Class
} }
} }
,_attachments: null
,initialize: function (props) ,initialize: function (props)
{ {
this._params = {}; this._params = {};
this.parent (props); this.parent (props);
} }
,get: function (paramName) ,get: function (field)
{ {
return this._params[paramName]; return this._params[field];
}
,set: function (paramName, value)
{
this._params[paramName] = value;
this.changed ();
}
/**
* Resets all values.
*/
,reset: function ()
{
this._params = {};
this.changed ();
} }
,keys: function () ,keys: function ()
@ -57,11 +52,35 @@ module.exports = new Class
return Object.keys (this._params); return Object.keys (this._params);
} }
,assign: function (object) ,assign: function (params)
{ {
for (var key in object) var diff = Value.partialDiff (this._params, params);
this._params[key] = object[key];
this.changed (); if (diff)
{
Object.assign (this._params, diff);
this._paramsChanged (diff);
this.changed (diff);
} }
}
,setAll: function (params)
{
var diff = Value.diff (this._params, params);
if (diff)
{
this._params = Value.kvClone (params);
this._paramsChanged (diff);
this.changed (diff);
}
}
/**
* Called when lot params changes, can be implemented by child classes to
* be notified about changes.
*
* @param {Object} diff Changed parameters and its new values
*/
,_paramsChanged: function () {}
}); });

View File

@ -2,8 +2,8 @@
var VnDate = require ('./date'); var VnDate = require ('./date');
/** /**
* Checks if two values are equal, it also checks objects. Basic * Checks if two values are equal, it also checks objects. Basic values are
* values are compared using the strict equality operator. * compared using the strict equality operator.
* *
* @param {*} a Value to compare to * @param {*} a Value to compare to
* @param {*} b Value to compare with * @param {*} b Value to compare with
@ -32,7 +32,7 @@ function equals (a, b)
} }
/** /**
* Calculates differences of two key-value objects. * Calculates differences between two key-value objects.
* *
* @param {Object} orgObject Value to compare to * @param {Object} orgObject Value to compare to
* @param {Object} newObject Value to compare with * @param {Object} newObject Value to compare with
@ -40,18 +40,13 @@ function equals (a, b)
*/ */
function diff (orgObject, newObject) function diff (orgObject, newObject)
{ {
var key;
var diff = {}; var diff = {};
var keys = Object.keys (orgObject); for (var key in orgObject)
for (var i = keys.length; --i; key = keys[i])
if (!simpleEquals (orgObject[key], newObject[key])) if (!simpleEquals (orgObject[key], newObject[key]))
diff[key] = simpleClone (newObject[key]); diff[key] = simpleClone (newObject[key]);
var keys = Object.keys (newObject); for (var key in newObject)
for (var i = keys.length; --i; key = keys[i])
if (orgObject[key] === undefined && newObject[key] !== undefined) if (orgObject[key] === undefined && newObject[key] !== undefined)
diff[key] = simpleClone (newObject[key]); diff[key] = simpleClone (newObject[key]);
@ -61,6 +56,39 @@ function diff (orgObject, newObject)
return null; return null;
} }
/**
* Calculates new differences between two key-value objects.
*
* @param {Object} orgObject Value to compare to
* @param {Object} newObject Value to compare with
* @return {Object} The differences or %null if there are no differences
*/
function partialDiff (orgObject, newObject)
{
var diff = {};
for (var key in newObject)
if (!simpleEquals (orgObject[key], newObject[key]))
diff[key] = simpleClone (newObject[key]);
if (Object.keys (diff).length > 0)
return diff;
return null;
}
function kvClone (object)
{
var key;
var copy = {};
var keys = Object.keys (object);
for (var i = keys.length; --i; key = keys[i])
copy[key] = simpleClone (object[key]);
return copy;
}
/** /**
* Copies a simple value. * Copies a simple value.
* *
@ -120,6 +148,8 @@ module.exports =
,equals: equals ,equals: equals
,diff: diff ,diff: diff
,partialDiff: partialDiff
,kvClone: kvClone
,simpleClone: simpleClone ,simpleClone: simpleClone
,simpleEquals: simpleEquals ,simpleEquals: simpleEquals
,sprintf: sprintf ,sprintf: sprintf