Mercurial > hg > dml-open-vis
view src/DML/MainVisBundle/Resources/assets/marionette/modules/ContextModule/ContextModule.10-ConfigGrid.js @ 0:493bcb69166c
added public content
author | Daniel Wolff |
---|---|
date | Tue, 09 Feb 2016 20:54:02 +0100 |
parents | |
children |
line wrap: on
line source
"use strict"; App.module("ContextModule", function(ContextModule, App, Backbone, Marionette, $, _, Logger) { // Define private variables var logger = null; ContextModule.addInitializer(function(options){ logger = Logger.get("ContextModule.ConfigGrid"); logger.setLevel(Logger.WARN); /** * ConfigGrid stores the configuration of a grid that consists of entityConfigs and viewConfigs * (both are Backbone.Collection of Config) * * In real situation entityConfigs are music collection configs and music recording configs * * two sub-collections can be interacted directly (without proxy methods) * * The grid can be given a read-only type on creation in order to easily to distinguish between collection and recording grid later * getType() method is available for this purpose. The type of the grid is not being serialized or unserialized * * The following events are triggered: * * change_layout * when both or any of the two collections of Config gets new objects, looses objects or shuffles * (but not when parameters in individual parameter bags change) * * change_entity:c123 * change_view:c123 * when a particular parameter bag changes (c123 is replaced with a corresponding client id of an entity or a view) * * change_entity_neighbours:c123 * change_view_neighbours:c123 * when a Config, which is right before or right after the given parameter bag, changes * This includes cases when neighbours are added or removed * * change_selection * when selectedEntityConfigClientId or (and) selectedViewConfigClientId change * * change * this event is triggered together with any of the above ones, but * maximum once during a complex operation such as unserialize */ ContextModule.ConfigGrid = Backbone.Model.extend({ defaults: { entityConfigs: null, viewConfigs: null, selectedEntityConfigClientId: null, selectedViewConfigClientId: null }, /** * @memberOf App.ContextModule.ConfigGrid */ initialize: function(type) { this.type = type; this.attributes.entityConfigs = new ContextModule.ConfigCollection(null, { comparator: false, configGridType: type, dimension: "entity", }); this.attributes.viewConfigs = new ContextModule.ConfigCollection(null, { comparator: false, configGridType: type, dimension: "view", }); // Shortcuts for entity configs and view configs (for quicker access) this.entityConfigs = this.attributes.entityConfigs; this.viewConfigs = this.attributes.viewConfigs; this._modificationPropagationEnabled = true; this._configCollectionsWereModified = false; this._configsWereModified = false; this._modifiedEntityConfigClientIds = []; this._modifiedViewConfigClientIds = []; this._lastSavedOrderedEntityClientIds = _.pluck(this.attributes.entityConfigs.models, "cid"); this._lastSavedOrderedViewClientIds = _.pluck(this.attributes.viewConfigs.models, "cid"); this._lastSavedSelectedEntityConfigClientId = this.attributes.selectedEntityConfigClientId; this._lastSavedSelectedViewConfigClientId = this.attributes.selectedViewConfigClientId; this.entityConfigs.bind("add remove reset sort", this._registerModificationOfConfigCollectionForEntities, this); this.viewConfigs.bind("add remove reset sort", this._registerModificationOfConfigCollectionForViews, this); this.entityConfigs.bind("change", this._registerModificationOfConfig, this); this.viewConfigs.bind("change", this._registerModificationOfConfig, this); this.bind("change:selectedEntityConfigClientId", this._registerModificationOfAtomicProperty); this.bind("change:selectedViewConfigClientId", this._registerModificationOfAtomicProperty); this.bind("change:entityWidth", this._registerModificationOfStandardAtomicProperty); }, /** * @memberOf App.ContextModule.ConfigGrid */ getType: function() { return this.type; }, /** * @memberOf App.ContextModule.ConfigGrid */ getPrevEntityNeighbour: function(entityConfig) { return this._getNeighbour(this.attributes.entityConfigs, entityConfig, -1); }, /** * @memberOf App.ContextModule.ConfigGrid */ getNextEntityNeighbour: function(entityConfig) { return this._getNeighbour(this.attributes.entityConfigs, entityConfig, 1); }, /** * @memberOf App.ContextModule.ConfigGrid */ getPrevViewNeighbour: function(viewConfig) { return this._getNeighbour(this.attributes.viewConfigs, viewConfig, -1); }, /** * @memberOf App.ContextModule.ConfigGrid */ getNextViewNeighbour: function(viewConfig) { return this._getNeighbour(this.attributes.viewConfigs, viewConfig, 1); }, /** * @memberOf App.ContextModule.ConfigGrid */ relocateEntityConfig: function(entityConfig, indexOrNextConfigOrNextConfigClientId) { return this._relocate(this.attributes.entityConfigs, entityConfig, indexOrNextConfigOrNextConfigClientId); }, /** * @memberOf App.ContextModule.ConfigGrid */ relocateViewConfig: function(viewConfig, indexOrNextConfigOrNextConfigClientId) { return this._relocate(this.attributes.viewConfigs, viewConfig, indexOrNextConfigOrNextConfigClientId); }, /** * @memberOf App.ContextModule.ConfigGrid */ serialize: function() { logger.debug("method called: ConfigGrid::serialize"); var _this = this; var result = { entityConfigs: this.attributes.entityConfigs.map(function(config){ return config.serialize(); }), viewConfigs: this.attributes.viewConfigs.map(function(config){ return config.serialize(); }) }; if (this.attributes.selectedEntityConfigClientId) { result.selectedEntityConfigClientId = this.attributes.selectedEntityConfigClientId; } if (this.attributes.selectedViewConfigClientId) { result.selectedViewConfigClientId = this.attributes.selectedViewConfigClientId; } if (this.attributes.entityWidth) { result.entityWidth = this.attributes.entityWidth; } return result; }, getSelectedEntityConfig: function() { return this.attributes.entityConfigs.get(this.attributes.selectedEntityConfigClientId); }, getSelectedViewConfig: function() { return this.attributes.viewConfigs.get(this.attributes.selectedViewConfigClientId); }, // getSelectedConfigAtGivenDimension: function(dimension) { // if (dimension == "entity") { // return this.getSelectedEntityConfig(); // } else if (dimension == "view") { // return this.getSelectedViewConfig(); // } // }, // addEntityAndSelectIt: function(entityConfig, indexOrNextConfigOrNextConfigClientId) { this._addAndSelect(this.attributes.entityConfigs, entityConfig, _.isUndefined(indexOrNextConfigOrNextConfigClientId) ? null : indexOrNextConfigOrNextConfigClientId); }, addViewAndSelectIt: function(viewConfig, indexOrNextConfigOrNextConfigClientId) { this._addAndSelect(this.attributes.viewConfigs, viewConfig, _.isUndefined(indexOrNextConfigOrNextConfigClientId) ? null : indexOrNextConfigOrNextConfigClientId); }, removeEntityAndSelectNeighbour: function(entityConfig) { this._removeAndSelectNeighbour(this.attributes.entityConfigs, entityConfig); }, removeViewAndSelectNeighbour: function(viewConfig) { this._removeAndSelectNeighbour(this.attributes.viewConfigs, viewConfig); }, _addAndSelect: function(configCollection, config, indexOrNextConfigOrNextConfigClientId) { this._modificationPropagationEnabled = false; configCollection.add(config); if (configCollection == this.attributes.entityConfigs) { this.attributes.selectedEntityConfigClientId = config.getClientId(); } else { this.attributes.selectedViewConfigClientId = config.getClientId(); } this._relocate(configCollection, config, indexOrNextConfigOrNextConfigClientId); this._triggerModificationEventsIfNeeded(); this._modificationPropagationEnabled = true; }, _removeAndSelectNeighbour: function(configCollection, config) { this._modificationPropagationEnabled = false; var neighbourToSelect = this._getNeighbour(configCollection, config, 1); if (!neighbourToSelect) { neighbourToSelect = this._getNeighbour(configCollection, config, -1); } configCollection.remove(config); if (configCollection == this.attributes.entityConfigs) { this.attributes.selectedEntityConfigClientId = neighbourToSelect ? neighbourToSelect.getClientId() : null; } else { this.attributes.selectedViewConfigClientId = neighbourToSelect ? neighbourToSelect.getClientId() : null; } this._triggerModificationEventsIfNeeded(); this._modificationPropagationEnabled = true; }, /** * @memberOf App.ContextModule.ConfigGrid */ unserialize: function(serializedAttributes) { logger.debug("method called: ConfigGrid::unserialize"); this._modificationPropagationEnabled = false; var fixedSerializedAttributes = serializedAttributes; if (!_.isSimpleObject(serializedAttributes)) { logger.warn("ConfigGrid::unserialize called for not an object: ", serializedAttributes); fixedSerializedAttributes = {}; } // entityConfigs var newConfigs = []; var fixedSerializedConfigs = fixedSerializedAttributes.entityConfigs; if (!_.isArray(fixedSerializedConfigs)) { if (_.isSimpleObject(serializedAttributes)) { logger.warn("ConfigGrid::unserialize called for an object with faulty entityConfigs: ", fixedSerializedConfigs); } fixedSerializedConfigs = []; }; for (var i = 0; i < fixedSerializedConfigs.length; i++) { var serializedConfig = fixedSerializedConfigs[i]; var config = this.attributes.entityConfigs.get(serializedConfig.clientId); if (!config) { config = new App.ContextModule.Config(serializedConfig); } else { config.unserialize(serializedConfig); } newConfigs.push(config); } this.attributes.entityConfigs.reset(newConfigs); // viewConfigs var newConfigs = []; var fixedSerializedConfigs = fixedSerializedAttributes.viewConfigs; if (!_.isArray(fixedSerializedConfigs)) { if (_.isSimpleObject(serializedAttributes)) { logger.warn("ConfigGrid::unserialize called for an object with faulty viewConfigs: ", fixedSerializedConfigs); } fixedSerializedConfigs = []; }; for (var i = 0; i < fixedSerializedConfigs.length; i++) { var serializedConfig = fixedSerializedConfigs[i]; var config = this.attributes.viewConfigs.get(serializedConfig.clientId); if (!config) { config = new App.ContextModule.Config(serializedConfig); } else { config.unserialize(serializedConfig); } newConfigs.push(config); } this.attributes.viewConfigs.reset(newConfigs); // selectedEntityConfigClientId, selectedViewConfigClientId this.attributes.selectedEntityConfigClientId = fixedSerializedAttributes.selectedEntityConfigClientId; this.attributes.selectedViewConfigClientId = fixedSerializedAttributes.selectedViewConfigClientId; this.attributes.entityWidth = fixedSerializedAttributes.entityWidth; this._triggerModificationEventsIfNeeded(); this._modificationPropagationEnabled = true; }, _getNeighbour: function(configCollection, config, offset) { var index = configCollection.indexOf(config); if (index === -1) { throw _.str.sprintf("Can't find config %s", JSON.stringify(config.serialize())); } return configCollection.at(index + offset); }, _relocate: function(configCollection, config, indexOrNextConfigOrNextConfigClientId) { var clientIds = _.pluck(configCollection.models, "cid"); var nextConfigClientId = null; if (_.isNumber(indexOrNextConfigOrNextConfigClientId) && indexOrNextConfigOrNextConfigClientId != clientIds.length) { nextConfigClientId = clientIds[indexOrNextConfigOrNextConfigClientId]; } if (_.isObject(indexOrNextConfigOrNextConfigClientId)) { nextConfigClientId = indexOrNextConfigOrNextConfigClientId.getClientId(); } if (_.isString(indexOrNextConfigOrNextConfigClientId)) { if (clientIds.indexOf(indexOrNextConfigOrNextConfigClientId) !== -1) { nextConfigClientId = indexOrNextConfigOrNextConfigClientId; } } if (!nextConfigClientId && !_.isNull(indexOrNextConfigOrNextConfigClientId) && indexOrNextConfigOrNextConfigClientId != configCollection.size()) { throw _.str.sprintf("Wrong value for indexOrNextConfigOrNextConfigClientId %s", indexOrNextConfigOrNextConfigClientId); } var configClientId = config.getClientId(); if (!configClientId || clientIds.indexOf(configClientId) == -1) { var flattenedConfig = config; if (_.isObject(flattenedConfig)) { flattenedConfig = JSON.stringify(flattenedConfig); } throw _.str.sprintf("Config %s with cid %s is either not a Config or does not belong to a corresponding configCollection with cids [%s]", flattenedConfig, _.isObject(config ) ? config.getClientId() : undefined, clientIds.join(", ")); } if (configCollection.get(configClientId) !== config) { throw _.str.sprintf("Config %s with cid %s is is a clone of what is stored in the grid. Relocation is not possible.", JSON.stringify(config), config.cid); } var newClientIds = _.without(clientIds, configClientId); if (_.isNull(nextConfigClientId)) { newClientIds.push(configClientId); } else { var nextConfigIndex = newClientIds.indexOf(nextConfigClientId); //if (nextConfigIndex) var tempClientIds = newClientIds.slice(0, nextConfigIndex); tempClientIds.push(configClientId); newClientIds = tempClientIds.concat(newClientIds.slice(nextConfigIndex)); } var oldComparator = configCollection.comparator; configCollection.comparator = function(model) { return newClientIds.indexOf(model.getClientId()); }; configCollection.sort(); configCollection.comparator = oldComparator; }, _registerModificationOfConfigCollectionForEntities: function(modelOrModels, options) { if (!_.isEqual(this._lastSavedOrderedEntityClientIds, _.pluck(this.attributes.entityConfigs.models, "cid"))) { this._configCollectionsWereModified = true; if (this._modificationPropagationEnabled) { this._triggerModificationEventsIfNeeded(); }; } }, _registerModificationOfConfigCollectionForViews: function(modelOrModels, options) { if (!_.isEqual(this._lastSavedOrderedViewClientIds, _.pluck(this.attributes.viewConfigs.models, "cid"))) { this._configCollectionsWereModified = true; if (this._modificationPropagationEnabled) { this._triggerModificationEventsIfNeeded(); }; } }, _registerModificationOfConfig: function() { for (var i = 0; i < this.attributes.entityConfigs.length; i++) { if(this.attributes.entityConfigs.at(i).hasChanged()) { this._configsWereModified = true; this._modifiedEntityConfigClientIds.push(this.attributes.entityConfigs.at(i).getClientId()); } } for (var i = 0; i < this.attributes.viewConfigs.length; i++) { if(this.attributes.viewConfigs.at(i).hasChanged()) { this._configsWereModified = true; this._modifiedViewConfigClientIds.push(this.attributes.viewConfigs.at(i).getClientId()); } } if (this._modificationPropagationEnabled) { this._triggerModificationEventsIfNeeded(); }; }, _registerModificationOfAtomicProperty: function() { if (this._modificationPropagationEnabled) { this._triggerModificationEventsIfNeeded(true); }; }, _registerModificationOfStandardAtomicProperty: function() { if (this._modificationPropagationEnabled) { this._triggerModificationEventsIfNeeded(); }; }, _triggerModificationEventsIfNeeded: function(specialCaseForRegisterModificationOfSelection) { var triggeredAtLeastSomething = false; if (this._configCollectionsWereModified) { triggeredAtLeastSomething = true; this.trigger("change_layout"); } var newOrderedEntityClientIds = null; var newOrderedViewClientIds = null; if (this._configCollectionsWereModified || this._modifiedEntityConfigClientIds.length || this._modifiedViewConfigClientIds.length) { newOrderedEntityClientIds = _.pluck(this.attributes.entityConfigs.models, "cid"); newOrderedViewClientIds = _.pluck(this.attributes.viewConfigs.models, "cid"); // change_entity:c123 if (this._modifiedEntityConfigClientIds.length) { for (var i = 0; i < newOrderedEntityClientIds.length; i++) { if (_.indexOf(this._modifiedEntityConfigClientIds, newOrderedEntityClientIds[i]) !== -1) { triggeredAtLeastSomething = true; this.trigger("change_entity:" + newOrderedEntityClientIds[i]); } } } // change_view:c123 if (this._modifiedViewConfigClientIds.length) { for (var i = 0; i < newOrderedViewClientIds.length; i++) { if (_.indexOf(this._modifiedViewConfigClientIds, newOrderedViewClientIds[i]) !== -1) { triggeredAtLeastSomething = true; this.trigger("change_view:" + newOrderedViewClientIds[i]); } } } // change_entity_neighbours:c123 for (var i = 0; i < newOrderedEntityClientIds.length; i++) { var entityClientId = newOrderedEntityClientIds[i]; var oldEntityIndex = this._lastSavedOrderedEntityClientIds.indexOf(entityClientId); if (oldEntityIndex == -1) { continue; } var newPrevEntityClientId = newOrderedEntityClientIds[i - 1]; var newNextEntityClientId = newOrderedEntityClientIds[i + 1]; var oldPrevEntityClientId = this._lastSavedOrderedEntityClientIds[oldEntityIndex - 1]; var oldNextEntityClientId = this._lastSavedOrderedEntityClientIds[oldEntityIndex + 1]; if (newPrevEntityClientId != oldPrevEntityClientId || newNextEntityClientId != oldNextEntityClientId || this._modifiedEntityConfigClientIds.indexOf(newPrevEntityClientId) !== -1 || this._modifiedEntityConfigClientIds.indexOf(newNextEntityClientId) !== -1 ) { triggeredAtLeastSomething = true; this.trigger("change_entity_neighbours:" + entityClientId); }; } // change_view_neighbours:c123 for (var i = 0; i < newOrderedViewClientIds.length; i++) { var viewClientId = newOrderedViewClientIds[i]; var oldViewIndex = this._lastSavedOrderedViewClientIds.indexOf(viewClientId); if (oldViewIndex == -1) { continue; } var newPrevViewClientId = newOrderedViewClientIds[i - 1]; var newNextViewClientId = newOrderedViewClientIds[i + 1]; var oldPrevViewClientId = this._lastSavedOrderedViewClientIds[oldViewIndex - 1]; var oldNextViewClientId = this._lastSavedOrderedViewClientIds[oldViewIndex + 1]; if (newPrevViewClientId != oldPrevViewClientId || newNextViewClientId != oldNextViewClientId || this._modifiedViewConfigClientIds.indexOf(newPrevViewClientId) !== -1 || this._modifiedViewConfigClientIds.indexOf(newNextViewClientId) !== -1 ) { triggeredAtLeastSomething = true; this.trigger("change_view_neighbours:" + viewClientId); }; }; } this._lastSavedOrderedEntityClientIds = _.pluck(this.attributes.entityConfigs.models, "cid"); this._lastSavedOrderedViewClientIds = _.pluck(this.attributes.viewConfigs.models, "cid"); // Fix selection if (!this.attributes.entityConfigs.get(this.attributes.selectedEntityConfigClientId)) { this.attributes.selectedEntityConfigClientId = null; } if (!this.attributes.viewConfigs.get(this.attributes.selectedViewConfigClientId)) { this.attributes.selectedViewConfigClientId = null; } if (this._lastSavedSelectedEntityConfigClientId != this.attributes.selectedEntityConfigClientId || this._lastSavedSelectedViewConfigClientId != this.attributes.selectedViewConfigClientId ) { if (!specialCaseForRegisterModificationOfSelection) { triggeredAtLeastSomething = true; } this.trigger("change_selection"); } if (this._lastSavedEntityWidth != this.attributes.entityWidth) { triggeredAtLeastSomething = true; } this._configCollectionsWereModified = false; this._configsWereModified = false; this._selectionWasModified = false; this._modifiedEntityConfigClientIds = []; this._modifiedViewConfigClientIds = []; this._lastSavedSelectedEntityConfigClientId = this.attributes.selectedEntityConfigClientId; this._lastSavedSelectedViewConfigClientId = this.attributes.selectedViewConfigClientId; this._lastSavedEntityWidth = this.attributes.entityWidth; if (triggeredAtLeastSomething) { this.trigger("change"); } }, }); }); }, Logger);