diff --git a/src/DataSet.js b/src/DataSet.js index 41dcafd1..71ad59a5 100644 --- a/src/DataSet.js +++ b/src/DataSet.js @@ -37,43 +37,39 @@ */ // TODO: add a DataSet constructor DataSet(data, options) function DataSet (data, options) { - this.id = util.randomUUID(); - // correctly read optional arguments if (data && !Array.isArray(data) && !util.isDataTable(data)) { options = data; data = null; } - this.options = options || {}; - this.data = {}; // map with data indexed by id - this.fieldId = this.options.fieldId || 'id'; // name of the field containing id - this.type = {}; // internal field types (NOTE: this can differ from this.options.type) - this.showInternalIds = this.options.showInternalIds || false; // show internal ids with the get function + this._options = options || {}; + this._data = {}; // map with data indexed by id + this._fieldId = this._options.fieldId || 'id'; // name of the field containing id + this._type = {}; // internal field types (NOTE: this can differ from this._options.type) // all variants of a Date are internally stored as Date, so we can convert // from everything to everything (also from ISODate to Number for example) - if (this.options.type) { - for (var field in this.options.type) { - if (this.options.type.hasOwnProperty(field)) { - var value = this.options.type[field]; + if (this._options.type) { + for (var field in this._options.type) { + if (this._options.type.hasOwnProperty(field)) { + var value = this._options.type[field]; if (value == 'Date' || value == 'ISODate' || value == 'ASPDate') { - this.type[field] = 'Date'; + this._type[field] = 'Date'; } else { - this.type[field] = value; + this._type[field] = value; } } } } // TODO: deprecated since version 1.1.1 (or 2.0.0?) - if (this.options.convert) { + if (this._options.convert) { throw new Error('Option "convert" is deprecated. Use "type" instead.'); } - this.subscribers = {}; // event subscribers - this.internalIds = {}; // internally generated id's + this._subscribers = {}; // event subscribers // add initial data when provided if (data) { @@ -91,10 +87,10 @@ function DataSet (data, options) { * {String | Number} senderId */ DataSet.prototype.on = function(event, callback) { - var subscribers = this.subscribers[event]; + var subscribers = this._subscribers[event]; if (!subscribers) { subscribers = []; - this.subscribers[event] = subscribers; + this._subscribers[event] = subscribers; } subscribers.push({ @@ -111,9 +107,9 @@ DataSet.prototype.subscribe = DataSet.prototype.on; * @param {function} callback */ DataSet.prototype.off = function(event, callback) { - var subscribers = this.subscribers[event]; + var subscribers = this._subscribers[event]; if (subscribers) { - this.subscribers[event] = subscribers.filter(function (listener) { + this._subscribers[event] = subscribers.filter(function (listener) { return (listener.callback != callback); }); } @@ -135,11 +131,11 @@ DataSet.prototype._trigger = function (event, params, senderId) { } var subscribers = []; - if (event in this.subscribers) { - subscribers = subscribers.concat(this.subscribers[event]); + if (event in this._subscribers) { + subscribers = subscribers.concat(this._subscribers[event]); } - if ('*' in this.subscribers) { - subscribers = subscribers.concat(this.subscribers['*']); + if ('*' in this._subscribers) { + subscribers = subscribers.concat(this._subscribers['*']); } for (var i = 0; i < subscribers.length; i++) { @@ -209,11 +205,11 @@ DataSet.prototype.update = function (data, senderId) { var addedIds = [], updatedIds = [], me = this, - fieldId = me.fieldId; + fieldId = me._fieldId; var addOrUpdate = function (item) { var id = item[fieldId]; - if (me.data[id]) { + if (me._data[id]) { // update item id = me._updateItem(item); updatedIds.push(id); @@ -299,7 +295,6 @@ DataSet.prototype.update = function (data, senderId) { */ DataSet.prototype.get = function (args) { var me = this; - var globalShowInternalIds = this.showInternalIds; // parse the arguments var id, ids, options, data; @@ -343,15 +338,8 @@ DataSet.prototype.get = function (args) { returnType = 'Array'; } - // we allow the setting of this value for a single get request. - if (options != undefined) { - if (options.showInternalIds != undefined) { - this.showInternalIds = options.showInternalIds; - } - } - // build options - var type = options && options.type || this.options.type; + var type = options && options.type || this._options.type; var filter = options && options.filter; var items = [], item, itemId, i, len; @@ -374,8 +362,8 @@ DataSet.prototype.get = function (args) { } else { // return all items - for (itemId in this.data) { - if (this.data.hasOwnProperty(itemId)) { + for (itemId in this._data) { + if (this._data.hasOwnProperty(itemId)) { item = me._getItem(itemId, type); if (!filter || filter(item)) { items.push(item); @@ -384,9 +372,6 @@ DataSet.prototype.get = function (args) { } } - // restore the global value of showInternalIds - this.showInternalIds = globalShowInternalIds; - // order the results if (options && options.order && id == undefined) { this._sort(items, options.order); @@ -452,10 +437,10 @@ DataSet.prototype.get = function (args) { * @return {Array} ids */ DataSet.prototype.getIds = function (options) { - var data = this.data, + var data = this._data, filter = options && options.filter, order = options && options.order, - type = options && options.type || this.options.type, + type = options && options.type || this._options.type, i, len, id, @@ -480,7 +465,7 @@ DataSet.prototype.getIds = function (options) { this._sort(items, order); for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this.fieldId]; + ids[i] = items[i][this._fieldId]; } } else { @@ -489,7 +474,7 @@ DataSet.prototype.getIds = function (options) { if (data.hasOwnProperty(id)) { item = this._getItem(id, type); if (filter(item)) { - ids.push(item[this.fieldId]); + ids.push(item[this._fieldId]); } } } @@ -509,7 +494,7 @@ DataSet.prototype.getIds = function (options) { this._sort(items, order); for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this.fieldId]; + ids[i] = items[i][this._fieldId]; } } else { @@ -517,7 +502,7 @@ DataSet.prototype.getIds = function (options) { for (id in data) { if (data.hasOwnProperty(id)) { item = data[id]; - ids.push(item[this.fieldId]); + ids.push(item[this._fieldId]); } } } @@ -538,8 +523,8 @@ DataSet.prototype.getIds = function (options) { */ DataSet.prototype.forEach = function (callback, options) { var filter = options && options.filter, - type = options && options.type || this.options.type, - data = this.data, + type = options && options.type || this._options.type, + data = this._data, item, id; @@ -549,7 +534,7 @@ DataSet.prototype.forEach = function (callback, options) { for (var i = 0, len = items.length; i < len; i++) { item = items[i]; - id = item[this.fieldId]; + id = item[this._fieldId]; callback(item, id); } } @@ -579,9 +564,9 @@ DataSet.prototype.forEach = function (callback, options) { */ DataSet.prototype.map = function (callback, options) { var filter = options && options.filter, - type = options && options.type || this.options.type, + type = options && options.type || this._options.type, mappedItems = [], - data = this.data, + data = this._data, item; // convert and filter items @@ -689,17 +674,15 @@ DataSet.prototype.remove = function (id, senderId) { */ DataSet.prototype._remove = function (id) { if (util.isNumber(id) || util.isString(id)) { - if (this.data[id]) { - delete this.data[id]; - delete this.internalIds[id]; + if (this._data[id]) { + delete this._data[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]; + var itemId = id[this._fieldId]; + if (itemId && this._data[itemId]) { + delete this._data[itemId]; return itemId; } } @@ -712,10 +695,9 @@ DataSet.prototype._remove = function (id) { * @return {Array} removedIds The ids of all removed items */ DataSet.prototype.clear = function (senderId) { - var ids = Object.keys(this.data); + var ids = Object.keys(this._data); - this.data = {}; - this.internalIds = {}; + this._data = {}; this._trigger('remove', {items: ids}, senderId); @@ -728,7 +710,7 @@ DataSet.prototype.clear = function (senderId) { * @return {Object | null} item Item containing max value, or null if no items */ DataSet.prototype.max = function (field) { - var data = this.data, + var data = this._data, max = null, maxField = null; @@ -752,7 +734,7 @@ DataSet.prototype.max = function (field) { * @return {Object | null} item Item containing max value, or null if no items */ DataSet.prototype.min = function (field) { - var data = this.data, + var data = this._data, min = null, minField = null; @@ -778,9 +760,9 @@ DataSet.prototype.min = function (field) { * The returned array is unordered. */ DataSet.prototype.distinct = function (field) { - var data = this.data, + var data = this._data, values = [], - fieldType = this.options.type[field], + fieldType = this._options.type[field], count = 0; for (var prop in data) { @@ -811,11 +793,11 @@ DataSet.prototype.distinct = function (field) { * @private */ DataSet.prototype._addItem = function (item) { - var id = item[this.fieldId]; + var id = item[this._fieldId]; if (id != undefined) { // check whether this id is already taken - if (this.data[id]) { + if (this._data[id]) { // item already exists throw new Error('Cannot add item: item with id ' + id + ' already exists'); } @@ -823,18 +805,17 @@ DataSet.prototype._addItem = function (item) { else { // generate an id id = util.randomUUID(); - item[this.fieldId] = id; - this.internalIds[id] = item; + item[this._fieldId] = id; } var d = {}; for (var field in item) { if (item.hasOwnProperty(field)) { - var fieldType = this.type[field]; // type may be undefined + var fieldType = this._type[field]; // type may be undefined d[field] = util.convert(item[field], fieldType); } } - this.data[id] = d; + this._data[id] = d; return id; }; @@ -842,31 +823,26 @@ DataSet.prototype._addItem = function (item) { /** * Get an item. Fields can be converted to a specific type * @param {String} id - * @param {Object.} [type] field types to convert + * @param {Object.} [types] field types to convert * @return {Object | null} item * @private */ -DataSet.prototype._getItem = function (id, type) { +DataSet.prototype._getItem = function (id, types) { var field, value; // get the item from the dataset - var raw = this.data[id]; + var raw = this._data[id]; if (!raw) { return null; } // convert the items field types - var converted = {}, - fieldId = this.fieldId, - internalIds = this.internalIds; - if (type) { + var converted = {}; + if (types) { for (field in raw) { if (raw.hasOwnProperty(field)) { value = raw[field]; - // output all fields, except internal ids - if ((field != fieldId) || (!(value in internalIds) || this.showInternalIds)) { - converted[field] = util.convert(value, type[field]); - } + converted[field] = util.convert(value, types[field]); } } } @@ -875,10 +851,7 @@ DataSet.prototype._getItem = function (id, type) { for (field in raw) { if (raw.hasOwnProperty(field)) { value = raw[field]; - // output all fields, except internal ids - if ((field != fieldId) || (!(value in internalIds) || this.showInternalIds)) { - converted[field] = value; - } + converted[field] = value; } } } @@ -894,11 +867,11 @@ DataSet.prototype._getItem = function (id, type) { * @private */ DataSet.prototype._updateItem = function (item) { - var id = item[this.fieldId]; + var id = item[this._fieldId]; if (id == undefined) { throw new Error('Cannot update item: item has no id (item: ' + JSON.stringify(item) + ')'); } - var d = this.data[id]; + var d = this._data[id]; if (!d) { // item doesn't exist throw new Error('Cannot update item: no item with id ' + id + ' found'); @@ -907,7 +880,7 @@ DataSet.prototype._updateItem = function (item) { // merge with current item for (var field in item) { if (item.hasOwnProperty(field)) { - var fieldType = this.type[field]; // type may be undefined + var fieldType = this._type[field]; // type may be undefined d[field] = util.convert(item[field], fieldType); } } @@ -915,17 +888,6 @@ DataSet.prototype._updateItem = function (item) { return id; }; -/** - * check if an id is an internal or external id - * @param id - * @returns {boolean} - * @private - */ -DataSet.prototype.isInternalId = function(id) { - return (id in this.internalIds); -}; - - /** * Get an array with the column names of a Google DataTable * @param {DataTable} dataTable diff --git a/src/DataView.js b/src/DataView.js index f9fb12c1..e7ff81ec 100644 --- a/src/DataView.js +++ b/src/DataView.js @@ -9,13 +9,11 @@ * @constructor DataView */ function DataView (data, options) { - this.id = util.randomUUID(); - - this.data = null; - this.ids = {}; // ids of the items currently in memory (just contains a boolean true) - this.options = options || {}; - this.fieldId = 'id'; // name of the field containing id - this.subscribers = {}; // event subscribers + this._data = null; + this._ids = {}; // ids of the items currently in memory (just contains a boolean true) + this._options = options || {}; + this._fieldId = 'id'; // name of the field containing id + this._subscribers = {}; // event subscribers var me = this; this.listener = function () { @@ -33,44 +31,44 @@ function DataView (data, options) { * @param {DataSet | DataView} data */ DataView.prototype.setData = function (data) { - var ids, dataItems, i, len; + var ids, i, len; - if (this.data) { + if (this._data) { // unsubscribe from current dataset - if (this.data.unsubscribe) { - this.data.unsubscribe('*', this.listener); + if (this._data.unsubscribe) { + this._data.unsubscribe('*', this.listener); } // trigger a remove of all items in memory ids = []; - for (var id in this.ids) { - if (this.ids.hasOwnProperty(id)) { + for (var id in this._ids) { + if (this._ids.hasOwnProperty(id)) { ids.push(id); } } - this.ids = {}; + this._ids = {}; this._trigger('remove', {items: ids}); } - this.data = data; + this._data = data; - if (this.data) { + if (this._data) { // update fieldId - this.fieldId = this.options.fieldId || - (this.data && this.data.options && this.data.options.fieldId) || + this._fieldId = this._options.fieldId || + (this._data && this._data.options && this._data.options.fieldId) || 'id'; // trigger an add of all added items - ids = this.data.getIds({filter: this.options && this.options.filter}); + ids = this._data.getIds({filter: this._options && this._options.filter}); for (i = 0, len = ids.length; i < len; i++) { id = ids[i]; - this.ids[id] = true; + this._ids[id] = true; } this._trigger('add', {items: ids}); // subscribe to new dataset - if (this.data.on) { - this.data.on('*', this.listener); + if (this._data.on) { + this._data.on('*', this.listener); } } }; @@ -128,12 +126,12 @@ DataView.prototype.get = function (args) { } // extend the options with the default options and provided options - var viewOptions = util.extend({}, this.options, options); + var viewOptions = util.extend({}, this._options, options); // create a combined filter method when needed - if (this.options.filter && options && options.filter) { + if (this._options.filter && options && options.filter) { viewOptions.filter = function (item) { - return me.options.filter(item) && options.filter(item); + return me._options.filter(item) && options.filter(item); } } @@ -145,7 +143,7 @@ DataView.prototype.get = function (args) { getArguments.push(viewOptions); getArguments.push(data); - return this.data && this.data.get.apply(this.data, getArguments); + return this._data && this._data.get.apply(this._data, getArguments); }; /** @@ -159,8 +157,8 @@ DataView.prototype.get = function (args) { DataView.prototype.getIds = function (options) { var ids; - if (this.data) { - var defaultFilter = this.options.filter; + if (this._data) { + var defaultFilter = this._options.filter; var filter; if (options && options.filter) { @@ -177,7 +175,7 @@ DataView.prototype.getIds = function (options) { filter = defaultFilter; } - ids = this.data.getIds({ + ids = this._data.getIds({ filter: filter, order: options && options.order }); @@ -201,7 +199,7 @@ DataView.prototype.getIds = function (options) { DataView.prototype._onEvent = function (event, params, senderId) { var i, len, id, item, ids = params && params.items, - data = this.data, + data = this._data, added = [], updated = [], removed = []; @@ -214,7 +212,7 @@ DataView.prototype._onEvent = function (event, params, senderId) { id = ids[i]; item = this.get(id); if (item) { - this.ids[id] = true; + this._ids[id] = true; added.push(id); } } @@ -229,17 +227,17 @@ DataView.prototype._onEvent = function (event, params, senderId) { item = this.get(id); if (item) { - if (this.ids[id]) { + if (this._ids[id]) { updated.push(id); } else { - this.ids[id] = true; + this._ids[id] = true; added.push(id); } } else { - if (this.ids[id]) { - delete this.ids[id]; + if (this._ids[id]) { + delete this._ids[id]; removed.push(id); } else { @@ -254,8 +252,8 @@ DataView.prototype._onEvent = function (event, params, senderId) { // filter the ids of the removed items for (i = 0, len = ids.length; i < len; i++) { id = ids[i]; - if (this.ids[id]) { - delete this.ids[id]; + if (this._ids[id]) { + delete this._ids[id]; removed.push(id); } } diff --git a/src/timeline/component/ItemSet.js b/src/timeline/component/ItemSet.js index 2f908afd..5ee83548 100644 --- a/src/timeline/component/ItemSet.js +++ b/src/timeline/component/ItemSet.js @@ -1081,12 +1081,12 @@ ItemSet.prototype._onDragEnd = function (event) { if ('start' in props.item.data) { changed = (props.start != props.item.data.start.valueOf()); itemData.start = util.convert(props.item.data.start, - dataset.options.type && dataset.options.type.start || 'Date'); + dataset._options.type && dataset._options.type.start || 'Date'); } if ('end' in props.item.data) { changed = changed || (props.end != props.item.data.end.valueOf()); itemData.end = util.convert(props.item.data.end, - dataset.options.type && dataset.options.type.end || 'Date'); + dataset._options.type && dataset._options.type.end || 'Date'); } if ('group' in props.item.data) { changed = changed || (props.group != props.item.data.group); @@ -1098,7 +1098,7 @@ ItemSet.prototype._onDragEnd = function (event) { me.options.onMove(itemData, function (itemData) { if (itemData) { // apply changes - itemData[dataset.fieldId] = id; // ensure the item contains its id (can be undefined) + itemData[dataset._fieldId] = id; // ensure the item contains its id (can be undefined) changes.push(itemData); } else { @@ -1197,8 +1197,7 @@ ItemSet.prototype._onAddItem = function (event) { newItem.end = snap ? snap(end) : end; } - var id = util.randomUUID(); - newItem[this.itemsData.fieldId] = id; + newItem[this.itemsData.fieldId] = util.randomUUID(); var group = ItemSet.groupFromTarget(event); if (group) { diff --git a/test/dataset.js b/test/dataset.js index 70e04e30..3e18923c 100644 --- a/test/dataset.js +++ b/test/dataset.js @@ -31,6 +31,7 @@ items.forEach(function (item) { var sort = function (a, b) { return a.id > b.id; }; + assert.deepEqual(data.get({ fields: ['id', 'content'] }).sort(sort), [ @@ -150,17 +151,7 @@ data.clear(); data.add({content: 'Item 1'}); data.add({content: 'Item 2'}); -assert.strictEqual(data.get()[0].id, undefined); -assert.deepEqual((data.get({"showInternalIds": true})[0].id == undefined),false); -assert.deepEqual(data.isInternalId(data.get({"showInternalIds": true})[0].id), true); -assert.deepEqual((data.get()[0].id == undefined), true); - -// check if the global setting is applied correctly -var data = new DataSet({showInternalIds: true}); -data.add({content: 'Item 1'}); -assert.deepEqual((data.get()[0].id == undefined), false); -assert.deepEqual(data.isInternalId(data.get()[0].id), true); -assert.deepEqual((data.get({"showInternalIds": false})[0].id == undefined),true); +assert.notStrictEqual(data.get()[0].id, undefined); // create a dataset with initial data var data = new DataSet([