|
@ -5,7 +5,7 @@ |
|
|
* A dynamic, browser-based visualization library. |
|
|
* A dynamic, browser-based visualization library. |
|
|
* |
|
|
* |
|
|
* @version 0.1.0-SNAPSHOT |
|
|
* @version 0.1.0-SNAPSHOT |
|
|
* @date 2013-06-18 |
|
|
|
|
|
|
|
|
* @date 2013-06-20 |
|
|
* |
|
|
* |
|
|
* @license |
|
|
* @license |
|
|
* Copyright (C) 2011-2013 Almende B.V, http://almende.com
|
|
|
* Copyright (C) 2011-2013 Almende B.V, http://almende.com
|
|
@ -162,7 +162,7 @@ util.cast = function cast(object, type) { |
|
|
|
|
|
|
|
|
case 'number': |
|
|
case 'number': |
|
|
case 'Number': |
|
|
case 'Number': |
|
|
return Number(object); |
|
|
|
|
|
|
|
|
return Number(object.valueOf()); |
|
|
|
|
|
|
|
|
case 'string': |
|
|
case 'string': |
|
|
case 'String': |
|
|
case 'String': |
|
@ -179,11 +179,9 @@ util.cast = function cast(object, type) { |
|
|
return new Date(object.valueOf()); |
|
|
return new Date(object.valueOf()); |
|
|
} |
|
|
} |
|
|
if (util.isString(object)) { |
|
|
if (util.isString(object)) { |
|
|
// parse ASP.Net Date pattern,
|
|
|
|
|
|
// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
|
|
|
|
|
|
// code from http://momentjs.com/
|
|
|
|
|
|
match = ASPDateRegex.exec(object); |
|
|
match = ASPDateRegex.exec(object); |
|
|
if (match) { |
|
|
if (match) { |
|
|
|
|
|
// object is an ASP date
|
|
|
return new Date(Number(match[1])); // parse number
|
|
|
return new Date(Number(match[1])); // parse number
|
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
@ -207,11 +205,9 @@ util.cast = function cast(object, type) { |
|
|
return moment.clone(); |
|
|
return moment.clone(); |
|
|
} |
|
|
} |
|
|
if (util.isString(object)) { |
|
|
if (util.isString(object)) { |
|
|
// parse ASP.Net Date pattern,
|
|
|
|
|
|
// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
|
|
|
|
|
|
// code from http://momentjs.com/
|
|
|
|
|
|
match = ASPDateRegex.exec(object); |
|
|
match = ASPDateRegex.exec(object); |
|
|
if (match) { |
|
|
if (match) { |
|
|
|
|
|
// object is an ASP date
|
|
|
return moment(Number(match[1])); // parse number
|
|
|
return moment(Number(match[1])); // parse number
|
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
@ -225,14 +221,24 @@ util.cast = function cast(object, type) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
case 'ISODate': |
|
|
case 'ISODate': |
|
|
if (object instanceof Date) { |
|
|
|
|
|
|
|
|
if (util.isNumber(object)) { |
|
|
|
|
|
return new Date(object); |
|
|
|
|
|
} |
|
|
|
|
|
else if (object instanceof Date) { |
|
|
return object.toISOString(); |
|
|
return object.toISOString(); |
|
|
} |
|
|
} |
|
|
else if (moment.isMoment(object)) { |
|
|
else if (moment.isMoment(object)) { |
|
|
return object.toDate().toISOString(); |
|
|
return object.toDate().toISOString(); |
|
|
} |
|
|
} |
|
|
else if (util.isNumber(object) || util.isString(object)) { |
|
|
|
|
|
return moment(object).toDate().toISOString(); |
|
|
|
|
|
|
|
|
else if (util.isString(object)) { |
|
|
|
|
|
match = ASPDateRegex.exec(object); |
|
|
|
|
|
if (match) { |
|
|
|
|
|
// object is an ASP date
|
|
|
|
|
|
return new Date(Number(match[1])).toISOString(); // parse number
|
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
return new Date(object).toISOString(); // parse string
|
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
throw new Error( |
|
|
throw new Error( |
|
@ -241,11 +247,23 @@ util.cast = function cast(object, type) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
case 'ASPDate': |
|
|
case 'ASPDate': |
|
|
if (object instanceof Date) { |
|
|
|
|
|
|
|
|
if (util.isNumber(object)) { |
|
|
|
|
|
return '/Date(' + object + ')/'; |
|
|
|
|
|
} |
|
|
|
|
|
else if (object instanceof Date) { |
|
|
return '/Date(' + object.valueOf() + ')/'; |
|
|
return '/Date(' + object.valueOf() + ')/'; |
|
|
} |
|
|
} |
|
|
else if (util.isNumber(object) || util.isString(object)) { |
|
|
|
|
|
return '/Date(' + moment(object).valueOf() + ')/'; |
|
|
|
|
|
|
|
|
else if (util.isString(object)) { |
|
|
|
|
|
match = ASPDateRegex.exec(object); |
|
|
|
|
|
var value; |
|
|
|
|
|
if (match) { |
|
|
|
|
|
// object is an ASP date
|
|
|
|
|
|
value = new Date(Number(match[1])).valueOf(); // parse number
|
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
value = new Date(object).valueOf(); // parse string
|
|
|
|
|
|
} |
|
|
|
|
|
return '/Date(' + value + ')/'; |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
throw new Error( |
|
|
throw new Error( |
|
@ -259,6 +277,9 @@ util.cast = function cast(object, type) { |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// parse ASP.Net Date pattern,
|
|
|
|
|
|
// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
|
|
|
|
|
|
// code from http://momentjs.com/
|
|
|
var ASPDateRegex = /^\/?Date\((\-?\d+)/i; |
|
|
var ASPDateRegex = /^\/?Date\((\-?\d+)/i; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
@ -1202,11 +1223,9 @@ function DataSet (options) { |
|
|
* @param {function} callback Callback method. Called with three parameters: |
|
|
* @param {function} callback Callback method. Called with three parameters: |
|
|
* {String} event |
|
|
* {String} event |
|
|
* {Object | null} params |
|
|
* {Object | null} params |
|
|
* {String} senderId |
|
|
|
|
|
* @param {String} [id] Optional id for the sender, used to filter |
|
|
|
|
|
* events triggered by the sender itself. |
|
|
|
|
|
|
|
|
* {String | Number} senderId |
|
|
*/ |
|
|
*/ |
|
|
DataSet.prototype.subscribe = function (event, callback, id) { |
|
|
|
|
|
|
|
|
DataSet.prototype.subscribe = function (event, callback) { |
|
|
var subscribers = this.subscribers[event]; |
|
|
var subscribers = this.subscribers[event]; |
|
|
if (!subscribers) { |
|
|
if (!subscribers) { |
|
|
subscribers = []; |
|
|
subscribers = []; |
|
@ -1214,7 +1233,6 @@ DataSet.prototype.subscribe = function (event, callback, id) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
subscribers.push({ |
|
|
subscribers.push({ |
|
|
id: id ? String(id) : null, |
|
|
|
|
|
callback: callback |
|
|
callback: callback |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
@ -1266,9 +1284,10 @@ DataSet.prototype._trigger = function (event, params, senderId) { |
|
|
* Adding an item will fail when there already is an item with the same id. |
|
|
* Adding an item will fail when there already is an item with the same id. |
|
|
* @param {Object | Array | DataTable} data |
|
|
* @param {Object | Array | DataTable} data |
|
|
* @param {String} [senderId] Optional sender id |
|
|
* @param {String} [senderId] Optional sender id |
|
|
|
|
|
* @return {Array} addedIds Array with the ids of the added items |
|
|
*/ |
|
|
*/ |
|
|
DataSet.prototype.add = function (data, senderId) { |
|
|
DataSet.prototype.add = function (data, senderId) { |
|
|
var addedItems = [], |
|
|
|
|
|
|
|
|
var addedIds = [], |
|
|
id, |
|
|
id, |
|
|
me = this; |
|
|
me = this; |
|
|
|
|
|
|
|
@ -1276,7 +1295,7 @@ DataSet.prototype.add = function (data, senderId) { |
|
|
// Array
|
|
|
// Array
|
|
|
for (var i = 0, len = data.length; i < len; i++) { |
|
|
for (var i = 0, len = data.length; i < len; i++) { |
|
|
id = me._addItem(data[i]); |
|
|
id = me._addItem(data[i]); |
|
|
addedItems.push(id); |
|
|
|
|
|
|
|
|
addedIds.push(id); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else if (util.isDataTable(data)) { |
|
|
else if (util.isDataTable(data)) { |
|
@ -1290,31 +1309,34 @@ DataSet.prototype.add = function (data, senderId) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
id = me._addItem(item); |
|
|
id = me._addItem(item); |
|
|
addedItems.push(id); |
|
|
|
|
|
|
|
|
addedIds.push(id); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else if (data instanceof Object) { |
|
|
else if (data instanceof Object) { |
|
|
// Single item
|
|
|
// Single item
|
|
|
id = me._addItem(data); |
|
|
id = me._addItem(data); |
|
|
addedItems.push(id); |
|
|
|
|
|
|
|
|
addedIds.push(id); |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
throw new Error('Unknown dataType'); |
|
|
throw new Error('Unknown dataType'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (addedItems.length) { |
|
|
|
|
|
this._trigger('add', {items: addedItems}, senderId); |
|
|
|
|
|
|
|
|
if (addedIds.length) { |
|
|
|
|
|
this._trigger('add', {items: addedIds}, senderId); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return addedIds; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Update existing items. When an item does not exist, it will be created |
|
|
* Update existing items. When an item does not exist, it will be created |
|
|
* @param {Object | Array | DataTable} data |
|
|
* @param {Object | Array | DataTable} data |
|
|
* @param {String} [senderId] Optional sender id |
|
|
* @param {String} [senderId] Optional sender id |
|
|
|
|
|
* @return {Array} updatedIds The ids of the added or updated items |
|
|
*/ |
|
|
*/ |
|
|
DataSet.prototype.update = function (data, senderId) { |
|
|
DataSet.prototype.update = function (data, senderId) { |
|
|
var addedItems = [], |
|
|
|
|
|
updatedItems = [], |
|
|
|
|
|
|
|
|
var addedIds = [], |
|
|
|
|
|
updatedIds = [], |
|
|
me = this, |
|
|
me = this, |
|
|
fieldId = me.fieldId; |
|
|
fieldId = me.fieldId; |
|
|
|
|
|
|
|
@ -1323,12 +1345,12 @@ DataSet.prototype.update = function (data, senderId) { |
|
|
if (me.data[id]) { |
|
|
if (me.data[id]) { |
|
|
// update item
|
|
|
// update item
|
|
|
id = me._updateItem(item); |
|
|
id = me._updateItem(item); |
|
|
updatedItems.push(id); |
|
|
|
|
|
|
|
|
updatedIds.push(id); |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
// add new item
|
|
|
// add new item
|
|
|
id = me._addItem(item); |
|
|
id = me._addItem(item); |
|
|
addedItems.push(id); |
|
|
|
|
|
|
|
|
addedIds.push(id); |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -1359,12 +1381,14 @@ DataSet.prototype.update = function (data, senderId) { |
|
|
throw new Error('Unknown dataType'); |
|
|
throw new Error('Unknown dataType'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (addedItems.length) { |
|
|
|
|
|
this._trigger('add', {items: addedItems}, senderId); |
|
|
|
|
|
|
|
|
if (addedIds.length) { |
|
|
|
|
|
this._trigger('add', {items: addedIds}, senderId); |
|
|
} |
|
|
} |
|
|
if (updatedItems.length) { |
|
|
|
|
|
this._trigger('update', {items: updatedItems}, senderId); |
|
|
|
|
|
|
|
|
if (updatedIds.length) { |
|
|
|
|
|
this._trigger('update', {items: updatedIds}, senderId); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return addedIds.concat(updatedIds); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
@ -1745,46 +1769,66 @@ DataSet.prototype._sort = function (items, order) { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Remove an object by pointer or by id |
|
|
* Remove an object by pointer or by id |
|
|
* @param {String | Number | Object | Array} id Object or id, or an array with |
|
|
|
|
|
* objects or ids to be removed |
|
|
|
|
|
|
|
|
* @param {String | Number | Object | Array} id Object or id, or an array with |
|
|
|
|
|
* objects or ids to be removed |
|
|
* @param {String} [senderId] Optional sender id |
|
|
* @param {String} [senderId] Optional sender id |
|
|
|
|
|
* @return {Array} removedIds |
|
|
*/ |
|
|
*/ |
|
|
DataSet.prototype.remove = function (id, senderId) { |
|
|
DataSet.prototype.remove = function (id, senderId) { |
|
|
var removedItems = [], |
|
|
|
|
|
i, len; |
|
|
|
|
|
|
|
|
var removedIds = [], |
|
|
|
|
|
i, len, removedId; |
|
|
|
|
|
|
|
|
if (util.isNumber(id) || util.isString(id)) { |
|
|
|
|
|
delete this.data[id]; |
|
|
|
|
|
delete this.internalIds[id]; |
|
|
|
|
|
removedItems.push(id); |
|
|
|
|
|
} |
|
|
|
|
|
else if (id instanceof Array) { |
|
|
|
|
|
|
|
|
if (id instanceof Array) { |
|
|
for (i = 0, len = id.length; i < len; i++) { |
|
|
for (i = 0, len = id.length; i < len; i++) { |
|
|
this.remove(id[i]); |
|
|
|
|
|
|
|
|
removedId = this._remove(id[i]); |
|
|
|
|
|
if (removedId != null) { |
|
|
|
|
|
removedIds.push(removedId); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
removedItems = items.concat(id); |
|
|
|
|
|
} |
|
|
} |
|
|
else if (id instanceof Object) { |
|
|
|
|
|
// search for the object
|
|
|
|
|
|
for (i in this.data) { |
|
|
|
|
|
if (this.data.hasOwnProperty(i)) { |
|
|
|
|
|
if (this.data[i] == id) { |
|
|
|
|
|
delete this.data[i]; |
|
|
|
|
|
delete this.internalIds[i]; |
|
|
|
|
|
removedItems.push(i); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
else { |
|
|
|
|
|
removedId = this._remove(id); |
|
|
|
|
|
if (removedId != null) { |
|
|
|
|
|
removedIds.push(removedId); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (removedItems.length) { |
|
|
|
|
|
this._trigger('remove', {items: removedItems}, senderId); |
|
|
|
|
|
|
|
|
if (removedIds.length) { |
|
|
|
|
|
this._trigger('remove', {items: removedIds}, senderId); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return removedIds; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Remove an item by its id |
|
|
|
|
|
* @param {Number | String | Object} id id or item |
|
|
|
|
|
* @returns {Number | String | null} id |
|
|
|
|
|
* @private |
|
|
|
|
|
*/ |
|
|
|
|
|
DataSet.prototype._remove = function (id) { |
|
|
|
|
|
if (util.isNumber(id) || util.isString(id)) { |
|
|
|
|
|
if (this.data[id]) { |
|
|
|
|
|
delete this.data[id]; |
|
|
|
|
|
delete this.internalIds[id]; |
|
|
|
|
|
return id; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else if (id instanceof Object) { |
|
|
|
|
|
var itemId = id[this.fieldId]; |
|
|
|
|
|
if (itemId && this.data[itemId]) { |
|
|
|
|
|
delete this.data[itemId]; |
|
|
|
|
|
delete this.internalIds[itemId]; |
|
|
|
|
|
return itemId; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return null; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Clear the data |
|
|
* Clear the data |
|
|
* @param {String} [senderId] Optional sender id |
|
|
* @param {String} [senderId] Optional sender id |
|
|
|
|
|
* @return {Array} removedIds The ids of all removed items |
|
|
*/ |
|
|
*/ |
|
|
DataSet.prototype.clear = function (senderId) { |
|
|
DataSet.prototype.clear = function (senderId) { |
|
|
var ids = Object.keys(this.data); |
|
|
var ids = Object.keys(this.data); |
|
@ -1793,6 +1837,8 @@ DataSet.prototype.clear = function (senderId) { |
|
|
this.internalIds = {}; |
|
|
this.internalIds = {}; |
|
|
|
|
|
|
|
|
this._trigger('remove', {items: ids}, senderId); |
|
|
this._trigger('remove', {items: ids}, senderId); |
|
|
|
|
|
|
|
|
|
|
|
return ids; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|