From 5a1c64c71c9326b7865cf6c65266590e50846dc4 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Wed, 18 Apr 2018 17:35:29 -0400 Subject: [PATCH 01/65] Revert default css rules for the image component. --- ui/image.reel/image.css | 7 ------- ui/list-item.reel/list-item.css | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/image.reel/image.css b/ui/image.reel/image.css index 945f8fdcd7..9639fc6d63 100644 --- a/ui/image.reel/image.css +++ b/ui/image.reel/image.css @@ -1,10 +1,3 @@ -.montage-image { - position: relative; - width: 100%; - height: 100%; - display: inline-block; -} - .montage-image[hidden] { display: none !important; } diff --git a/ui/list-item.reel/list-item.css b/ui/list-item.reel/list-item.css index dbd74c0f22..e8d69aea30 100755 --- a/ui/list-item.reel/list-item.css +++ b/ui/list-item.reel/list-item.css @@ -76,6 +76,13 @@ justify-content: center; } +.ListItem .ListItem-icon .montage-image { + position: relative; + height: 24px; + width: 24px; + display: inline-block; +} + /** Label + description **/ .ListItem .ListItem-text { From a4c1e74b756fc219bb59a060b8bce3f58772f3c5 Mon Sep 17 00:00:00 2001 From: Thomas Jaede Date: Wed, 16 May 2018 19:38:38 -0700 Subject: [PATCH 02/65] Add serialization/deserialization to Map --- core/core.js | 1 + core/extras/map.js | 49 ++++ data/service/raw-data-worker.js | 364 ++++++++++++++++++++++++++++++ test/sentinel.js | 16 ++ test/spec/core/extras/map.js | 90 ++++++++ test/spec/data/raw-data-worker.js | 280 +++++++++++++++++++++++ 6 files changed, 800 insertions(+) create mode 100644 core/extras/map.js create mode 100644 data/service/raw-data-worker.js create mode 100644 test/sentinel.js create mode 100644 test/spec/core/extras/map.js create mode 100644 test/spec/data/raw-data-worker.js diff --git a/core/core.js b/core/core.js index 944ab6e4a9..30f90ee968 100644 --- a/core/core.js +++ b/core/core.js @@ -9,6 +9,7 @@ require("./extras/object"); require("./extras/date"); require("./extras/element"); require("./extras/function"); +require("./extras/map"); require("./extras/regexp"); require("./extras/string"); require("proxy-polyfill/proxy.min"); diff --git a/core/extras/map.js b/core/extras/map.js new file mode 100644 index 0000000000..c4fa896e3b --- /dev/null +++ b/core/extras/map.js @@ -0,0 +1,49 @@ +/** + Defines extensions to intrinsic `Map`. + @see {external:Map} + @module montage/core/extras/map +*/ + +/** + * Deserialize a map object included in a serialization + * @param {Deserializer} deserializer The Deserializer containing the serialization information + * @function external:Map.deserializeSelf +*/ +Object.defineProperty(Map.prototype, "deserializeSelf", { + value: function (deserializer) { + var entries, keys, values, + i, n; + + entries = deserializer.getProperty("entries"); + if (entries) { + for (i = 0, n = entries.length; i < n; i++) { + this.set(entries[i].key, entries[i].value); + } + } + if (!entries) { + keys = deserializer.getProperty("keys"); + values = deserializer.getProperty("values"); + if (keys && values) { + for (i = 0, n = keys.length; i < n; i++) { + this.set(keys[i], values[i]); + } + } + } + }, + writable: true, + configurable: true +}); + + +/** + * Deserialize a map object included in a serialization + * @param {Deserializer} deserializer The Serializer building out the serialization + * @function external:Map.deserializeSelf +*/ +Object.defineProperty(Map.prototype, "serializeSelf", { + value: function (serializer) { + + }, + writable: true, + configurable: true +}); \ No newline at end of file diff --git a/data/service/raw-data-worker.js b/data/service/raw-data-worker.js new file mode 100644 index 0000000000..eea656491a --- /dev/null +++ b/data/service/raw-data-worker.js @@ -0,0 +1,364 @@ +var Montage = require("montage").Montage, + Criteria = require("core/criteria").Criteria, + DataQuery = require("data/model/data-query").DataQuery, + Map = require("collections/map"), + ModuleReference = require("core/module-reference").ModuleReference, + ObjectDescriptor = require("core/meta/object-descriptor").ObjectDescriptor, + OperationType = require("data/service/data-operation").DataOperation.Type, + Promise = require("core/promise").Promise; + + +exports.RawDataWorker = Montage.specialize({ + + + + /*************************************************************************** + * Serialization + */ + + // serializeSelf: { + // value: function (serializer) { + // } + // }, + + deserializeSelf: { + value: function (deserializer) { + var references = deserializer.getProperty("childServices") || []; + + // this.registerServiceReferences(references); + + var value = deserializer.getProperty("childServicesMap") || []; + this.registerServiceReferencesMap(value); + + value = deserializer.getProperty("childServicesArrays") || []; + this.registerServiceReferencesArray(value); + } + }, + + registerServiceReferencesArray: { + value: function (references) { + var map = new Map(), + keys = references.keys, + values = references.values, + i, n; + + for (i = 0, n = keys.length; i < n; i++) { + map.set(keys[i], values[i]); + } + + this._childServicesArrays = map; + } + }, + + + registerServiceReferencesMap: { + value: function (references) { + var map = new Map(), + i, n; + + for (i = 0, n = references.length; i < n; i++) { + map.set(references[i].key, references[i].value); + } + + this._childServicesMap = map; + } + }, + + + /*************************************************************************** + * Service Tree + */ + + + _serviceReferenceRegistrationPromise: { + get: function () { + if (!this.__serviceReferenceRegistrationPromise) { + this.__serviceReferenceRegistrationPromise = Promise.resolve(null); + } + return this.__serviceReferenceRegistrationPromise; + } + }, + + serviceReferences: { + get: function() { + if (!this._serviceReferences) { + this._serviceReferences = new Set(); + } + return this._serviceReferences; + } + }, + + serviceReferenceByObjectDescriptor: { + get: function () { + if (!this._serviceReferenceByObjectDescriptor) { + this._serviceReferenceByObjectDescriptor = new Map(); + } + return this._serviceReferenceByObjectDescriptor; + } + }, + + serviceReferenceForObjectDescriptor: { + value: function (type) { + var services; + type = type instanceof ObjectDescriptor ? type : this._objectDescriptorForType(type); + services = this._serviceReferenceByObjectDescriptor.get(type) || this._serviceReferenceByObjectDescriptor.get(null); + return services && services[0] || null; + } + }, + + registerServiceReferences: { + value: function (serviceReferences) { + var self; + if (!this.__serviceReferenceRegistrationPromise) { + self = this; + this.__serviceReferenceRegistrationPromise = Promise.all(serviceReferences.map(function (service) { + return self.registerServiceReference(service); + })); + } + } + }, + + registerServiceReference: { + value: function (service, types) { + var self = this; + // possible types + // -- types is passed in as an array or a single type. + // -- a model is set on the service. + // -- types is set on the service. + // any type can be asychronous or synchronous. + types = types && Array.isArray(types) && types || + types && [types] || + service.model && service.model.objectDescriptors || + service.types && Array.isArray(service.types) && service.types || + service.types && [service.types] || + []; + + return this._registerServiceReferenceObjectDescriptors(service, types); + } + }, + + _registerServiceReferenceObjectDescriptors: { + value: function (service, types) { + this._addServiceReference(service, types); + this._registerObjectDescriptorsByModuleId(types); + return this.nullPromise; + } + }, + + _addServiceReference: { + value: function (service, types) { + var serviceReference, type, i, n, nIfEmpty = 1; + types = types || service.model && service.model.objectDescriptors || service.types; + + // Add the new service to this service's serviceren set. + this.serviceReferences.add(service); + + // Add the new service service to the services array of each of its + // types or to the "all types" service array identified by the + // `null` type, and add each of the new service's types to the array + // of service types if they're not already there. + for (i = 0, n = types && types.length || nIfEmpty; i < n; i += 1) { + type = types && types.length && types[i] || null; + serviceReference = this.serviceReferenceByObjectDescriptor.get(type) || []; + serviceReference.push(service); + if (serviceReference.length === 1) { + this.serviceReferenceByObjectDescriptor.set(type, serviceReference); + } + } + } + }, + + _registerObjectDescriptorsByModuleId: { + value: function (types) { + var self = this; + types.forEach(function (objectDescriptor) { + var module = objectDescriptor.module, + moduleId = [module.id, objectDescriptor.exportName].join("/"); + self.objectDescriptorsByModuleID.set(moduleId, objectDescriptor); + }); + } + }, + + nullPromise: { + get: function () { + if (!exports.RawDataWorker._nullPromise) { + exports.RawDataWorker._nullPromise = Promise.resolve(null); + } + return exports.RawDataWorker._nullPromise; + } + }, + + /*************************************************************************** + * Operation Handlers + */ + + handleOperation: { + value: function (operation) { + var self = this, + objectDescriptor, service; + + return this._serviceReferenceRegistrationPromise.then(function () { + return self._objectDescriptorForOperation(operation); + }).then(function (descriptor) { + objectDescriptor = descriptor; + return self._serviceForObjectDescriptor(descriptor); + }).then(function (service) { + var handlerName = self._handlerNameForOperationType(operation.type); + if (!service) { + // console.log(operation, self, objectDescriptor); + throw new Error("No service available to handle operation with type (" + (objectDescriptor && objectDescriptor.name) + ")"); + } + return self[handlerName](operation, service, objectDescriptor); + }); + } + }, + + _handlerNameForOperationType: { + value: function (operationType) { + var name = "_perform"; + name += this._operationTypeNameByOperationType(operationType); + return name + "Operation"; + } + }, + + _operationTypeNameByOperationType: { + value: function (operationType) { + return operationType.isCreate ? "Create" : + operationType.isRead ? "Read" : + operationType.isUpdate ? "Update" : + operationType.isDelete ? "Delete" : + null; + } + }, + + _performCreateOperation: { + value: function (operation, service, objectDescriptor) { + return service.saveRawData(operation.data); + } + }, + + _performDeleteOperation: { + value: function (operation, service, objectDescriptor) { + return service.deleteRawData(operation.data); + } + }, + + _performReadOperation: { + value: function (operation, service, objectDescriptor) { + var criteria = operation.criteria || operation.data, + query, parameters, expression; + + if (!(criteria instanceof Criteria)) { + parameters = criteria ? criteria.parameters : {}; + expression = criteria ? criteria.expression : ""; + criteria = new Criteria().initWithExpression(expression, parameters); + } + query = DataQuery.withTypeAndCriteria(objectDescriptor, criteria); + + return service.fetchData(query); + } + }, + + _performUpdateOperation: { + value: function (operation, service, objectDescriptor) { + return service.saveRawData(operation.data); + } + }, + + /*************************************************************************** + * Service & ObjectDescriptor Creation + */ + + objectDescriptorForType: { + value: function () { + + } + }, + + _serviceReferenceForObjectDescriptor: { + value: function (objectDescriptor) { + var services = this.serviceReferenceByObjectDescriptor.get(objectDescriptor); + services = services || this.serviceReferenceByObjectDescriptor.get(null); + return services && services[0] || null; + } + }, + + _serviceForObjectDescriptor: { + value: function (objectDescriptor) { + var self = this, + serviceReference = this._serviceReferenceForObjectDescriptor(objectDescriptor), + service = serviceReference && this.servicesByModuleID.get(serviceReference.moduleId); + + + + return !serviceReference ? Promise.resolve(null) : + service ? Promise.resolve(service) : + serviceReference.promise.then(function (service) { + self._servicesByModuleID.set(serviceReference.moduleId, service); + return service; + }); + } + }, + + _objectDescriptorForOperation: { + value: function (operation) { + var self = this, + descriptorOrModule = operation.dataType, + module, descriptor, result, moduleId; + + if (descriptorOrModule instanceof ModuleReference) { + module = descriptorOrModule; + descriptor = this.objectDescriptorsByModuleID.get(module.id); + if (descriptor) { + result = Promise.resolve(descriptor); + } else { + result = module.exports.then(function (exports) { + var instance = exports.montageObject, + moduleId = [module.id, instance.exportName].join("/"); + self.objectDescriptorsByModuleID.set(module.id, instance); + self.objectDescriptorsByModuleID.set(moduleId, instance); + return instance; + }); + } + } else if (descriptorOrModule instanceof ObjectDescriptor){ + descriptor = descriptorOrModule; + module = descriptor.module; + moduleId = [module.id, descriptor.exportName].join("/"); + if (!this.objectDescriptorsByModuleID.has(moduleId)) { + this.objectDescriptorsByModuleID.set(moduleId, descriptor); + } else { + descriptor = this.objectDescriptorsByModuleID.get(moduleId); + } + result = Promise.resolve(descriptor); + } + + + + + return result; + } + }, + + /*************************************************************************** + * Service/Type Caching + */ + + servicesByModuleID: { + get: function () { + if (!this._servicesByModuleID) { + this._servicesByModuleID = new Map(); + } + return this._servicesByModuleID; + } + }, + + objectDescriptorsByModuleID: { + get: function () { + if (!this._objectDescriptorsByModuleID) { + this._objectDescriptorsByModuleID = new Map(); + } + return this._objectDescriptorsByModuleID; + } + } + +}); \ No newline at end of file diff --git a/test/sentinel.js b/test/sentinel.js new file mode 100644 index 0000000000..0d45db990a --- /dev/null +++ b/test/sentinel.js @@ -0,0 +1,16 @@ +console.log('montage-testing', 'Start'); + +module.exports = require("montage-testing").run(require, [ + + {name: "spec/core/extras/map"}, + {name: "spec/data/raw-data-worker"}, + {name: "spec/data/data-service-mapping"}, + {name: "spec/data/raw-data-service"}, + {name: "spec/data/data-service"} + +]).then(function () { + console.log('montage-testing', 'End'); +}, function (err) { + console.log('montage-testing', 'Fail', err, err.stack); + throw err; +}); diff --git a/test/spec/core/extras/map.js b/test/spec/core/extras/map.js new file mode 100644 index 0000000000..c53cee0843 --- /dev/null +++ b/test/spec/core/extras/map.js @@ -0,0 +1,90 @@ +var Deserializer = require("montage/core/serialization/deserializer/montage-deserializer").MontageDeserializer, + deserialize = require("montage/core/serialization/deserializer/montage-deserializer").deserialize; + +require("montage"); + +describe("core/extras/map", function () { + + describe("Map#deserializeSelf", function () { + + it("can deserialize with entries", function (done) { + + var deserializer = new Deserializer(), + entries = [], + serialization = { + "root": { + "prototype": "collections/map[Map]", + "values": { + "entries": entries + } + } + }, + string, i; + + for (i = 0; i < 5000; ++i) { + entries.push({key: i, value:{name: i}}); + } + + string = JSON.stringify(serialization); + deserializer.init(string, require); + console.time("entries"); + return deserializer.deserializeObject().then(function (root) { + console.timeEnd("entries"); + console.log("Map1", root); + expect(root instanceof Map).toBeTruthy(); + done(); + }).catch(function(reason) { + console.warn(reason); + fail(reason); + }); + + }); + + it("can deserialize with keys and values", function (done) { + var deserializer = new Deserializer(), + keys = [], + values = [], + serialization = { + "root": { + "prototype": "collections/map[Map]", + "values": { + "keys": keys, + "values": values + } + } + }, + string, i; + + for (i = 0; i < 5000; ++i) { + keys.push(i); + values.push({name: i}); + } + string = JSON.stringify(serialization); + deserializer.init(string, require); + console.time("keyValues"); + return deserializer.deserializeObject().then(function (root) { + console.timeEnd("keyValues"); + console.log("Map2", root); + expect(root instanceof Map).toBeTruthy(); + done(); + }).catch(function(reason) { + console.warn(reason); + fail(reason); + }); + + + }); + + }); + + describe("Map#serializeSelf", function () { + + xit("can serialize", function () { + expect("abc".contains("bc")).toBe(true); + }); + + + }); + +}); + diff --git a/test/spec/data/raw-data-worker.js b/test/spec/data/raw-data-worker.js new file mode 100644 index 0000000000..607d4debc0 --- /dev/null +++ b/test/spec/data/raw-data-worker.js @@ -0,0 +1,280 @@ +var RawDataWorker = require("montage/data/service/raw-data-worker").RawDataWorker, + DataOperation = require("montage/data/service/data-operation").DataOperation, + OperationType = require("montage/data/service/data-operation").DataOperation.Type, + Category = require("spec/data/logic/model/category").Category, + CategoryDescriptor = require("spec/data/logic/model/category.mjson").montageObject, + Criteria = require("montage/core/criteria").Criteria, + DataMapping = require("montage/data/service/data-mapping").DataMapping, + DataService = require("montage/data/service/data-service").DataService, + DataServiceReference = require("montage/data/service/data-service-reference").DataServiceReference, + DataStream = require("montage/data/service/data-stream").DataStream, + DataObjectDescriptor = require("montage/data/model/data-object-descriptor").DataObjectDescriptor, + ObjectDescriptor = require("montage/core/meta/object-descriptor").ObjectDescriptor, + ModuleReference = require("montage/core/module-reference").ModuleReference, + MovieDescriptor = require("spec/data/logic/model/movie.mjson").montageObject, + RawDataTypeMapping = require("montage/data/service/raw-data-type-mapping").RawDataTypeMapping; + + + +var Deserializer = require("montage/core/serialization/deserializer/montage-deserializer").MontageDeserializer, + deserialize = require("montage/core/serialization/deserializer/montage-deserializer").deserialize; + +describe("A RawDataWorker", function() { + var worker, + typeReference, + operation; + + function makeOperation(operationType, dataType, data, criteria) { + var newOperation = new DataOperation(); + newOperation.type = operationType; + newOperation.dataType = dataType; + newOperation.data = data; + newOperation.criteria = criteria; + return newOperation; + } + + it("can be created", function () { + expect(new RawDataWorker()).toBeDefined(); + }); + + it("can register service references", function (done) { + var serviceID = "spec/data/logic/service/category-service.mjson", + types = [CategoryDescriptor], + serviceReference = new DataServiceReference().initWithIdTypesAndRequire(serviceID, types, require); + worker = new RawDataWorker(); + + worker.registerServiceReference(serviceReference).then(function () { + expect(worker.serviceReferences.size).toBe(1); + done(); + }); + }); + + + describe("can lazily", function () { + + it("register type for DataOperation with descriptor", function (done) { + var movieDescriptor, operation2; + + operation = makeOperation(null, CategoryDescriptor); + operation2 = makeOperation(null, CategoryDescriptor); + worker._objectDescriptorForOperation(operation).then(function (descriptor) { + expect(descriptor).toBeDefined(); + movieDescriptor = descriptor; + return worker._objectDescriptorForOperation(operation2); + }).then(function (descriptor) { + expect(descriptor).toBeDefined(); + expect(descriptor).toBe(movieDescriptor); + done(); + }); + }); + + it("register type for DataOperation with reference", function (done) { + var movieDescriptor, operation2; + typeReference = new ModuleReference().initWithIdAndRequire("spec/data/logic/model/category.mjson", require); + operation = makeOperation(null, typeReference); + operation2 = makeOperation(null, typeReference); + worker._objectDescriptorForOperation(operation).then(function (descriptor) { + expect(descriptor).toBeDefined(); + movieDescriptor = descriptor; + return worker._objectDescriptorForOperation(operation2); + }).then(function (descriptor) { + expect(descriptor).toBeDefined(); + expect(descriptor).toBe(movieDescriptor); + done(); + }); + }); + + it("register type for DataOperation with descriptor & reference", function (done) { + var movieDescriptor, operation2; + typeReference = new ModuleReference().initWithIdAndRequire("spec/data/logic/model/category.mjson", require); + operation = makeOperation(null, CategoryDescriptor); + operation2 = makeOperation(null, typeReference); + worker._objectDescriptorForOperation(operation).then(function (descriptor) { + expect(descriptor).toBeDefined(); + movieDescriptor = descriptor; + return worker._objectDescriptorForOperation(operation2); + }).then(function (descriptor) { + expect(descriptor).toBeDefined(); + expect(descriptor).toBe(movieDescriptor); + done(); + }); + }); + + it("register type for DataOperation with reference & descriptor", function (done) { + var movieDescriptor, operation2; + typeReference = new ModuleReference().initWithIdAndRequire("spec/data/logic/model/category.mjson", require); + operation = makeOperation(null, typeReference); + operation2 = makeOperation(null, CategoryDescriptor); + worker._objectDescriptorForOperation(operation).then(function (descriptor) { + expect(descriptor).toBeDefined(); + movieDescriptor = descriptor; + return worker._objectDescriptorForOperation(operation2); + }).then(function (descriptor) { + expect(descriptor).toBeDefined(); + expect(descriptor).toBe(movieDescriptor); + done(); + }); + }); + + }); + + describe("can handle basic ", function () { + // worker = new RawDataWorker(); + + it("create operation", function (done) { + var rawData = { + name: "Comedy" + }; + operation = makeOperation(OperationType.Create, CategoryDescriptor, rawData); + + worker.handleOperation(operation).then(function (data) { + expect(Array.isArray(data)).toBe(true); + expect(data[1]).toBe(rawData.name); + done(); + }); + }); + + it("read operation", function (done) { + + operation = makeOperation(OperationType.Read, CategoryDescriptor); + + worker.handleOperation(operation).then(function (data) { + expect(Array.isArray(data)).toBe(true); + expect(data.length).toBe(1); + done(); + }); + }); + + it("update operation", function (done) { + var rawData = { + name: "Science Fiction", + categoryID: 1 + }; + //Should use criteria to identify which object to update + operation = makeOperation(OperationType.Update, CategoryDescriptor, rawData); + + worker.handleOperation(operation).then(function (data) { + expect(Array.isArray(data)).toBe(true); + expect(data[1]).toBe(rawData.name); + done(); + }); + }); + + + it("delete operation", function (done) { + var rawData = { + name: "Science Fiction", + categoryID: 1 + }; + operation = makeOperation(OperationType.Delete, CategoryDescriptor, rawData); + + worker.handleOperation(operation).then(function (data) { + expect(Array.isArray(data)).toBe(true); + expect(data.length).toBe(1); + done(); + }); + }); + }); + + describe("can handle read operation", function () { + worker = new RawDataWorker(); + + it("with criteria", function (done) { + criteria = new Criteria().initWithExpression("id == $.id", { + categoryID: 1 + }); + operation = makeOperation(OperationType.Read, CategoryDescriptor, null, criteria); + + worker.handleOperation(operation).then(function (data) { + expect(Array.isArray(data)).toBe(true); + expect(data.length).toBe(1); + expect(data[0].name).toBe("Action"); + done(); + }); + + }); + + }); + + describe("can deserialize", function () { + it("without childServices", function (done) { + var deserializer = new Deserializer(); + serialization = { + "root": { + "prototype": "montage/data/service/raw-data-worker", + "values": { + "name": "RawDataWorker" + } + } + }, + serializationString = JSON.stringify(serialization); + + deserializer.init(serializationString, require); + deserializer.deserializeObject().then(function (root) { + expect(Object.getPrototypeOf(root)).toBe(RawDataWorker.prototype); + }).catch(function(reason) { + fail(reason); + }).finally(function () { + done(); + }); + }); + + it("with childServices", function (done) { + var deserializer = new Deserializer(); + serialization = { + "root": { + "prototype": "montage/data/service/raw-data-worker", + "values": { + "name": "RawDataWorker", + "childServices": {"@": "ChildServicesMap"} + } + }, + "ChildServicesMap": { + "prototype": "collections/map[Map]", + "values": { + "keys": [ + {"@": "Category"}, + {"@": "Movie"} + ], + "values": [ + {"%": "spec/data/logic/service/category-service.mjson"}, + {"%": "spec/data/logic/service/movie-service.mjson"} + ] + } + }, + + "Category": { + "object": "spec/data/logic/model/category.mjson" + }, + + "Movie": { + "object": "spec/data/logic/model/category.mjson" + }, + }, + serializationString = JSON.stringify(serialization), + operation = makeOperation(OperationType.Read, CategoryDescriptor); + operation2 = makeOperation(OperationType.Read, MovieDescriptor); + + deserializer.init(serializationString, require); + deserializer.deserializeObject().then(function (root) { + expect(Object.getPrototypeOf(root)).toBe(RawDataWorker.prototype); + expect(root.serviceReferences.size).toBe(2); + return root.handleOperation(operation).then(function (data) { + expect(Array.isArray(data)).toBe(true); + expect(data.length).toBe(1); + expect(data[0] instanceof Category).toBe(true); + return root.handleOperation(operation2); + }).then(function (data) { + expect(Array.isArray(data)).toBe(true); + expect(data.length).toBe(1); + return null; + }); + }).catch(function(reason) { + fail(reason); + }).finally(function () { + done(); + }); + + }); + }); +}) \ No newline at end of file From 3f4980b60189c48490f24eb21d18287453f20c69 Mon Sep 17 00:00:00 2001 From: Thomas Jaede Date: Thu, 17 May 2018 08:40:15 -0700 Subject: [PATCH 03/65] Add support for Map, Set, WeakMap as serialization prototypes --- core/core.js | 2 + core/extras/map.js | 98 +++++++++------- core/extras/set.js | 48 ++++++++ core/extras/weak-map.js | 59 ++++++++++ .../deserializer/montage-reviver.js | 9 +- .../serializer/montage-visitor.js | 71 ++++++++++++ test/sentinel.js | 2 + test/spec/core/extras/map.js | 39 +++++-- test/spec/core/extras/set.js | 72 ++++++++++++ test/spec/core/extras/weak-map.js | 108 ++++++++++++++++++ 10 files changed, 453 insertions(+), 55 deletions(-) create mode 100644 core/extras/set.js create mode 100644 core/extras/weak-map.js create mode 100644 test/spec/core/extras/set.js create mode 100644 test/spec/core/extras/weak-map.js diff --git a/core/core.js b/core/core.js index 30f90ee968..fcd2f05df5 100644 --- a/core/core.js +++ b/core/core.js @@ -12,6 +12,8 @@ require("./extras/function"); require("./extras/map"); require("./extras/regexp"); require("./extras/string"); +require("./extras/set"); +require("./extras/weak-map"); require("proxy-polyfill/proxy.min"); diff --git a/core/extras/map.js b/core/extras/map.js index c4fa896e3b..5c8c1f3d14 100644 --- a/core/extras/map.js +++ b/core/extras/map.js @@ -1,49 +1,61 @@ -/** - Defines extensions to intrinsic `Map`. - @see {external:Map} - @module montage/core/extras/map -*/ + /** + Defines extensions to intrinsic `Map`. + @see {external:Map} + @module montage/core/extras/map + */ -/** - * Deserialize a map object included in a serialization - * @param {Deserializer} deserializer The Deserializer containing the serialization information - * @function external:Map.deserializeSelf -*/ -Object.defineProperty(Map.prototype, "deserializeSelf", { - value: function (deserializer) { - var entries, keys, values, - i, n; + /** + * Deserialize a map object included in a serialization + * @param {Deserializer} deserializer The Deserializer containing the serialization information + * @function external:Map.deserializeSelf + */ + Object.defineProperty(Map.prototype, "deserializeSelf", { + value: function (deserializer) { + var entries, keys, values, + i, n; - entries = deserializer.getProperty("entries"); - if (entries) { - for (i = 0, n = entries.length; i < n; i++) { - this.set(entries[i].key, entries[i].value); - } - } - if (!entries) { - keys = deserializer.getProperty("keys"); - values = deserializer.getProperty("values"); - if (keys && values) { - for (i = 0, n = keys.length; i < n; i++) { - this.set(keys[i], values[i]); + entries = deserializer.getProperty("entries"); + if (entries) { + for (i = 0, n = entries.length; i < n; i++) { + this.set(entries[i].key, entries[i].value); + } + } + if (!entries) { + keys = deserializer.getProperty("keys"); + values = deserializer.getProperty("values"); + if (keys && values) { + for (i = 0, n = keys.length; i < n; i++) { + this.set(keys[i], values[i]); + } } } - } - }, - writable: true, - configurable: true -}); + }, + writable: true, + configurable: true + }); -/** - * Deserialize a map object included in a serialization - * @param {Deserializer} deserializer The Serializer building out the serialization - * @function external:Map.deserializeSelf -*/ -Object.defineProperty(Map.prototype, "serializeSelf", { - value: function (serializer) { - - }, - writable: true, - configurable: true -}); \ No newline at end of file + /** + * Sserialize a Map object + * @param {Deserializer} serializer The Serializer building out the serialization + * @function external:Map.serializeSelf + */ + Object.defineProperty(Map.prototype, "serializeSelf", { + value: function (serializer) { + var entries = this.entries(), + serializedKeys = [], + serializedValues = [], + entry; + + while ((entry = entries.next().value)) { + serializedKeys.push(entry[0]); + serializedValues.push(entry[1]); + } + + serializer.setProperty("keys", serializedKeys); + serializer.setProperty("values", serializedValues); + + }, + writable: true, + configurable: true + }); \ No newline at end of file diff --git a/core/extras/set.js b/core/extras/set.js new file mode 100644 index 0000000000..e64023e86c --- /dev/null +++ b/core/extras/set.js @@ -0,0 +1,48 @@ +/** + Defines extensions to intrinsic `Set`. + @see {external:Set} + @module montage/core/extras/set +*/ + +/** + * Deserialize a set object included in a serialization + * @param {Deserializer} deserializer The Deserializer containing the serialization information + * @function external:Set.deserializeSelf +*/ +Object.defineProperty(Set.prototype, "deserializeSelf", { + value: function (deserializer) { + var values, + i, n; + + values = deserializer.getProperty("values"); + if (values) { + for (i = 0, n = values.length; i < n; i++) { + this.add(values[i]); + } + } + }, + writable: true, + configurable: true +}); + + +/** + * Serialize a Set object + * @param {Deserializer} serializer The Serializer building out the serialization + * @function external:Set.serializeSelf +*/ +Object.defineProperty(Set.prototype, "serializeSelf", { + value: function (serializer) { + var serializedValues = [], + items = this.keys(), + item; + + while ((item = items.next().value)) { + serializedValues.push(item); + } + + serializer.setProperty("values", serializedValues); + }, + writable: true, + configurable: true +}); \ No newline at end of file diff --git a/core/extras/weak-map.js b/core/extras/weak-map.js new file mode 100644 index 0000000000..6e5eb2fd1f --- /dev/null +++ b/core/extras/weak-map.js @@ -0,0 +1,59 @@ +/** + Defines extensions to intrinsic `WeakMap`. + @see {external:WeakMap} + @module montage/core/extras/weak-map +*/ + +/** + * Deserialize a weak-map object included in a serialization + * @param {Deserializer} deserializer The Deserializer containing the serialization information + * @function external:WeakMap.deserializeSelf +*/ +Object.defineProperty(WeakMap.prototype, "deserializeSelf", { + value: function (deserializer) { + var entries, keys, values, + i, n; + + entries = deserializer.getProperty("entries"); + if (entries) { + for (i = 0, n = entries.length; i < n; i++) { + this.set(entries[i].key, entries[i].value); + } + } + if (!entries) { + keys = deserializer.getProperty("keys"); + values = deserializer.getProperty("values"); + if (keys && values) { + for (i = 0, n = keys.length; i < n; i++) { + this.set(keys[i], values[i]); + } + } + } + }, + writable: true, + configurable: true +}); + + +/** + * Serialize a WeakMap object + * @param {Deserializer} serializer The Serializer building out the serialization + * @function external:WeakMap.serializeSelf +*/ +Object.defineProperty(WeakMap.prototype, "serializeSelf", { + value: function (serializer) { + var entries = this.entries(), + serializedKeys = [], + serializedValues = [], + entry; + + while ((entry = entries.next().value)) { + serializedKeys.push(entry[0]); + serializedValues.push(entry[1]); + } + serializer.setProperty("keys", serializedKeys); + serializer.setProperty("values", serializedValues); + }, + writable: true, + configurable: true +}); \ No newline at end of file diff --git a/core/serialization/deserializer/montage-reviver.js b/core/serialization/deserializer/montage-reviver.js index 1753ed9ae7..738d8dd2a5 100644 --- a/core/serialization/deserializer/montage-reviver.js +++ b/core/serialization/deserializer/montage-reviver.js @@ -446,6 +446,10 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont } }, + _nativePrototypes: { + value: new Set(["Map", "Set", "WeakMap"]) + }, + reviveMontageObject: { value: function (value, context, label) { var self = this, @@ -454,7 +458,10 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont (locationId.endsWith(".mjson") || locationId.endsWith(".meta"))), module, locationDesc, location, objectName; - if (locationId) { + if (this._nativePrototypes.has(locationId)) { + module = global; + objectName = locationId; + } else if (locationId) { locationDesc = MontageReviver.parseObjectLocationId(locationId); module = this.moduleLoader.getModule(locationDesc.moduleId, label); objectName = locationDesc.objectName; diff --git a/core/serialization/serializer/montage-visitor.js b/core/serialization/serializer/montage-visitor.js index 293eaef142..ef161af466 100644 --- a/core/serialization/serializer/montage-visitor.js +++ b/core/serialization/serializer/montage-visitor.js @@ -29,6 +29,10 @@ var MontageVisitor = Montage.specialize({ } }, + _nativePrototypes: { + value: new Set(["Map", "Set", "WeakMap"]) + }, + getTypeOf: { value: function (object) { // Module and Alias are MontageObject's too so they need to be @@ -37,6 +41,8 @@ var MontageVisitor = Montage.specialize({ return "Module"; } else if (object instanceof Alias) { return "Alias"; + } else if (this._nativePrototypes.has(object.constructor.name)) { + return "NativeObject"; } else if ("getInfoForObject" in object || "getInfoForObject" in object.constructor) { return "MontageObject"; } else if (object.thisIsAReferenceCreatedByMontageSerializer) { @@ -128,6 +134,34 @@ var MontageVisitor = Montage.specialize({ } }, + visitNativeObject: { + value: function (malker, object, name) { + if (this.isObjectSerialized(object)) { + this.serializeReferenceToMontageObject(malker, object, name); + } else { + this.handleNativeObject(malker, object, name); + } + } + }, + + handleNativeObject: { + value: function (malker, object, name) { + var builderObject = this.builder.createCustomObject(), + substituteObject; + + this.setObjectSerialization(object, builderObject); + + substituteObject = this.serializeNativeObject(malker, object, builderObject); + + if (substituteObject) { + this.serializeSubstituteObject(malker, object, name, builderObject, substituteObject); + } else { + builderObject.setLabel(this.labeler.getObjectLabel(object)); + this.builder.top.setProperty(name, builderObject); + } + } + }, + serializeReferenceToMontageObject: { value: function (malker, object, name) { var label = this.labeler.getObjectLabel(object), @@ -234,6 +268,43 @@ var MontageVisitor = Montage.specialize({ } }, + serializeNativeObject: { + value: function (malker, object, builderObject) { + var selfSerializer, + substituteObject, + valuesBuilderObject = this.builder.createObjectLiteral(); + + // this.setObjectType(object, builderObject); + builderObject.setProperty("prototype", object.constructor.name); + builderObject.setProperty("values", valuesBuilderObject); + + this.builder.push(builderObject); + + if (typeof object.serializeSelf === "function") { + selfSerializer = new SelfSerializer(). + initWithMalkerAndVisitorAndObject( + malker, this, object, builderObject); + substituteObject = object.serializeSelf(selfSerializer); + } else { + this.setObjectValues(malker, object); + this.setObjectBindings(malker, object); + this.setObjectCustomUnits(malker, object); + } + + this.builder.pop(); + + // Remove the values unit in case none was serialized, + // we need to add it before any other units to make sure that + // it's the first unit to show up in the serialization, since we + // don't have a way to order the property names in a serialization. + if (valuesBuilderObject.getPropertyNames().length === 0) { + builderObject.clearProperty("values"); + } + + return substituteObject; + } + }, + setObjectType: { value: function (object, builderObject) { var isInstance = Montage.getInfoForObject(object).isInstance, diff --git a/test/sentinel.js b/test/sentinel.js index 0d45db990a..78c3d1f015 100644 --- a/test/sentinel.js +++ b/test/sentinel.js @@ -3,6 +3,8 @@ console.log('montage-testing', 'Start'); module.exports = require("montage-testing").run(require, [ {name: "spec/core/extras/map"}, + {name: "spec/core/extras/weak-map"}, + {name: "spec/core/extras/set"}, {name: "spec/data/raw-data-worker"}, {name: "spec/data/data-service-mapping"}, {name: "spec/data/raw-data-service"}, diff --git a/test/spec/core/extras/map.js b/test/spec/core/extras/map.js index c53cee0843..d2be0c4046 100644 --- a/test/spec/core/extras/map.js +++ b/test/spec/core/extras/map.js @@ -1,5 +1,5 @@ var Deserializer = require("montage/core/serialization/deserializer/montage-deserializer").MontageDeserializer, - deserialize = require("montage/core/serialization/deserializer/montage-deserializer").deserialize; + Serializer = require("montage/core/serialization/serializer/montage-serializer").MontageSerializer; require("montage"); @@ -13,7 +13,7 @@ describe("core/extras/map", function () { entries = [], serialization = { "root": { - "prototype": "collections/map[Map]", + "prototype": "Map", "values": { "entries": entries } @@ -27,10 +27,7 @@ describe("core/extras/map", function () { string = JSON.stringify(serialization); deserializer.init(string, require); - console.time("entries"); return deserializer.deserializeObject().then(function (root) { - console.timeEnd("entries"); - console.log("Map1", root); expect(root instanceof Map).toBeTruthy(); done(); }).catch(function(reason) { @@ -46,7 +43,7 @@ describe("core/extras/map", function () { values = [], serialization = { "root": { - "prototype": "collections/map[Map]", + "prototype": "Map", "values": { "keys": keys, "values": values @@ -61,10 +58,7 @@ describe("core/extras/map", function () { } string = JSON.stringify(serialization); deserializer.init(string, require); - console.time("keyValues"); return deserializer.deserializeObject().then(function (root) { - console.timeEnd("keyValues"); - console.log("Map2", root); expect(root instanceof Map).toBeTruthy(); done(); }).catch(function(reason) { @@ -78,9 +72,32 @@ describe("core/extras/map", function () { }); describe("Map#serializeSelf", function () { + var serializer; - xit("can serialize", function () { - expect("abc".contains("bc")).toBe(true); + beforeEach(function () { + originalUnits = Serializer._units; + Serializer._units = {}; + serializer = new Serializer().initWithRequire(require); + serializer.setSerializationIndentation(4); + }); + + it("can serialize", function () { + var map = new Map(), + serialization; + map.set("A", {name: "A"}); + map.set("B", {name: "B"}); + map.set("C", {name: "C"}); + + + serialization = serializer.serializeObject(map); + serialization = JSON.parse(serialization); + expect(serialization.root.prototype).toBe("Map"); + expect(serialization.root.values.keys[0]).toBe("A"); + expect(serialization.root.values.keys[1]).toBe("B"); + expect(serialization.root.values.keys[2]).toBe("C"); + expect(serialization.root.values.values[0].name).toBe("A"); + expect(serialization.root.values.values[1].name).toBe("B"); + expect(serialization.root.values.values[2].name).toBe("C"); }); diff --git a/test/spec/core/extras/set.js b/test/spec/core/extras/set.js new file mode 100644 index 0000000000..f27494b0c1 --- /dev/null +++ b/test/spec/core/extras/set.js @@ -0,0 +1,72 @@ +var Deserializer = require("montage/core/serialization/deserializer/montage-deserializer").MontageDeserializer, + Serializer = require("montage/core/serialization/serializer/montage-serializer").MontageSerializer; + +require("montage"); + +describe("core/extras/set", function () { + + describe("Set#deserializeSelf", function () { + + it("can deserialize with entries", function (done) { + + var deserializer = new Deserializer(), + values = [], + serialization = { + "root": { + "prototype": "Set", + "values": { + "values": values + } + } + }, + string, i; + + for (i = 0; i < 5000; ++i) { + values.push({key: i, value:{name: i}}); + } + + string = JSON.stringify(serialization); + deserializer.init(string, require); + return deserializer.deserializeObject().then(function (root) { + expect(root instanceof Set).toBeTruthy(); + done(); + }).catch(function(reason) { + console.warn(reason); + fail(reason); + }); + + }); + + }); + + describe("Set#serializeSelf", function () { + var serializer; + + beforeEach(function () { + originalUnits = Serializer._units; + Serializer._units = {}; + serializer = new Serializer().initWithRequire(require); + serializer.setSerializationIndentation(4); + }); + + it("can serialize", function () { + var set = new Set(), + serialization; + + set.add({name: "A"}); + set.add({name: "B"}); + set.add({name: "C"}); + + + serialization = serializer.serializeObject(set); + serialization = JSON.parse(serialization); + expect(serialization.root.prototype).toBe("Set"); + expect(serialization.root.values.values[0].name).toBe("A"); + expect(serialization.root.values.values[1].name).toBe("B"); + expect(serialization.root.values.values[2].name).toBe("C"); + }); + + }); + +}); + diff --git a/test/spec/core/extras/weak-map.js b/test/spec/core/extras/weak-map.js new file mode 100644 index 0000000000..c2c4a2ad6d --- /dev/null +++ b/test/spec/core/extras/weak-map.js @@ -0,0 +1,108 @@ +var Deserializer = require("montage/core/serialization/deserializer/montage-deserializer").MontageDeserializer, + Serializer = require("montage/core/serialization/serializer/montage-serializer").MontageSerializer; + +require("montage"); + +describe("core/extras/weak-map", function () { + + describe("WeakMap#deserializeSelf", function () { + + it("can deserialize with entries", function (done) { + + var deserializer = new Deserializer(), + entries = [], + serialization = { + "root": { + "prototype": "WeakMap", + "values": { + "entries": entries + } + } + }, + string, i; + + for (i = 0; i < 5000; ++i) { + entries.push({key: {id: i}, value:{name: i}}); + } + + string = JSON.stringify(serialization); + deserializer.init(string, require); + return deserializer.deserializeObject().then(function (root) { + expect(root instanceof WeakMap).toBeTruthy(); + done(); + }).catch(function(reason) { + console.warn(reason); + fail(reason); + }); + + }); + + it("can deserialize with keys and values", function (done) { + var deserializer = new Deserializer(), + keys = [], + values = [], + serialization = { + "root": { + "prototype": "WeakMap", + "values": { + "keys": keys, + "values": values + } + } + }, + string, i; + + for (i = 0; i < 5000; ++i) { + keys.push({id: i}); + values.push({name: i}); + } + string = JSON.stringify(serialization); + deserializer.init(string, require); + return deserializer.deserializeObject().then(function (root) { + expect(root instanceof WeakMap).toBeTruthy(); + done(); + }).catch(function(reason) { + console.warn(reason); + fail(reason); + }); + + + }); + + }); + + describe("WeakMap#serializeSelf", function () { + + var serializer; + + beforeEach(function () { + originalUnits = Serializer._units; + Serializer._units = {}; + serializer = new Serializer().initWithRequire(require); + serializer.setSerializationIndentation(4); + }); + + it("can serialize", function () { + var map = new Map(), + serialization; + map.set("A", {name: "A"}); + map.set("B", {name: "B"}); + map.set("C", {name: "C"}); + + + serialization = serializer.serializeObject(map); + serialization = JSON.parse(serialization); + expect(serialization.root.prototype).toBe("Map"); + expect(serialization.root.values.keys[0]).toBe("A"); + expect(serialization.root.values.keys[1]).toBe("B"); + expect(serialization.root.values.keys[2]).toBe("C"); + expect(serialization.root.values.values[0].name).toBe("A"); + expect(serialization.root.values.values[1].name).toBe("B"); + expect(serialization.root.values.values[2].name).toBe("C"); + }); + + + }); + +}); + From 4bc812d658cb2b657a4ddcc082717477714cdf57 Mon Sep 17 00:00:00 2001 From: Thomas Jaede Date: Thu, 17 May 2018 12:09:52 -0700 Subject: [PATCH 04/65] Remove _nativePrototypes Set in favor of global["Map"] check --- .../deserializer/montage-reviver.js | 6 +--- .../serializer/montage-visitor.js | 33 +++++++++---------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/core/serialization/deserializer/montage-reviver.js b/core/serialization/deserializer/montage-reviver.js index 738d8dd2a5..d7224c8451 100644 --- a/core/serialization/deserializer/montage-reviver.js +++ b/core/serialization/deserializer/montage-reviver.js @@ -446,10 +446,6 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont } }, - _nativePrototypes: { - value: new Set(["Map", "Set", "WeakMap"]) - }, - reviveMontageObject: { value: function (value, context, label) { var self = this, @@ -458,7 +454,7 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont (locationId.endsWith(".mjson") || locationId.endsWith(".meta"))), module, locationDesc, location, objectName; - if (this._nativePrototypes.has(locationId)) { + if (global[locationId] && typeof global[locationId] === "function") { module = global; objectName = locationId; } else if (locationId) { diff --git a/core/serialization/serializer/montage-visitor.js b/core/serialization/serializer/montage-visitor.js index ef161af466..ef272905f8 100644 --- a/core/serialization/serializer/montage-visitor.js +++ b/core/serialization/serializer/montage-visitor.js @@ -29,10 +29,6 @@ var MontageVisitor = Montage.specialize({ } }, - _nativePrototypes: { - value: new Set(["Map", "Set", "WeakMap"]) - }, - getTypeOf: { value: function (object) { // Module and Alias are MontageObject's too so they need to be @@ -41,7 +37,7 @@ var MontageVisitor = Montage.specialize({ return "Module"; } else if (object instanceof Alias) { return "Alias"; - } else if (this._nativePrototypes.has(object.constructor.name)) { + } else if (this._isSerializableNativeObject(object)) { return "NativeObject"; } else if ("getInfoForObject" in object || "getInfoForObject" in object.constructor) { return "MontageObject"; @@ -53,6 +49,17 @@ var MontageVisitor = Montage.specialize({ } }, + _isSerializableNativeObject: { + value: function (object) { + var typeName = object.constructor.name, + nativeType = global[typeName], + isNative = typeof nativeType === "function", + isSerializeable = isNative && typeof object.serializeSelf === "function"; + + return isNative && isSerializeable; + } + }, + visitMontageReference: { value: function (malker, object, name) { this.builder.top.setProperty(name, object.reference); @@ -274,22 +281,14 @@ var MontageVisitor = Montage.specialize({ substituteObject, valuesBuilderObject = this.builder.createObjectLiteral(); - // this.setObjectType(object, builderObject); builderObject.setProperty("prototype", object.constructor.name); builderObject.setProperty("values", valuesBuilderObject); this.builder.push(builderObject); - - if (typeof object.serializeSelf === "function") { - selfSerializer = new SelfSerializer(). - initWithMalkerAndVisitorAndObject( - malker, this, object, builderObject); - substituteObject = object.serializeSelf(selfSerializer); - } else { - this.setObjectValues(malker, object); - this.setObjectBindings(malker, object); - this.setObjectCustomUnits(malker, object); - } + selfSerializer = new SelfSerializer(). + initWithMalkerAndVisitorAndObject( + malker, this, object, builderObject); + substituteObject = object.serializeSelf(selfSerializer); this.builder.pop(); From f751006bdd36ffa96fff97152416c8e3663c8a43 Mon Sep 17 00:00:00 2001 From: Thomas Jaede Date: Thu, 17 May 2018 12:22:20 -0700 Subject: [PATCH 05/65] REmove files included with cherry-pick --- data/service/raw-data-worker.js | 364 ------------------------------ test/sentinel.js | 18 -- test/spec/data/raw-data-worker.js | 280 ----------------------- 3 files changed, 662 deletions(-) delete mode 100644 data/service/raw-data-worker.js delete mode 100644 test/sentinel.js delete mode 100644 test/spec/data/raw-data-worker.js diff --git a/data/service/raw-data-worker.js b/data/service/raw-data-worker.js deleted file mode 100644 index eea656491a..0000000000 --- a/data/service/raw-data-worker.js +++ /dev/null @@ -1,364 +0,0 @@ -var Montage = require("montage").Montage, - Criteria = require("core/criteria").Criteria, - DataQuery = require("data/model/data-query").DataQuery, - Map = require("collections/map"), - ModuleReference = require("core/module-reference").ModuleReference, - ObjectDescriptor = require("core/meta/object-descriptor").ObjectDescriptor, - OperationType = require("data/service/data-operation").DataOperation.Type, - Promise = require("core/promise").Promise; - - -exports.RawDataWorker = Montage.specialize({ - - - - /*************************************************************************** - * Serialization - */ - - // serializeSelf: { - // value: function (serializer) { - // } - // }, - - deserializeSelf: { - value: function (deserializer) { - var references = deserializer.getProperty("childServices") || []; - - // this.registerServiceReferences(references); - - var value = deserializer.getProperty("childServicesMap") || []; - this.registerServiceReferencesMap(value); - - value = deserializer.getProperty("childServicesArrays") || []; - this.registerServiceReferencesArray(value); - } - }, - - registerServiceReferencesArray: { - value: function (references) { - var map = new Map(), - keys = references.keys, - values = references.values, - i, n; - - for (i = 0, n = keys.length; i < n; i++) { - map.set(keys[i], values[i]); - } - - this._childServicesArrays = map; - } - }, - - - registerServiceReferencesMap: { - value: function (references) { - var map = new Map(), - i, n; - - for (i = 0, n = references.length; i < n; i++) { - map.set(references[i].key, references[i].value); - } - - this._childServicesMap = map; - } - }, - - - /*************************************************************************** - * Service Tree - */ - - - _serviceReferenceRegistrationPromise: { - get: function () { - if (!this.__serviceReferenceRegistrationPromise) { - this.__serviceReferenceRegistrationPromise = Promise.resolve(null); - } - return this.__serviceReferenceRegistrationPromise; - } - }, - - serviceReferences: { - get: function() { - if (!this._serviceReferences) { - this._serviceReferences = new Set(); - } - return this._serviceReferences; - } - }, - - serviceReferenceByObjectDescriptor: { - get: function () { - if (!this._serviceReferenceByObjectDescriptor) { - this._serviceReferenceByObjectDescriptor = new Map(); - } - return this._serviceReferenceByObjectDescriptor; - } - }, - - serviceReferenceForObjectDescriptor: { - value: function (type) { - var services; - type = type instanceof ObjectDescriptor ? type : this._objectDescriptorForType(type); - services = this._serviceReferenceByObjectDescriptor.get(type) || this._serviceReferenceByObjectDescriptor.get(null); - return services && services[0] || null; - } - }, - - registerServiceReferences: { - value: function (serviceReferences) { - var self; - if (!this.__serviceReferenceRegistrationPromise) { - self = this; - this.__serviceReferenceRegistrationPromise = Promise.all(serviceReferences.map(function (service) { - return self.registerServiceReference(service); - })); - } - } - }, - - registerServiceReference: { - value: function (service, types) { - var self = this; - // possible types - // -- types is passed in as an array or a single type. - // -- a model is set on the service. - // -- types is set on the service. - // any type can be asychronous or synchronous. - types = types && Array.isArray(types) && types || - types && [types] || - service.model && service.model.objectDescriptors || - service.types && Array.isArray(service.types) && service.types || - service.types && [service.types] || - []; - - return this._registerServiceReferenceObjectDescriptors(service, types); - } - }, - - _registerServiceReferenceObjectDescriptors: { - value: function (service, types) { - this._addServiceReference(service, types); - this._registerObjectDescriptorsByModuleId(types); - return this.nullPromise; - } - }, - - _addServiceReference: { - value: function (service, types) { - var serviceReference, type, i, n, nIfEmpty = 1; - types = types || service.model && service.model.objectDescriptors || service.types; - - // Add the new service to this service's serviceren set. - this.serviceReferences.add(service); - - // Add the new service service to the services array of each of its - // types or to the "all types" service array identified by the - // `null` type, and add each of the new service's types to the array - // of service types if they're not already there. - for (i = 0, n = types && types.length || nIfEmpty; i < n; i += 1) { - type = types && types.length && types[i] || null; - serviceReference = this.serviceReferenceByObjectDescriptor.get(type) || []; - serviceReference.push(service); - if (serviceReference.length === 1) { - this.serviceReferenceByObjectDescriptor.set(type, serviceReference); - } - } - } - }, - - _registerObjectDescriptorsByModuleId: { - value: function (types) { - var self = this; - types.forEach(function (objectDescriptor) { - var module = objectDescriptor.module, - moduleId = [module.id, objectDescriptor.exportName].join("/"); - self.objectDescriptorsByModuleID.set(moduleId, objectDescriptor); - }); - } - }, - - nullPromise: { - get: function () { - if (!exports.RawDataWorker._nullPromise) { - exports.RawDataWorker._nullPromise = Promise.resolve(null); - } - return exports.RawDataWorker._nullPromise; - } - }, - - /*************************************************************************** - * Operation Handlers - */ - - handleOperation: { - value: function (operation) { - var self = this, - objectDescriptor, service; - - return this._serviceReferenceRegistrationPromise.then(function () { - return self._objectDescriptorForOperation(operation); - }).then(function (descriptor) { - objectDescriptor = descriptor; - return self._serviceForObjectDescriptor(descriptor); - }).then(function (service) { - var handlerName = self._handlerNameForOperationType(operation.type); - if (!service) { - // console.log(operation, self, objectDescriptor); - throw new Error("No service available to handle operation with type (" + (objectDescriptor && objectDescriptor.name) + ")"); - } - return self[handlerName](operation, service, objectDescriptor); - }); - } - }, - - _handlerNameForOperationType: { - value: function (operationType) { - var name = "_perform"; - name += this._operationTypeNameByOperationType(operationType); - return name + "Operation"; - } - }, - - _operationTypeNameByOperationType: { - value: function (operationType) { - return operationType.isCreate ? "Create" : - operationType.isRead ? "Read" : - operationType.isUpdate ? "Update" : - operationType.isDelete ? "Delete" : - null; - } - }, - - _performCreateOperation: { - value: function (operation, service, objectDescriptor) { - return service.saveRawData(operation.data); - } - }, - - _performDeleteOperation: { - value: function (operation, service, objectDescriptor) { - return service.deleteRawData(operation.data); - } - }, - - _performReadOperation: { - value: function (operation, service, objectDescriptor) { - var criteria = operation.criteria || operation.data, - query, parameters, expression; - - if (!(criteria instanceof Criteria)) { - parameters = criteria ? criteria.parameters : {}; - expression = criteria ? criteria.expression : ""; - criteria = new Criteria().initWithExpression(expression, parameters); - } - query = DataQuery.withTypeAndCriteria(objectDescriptor, criteria); - - return service.fetchData(query); - } - }, - - _performUpdateOperation: { - value: function (operation, service, objectDescriptor) { - return service.saveRawData(operation.data); - } - }, - - /*************************************************************************** - * Service & ObjectDescriptor Creation - */ - - objectDescriptorForType: { - value: function () { - - } - }, - - _serviceReferenceForObjectDescriptor: { - value: function (objectDescriptor) { - var services = this.serviceReferenceByObjectDescriptor.get(objectDescriptor); - services = services || this.serviceReferenceByObjectDescriptor.get(null); - return services && services[0] || null; - } - }, - - _serviceForObjectDescriptor: { - value: function (objectDescriptor) { - var self = this, - serviceReference = this._serviceReferenceForObjectDescriptor(objectDescriptor), - service = serviceReference && this.servicesByModuleID.get(serviceReference.moduleId); - - - - return !serviceReference ? Promise.resolve(null) : - service ? Promise.resolve(service) : - serviceReference.promise.then(function (service) { - self._servicesByModuleID.set(serviceReference.moduleId, service); - return service; - }); - } - }, - - _objectDescriptorForOperation: { - value: function (operation) { - var self = this, - descriptorOrModule = operation.dataType, - module, descriptor, result, moduleId; - - if (descriptorOrModule instanceof ModuleReference) { - module = descriptorOrModule; - descriptor = this.objectDescriptorsByModuleID.get(module.id); - if (descriptor) { - result = Promise.resolve(descriptor); - } else { - result = module.exports.then(function (exports) { - var instance = exports.montageObject, - moduleId = [module.id, instance.exportName].join("/"); - self.objectDescriptorsByModuleID.set(module.id, instance); - self.objectDescriptorsByModuleID.set(moduleId, instance); - return instance; - }); - } - } else if (descriptorOrModule instanceof ObjectDescriptor){ - descriptor = descriptorOrModule; - module = descriptor.module; - moduleId = [module.id, descriptor.exportName].join("/"); - if (!this.objectDescriptorsByModuleID.has(moduleId)) { - this.objectDescriptorsByModuleID.set(moduleId, descriptor); - } else { - descriptor = this.objectDescriptorsByModuleID.get(moduleId); - } - result = Promise.resolve(descriptor); - } - - - - - return result; - } - }, - - /*************************************************************************** - * Service/Type Caching - */ - - servicesByModuleID: { - get: function () { - if (!this._servicesByModuleID) { - this._servicesByModuleID = new Map(); - } - return this._servicesByModuleID; - } - }, - - objectDescriptorsByModuleID: { - get: function () { - if (!this._objectDescriptorsByModuleID) { - this._objectDescriptorsByModuleID = new Map(); - } - return this._objectDescriptorsByModuleID; - } - } - -}); \ No newline at end of file diff --git a/test/sentinel.js b/test/sentinel.js deleted file mode 100644 index 78c3d1f015..0000000000 --- a/test/sentinel.js +++ /dev/null @@ -1,18 +0,0 @@ -console.log('montage-testing', 'Start'); - -module.exports = require("montage-testing").run(require, [ - - {name: "spec/core/extras/map"}, - {name: "spec/core/extras/weak-map"}, - {name: "spec/core/extras/set"}, - {name: "spec/data/raw-data-worker"}, - {name: "spec/data/data-service-mapping"}, - {name: "spec/data/raw-data-service"}, - {name: "spec/data/data-service"} - -]).then(function () { - console.log('montage-testing', 'End'); -}, function (err) { - console.log('montage-testing', 'Fail', err, err.stack); - throw err; -}); diff --git a/test/spec/data/raw-data-worker.js b/test/spec/data/raw-data-worker.js deleted file mode 100644 index 607d4debc0..0000000000 --- a/test/spec/data/raw-data-worker.js +++ /dev/null @@ -1,280 +0,0 @@ -var RawDataWorker = require("montage/data/service/raw-data-worker").RawDataWorker, - DataOperation = require("montage/data/service/data-operation").DataOperation, - OperationType = require("montage/data/service/data-operation").DataOperation.Type, - Category = require("spec/data/logic/model/category").Category, - CategoryDescriptor = require("spec/data/logic/model/category.mjson").montageObject, - Criteria = require("montage/core/criteria").Criteria, - DataMapping = require("montage/data/service/data-mapping").DataMapping, - DataService = require("montage/data/service/data-service").DataService, - DataServiceReference = require("montage/data/service/data-service-reference").DataServiceReference, - DataStream = require("montage/data/service/data-stream").DataStream, - DataObjectDescriptor = require("montage/data/model/data-object-descriptor").DataObjectDescriptor, - ObjectDescriptor = require("montage/core/meta/object-descriptor").ObjectDescriptor, - ModuleReference = require("montage/core/module-reference").ModuleReference, - MovieDescriptor = require("spec/data/logic/model/movie.mjson").montageObject, - RawDataTypeMapping = require("montage/data/service/raw-data-type-mapping").RawDataTypeMapping; - - - -var Deserializer = require("montage/core/serialization/deserializer/montage-deserializer").MontageDeserializer, - deserialize = require("montage/core/serialization/deserializer/montage-deserializer").deserialize; - -describe("A RawDataWorker", function() { - var worker, - typeReference, - operation; - - function makeOperation(operationType, dataType, data, criteria) { - var newOperation = new DataOperation(); - newOperation.type = operationType; - newOperation.dataType = dataType; - newOperation.data = data; - newOperation.criteria = criteria; - return newOperation; - } - - it("can be created", function () { - expect(new RawDataWorker()).toBeDefined(); - }); - - it("can register service references", function (done) { - var serviceID = "spec/data/logic/service/category-service.mjson", - types = [CategoryDescriptor], - serviceReference = new DataServiceReference().initWithIdTypesAndRequire(serviceID, types, require); - worker = new RawDataWorker(); - - worker.registerServiceReference(serviceReference).then(function () { - expect(worker.serviceReferences.size).toBe(1); - done(); - }); - }); - - - describe("can lazily", function () { - - it("register type for DataOperation with descriptor", function (done) { - var movieDescriptor, operation2; - - operation = makeOperation(null, CategoryDescriptor); - operation2 = makeOperation(null, CategoryDescriptor); - worker._objectDescriptorForOperation(operation).then(function (descriptor) { - expect(descriptor).toBeDefined(); - movieDescriptor = descriptor; - return worker._objectDescriptorForOperation(operation2); - }).then(function (descriptor) { - expect(descriptor).toBeDefined(); - expect(descriptor).toBe(movieDescriptor); - done(); - }); - }); - - it("register type for DataOperation with reference", function (done) { - var movieDescriptor, operation2; - typeReference = new ModuleReference().initWithIdAndRequire("spec/data/logic/model/category.mjson", require); - operation = makeOperation(null, typeReference); - operation2 = makeOperation(null, typeReference); - worker._objectDescriptorForOperation(operation).then(function (descriptor) { - expect(descriptor).toBeDefined(); - movieDescriptor = descriptor; - return worker._objectDescriptorForOperation(operation2); - }).then(function (descriptor) { - expect(descriptor).toBeDefined(); - expect(descriptor).toBe(movieDescriptor); - done(); - }); - }); - - it("register type for DataOperation with descriptor & reference", function (done) { - var movieDescriptor, operation2; - typeReference = new ModuleReference().initWithIdAndRequire("spec/data/logic/model/category.mjson", require); - operation = makeOperation(null, CategoryDescriptor); - operation2 = makeOperation(null, typeReference); - worker._objectDescriptorForOperation(operation).then(function (descriptor) { - expect(descriptor).toBeDefined(); - movieDescriptor = descriptor; - return worker._objectDescriptorForOperation(operation2); - }).then(function (descriptor) { - expect(descriptor).toBeDefined(); - expect(descriptor).toBe(movieDescriptor); - done(); - }); - }); - - it("register type for DataOperation with reference & descriptor", function (done) { - var movieDescriptor, operation2; - typeReference = new ModuleReference().initWithIdAndRequire("spec/data/logic/model/category.mjson", require); - operation = makeOperation(null, typeReference); - operation2 = makeOperation(null, CategoryDescriptor); - worker._objectDescriptorForOperation(operation).then(function (descriptor) { - expect(descriptor).toBeDefined(); - movieDescriptor = descriptor; - return worker._objectDescriptorForOperation(operation2); - }).then(function (descriptor) { - expect(descriptor).toBeDefined(); - expect(descriptor).toBe(movieDescriptor); - done(); - }); - }); - - }); - - describe("can handle basic ", function () { - // worker = new RawDataWorker(); - - it("create operation", function (done) { - var rawData = { - name: "Comedy" - }; - operation = makeOperation(OperationType.Create, CategoryDescriptor, rawData); - - worker.handleOperation(operation).then(function (data) { - expect(Array.isArray(data)).toBe(true); - expect(data[1]).toBe(rawData.name); - done(); - }); - }); - - it("read operation", function (done) { - - operation = makeOperation(OperationType.Read, CategoryDescriptor); - - worker.handleOperation(operation).then(function (data) { - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(1); - done(); - }); - }); - - it("update operation", function (done) { - var rawData = { - name: "Science Fiction", - categoryID: 1 - }; - //Should use criteria to identify which object to update - operation = makeOperation(OperationType.Update, CategoryDescriptor, rawData); - - worker.handleOperation(operation).then(function (data) { - expect(Array.isArray(data)).toBe(true); - expect(data[1]).toBe(rawData.name); - done(); - }); - }); - - - it("delete operation", function (done) { - var rawData = { - name: "Science Fiction", - categoryID: 1 - }; - operation = makeOperation(OperationType.Delete, CategoryDescriptor, rawData); - - worker.handleOperation(operation).then(function (data) { - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(1); - done(); - }); - }); - }); - - describe("can handle read operation", function () { - worker = new RawDataWorker(); - - it("with criteria", function (done) { - criteria = new Criteria().initWithExpression("id == $.id", { - categoryID: 1 - }); - operation = makeOperation(OperationType.Read, CategoryDescriptor, null, criteria); - - worker.handleOperation(operation).then(function (data) { - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(1); - expect(data[0].name).toBe("Action"); - done(); - }); - - }); - - }); - - describe("can deserialize", function () { - it("without childServices", function (done) { - var deserializer = new Deserializer(); - serialization = { - "root": { - "prototype": "montage/data/service/raw-data-worker", - "values": { - "name": "RawDataWorker" - } - } - }, - serializationString = JSON.stringify(serialization); - - deserializer.init(serializationString, require); - deserializer.deserializeObject().then(function (root) { - expect(Object.getPrototypeOf(root)).toBe(RawDataWorker.prototype); - }).catch(function(reason) { - fail(reason); - }).finally(function () { - done(); - }); - }); - - it("with childServices", function (done) { - var deserializer = new Deserializer(); - serialization = { - "root": { - "prototype": "montage/data/service/raw-data-worker", - "values": { - "name": "RawDataWorker", - "childServices": {"@": "ChildServicesMap"} - } - }, - "ChildServicesMap": { - "prototype": "collections/map[Map]", - "values": { - "keys": [ - {"@": "Category"}, - {"@": "Movie"} - ], - "values": [ - {"%": "spec/data/logic/service/category-service.mjson"}, - {"%": "spec/data/logic/service/movie-service.mjson"} - ] - } - }, - - "Category": { - "object": "spec/data/logic/model/category.mjson" - }, - - "Movie": { - "object": "spec/data/logic/model/category.mjson" - }, - }, - serializationString = JSON.stringify(serialization), - operation = makeOperation(OperationType.Read, CategoryDescriptor); - operation2 = makeOperation(OperationType.Read, MovieDescriptor); - - deserializer.init(serializationString, require); - deserializer.deserializeObject().then(function (root) { - expect(Object.getPrototypeOf(root)).toBe(RawDataWorker.prototype); - expect(root.serviceReferences.size).toBe(2); - return root.handleOperation(operation).then(function (data) { - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(1); - expect(data[0] instanceof Category).toBe(true); - return root.handleOperation(operation2); - }).then(function (data) { - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(1); - return null; - }); - }).catch(function(reason) { - fail(reason); - }).finally(function () { - done(); - }); - - }); - }); -}) \ No newline at end of file From 0c1ada1b3b19d96cc4a676ff3b91d3c4fd0c229e Mon Sep 17 00:00:00 2001 From: Thomas Jaede Date: Thu, 17 May 2018 12:37:10 -0700 Subject: [PATCH 06/65] Reorder MontageVisitor getObjectType to deprioritize NativeObject --- core/serialization/serializer/montage-visitor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/serialization/serializer/montage-visitor.js b/core/serialization/serializer/montage-visitor.js index ef272905f8..0bafee6774 100644 --- a/core/serialization/serializer/montage-visitor.js +++ b/core/serialization/serializer/montage-visitor.js @@ -37,14 +37,14 @@ var MontageVisitor = Montage.specialize({ return "Module"; } else if (object instanceof Alias) { return "Alias"; - } else if (this._isSerializableNativeObject(object)) { - return "NativeObject"; } else if ("getInfoForObject" in object || "getInfoForObject" in object.constructor) { return "MontageObject"; } else if (object.thisIsAReferenceCreatedByMontageSerializer) { return "MontageReference"; } else if (typeof Element !== "undefined" && Element.isElement(object)) { return "Element"; + } else if (this._isSerializableNativeObject(object)) { + return "NativeObject"; } } }, From 71ee50941e16a090af795ad2168edc6493dedfb9 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Tue, 29 May 2018 23:27:02 +0200 Subject: [PATCH 07/65] Initial commit for the drag & drop Manager --- core/drag/drag-manager.js | 625 ++++++++++++++++++ core/drag/drag.info/sample/index.html | 20 + core/drag/drag.info/sample/package.json | 11 + .../drag.info/sample/ui/drop.reel/drop.css | 27 + .../drag.info/sample/ui/drop.reel/drop.html | 39 ++ .../drag.info/sample/ui/drop.reel/drop.js | 64 ++ .../drag.info/sample/ui/main.reel/main.css | 70 ++ .../drag.info/sample/ui/main.reel/main.html | 95 +++ .../drag.info/sample/ui/main.reel/main.js | 15 + .../sample/ui/square.reel/square.css | 32 + .../sample/ui/square.reel/square.html | 28 + .../drag.info/sample/ui/square.reel/square.js | 55 ++ core/drag/dragging-operation-info.js | 60 ++ index.html | 3 + ui/component.js | 221 ++++++- 15 files changed, 1362 insertions(+), 3 deletions(-) create mode 100644 core/drag/drag-manager.js create mode 100644 core/drag/drag.info/sample/index.html create mode 100644 core/drag/drag.info/sample/package.json create mode 100644 core/drag/drag.info/sample/ui/drop.reel/drop.css create mode 100644 core/drag/drag.info/sample/ui/drop.reel/drop.html create mode 100644 core/drag/drag.info/sample/ui/drop.reel/drop.js create mode 100644 core/drag/drag.info/sample/ui/main.reel/main.css create mode 100644 core/drag/drag.info/sample/ui/main.reel/main.html create mode 100644 core/drag/drag.info/sample/ui/main.reel/main.js create mode 100644 core/drag/drag.info/sample/ui/square.reel/square.css create mode 100644 core/drag/drag.info/sample/ui/square.reel/square.html create mode 100644 core/drag/drag.info/sample/ui/square.reel/square.js create mode 100644 core/drag/dragging-operation-info.js diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js new file mode 100644 index 0000000000..030a6008d8 --- /dev/null +++ b/core/drag/drag-manager.js @@ -0,0 +1,625 @@ +var Montage = require("../core").Montage, + TranslateComposer = require("../../composer/translate-composer").TranslateComposer, + DraggingOperationInfo = require("./dragging-operation-info").DraggingOperationInfo; + +var DRAG_OPERATION = 0; +var DROP_OPERATION = 1; + +var DragManager = exports.DragManager = Montage.specialize({ + + __draggingSources: { + value: null + }, + + _draggingSources: { + get: function () { + return this.__draggingSources || (this.__draggingSources = []); + } + }, + + __droppingDestinations: { + value: null + }, + + _droppingDestinations: { + get: function () { + return this.__droppingDestinations || (this.__droppingDestinations = []); + } + }, + + __rootComponent: { + value: null + }, + + _rootComponent: { + set: function (component) { + if (this.__rootComponent !== component) { + if (this.__rootComponent) { + this.__rootComponent.removeComposer(this._translateComposer); + } + + if (component) { + component.addComposerForElement( + this._translateComposer, component.element + ); + } + + this.__rootComponent = component; + } + }, + get: function () { + return this.__rootComponent; + } + }, + + _TOUCH_POINTER: { + value: "touch", + writable: false + }, + + __translateComposer: { + value: null + }, + + _translateComposer: { + get: function () { + if (!this.__translateComposer) { + this.__translateComposer = new TranslateComposer(); + this.__translateComposer.hasMomentum = false; + this.__translateComposer.shouldCancelOnSroll = true; + this.__translateComposer.translateX = 0; + this.__translateComposer.translateY = 0; + this.__translateComposer.lazyLoad = false; + } + + return this.__translateComposer; + } + }, + + _draggingOperationInfo: { + value: null + }, + + _isDragging: { + value: false + }, + + _willTerminateDraggingOperation: { + value: false + }, + + _needsToWaitforGhostElementBoundaries: { + value: false + }, + + initWithComponent: { + value: function (component) { + this._rootComponent = component; + var element = this._rootComponent.element; + + if ("webkitTransform" in element.style) { + DragManager.cssTransform = "webkitTransform"; + } else if ("MozTransform" in element.style) { + DragManager.cssTransform = "MozTransform"; + } else if ("oTransform" in element.style) { + DragManager.cssTransform = "oTransform"; + } else { + DragManager.cssTransform = "transform"; + } + + if (window.PointerEvent) { + element.addEventListener("pointerdown", this, true); + + } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { + element.addEventListener("MSPointerDown", this, true); + + } else { + element.addEventListener("touchstart", this, true); + } + + this._translateComposer.addEventListener("translateStart", this); + + return this; + } + }, + + registerForDragSource: { + value: function (component) { + this._register(component, DRAG_OPERATION); + } + }, + + registerForDragDestination: { + value: function (component) { + this._register(component, DROP_OPERATION); + } + }, + + unregisterForDragSource: { + value: function (component) { + this._unregister(component, DRAG_OPERATION); + } + }, + + unregisterForDragDestination: { + value: function (component) { + this._unregister(component, DROP_OPERATION); + } + }, + + _register: { + value: function (component, operationType) { + if (component) { + var components = operationType === DRAG_OPERATION ? + this._draggingSources : this._droppingDestinations; + + if (components.indexOf(component) === -1) { + components.push(component); + } + } + } + }, + + _unregister: { + value: function (component, operationType) { + if (component) { + var components = operationType === DRAG_OPERATION ? + this._draggingSources : this._droppingDestinations, + index; + + if ((index = components.indexOf(component)) > -1) { + components.splice(index, 1); + } + } + } + }, + + _createDraggingOperationInfoWithSourceAndPosition: { + value: function (source, startPosition) { + var draggingOperationInfo = new DraggingOperationInfo(), + draggingImage = source.element.cloneNode(true); + + draggingImage.classList.add("montage-dragging-image"); + draggingImage.style.visibility = "hidden"; + draggingImage.style.position = "absolute"; + draggingImage.style.pointerEvents = "none"; + draggingImage.style.boxSizing = "border-box"; + draggingImage.style.zIndex = 999999; + + draggingOperationInfo.source = source; + draggingOperationInfo.draggingImage = draggingImage; + draggingOperationInfo.startPositionX = startPosition.pageX; + draggingOperationInfo.startPositionY = startPosition.pageY; + draggingOperationInfo.positionX = startPosition.pageX; + draggingOperationInfo.positionY = startPosition.pageY; + + return draggingOperationInfo; + } + }, + + _dispatchDraggingOperationStart: { + value: function (draggingOperationInfo) { + var component; + + for (var i = 0, length = this._droppingDestinations.length; i < length; i++) { + component = this._droppingDestinations[i]; + component._draggingStarted(draggingOperationInfo); + } + } + }, + + _dispatchDraggingOperationEnd: { + value: function (draggingOperationInfo) { + var component; + + for (var i = 0, length = this._droppingDestinations.length; i < length; i++) { + component = this._droppingDestinations[i]; + component._draggingEnded(draggingOperationInfo); + } + } + }, + + _notifyDroppingDestinationToPerformDropOperation: { + value: function (draggingOperationInfo) { + if (this._droppingDestination) { + this._droppingDestination._performDropOperation( + draggingOperationInfo + ); + } + } + }, + + _notifyDroppingDestinationToConcludeDropOperation: { + value: function (draggingOperationInfo) { + if (this._droppingDestination) { + this._droppingDestination._concludeDropOperation( + draggingOperationInfo + ); + } + } + }, + + _notifyDroppingDestinationDraggingImageHasEntered: { + value: function (draggingOperationInfo) { + if (this._droppingDestination) { + this._droppingDestination._draggingEntered( + draggingOperationInfo + ); + } + } + }, + + _notifyDroppingDestinationDraggingImageHasUpdated: { + value: function (draggingOperationInfo) { + if (this._droppingDestination) { + this._droppingDestination._draggingUpdated( + draggingOperationInfo + ); + } + } + }, + + _notifyDroppingDestinationDraggingImageHasExited: { + value: function (draggingOperationInfo) { + if (this._droppingDestination) { + this._droppingDestination._draggingExited( + draggingOperationInfo + ); + } + } + }, + + _findDraggingSourceAtPosition: { + value: function (positionX, positionY) { + return this._findRegisteredComponentAtPosistion( + positionX, + positionY, + DRAG_OPERATION + ); + } + }, + + _findDropDestinationAtPosition: { + value: function (positionX, positionY) { + var droppingDestination = this._findRegisteredComponentAtPosistion( + positionX, + positionY, + DROP_OPERATION + ); + + return droppingDestination && droppingDestination.acceptDragOperation ? + droppingDestination : null; + } + }, + + _findRegisteredComponentAtPosistion: { + value: function (positionX, positionY, operationType) { + var targetComponent = this._findComponentAtPosition(positionX, positionY), + registeredComponent; + + if (targetComponent) { + var registeredComponents = operationType === DRAG_OPERATION ? + this._draggingSources : this._droppingDestinations, + index; + + while (targetComponent) { + if ((index = registeredComponents.indexOf(targetComponent)) > -1) { + registeredComponent = registeredComponents[index]; + targetComponent = null; + } else { + targetComponent = targetComponent.parentComponent; + } + } + } + + return registeredComponent; + } + }, + + _findComponentAtPosition: { + value: function (positionX, positionY) { + var element = document.elementFromPoint(positionX, positionY), + component; + + if (element) { + while (element && !(component = element.component)) { + element = element.parentElement; + } + } + + return component; + } + }, + + _addTranslateListeners: { + value: function () { + this._translateComposer.addEventListener('translate', this); + this._translateComposer.addEventListener('translateEnd', this); + this._translateComposer.addEventListener('translateCancel', this); + } + }, + + _removeTranslateListeners: { + value: function () { + this._translateComposer.removeEventListener('translate', this); + this._translateComposer.removeEventListener('translateEnd', this); + this._translateComposer.removeEventListener('translateCancel', this); + } + }, + + _resetTranslateContext: { + value: function () { + this._removeTranslateListeners(); + this._isDragging = false; + this.__translateComposer.translateX = 0; + this.__translateComposer.translateY = 0; + this._draggingImageBoundingRect = null; + this._willTerminateDraggingOperation = false; + this._needsToWaitforGhostElementBoundaries = false; + } + }, + + capturePointerdown: { + value: function (event) { + if (event.pointerType === this._TOUCH_POINTER || + (window.MSPointerEvent && event.pointerType === window.MSPointerEvent.MSPOINTER_TYPE_TOUCH) + ) { + this.captureTouchstart(event); + } + } + }, + + captureTouchstart: { + value: function (event) { + var sourceComponent = this._findDraggingSourceAtPosition( + event.pageX, + event.pageY + ); + + if (sourceComponent) { + if (window.PointerEvent) { + this._rootComponent.element.addEventListener("pointermove", this, true); + } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { + this._rootComponent.element.addEventListener("MSPointerMove", this, true); + } else { + this._rootComponent.element.addEventListener("touchmove", this, true); + } + } + } + }, + + capturePointermove: { + value: function (event) { + this.captureTouchmove(event); + } + }, + + captureTouchmove: { + value: function (event) { + // Prevent Scroll on touch devices + event.preventDefault(); + + if (window.PointerEvent) { + this._rootComponent.element.removeEventListener("pointermove", this, true); + } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { + this._rootComponent.element.removeEventListener("MSPointerMove", this, true); + } else { + this._rootComponent.element.removeEventListener("touchmove", this, true); + } + } + }, + + handleTranslateStart: { + value: function (event) { + var startPosition = this._translateComposer.pointerStartEventPosition, + sourceComponent = this._findDraggingSourceAtPosition( + startPosition.pageX, + startPosition.pageY + ); + + if (sourceComponent) { + this._draggingOperationInfo = this._createDraggingOperationInfoWithSourceAndPosition( + sourceComponent, + startPosition + ); + + this._draggingOperationInfo.draggingOperationType = ( + sourceComponent.draggingOperationType || DragManager.DragOperationCopy + ); + + sourceComponent._beginDraggingOperation(this._draggingOperationInfo); + this._dispatchDraggingOperationStart(this._draggingOperationInfo); + this._isDragging = true; + this._rootComponent.needsDraw = true; + this._addTranslateListeners(); + } else { + this._translateComposer._cancel(); + } + } + }, + + handleTranslate: { + value: function (event) { + this._draggingOperationInfo.deltaX = event.translateX; + this._draggingOperationInfo.deltaY = event.translateY; + this._draggingOperationInfo.positionX = ( + this._draggingOperationInfo.startPositionX + event.translateX + ); + this._draggingOperationInfo.positionY = ( + this._draggingOperationInfo.startPositionY + event.translateY + ); + + var droppingDestination = this._findDropDestinationAtPosition( + this._draggingOperationInfo.positionX, + this._draggingOperationInfo.positionY + ); + + this._draggingOperationInfo.source._updateDraggingOperation( + this._draggingOperationInfo + ); + + if (droppingDestination !== this._droppingDestination) { + if (this._droppingDestination) { + this._notifyDroppingDestinationDraggingImageHasExited(); + } + + if (droppingDestination) { + this._notifyDroppingDestinationDraggingImageHasEntered(); + } + } else if (droppingDestination) { + this._notifyDroppingDestinationDraggingImageHasUpdated(); + } + + this._droppingDestination = droppingDestination; + + this._rootComponent.needsDraw = true; + } + }, + + handleTranslateEnd: { + value: function () { + this._willTerminateDraggingOperation = true; + this._rootComponent.needsDraw = true; + } + }, + + + handleTranslateCancel: { + value: function () { + this._droppingDestination = null; + this._willTerminateDraggingOperation = true; + this._rootComponent.needsDraw = true; + } + }, + + willDraw: { + value: function () { + if (this._isDragging && this._draggingOperationInfo && !this._draggingImageBoundingRect) { + this._draggingImageBoundingRect = this._draggingOperationInfo.source.element.getBoundingClientRect(); + } + } + }, + + draw: { + value: function () { + var draggingOperationInfo = this._draggingOperationInfo; + + if (this._isDragging && !this._willTerminateDraggingOperation) { + var draggingImage = draggingOperationInfo.draggingImage; + + if (!draggingImage.parentElement) { + draggingImage.style.top = this._draggingImageBoundingRect.top + "px"; + draggingImage.style.left = this._draggingImageBoundingRect.left + "px"; + draggingImage.style.width = this._draggingImageBoundingRect.width + "px"; + draggingImage.style.height = this._draggingImageBoundingRect.height + "px"; + document.body.appendChild(draggingImage); + + if (draggingOperationInfo.draggingOperationType === DragManager.DragOperationMove) { + this._oldSourceDisplayStyle = draggingOperationInfo.source.element.style.display; + draggingOperationInfo.source.element.style.display = 'none'; + + if (draggingOperationInfo.draggingSourcePlaceholderStrategy === DragManager.DraggingSourcePlaceholderStrategyVisible) { + this._placeholderElement = document.createElement('div'); + this._placeholderElement.style.width = this._draggingImageBoundingRect.width + "px"; + this._placeholderElement.style.height = this._draggingImageBoundingRect.height + "px"; + this._placeholderElement.style.boxSizing = "border-box"; + this._placeholderElement.classList.add('montage-placeholder'); + + draggingOperationInfo.source.element.parentNode.insertBefore( + this._placeholderElement, + draggingOperationInfo.source.element + ); + } + } + + this._needsToWaitforGhostElementBoundaries = true; + } + + if (!this._needsToWaitforGhostElementBoundaries) { + draggingImage.style.visibility = "visible"; + } else { + this._needsToWaitforGhostElementBoundaries = false; + } + + draggingImage.style[DragManager.cssTransform] = "translate3d(" + + this._draggingOperationInfo.deltaX + "px," + + this._draggingOperationInfo.deltaY + "px,0)"; + + } else if (this._willTerminateDraggingOperation) { + document.body.removeChild(draggingOperationInfo.draggingImage); + + if (this._droppingDestination) { + draggingOperationInfo.hasBeenDrop = true; + } + + this._notifyDroppingDestinationToPerformDropOperation( + draggingOperationInfo + ); + + this._resetTranslateContext(); + + this._notifyDroppingDestinationToConcludeDropOperation( + draggingOperationInfo + ); + + this._droppingDestination = null; + + draggingOperationInfo.source._endDraggingOperation(draggingOperationInfo); + + this._dispatchDraggingOperationEnd( + draggingOperationInfo + ); + + if (draggingOperationInfo.draggingOperationType === DragManager.DragOperationMove) { + this._shouldRemovePlaceholder = true; + this._rootComponent.needsDraw = true; + // Wait for the next draw cycle to remove the placeholder, + // allowing the receiver to perform any necessary clean-up. + return void 0; + } + } + + if (this._shouldRemovePlaceholder) { + draggingOperationInfo.source.element.style.display = this._oldSourceDisplayStyle; + + if (draggingOperationInfo.draggingSourcePlaceholderStrategy === DragManager.DraggingSourcePlaceholderStrategyVisible) { + draggingOperationInfo.source.element.parentNode.removeChild( + this._placeholderElement + ); + } + + this._shouldRemovePlaceholder = false; + } + } + } + +}, { + + DragOperationCopy: { + value: 0 + }, + + DragOperationLink: { + value: 1 + }, + + DragOperationMove: { + value: 2 + }, + + DragOperationAll :{ + value: 3 + }, + + DraggingSourcePlaceholderStrategyHidden: { + value: 0 + }, + + DraggingSourcePlaceholderStrategyVisible: { + value: 1 + } + +}); + +DragManager.prototype.captureMSPointerDown = DragManager.prototype.capturePointerdown; +DragManager.prototype.captureMSPointerMove = DragManager.prototype.capturePointermove; diff --git a/core/drag/drag.info/sample/index.html b/core/drag/drag.info/sample/index.html new file mode 100644 index 0000000000..57427bfd06 --- /dev/null +++ b/core/drag/drag.info/sample/index.html @@ -0,0 +1,20 @@ + + + + + + Drag & Drop Samples + + + + + + + + diff --git a/core/drag/drag.info/sample/package.json b/core/drag/drag.info/sample/package.json new file mode 100644 index 0000000000..386a944e5e --- /dev/null +++ b/core/drag/drag.info/sample/package.json @@ -0,0 +1,11 @@ +{ + "name": "placeholder-samples", + "version": "0.1.0", + "private": true, + "dependencies": { + "montage": "*" + }, + "mappings": { + "montage": "../../../../" + } +} diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.css b/core/drag/drag.info/sample/ui/drop.reel/drop.css new file mode 100644 index 0000000000..7197609dec --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.css @@ -0,0 +1,27 @@ +.Drop { + height: 200px; + width: 200px; + border: 2px solid #34495e; + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + -ms-align-items: center; + align-items: center; + -webkit-justify-content: center; + -ms-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: rgba(0,0,0,0); + touch-action: none; +} + +.Drop.accept-dragging-image { + border: 2px dashed #3498db; +} + +.Drop.dragging-image-over { + border: 2px solid #3498db; +} diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.html b/core/drag/drag.info/sample/ui/drop.reel/drop.html new file mode 100644 index 0000000000..a97a61b8f1 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.html @@ -0,0 +1,39 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.js b/core/drag/drag.info/sample/ui/drop.reel/drop.js new file mode 100644 index 0000000000..92df52e05e --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.js @@ -0,0 +1,64 @@ +/** + * @module ui/drop.reel + */ +var Component = require("montage/ui/component").Component, + DragManager = require("montage/core/drag/drag-manager").DragManager; + +/** + * @class Drop + * @extends Component + */ +exports.Drop = Component.specialize(/** @lends Drop# */ { + + dataSource: { + value: null + }, + + data: { + value: null + }, + + enterDocument: { + value: function () { + this.data = []; + this.registerForDragDestination(); + } + }, + + exitDocument: { + value: function () { + this.unregisterForDragDestination(); + } + }, + + draggingStarted: { + value: function (draggingOperationInfo) { + var value = draggingOperationInfo.source.value; + return value && this.data.indexOf(value) === -1; + } + }, + + performDropOperation: { + value: function (draggingOperationInfo) { + console.log( + draggingOperationInfo.source.identifier + + ': ' + draggingOperationInfo.data.get('secret') + ); + + var value = draggingOperationInfo.source.value; + + if (value && this.data.indexOf(value) === -1) { + this.data.push(value); + + if (draggingOperationInfo.draggingOperationType === DragManager.DragOperationMove) { + var index; + + if (this.dataSource && (index = this.dataSource.indexOf(value)) > -1) { + this.dataSource.splice(index, 1); + } + } + } + } + } + +}); diff --git a/core/drag/drag.info/sample/ui/main.reel/main.css b/core/drag/drag.info/sample/ui/main.reel/main.css new file mode 100644 index 0000000000..f3d16d5e49 --- /dev/null +++ b/core/drag/drag.info/sample/ui/main.reel/main.css @@ -0,0 +1,70 @@ +html, body { + padding: 0; + margin: 0; + font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: fixed; +} + +.Main { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +header { + margin: 20px 0; + font-size: 2rem; + text-align: center; + color: #33495d; + min-height: 40px; +} + +h4 { + font-size: 1rem; + color: #33495d; + margin: 40px 0; +} + +.options, +.samples { + padding: 15px; +} + +.samples { + position: absolute; + top: 250px; + bottom: 0; + left: 0; + right: 0; + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +.flex { + display: flex; + flex-wrap: wrap; +} + +.flex-row { + flex-direction: row; +} + +.list { + padding: 8px; +} + +.list > * { + margin-top: 8px; + margin-left: 8px; +} + +.squares .montage-placeholder { + border: 2px dashed #9b59b6; +} diff --git a/core/drag/drag.info/sample/ui/main.reel/main.html b/core/drag/drag.info/sample/ui/main.reel/main.html new file mode 100644 index 0000000000..c118ba5679 --- /dev/null +++ b/core/drag/drag.info/sample/ui/main.reel/main.html @@ -0,0 +1,95 @@ + + + + + + + +
+
Drag & Drop Samples
+ +
+

Options:

+

+ Enable Visible Placeholder + +

+

+ Enable Move operation + +

+
+ +
+

Simple drag&Drop

+
+
+
+
+
+
+
+ +
+
+ + diff --git a/core/drag/drag.info/sample/ui/main.reel/main.js b/core/drag/drag.info/sample/ui/main.reel/main.js new file mode 100644 index 0000000000..38580bfff2 --- /dev/null +++ b/core/drag/drag.info/sample/ui/main.reel/main.js @@ -0,0 +1,15 @@ +var Component = require("montage/ui/component").Component; + +exports.Main = Component.specialize(/** @lends Main# */{ + + data: { + value: [1, 2, 3, 4, 5] + }, + + dragDestinationShouldAcceptDraggingOperation: { + value: function () { + return false; + } + } + +}); diff --git a/core/drag/drag.info/sample/ui/square.reel/square.css b/core/drag/drag.info/sample/ui/square.reel/square.css new file mode 100644 index 0000000000..3a7a11ffcf --- /dev/null +++ b/core/drag/drag.info/sample/ui/square.reel/square.css @@ -0,0 +1,32 @@ +.Square { + height: 50px; + width: 50px; + background-color: #34495e; + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + -ms-align-items: center; + align-items: center; + -webkit-justify-content: center; + -ms-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + color: white; + -webkit-tap-highlight-color: rgba(0,0,0,0); + touch-action: none; +} + +.Square:hover { + cursor: pointer; +} + +.Square.hide { + display: none; +} + +.Square.montage-dragging-image { + background-color: #9b59b6; +} diff --git a/core/drag/drag.info/sample/ui/square.reel/square.html b/core/drag/drag.info/sample/ui/square.reel/square.html new file mode 100644 index 0000000000..479482a866 --- /dev/null +++ b/core/drag/drag.info/sample/ui/square.reel/square.html @@ -0,0 +1,28 @@ + + + + + + + +
+
+
+ + diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js new file mode 100644 index 0000000000..84380f893a --- /dev/null +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -0,0 +1,55 @@ +/** + * @module ui/square.reel + */ +var Component = require("montage/ui/component").Component, + DragManager = require("montage/core/drag/drag-manager").DragManager; + +/** + * @class Square + * @extends Component + */ +exports.Square = Component.specialize(/** @lends Square# */ { + + enableMoveOperation: { + value: false + }, + + enableVisiblePlaceholder: { + value: false + }, + + secret: { + value: null + }, + + enterDocument: { + value: function () { + this.registerForDragSource(); + } + }, + + exitDocument: { + value: function () { + this.unregisterForDragSource(); + } + }, + + beginDraggingOperation: { + value: function (draggingOperationInfo) { + if (this.enableMoveOperation) { + draggingOperationInfo.draggingOperationType = DragManager.DragOperationMove; + } + + if (this.enableVisiblePlaceholder) { + draggingOperationInfo.draggingSourcePlaceholderStrategy = ( + DragManager.DraggingSourcePlaceholderStrategyVisible + ); + } + + if (this.secret) { + draggingOperationInfo.data.set("secret", this.secret); + } + } + } + +}); diff --git a/core/drag/dragging-operation-info.js b/core/drag/dragging-operation-info.js new file mode 100644 index 0000000000..37697691d5 --- /dev/null +++ b/core/drag/dragging-operation-info.js @@ -0,0 +1,60 @@ +var Montage = require("../core").Montage; + +// name -> DraggingOperationContext? +exports.DraggingOperationInfo = Montage.specialize({ + + source: { + value: null + }, + + draggingImage: { + value: null + }, + + startPositionX: { + value: 0 + }, + + startPositionY: { + value: 0 + }, + + positionX: { + value: 0 + }, + + positionY: { + value: 0 + }, + + deltaX: { + value: 0 + }, + + deltaY: { + value: 0 + }, + + draggingSourcePlaceholderStrategy: { + value: 0 // default DraggingSourcePlaceholderStrategyHidden + }, + + draggingOperationType: { + value: 0 // default DragOperationCopy + }, + + _data: { + value: null + }, + + data: { + get: function () { + return this._data || (this._data = new Map()); + } + }, + + hasBeenDrop: { + value: false + } + +}); diff --git a/index.html b/index.html index 177fc4c519..174527d51d 100644 --- a/index.html +++ b/index.html @@ -45,6 +45,9 @@

Components:

TreeList VirtualList +

Managers:

+ Drag & Drop +

Tests:

Run tests diff --git a/ui/component.js b/ui/component.js index 99a394086e..38adee9221 100644 --- a/ui/component.js +++ b/ui/component.js @@ -21,7 +21,7 @@ var Montage = require("../core/core").Montage, Promise = require("../core/promise").Promise, defaultEventManager = require("../core/event/event-manager").defaultEventManager, Alias = require("../core/serialization/alias").Alias, - + DragManager = require("../core/drag/drag-manager").DragManager, logger = require("../core/logger").logger("component"), drawPerformanceLogger = require("../core/logger").logger("Drawing performance").color.green(), drawListLogger = require("../core/logger").logger("drawing list").color.blue(), @@ -39,7 +39,8 @@ var Montage = require("../core/core").Montage, var ATTR_LE_COMPONENT = "data-montage-le-component", ATTR_LE_ARG = "data-montage-le-arg", ATTR_LE_ARG_BEGIN = "data-montage-le-arg-begin", - ATTR_LE_ARG_END = "data-montage-le-arg-end"; + ATTR_LE_ARG_END = "data-montage-le-arg-end", + _defaultDragManager; function loggerToString (object) { @@ -744,6 +745,13 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto } }, + dragManager: { + get: function () { + return _defaultDragManager || + ((_defaultDragManager = new DragManager()).initWithComponent(this.rootComponent)); + } + }, + /** * TemplateArgumentProvider implementation */ @@ -2904,6 +2912,199 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto } }, + // Drag & Drop operations + + /** + * Register a component for beeing a dragging source. + */ + registerForDragSource: { + value: function (draggingOperationType) { + this.dragManager.registerForDragSource(this); + } + }, + + /** + * unregister a component for beeing a dragging source. + */ + unregisterForDragSource: { + value: function () { + this.dragManager.unregisterForDragSource(this); + } + }, + + /** + * Register a component for beeing a drop destination. + */ + registerForDragDestination: { + value: function () { + this.dragManager.registerForDragDestination(this); + this.classList.add("montage-drag-destination"); + } + }, + + /** + * Unregister a component for beeing a drop destination. + */ + unregisterForDragDestination: { + value: function () { + this.dragManager.unregisterForDragDestination(this); + this.classList.remove("montage-drag-destination"); + } + }, + + /** + * Called on the source when the drag operation starts. + */ + _beginDraggingOperation: { + value: function (draggingOperationInfo) { + if (typeof this.beginDraggingOperation === "function") { + this.beginDraggingOperation(draggingOperationInfo); + } + } + }, + + /** + * Called on the source when the dragged image is moving. + */ + _updateDraggingOperation: { + value: function (draggingOperationInfo) { + if (typeof this.updateDraggingOperation === "function") { + this.updateDraggingOperation(draggingOperationInfo); + } + } + }, + + /** + * Called on the source when the drag operation ends. + */ + _endDraggingOperation: { + value: function (draggingOperationInfo) { + if (typeof this.endDraggingOperation === "function") { + this.endDraggingOperation(draggingOperationInfo); + } + } + }, + + /** + * Called when the drag operation start, + * allowing the receivers to agree to or refuse the drag operation. + * By default all receivers will not accept any drag operation. + * The method `draggingStarted` should return a boolean value. + */ + _draggingStarted: { + value: function (draggingOperationInfo) { + var acceptDragOperation = false, + acceptDragOperationDelegate = this.callDelegateMethod( + "dragDestinationShouldAcceptDraggingOperation", + this, + draggingOperationInfo + ); + + if (acceptDragOperationDelegate !== void 0) { + acceptDragOperation = acceptDragOperationDelegate; + + } else if (typeof this.draggingStarted === "function") { + acceptDragOperation = this.draggingStarted(draggingOperationInfo); + acceptDragOperation = acceptDragOperation === void 0 ? + false : !!acceptDragOperation; + } + + if (acceptDragOperation) { + this.classList.add('accept-dragging-image'); + } + + this.acceptDragOperation = acceptDragOperation; + } + }, + + /** + * Called when the drag operation end, + * allowing the receivers to perform any necessary clean-up + */ + _draggingEnded: { + value: function (draggingOperationInfo) { + this.classList.remove('accept-dragging-image'); + + if (typeof this.draggingEnded === "function") { + this.draggingEnded(draggingOperationInfo); + } + } + }, + + /** + * Called when the dragged image enters + * the destination’s bounds rectangle + */ + _draggingEntered: { + value: function (draggingOperationInfo) { + this.classList.add("dragging-image-entered"); + + if (typeof this.draggingEntered === "function") { + this.draggingEntered(draggingOperationInfo); + } + } + }, + + /** + * Called periodically when the dragged image is held within + * the destination’s bounds rectangle + */ + _draggingUpdated: { + value: function (draggingOperationInfo) { + this.classList.add("dragging-image-over"); + + if (typeof this.draggingUpdated === "function") { + this.draggingUpdated(draggingOperationInfo); + } + } + }, + + /** + * Called when the dragged image exits + * the destination’s bounds rectangle + */ + _draggingExited: { + value: function (draggingOperationInfo) { + this.classList.remove("dragging-image-entered"); + this.classList.remove("dragging-image-over"); + + if (typeof this.draggingExited === "function") { + this.draggingExited(draggingOperationInfo); + } + } + }, + + /** + * Called after the released image has been removed from the screen, + * allowing the receiver to import the data. + */ + _performDropOperation: { + value: function (draggingOperationInfo) { + if (this.acceptDragOperation) { + if (typeof this.performDropOperation === "function") { + this.performDropOperation(draggingOperationInfo); + } + } + } + }, + + /** + * Called when the dropping operation is complete, + * allowing the receiver to perform any necessary clean-up. + */ + _concludeDropOperation: { + value: function (draggingOperationInfo) { + if (this.acceptDragOperation) { + this.classList.remove("dragging-image-entered"); + this.classList.remove("dragging-image-over"); + + if (typeof this.concludeDropOperation === "function") { + this.concludeDropOperation(draggingOperationInfo); + } + } + } + }, + // // Attribute Handling // @@ -4442,7 +4643,21 @@ var RootComponent = Component.specialize( /** @lends RootComponent.prototype */{ this._element = document.documentElement; this._documentResources = DocumentResources.getInstanceForDocument(document); } - } + }, + + willDraw: { + value: function () { + this.dragManager.willDraw(); + } + }, + + draw: { + value: function () { + this.dragManager.draw(); + } + } + + }); exports.__root__ = rootComponent = new RootComponent().init(); From 3309d4d9766f8a533fbc815c9d5a5d8e1099a21f Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Tue, 29 May 2018 23:35:13 +0200 Subject: [PATCH 08/65] Change cursor shape related to the dragging operation type. --- core/drag/drag-manager.js | 8 ++++++++ core/drag/drag.info/sample/ui/square.reel/square.css | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 030a6008d8..673783bf6a 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -545,7 +545,15 @@ var DragManager = exports.DragManager = Montage.specialize({ this._draggingOperationInfo.deltaX + "px," + this._draggingOperationInfo.deltaY + "px,0)"; + if (this._droppingDestination && + draggingOperationInfo.draggingOperationType === DragManager.DragOperationCopy + ) { + this._rootComponent.element.style.cursor = 'copy'; + } else { + this._rootComponent.element.style.cursor = 'move'; + } } else if (this._willTerminateDraggingOperation) { + this._rootComponent.element.style.cursor = 'default'; document.body.removeChild(draggingOperationInfo.draggingImage); if (this._droppingDestination) { diff --git a/core/drag/drag.info/sample/ui/square.reel/square.css b/core/drag/drag.info/sample/ui/square.reel/square.css index 3a7a11ffcf..9dc34603d5 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.css +++ b/core/drag/drag.info/sample/ui/square.reel/square.css @@ -20,7 +20,7 @@ } .Square:hover { - cursor: pointer; + cursor: move; } .Square.hide { From 991455a84b8eb1f062e91190211b149f759aa8f1 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Tue, 29 May 2018 23:50:33 +0200 Subject: [PATCH 09/65] Update drag&drop sample --- core/drag/drag.info/sample/ui/drop.reel/drop.css | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.css b/core/drag/drag.info/sample/ui/drop.reel/drop.css index 7197609dec..e87a3939b1 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.css +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.css @@ -1,7 +1,7 @@ .Drop { height: 200px; width: 200px; - border: 2px solid #34495e; + border: 4px solid #34495e; display: -webkit-flex; display: flex; -webkit-align-items: center; @@ -16,12 +16,19 @@ user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); touch-action: none; + box-sizing: border-box; } .Drop.accept-dragging-image { - border: 2px dashed #3498db; + border: 4px dashed #3498db25; + animation: blink 1.5s linear infinite alternate; } +@keyframes blink { + 50% { border-color: #3498db;} + } + .Drop.dragging-image-over { - border: 2px solid #3498db; + border: 4px solid #3498db; + animation: none; } From ccc70a0e1a5c9aecb67b007a8a86853ab3fbe1f7 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Wed, 30 May 2018 17:29:32 +0200 Subject: [PATCH 10/65] Add a default opacity to the dragged image --- core/drag/drag-manager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 673783bf6a..737a811868 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -185,6 +185,7 @@ var DragManager = exports.DragManager = Montage.specialize({ draggingImage.style.pointerEvents = "none"; draggingImage.style.boxSizing = "border-box"; draggingImage.style.zIndex = 999999; + draggingImage.style.opacity = 0.95; draggingOperationInfo.source = source; draggingOperationInfo.draggingImage = draggingImage; From b612985aaa9f14f9d382c0f347b27f4bacc6d4b0 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Wed, 30 May 2018 19:18:27 +0200 Subject: [PATCH 11/65] Allow the dragging source to be contained. --- core/drag/drag-manager.js | 38 +++++++++++++++++-- .../drag.info/sample/ui/drop.reel/drop.html | 3 +- .../drag.info/sample/ui/square.reel/square.js | 4 ++ core/drag/dragging-operation-info.js | 17 +++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 737a811868..842ac9b94d 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -355,6 +355,7 @@ var DragManager = exports.DragManager = Montage.specialize({ this.__translateComposer.translateX = 0; this.__translateComposer.translateY = 0; this._draggingImageBoundingRect = null; + this._draggingSourceContainerBoundingRect = null; this._willTerminateDraggingOperation = false; this._needsToWaitforGhostElementBoundaries = false; } @@ -497,6 +498,10 @@ var DragManager = exports.DragManager = Montage.specialize({ value: function () { if (this._isDragging && this._draggingOperationInfo && !this._draggingImageBoundingRect) { this._draggingImageBoundingRect = this._draggingOperationInfo.source.element.getBoundingClientRect(); + + if (this._draggingOperationInfo.draggingSourceContainer) { + this._draggingSourceContainerBoundingRect = this._draggingOperationInfo.draggingSourceContainer.getBoundingClientRect(); + } } } }, @@ -506,7 +511,9 @@ var DragManager = exports.DragManager = Montage.specialize({ var draggingOperationInfo = this._draggingOperationInfo; if (this._isDragging && !this._willTerminateDraggingOperation) { - var draggingImage = draggingOperationInfo.draggingImage; + var draggingImage = draggingOperationInfo.draggingImage, + translateX = this._draggingOperationInfo.deltaX, + translateY = this._draggingOperationInfo.deltaY; if (!draggingImage.parentElement) { draggingImage.style.top = this._draggingImageBoundingRect.top + "px"; @@ -542,9 +549,34 @@ var DragManager = exports.DragManager = Montage.specialize({ this._needsToWaitforGhostElementBoundaries = false; } + if (this._draggingSourceContainerBoundingRect) { + var rect = this._draggingSourceContainerBoundingRect, + deltaPointerLeft, deltaPointerRight, + deltaPointerTop, deltaPointerBottom; + + if (draggingOperationInfo.positionX - ( + deltaPointerLeft = draggingOperationInfo.startPositionX - this._draggingImageBoundingRect.left + ) < rect.left) { + translateX = rect.left - draggingOperationInfo.startPositionX + deltaPointerLeft; + } else if (draggingOperationInfo.positionX + ( + deltaPointerRight = this._draggingImageBoundingRect.right - draggingOperationInfo.startPositionX + ) > rect.right) { + translateX = rect.right - draggingOperationInfo.startPositionX - deltaPointerRight; + } + + if (draggingOperationInfo.positionY - ( + deltaPointerTop = draggingOperationInfo.startPositionY - this._draggingImageBoundingRect.top + ) < rect.top) { + translateY = rect.top - draggingOperationInfo.startPositionY + deltaPointerTop; + } else if (draggingOperationInfo.positionY + ( + deltaPointerBottom = this._draggingImageBoundingRect.bottom - draggingOperationInfo.startPositionY + ) > rect.bottom) { + translateY = rect.bottom - draggingOperationInfo.startPositionY - deltaPointerBottom; + } + } + draggingImage.style[DragManager.cssTransform] = "translate3d(" + - this._draggingOperationInfo.deltaX + "px," + - this._draggingOperationInfo.deltaY + "px,0)"; + translateX + "px," + translateY + "px,0)"; if (this._droppingDestination && draggingOperationInfo.draggingOperationType === DragManager.DragOperationCopy diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.html b/core/drag/drag.info/sample/ui/drop.reel/drop.html index a97a61b8f1..c042e280a0 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.html +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.html @@ -23,7 +23,8 @@ "values": { "element": {"#": "square"}, "identifier": {"<-": "'square ' + @repetition:iteration.object"}, - "value": {"<-": "@repetition:iteration.object"} + "value": {"<-": "@repetition:iteration.object"}, + "container": {"@": "owner"} } } } diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js index 84380f893a..79bdcbb421 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.js +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -40,6 +40,10 @@ exports.Square = Component.specialize(/** @lends Square# */ { draggingOperationInfo.draggingOperationType = DragManager.DragOperationMove; } + if (this.container) { + draggingOperationInfo.draggingSourceContainer = this.container; + } + if (this.enableVisiblePlaceholder) { draggingOperationInfo.draggingSourcePlaceholderStrategy = ( DragManager.DraggingSourcePlaceholderStrategyVisible diff --git a/core/drag/dragging-operation-info.js b/core/drag/dragging-operation-info.js index 37697691d5..a2a045023a 100644 --- a/core/drag/dragging-operation-info.js +++ b/core/drag/dragging-operation-info.js @@ -43,6 +43,23 @@ exports.DraggingOperationInfo = Montage.specialize({ value: 0 // default DragOperationCopy }, + _draggingSourceContainer: { + value: null + }, + + draggingSourceContainer: { + set: function (element) { + if (element instanceof Element) { + this._draggingSourceContainer = element; + } else if (element.element instanceof Element) { + this._draggingSourceContainer = element.element; + } + }, + get: function () { + return this._draggingSourceContainer; + } + }, + _data: { value: null }, From 16e5dfedf609458cf945bc12495629b090c2b31b Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Wed, 30 May 2018 19:47:53 +0200 Subject: [PATCH 12/65] Update drag&drop sample --- .../drag.info/sample/ui/drop.reel/drop.css | 26 +++++++++-- .../drag.info/sample/ui/drop.reel/drop.html | 4 +- .../drag.info/sample/ui/main.reel/main.css | 2 +- .../drag.info/sample/ui/main.reel/main.html | 45 ++++++++++++++++--- .../sample/ui/square.reel/square.css | 1 + 5 files changed, 67 insertions(+), 11 deletions(-) diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.css b/core/drag/drag.info/sample/ui/drop.reel/drop.css index e87a3939b1..f7271ee1da 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.css +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.css @@ -19,16 +19,36 @@ box-sizing: border-box; } +.Drop .drop-placeholder { + display: none; + color: #34495e; +} + +.Drop.is-empty .drop-placeholder { + display: block; +} + .Drop.accept-dragging-image { border: 4px dashed #3498db25; animation: blink 1.5s linear infinite alternate; } -@keyframes blink { - 50% { border-color: #3498db;} - } +.Drop.accept-dragging-image.is-empty .drop-placeholder { + color:#3498db25; + animation: blink 1.5s linear infinite alternate; +} + +.Drop.dragging-image-over.is-empty .drop-placeholder { + color:#3498db; + animation: none; +} .Drop.dragging-image-over { border: 4px solid #3498db; animation: none; } + +@keyframes blink { + 50% { border-color: #3498db; color: #3498db } + } + diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.html b/core/drag/drag.info/sample/ui/drop.reel/drop.html index c042e280a0..1b67324cb3 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.html +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.html @@ -6,7 +6,8 @@ { "owner": { "values": { - "element": {"#": "owner"} + "element": {"#": "owner"}, + "classList.has('is-empty')": {"<-": "@owner.data.length == 0"} } }, @@ -32,6 +33,7 @@
+
diff --git a/core/drag/drag.info/sample/ui/main.reel/main.css b/core/drag/drag.info/sample/ui/main.reel/main.css index f3d16d5e49..8e9ecb7876 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.css +++ b/core/drag/drag.info/sample/ui/main.reel/main.css @@ -65,6 +65,6 @@ h4 { margin-left: 8px; } -.squares .montage-placeholder { +.samples .montage-placeholder { border: 2px dashed #9b59b6; } diff --git a/core/drag/drag.info/sample/ui/main.reel/main.html b/core/drag/drag.info/sample/ui/main.reel/main.html index c118ba5679..1b72f8021b 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.html +++ b/core/drag/drag.info/sample/ui/main.reel/main.html @@ -24,6 +24,27 @@ } }, + "square1": { + "prototype": "../square.reel", + "values": { + "element": {"#": "square1"}, + "value": {"<-": "'drag me'"}, + "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, + "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} + } + }, + + "square2": { + "prototype": "../square.reel", + "values": { + "element": {"#": "square2"}, + "value": {"<-": "'drag me'"}, + "container": {"#": "container1"}, + "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, + "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} + } + }, + "repetition": { "prototype": "montage/ui/repetition.reel", "values": { @@ -32,10 +53,10 @@ } }, - "square": { + "square3": { "prototype": "../square.reel", "values": { - "element": {"#": "square"}, + "element": {"#": "square3"}, "identifier": {"<-": "'square ' + @repetition:iteration.object"}, "value": {"<-": "@repetition:iteration.object"}, "secret": {"<-": "'secret' + @repetition:iteration.object"}, @@ -80,13 +101,25 @@

Options:

-

Simple drag&Drop

+

Simple drag

+
+ +

Drag within a container

+
+
+
+ +

Drag&Drop

-
+
-
-
+
+
Drop Here
+
+
+
Drop not allowed
+
diff --git a/core/drag/drag.info/sample/ui/square.reel/square.css b/core/drag/drag.info/sample/ui/square.reel/square.css index 9dc34603d5..ff8677bdc2 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.css +++ b/core/drag/drag.info/sample/ui/square.reel/square.css @@ -17,6 +17,7 @@ color: white; -webkit-tap-highlight-color: rgba(0,0,0,0); touch-action: none; + text-align: center; } .Square:hover { From 95757dacada5d41c68d8557121e265465721fe86 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Wed, 30 May 2018 20:29:45 +0200 Subject: [PATCH 13/65] Add drag&drop outer/inner sample --- .../sample/ui/drop-inner.reel/drop-inner.css | 25 +++++++++++++ .../sample/ui/drop-inner.reel/drop-inner.html | 20 ++++++++++ .../sample/ui/drop-inner.reel/drop-inner.js | 37 +++++++++++++++++++ .../sample/ui/drop-outer.reel/drop-outer.css | 32 ++++++++++++++++ .../sample/ui/drop-outer.reel/drop-outer.html | 21 +++++++++++ .../sample/ui/drop-outer.reel/drop-outer.js | 37 +++++++++++++++++++ .../drag.info/sample/ui/drop.reel/drop.css | 1 + .../drag.info/sample/ui/drop.reel/drop.js | 3 +- .../drag.info/sample/ui/main.reel/main.html | 34 ++++++++++++++++- 9 files changed, 207 insertions(+), 3 deletions(-) create mode 100644 core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css create mode 100644 core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.html create mode 100644 core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js create mode 100644 core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css create mode 100644 core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.html create mode 100644 core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css new file mode 100644 index 0000000000..7fed8ed448 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css @@ -0,0 +1,25 @@ +.DropInner::before { + position: absolute; + top: 5px; + left: 5px; + content: "inner"; +} +.Drop.DropInner.accept-dragging-image { + border: 4px solid #34495e; + animation: none; +} + +.Drop.DropInner.accept-dragging-image.is-empty .drop-placeholder { + color:#34495e; + animation: none; +} + +.Drop.DropInner.dragging-image-over.is-empty .drop-placeholder { + color:#3498db; + animation: none; +} + +.Drop.DropInner.dragging-image-over { + border: 4px solid #3498db; + animation: none; +} \ No newline at end of file diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.html b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.html new file mode 100644 index 0000000000..f8e4c85c08 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.html @@ -0,0 +1,20 @@ + + + + + + + + +
+
+ + diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js new file mode 100644 index 0000000000..6f05e8ec19 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js @@ -0,0 +1,37 @@ +/** + * @module ui/drop-inner.reel + */ +var Component = require("montage/ui/component").Component; + +/** + * @class DropInner + * @extends Component + */ +exports.DropInner = Component.specialize(/** @lends DropInner# */ { + + enterDocument: { + value: function () { + this.data = []; + this.registerForDragDestination(); + } + }, + + exitDocument: { + value: function () { + this.unregisterForDragDestination(); + } + }, + + draggingStarted: { + value: function (draggingOperationInfo) { + return true; + } + }, + + performDropOperation: { + value: function (draggingOperationInfo) { + console.log('dropzone inner received dragging operation'); + } + } + +}); diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css new file mode 100644 index 0000000000..a33754b820 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css @@ -0,0 +1,32 @@ +.DropOuter { + height: 400px !important; + width: 400px !important; + margin-top: 20px; +} + +.DropOuter::before { + position: absolute; + top: 5px; + left: 5px; + content: "outer"; +} + +.Drop.DropOuter.accept-dragging-image { + border: 4px solid #34495e; + animation: none; +} + +.Drop.DropOuter.accept-dragging-image.is-empty .drop-placeholder { + color:#34495e; + animation: none; +} + +.Drop.DropOuter.dragging-image-over.is-empty .drop-placeholder { + color:#3498db; + animation: none; +} + +.Drop.DropOuter.dragging-image-over { + border: 4px solid #3498db; + animation: none; +} \ No newline at end of file diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.html b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.html new file mode 100644 index 0000000000..a0eb1306f4 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.html @@ -0,0 +1,21 @@ + + + + + + + + +
+
+
+ + diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js new file mode 100644 index 0000000000..2149a13918 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js @@ -0,0 +1,37 @@ +/** + * @module ui/drop-outer.reel + */ +var Component = require("montage/ui/component").Component; + +/** + * @class DropOuter + * @extends Component + */ +exports.DropOuter = Component.specialize(/** @lends DropOuter# */ { + + enterDocument: { + value: function () { + this.data = []; + this.registerForDragDestination(); + } + }, + + exitDocument: { + value: function () { + this.unregisterForDragDestination(); + } + }, + + draggingStarted: { + value: function (draggingOperationInfo) { + return true; + } + }, + + performDropOperation: { + value: function (draggingOperationInfo) { + console.log('dropzone outer received dragging operation'); + } + } + +}); diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.css b/core/drag/drag.info/sample/ui/drop.reel/drop.css index f7271ee1da..38af29e08b 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.css +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.css @@ -17,6 +17,7 @@ -webkit-tap-highlight-color: rgba(0,0,0,0); touch-action: none; box-sizing: border-box; + position: relative; } .Drop .drop-placeholder { diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.js b/core/drag/drag.info/sample/ui/drop.reel/drop.js index 92df52e05e..4bd6dac51c 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.js +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.js @@ -34,7 +34,8 @@ exports.Drop = Component.specialize(/** @lends Drop# */ { draggingStarted: { value: function (draggingOperationInfo) { var value = draggingOperationInfo.source.value; - return value && this.data.indexOf(value) === -1; + return value && this.data.indexOf(value) === -1 && + this.dataSource.indexOf(value) > -1; } }, diff --git a/core/drag/drag.info/sample/ui/main.reel/main.html b/core/drag/drag.info/sample/ui/main.reel/main.html index 1b72f8021b..c1c67d2300 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.html +++ b/core/drag/drag.info/sample/ui/main.reel/main.html @@ -28,7 +28,7 @@ "prototype": "../square.reel", "values": { "element": {"#": "square1"}, - "value": {"<-": "'drag me'"}, + "value": "drag me", "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} } @@ -38,7 +38,7 @@ "prototype": "../square.reel", "values": { "element": {"#": "square2"}, - "value": {"<-": "'drag me'"}, + "value": "drag me", "container": {"#": "container1"}, "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} @@ -79,6 +79,30 @@ "element": {"#": "drop2"}, "delegate": {"@": "owner"} } + }, + + "drop3": { + "prototype": "../drop-outer.reel", + "values": { + "element": {"#": "drop3"} + } + }, + + "drop4": { + "prototype": "../drop-inner.reel", + "values": { + "element": {"#": "drop4"} + } + }, + + "square4": { + "prototype": "../square.reel", + "values": { + "element": {"#": "square4"}, + "value": "drag me", + "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, + "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} + } } } @@ -121,6 +145,12 @@

Drag&Drop

Drop not allowed
+ +

inner Dropzone

+
+
+
+
From ea71455eb7c34a83b18c779bf8fed4f09b3a5fe8 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Wed, 30 May 2018 21:55:29 +0200 Subject: [PATCH 14/65] Allow to change the dragged image when dragging a component. --- core/drag/drag-manager.js | 66 ++++++++++++------- .../drag.info/sample/ui/main.reel/main.css | 2 +- .../drag.info/sample/ui/main.reel/main.html | 16 +++++ .../drag.info/sample/ui/square.reel/square.js | 11 ++++ core/drag/dragging-operation-info.js | 15 ++++- 5 files changed, 82 insertions(+), 28 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 842ac9b94d..fd528f07f1 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -176,19 +176,8 @@ var DragManager = exports.DragManager = Montage.specialize({ _createDraggingOperationInfoWithSourceAndPosition: { value: function (source, startPosition) { - var draggingOperationInfo = new DraggingOperationInfo(), - draggingImage = source.element.cloneNode(true); - - draggingImage.classList.add("montage-dragging-image"); - draggingImage.style.visibility = "hidden"; - draggingImage.style.position = "absolute"; - draggingImage.style.pointerEvents = "none"; - draggingImage.style.boxSizing = "border-box"; - draggingImage.style.zIndex = 999999; - draggingImage.style.opacity = 0.95; - + var draggingOperationInfo = new DraggingOperationInfo(); draggingOperationInfo.source = source; - draggingOperationInfo.draggingImage = draggingImage; draggingOperationInfo.startPositionX = startPosition.pageX; draggingOperationInfo.startPositionY = startPosition.pageY; draggingOperationInfo.positionX = startPosition.pageX; @@ -198,6 +187,20 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + _sanitizeDraggedImage: { + value: function (draggedImage) { + draggedImage.classList.add("montage-dragging-image"); + draggedImage.style.visibility = "hidden"; + draggedImage.style.position = "absolute"; + draggedImage.style.pointerEvents = "none"; + draggedImage.style.boxSizing = "border-box"; + draggedImage.style.zIndex = 999999; + draggedImage.style.opacity = 0.95; + + return draggedImage; + } + }, + _dispatchDraggingOperationStart: { value: function (draggingOperationInfo) { var component; @@ -417,7 +420,8 @@ var DragManager = exports.DragManager = Montage.specialize({ sourceComponent = this._findDraggingSourceAtPosition( startPosition.pageX, startPosition.pageY - ); + ), + draggedImage; if (sourceComponent) { this._draggingOperationInfo = this._createDraggingOperationInfoWithSourceAndPosition( @@ -430,6 +434,17 @@ var DragManager = exports.DragManager = Montage.specialize({ ); sourceComponent._beginDraggingOperation(this._draggingOperationInfo); + + if (!this._draggingOperationInfo.draggedImage) { + draggedImage = sourceComponent.element.cloneNode(true); + } else { + draggedImage = this._draggingOperationInfo.draggedImage; + } + + this._draggingOperationInfo.draggedImage = this._sanitizeDraggedImage( + draggedImage + ); + this._dispatchDraggingOperationStart(this._draggingOperationInfo); this._isDragging = true; this._rootComponent.needsDraw = true; @@ -511,16 +526,16 @@ var DragManager = exports.DragManager = Montage.specialize({ var draggingOperationInfo = this._draggingOperationInfo; if (this._isDragging && !this._willTerminateDraggingOperation) { - var draggingImage = draggingOperationInfo.draggingImage, - translateX = this._draggingOperationInfo.deltaX, - translateY = this._draggingOperationInfo.deltaY; + var draggedImage = draggingOperationInfo.draggedImage, + translateX = draggingOperationInfo.deltaX, + translateY = draggingOperationInfo.deltaY; - if (!draggingImage.parentElement) { - draggingImage.style.top = this._draggingImageBoundingRect.top + "px"; - draggingImage.style.left = this._draggingImageBoundingRect.left + "px"; - draggingImage.style.width = this._draggingImageBoundingRect.width + "px"; - draggingImage.style.height = this._draggingImageBoundingRect.height + "px"; - document.body.appendChild(draggingImage); + if (!draggedImage.parentElement) { + draggedImage.style.top = this._draggingImageBoundingRect.top + "px"; + draggedImage.style.left = this._draggingImageBoundingRect.left + "px"; + draggedImage.style.width = this._draggingImageBoundingRect.width + "px"; + draggedImage.style.height = this._draggingImageBoundingRect.height + "px"; + document.body.appendChild(draggedImage); if (draggingOperationInfo.draggingOperationType === DragManager.DragOperationMove) { this._oldSourceDisplayStyle = draggingOperationInfo.source.element.style.display; @@ -540,11 +555,12 @@ var DragManager = exports.DragManager = Montage.specialize({ } } + draggingOperationInfo.isDragging = true; this._needsToWaitforGhostElementBoundaries = true; } if (!this._needsToWaitforGhostElementBoundaries) { - draggingImage.style.visibility = "visible"; + draggedImage.style.visibility = "visible"; } else { this._needsToWaitforGhostElementBoundaries = false; } @@ -575,7 +591,7 @@ var DragManager = exports.DragManager = Montage.specialize({ } } - draggingImage.style[DragManager.cssTransform] = "translate3d(" + + draggedImage.style[DragManager.cssTransform] = "translate3d(" + translateX + "px," + translateY + "px,0)"; if (this._droppingDestination && @@ -587,7 +603,7 @@ var DragManager = exports.DragManager = Montage.specialize({ } } else if (this._willTerminateDraggingOperation) { this._rootComponent.element.style.cursor = 'default'; - document.body.removeChild(draggingOperationInfo.draggingImage); + document.body.removeChild(draggingOperationInfo.draggedImage); if (this._droppingDestination) { draggingOperationInfo.hasBeenDrop = true; diff --git a/core/drag/drag.info/sample/ui/main.reel/main.css b/core/drag/drag.info/sample/ui/main.reel/main.css index 8e9ecb7876..3060cd2f62 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.css +++ b/core/drag/drag.info/sample/ui/main.reel/main.css @@ -39,7 +39,7 @@ h4 { .samples { position: absolute; - top: 250px; + top: 300px; bottom: 0; left: 0; right: 0; diff --git a/core/drag/drag.info/sample/ui/main.reel/main.html b/core/drag/drag.info/sample/ui/main.reel/main.html index c1c67d2300..ebb1af2df8 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.html +++ b/core/drag/drag.info/sample/ui/main.reel/main.html @@ -24,12 +24,20 @@ } }, + "switchDraggedImage": { + "prototype": "montage/ui/checkbox.reel", + "values": { + "element": {"#": "switchDraggedImage"} + } + }, + "square1": { "prototype": "../square.reel", "values": { "element": {"#": "square1"}, "value": "drag me", "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, + "switchDraggedImage": {"<-": "!!@switchDraggedImage.checked"}, "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} } }, @@ -41,6 +49,7 @@ "value": "drag me", "container": {"#": "container1"}, "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, + "switchDraggedImage": {"<-": "!!@switchDraggedImage.checked"}, "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} } }, @@ -60,6 +69,7 @@ "identifier": {"<-": "'square ' + @repetition:iteration.object"}, "value": {"<-": "@repetition:iteration.object"}, "secret": {"<-": "'secret' + @repetition:iteration.object"}, + "switchDraggedImage": {"<-": "!!@switchDraggedImage.checked"}, "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} } @@ -100,6 +110,7 @@ "values": { "element": {"#": "square4"}, "value": "drag me", + "switchDraggedImage": {"<-": "!!@switchDraggedImage.checked"}, "enableVisiblePlaceholder": {"<-": "!!@enableVisiblePlaceholder.checked"}, "enableMoveOperation": {"<-": "!!@enableMoveOperation.checked"} } @@ -122,6 +133,11 @@

Options:

Enable Move operation

+ +

+ Switch Dragged Image + +

diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js index 79bdcbb421..bb15559b21 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.js +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -53,6 +53,17 @@ exports.Square = Component.specialize(/** @lends Square# */ { if (this.secret) { draggingOperationInfo.data.set("secret", this.secret); } + + if (this.switchDraggedImage) { + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + var circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); + circle.setAttributeNS(null, 'cx', 25); + circle.setAttributeNS(null, 'cy', 25); + circle.setAttributeNS(null, 'r', 25); + circle.setAttributeNS(null, 'style', 'fill: #e74c3c;'); + svg.appendChild(circle); + draggingOperationInfo.draggedImage = svg; + } } } diff --git a/core/drag/dragging-operation-info.js b/core/drag/dragging-operation-info.js index a2a045023a..9b818a6ce5 100644 --- a/core/drag/dragging-operation-info.js +++ b/core/drag/dragging-operation-info.js @@ -7,8 +7,19 @@ exports.DraggingOperationInfo = Montage.specialize({ value: null }, - draggingImage: { - value: null + draggedImage: { + set: function (image) { + if (!this.isDragging) { + this._draggedImage = image; + } + }, + get: function () { + return this._draggedImage; + } + }, + + isDragging: { + value: false }, startPositionX: { From 2eaf49d3715d2ad47b9db9862a390cdf12285104 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Thu, 31 May 2018 17:21:57 +0200 Subject: [PATCH 15/65] Clean up drag manager --- core/drag/drag-manager.js | 596 +++++++++++++----- .../sample/ui/drop-inner.reel/drop-inner.css | 8 +- .../sample/ui/drop-inner.reel/drop-inner.js | 2 +- .../sample/ui/drop-outer.reel/drop-outer.css | 8 +- .../sample/ui/drop-outer.reel/drop-outer.js | 2 +- .../drag.info/sample/ui/drop.reel/drop.css | 8 +- .../drag.info/sample/ui/drop.reel/drop.js | 10 +- .../drag.info/sample/ui/main.reel/main.css | 2 +- .../sample/ui/square.reel/square.css | 2 +- .../drag.info/sample/ui/square.reel/square.js | 13 +- core/drag/dragging-operation-info.js | 26 +- ui/component.js | 38 +- 12 files changed, 493 insertions(+), 222 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index fd528f07f1..2709cd105e 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -2,31 +2,36 @@ var Montage = require("../core").Montage, TranslateComposer = require("../../composer/translate-composer").TranslateComposer, DraggingOperationInfo = require("./dragging-operation-info").DraggingOperationInfo; -var DRAG_OPERATION = 0; -var DROP_OPERATION = 1; +var DRAG_SOURCE = 0; +var DRAG_DESTINATION = 1; +var TOUCH_POINTER = "touch"; var DragManager = exports.DragManager = Montage.specialize({ - __draggingSources: { + __dragSources: { value: null }, - _draggingSources: { + _dragSources: { get: function () { - return this.__draggingSources || (this.__draggingSources = []); + return this.__dragSources || (this.__dragSources = []); } }, - __droppingDestinations: { + __dragDestinations: { value: null }, - _droppingDestinations: { + _dragDestinations: { get: function () { - return this.__droppingDestinations || (this.__droppingDestinations = []); + return this.__dragDestinations || (this.__dragDestinations = []); } }, + _dragDestination: { + value: null + }, + __rootComponent: { value: null }, @@ -35,7 +40,9 @@ var DragManager = exports.DragManager = Montage.specialize({ set: function (component) { if (this.__rootComponent !== component) { if (this.__rootComponent) { - this.__rootComponent.removeComposer(this._translateComposer); + this.__rootComponent.removeComposer( + this._translateComposer + ); } if (component) { @@ -52,11 +59,6 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, - _TOUCH_POINTER: { - value: "touch", - writable: false - }, - __translateComposer: { value: null }, @@ -88,10 +90,22 @@ var DragManager = exports.DragManager = Montage.specialize({ value: false }, - _needsToWaitforGhostElementBoundaries: { + _needsToWaitforDraggedImageBoundaries: { value: false }, + _dragSourceContainerBoundingRect: { + value: null + }, + + _draggedImageBoundingRect: { + value: null + }, + + _oldDragSourceDisplayStyle: { + value: null + }, + initWithComponent: { value: function (component) { this._rootComponent = component; @@ -109,10 +123,8 @@ var DragManager = exports.DragManager = Montage.specialize({ if (window.PointerEvent) { element.addEventListener("pointerdown", this, true); - } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { element.addEventListener("MSPointerDown", this, true); - } else { element.addEventListener("touchstart", this, true); } @@ -125,33 +137,44 @@ var DragManager = exports.DragManager = Montage.specialize({ registerForDragSource: { value: function (component) { - this._register(component, DRAG_OPERATION); + this._register(component, DRAG_SOURCE); } }, registerForDragDestination: { value: function (component) { - this._register(component, DROP_OPERATION); + this._register(component, DRAG_DESTINATION); } }, unregisterForDragSource: { value: function (component) { - this._unregister(component, DRAG_OPERATION); + this._unregister(component, DRAG_SOURCE); } }, unregisterForDragDestination: { value: function (component) { - this._unregister(component, DROP_OPERATION); + this._unregister(component, DRAG_DESTINATION); } }, + /** + * Private APIs + */ + + /** + * @private + * @function + * @param {Component} component + * @param {number} role - component's role -> drag source or destination + * @description register an component to be a drag source or destination + */ _register: { - value: function (component, operationType) { + value: function (component, role) { if (component) { - var components = operationType === DRAG_OPERATION ? - this._draggingSources : this._droppingDestinations; + var components = role === DRAG_SOURCE ? + this._dragSources : this._dragDestinations; if (components.indexOf(component) === -1) { components.push(component); @@ -160,11 +183,19 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + /** + * @private + * @function + * @param {Component} component + * @param {number} role - component's role -> drag source or destination + * @description unregister an component from beeing + * a drag source or destination + */ _unregister: { - value: function (component, operationType) { + value: function (component, role) { if (component) { - var components = operationType === DRAG_OPERATION ? - this._draggingSources : this._droppingDestinations, + var components = role === DRAG_SOURCE ? + this._dragSources : this._dragDestinations, index; if ((index = components.indexOf(component)) > -1) { @@ -174,10 +205,17 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + /** + * @private + * @function + * @param {Element} draggedImage - node element that will be used + * as a dragged image + * @description set some default css style on the dragged image. + */ _createDraggingOperationInfoWithSourceAndPosition: { - value: function (source, startPosition) { + value: function (dragSource, startPosition) { var draggingOperationInfo = new DraggingOperationInfo(); - draggingOperationInfo.source = source; + draggingOperationInfo.dragSource = dragSource; draggingOperationInfo.startPositionX = startPosition.pageX; draggingOperationInfo.startPositionY = startPosition.pageY; draggingOperationInfo.positionX = startPosition.pageX; @@ -187,9 +225,16 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + /** + * @private + * @function + * @param {Element} draggedImage - node element that will be used + * as a dragged image + * @description set some default css style on the dragged image. + */ _sanitizeDraggedImage: { value: function (draggedImage) { - draggedImage.classList.add("montage-dragging-image"); + draggedImage.classList.add("montage-dragged-image"); draggedImage.style.visibility = "hidden"; draggedImage.style.position = "absolute"; draggedImage.style.pointerEvents = "none"; @@ -201,114 +246,199 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + /** + * @private + * @function + * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * operation info object + * @description Dispatch to drag destinations that + * the dragging operation has started. + */ _dispatchDraggingOperationStart: { value: function (draggingOperationInfo) { - var component; - - for (var i = 0, length = this._droppingDestinations.length; i < length; i++) { - component = this._droppingDestinations[i]; + var dragDestinations = this._dragDestinations, + component; + + for (var i = 0, length = dragDestinations.length; i < length; i++) { + component = dragDestinations[i]; component._draggingStarted(draggingOperationInfo); } } }, + /** + * @private + * @function + * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * operation info object + * @description Dispatch to drag destinations that + * the dragging operation has ended. + */ _dispatchDraggingOperationEnd: { value: function (draggingOperationInfo) { - var component; + var dragDestinations = this._dragDestinations, + component; - for (var i = 0, length = this._droppingDestinations.length; i < length; i++) { - component = this._droppingDestinations[i]; + for (var i = 0, length = dragDestinations.length; i < length; i++) { + component = dragDestinations[i]; component._draggingEnded(draggingOperationInfo); } } }, - _notifyDroppingDestinationToPerformDropOperation: { + /** + * @private + * @function + * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * operation info object + * @description Notify to the drag destination + * to perform the drag operation. + */ + _notifyDragDestinationToPerformDragOperation: { value: function (draggingOperationInfo) { - if (this._droppingDestination) { - this._droppingDestination._performDropOperation( + if (this._dragDestination) { + this._dragDestination._performDragOperation( draggingOperationInfo ); } } }, - _notifyDroppingDestinationToConcludeDropOperation: { + /** + * @private + * @function + * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * operation info object + * @description Notify to the drag destination + * to conclude the drag operation. + */ + _notifyDragDestinationToConcludeDragOperation: { value: function (draggingOperationInfo) { - if (this._droppingDestination) { - this._droppingDestination._concludeDropOperation( + if (this._dragDestination) { + this._dragDestination._concludeDragOperation( draggingOperationInfo ); } } }, - _notifyDroppingDestinationDraggingImageHasEntered: { + /** + * @private + * @function + * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * operation info object + * @description Notify to the drag destination + * that the dragged image has entered its bounds rectangle. + */ + _notifyDragDestinationDraggedImageHasEntered: { value: function (draggingOperationInfo) { - if (this._droppingDestination) { - this._droppingDestination._draggingEntered( + if (this._dragDestination) { + this._dragDestination._draggingEntered( draggingOperationInfo ); } } }, - _notifyDroppingDestinationDraggingImageHasUpdated: { + /** + * @private + * @function + * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * operation info object + * @description Notify to the drag destination + * that the dragged image is held within its bounds rectangle. + */ + _notifyDragDestinationDraggedImageHasUpdated: { value: function (draggingOperationInfo) { - if (this._droppingDestination) { - this._droppingDestination._draggingUpdated( + if (this._dragDestination) { + this._dragDestination._draggingUpdated( draggingOperationInfo ); } } }, - _notifyDroppingDestinationDraggingImageHasExited: { + /** + * @private + * @function + * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * operation info object + * @description Notify to the drag destination + * that the dragged image has exited its bounds rectangle. + */ + _notifyDragDestinationDraggedImageHasExited: { value: function (draggingOperationInfo) { - if (this._droppingDestination) { - this._droppingDestination._draggingExited( + if (this._dragDestination) { + this._dragDestination._draggingExited( draggingOperationInfo ); } } }, - _findDraggingSourceAtPosition: { + /** + * @private + * @function + * @param {string} positionX - x coordinate + * @param {string} positionY - y coordinate + * @description try to find a drag source at the given position. + * @returns {Component|null} + */ + _findDragSourceAtPosition: { value: function (positionX, positionY) { return this._findRegisteredComponentAtPosistion( positionX, positionY, - DRAG_OPERATION + DRAG_SOURCE ); } }, - _findDropDestinationAtPosition: { + /** + * @private + * @function + * @param {string} positionX - x coordinate + * @param {string} positionY - y coordinate + * @description try to find a drag destination at the given position. + * @returns {Component|null} + */ + _findDragDestinationAtPosition: { value: function (positionX, positionY) { - var droppingDestination = this._findRegisteredComponentAtPosistion( + var dragDestination = this._findRegisteredComponentAtPosistion( positionX, positionY, - DROP_OPERATION + DRAG_DESTINATION ); - return droppingDestination && droppingDestination.acceptDragOperation ? - droppingDestination : null; + return dragDestination && dragDestination.acceptDragOperation ? + dragDestination : null; } }, + /** + * @private + * @function + * @param {string} positionX - x coordinate + * @param {string} positionY - y coordinate + * @description try to find a drag source or destination + * at the given position. + * @returns {Component|null} + */ _findRegisteredComponentAtPosistion: { - value: function (positionX, positionY, operationType) { - var targetComponent = this._findComponentAtPosition(positionX, positionY), - registeredComponent; + value: function (positionX, positionY, role) { + var targetComponent = this._findComponentAtPosition( + positionX, positionY + ), + registeredComponent = null; if (targetComponent) { - var registeredComponents = operationType === DRAG_OPERATION ? - this._draggingSources : this._droppingDestinations, + var components = role === DRAG_SOURCE ? + this._dragSources : this._dragDestinations, index; while (targetComponent) { - if ((index = registeredComponents.indexOf(targetComponent)) > -1) { - registeredComponent = registeredComponents[index]; + if ((index = components.indexOf(targetComponent)) > -1) { + registeredComponent = components[index]; targetComponent = null; } else { targetComponent = targetComponent.parentComponent; @@ -320,10 +450,18 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + /** + * @private + * @function + * @param {string} positionX - x coordinate + * @param {string} positionY - y coordinate + * @description try to find a component at the given position. + * @returns {Component|null} + */ _findComponentAtPosition: { value: function (positionX, positionY) { var element = document.elementFromPoint(positionX, positionY), - component; + component = null; if (element) { while (element && !(component = element.component)) { @@ -335,6 +473,11 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + /** + * @private + * @function + * @description add translate listeners. + */ _addTranslateListeners: { value: function () { this._translateComposer.addEventListener('translate', this); @@ -343,6 +486,11 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + /** + * @private + * @function + * @description remove translate listeners. + */ _removeTranslateListeners: { value: function () { this._translateComposer.removeEventListener('translate', this); @@ -351,23 +499,34 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + /** + * @private + * @function + * @description reset the dragging operation context. + */ _resetTranslateContext: { value: function () { this._removeTranslateListeners(); this._isDragging = false; this.__translateComposer.translateX = 0; this.__translateComposer.translateY = 0; - this._draggingImageBoundingRect = null; - this._draggingSourceContainerBoundingRect = null; + this._oldDragSourceDisplayStyle = null; + this._draggedImageBoundingRect = null; + this._dragSourceContainerBoundingRect = null; this._willTerminateDraggingOperation = false; - this._needsToWaitforGhostElementBoundaries = false; + this._needsToWaitforDraggedImageBoundaries = false; } }, + /** + * Events Handlers + */ + capturePointerdown: { value: function (event) { - if (event.pointerType === this._TOUCH_POINTER || - (window.MSPointerEvent && event.pointerType === window.MSPointerEvent.MSPOINTER_TYPE_TOUCH) + if (event.pointerType === TOUCH_POINTER || + (window.MSPointerEvent && + event.pointerType === window.MSPointerEvent.MSPOINTER_TYPE_TOUCH) ) { this.captureTouchstart(event); } @@ -376,18 +535,27 @@ var DragManager = exports.DragManager = Montage.specialize({ captureTouchstart: { value: function (event) { - var sourceComponent = this._findDraggingSourceAtPosition( + var dragSource = this._findDragSourceAtPosition( event.pageX, event.pageY ); - if (sourceComponent) { + if (dragSource) { if (window.PointerEvent) { - this._rootComponent.element.addEventListener("pointermove", this, true); - } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { - this._rootComponent.element.addEventListener("MSPointerMove", this, true); + this._rootComponent.element.addEventListener( + "pointermove", this, true + ); + } else if ( + window.MSPointerEvent && + window.navigator.msPointerEnabled + ) { + this._rootComponent.element.addEventListener( + "MSPointerMove", this, true + ); } else { - this._rootComponent.element.addEventListener("touchmove", this, true); + this._rootComponent.element.addEventListener( + "touchmove", this, true + ); } } } @@ -405,11 +573,17 @@ var DragManager = exports.DragManager = Montage.specialize({ event.preventDefault(); if (window.PointerEvent) { - this._rootComponent.element.removeEventListener("pointermove", this, true); + this._rootComponent.element.removeEventListener( + "pointermove", this, true + ); } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { - this._rootComponent.element.removeEventListener("MSPointerMove", this, true); + this._rootComponent.element.removeEventListener( + "MSPointerMove", this, true + ); } else { - this._rootComponent.element.removeEventListener("touchmove", this, true); + this._rootComponent.element.removeEventListener( + "touchmove", this, true + ); } } }, @@ -417,38 +591,44 @@ var DragManager = exports.DragManager = Montage.specialize({ handleTranslateStart: { value: function (event) { var startPosition = this._translateComposer.pointerStartEventPosition, - sourceComponent = this._findDraggingSourceAtPosition( + dragSource = this._findDragSourceAtPosition( startPosition.pageX, startPosition.pageY ), draggedImage; - if (sourceComponent) { - this._draggingOperationInfo = this._createDraggingOperationInfoWithSourceAndPosition( - sourceComponent, - startPosition - ); + if (dragSource) { + var draggingOperationInfo; + + this._draggingOperationInfo = (draggingOperationInfo = ( + this._createDraggingOperationInfoWithSourceAndPosition( + dragSource, + startPosition + ) + )); - this._draggingOperationInfo.draggingOperationType = ( - sourceComponent.draggingOperationType || DragManager.DragOperationCopy + draggingOperationInfo.dragOperationType = ( + dragSource.dragOperationType || + DragManager.DragOperationCopy ); - sourceComponent._beginDraggingOperation(this._draggingOperationInfo); + dragSource._beginDraggingOperation(draggingOperationInfo); - if (!this._draggingOperationInfo.draggedImage) { - draggedImage = sourceComponent.element.cloneNode(true); + if (!draggingOperationInfo.draggedImage) { + draggedImage = dragSource.element.cloneNode(true); } else { - draggedImage = this._draggingOperationInfo.draggedImage; + draggedImage = draggingOperationInfo.draggedImage; } - this._draggingOperationInfo.draggedImage = this._sanitizeDraggedImage( + draggingOperationInfo.draggedImage = this._sanitizeDraggedImage( draggedImage ); - this._dispatchDraggingOperationStart(this._draggingOperationInfo); + this._dispatchDraggingOperationStart(draggingOperationInfo); + this._addTranslateListeners(); + this._isDragging = true; this._rootComponent.needsDraw = true; - this._addTranslateListeners(); } else { this._translateComposer._cancel(); } @@ -466,28 +646,28 @@ var DragManager = exports.DragManager = Montage.specialize({ this._draggingOperationInfo.startPositionY + event.translateY ); - var droppingDestination = this._findDropDestinationAtPosition( + var dragDestination = this._findDragDestinationAtPosition( this._draggingOperationInfo.positionX, this._draggingOperationInfo.positionY ); - this._draggingOperationInfo.source._updateDraggingOperation( + this._draggingOperationInfo.dragSource._updateDraggingOperation( this._draggingOperationInfo ); - if (droppingDestination !== this._droppingDestination) { - if (this._droppingDestination) { - this._notifyDroppingDestinationDraggingImageHasExited(); + if (dragDestination !== this._dragDestination) { + if (this._dragDestination) { + this._notifyDragDestinationDraggedImageHasExited(); } - if (droppingDestination) { - this._notifyDroppingDestinationDraggingImageHasEntered(); + if (dragDestination) { + this._notifyDragDestinationDraggedImageHasEntered(); } - } else if (droppingDestination) { - this._notifyDroppingDestinationDraggingImageHasUpdated(); + } else if (dragDestination) { + this._notifyDragDestinationDraggedImageHasUpdated(); } - this._droppingDestination = droppingDestination; + this._dragDestination = dragDestination; this._rootComponent.needsDraw = true; } @@ -500,22 +680,35 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, - handleTranslateCancel: { value: function () { - this._droppingDestination = null; + this._dragDestination = null; this._willTerminateDraggingOperation = true; this._rootComponent.needsDraw = true; } }, + /** + * Draw Cycles Management + */ + willDraw: { value: function () { - if (this._isDragging && this._draggingOperationInfo && !this._draggingImageBoundingRect) { - this._draggingImageBoundingRect = this._draggingOperationInfo.source.element.getBoundingClientRect(); + if (this._isDragging) { + var draggingOperationInfo; - if (this._draggingOperationInfo.draggingSourceContainer) { - this._draggingSourceContainerBoundingRect = this._draggingOperationInfo.draggingSourceContainer.getBoundingClientRect(); + if ((draggingOperationInfo = this._draggingOperationInfo) && + !this._draggedImageBoundingRect + ) { + this._draggedImageBoundingRect = ( + draggingOperationInfo.dragSource.element.getBoundingClientRect() + ); + + if (draggingOperationInfo.dragSourceContainer) { + this._dragSourceContainerBoundingRect = ( + draggingOperationInfo.dragSourceContainer.getBoundingClientRect() + ); + } } } } @@ -530,72 +723,75 @@ var DragManager = exports.DragManager = Montage.specialize({ translateX = draggingOperationInfo.deltaX, translateY = draggingOperationInfo.deltaY; - if (!draggedImage.parentElement) { - draggedImage.style.top = this._draggingImageBoundingRect.top + "px"; - draggedImage.style.left = this._draggingImageBoundingRect.left + "px"; - draggedImage.style.width = this._draggingImageBoundingRect.width + "px"; - draggedImage.style.height = this._draggingImageBoundingRect.height + "px"; - document.body.appendChild(draggedImage); - - if (draggingOperationInfo.draggingOperationType === DragManager.DragOperationMove) { - this._oldSourceDisplayStyle = draggingOperationInfo.source.element.style.display; - draggingOperationInfo.source.element.style.display = 'none'; - - if (draggingOperationInfo.draggingSourcePlaceholderStrategy === DragManager.DraggingSourcePlaceholderStrategyVisible) { - this._placeholderElement = document.createElement('div'); - this._placeholderElement.style.width = this._draggingImageBoundingRect.width + "px"; - this._placeholderElement.style.height = this._draggingImageBoundingRect.height + "px"; - this._placeholderElement.style.boxSizing = "border-box"; - this._placeholderElement.classList.add('montage-placeholder'); - - draggingOperationInfo.source.element.parentNode.insertBefore( - this._placeholderElement, - draggingOperationInfo.source.element - ); - } - } - - draggingOperationInfo.isDragging = true; - this._needsToWaitforGhostElementBoundaries = true; - } + this._setUpDraggedImageIfNeeded(draggedImage); - if (!this._needsToWaitforGhostElementBoundaries) { + if (!this._needsToWaitforDraggedImageBoundaries) { draggedImage.style.visibility = "visible"; } else { - this._needsToWaitforGhostElementBoundaries = false; + this._needsToWaitforDraggedImageBoundaries = false; } - if (this._draggingSourceContainerBoundingRect) { - var rect = this._draggingSourceContainerBoundingRect, + if (this._dragSourceContainerBoundingRect) { + var rect = this._dragSourceContainerBoundingRect, deltaPointerLeft, deltaPointerRight, deltaPointerTop, deltaPointerBottom; if (draggingOperationInfo.positionX - ( - deltaPointerLeft = draggingOperationInfo.startPositionX - this._draggingImageBoundingRect.left + deltaPointerLeft = ( + draggingOperationInfo.startPositionX - + this._draggedImageBoundingRect.left + ) ) < rect.left) { - translateX = rect.left - draggingOperationInfo.startPositionX + deltaPointerLeft; + translateX = ( + rect.left - + draggingOperationInfo.startPositionX + + deltaPointerLeft + ); } else if (draggingOperationInfo.positionX + ( - deltaPointerRight = this._draggingImageBoundingRect.right - draggingOperationInfo.startPositionX + deltaPointerRight = ( + this._draggedImageBoundingRect.right - + draggingOperationInfo.startPositionX + ) ) > rect.right) { - translateX = rect.right - draggingOperationInfo.startPositionX - deltaPointerRight; + translateX = ( + rect.right - + draggingOperationInfo.startPositionX - + deltaPointerRight + ); } if (draggingOperationInfo.positionY - ( - deltaPointerTop = draggingOperationInfo.startPositionY - this._draggingImageBoundingRect.top + deltaPointerTop = ( + draggingOperationInfo.startPositionY - + this._draggedImageBoundingRect.top + ) ) < rect.top) { - translateY = rect.top - draggingOperationInfo.startPositionY + deltaPointerTop; + translateY = ( + rect.top - + draggingOperationInfo.startPositionY + + deltaPointerTop + ); } else if (draggingOperationInfo.positionY + ( - deltaPointerBottom = this._draggingImageBoundingRect.bottom - draggingOperationInfo.startPositionY + deltaPointerBottom = ( + this._draggedImageBoundingRect.bottom - + draggingOperationInfo.startPositionY + ) ) > rect.bottom) { - translateY = rect.bottom - draggingOperationInfo.startPositionY - deltaPointerBottom; + translateY = ( + rect.bottom - + draggingOperationInfo.startPositionY - + deltaPointerBottom + ); } } draggedImage.style[DragManager.cssTransform] = "translate3d(" + translateX + "px," + translateY + "px,0)"; - if (this._droppingDestination && - draggingOperationInfo.draggingOperationType === DragManager.DragOperationCopy + if ( + this._dragDestination && + draggingOperationInfo.dragOperationType === + DragManager.DragOperationCopy ) { this._rootComponent.element.style.cursor = 'copy'; } else { @@ -605,29 +801,35 @@ var DragManager = exports.DragManager = Montage.specialize({ this._rootComponent.element.style.cursor = 'default'; document.body.removeChild(draggingOperationInfo.draggedImage); - if (this._droppingDestination) { + if (this._dragDestination) { draggingOperationInfo.hasBeenDrop = true; + draggingOperationInfo.dragDestination = this._dragDestination; } - this._notifyDroppingDestinationToPerformDropOperation( + this._notifyDragDestinationToPerformDragOperation( draggingOperationInfo ); this._resetTranslateContext(); - this._notifyDroppingDestinationToConcludeDropOperation( + this._notifyDragDestinationToConcludeDragOperation( draggingOperationInfo ); - this._droppingDestination = null; + this._dragDestination = null; - draggingOperationInfo.source._endDraggingOperation(draggingOperationInfo); + draggingOperationInfo.dragSource._endDraggingOperation( + draggingOperationInfo + ); this._dispatchDraggingOperationEnd( draggingOperationInfo ); - if (draggingOperationInfo.draggingOperationType === DragManager.DragOperationMove) { + if ( + draggingOperationInfo.dragOperationType === + DragManager.DragOperationMove + ) { this._shouldRemovePlaceholder = true; this._rootComponent.needsDraw = true; // Wait for the next draw cycle to remove the placeholder, @@ -636,11 +838,73 @@ var DragManager = exports.DragManager = Montage.specialize({ } } - if (this._shouldRemovePlaceholder) { - draggingOperationInfo.source.element.style.display = this._oldSourceDisplayStyle; + this._removeDragSourcePlaceholderIfNeeded(draggingOperationInfo); + } + }, + + _setUpDraggedImageIfNeeded: { + value: function (draggedImage) { + var draggingOperationInfo = this._draggingOperationInfo; + + if (!draggedImage.parentElement) { + var draggedImageBoundingRect = this._draggedImageBoundingRect; + draggedImage.style.top = draggedImageBoundingRect.top + "px"; + draggedImage.style.left = draggedImageBoundingRect.left + "px"; + draggedImage.style.width = draggedImageBoundingRect.width + "px"; + draggedImage.style.height = draggedImageBoundingRect.height + "px"; + + if ( + draggingOperationInfo.dragOperationType === + DragManager.DragOperationMove + ) { + var dragSourceElement = draggingOperationInfo.dragSource.element; + this._oldDragSourceDisplayStyle = dragSourceElement.style.display; + dragSourceElement.style.display = 'none'; + + if ( + draggingOperationInfo.dragSourcePlaceholderStrategy === + DragManager.DragSourcePlaceholderStrategyVisible + ) { + var placeholderElement = document.createElement('div'); + placeholderElement.style.width = ( + draggedImageBoundingRect.width + "px" + ); + placeholderElement.style.height = ( + draggedImageBoundingRect.height + "px" + ); + placeholderElement.style.boxSizing = "border-box"; + placeholderElement.classList.add( + 'montage-drag-source-placeholder' + ); + + dragSourceElement.parentNode.insertBefore( + placeholderElement, + dragSourceElement + ); + + this._placeholderElement = placeholderElement; + } + } + + document.body.appendChild(draggedImage); + draggingOperationInfo.isDraggOperationStarted = true; + this._needsToWaitforDraggedImageBoundaries = true; + } + } + }, + + _removeDragSourcePlaceholderIfNeeded: { + value: function (draggingOperationInfo) { + if (this._shouldRemovePlaceholder && draggingOperationInfo) { + var dragSourceElement = draggingOperationInfo.dragSource.element; + + dragSourceElement.style.display = this._oldDragSourceDisplayStyle; - if (draggingOperationInfo.draggingSourcePlaceholderStrategy === DragManager.DraggingSourcePlaceholderStrategyVisible) { - draggingOperationInfo.source.element.parentNode.removeChild( + if ( + draggingOperationInfo.dragSourcePlaceholderStrategy === + DragManager.DragSourcePlaceholderStrategyVisible + ) { + dragSourceElement.parentNode.removeChild( this._placeholderElement ); } @@ -668,11 +932,11 @@ var DragManager = exports.DragManager = Montage.specialize({ value: 3 }, - DraggingSourcePlaceholderStrategyHidden: { + DragSourcePlaceholderStrategyHidden: { value: 0 }, - DraggingSourcePlaceholderStrategyVisible: { + DragSourcePlaceholderStrategyVisible: { value: 1 } diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css index 7fed8ed448..f1d2f00caf 100644 --- a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css @@ -4,22 +4,22 @@ left: 5px; content: "inner"; } -.Drop.DropInner.accept-dragging-image { +.Drop.DropInner.accept-dragged-image { border: 4px solid #34495e; animation: none; } -.Drop.DropInner.accept-dragging-image.is-empty .drop-placeholder { +.Drop.DropInner.accept-dragged-image.is-empty .drop-placeholder { color:#34495e; animation: none; } -.Drop.DropInner.dragging-image-over.is-empty .drop-placeholder { +.Drop.DropInner.dragged-image-over.is-empty .drop-placeholder { color:#3498db; animation: none; } -.Drop.DropInner.dragging-image-over { +.Drop.DropInner.dragged-image-over { border: 4px solid #3498db; animation: none; } \ No newline at end of file diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js index 6f05e8ec19..1fda15466f 100644 --- a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js @@ -28,7 +28,7 @@ exports.DropInner = Component.specialize(/** @lends DropInner# */ { } }, - performDropOperation: { + performDragOperation: { value: function (draggingOperationInfo) { console.log('dropzone inner received dragging operation'); } diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css index a33754b820..aa74fc37ba 100644 --- a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css @@ -11,22 +11,22 @@ content: "outer"; } -.Drop.DropOuter.accept-dragging-image { +.Drop.DropOuter.accept-dragged-image { border: 4px solid #34495e; animation: none; } -.Drop.DropOuter.accept-dragging-image.is-empty .drop-placeholder { +.Drop.DropOuter.accept-dragged-image.is-empty .drop-placeholder { color:#34495e; animation: none; } -.Drop.DropOuter.dragging-image-over.is-empty .drop-placeholder { +.Drop.DropOuter.dragged-image-over.is-empty .drop-placeholder { color:#3498db; animation: none; } -.Drop.DropOuter.dragging-image-over { +.Drop.DropOuter.dragged-image-over { border: 4px solid #3498db; animation: none; } \ No newline at end of file diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js index 2149a13918..5e36f5c65c 100644 --- a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js @@ -28,7 +28,7 @@ exports.DropOuter = Component.specialize(/** @lends DropOuter# */ { } }, - performDropOperation: { + performDragOperation: { value: function (draggingOperationInfo) { console.log('dropzone outer received dragging operation'); } diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.css b/core/drag/drag.info/sample/ui/drop.reel/drop.css index 38af29e08b..de2261ea8a 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.css +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.css @@ -29,22 +29,22 @@ display: block; } -.Drop.accept-dragging-image { +.Drop.accept-dragged-image { border: 4px dashed #3498db25; animation: blink 1.5s linear infinite alternate; } -.Drop.accept-dragging-image.is-empty .drop-placeholder { +.Drop.accept-dragged-image.is-empty .drop-placeholder { color:#3498db25; animation: blink 1.5s linear infinite alternate; } -.Drop.dragging-image-over.is-empty .drop-placeholder { +.Drop.dragged-image-over.is-empty .drop-placeholder { color:#3498db; animation: none; } -.Drop.dragging-image-over { +.Drop.dragged-image-over { border: 4px solid #3498db; animation: none; } diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.js b/core/drag/drag.info/sample/ui/drop.reel/drop.js index 4bd6dac51c..4140a397ac 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.js +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.js @@ -33,25 +33,25 @@ exports.Drop = Component.specialize(/** @lends Drop# */ { draggingStarted: { value: function (draggingOperationInfo) { - var value = draggingOperationInfo.source.value; + var value = draggingOperationInfo.dragSource.value; return value && this.data.indexOf(value) === -1 && this.dataSource.indexOf(value) > -1; } }, - performDropOperation: { + performDragOperation: { value: function (draggingOperationInfo) { console.log( - draggingOperationInfo.source.identifier + + draggingOperationInfo.dragSource.identifier + ': ' + draggingOperationInfo.data.get('secret') ); - var value = draggingOperationInfo.source.value; + var value = draggingOperationInfo.dragSource.value; if (value && this.data.indexOf(value) === -1) { this.data.push(value); - if (draggingOperationInfo.draggingOperationType === DragManager.DragOperationMove) { + if (draggingOperationInfo.dragOperationType === DragManager.DragOperationMove) { var index; if (this.dataSource && (index = this.dataSource.indexOf(value)) > -1) { diff --git a/core/drag/drag.info/sample/ui/main.reel/main.css b/core/drag/drag.info/sample/ui/main.reel/main.css index 3060cd2f62..6b66427bab 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.css +++ b/core/drag/drag.info/sample/ui/main.reel/main.css @@ -65,6 +65,6 @@ h4 { margin-left: 8px; } -.samples .montage-placeholder { +.samples .montage-drag-source-placeholder { border: 2px dashed #9b59b6; } diff --git a/core/drag/drag.info/sample/ui/square.reel/square.css b/core/drag/drag.info/sample/ui/square.reel/square.css index ff8677bdc2..b6a438345d 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.css +++ b/core/drag/drag.info/sample/ui/square.reel/square.css @@ -28,6 +28,6 @@ display: none; } -.Square.montage-dragging-image { +.Square.montage-dragged-image { background-color: #9b59b6; } diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js index bb15559b21..1f66905aed 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.js +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -37,16 +37,16 @@ exports.Square = Component.specialize(/** @lends Square# */ { beginDraggingOperation: { value: function (draggingOperationInfo) { if (this.enableMoveOperation) { - draggingOperationInfo.draggingOperationType = DragManager.DragOperationMove; + draggingOperationInfo.dragOperationType = DragManager.DragOperationMove; } if (this.container) { - draggingOperationInfo.draggingSourceContainer = this.container; + draggingOperationInfo.dragSourceContainer = this.container; } if (this.enableVisiblePlaceholder) { - draggingOperationInfo.draggingSourcePlaceholderStrategy = ( - DragManager.DraggingSourcePlaceholderStrategyVisible + draggingOperationInfo.dragSourcePlaceholderStrategy = ( + DragManager.DragSourcePlaceholderStrategyVisible ); } @@ -55,8 +55,9 @@ exports.Square = Component.specialize(/** @lends Square# */ { } if (this.switchDraggedImage) { - var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - var circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), + circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); + circle.setAttributeNS(null, 'cx', 25); circle.setAttributeNS(null, 'cy', 25); circle.setAttributeNS(null, 'r', 25); diff --git a/core/drag/dragging-operation-info.js b/core/drag/dragging-operation-info.js index 9b818a6ce5..afd524e1f5 100644 --- a/core/drag/dragging-operation-info.js +++ b/core/drag/dragging-operation-info.js @@ -3,13 +3,13 @@ var Montage = require("../core").Montage; // name -> DraggingOperationContext? exports.DraggingOperationInfo = Montage.specialize({ - source: { + dragSource: { value: null }, draggedImage: { set: function (image) { - if (!this.isDragging) { + if (!this.isDraggOperationStarted) { this._draggedImage = image; } }, @@ -18,7 +18,7 @@ exports.DraggingOperationInfo = Montage.specialize({ } }, - isDragging: { + isDraggOperationStarted: { value: false }, @@ -46,28 +46,28 @@ exports.DraggingOperationInfo = Montage.specialize({ value: 0 }, - draggingSourcePlaceholderStrategy: { - value: 0 // default DraggingSourcePlaceholderStrategyHidden + dragSourcePlaceholderStrategy: { + value: 0 // default DragSourcePlaceholderStrategyHidden }, - draggingOperationType: { + dragOperationType: { value: 0 // default DragOperationCopy }, - _draggingSourceContainer: { + _dragSourceContainer: { value: null }, - draggingSourceContainer: { + dragSourceContainer: { set: function (element) { if (element instanceof Element) { - this._draggingSourceContainer = element; + this._dragSourceContainer = element; } else if (element.element instanceof Element) { - this._draggingSourceContainer = element.element; + this._dragSourceContainer = element.element; } }, get: function () { - return this._draggingSourceContainer; + return this._dragSourceContainer; } }, @@ -83,6 +83,10 @@ exports.DraggingOperationInfo = Montage.specialize({ hasBeenDrop: { value: false + }, + + dragDestination: { + value: null } }); diff --git a/ui/component.js b/ui/component.js index 38adee9221..39c90c8bb5 100644 --- a/ui/component.js +++ b/ui/component.js @@ -2918,8 +2918,9 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto * Register a component for beeing a dragging source. */ registerForDragSource: { - value: function (draggingOperationType) { + value: function () { this.dragManager.registerForDragSource(this); + this.classList.add("montage-drag-source"); } }, @@ -2929,11 +2930,12 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto unregisterForDragSource: { value: function () { this.dragManager.unregisterForDragSource(this); + this.classList.remove("montage-drag-source"); } }, /** - * Register a component for beeing a drop destination. + * Register a component for beeing a drag destination. */ registerForDragDestination: { value: function () { @@ -2943,7 +2945,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto }, /** - * Unregister a component for beeing a drop destination. + * Unregister a component for beeing a drag destination. */ unregisterForDragDestination: { value: function () { @@ -3010,7 +3012,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto } if (acceptDragOperation) { - this.classList.add('accept-dragging-image'); + this.classList.add('accept-dragged-image'); } this.acceptDragOperation = acceptDragOperation; @@ -3023,7 +3025,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto */ _draggingEnded: { value: function (draggingOperationInfo) { - this.classList.remove('accept-dragging-image'); + this.classList.remove('accept-dragged-image'); if (typeof this.draggingEnded === "function") { this.draggingEnded(draggingOperationInfo); @@ -3037,7 +3039,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto */ _draggingEntered: { value: function (draggingOperationInfo) { - this.classList.add("dragging-image-entered"); + this.classList.add("dragged-image-entered"); if (typeof this.draggingEntered === "function") { this.draggingEntered(draggingOperationInfo); @@ -3051,7 +3053,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto */ _draggingUpdated: { value: function (draggingOperationInfo) { - this.classList.add("dragging-image-over"); + this.classList.add("dragged-image-over"); if (typeof this.draggingUpdated === "function") { this.draggingUpdated(draggingOperationInfo); @@ -3065,8 +3067,8 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto */ _draggingExited: { value: function (draggingOperationInfo) { - this.classList.remove("dragging-image-entered"); - this.classList.remove("dragging-image-over"); + this.classList.remove("dragged-image-entered"); + this.classList.remove("dragged-image-over"); if (typeof this.draggingExited === "function") { this.draggingExited(draggingOperationInfo); @@ -3078,28 +3080,28 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto * Called after the released image has been removed from the screen, * allowing the receiver to import the data. */ - _performDropOperation: { + _performDragOperation: { value: function (draggingOperationInfo) { if (this.acceptDragOperation) { - if (typeof this.performDropOperation === "function") { - this.performDropOperation(draggingOperationInfo); + if (typeof this.performDragOperation === "function") { + this.performDragOperation(draggingOperationInfo); } } } }, /** - * Called when the dropping operation is complete, + * Called when the dragging operation is complete, * allowing the receiver to perform any necessary clean-up. */ - _concludeDropOperation: { + _concludeDragOperation: { value: function (draggingOperationInfo) { if (this.acceptDragOperation) { - this.classList.remove("dragging-image-entered"); - this.classList.remove("dragging-image-over"); + this.classList.remove("dragged-image-entered"); + this.classList.remove("dragged-image-over"); - if (typeof this.concludeDropOperation === "function") { - this.concludeDropOperation(draggingOperationInfo); + if (typeof this.concludeDragOperation === "function") { + this.concludeDragOperation(draggingOperationInfo); } } } From c3ddc82128ac22f7d9b7dbb314a2de9e125c0883 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Fri, 1 Jun 2018 15:17:40 +0200 Subject: [PATCH 16/65] Performance optimisation for the drag manager --- core/drag/drag-manager.js | 56 ++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 2709cd105e..532356c58f 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -5,6 +5,9 @@ var Montage = require("../core").Montage, var DRAG_SOURCE = 0; var DRAG_DESTINATION = 1; var TOUCH_POINTER = "touch"; +var POINTER_MOVE = "move"; +var POINTER_COPY = "copy"; +var POINTER_DEFAULT = "default"; var DragManager = exports.DragManager = Montage.specialize({ @@ -645,30 +648,6 @@ var DragManager = exports.DragManager = Montage.specialize({ this._draggingOperationInfo.positionY = ( this._draggingOperationInfo.startPositionY + event.translateY ); - - var dragDestination = this._findDragDestinationAtPosition( - this._draggingOperationInfo.positionX, - this._draggingOperationInfo.positionY - ); - - this._draggingOperationInfo.dragSource._updateDraggingOperation( - this._draggingOperationInfo - ); - - if (dragDestination !== this._dragDestination) { - if (this._dragDestination) { - this._notifyDragDestinationDraggedImageHasExited(); - } - - if (dragDestination) { - this._notifyDragDestinationDraggedImageHasEntered(); - } - } else if (dragDestination) { - this._notifyDragDestinationDraggedImageHasUpdated(); - } - - this._dragDestination = dragDestination; - this._rootComponent.needsDraw = true; } }, @@ -709,6 +688,29 @@ var DragManager = exports.DragManager = Montage.specialize({ draggingOperationInfo.dragSourceContainer.getBoundingClientRect() ); } + } else { + var dragDestination = this._findDragDestinationAtPosition( + this._draggingOperationInfo.positionX, + this._draggingOperationInfo.positionY + ); + + this._draggingOperationInfo.dragSource._updateDraggingOperation( + this._draggingOperationInfo + ); + + if (dragDestination !== this._dragDestination) { + if (this._dragDestination) { + this._notifyDragDestinationDraggedImageHasExited(); + } + + if (dragDestination) { + this._notifyDragDestinationDraggedImageHasEntered(); + } + } else if (dragDestination) { + this._notifyDragDestinationDraggedImageHasUpdated(); + } + + this._dragDestination = dragDestination; } } } @@ -793,12 +795,12 @@ var DragManager = exports.DragManager = Montage.specialize({ draggingOperationInfo.dragOperationType === DragManager.DragOperationCopy ) { - this._rootComponent.element.style.cursor = 'copy'; + this._rootComponent.element.style.cursor = POINTER_COPY; } else { - this._rootComponent.element.style.cursor = 'move'; + this._rootComponent.element.style.cursor = POINTER_MOVE; } } else if (this._willTerminateDraggingOperation) { - this._rootComponent.element.style.cursor = 'default'; + this._rootComponent.element.style.cursor = POINTER_DEFAULT; document.body.removeChild(draggingOperationInfo.draggedImage); if (this._dragDestination) { From 2721d68958c6511f80b6b2e3f45fee2caf62418b Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Fri, 1 Jun 2018 15:33:54 +0200 Subject: [PATCH 17/65] Improvements. --- core/drag/drag-manager.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 532356c58f..ba30e1a1d2 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -8,6 +8,7 @@ var TOUCH_POINTER = "touch"; var POINTER_MOVE = "move"; var POINTER_COPY = "copy"; var POINTER_DEFAULT = "default"; +var PX = "px"; var DragManager = exports.DragManager = Montage.specialize({ @@ -850,10 +851,10 @@ var DragManager = exports.DragManager = Montage.specialize({ if (!draggedImage.parentElement) { var draggedImageBoundingRect = this._draggedImageBoundingRect; - draggedImage.style.top = draggedImageBoundingRect.top + "px"; - draggedImage.style.left = draggedImageBoundingRect.left + "px"; - draggedImage.style.width = draggedImageBoundingRect.width + "px"; - draggedImage.style.height = draggedImageBoundingRect.height + "px"; + draggedImage.style.top = draggedImageBoundingRect.top + PX; + draggedImage.style.left = draggedImageBoundingRect.left + PX; + draggedImage.style.width = draggedImageBoundingRect.width + PX; + draggedImage.style.height = draggedImageBoundingRect.height + PX; if ( draggingOperationInfo.dragOperationType === @@ -869,10 +870,10 @@ var DragManager = exports.DragManager = Montage.specialize({ ) { var placeholderElement = document.createElement('div'); placeholderElement.style.width = ( - draggedImageBoundingRect.width + "px" + draggedImageBoundingRect.width + PX ); placeholderElement.style.height = ( - draggedImageBoundingRect.height + "px" + draggedImageBoundingRect.height + PX ); placeholderElement.style.boxSizing = "border-box"; placeholderElement.classList.add( From e04119aa3cc02c73c36ee806ec6203a16367051f Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Fri, 1 Jun 2018 17:59:14 +0200 Subject: [PATCH 18/65] Drag manager support drop from outside. --- core/drag/drag-manager.js | 269 +++++++++++++----- .../sample/ui/drop-file.reel/drop-file.css | 3 + .../sample/ui/drop-file.reel/drop-file.html | 30 ++ .../sample/ui/drop-file.reel/drop-file.js | 42 +++ .../sample/ui/drop-inner.reel/drop-inner.html | 1 - .../sample/ui/drop-outer.reel/drop-outer.html | 1 - .../drag.info/sample/ui/drop.reel/drop.css | 2 +- .../drag.info/sample/ui/drop.reel/drop.js | 42 +-- .../drag.info/sample/ui/main.reel/main.html | 12 + core/drag/dragging-operation-info.js | 4 + 10 files changed, 312 insertions(+), 94 deletions(-) create mode 100644 core/drag/drag.info/sample/ui/drop-file.reel/drop-file.css create mode 100644 core/drag/drag.info/sample/ui/drop-file.reel/drop-file.html create mode 100644 core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index ba30e1a1d2..09d55cb584 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -110,6 +110,10 @@ var DragManager = exports.DragManager = Montage.specialize({ value: null }, + _dragEnterCounter: { + value: 0 + }, + initWithComponent: { value: function (component) { this._rootComponent = component; @@ -134,6 +138,7 @@ var DragManager = exports.DragManager = Montage.specialize({ } this._translateComposer.addEventListener("translateStart", this); + element.addEventListener("dragenter", this); return this; } @@ -503,6 +508,24 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + _addDragListeners: { + value: function () { + var element = this._rootComponent.element; + element.addEventListener("dragover", this); + element.addEventListener("drop", this); + element.addEventListener("dragleave", this); + } + }, + + _removeDragListeners: { + value: function () { + var element = this._rootComponent.element; + element.removeEventListener("dragover", this); + element.removeEventListener("drop", this); + element.removeEventListener("dragleave", this); + } + }, + /** * @private * @function @@ -511,6 +534,8 @@ var DragManager = exports.DragManager = Montage.specialize({ _resetTranslateContext: { value: function () { this._removeTranslateListeners(); + this._removeDragListeners(); + this._dragEnterCounter = 0; this._isDragging = false; this.__translateComposer.translateX = 0; this.__translateComposer.translateY = 0; @@ -522,6 +547,22 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + _populateDragOperationWithDataTransfer: { + value: function (dataTransfer) { + this._draggingOperationInfo.data.set( + "files", dataTransfer.files + ); + + this._draggingOperationInfo.data.set( + "items", dataTransfer.items + ); + + this._draggingOperationInfo.data.set( + "types", dataTransfer.types + ); + } + }, + /** * Events Handlers */ @@ -592,6 +633,73 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, + handleDragenter: { + value: function (event) { + if (!this._dragEnterCounter) { + var types = event.dataTransfer.types; + + var draggingOperationInfo; + + this._draggingOperationInfo = (draggingOperationInfo = ( + this._createDraggingOperationInfoWithSourceAndPosition( + null, + event + ) + )); + + this._populateDragOperationWithDataTransfer(event.dataTransfer); + this._dispatchDraggingOperationStart(draggingOperationInfo); + this._addDragListeners(); + this._isDragging = true; + this._rootComponent.needsDraw = true; + } + + this._dragEnterCounter++; + } + }, + + handleDragover: { + value: function (event) { + if (this._dragDestination) { + event.preventDefault(); + } + + if ( + this._draggingOperationInfo.positionX !== event.pageX || + this._draggingOperationInfo.positionY !== event.pageY + ) { + this._draggingOperationInfo.deltaX = ( + event.pageX - this._draggingOperationInfo.startPositionX + ); + this._draggingOperationInfo.deltaY = ( + event.pageY - this._draggingOperationInfo.startPositionY + ); + this._draggingOperationInfo.positionX = event.pageX; + this._draggingOperationInfo.positionY = event.pageY; + + this._rootComponent.needsDraw = true; + } + } + }, + + handleDrop: { + value: function (event) { + event.preventDefault(); + this._populateDragOperationWithDataTransfer(event.dataTransfer); + this.handleTranslateEnd(); + } + }, + + handleDragleave: { + value: function (event) { + this._dragEnterCounter--; + + if (!this._dragEnterCounter) { + this.handleTranslateCancel(); + } + } + }, + handleTranslateStart: { value: function (event) { var startPosition = this._translateComposer.pointerStartEventPosition, @@ -678,7 +786,8 @@ var DragManager = exports.DragManager = Montage.specialize({ var draggingOperationInfo; if ((draggingOperationInfo = this._draggingOperationInfo) && - !this._draggedImageBoundingRect + !this._draggedImageBoundingRect && + draggingOperationInfo.dragSource ) { this._draggedImageBoundingRect = ( draggingOperationInfo.dragSource.element.getBoundingClientRect() @@ -693,12 +802,14 @@ var DragManager = exports.DragManager = Montage.specialize({ var dragDestination = this._findDragDestinationAtPosition( this._draggingOperationInfo.positionX, this._draggingOperationInfo.positionY - ); - - this._draggingOperationInfo.dragSource._updateDraggingOperation( - this._draggingOperationInfo ); - + + if (this._draggingOperationInfo.dragSource) { + this._draggingOperationInfo.dragSource._updateDraggingOperation( + this._draggingOperationInfo + ); + } + if (dragDestination !== this._dragDestination) { if (this._dragDestination) { this._notifyDragDestinationDraggedImageHasExited(); @@ -722,74 +833,77 @@ var DragManager = exports.DragManager = Montage.specialize({ var draggingOperationInfo = this._draggingOperationInfo; if (this._isDragging && !this._willTerminateDraggingOperation) { - var draggedImage = draggingOperationInfo.draggedImage, - translateX = draggingOperationInfo.deltaX, - translateY = draggingOperationInfo.deltaY; + var draggedImage = draggingOperationInfo.draggedImage; - this._setUpDraggedImageIfNeeded(draggedImage); + if (draggedImage) { + var translateX = draggingOperationInfo.deltaX, + translateY = draggingOperationInfo.deltaY; - if (!this._needsToWaitforDraggedImageBoundaries) { - draggedImage.style.visibility = "visible"; - } else { - this._needsToWaitforDraggedImageBoundaries = false; - } + this._setUpDraggedImageIfNeeded(draggedImage); - if (this._dragSourceContainerBoundingRect) { - var rect = this._dragSourceContainerBoundingRect, - deltaPointerLeft, deltaPointerRight, - deltaPointerTop, deltaPointerBottom; - - if (draggingOperationInfo.positionX - ( - deltaPointerLeft = ( - draggingOperationInfo.startPositionX - - this._draggedImageBoundingRect.left - ) - ) < rect.left) { - translateX = ( - rect.left - - draggingOperationInfo.startPositionX + - deltaPointerLeft - ); - } else if (draggingOperationInfo.positionX + ( - deltaPointerRight = ( - this._draggedImageBoundingRect.right - - draggingOperationInfo.startPositionX - ) - ) > rect.right) { - translateX = ( - rect.right - - draggingOperationInfo.startPositionX - - deltaPointerRight - ); + if (!this._needsToWaitforDraggedImageBoundaries) { + draggedImage.style.visibility = "visible"; + } else { + this._needsToWaitforDraggedImageBoundaries = false; } - - if (draggingOperationInfo.positionY - ( - deltaPointerTop = ( - draggingOperationInfo.startPositionY - - this._draggedImageBoundingRect.top - ) - ) < rect.top) { - translateY = ( - rect.top - - draggingOperationInfo.startPositionY + - deltaPointerTop - ); - } else if (draggingOperationInfo.positionY + ( - deltaPointerBottom = ( - this._draggedImageBoundingRect.bottom - - draggingOperationInfo.startPositionY - ) - ) > rect.bottom) { - translateY = ( - rect.bottom - - draggingOperationInfo.startPositionY - - deltaPointerBottom - ); + + if (this._dragSourceContainerBoundingRect) { + var rect = this._dragSourceContainerBoundingRect, + deltaPointerLeft, deltaPointerRight, + deltaPointerTop, deltaPointerBottom; + + if (draggingOperationInfo.positionX - ( + deltaPointerLeft = ( + draggingOperationInfo.startPositionX - + this._draggedImageBoundingRect.left + ) + ) < rect.left) { + translateX = ( + rect.left - + draggingOperationInfo.startPositionX + + deltaPointerLeft + ); + } else if (draggingOperationInfo.positionX + ( + deltaPointerRight = ( + this._draggedImageBoundingRect.right - + draggingOperationInfo.startPositionX + ) + ) > rect.right) { + translateX = ( + rect.right - + draggingOperationInfo.startPositionX - + deltaPointerRight + ); + } + + if (draggingOperationInfo.positionY - ( + deltaPointerTop = ( + draggingOperationInfo.startPositionY - + this._draggedImageBoundingRect.top + ) + ) < rect.top) { + translateY = ( + rect.top - + draggingOperationInfo.startPositionY + + deltaPointerTop + ); + } else if (draggingOperationInfo.positionY + ( + deltaPointerBottom = ( + this._draggedImageBoundingRect.bottom - + draggingOperationInfo.startPositionY + ) + ) > rect.bottom) { + translateY = ( + rect.bottom - + draggingOperationInfo.startPositionY - + deltaPointerBottom + ); + } } - } - draggedImage.style[DragManager.cssTransform] = "translate3d(" + - translateX + "px," + translateY + "px,0)"; + draggedImage.style[DragManager.cssTransform] = "translate3d(" + + translateX + "px," + translateY + "px,0)"; + } if ( this._dragDestination && @@ -802,7 +916,10 @@ var DragManager = exports.DragManager = Montage.specialize({ } } else if (this._willTerminateDraggingOperation) { this._rootComponent.element.style.cursor = POINTER_DEFAULT; - document.body.removeChild(draggingOperationInfo.draggedImage); + + if (draggingOperationInfo.draggedImage) { + document.body.removeChild(draggingOperationInfo.draggedImage); + } if (this._dragDestination) { draggingOperationInfo.hasBeenDrop = true; @@ -821,15 +938,18 @@ var DragManager = exports.DragManager = Montage.specialize({ this._dragDestination = null; - draggingOperationInfo.dragSource._endDraggingOperation( - draggingOperationInfo - ); + if (draggingOperationInfo.dragSource) { + draggingOperationInfo.dragSource._endDraggingOperation( + draggingOperationInfo + ); + } this._dispatchDraggingOperationEnd( draggingOperationInfo ); if ( + draggingOperationInfo.dragSource && draggingOperationInfo.dragOperationType === DragManager.DragOperationMove ) { @@ -898,7 +1018,10 @@ var DragManager = exports.DragManager = Montage.specialize({ _removeDragSourcePlaceholderIfNeeded: { value: function (draggingOperationInfo) { - if (this._shouldRemovePlaceholder && draggingOperationInfo) { + if ( + this._shouldRemovePlaceholder && draggingOperationInfo && + draggingOperationInfo.dragSource + ) { var dragSourceElement = draggingOperationInfo.dragSource.element; dragSourceElement.style.display = this._oldDragSourceDisplayStyle; diff --git a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.css b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.css new file mode 100644 index 0000000000..fc7703c5fd --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.css @@ -0,0 +1,3 @@ +.DropFile { + +} \ No newline at end of file diff --git a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.html b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.html new file mode 100644 index 0000000000..cde3da97a4 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.html @@ -0,0 +1,30 @@ + + + + + + + +
+
+
+
+ + diff --git a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js new file mode 100644 index 0000000000..5c33a8e025 --- /dev/null +++ b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js @@ -0,0 +1,42 @@ +/** + * @module ui/drop-file.reel + */ +var Component = require("montage/ui/component").Component; + +/** + * @class DropFile + * @extends Component + */ +exports.DropFile = Component.specialize(/** @lends DropFile# */ { + + fileName: { + value: null + }, + + enterDocument: { + value: function () { + this.fileName = + this.registerForDragDestination(); + } + }, + + exitDocument: { + value: function () { + this.unregisterForDragDestination(); + } + }, + + draggingStarted: { + value: function (draggingOperationInfo) { + return !!(draggingOperationInfo.data.has('types') && + draggingOperationInfo.data.get('types').indexOf('Files') > -1); + } + }, + + performDragOperation: { + value: function (draggingOperationInfo) { + console.log(draggingOperationInfo.data.get("files")); + this.fileName = draggingOperationInfo.data.get("files")[0].name; + } + } +}); diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.html b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.html index f8e4c85c08..d47c8c6f1b 100644 --- a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.html +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.html @@ -1,7 +1,6 @@ - + + + +
drag
+
+ + diff --git a/test/spec/core/drag/drag-test.js b/test/spec/core/drag/drag-test.js new file mode 100644 index 0000000000..7830a13883 --- /dev/null +++ b/test/spec/core/drag/drag-test.js @@ -0,0 +1,7 @@ +"use strict"; + +var TestController = require("montage-testing/test-controller").TestController; + +exports.DragTest = TestController.specialize({ + +}); diff --git a/ui/component.js b/ui/component.js index 9997e67a29..3269351913 100644 --- a/ui/component.js +++ b/ui/component.js @@ -1209,7 +1209,15 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto __exitDocument: { value: function () { - if (this._inDocument && typeof this.exitDocument === "function") { + if (this.isDragSource) { + this.unregisterForDragSource(); + } + + if (this.isDragDestination) { + this.unregisterForDragDestination(); + } + + if (this._inDocument && typeof this.exitDocument === "function") { this.exitDocument(); this._inDocument = false; } @@ -1274,6 +1282,56 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto } }, + _isDragSource: { + value: false + }, + + isDragSource: { + set: function (isDragSource) { + isDragSource = !!isDragSource; + + if (this._isDragSource !== isDragSource) { + if (this._inDocument) { + if (this._isDragSource) { + this.unregisterForDragSource(); + } else { + this.registerForDragSource(); + } + } + + this._isDragSource = isDragSource; + } + }, + get: function () { + return this._isDragSource; + } + }, + + _isDragDestination: { + value: false + }, + + isDragDestination: { + set: function (isDragDestination) { + isDragDestination = !!isDragDestination; + + if (this._isDragDestination !== isDragDestination) { + if (this._inDocument) { + if (this._isDragDestination) { + this.unregisterForDragDestination(); + } else { + this.registerForDragDestination(); + } + } + + this._isDragDestination = isDragDestination; + } + }, + get: function () { + return this._isDragDestination; + } + }, + /** * The owner component is the owner of the template form which this * component was instantiated. @@ -2920,6 +2978,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto registerForDragSource: { value: function () { this.dragManager.registerForDragSource(this); + this.__isDragSource = true; this.classList.add("montage-drag-source"); } }, @@ -2940,6 +2999,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto registerForDragDestination: { value: function () { this.dragManager.registerForDragDestination(this); + this.__isDragDestination = true; this.classList.add("montage-drag-destination"); } }, @@ -3428,6 +3488,14 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto value: function (firstTime) { var originalElement; + if (this.isDragSource) { + this.registerForDragSource(); + } + + if (this.isDragDestination) { + this.registerForDragDestination(); + } + if (firstTime) { // The element is now ready, so we can read the attributes that // have been set on it. From 3fe19885e809671877bc493fda192bc5f720a0ae Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 18 Jun 2018 16:36:30 -0400 Subject: [PATCH 25/65] First attempt to use drag events within the drag manager --- core/drag/drag-event.js | 318 ++++++++ core/drag/drag-manager.js | 708 +++++++++--------- .../sample/ui/drop-file.reel/drop-file.js | 49 +- .../sample/ui/drop-inner.reel/drop-inner.js | 53 +- .../sample/ui/drop-outer.reel/drop-outer.js | 53 +- .../drag.info/sample/ui/drop.reel/drop.js | 86 ++- .../drag.info/sample/ui/main.reel/main.html | 5 +- .../drag.info/sample/ui/main.reel/main.js | 6 - .../drag.info/sample/ui/square.reel/square.js | 39 +- core/drag/dragging-operation-context.js | 65 ++ core/drag/dragging-operation-info.js | 196 ----- core/drag/dragging-operation-type.js | 74 -- core/event/event-manager.js | 5 +- core/extras/event.js | 62 ++ ui/component.js | 238 ++---- 15 files changed, 1056 insertions(+), 901 deletions(-) create mode 100644 core/drag/drag-event.js create mode 100644 core/drag/dragging-operation-context.js delete mode 100644 core/drag/dragging-operation-info.js delete mode 100644 core/drag/dragging-operation-type.js create mode 100644 core/extras/event.js diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js new file mode 100644 index 0000000000..ec94bc24aa --- /dev/null +++ b/core/drag/drag-event.js @@ -0,0 +1,318 @@ +var MutableEvent = require("../event/mutable-event").MutableEvent, + Montage = require("../core").Montage; + +var DataTransfer = Montage.specialize({ + + __data: { + enumerable: false, + value: null + }, + + _data: { + enumerable: false, + get: function () { + return this.__data || (this.__data = new Map()); + } + }, + + _dragImage: { + value: null, + enumerable: false, + }, + + _dragEffect: { + value: null + }, + + dragEffect: { + set: function (effect) { + if (DataTransfer.ALLOWED_EFFECTS.indexOf(effect) > -1) { + this._dragEffect = effect; + } + }, + get: function () { + return this._dragEffect || DataTransfer.Default; + } + }, + + _dropEffect: { + value: null + }, + + dropEffect: { + set: function (effect) { + if ( + effect && + DataTransfer.ALLOWED_EFFECTS.indexOf(effect) > -1 && + DataTransfer.isDropEffectAllowed( + effect, this.effectAllowed + ) + ) { + this._dropEffect = effect; + } else { + this._dropEffect = null; + } + }, + get: function () { + if (!this._dropEffect) { + var index; + + if ( + this.effectAllowed === DataTransfer.All || + this.effectAllowed.startsWith('c') + ) { + this._dropEffect = DataTransfer.Copy; + } else if ((index = DataTransfer.ALLOWED_EFFECTS.indexOf( + this.effectAllowed)) > -1 + ) { + this._dropEffect = DataTransfer.ALLOWED_EFFECTS[index]; + } else { + this._dropEffect = DataTransfer.Link; + } + } + + return this._dropEffect; + } + }, + + _effectAllowed: { + value: null + }, + + effectAllowed: { + set: function (effect) { + if (DataTransfer.ALLOWED_DROP_EFFECTS.indexOf(effect) > -1) { + this._effectAllowed = effect; + } + }, + get: function () { + return this._effectAllowed || DataTransfer.All; + } + }, + + files: { + value: null + }, + + items: { + value: null + }, + + types: { + value: null + }, + + dragTarget: { + value: null + }, + + _candidateDropTargets: { + value: null, + enumerable: false + }, + + candidateDropTargets: { + get: function () { + return this._candidateDropTargets || + (this._candidateDropTargets = new Set()); + } + }, + + dragabblePlaceholderStrategy: { + value: 'hidden' + }, + + clearData: { + value: function () { + return this._data.clear(); + } + }, + + getData: { + value: function (key) { + return this._data.get(key); + } + }, + + hasData: { + value: function (key) { + return this._data.has(key); + } + }, + + setData: { + value: function (key, value) { + return this._data.set(key, value); + } + }, + + setDragImage: { + value: function (img, xOffset, yOffset) { + if (!this._dragImage) { + this._dragImage = img; + } + } + }, + + getDragImage: { + value: function () { + return this._dragImage; + } + }, + +}, { + Default: { + value: "default" + }, + + Copy: { + value: "copy" + }, + + Move: { + value: "move" + }, + + Link: { + value: "alias" + }, + + CopyLink: { + value: "copyLink" + }, + + CopyMove: { + value: "copyMove" + }, + + LinkMove: { + value: "linkMove" + }, + + All: { + value: "all" + }, + + _ALLOWED_EFFECTS: { + value: null + }, + + ALLOWED_EFFECTS: { + get: function () { + if (!this._ALLOWED_EFFECTS) { + this._ALLOWED_EFFECTS = [ + this.Default, + this.Copy, + this.Link, + this.Move + ]; + } + + return this._ALLOWED_EFFECTS; + } + }, + + _ALLOWED_DROP_EFFECTS: { + value: null + }, + + ALLOWED_DROP_EFFECTS: { + get: function () { + if (!this._ALLOWED_DROP_EFFECTS) { + this._ALLOWED_DROP_EFFECTS = this.ALLOWED_EFFECTS.concat([ + this.All, + this.CopyMove, + this.CopyLink, + this.LinkMove + ]); + } + + return this._ALLOWED_DROP_EFFECTS; + } + }, + + isDropEffectAllowed: { + value: function (effect, effectAllowed) { + return effectAllowed === this.All || + effect === effectAllowed || + (effect === this.Copy && ( + effectAllowed === this.CopyMove || + effectAllowed === this.CopyLink + )) || + (effect === this.Move && ( + effectAllowed === this.CopyMove || + effectAllowed === this.LinkMove + )) || + (effect === this.Link && ( + effectAllowed === this.LinkMove || + effectAllowed === this.CopyLink + )); + } + } +}); + +exports.DragEvent = MutableEvent.specialize({ + + type: { + value: "drag" + }, + + _event: { + enumerable: false, + value: null + }, + + event: { + get: function () { + return this._event; + }, + set: function (value) { + this._event = value; + } + }, + + bubbles: { + value: true + }, + + dataTransfer: { + value: null + }, + + constructor: { + value: function (type, eventInit) { + this.dataTransfer = new DataTransfer(); + this._event = new CustomEvent(type, eventInit); + this.type = type; + } + } + +}, { + DRAGEND: { + value: "dragstart" + }, + + DRAG: { + value: "drag" + }, + + DRAGENTER: { + value: "dragenter" + }, + + DRAGEXIT: { + value: "dragexit" + }, + + DRAGLEAVE: { + value: "dragleave" + }, + + DROP: { + value: "drop" + }, + + DRAGEND: { + value: "dragend" + } +}); diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index e04da78d2b..64b1b9bcca 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -1,37 +1,37 @@ var Montage = require("../core").Montage, + DragEvent = require("./drag-event").DragEvent, TranslateComposer = require("../../composer/translate-composer").TranslateComposer, - DraggingOperationInfo = require("./dragging-operation-info").DraggingOperationInfo, - DraggingOperationType = require("./dragging-operation-type").DraggingOperationType; + DraggingOperationContext = require("./dragging-operation-context").DraggingOperationContext; -var DRAG_SOURCE = 0; -var DRAG_DESTINATION = 1; +var DRAGGABLE = 0; +var DROPABBLE = 1; var TOUCH_POINTER = "touch"; var NOT_ALLOWED_CURSOR = "not-allowed"; var PX = "px"; var DragManager = exports.DragManager = Montage.specialize({ - __dragSources: { + __dragabbles: { value: null }, - _dragSources: { + _dragabbles: { get: function () { - return this.__dragSources || (this.__dragSources = []); + return this.__dragabbles || (this.__dragabbles = []); } }, - __dragDestinations: { + __droppables: { value: null }, - _dragDestinations: { + _droppables: { get: function () { - return this.__dragDestinations || (this.__dragDestinations = []); + return this.__droppables || (this.__droppables = []); } }, - _dragDestination: { + _dropDestination: { value: null }, @@ -81,7 +81,7 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, - _draggingOperationInfo: { + _draggingOperationContext: { value: null }, @@ -97,7 +97,7 @@ var DragManager = exports.DragManager = Montage.specialize({ value: false }, - _dragSourceContainerBoundingRect: { + _draggableContainerBoundingRect: { value: null }, @@ -105,7 +105,7 @@ var DragManager = exports.DragManager = Montage.specialize({ value: null }, - _oldDragSourceDisplayStyle: { + _oldDraggableDisplayStyle: { value: null }, @@ -113,12 +113,17 @@ var DragManager = exports.DragManager = Montage.specialize({ value: 0 }, - _dragEffect: { + // TODO: rename + _cursorStyle: { value: null }, _scrollThreshold: { - value: 25 + value: 25 //px + }, + + _shouldRemovePlaceholder: { + value: false }, initWithComponent: { @@ -145,7 +150,7 @@ var DragManager = exports.DragManager = Montage.specialize({ } this._translateComposer.addEventListener("translateStart", this); - element.addEventListener("dragenter", this); + element.addEventListener("dragenter", this, true); return this; } @@ -155,11 +160,11 @@ var DragManager = exports.DragManager = Montage.specialize({ * @public * @function * @param {Component} component - a component - * @description Register a component to be a Drag Source + * @description Register a component to be draggable */ - registerForDragSource: { + registerDraggable: { value: function (component) { - this._register(component, DRAG_SOURCE); + this._register(component, DRAGGABLE); } }, @@ -167,11 +172,11 @@ var DragManager = exports.DragManager = Montage.specialize({ * @public * @function * @param {Component} component - a component - * @description Register a component to be a Drag Destination + * @description Register a component to be droppable */ - registerForDragDestination: { + registerDroppable: { value: function (component) { - this._register(component, DRAG_DESTINATION); + this._register(component, DROPABBLE); } }, @@ -179,11 +184,11 @@ var DragManager = exports.DragManager = Montage.specialize({ * @public * @function * @param {Component} component - a component - * @description Unregister a component to be a Drag Source + * @description Unregister a component to be draggable */ - unregisterForDragSource: { + unregisterDraggable: { value: function (component) { - this._unregister(component, DRAG_SOURCE); + this._unregister(component, DRAGGABLE); } }, @@ -191,11 +196,11 @@ var DragManager = exports.DragManager = Montage.specialize({ * @public * @function * @param {Component} component - a component - * @description Unregister a component to be a Drag Destination + * @description Unregister a component to be droppable */ - unregisterForDragDestination: { + unregisterDroppable: { value: function (component) { - this._unregister(component, DRAG_DESTINATION); + this._unregister(component, DROPABBLE); } }, @@ -207,14 +212,14 @@ var DragManager = exports.DragManager = Montage.specialize({ * @private * @function * @param {Component} component - * @param {number} role - component's role -> drag source or destination - * @description register an component to be a drag source or destination + * @param {number} role - component's role -> draggable or droppable + * @description register an component to be draggable or droppable */ _register: { value: function (component, role) { if (component) { - var components = role === DRAG_SOURCE ? - this._dragSources : this._dragDestinations; + var components = role === DRAGGABLE ? + this._dragabbles : this._droppables; if (components.indexOf(component) === -1) { components.push(component); @@ -227,15 +232,14 @@ var DragManager = exports.DragManager = Montage.specialize({ * @private * @function * @param {Component} component - * @param {number} role - component's role -> drag source or destination - * @description unregister an component from beeing - * a drag source or destination + * @param {number} role - component's role -> draggable or droppable + * @description unregister an component from beeing draggable or droppable */ _unregister: { value: function (component, role) { if (component) { - var components = role === DRAG_SOURCE ? - this._dragSources : this._dragDestinations, + var components = role === DRAGGABLE ? + this._dragabbles : this._droppables, index; if ((index = components.indexOf(component)) > -1) { @@ -250,18 +254,19 @@ var DragManager = exports.DragManager = Montage.specialize({ * @function * @param {Element} draggedImage - node element that will be used * as a dragged image + * @param {Object} startPosition - coordinates of the start position * @description set some default css style on the dragged image. */ - _createDraggingOperationInfoWithSourceAndPosition: { - value: function (dragSource, startPosition) { - var draggingOperationInfo = new DraggingOperationInfo(); - draggingOperationInfo.dragSource = dragSource; - draggingOperationInfo.startPositionX = startPosition.pageX; - draggingOperationInfo.startPositionY = startPosition.pageY; - draggingOperationInfo.positionX = startPosition.pageX; - draggingOperationInfo.positionY = startPosition.pageY; - - return draggingOperationInfo; + _createDraggingOperationContextWithDraggableAndPosition: { + value: function (draggable, startPosition) { + var draggingOperationContext = new DraggingOperationContext(); + draggingOperationContext.draggable = draggable; + draggingOperationContext.startPositionX = startPosition.pageX; + draggingOperationContext.startPositionY = startPosition.pageY; + draggingOperationContext.positionX = startPosition.pageX; + draggingOperationContext.positionY = startPosition.pageY; + + return draggingOperationContext; } }, @@ -289,56 +294,74 @@ var DragManager = exports.DragManager = Montage.specialize({ /** * @private * @function - * @param {DraggingOperationInfo} draggingOperationInfo - current dragging - * operation info object - * @description Dispatch to drag destinations that - * the dragging operation has started. + * @param {string} type drag event type + * @param {DraggingOperationContext} draggingOperationContext dragging operation context + * @description Create a Custon Drag Event */ - _dispatchDraggingOperationStart: { - value: function (draggingOperationInfo) { - var dragDestinations = this._dragDestinations, - component; - - for (var i = 0, length = dragDestinations.length; i < length; i++) { - component = dragDestinations[i]; - component._draggingStarted(draggingOperationInfo); + _createDragEvent: { + value: function (type, draggingOperationContext) { + var dragEvent = new DragEvent(type); + + if (!draggingOperationContext.dataTransfer) { + draggingOperationContext.dataTransfer = dragEvent.dataTransfer; + } else { + dragEvent.dataTransfer = draggingOperationContext.dataTransfer; } + + return dragEvent; } }, /** * @private * @function - * @param {DraggingOperationInfo} draggingOperationInfo - current dragging - * operation info object - * @description Dispatch to drag destinations that - * the dragging operation has ended. + * @description Dispatch Drag Start Event */ - _dispatchDraggingOperationEnd: { - value: function (draggingOperationInfo) { - var dragDestinations = this._dragDestinations, - component; - - for (var i = 0, length = dragDestinations.length; i < length; i++) { - component = dragDestinations[i]; - component._draggingEnded(draggingOperationInfo); + _dispatchDragStart: { + value: function () { + var draggable = this._draggingOperationContext.draggable, + dragStartEvent = this._createDragEvent( + "dragstart", this._draggingOperationContext + ); + + if (draggable) { + draggable.dispatchEvent(dragStartEvent); + } else { + this._rootComponent.application.dispatchEvent(dragStartEvent); } + + this._draggingOperationContext.candidateDropTargets = ( + dragStartEvent.dataTransfer.candidateDropTargets + ); + + this._draggingOperationContext.candidateDropTargets.forEach( + function (droppable) { + droppable.classList.add('accept-dragged-image'); + } + ); + + return dragStartEvent; } }, /** * @private * @function - * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * @param {DraggingOperationContext} draggingOperationContext - current dragging * operation info object - * @description Notify to the drag destination - * to perform the drag operation. + * @description Dispatch Drag End Event */ - _notifyDragDestinationToPerformDragOperation: { - value: function (draggingOperationInfo) { - if (this._dragDestination) { - this._dragDestination._performDragOperation( - draggingOperationInfo + _dispatchDragEnd: { + value: function (draggingOperationContext) { + draggingOperationContext.candidateDropTargets.forEach(function (droppable) { + droppable.classList.remove('accept-dragged-image'); + }); + + if (draggingOperationContext.draggable) { + draggingOperationContext.draggable.dispatchEvent( + this._createDragEvent( + "dragend", draggingOperationContext + ) ); } } @@ -347,17 +370,19 @@ var DragManager = exports.DragManager = Montage.specialize({ /** * @private * @function - * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * @param {DraggingOperationContext} draggingOperationContext - current dragging * operation info object - * @description Notify to the drag destination - * to conclude the drag operation. + * @description Dispatch Drop Event */ - _notifyDragDestinationToConcludeDragOperation: { - value: function (draggingOperationInfo) { - if (this._dragDestination) { - this._dragDestination._concludeDragOperation( - draggingOperationInfo - ); + _dispatchDrop: { + value: function (draggingOperationContext) { + if (this._dropDestination) { + this._dropDestination.classList.remove("dragged-image-entered"); + this._dropDestination.classList.remove("dragged-image-over"); + + this._dropDestination.dispatchEvent(this._createDragEvent( + "drop", draggingOperationContext + )); } } }, @@ -365,16 +390,19 @@ var DragManager = exports.DragManager = Montage.specialize({ /** * @private * @function - * @param {DraggingOperationInfo} draggingOperationInfo - current dragging - * operation info object - * @description Notify to the drag destination - * that the dragged image has entered its bounds rectangle. + * @description Dispatch Drag Enter Event */ - _notifyDragDestinationDraggedImageHasEntered: { - value: function (draggingOperationInfo) { - if (this._dragDestination) { - this._dragDestination._draggingEntered( - draggingOperationInfo + _dispatchDragEnter: { + value: function (draggingOperationContext) { + if (this._dropDestination) { + this._dropDestination.classList.add("dragged-image-entered"); + var dragEnterEvent = this._createDragEvent( + "dragenter", draggingOperationContext + ); + + this._dropDestination.dispatchEvent(dragEnterEvent); + draggingOperationContext.dropEffect = ( + dragEnterEvent.dataTransfer.dropEffect || "default" ); } } @@ -383,16 +411,19 @@ var DragManager = exports.DragManager = Montage.specialize({ /** * @private * @function - * @param {DraggingOperationInfo} draggingOperationInfo - current dragging - * operation info object - * @description Notify to the drag destination - * that the dragged image is held within its bounds rectangle. + * @description Dispatch Drag Over Event */ - _notifyDragDestinationDraggedImageHasUpdated: { - value: function (draggingOperationInfo) { - if (this._dragDestination) { - this._dragDestination._draggingUpdated( - draggingOperationInfo + _dispatchDragOver: { + value: function (draggingOperationContext) { + if (this._dropDestination) { + this._dropDestination.classList.add("dragged-image-over"); + var dragOverEvent = this._createDragEvent( + "dragover", draggingOperationContext + ); + + this._dropDestination.dispatchEvent(dragOverEvent); + draggingOperationContext.dropEffect = ( + dragOverEvent.dataTransfer.dropEffect || "default" ); } } @@ -401,17 +432,19 @@ var DragManager = exports.DragManager = Montage.specialize({ /** * @private * @function - * @param {DraggingOperationInfo} draggingOperationInfo - current dragging + * @param {DraggingOperationContext} draggingOperationContext - current dragging * operation info object - * @description Notify to the drag destination - * that the dragged image has exited its bounds rectangle. + * @description Dispatch Drag Leave Event */ - _notifyDragDestinationDraggedImageHasExited: { - value: function (draggingOperationInfo) { - if (this._dragDestination) { - this._dragDestination._draggingExited( - draggingOperationInfo - ); + _dispatchDragLeave: { + value: function (draggingOperationContext) { + if (this._dropDestination) { + this._dropDestination.classList.remove("dragged-image-over"); + this._dropDestination.classList.remove("dragged-image-entered"); + + this._dropDestination.dispatchEvent(this._createDragEvent( + "dragleave", draggingOperationContext + )); } } }, @@ -421,15 +454,15 @@ var DragManager = exports.DragManager = Montage.specialize({ * @function * @param {string} positionX - x coordinate * @param {string} positionY - y coordinate - * @description try to find a drag source at the given position. + * @description try to find a draggable component at the given position. * @returns {Component|null} */ - _findDragSourceAtPosition: { + _findDraggableAtPosition: { value: function (positionX, positionY) { return this._findRegisteredComponentAtPosistion( positionX, positionY, - DRAG_SOURCE + DRAGGABLE ); } }, @@ -439,15 +472,15 @@ var DragManager = exports.DragManager = Montage.specialize({ * @function * @param {string} positionX - x coordinate * @param {string} positionY - y coordinate - * @description try to find a drag destination at the given position. + * @description try to find a droppable component at the given position. * @returns {Component|null} */ - _findDragDestinationAtPosition: { + _findDroppableAtPosition: { value: function (positionX, positionY) { return this._findRegisteredComponentAtPosistion( positionX, positionY, - DRAG_DESTINATION + DROPABBLE ); } }, @@ -457,7 +490,7 @@ var DragManager = exports.DragManager = Montage.specialize({ * @function * @param {string} positionX - x coordinate * @param {string} positionY - y coordinate - * @description try to find a drag source or destination + * @description try to find a droppable or draggable component * at the given position. * @returns {Component|null} */ @@ -469,8 +502,8 @@ var DragManager = exports.DragManager = Montage.specialize({ registeredComponent = null; if (targetComponent) { - var components = role === DRAG_SOURCE ? - this._dragSources : this._dragDestinations, + var components = role === DRAGGABLE ? + this._dragabbles : this._droppables, index; while (targetComponent) { @@ -544,9 +577,9 @@ var DragManager = exports.DragManager = Montage.specialize({ _addDragListeners: { value: function () { var element = this._rootComponent.element; - element.addEventListener("dragover", this); - element.addEventListener("drop", this); - element.addEventListener("dragleave", this); + element.addEventListener("dragover", this, true); + element.addEventListener("drop", this, true); + element.addEventListener("dragleave", this, true); } }, @@ -558,9 +591,9 @@ var DragManager = exports.DragManager = Montage.specialize({ _removeDragListeners: { value: function () { var element = this._rootComponent.element; - element.removeEventListener("dragover", this); - element.removeEventListener("drop", this); - element.removeEventListener("dragleave", this); + element.removeEventListener("dragover", this, true); + element.removeEventListener("drop", this, true); + element.removeEventListener("dragleave", this, true); } }, @@ -577,35 +610,14 @@ var DragManager = exports.DragManager = Montage.specialize({ this._isDragging = false; this.__translateComposer.translateX = 0; this.__translateComposer.translateY = 0; - this._oldDragSourceDisplayStyle = null; + this._oldDraggableDisplayStyle = null; this._draggedImageBoundingRect = null; - this._dragSourceContainerBoundingRect = null; + this._draggableContainerBoundingRect = null; this._willTerminateDraggingOperation = false; this._needsToWaitforDraggedImageBoundaries = false; } }, - /** - * @private - * @function - * @description populate the data property with the drag transfer data. - */ - _populateDraggingOperationWithDataTransfer: { - value: function (dataTransfer) { - this._draggingOperationInfo.data.set( - "files", dataTransfer.files - ); - - this._draggingOperationInfo.data.set( - "items", dataTransfer.items - ); - - this._draggingOperationInfo.data.set( - "types", dataTransfer.types - ); - } - }, - /** * Events Handlers */ @@ -623,12 +635,12 @@ var DragManager = exports.DragManager = Montage.specialize({ captureTouchstart: { value: function (event) { - var dragSource = this._findDragSourceAtPosition( + var draggable = this._findDraggableAtPosition( event.pageX, event.pageY ); - if (dragSource) { + if (draggable) { if (window.PointerEvent) { this._rootComponent.element.addEventListener( "pointermove", this, true @@ -676,64 +688,91 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, - handleDragenter: { + captureDragenter: { value: function (event) { - if (!this._dragEnterCounter) { + if (!this._draggingOperationContext) { var types = event.dataTransfer.types; - - var draggingOperationInfo; - this._draggingOperationInfo = (draggingOperationInfo = ( - this._createDraggingOperationInfoWithSourceAndPosition( - null, - event - ) - )); + if (types.indexOf("Files") > -1) { + var draggingOperationContext; - this._populateDraggingOperationWithDataTransfer(event.dataTransfer); - this._dispatchDraggingOperationStart(draggingOperationInfo); - this._addDragListeners(); - this._isDragging = true; - this._rootComponent.needsDraw = true; - } + this._draggingOperationContext = (draggingOperationContext = ( + this._createDraggingOperationContextWithDraggableAndPosition( + null, + event + ) + )); + + draggingOperationContext.dataTransfer = event.dataTransfer; + + var dragStartEvent = this._dispatchDragStart(); + + draggingOperationContext.dragEffect = ( + dragStartEvent.dataTransfer.dragEffect + ); + + this._addDragListeners(); + this._isDragging = true; + this._rootComponent.needsDraw = true; + } + } + this._dragEnterCounter++; } }, - handleDragover: { + captureDragover: { value: function (event) { - if (this._dragDestination) { + if (this._dropDestination) { event.preventDefault(); } if ( - this._draggingOperationInfo.positionX !== event.pageX || - this._draggingOperationInfo.positionY !== event.pageY + this._draggingOperationContext.positionX !== event.pageX || + this._draggingOperationContext.positionY !== event.pageY ) { - this._draggingOperationInfo.deltaX = ( - event.pageX - this._draggingOperationInfo.startPositionX + this._draggingOperationContext.deltaX = ( + event.pageX - this._draggingOperationContext.startPositionX ); - this._draggingOperationInfo.deltaY = ( - event.pageY - this._draggingOperationInfo.startPositionY + this._draggingOperationContext.deltaY = ( + event.pageY - this._draggingOperationContext.startPositionY ); - this._draggingOperationInfo.positionX = event.pageX; - this._draggingOperationInfo.positionY = event.pageY; - + this._draggingOperationContext.positionX = event.pageX; + this._draggingOperationContext.positionY = event.pageY; + this._draggingOperationContext.dataTransfer = event.dataTransfer; + this._rootComponent.needsDraw = true; } } }, - handleDrop: { + // maybe not needed here + captureDrop: { value: function (event) { event.preventDefault(); - this._populateDraggingOperationWithDataTransfer(event.dataTransfer); + event.stopPropagation(); + + this._draggingOperationContext.deltaX = ( + event.pageX - this._draggingOperationContext.startPositionX + ); + this._draggingOperationContext.deltaY = ( + event.pageY - this._draggingOperationContext.startPositionY + ); + this._draggingOperationContext.positionX = event.pageX; + this._draggingOperationContext.positionY = event.pageY; + this._draggingOperationContext.dataTransfer = { + files: event.dataTransfer.files, + items: event.dataTransfer.items, + types: event.dataTransfer.types + }; + + this._removeDragListeners(); this.handleTranslateEnd(); } }, - handleDragleave: { + captureDragleave: { value: function (event) { this._dragEnterCounter--; @@ -746,42 +785,38 @@ var DragManager = exports.DragManager = Montage.specialize({ handleTranslateStart: { value: function (event) { var startPosition = this._translateComposer.pointerStartEventPosition, - dragSource = this._findDragSourceAtPosition( + draggable = this._findDraggableAtPosition( startPosition.pageX, startPosition.pageY - ), - draggedImage; + ); - if (dragSource) { - var draggingOperationInfo; + if (draggable) { + var draggingOperationContext, draggedImage; - this._draggingOperationInfo = (draggingOperationInfo = ( - this._createDraggingOperationInfoWithSourceAndPosition( - dragSource, + this._draggingOperationContext = (draggingOperationContext = ( + this._createDraggingOperationContextWithDraggableAndPosition( + draggable, startPosition ) )); - draggingOperationInfo.dragEffect = ( - dragSource.dragEffect || - DraggingOperationType.Default + var dragStartEvent = this._dispatchDragStart(dragStartEvent); + + this._draggingOperationContext.dataTransfer = dragStartEvent.dataTransfer; + this._draggingOperationContext.dragEffect = dragStartEvent.dataTransfer.dragEffect; + this._draggingOperationContext.draggablePlaceholderStrategy = ( + dragStartEvent.dataTransfer.draggablePlaceholderStrategy ); - dragSource._beginDraggingOperation(draggingOperationInfo); - - if (!draggingOperationInfo.draggedImage) { - draggedImage = dragSource.element.cloneNode(true); - } else { - draggedImage = draggingOperationInfo.draggedImage; + if (!(draggedImage = dragStartEvent.dataTransfer.getDragImage())) { + draggedImage = draggable.element.cloneNode(true); } - draggingOperationInfo.draggedImage = this._sanitizeDraggedImage( + draggingOperationContext.draggedImage = this._sanitizeDraggedImage( draggedImage ); - this._dispatchDraggingOperationStart(draggingOperationInfo); this._addTranslateListeners(); - this._isDragging = true; this._rootComponent.needsDraw = true; } else { @@ -792,13 +827,13 @@ var DragManager = exports.DragManager = Montage.specialize({ handleTranslate: { value: function (event) { - this._draggingOperationInfo.deltaX = event.translateX; - this._draggingOperationInfo.deltaY = event.translateY; - this._draggingOperationInfo.positionX = ( - this._draggingOperationInfo.startPositionX + event.translateX + this._draggingOperationContext.deltaX = event.translateX; + this._draggingOperationContext.deltaY = event.translateY; + this._draggingOperationContext.positionX = ( + this._draggingOperationContext.startPositionX + event.translateX ); - this._draggingOperationInfo.positionY = ( - this._draggingOperationInfo.startPositionY + event.translateY + this._draggingOperationContext.positionY = ( + this._draggingOperationContext.startPositionY + event.translateY ); this._rootComponent.needsDraw = true; } @@ -813,7 +848,7 @@ var DragManager = exports.DragManager = Montage.specialize({ handleTranslateCancel: { value: function () { - this._dragDestination = null; + this._dropDestination = null; this._willTerminateDraggingOperation = true; this._rootComponent.needsDraw = true; } @@ -825,61 +860,73 @@ var DragManager = exports.DragManager = Montage.specialize({ willDraw: { value: function () { - if (this._isDragging) { - var draggingOperationInfo; + var draggingOperationContext; - if ((draggingOperationInfo = this._draggingOperationInfo) && + if (this._isDragging && + (draggingOperationContext = this._draggingOperationContext) + ) { + var draggable = draggingOperationContext.draggable; + + if ( !this._draggedImageBoundingRect && - draggingOperationInfo.dragSource + draggingOperationContext.draggable ) { this._draggedImageBoundingRect = ( - draggingOperationInfo.dragSource.element.getBoundingClientRect() + draggingOperationContext.draggable.element.getBoundingClientRect() ); - if (draggingOperationInfo.dragSourceContainer) { - this._dragSourceContainerBoundingRect = ( - draggingOperationInfo.dragSourceContainer.getBoundingClientRect() + if (draggable.draggableContainer) { + this._draggableContainerBoundingRect = ( + draggable.draggableContainer.getBoundingClientRect() ); } } else { - var dragDestination = this._findDragDestinationAtPosition( - draggingOperationInfo.positionX, - draggingOperationInfo.positionY + var droppable = this._findDroppableAtPosition( + draggingOperationContext.positionX, + draggingOperationContext.positionY ); - if (dragDestination && !dragDestination.acceptDragOperation) { - dragDestination = null; - this._dragEffect = NOT_ALLOWED_CURSOR; - } else { - this._dragEffect = draggingOperationInfo.dragEffect; - } + if (droppable && + !draggingOperationContext.candidateDropTargets.has( + droppable + ) + ) { + droppable = null; + this._cursorStyle = NOT_ALLOWED_CURSOR; + } - if (draggingOperationInfo.dragSource) { - draggingOperationInfo.dragSource._updateDraggingOperation( - draggingOperationInfo - ); + if (draggable) { + draggable.dispatchEvent(this._createDragEvent( + "drag", draggingOperationContext + )); } - if (dragDestination !== this._dragDestination) { - if (this._dragDestination) { - this._notifyDragDestinationDraggedImageHasExited( - draggingOperationInfo + if (droppable !== this._dropDestination) { + if (this._dropDestination) { + this._dispatchDragLeave( + draggingOperationContext ); } - this._dragDestination = dragDestination; + this._dropDestination = droppable; - if (dragDestination) { - this._notifyDragDestinationDraggedImageHasEntered( - draggingOperationInfo + if (droppable) { + this._dispatchDragEnter( + draggingOperationContext ); } - } else if (dragDestination) { - this._notifyDragDestinationDraggedImageHasUpdated( - draggingOperationInfo + } else if (droppable) { + this._dispatchDragOver( + draggingOperationContext ); } else { - this._dragDestination = null; + this._dropDestination = null; + } + + if (droppable) { + this._cursorStyle = draggingOperationContext.dropEffect; + } else { + this._cursorStyle = draggingOperationContext.dragEffect; } } } @@ -888,14 +935,14 @@ var DragManager = exports.DragManager = Montage.specialize({ draw: { value: function () { - var draggingOperationInfo = this._draggingOperationInfo; + var draggingOperationContext = this._draggingOperationContext; if (this._isDragging && !this._willTerminateDraggingOperation) { - var draggedImage = draggingOperationInfo.draggedImage; + var draggedImage = draggingOperationContext.draggedImage; if (draggedImage) { - var translateX = draggingOperationInfo.deltaX, - translateY = draggingOperationInfo.deltaY; + var translateX = draggingOperationContext.deltaX, + translateY = draggingOperationContext.deltaY; this._setUpDraggedImageIfNeeded(draggedImage); @@ -905,55 +952,55 @@ var DragManager = exports.DragManager = Montage.specialize({ this._needsToWaitforDraggedImageBoundaries = false; } - if (this._dragSourceContainerBoundingRect) { - var rect = this._dragSourceContainerBoundingRect, + if (this._draggableContainerBoundingRect) { + var rect = this._draggableContainerBoundingRect, deltaPointerLeft, deltaPointerRight, deltaPointerTop, deltaPointerBottom; - if (draggingOperationInfo.positionX - ( + if (draggingOperationContext.positionX - ( deltaPointerLeft = ( - draggingOperationInfo.startPositionX - + draggingOperationContext.startPositionX - this._draggedImageBoundingRect.left ) ) < rect.left) { translateX = ( rect.left - - draggingOperationInfo.startPositionX + + draggingOperationContext.startPositionX + deltaPointerLeft ); - } else if (draggingOperationInfo.positionX + ( + } else if (draggingOperationContext.positionX + ( deltaPointerRight = ( this._draggedImageBoundingRect.right - - draggingOperationInfo.startPositionX + draggingOperationContext.startPositionX ) ) > rect.right) { translateX = ( rect.right - - draggingOperationInfo.startPositionX - + draggingOperationContext.startPositionX - deltaPointerRight ); } - if (draggingOperationInfo.positionY - ( + if (draggingOperationContext.positionY - ( deltaPointerTop = ( - draggingOperationInfo.startPositionY - + draggingOperationContext.startPositionY - this._draggedImageBoundingRect.top ) ) < rect.top) { translateY = ( rect.top - - draggingOperationInfo.startPositionY + + draggingOperationContext.startPositionY + deltaPointerTop ); - } else if (draggingOperationInfo.positionY + ( + } else if (draggingOperationContext.positionY + ( deltaPointerBottom = ( this._draggedImageBoundingRect.bottom - - draggingOperationInfo.startPositionY + draggingOperationContext.startPositionY ) ) > rect.bottom) { translateY = ( rect.bottom - - draggingOperationInfo.startPositionY - + draggingOperationContext.startPositionY - deltaPointerBottom ); } @@ -963,50 +1010,36 @@ var DragManager = exports.DragManager = Montage.specialize({ translateX + "px," + translateY + "px,0)"; this._scrollIfNeeded( - draggingOperationInfo.positionX, - draggingOperationInfo.positionY + draggingOperationContext.positionX, + draggingOperationContext.positionY ); } - this._rootComponent.element.style.cursor = this._dragDestination ? - draggingOperationInfo.dropEffect : this._dragEffect; + this._rootComponent.element.style.cursor = this._cursorStyle; } else if (this._willTerminateDraggingOperation) { - this._rootComponent.element.style.cursor = DraggingOperationType.Default; + this._rootComponent.element.style.cursor = "default"; - if (draggingOperationInfo.draggedImage) { - document.body.removeChild(draggingOperationInfo.draggedImage); + if (draggingOperationContext.draggedImage) { + document.body.removeChild(draggingOperationContext.draggedImage); } - if (this._dragDestination) { - draggingOperationInfo.hasBeenDrop = true; - draggingOperationInfo.dragDestination = this._dragDestination; + if (this._dropDestination) { + draggingOperationContext.hasBeenDrop = true; + draggingOperationContext.droppable = this._dropDestination; } - this._notifyDragDestinationToPerformDragOperation( - draggingOperationInfo + this._dispatchDrop( + draggingOperationContext ); this._resetTranslateContext(); - - this._notifyDragDestinationToConcludeDragOperation( - draggingOperationInfo - ); - - this._dragDestination = null; - - if (draggingOperationInfo.dragSource) { - draggingOperationInfo.dragSource._endDraggingOperation( - draggingOperationInfo - ); - } - - this._dispatchDraggingOperationEnd(draggingOperationInfo); + this._dropDestination = null; + this._dispatchDragEnd(draggingOperationContext); if ( - draggingOperationInfo.dragSource && - draggingOperationInfo.dragEffect === - DraggingOperationType.Move + draggingOperationContext.draggable && + draggingOperationContext.dragEffect === "move" ) { this._shouldRemovePlaceholder = true; this._rootComponent.needsDraw = true; @@ -1016,13 +1049,13 @@ var DragManager = exports.DragManager = Montage.specialize({ } } - this._removeDragSourcePlaceholderIfNeeded(draggingOperationInfo); + this._removeDraggablePlaceholderIfNeeded(); } }, _setUpDraggedImageIfNeeded: { value: function (draggedImage) { - var draggingOperationInfo = this._draggingOperationInfo; + var draggingOperationContext = this._draggingOperationContext; if (!draggedImage.parentElement) { var draggedImageBoundingRect = this._draggedImageBoundingRect; @@ -1031,17 +1064,13 @@ var DragManager = exports.DragManager = Montage.specialize({ draggedImage.style.width = draggedImageBoundingRect.width + PX; draggedImage.style.height = draggedImageBoundingRect.height + PX; - if ( - draggingOperationInfo.dragEffect === - DraggingOperationType.Move - ) { - var dragSourceElement = draggingOperationInfo.dragSource.element; - this._oldDragSourceDisplayStyle = dragSourceElement.style.display; - dragSourceElement.style.display = 'none'; + if (draggingOperationContext.dragEffect === "move") { + var draggableElement = draggingOperationContext.draggable.element; + this._oldDraggableDisplayStyle = draggableElement.style.display; + draggableElement.style.display = 'none'; if ( - draggingOperationInfo.dragSourcePlaceholderStrategy === - DragManager.DragSourcePlaceholderStrategyVisible + draggingOperationContext.draggablePlaceholderStrategy === "visible" ) { var placeholderElement = document.createElement('div'); placeholderElement.style.width = ( @@ -1055,9 +1084,9 @@ var DragManager = exports.DragManager = Montage.specialize({ 'montage-drag-source-placeholder' ); - dragSourceElement.parentNode.insertBefore( + draggableElement.parentNode.insertBefore( placeholderElement, - dragSourceElement + draggableElement ); this._placeholderElement = placeholderElement; @@ -1065,32 +1094,30 @@ var DragManager = exports.DragManager = Montage.specialize({ } document.body.appendChild(draggedImage); - draggingOperationInfo.isDragOperationStarted = true; this._needsToWaitforDraggedImageBoundaries = true; } } }, - _removeDragSourcePlaceholderIfNeeded: { - value: function (draggingOperationInfo) { - if ( - this._shouldRemovePlaceholder && draggingOperationInfo && - draggingOperationInfo.dragSource - ) { - var dragSourceElement = draggingOperationInfo.dragSource.element; - - dragSourceElement.style.display = this._oldDragSourceDisplayStyle; + _removeDraggablePlaceholderIfNeeded: { + value: function () { + if (this._shouldRemovePlaceholder) { + var draggingOperationContext = this._draggingOperationContext; + this._draggingOperationContext = null; + this._shouldRemovePlaceholder = false; - if ( - draggingOperationInfo.dragSourcePlaceholderStrategy === - DragManager.DragSourcePlaceholderStrategyVisible - ) { - dragSourceElement.parentNode.removeChild( - this._placeholderElement - ); + if (draggingOperationContext && draggingOperationContext.draggable) { + var draggableElement = draggingOperationContext.draggable.element; + draggableElement.style.display = this._oldDraggableDisplayStyle; + + if ( + draggingOperationContext.draggablePlaceholderStrategy === "visible" + ) { + draggableElement.parentNode.removeChild( + this._placeholderElement + ); + } } - - this._shouldRemovePlaceholder = false; } } }, @@ -1098,6 +1125,7 @@ var DragManager = exports.DragManager = Montage.specialize({ _scrollIfNeeded: { value: function (positionX, positionY) { var element = document.elementFromPoint(positionX, positionY), + containerBoundingRect = this._draggableContainerBoundingRect, scrollThreshold = this._scrollThreshold, stopSearchingX = false, stopSearchingY = false, @@ -1129,7 +1157,10 @@ var DragManager = exports.DragManager = Montage.specialize({ stopSearchingY = false; // Check for horizontal scroll up - if (positionY >= top) { + if ( + positionY >= top && + (!containerBoundingRect || positionY >= containerBoundingRect.top) + ) { if (positionY <= top + scrollThreshold) { scrollTop = element.scrollTop; @@ -1152,7 +1183,10 @@ var DragManager = exports.DragManager = Montage.specialize({ } // Check for horizontal scroll down - if (!stopSearchingY && positionY <= bottom) { + if ( + !stopSearchingY && positionY <= bottom && + (!containerBoundingRect || positionY <= containerBoundingRect.bottom) + ) { if (positionY >= bottom - scrollThreshold) { scrollTop = element.scrollTop; @@ -1174,7 +1208,10 @@ var DragManager = exports.DragManager = Montage.specialize({ } // Check for vertical scroll left - if (positionX >= left) { + if ( + positionX >= left && + (!containerBoundingRect || positionX >= containerBoundingRect.left) + ) { if (positionX <= left + scrollThreshold) { scrollLeft = element.scrollLeft; @@ -1197,7 +1234,10 @@ var DragManager = exports.DragManager = Montage.specialize({ } // Check for horizontal scroll right - if (!stopSearchingX && positionX <= right) { + if ( + !stopSearchingX && positionX <= right && + (!containerBoundingRect || positionX <= containerBoundingRect.right) + ) { if (positionX >= right - scrollThreshold) { scrollLeft = element.scrollLeft; scrollWidth = scrollWidth || element.scrollWidth; @@ -1236,16 +1276,6 @@ var DragManager = exports.DragManager = Montage.specialize({ } } -}, { - - DragSourcePlaceholderStrategyHidden: { - value: 0 - }, - - DragSourcePlaceholderStrategyVisible: { - value: 1 - } - }); DragManager.prototype.captureMSPointerDown = DragManager.prototype.capturePointerdown; diff --git a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js index 5c33a8e025..724cc3c27b 100644 --- a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js +++ b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js @@ -15,28 +15,55 @@ exports.DropFile = Component.specialize(/** @lends DropFile# */ { enterDocument: { value: function () { - this.fileName = - this.registerForDragDestination(); + this.registerDroppable(); + this.application.addEventListener("dragstart", this); } }, exitDocument: { value: function () { - this.unregisterForDragDestination(); + this.unregisterDroppable(); + this.application.removeEventListener("dragstart", this); } }, - draggingStarted: { - value: function (draggingOperationInfo) { - return !!(draggingOperationInfo.data.has('types') && - draggingOperationInfo.data.get('types').indexOf('Files') > -1); + handleDragstart: { + value: function (event) { + var shouldAccept = !!(event.dataTransfer.types && + event.dataTransfer.types.indexOf('Files') > -1); + + if (shouldAccept) { + event.dataTransfer.candidateDropTargets.add(this); + this._addEventListeners(); + } } }, - performDragOperation: { - value: function (draggingOperationInfo) { - console.log(draggingOperationInfo.data.get("files")); - this.fileName = draggingOperationInfo.data.get("files")[0].name; + handleDrop: { + value: function (event) { + console.log(event.dataTransfer.files); + this.fileName = event.dataTransfer.files[0].name; + } + }, + + handleDragended: { + value: function (event) { + this._removeEventListeners(); + } + }, + + _addEventListeners: { + value: function () { + this.application.addEventListener("dragend", this); + this.addEventListener("drop", this); + } + }, + + _removeEventListeners: { + value: function () { + this.application.removeEventListener("dragend", this); + this.removeEventListener("drop", this); } } + }); diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js index 0c72a5ba5f..6cff408d60 100644 --- a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js @@ -1,8 +1,7 @@ /** * @module ui/drop-inner.reel */ -var Component = require("montage/ui/component").Component, - DraggingOperationType = require("montage/core/drag/dragging-operation-type").DraggingOperationType; +var Component = require("montage/ui/component").Component; /** * @class DropInner @@ -12,32 +11,58 @@ exports.DropInner = Component.specialize(/** @lends DropInner# */ { enterDocument: { value: function () { - this.data = []; - this.registerForDragDestination(); + this.registerDroppable(); + this.application.addEventListener("dragstart", this, false); } }, exitDocument: { value: function () { - this.unregisterForDragDestination(); + this.unregisterDroppable(); + this.application.removeEventListener("dragstart", this, false); } }, - draggingStarted: { - value: function (draggingOperationInfo) { - return true; + handleDragstart: { + value: function (event) { + event.dataTransfer.candidateDropTargets.add(this); + this._addEventListeners(); } }, - draggingEntered: { - value: function (draggingOperationInfo) { - draggingOperationInfo.dropEffect = DraggingOperationType.Move; + handleDragenter: { + value: function (event) { + event.stopPropagation(); + event.dataTransfer.dropEffect = "move"; } }, - performDragOperation: { - value: function (draggingOperationInfo) { - console.log('dropzone inner received dragging operation'); + handleDrop: { + value: function (event) { + event.stopPropagation(); + console.log('dropzone inner received drop'); + } + }, + + handleDragended: { + value: function (event) { + this._removeEventListeners(); + } + }, + + _addEventListeners: { + value: function () { + this.addEventListener("dragenter", this); + this.addEventListener("dragended", this); + this.addEventListener("drop", this); + } + }, + + _removeEventListeners: { + value: function () { + this.removeEventListener("dragenter", this); + this.removeEventListener("dragended", this); + this.removeEventListener("drop", this); } } diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js index 3f01474aa0..5c4a5e9d73 100644 --- a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js @@ -1,8 +1,7 @@ /** * @module ui/drop-outer.reel */ -var Component = require("montage/ui/component").Component, - DraggingOperationType = require("montage/core/drag/dragging-operation-type").DraggingOperationType; +var Component = require("montage/ui/component").Component; /** * @class DropOuter @@ -12,32 +11,58 @@ exports.DropOuter = Component.specialize(/** @lends DropOuter# */ { enterDocument: { value: function () { - this.data = []; - this.registerForDragDestination(); + this.registerDroppable(); + this.application.addEventListener("dragstart", this, false); } }, exitDocument: { value: function () { - this.unregisterForDragDestination(); + this.unregisterDroppable(); + this.application.removeEventListener("dragstart", this, false); } }, - draggingStarted: { - value: function (draggingOperationInfo) { - return true; + handleDragstart: { + value: function (event) { + event.dataTransfer.candidateDropTargets.add(this); + this._addEventListeners(); } }, - draggingEntered: { - value: function (draggingOperationInfo) { - draggingOperationInfo.dropEffect = DraggingOperationType.Link; + handleDragenter: { + value: function (event) { + event.stopPropagation(); + event.dataTransfer.dropEffect = "alias"; } }, - performDragOperation: { - value: function (draggingOperationInfo) { - console.log('dropzone outer received dragging operation'); + handleDrop: { + value: function (event) { + event.stopPropagation(); + console.log('dropzone outer received drop'); + } + }, + + handleDragended: { + value: function (event) { + this._removeEventListeners(); + } + }, + + _addEventListeners: { + value: function () { + this.addEventListener("dragenter", this); + this.addEventListener("dragended", this); + this.addEventListener("drop", this); + } + }, + + _removeEventListeners: { + value: function () { + this.removeEventListener("dragenter", this); + this.removeEventListener("dragended", this); + this.removeEventListener("drop", this); } } diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.js b/core/drag/drag.info/sample/ui/drop.reel/drop.js index 0a60088abe..ac0c61ba3a 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.js +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.js @@ -1,9 +1,7 @@ /** * @module ui/drop.reel */ -var Component = require("montage/ui/component").Component, - DragManager = require("montage/core/drag/drag-manager").DragManager, - DraggingOperationType = require("montage/core/drag/dragging-operation-type").DraggingOperationType; +var Component = require("montage/ui/component").Component; /** * @class Drop @@ -22,56 +20,74 @@ exports.Drop = Component.specialize(/** @lends Drop# */ { enterDocument: { value: function () { this.data = []; - this.registerForDragDestination(); + this.registerDroppable(); + this.application.addEventListener("dragstart", this, false); } }, exitDocument: { value: function () { - this.unregisterForDragDestination(); + this.unregisterDroppable(); + this.application.removeEventListener("dragstart", this, false); } }, - draggingStarted: { - value: function (draggingOperationInfo) { - if (draggingOperationInfo.dragSource) { - var value = draggingOperationInfo.dragSource.value; - return value && this.data.indexOf(value) === -1 && - this.dataSource.indexOf(value) > -1; + handleDragstart: { + value: function (event) { + var shouldAddToCandidate = false; + + if (this.dataSource) { + var value = event.dataTransfer.getData("text/plain"); + shouldAddToCandidate = value && this.data.indexOf(value) === -1 && + this.dataSource.indexOf(+value) > -1; + } + + if (shouldAddToCandidate) { + event.dataTransfer.candidateDropTargets.add(this); + this._addEventListeners(); } - return false; } }, - performDragOperation: { - value: function (draggingOperationInfo) { - if (draggingOperationInfo.dragSource) { - console.log( - draggingOperationInfo.dragSource.identifier + - ': ' + draggingOperationInfo.data.get('secret') - ); - - var value = draggingOperationInfo.dragSource.value; - - if (value && this.data.indexOf(value) === -1) { - this.data.push(value); - + handleDrop: { + value: function (event) { + var value = event.dataTransfer.getData("text/plain"); + + if (value && this.data.indexOf(value) === -1) { + this.data.push(value); + + if (event.dataTransfer.dropEffect === "move") { + var index; + if ( - draggingOperationInfo.dragEffect === - DraggingOperationType.Move + this.dataSource && + (index = this.dataSource.indexOf(value)) > -1 ) { - var index; - - if ( - this.dataSource && - (index = this.dataSource.indexOf(value)) > -1 - ) { - this.dataSource.splice(index, 1); - } + this.dataSource.splice(index, 1); } } } } + }, + + handleDragended: { + value: function (event) { + this._removeEventListeners(); + } + }, + + _addEventListeners: { + value: function () { + this.addEventListener("dragended", this); + this.addEventListener("drop", this); + } + }, + + _removeEventListeners: { + value: function () { + this.removeEventListener("dragended", this); + this.removeEventListener("drop", this); + } } }); diff --git a/core/drag/drag.info/sample/ui/main.reel/main.html b/core/drag/drag.info/sample/ui/main.reel/main.html index 1fa70d26dd..37ec661b7b 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.html +++ b/core/drag/drag.info/sample/ui/main.reel/main.html @@ -86,8 +86,7 @@ "drop2": { "prototype": "../drop.reel", "values": { - "element": {"#": "drop2"}, - "delegate": {"@": "owner"} + "element": {"#": "drop2"} } }, @@ -128,7 +127,7 @@ "values": { "element": {"#": "customDrag"}, "hasTemplate": false, - "isDragSource": true + "isDraggable": true } } diff --git a/core/drag/drag.info/sample/ui/main.reel/main.js b/core/drag/drag.info/sample/ui/main.reel/main.js index 38580bfff2..59b3db1163 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.js +++ b/core/drag/drag.info/sample/ui/main.reel/main.js @@ -4,12 +4,6 @@ exports.Main = Component.specialize(/** @lends Main# */{ data: { value: [1, 2, 3, 4, 5] - }, - - dragDestinationShouldAcceptDraggingOperation: { - value: function () { - return false; - } } }); diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js index 37e17ea80b..67bd953c25 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.js +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -1,9 +1,7 @@ /** * @module ui/square.reel */ -var Component = require("montage/ui/component").Component, - DragManager = require("montage/core/drag/drag-manager").DragManager, - DraggingOperationType = require("montage/core/drag/dragging-operation-type").DraggingOperationType; +var Component = require("montage/ui/component").Component; /** * @class Square @@ -19,42 +17,41 @@ exports.Square = Component.specialize(/** @lends Square# */ { value: false }, - secret: { - value: null - }, - enterDocument: { value: function () { - this.registerForDragSource(); + this.registerDraggable(); + this.addEventListener("dragstart", this, false); } }, exitDocument: { value: function () { - this.unregisterForDragSource(); + this.removeEventListener("dragstart", this, false); + this.unregisterDraggable(); } }, - beginDraggingOperation: { - value: function (draggingOperationInfo) { + handleDragstart: { + value: function (event) { if (this.enableMoveOperation) { - draggingOperationInfo.dragEffect = DraggingOperationType.Move; - draggingOperationInfo.dropEffectAllowed = DraggingOperationType.Move; + event.dataTransfer.effectAllowed = "move"; + event.dataTransfer.dragEffect = "move"; + } else { + event.dataTransfer.effectAllowed = "all"; } + if (this.container) { - draggingOperationInfo.dragSourceContainer = this.container; + this.draggableContainer = this.container; + } else { + this.draggableContainer = null; } if (this.enableVisiblePlaceholder) { - draggingOperationInfo.dragSourcePlaceholderStrategy = ( - DragManager.DragSourcePlaceholderStrategyVisible - ); + event.dataTransfer.draggablePlaceholderStrategy = "visible"; } - if (this.secret) { - draggingOperationInfo.data.set("secret", this.secret); - } + event.dataTransfer.setData("text/plain", this.value); if (this.switchDraggedImage) { var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), @@ -65,7 +62,7 @@ exports.Square = Component.specialize(/** @lends Square# */ { circle.setAttributeNS(null, 'r', 25); circle.setAttributeNS(null, 'style', 'fill: #e74c3c;'); svg.appendChild(circle); - draggingOperationInfo.draggedImage = svg; + event.dataTransfer.setDragImage(svg, 50, 50); } } } diff --git a/core/drag/dragging-operation-context.js b/core/drag/dragging-operation-context.js new file mode 100644 index 0000000000..9d9724a303 --- /dev/null +++ b/core/drag/dragging-operation-context.js @@ -0,0 +1,65 @@ +var Montage = require("../core").Montage; + +exports.DraggingOperationContext = Montage.specialize({ + + draggable: { + value: null + }, + + draggedImage: { + value: null + }, + + startPositionX: { + value: 0 + }, + + startPositionY: { + value: 0 + }, + + positionX: { + value: 0 + }, + + positionY: { + value: 0 + }, + + deltaX: { + value: 0 + }, + + deltaY: { + value: 0 + }, + + dragabblePlaceholderStrategy: { + value: 'hidden' + }, + + dragEffect: { + value: null + }, + + dropEffect: { + value: null + }, + + effectAllowed: { + value: null + }, + + dataTransfer: { + value: null + }, + + hasBeenDrop: { + value: false + }, + + dragTarget: { + value: null + } + +}); diff --git a/core/drag/dragging-operation-info.js b/core/drag/dragging-operation-info.js deleted file mode 100644 index bd0f810ed9..0000000000 --- a/core/drag/dragging-operation-info.js +++ /dev/null @@ -1,196 +0,0 @@ -var Montage = require("../core").Montage, - DraggingOperationType = require("./dragging-operation-type").DraggingOperationType; - -// name -> DraggingOperationContext? -var DraggingOperationInfo = exports.DraggingOperationInfo = Montage.specialize({ - - dragSource: { - value: null - }, - - _draggedImage: { - value: null - }, - - draggedImage: { - set: function (image) { - if (!this.isDragOperationStarted) { - this._draggedImage = image; - } - }, - get: function () { - return this._draggedImage; - } - }, - - isDragOperationStarted: { - value: false - }, - - startPositionX: { - value: 0 - }, - - startPositionY: { - value: 0 - }, - - positionX: { - value: 0 - }, - - positionY: { - value: 0 - }, - - deltaX: { - value: 0 - }, - - deltaY: { - value: 0 - }, - - dragSourcePlaceholderStrategy: { - value: 0 // default DragSourcePlaceholderStrategyHidden - }, - - _dropEffect: { - value: null - }, - - dropEffect: { - set: function (effect) { - if ( - effect && - DraggingOperationType.ALLOWED_EFFECTS.indexOf(effect) > -1 && - DraggingOperationInfo.isDropEffectAllowed( - effect, this.dropEffectAllowed - ) - ) { - this._dropEffect = effect; - } else { - this._dropEffect = null; - } - }, - get: function () { - if (!this._dropEffect) { - var index; - - if ( - this.dropEffectAllowed === DraggingOperationType.All || - this.dropEffectAllowed.startsWith('c') - ) { - this._dropEffect = DraggingOperationType.Copy; - } else if ((index = DraggingOperationType.ALLOWED_EFFECTS.indexOf( - this.dropEffectAllowed)) > -1 - ) { - this._dropEffect = DraggingOperationType.ALLOWED_EFFECTS[index]; - } else { - this._dropEffect = DraggingOperationType.Link; - } - } - - return this._dropEffect; - } - }, - - _dragEffect: { - value: null - }, - - dragEffect: { - set: function (effect) { - if ( - !this.isDragOperationStarted && - DraggingOperationType.ALLOWED_EFFECTS.indexOf(effect) > -1 - ) { - this._dragEffect = effect; - } - }, - get: function () { - return this._dragEffect || DraggingOperationType.Default; - } - }, - - _dropEffectAllowed: { - value: null - }, - - dropEffectAllowed: { - set: function (effect) { - if ( - !this.isDragOperationStarted && - DraggingOperationType.ALLOWED_DROP_EFFECTS.indexOf(effect) > -1 - ) { - this._dropEffectAllowed = effect; - } - }, - get: function () { - return this._dropEffectAllowed || DraggingOperationType.All; - } - }, - - _dragSourceContainer: { - value: null - }, - - dragSourceContainer: { - set: function (element) { - if (element instanceof Element) { - this._dragSourceContainer = element; - } else if (element.element instanceof Element) { - this._dragSourceContainer = element.element; - } - }, - get: function () { - return this._dragSourceContainer; - } - }, - - _data: { - value: null - }, - - data: { - get: function () { - return this._data || (this._data = new Map()); - } - }, - - hasBeenDrop: { - value: false - }, - - dragDestination: { - value: null - } - -}, { - - isDropEffectAllowed: { - value: function (effect, effectAllowed) { - return effectAllowed === DraggingOperationType.All || - effect === effectAllowed || - (effect === DraggingOperationType.Copy && - ( - effectAllowed === DraggingOperationType.CopyMove || - effectAllowed === DraggingOperationType.CopyLink - ) - ) || - (effect === DraggingOperationType.Move && - ( - effectAllowed === DraggingOperationType.CopyMove || - effectAllowed === DraggingOperationType.LinkMove - ) - ) || - (effect === DraggingOperationType.Link && - ( - effectAllowed === DraggingOperationType.LinkMove || - effectAllowed === DraggingOperationType.CopyLink - ) - ); - } - } - -}); diff --git a/core/drag/dragging-operation-type.js b/core/drag/dragging-operation-type.js deleted file mode 100644 index f699e340be..0000000000 --- a/core/drag/dragging-operation-type.js +++ /dev/null @@ -1,74 +0,0 @@ -var Montage = require("../core").Montage; - -var DraggingOperationType = exports.DraggingOperationType = Montage.specialize(null, { - - Default: { - value: "default" - }, - - Copy: { - value: "copy" - }, - - Move: { - value: "move" - }, - - Link: { - value: "alias" - }, - - CopyLink: { - value: "copyLink" - }, - - CopyMove: { - value: "copyMove" - }, - - LinkMove: { - value: "linkMove" - }, - - All :{ - value: "all" - }, - - _ALLOWED_EFFECTS: { - value: null - }, - - ALLOWED_EFFECTS: { - get: function () { - if (!this._ALLOWED_EFFECTS) { - this._ALLOWED_EFFECTS = [ - this.Default, - this.Copy, - this.Link, - this.Move - ]; - } - - return this._ALLOWED_EFFECTS; - } - }, - - _ALLOWED_DROP_EFFECTS: { - value: null - }, - - ALLOWED_DROP_EFFECTS: { - get: function () { - if (!this._ALLOWED_DROP_EFFECTS) { - this._ALLOWED_DROP_EFFECTS = this.ALLOWED_EFFECTS.concat([ - this.All, - this.CopyMove, - this.CopyLink, - this.LinkMove - ]); - } - - return this._ALLOWED_DROP_EFFECTS; - } - } -}); diff --git a/core/event/event-manager.js b/core/event/event-manager.js index 17ccba4a43..df3a2291e6 100644 --- a/core/event/event-manager.js +++ b/core/event/event-manager.js @@ -15,15 +15,16 @@ */ var Montage = require("../core").Montage, - MutableEvent = require("./mutable-event").MutableEvent, + MutableEvent = require("./mutable-event").MutableEvent, Serializer = require("../serialization/serializer/montage-serializer").MontageSerializer, Deserializer = require("../serialization/deserializer/montage-deserializer").MontageDeserializer, Map = require("collections/map"), WeakMap = require("collections/weak-map"), currentEnvironment = require("../environment").currentEnvironment; -var defaultEventManager; +require("../extras/event"); +var defaultEventManager; //This is a quick polyfill for IE10 that is not exposing CustomEvent as a function. //From https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill diff --git a/core/extras/event.js b/core/extras/event.js new file mode 100644 index 0000000000..da11e66d9b --- /dev/null +++ b/core/extras/event.js @@ -0,0 +1,62 @@ +/* global DataTransfer */ + +var EventPrototype = Event.prototype, + propertyDescriptor = Object.getPropertyDescriptor(EventPrototype, "target"); + +if (typeof DataTransfer !== "undefined") { + var DataTransferPrototype = DataTransfer.prototype, + oldSetDragImage = DataTransferPrototype.setDragImage; + + Object.defineProperties(DataTransferPrototype, { + + effectAllowed: { + value: 'none', + writable: true + }, + + dropEffect: { + value: 'none', + writable: true + }, + + dragEffect: { + value: 'default', + writable: true + }, + + _dragImage: { + value: null, + writable: true, + enumerable: false + }, + + setDragImage: { + value: function (img, xOffset, yOffset) { + if (!this._dragImage) { + this._dragImage = img; + oldSetDragImage.call(this, img, xOffset, yOffset); + } + } + }, + + getDragImage: { + value: function (img, xOffset, yOffset) { + return this._dragImage; + } + }, + + _candidateDropTargets: { + value: null, + writable: true, + enumerable: false + }, + + candidateDropTargets: { + get: function () { + return this._candidateDropTargets || + (this._candidateDropTargets = new Set()); + } + } + + }); +} diff --git a/ui/component.js b/ui/component.js index 3269351913..c38aaae857 100644 --- a/ui/component.js +++ b/ui/component.js @@ -1209,12 +1209,12 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto __exitDocument: { value: function () { - if (this.isDragSource) { - this.unregisterForDragSource(); + if (this.isDraggable) { + this.unregisterDraggable(); } - if (this.isDragDestination) { - this.unregisterForDragDestination(); + if (this.isDroppable) { + this.unregisterDroppable(); } if (this._inDocument && typeof this.exitDocument === "function") { @@ -1282,53 +1282,53 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto } }, - _isDragSource: { + _isDraggable: { value: false }, - isDragSource: { - set: function (isDragSource) { - isDragSource = !!isDragSource; + isDraggable: { + set: function (isDraggable) { + isDraggable = !!isDraggable; - if (this._isDragSource !== isDragSource) { + if (this._isDraggable !== isDraggable) { if (this._inDocument) { - if (this._isDragSource) { - this.unregisterForDragSource(); + if (this._isDraggable) { + this.unregisterDraggable(); } else { - this.registerForDragSource(); + this.registerDraggable(); } } - this._isDragSource = isDragSource; + this._isDraggable = isDraggable; } }, get: function () { - return this._isDragSource; + return this._isDraggable; } }, - _isDragDestination: { + _isDroppable: { value: false }, - isDragDestination: { - set: function (isDragDestination) { - isDragDestination = !!isDragDestination; + isDroppable: { + set: function (isDroppable) { + isDroppable = !!isDroppable; - if (this._isDragDestination !== isDragDestination) { + if (this._isDroppable !== isDroppable) { if (this._inDocument) { - if (this._isDragDestination) { - this.unregisterForDragDestination(); + if (this._isDroppable) { + this.unregisterDroppable(); } else { - this.registerForDragDestination(); + this.registerDroppable(); } } - this._isDragDestination = isDragDestination; + this._isDroppable = isDroppable; } }, get: function () { - return this._isDragDestination; + return this._isDroppable; } }, @@ -2971,14 +2971,15 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto }, // Drag & Drop operations + //registerDraggableComponent /** * Register a component for beeing a dragging source. */ - registerForDragSource: { + registerDraggable: { value: function () { - this.dragManager.registerForDragSource(this); - this.__isDragSource = true; + this.dragManager.registerDraggable(this); + this.__isDraggable = true; this.classList.add("montage-drag-source"); } }, @@ -2986,20 +2987,21 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto /** * unregister a component for beeing a dragging source. */ - unregisterForDragSource: { + unregisterDraggable: { value: function () { - this.dragManager.unregisterForDragSource(this); + this.dragManager.unregisterDraggable(this); this.classList.remove("montage-drag-source"); } }, + //registerDroppableComponent /** * Register a component for beeing a drag destination. */ - registerForDragDestination: { + registerDroppable: { value: function () { - this.dragManager.registerForDragDestination(this); - this.__isDragDestination = true; + this.dragManager.registerDroppable(this); + this.__isDroppable = true; this.classList.add("montage-drag-destination"); } }, @@ -3007,165 +3009,29 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto /** * Unregister a component for beeing a drag destination. */ - unregisterForDragDestination: { + unregisterDroppable: { value: function () { - this.dragManager.unregisterForDragDestination(this); + this.dragManager.unregisterDroppable(this); this.classList.remove("montage-drag-destination"); } }, - /** - * Called on the source when the drag operation starts. - */ - _beginDraggingOperation: { - value: function (draggingOperationInfo) { - if (typeof this.beginDraggingOperation === "function") { - this.beginDraggingOperation(draggingOperationInfo); - } - } - }, - - /** - * Called on the source when the dragged image is moving. - */ - _updateDraggingOperation: { - value: function (draggingOperationInfo) { - if (typeof this.updateDraggingOperation === "function") { - this.updateDraggingOperation(draggingOperationInfo); - } - } - }, - - /** - * Called on the source when the drag operation ends. - */ - _endDraggingOperation: { - value: function (draggingOperationInfo) { - if (typeof this.endDraggingOperation === "function") { - this.endDraggingOperation(draggingOperationInfo); - } - } - }, - - /** - * Called when the drag operation start, - * allowing the receivers to agree to or refuse the drag operation. - * By default all receivers will not accept any drag operation. - * The method `draggingStarted` should return a boolean value. - */ - _draggingStarted: { - value: function (draggingOperationInfo) { - var acceptDragOperation = false, - acceptDragOperationDelegate = this.callDelegateMethod( - "dragDestinationShouldAcceptDraggingOperation", - this, - draggingOperationInfo - ); - - if (acceptDragOperationDelegate !== void 0) { - acceptDragOperation = acceptDragOperationDelegate; - - } else if (typeof this.draggingStarted === "function") { - acceptDragOperation = this.draggingStarted(draggingOperationInfo); - acceptDragOperation = acceptDragOperation === void 0 ? - false : !!acceptDragOperation; - } - - if (acceptDragOperation) { - this.classList.add('accept-dragged-image'); - } - - this.acceptDragOperation = acceptDragOperation; - } - }, - - /** - * Called when the drag operation end, - * allowing the receivers to perform any necessary clean-up - */ - _draggingEnded: { - value: function (draggingOperationInfo) { - this.classList.remove('accept-dragged-image'); - - if (typeof this.draggingEnded === "function") { - this.draggingEnded(draggingOperationInfo); - } - } - }, - - /** - * Called when the dragged image enters - * the destination’s bounds rectangle - */ - _draggingEntered: { - value: function (draggingOperationInfo) { - this.classList.add("dragged-image-entered"); - - if (typeof this.draggingEntered === "function") { - this.draggingEntered(draggingOperationInfo); - } - } - }, - - /** - * Called periodically when the dragged image is held within - * the destination’s bounds rectangle - */ - _draggingUpdated: { - value: function (draggingOperationInfo) { - this.classList.add("dragged-image-over"); - - if (typeof this.draggingUpdated === "function") { - this.draggingUpdated(draggingOperationInfo); - } - } - }, - - /** - * Called when the dragged image exits - * the destination’s bounds rectangle - */ - _draggingExited: { - value: function (draggingOperationInfo) { - this.classList.remove("dragged-image-entered"); - this.classList.remove("dragged-image-over"); - - if (typeof this.draggingExited === "function") { - this.draggingExited(draggingOperationInfo); - } - - draggingOperationInfo.dropEffect = null; - } - }, - - /** - * Called after the released image has been removed from the screen, - * allowing the receiver to import the data. - */ - _performDragOperation: { - value: function (draggingOperationInfo) { - if (this.acceptDragOperation) { - if (typeof this.performDragOperation === "function") { - this.performDragOperation(draggingOperationInfo); - } - } - } + _draggableContainer: { + value: null }, - /** - * Called when the dragging operation is complete, - * allowing the receiver to perform any necessary clean-up. - */ - _concludeDragOperation: { - value: function (draggingOperationInfo) { - if (this.acceptDragOperation) { - this.classList.remove("dragged-image-entered"); - this.classList.remove("dragged-image-over"); - - if (typeof this.concludeDragOperation === "function") { - this.concludeDragOperation(draggingOperationInfo); + draggableContainer: { + set: function (element) { + if (element) { + if (element instanceof Element) { + this._draggableContainer = element; + } else if (element.element instanceof Element) { + this._draggableContainer = element.element; } } + }, + get: function () { + return this._draggableContainer; } }, @@ -3488,12 +3354,12 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto value: function (firstTime) { var originalElement; - if (this.isDragSource) { - this.registerForDragSource(); + if (this.isDraggable) { + this.registerDraggable(); } - if (this.isDragDestination) { - this.registerForDragDestination(); + if (this.isDroppable) { + this.registerDroppable(); } if (firstTime) { From 33602c25c7f45c1745dcab88157bb37dbd361a93 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 18 Jun 2018 17:00:13 -0400 Subject: [PATCH 26/65] Add sugar draggable and droppable properties --- .../sample/ui/drop-file.reel/drop-file.js | 6 +- .../sample/ui/drop-inner.reel/drop-inner.js | 6 +- .../sample/ui/drop-outer.reel/drop-outer.js | 6 +- .../drag.info/sample/ui/drop.reel/drop.js | 6 +- .../drag.info/sample/ui/main.reel/main.html | 2 +- .../drag.info/sample/ui/square.reel/square.js | 6 +- ui/component.js | 81 +++++++------------ 7 files changed, 50 insertions(+), 63 deletions(-) diff --git a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js index 724cc3c27b..bf9872f338 100644 --- a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js +++ b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js @@ -13,16 +13,18 @@ exports.DropFile = Component.specialize(/** @lends DropFile# */ { value: null }, + droppable: { + value: true + }, + enterDocument: { value: function () { - this.registerDroppable(); this.application.addEventListener("dragstart", this); } }, exitDocument: { value: function () { - this.unregisterDroppable(); this.application.removeEventListener("dragstart", this); } }, diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js index 6cff408d60..d12a69b8b8 100644 --- a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js @@ -8,17 +8,19 @@ var Component = require("montage/ui/component").Component; * @extends Component */ exports.DropInner = Component.specialize(/** @lends DropInner# */ { + + droppable: { + value: true + }, enterDocument: { value: function () { - this.registerDroppable(); this.application.addEventListener("dragstart", this, false); } }, exitDocument: { value: function () { - this.unregisterDroppable(); this.application.removeEventListener("dragstart", this, false); } }, diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js index 5c4a5e9d73..0935c73749 100644 --- a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js @@ -9,16 +9,18 @@ var Component = require("montage/ui/component").Component; */ exports.DropOuter = Component.specialize(/** @lends DropOuter# */ { + droppable: { + value: true + }, + enterDocument: { value: function () { - this.registerDroppable(); this.application.addEventListener("dragstart", this, false); } }, exitDocument: { value: function () { - this.unregisterDroppable(); this.application.removeEventListener("dragstart", this, false); } }, diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.js b/core/drag/drag.info/sample/ui/drop.reel/drop.js index ac0c61ba3a..5994257771 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.js +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.js @@ -17,17 +17,19 @@ exports.Drop = Component.specialize(/** @lends Drop# */ { value: null }, + droppable: { + value: true + }, + enterDocument: { value: function () { this.data = []; - this.registerDroppable(); this.application.addEventListener("dragstart", this, false); } }, exitDocument: { value: function () { - this.unregisterDroppable(); this.application.removeEventListener("dragstart", this, false); } }, diff --git a/core/drag/drag.info/sample/ui/main.reel/main.html b/core/drag/drag.info/sample/ui/main.reel/main.html index 37ec661b7b..eec80ec021 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.html +++ b/core/drag/drag.info/sample/ui/main.reel/main.html @@ -127,7 +127,7 @@ "values": { "element": {"#": "customDrag"}, "hasTemplate": false, - "isDraggable": true + "draggable": true } } diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js index 67bd953c25..86f4d185ab 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.js +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -17,9 +17,12 @@ exports.Square = Component.specialize(/** @lends Square# */ { value: false }, + draggable: { + value: true + }, + enterDocument: { value: function () { - this.registerDraggable(); this.addEventListener("dragstart", this, false); } }, @@ -27,7 +30,6 @@ exports.Square = Component.specialize(/** @lends Square# */ { exitDocument: { value: function () { this.removeEventListener("dragstart", this, false); - this.unregisterDraggable(); } }, diff --git a/ui/component.js b/ui/component.js index c38aaae857..d4a7cd8418 100644 --- a/ui/component.js +++ b/ui/component.js @@ -1209,11 +1209,11 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto __exitDocument: { value: function () { - if (this.isDraggable) { + if (this.draggable) { this.unregisterDraggable(); } - if (this.isDroppable) { + if (this.droppable) { this.unregisterDroppable(); } @@ -1282,56 +1282,14 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto } }, - _isDraggable: { + draggable: { value: false }, - isDraggable: { - set: function (isDraggable) { - isDraggable = !!isDraggable; - - if (this._isDraggable !== isDraggable) { - if (this._inDocument) { - if (this._isDraggable) { - this.unregisterDraggable(); - } else { - this.registerDraggable(); - } - } - - this._isDraggable = isDraggable; - } - }, - get: function () { - return this._isDraggable; - } - }, - - _isDroppable: { + droppable: { value: false }, - isDroppable: { - set: function (isDroppable) { - isDroppable = !!isDroppable; - - if (this._isDroppable !== isDroppable) { - if (this._inDocument) { - if (this._isDroppable) { - this.unregisterDroppable(); - } else { - this.registerDroppable(); - } - } - - this._isDroppable = isDroppable; - } - }, - get: function () { - return this._isDroppable; - } - }, - /** * The owner component is the owner of the template form which this * component was instantiated. @@ -1886,6 +1844,9 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto if(this._templateObjects) { this._setupTemplateObjects(documentPart.objects); } + + this.addOwnPropertyChangeListener("draggable", this); + this.addOwnPropertyChangeListener("droppable", this); } }, @@ -2971,7 +2932,26 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto }, // Drag & Drop operations - //registerDraggableComponent + + handleDraggableChange: { + value: function (value) { + if (value) { + this.registerDraggable(); + } else { + this.unregisterDraggable(); + } + } + }, + + handleDroppableChange: { + value: function (value) { + if (value) { + this.registerDroppable(); + } else { + this.unregisterDroppable(); + } + } + }, /** * Register a component for beeing a dragging source. @@ -2979,7 +2959,6 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto registerDraggable: { value: function () { this.dragManager.registerDraggable(this); - this.__isDraggable = true; this.classList.add("montage-drag-source"); } }, @@ -2994,14 +2973,12 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto } }, - //registerDroppableComponent /** * Register a component for beeing a drag destination. */ registerDroppable: { value: function () { this.dragManager.registerDroppable(this); - this.__isDroppable = true; this.classList.add("montage-drag-destination"); } }, @@ -3354,11 +3331,11 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto value: function (firstTime) { var originalElement; - if (this.isDraggable) { + if (this.draggable) { this.registerDraggable(); } - if (this.isDroppable) { + if (this.droppable) { this.registerDroppable(); } From 6eeeb961249a5ccf7cc3cbab911b9c0608a3c8a0 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 18 Jun 2018 17:03:10 -0400 Subject: [PATCH 27/65] Remove event extras --- core/event/event-manager.js | 2 -- core/extras/event.js | 62 ------------------------------------- 2 files changed, 64 deletions(-) delete mode 100644 core/extras/event.js diff --git a/core/event/event-manager.js b/core/event/event-manager.js index df3a2291e6..e4aef1c155 100644 --- a/core/event/event-manager.js +++ b/core/event/event-manager.js @@ -22,8 +22,6 @@ var Montage = require("../core").Montage, WeakMap = require("collections/weak-map"), currentEnvironment = require("../environment").currentEnvironment; -require("../extras/event"); - var defaultEventManager; //This is a quick polyfill for IE10 that is not exposing CustomEvent as a function. diff --git a/core/extras/event.js b/core/extras/event.js deleted file mode 100644 index da11e66d9b..0000000000 --- a/core/extras/event.js +++ /dev/null @@ -1,62 +0,0 @@ -/* global DataTransfer */ - -var EventPrototype = Event.prototype, - propertyDescriptor = Object.getPropertyDescriptor(EventPrototype, "target"); - -if (typeof DataTransfer !== "undefined") { - var DataTransferPrototype = DataTransfer.prototype, - oldSetDragImage = DataTransferPrototype.setDragImage; - - Object.defineProperties(DataTransferPrototype, { - - effectAllowed: { - value: 'none', - writable: true - }, - - dropEffect: { - value: 'none', - writable: true - }, - - dragEffect: { - value: 'default', - writable: true - }, - - _dragImage: { - value: null, - writable: true, - enumerable: false - }, - - setDragImage: { - value: function (img, xOffset, yOffset) { - if (!this._dragImage) { - this._dragImage = img; - oldSetDragImage.call(this, img, xOffset, yOffset); - } - } - }, - - getDragImage: { - value: function (img, xOffset, yOffset) { - return this._dragImage; - } - }, - - _candidateDropTargets: { - value: null, - writable: true, - enumerable: false - }, - - candidateDropTargets: { - get: function () { - return this._candidateDropTargets || - (this._candidateDropTargets = new Set()); - } - } - - }); -} From 1941617d295ef8974d63cb7919e3019e765b9c97 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 18 Jun 2018 17:40:17 -0400 Subject: [PATCH 28/65] Fix files Drag & Drop support --- core/drag/drag-event.js | 24 ++++++++++++++++++++++-- core/drag/drag-manager.js | 21 ++++++++++++--------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index ec94bc24aa..cb74979d97 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -1,7 +1,7 @@ var MutableEvent = require("../event/mutable-event").MutableEvent, Montage = require("../core").Montage; -var DataTransfer = Montage.specialize({ +var DataTransfer = exports.DataTransfer = Montage.specialize({ __data: { enumerable: false, @@ -248,7 +248,27 @@ var DataTransfer = Montage.specialize({ effectAllowed === this.CopyLink )); } - } + }, + + /** + * @function + * @param {window.DataTransfer} dataTransfer The original DataTransfer. + * @returns DataTransfer + */ + fromDataTransfer: { + value: function (dataTransfer) { + montageDataTransfer = new DataTransfer(); + + montageDataTransfer.items = dataTransfer.items; + montageDataTransfer.files = dataTransfer.files; + montageDataTransfer.types = dataTransfer.types; + montageDataTransfer.dropEffect = dataTransfer.dropEffect === 'none' ? + this.Default : dataTransfer.dropEffect; + montageDataTransfer.effectAllowed = dataTransfer.effectAllowed; + + return montageDataTransfer; + } + }, }); exports.DragEvent = MutableEvent.specialize({ diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 64b1b9bcca..6a882515fd 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -1,5 +1,6 @@ var Montage = require("../core").Montage, DragEvent = require("./drag-event").DragEvent, + DataTransfer = require("./drag-event").DataTransfer, TranslateComposer = require("../../composer/translate-composer").TranslateComposer, DraggingOperationContext = require("./dragging-operation-context").DraggingOperationContext; @@ -113,7 +114,6 @@ var DragManager = exports.DragManager = Montage.specialize({ value: 0 }, - // TODO: rename _cursorStyle: { value: null }, @@ -703,7 +703,9 @@ var DragManager = exports.DragManager = Montage.specialize({ ) )); - draggingOperationContext.dataTransfer = event.dataTransfer; + draggingOperationContext.dataTransfer = ( + DataTransfer.fromDataTransfer(event.dataTransfer) + ); var dragStartEvent = this._dispatchDragStart(); @@ -714,7 +716,6 @@ var DragManager = exports.DragManager = Montage.specialize({ this._addDragListeners(); this._isDragging = true; this._rootComponent.needsDraw = true; - } } @@ -742,6 +743,10 @@ var DragManager = exports.DragManager = Montage.specialize({ this._draggingOperationContext.positionY = event.pageY; this._draggingOperationContext.dataTransfer = event.dataTransfer; + this._draggingOperationContext.dataTransfer = ( + DataTransfer.fromDataTransfer(event.dataTransfer) + ); + this._rootComponent.needsDraw = true; } } @@ -761,11 +766,9 @@ var DragManager = exports.DragManager = Montage.specialize({ ); this._draggingOperationContext.positionX = event.pageX; this._draggingOperationContext.positionY = event.pageY; - this._draggingOperationContext.dataTransfer = { - files: event.dataTransfer.files, - items: event.dataTransfer.items, - types: event.dataTransfer.types - }; + this._draggingOperationContext.dataTransfer = ( + DataTransfer.fromDataTransfer(event.dataTransfer) + ); this._removeDragListeners(); this.handleTranslateEnd(); @@ -800,7 +803,7 @@ var DragManager = exports.DragManager = Montage.specialize({ ) )); - var dragStartEvent = this._dispatchDragStart(dragStartEvent); + var dragStartEvent = this._dispatchDragStart(); this._draggingOperationContext.dataTransfer = dragStartEvent.dataTransfer; this._draggingOperationContext.dragEffect = dragStartEvent.dataTransfer.dragEffect; From 044dc2220ca5578f9326290476db84bff18d60ab Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 18 Jun 2018 17:54:46 -0400 Subject: [PATCH 29/65] Fix broken specs --- core/drag/drag-event.js | 4 ++-- core/drag/drag-manager.js | 14 +++++------ .../sample/ui/drop-inner.reel/drop-inner.css | 2 +- .../drag.info/sample/ui/main.reel/main.css | 2 +- test/spec/core/drag/drag-spec.js | 24 +++++++++---------- test/spec/core/drag/drag-test.html | 4 ++-- ui/component.js | 8 +++---- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index cb74979d97..fdfcda28ab 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -257,7 +257,7 @@ var DataTransfer = exports.DataTransfer = Montage.specialize({ */ fromDataTransfer: { value: function (dataTransfer) { - montageDataTransfer = new DataTransfer(); + var montageDataTransfer = new DataTransfer(); montageDataTransfer.items = dataTransfer.items; montageDataTransfer.files = dataTransfer.files; @@ -308,7 +308,7 @@ exports.DragEvent = MutableEvent.specialize({ } }, { - DRAGEND: { + DRAGSTART: { value: "dragstart" }, diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 6a882515fd..29944684e8 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -12,13 +12,13 @@ var PX = "px"; var DragManager = exports.DragManager = Montage.specialize({ - __dragabbles: { + __draggables: { value: null }, - _dragabbles: { + _draggables: { get: function () { - return this.__dragabbles || (this.__dragabbles = []); + return this.__draggables || (this.__draggables = []); } }, @@ -219,7 +219,7 @@ var DragManager = exports.DragManager = Montage.specialize({ value: function (component, role) { if (component) { var components = role === DRAGGABLE ? - this._dragabbles : this._droppables; + this._draggables : this._droppables; if (components.indexOf(component) === -1) { components.push(component); @@ -239,7 +239,7 @@ var DragManager = exports.DragManager = Montage.specialize({ value: function (component, role) { if (component) { var components = role === DRAGGABLE ? - this._dragabbles : this._droppables, + this._draggables : this._droppables, index; if ((index = components.indexOf(component)) > -1) { @@ -503,7 +503,7 @@ var DragManager = exports.DragManager = Montage.specialize({ if (targetComponent) { var components = role === DRAGGABLE ? - this._dragabbles : this._droppables, + this._draggables : this._droppables, index; while (targetComponent) { @@ -1084,7 +1084,7 @@ var DragManager = exports.DragManager = Montage.specialize({ ); placeholderElement.style.boxSizing = "border-box"; placeholderElement.classList.add( - 'montage-drag-source-placeholder' + 'montage-draggable-placeholder' ); draggableElement.parentNode.insertBefore( diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css index f1d2f00caf..06d2d63eb3 100644 --- a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css @@ -22,4 +22,4 @@ .Drop.DropInner.dragged-image-over { border: 4px solid #3498db; animation: none; -} \ No newline at end of file +} diff --git a/core/drag/drag.info/sample/ui/main.reel/main.css b/core/drag/drag.info/sample/ui/main.reel/main.css index b9a96c35e5..04276c3e95 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.css +++ b/core/drag/drag.info/sample/ui/main.reel/main.css @@ -74,7 +74,7 @@ h4 { margin-left: 8px; } -.samples .montage-drag-source-placeholder { +.samples .montage-draggable-placeholder { border: 2px dashed #9b59b6; } diff --git a/test/spec/core/drag/drag-spec.js b/test/spec/core/drag/drag-spec.js index 0a49a5ef62..05e2036920 100644 --- a/test/spec/core/drag/drag-spec.js +++ b/test/spec/core/drag/drag-spec.js @@ -20,35 +20,35 @@ TestPageLoader.queueTest("drag-test", function (testPage) { describe("Drag Source", function () { it("shoud be registered within the drag manager", function () { - expect(dragComponent.isDragSource).toEqual(true); - expect(dragComponent.dragManager._dragSources.indexOf(dragComponent) > -1).toEqual(true); + expect(dragComponent.draggable).toEqual(true); + expect(dragComponent.dragManager._draggables.indexOf(dragComponent) > -1).toEqual(true); }); - it("shoud have the class name `montage-drag-source`", function () { - expect(dragComponent.classList.has("montage-drag-source")).toEqual(true); + it("shoud have the class name `montage-draggable`", function () { + expect(dragComponent.classList.has("montage-draggable")).toEqual(true); }); it("shoud be unregistered when leaving the component tree", function () { dragComponent._exitDocument(); - expect(dragComponent.dragManager._dragSources.indexOf(dragComponent) === -1).toEqual(true); - expect(dragComponent.classList.has("montage-drag-source")).toEqual(false); + expect(dragComponent.dragManager._draggables.indexOf(dragComponent) === -1).toEqual(true); + expect(dragComponent.classList.has("montage-draggable")).toEqual(false); }); }); describe("Drag Destination", function () { it("shoud be registered within the drag manager ", function () { - expect(dropComponent.isDragDestination).toEqual(true); - expect(dropComponent.dragManager._dragDestinations.indexOf(dropComponent) > -1).toEqual(true); + expect(dropComponent.droppable).toEqual(true); + expect(dropComponent.dragManager._droppables.indexOf(dropComponent) > -1).toEqual(true); }); - it("shoud have the class name `montage-drag-destination`", function () { - expect(dropComponent.classList.has("montage-drag-destination")).toEqual(true); + it("shoud have the class name `montage-droppable`", function () { + expect(dropComponent.classList.has("montage-droppable")).toEqual(true); }); it("shoud be unregistered when leaving the component tree", function () { dropComponent._exitDocument(); - expect(dropComponent.dragManager._dragDestinations.indexOf(dropComponent) === -1).toEqual(true); - expect(dropComponent.classList.has("montage-drag-destination")).toEqual(false); + expect(dropComponent.dragManager._droppables.indexOf(dropComponent) === -1).toEqual(true); + expect(dropComponent.classList.has("montage-droppable")).toEqual(false); }); }); diff --git a/test/spec/core/drag/drag-test.html b/test/spec/core/drag/drag-test.html index aff5e6c271..036d962047 100644 --- a/test/spec/core/drag/drag-test.html +++ b/test/spec/core/drag/drag-test.html @@ -12,7 +12,7 @@ "values": { "element": {"#": "drag"}, "hasTemplate": false, - "isDragSource": true + "draggable": true } }, "drop": { @@ -20,7 +20,7 @@ "values": { "element": {"#": "drop"}, "hasTemplate": false, - "isDragDestination": true + "droppable": true } } } diff --git a/ui/component.js b/ui/component.js index d4a7cd8418..713877f54f 100644 --- a/ui/component.js +++ b/ui/component.js @@ -2959,7 +2959,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto registerDraggable: { value: function () { this.dragManager.registerDraggable(this); - this.classList.add("montage-drag-source"); + this.classList.add("montage-draggable"); } }, @@ -2969,7 +2969,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto unregisterDraggable: { value: function () { this.dragManager.unregisterDraggable(this); - this.classList.remove("montage-drag-source"); + this.classList.remove("montage-draggable"); } }, @@ -2979,7 +2979,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto registerDroppable: { value: function () { this.dragManager.registerDroppable(this); - this.classList.add("montage-drag-destination"); + this.classList.add("montage-droppable"); } }, @@ -2989,7 +2989,7 @@ var Component = exports.Component = Target.specialize(/** @lends Component.proto unregisterDroppable: { value: function () { this.dragManager.unregisterDroppable(this); - this.classList.remove("montage-drag-destination"); + this.classList.remove("montage-droppable"); } }, From ed03a5ee179b537c5e453c40ad13572d87efa5ba Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Thu, 21 Jun 2018 16:11:23 -0400 Subject: [PATCH 30/65] =?UTF-8?q?Make=20sure=20the=20dragging=20context=20?= =?UTF-8?q?is=20cleaned=20once=20it=E2=80=99s=20over.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/drag/drag-manager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 29944684e8..a6c4dba6a7 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -1049,6 +1049,8 @@ var DragManager = exports.DragManager = Montage.specialize({ // Wait for the next draw cycle to remove the placeholder, // allowing the receiver to perform any necessary clean-up. return void 0; + } else { + this._draggingOperationContext = null; } } From 58c3bbc12c6c437c059ece876c83a9dc17de9882 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Fri, 22 Jun 2018 14:54:21 -0400 Subject: [PATCH 31/65] Fix node specs --- core/drag/drag-event.js | 531 ++++++++++++++++++++-------------------- 1 file changed, 268 insertions(+), 263 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index fdfcda28ab..25a616d72b 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -1,313 +1,316 @@ var MutableEvent = require("../event/mutable-event").MutableEvent, Montage = require("../core").Montage; -var DataTransfer = exports.DataTransfer = Montage.specialize({ +// XXX Does not presently function server-side +if (typeof window !== "undefined") { - __data: { - enumerable: false, - value: null - }, + var DataTransfer = exports.DataTransfer = Montage.specialize({ - _data: { - enumerable: false, - get: function () { - return this.__data || (this.__data = new Map()); - } - }, + __data: { + enumerable: false, + value: null + }, - _dragImage: { - value: null, - enumerable: false, - }, + _data: { + enumerable: false, + get: function () { + return this.__data || (this.__data = new Map()); + } + }, - _dragEffect: { - value: null - }, + _dragImage: { + value: null, + enumerable: false, + }, - dragEffect: { - set: function (effect) { - if (DataTransfer.ALLOWED_EFFECTS.indexOf(effect) > -1) { - this._dragEffect = effect; - } + _dragEffect: { + value: null }, - get: function () { - return this._dragEffect || DataTransfer.Default; - } - }, - - _dropEffect: { - value: null - }, - - dropEffect: { - set: function (effect) { - if ( - effect && - DataTransfer.ALLOWED_EFFECTS.indexOf(effect) > -1 && - DataTransfer.isDropEffectAllowed( - effect, this.effectAllowed - ) - ) { - this._dropEffect = effect; - } else { - this._dropEffect = null; + + dragEffect: { + set: function (effect) { + if (DataTransfer.ALLOWED_EFFECTS.indexOf(effect) > -1) { + this._dragEffect = effect; + } + }, + get: function () { + return this._dragEffect || DataTransfer.Default; } }, - get: function () { - if (!this._dropEffect) { - var index; + _dropEffect: { + value: null + }, + + dropEffect: { + set: function (effect) { if ( - this.effectAllowed === DataTransfer.All || - this.effectAllowed.startsWith('c') - ) { - this._dropEffect = DataTransfer.Copy; - } else if ((index = DataTransfer.ALLOWED_EFFECTS.indexOf( - this.effectAllowed)) > -1 + effect && + DataTransfer.ALLOWED_EFFECTS.indexOf(effect) > -1 && + DataTransfer.isDropEffectAllowed( + effect, this.effectAllowed + ) ) { - this._dropEffect = DataTransfer.ALLOWED_EFFECTS[index]; + this._dropEffect = effect; } else { - this._dropEffect = DataTransfer.Link; + this._dropEffect = null; + } + }, + get: function () { + if (!this._dropEffect) { + var index; + + if ( + this.effectAllowed === DataTransfer.All || + this.effectAllowed.startsWith('c') + ) { + this._dropEffect = DataTransfer.Copy; + } else if ((index = DataTransfer.ALLOWED_EFFECTS.indexOf( + this.effectAllowed)) > -1 + ) { + this._dropEffect = DataTransfer.ALLOWED_EFFECTS[index]; + } else { + this._dropEffect = DataTransfer.Link; + } } - } - return this._dropEffect; - } - }, + return this._dropEffect; + } + }, - _effectAllowed: { - value: null - }, + _effectAllowed: { + value: null + }, - effectAllowed: { - set: function (effect) { - if (DataTransfer.ALLOWED_DROP_EFFECTS.indexOf(effect) > -1) { - this._effectAllowed = effect; + effectAllowed: { + set: function (effect) { + if (DataTransfer.ALLOWED_DROP_EFFECTS.indexOf(effect) > -1) { + this._effectAllowed = effect; + } + }, + get: function () { + return this._effectAllowed || DataTransfer.All; } }, - get: function () { - return this._effectAllowed || DataTransfer.All; - } - }, - files: { - value: null - }, - - items: { - value: null - }, + files: { + value: null + }, - types: { - value: null - }, + items: { + value: null + }, - dragTarget: { - value: null - }, + types: { + value: null + }, - _candidateDropTargets: { - value: null, - enumerable: false - }, + dragTarget: { + value: null + }, - candidateDropTargets: { - get: function () { - return this._candidateDropTargets || - (this._candidateDropTargets = new Set()); - } - }, + _candidateDropTargets: { + value: null, + enumerable: false + }, - dragabblePlaceholderStrategy: { - value: 'hidden' - }, + candidateDropTargets: { + get: function () { + return this._candidateDropTargets || + (this._candidateDropTargets = new Set()); + } + }, - clearData: { - value: function () { - return this._data.clear(); - } - }, + dragabblePlaceholderStrategy: { + value: 'hidden' + }, - getData: { - value: function (key) { - return this._data.get(key); - } - }, + clearData: { + value: function () { + return this._data.clear(); + } + }, - hasData: { - value: function (key) { - return this._data.has(key); - } - }, + getData: { + value: function (key) { + return this._data.get(key); + } + }, - setData: { - value: function (key, value) { - return this._data.set(key, value); - } - }, + hasData: { + value: function (key) { + return this._data.has(key); + } + }, - setDragImage: { - value: function (img, xOffset, yOffset) { - if (!this._dragImage) { - this._dragImage = img; + setData: { + value: function (key, value) { + return this._data.set(key, value); } - } - }, + }, - getDragImage: { - value: function () { - return this._dragImage; - } - }, - -}, { - Default: { - value: "default" - }, - - Copy: { - value: "copy" - }, - - Move: { - value: "move" - }, - - Link: { - value: "alias" - }, - - CopyLink: { - value: "copyLink" - }, - - CopyMove: { - value: "copyMove" - }, - - LinkMove: { - value: "linkMove" - }, - - All: { - value: "all" - }, - - _ALLOWED_EFFECTS: { - value: null - }, - - ALLOWED_EFFECTS: { - get: function () { - if (!this._ALLOWED_EFFECTS) { - this._ALLOWED_EFFECTS = [ - this.Default, - this.Copy, - this.Link, - this.Move - ]; + setDragImage: { + value: function (img, xOffset, yOffset) { + if (!this._dragImage) { + this._dragImage = img; + } } + }, - return this._ALLOWED_EFFECTS; - } - }, - - _ALLOWED_DROP_EFFECTS: { - value: null - }, - - ALLOWED_DROP_EFFECTS: { - get: function () { - if (!this._ALLOWED_DROP_EFFECTS) { - this._ALLOWED_DROP_EFFECTS = this.ALLOWED_EFFECTS.concat([ - this.All, - this.CopyMove, - this.CopyLink, - this.LinkMove - ]); + getDragImage: { + value: function () { + return this._dragImage; } + }, - return this._ALLOWED_DROP_EFFECTS; - } - }, - - isDropEffectAllowed: { - value: function (effect, effectAllowed) { - return effectAllowed === this.All || - effect === effectAllowed || - (effect === this.Copy && ( - effectAllowed === this.CopyMove || - effectAllowed === this.CopyLink - )) || - (effect === this.Move && ( - effectAllowed === this.CopyMove || - effectAllowed === this.LinkMove - )) || - (effect === this.Link && ( - effectAllowed === this.LinkMove || - effectAllowed === this.CopyLink - )); - } - }, - - /** - * @function - * @param {window.DataTransfer} dataTransfer The original DataTransfer. - * @returns DataTransfer - */ - fromDataTransfer: { - value: function (dataTransfer) { - var montageDataTransfer = new DataTransfer(); - - montageDataTransfer.items = dataTransfer.items; - montageDataTransfer.files = dataTransfer.files; - montageDataTransfer.types = dataTransfer.types; - montageDataTransfer.dropEffect = dataTransfer.dropEffect === 'none' ? - this.Default : dataTransfer.dropEffect; - montageDataTransfer.effectAllowed = dataTransfer.effectAllowed; - - return montageDataTransfer; - } - }, -}); + }, { + Default: { + value: "default" + }, + + Copy: { + value: "copy" + }, + + Move: { + value: "move" + }, + + Link: { + value: "alias" + }, + + CopyLink: { + value: "copyLink" + }, + + CopyMove: { + value: "copyMove" + }, + + LinkMove: { + value: "linkMove" + }, + + All: { + value: "all" + }, + + _ALLOWED_EFFECTS: { + value: null + }, + + ALLOWED_EFFECTS: { + get: function () { + if (!this._ALLOWED_EFFECTS) { + this._ALLOWED_EFFECTS = [ + this.Default, + this.Copy, + this.Link, + this.Move + ]; + } + + return this._ALLOWED_EFFECTS; + } + }, + + _ALLOWED_DROP_EFFECTS: { + value: null + }, + + ALLOWED_DROP_EFFECTS: { + get: function () { + if (!this._ALLOWED_DROP_EFFECTS) { + this._ALLOWED_DROP_EFFECTS = this.ALLOWED_EFFECTS.concat([ + this.All, + this.CopyMove, + this.CopyLink, + this.LinkMove + ]); + } + + return this._ALLOWED_DROP_EFFECTS; + } + }, + + isDropEffectAllowed: { + value: function (effect, effectAllowed) { + return effectAllowed === this.All || + effect === effectAllowed || + (effect === this.Copy && ( + effectAllowed === this.CopyMove || + effectAllowed === this.CopyLink + )) || + (effect === this.Move && ( + effectAllowed === this.CopyMove || + effectAllowed === this.LinkMove + )) || + (effect === this.Link && ( + effectAllowed === this.LinkMove || + effectAllowed === this.CopyLink + )); + } + }, + + /** + * @function + * @param {window.DataTransfer} dataTransfer The original DataTransfer. + * @returns DataTransfer + */ + fromDataTransfer: { + value: function (dataTransfer) { + var montageDataTransfer = new DataTransfer(); + + montageDataTransfer.items = dataTransfer.items; + montageDataTransfer.files = dataTransfer.files; + montageDataTransfer.types = dataTransfer.types; + montageDataTransfer.dropEffect = dataTransfer.dropEffect === 'none' ? + this.Default : dataTransfer.dropEffect; + montageDataTransfer.effectAllowed = dataTransfer.effectAllowed; + + return montageDataTransfer; + } + }, + }); -exports.DragEvent = MutableEvent.specialize({ + exports.DragEvent = MutableEvent.specialize({ - type: { - value: "drag" - }, + type: { + value: "drag" + }, - _event: { - enumerable: false, - value: null - }, + _event: { + enumerable: false, + value: null + }, - event: { - get: function () { - return this._event; + event: { + get: function () { + return this._event; + }, + set: function (value) { + this._event = value; + } }, - set: function (value) { - this._event = value; - } - }, - bubbles: { - value: true - }, + bubbles: { + value: true + }, - dataTransfer: { - value: null - }, + dataTransfer: { + value: null + }, - constructor: { - value: function (type, eventInit) { - this.dataTransfer = new DataTransfer(); - this._event = new CustomEvent(type, eventInit); - this.type = type; + constructor: { + value: function (type, eventInit) { + this.dataTransfer = new DataTransfer(); + this._event = new CustomEvent(type, eventInit); + this.type = type; + } } - } -}, { + }, { DRAGSTART: { value: "dragstart" }, @@ -335,4 +338,6 @@ exports.DragEvent = MutableEvent.specialize({ DRAGEND: { value: "dragend" } -}); + }); + +} From 41b8402ae6635e733229f649a5e9aee4dbd11a72 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Fri, 22 Jun 2018 16:34:10 -0400 Subject: [PATCH 32/65] Fix #1985 --- core/range-controller.js | 16 ---------------- core/range-controller.meta | 17 ----------------- test/spec/base/abstract-select-spec.js | 18 +++++++++--------- ui/base/abstract-select.js | 5 ++--- ui/base/abstract-select.meta | 8 ++++---- 5 files changed, 15 insertions(+), 49 deletions(-) diff --git a/core/range-controller.js b/core/range-controller.js index d1eca2c6fc..e59482dc84 100644 --- a/core/range-controller.js +++ b/core/range-controller.js @@ -4,7 +4,6 @@ var Montage = require("./core").Montage; var GenericCollection = require("collections/generic-collection"); var observableArrayProperties = require("collections/listen/array-changes").observableArrayProperties; -var deprecate = require("core/deprecate"); // The content controller is responsible for determining which content from a // source collection are visible, their order of appearance, and whether they @@ -364,21 +363,6 @@ var RangeController = exports.RangeController = Montage.specialize( /** @lends R */ allowsMultipleSelection: {value: false}, - /** - * @deprecated - */ - multiSelect: { - set: function (multiSelect) { - deprecate.deprecationWarning("multiSelect", "allowsMultipleSelection"); - this.allowsMultipleSelection = !!multiSelect; - }, - get: function () { - deprecate.deprecationWarning("multiSelect", "allowsMultipleSelection"); - return this.allowsMultipleSelection; - } - }, - - // Properties managed by the controller // ------------------------------------ diff --git a/core/range-controller.meta b/core/range-controller.meta index 2e7fda17d7..eff2058a8b 100644 --- a/core/range-controller.meta +++ b/core/range-controller.meta @@ -100,17 +100,6 @@ "helpKey": "" } }, - "rangeController_multiSelect": { - "prototype": "core/meta/property-descriptor", - "values": { - "name": "multiSelect", - "objectDescriptor": { - "@": "root" - }, - "valueType": "boolean", - "helpKey": "" - } - }, "root": { "prototype": "core/meta/module-object-descriptor", "values": { @@ -143,9 +132,6 @@ }, { "@": "rangeController_avoidsEmptySelection" - }, - { - "@": "rangeController_multiSelect" } ], "propertyDescriptorGroups": { @@ -176,9 +162,6 @@ }, { "@": "rangeController_avoidsEmptySelection" - }, - { - "@": "rangeController_multiSelect" } ] }, diff --git a/test/spec/base/abstract-select-spec.js b/test/spec/base/abstract-select-spec.js index ce5d160db2..af9c6dad03 100644 --- a/test/spec/base/abstract-select-spec.js +++ b/test/spec/base/abstract-select-spec.js @@ -152,11 +152,11 @@ describe("test/base/abstract-select-spec", function () { }); }); - describe("value with multiSelect", function () { + describe("value with allowsMultipleSelection", function () { beforeEach(function () { aSelect = new Select(); aSelect.content = content; - aSelect.multiSelect = true; + aSelect.allowsMultipleSelection = true; }); it("should have first of the values", function () { @@ -175,7 +175,7 @@ describe("test/base/abstract-select-spec", function () { beforeEach(function () { aSelect = new Select(); aSelect.content = content; - aSelect.multiSelect = true; + aSelect.allowsMultipleSelection = true; }); it("should change the selection of the content controller", function () { @@ -224,25 +224,25 @@ describe("test/base/abstract-select-spec", function () { }); }); - describe("multiSelect", function () { + describe("allowsMultipleSelection", function () { beforeEach(function () { aSelect = new Select(); aSelect.content = content; }); - it("should only have one item in the content controller's selection when multiSelect is off", function () { - aSelect.multiSelect = false; + it("should only have one item in the content controller's selection when allowsMultipleSelection is off", function () { + aSelect.allowsMultipleSelection = false; expect(aSelect.contentController.selection.length).toBe(1); aSelect.values = [content[1], content[2]]; expect(aSelect.contentController.selection.length).toBe(1); }); - it("should only have one selected item in content controller's selection when multiSelect is turned off", function () { - aSelect.multiSelect = true; + it("should only have one selected item in content controller's selection when allowsMultipleSelection is turned off", function () { + aSelect.allowsMultipleSelection = true; aSelect.values = [content[1], content[2]]; - aSelect.multiSelect = false; + aSelect.allowsMultipleSelection = false; expect(aSelect.contentController.selection.length).toBe(1); }); }); diff --git a/ui/base/abstract-select.js b/ui/base/abstract-select.js index b43c233878..238095bf99 100644 --- a/ui/base/abstract-select.js +++ b/ui/base/abstract-select.js @@ -48,7 +48,7 @@ var AbstractSelect = exports.AbstractSelect = AbstractControl.specialize( /** @l // "<->": "values.one()" // }, "contentController.allowsMultipleSelection": { - "<-": "multiSelect" + "<-": "allowsMultipleSelection" }, // classList management "classList.has('montage--disabled')": { @@ -154,7 +154,7 @@ var AbstractSelect = exports.AbstractSelect = AbstractControl.specialize( /** @l } }, - multiSelect: { + allowsMultipleSelection: { value: false }, @@ -265,4 +265,3 @@ var AbstractSelect = exports.AbstractSelect = AbstractControl.specialize( /** @l } }); - diff --git a/ui/base/abstract-select.meta b/ui/base/abstract-select.meta index 644bbd1c6e..3f8ac16bf7 100644 --- a/ui/base/abstract-select.meta +++ b/ui/base/abstract-select.meta @@ -59,10 +59,10 @@ } } }, - "multiSelect_property": { + "allowsMultipleSelection_property": { "prototype": "core/meta/property-descriptor", "values": { - "name": "multiSelect", + "name": "allowsMultipleSelection", "valueType": "boolean", "objectDescriptor": { "@": "root" @@ -99,7 +99,7 @@ "@": "values_property" }, { - "@": "multiSelect_property" + "@": "allowsMultipleSelection_property" } ], "propertyDescriptorGroups": { @@ -123,7 +123,7 @@ "@": "values_property" }, { - "@": "multiSelect_property" + "@": "allowsMultipleSelection_property" } ] }, From 4513dd08b0c5d9cedaec1e3a65450cae834cb9ae Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Fri, 22 Jun 2018 17:13:59 -0400 Subject: [PATCH 33/65] Fix typo --- core/drag/drag-event.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index 25a616d72b..4edff0ee3d 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -121,7 +121,7 @@ if (typeof window !== "undefined") { } }, - dragabblePlaceholderStrategy: { + draggablePlaceholderStrategy: { value: 'hidden' }, From 64c2ff55e485e21a6ffa1d35d98730f0fe0d4a04 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 13:13:44 -0400 Subject: [PATCH 34/65] Performance improvement --- core/drag/drag-manager.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index a6c4dba6a7..94924da12f 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -1009,8 +1009,13 @@ var DragManager = exports.DragManager = Montage.specialize({ } } - draggedImage.style[DragManager.cssTransform] = "translate3d(" + - translateX + "px," + translateY + "px,0)"; + var translate = "translate3d("; + translate += translateX; + translate += "px,"; + translate += translateY; + translate += "px,0)"; + + draggedImage.style[DragManager.cssTransform] = translate; this._scrollIfNeeded( draggingOperationContext.positionX, From 369544190aacd565b82f7d36e465aa8539fb5b52 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 13:26:51 -0400 Subject: [PATCH 35/65] Refactor Drag & Drop class names --- core/drag/drag-manager.js | 26 +++++++++++-------- .../sample/ui/drop-inner.reel/drop-inner.css | 8 +++--- .../sample/ui/drop-outer.reel/drop-outer.css | 10 +++---- .../drag.info/sample/ui/drop.reel/drop.css | 9 +++---- .../drag.info/sample/ui/main.reel/main.css | 6 ++++- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 94924da12f..8fe3ec6094 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -336,7 +336,7 @@ var DragManager = exports.DragManager = Montage.specialize({ this._draggingOperationContext.candidateDropTargets.forEach( function (droppable) { - droppable.classList.add('accept-dragged-image'); + droppable.classList.add('valid-drop-target'); } ); @@ -354,7 +354,7 @@ var DragManager = exports.DragManager = Montage.specialize({ _dispatchDragEnd: { value: function (draggingOperationContext) { draggingOperationContext.candidateDropTargets.forEach(function (droppable) { - droppable.classList.remove('accept-dragged-image'); + droppable.classList.remove('valid-drop-target'); }); if (draggingOperationContext.draggable) { @@ -377,8 +377,8 @@ var DragManager = exports.DragManager = Montage.specialize({ _dispatchDrop: { value: function (draggingOperationContext) { if (this._dropDestination) { - this._dropDestination.classList.remove("dragged-image-entered"); - this._dropDestination.classList.remove("dragged-image-over"); + this._dropDestination.classList.remove("drag-enter"); + this._dropDestination.classList.remove("drag-over"); this._dropDestination.dispatchEvent(this._createDragEvent( "drop", draggingOperationContext @@ -395,7 +395,7 @@ var DragManager = exports.DragManager = Montage.specialize({ _dispatchDragEnter: { value: function (draggingOperationContext) { if (this._dropDestination) { - this._dropDestination.classList.add("dragged-image-entered"); + this._dropDestination.classList.add("drag-enter"); var dragEnterEvent = this._createDragEvent( "dragenter", draggingOperationContext ); @@ -416,7 +416,7 @@ var DragManager = exports.DragManager = Montage.specialize({ _dispatchDragOver: { value: function (draggingOperationContext) { if (this._dropDestination) { - this._dropDestination.classList.add("dragged-image-over"); + this._dropDestination.classList.add("drag-over"); var dragOverEvent = this._createDragEvent( "dragover", draggingOperationContext ); @@ -439,8 +439,8 @@ var DragManager = exports.DragManager = Montage.specialize({ _dispatchDragLeave: { value: function (draggingOperationContext) { if (this._dropDestination) { - this._dropDestination.classList.remove("dragged-image-over"); - this._dropDestination.classList.remove("dragged-image-entered"); + this._dropDestination.classList.remove("drag-over"); + this._dropDestination.classList.remove("drag-enter"); this._dropDestination.dispatchEvent(this._createDragEvent( "dragleave", draggingOperationContext @@ -894,9 +894,13 @@ var DragManager = exports.DragManager = Montage.specialize({ droppable ) ) { + droppable.classList.add('invalid-drop-target'); + this._invalidDroppable = droppable; droppable = null; - this._cursorStyle = NOT_ALLOWED_CURSOR; - } + } else if (this._invalidDroppable) { + this._invalidDroppable.classList.remove('invalid-drop-target'); + this._invalidDroppable = null; + } if (draggable) { draggable.dispatchEvent(this._createDragEvent( @@ -1091,7 +1095,7 @@ var DragManager = exports.DragManager = Montage.specialize({ ); placeholderElement.style.boxSizing = "border-box"; placeholderElement.classList.add( - 'montage-draggable-placeholder' + 'montage-drag-placeholder' ); draggableElement.parentNode.insertBefore( diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css index 06d2d63eb3..fca84730e7 100644 --- a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.css @@ -4,22 +4,22 @@ left: 5px; content: "inner"; } -.Drop.DropInner.accept-dragged-image { +.Drop.DropInner.valid-drop-target { border: 4px solid #34495e; animation: none; } -.Drop.DropInner.accept-dragged-image.is-empty .drop-placeholder { +.Drop.DropInner.valid-drop-target.is-empty .drop-placeholder { color:#34495e; animation: none; } -.Drop.DropInner.dragged-image-over.is-empty .drop-placeholder { +.Drop.DropInner.drag-over.is-empty .drop-placeholder { color:#3498db; animation: none; } -.Drop.DropInner.dragged-image-over { +.Drop.DropInner.drag-over { border: 4px solid #3498db; animation: none; } diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css index aa74fc37ba..8ad4a58c12 100644 --- a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.css @@ -11,22 +11,22 @@ content: "outer"; } -.Drop.DropOuter.accept-dragged-image { +.Drop.DropOuter.valid-drop-target { border: 4px solid #34495e; animation: none; } -.Drop.DropOuter.accept-dragged-image.is-empty .drop-placeholder { +.Drop.DropOuter.valid-drop-target.is-empty .drop-placeholder { color:#34495e; animation: none; } -.Drop.DropOuter.dragged-image-over.is-empty .drop-placeholder { +.Drop.DropOuter.drag-over.is-empty .drop-placeholder { color:#3498db; animation: none; } -.Drop.DropOuter.dragged-image-over { +.Drop.DropOuter.drag-over { border: 4px solid #3498db; animation: none; -} \ No newline at end of file +} diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.css b/core/drag/drag.info/sample/ui/drop.reel/drop.css index 29d6c222eb..1cfd2b10bf 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.css +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.css @@ -29,22 +29,22 @@ display: block; } -.Drop.accept-dragged-image { +.Drop.valid-drop-target { border: 4px dashed #3498db25; animation: blink 1.5s linear infinite alternate; } -.Drop.accept-dragged-image.is-empty .drop-placeholder { +.Drop.valid-drop-target.is-empty .drop-placeholder { color:#3498db25; animation: blink 1.5s linear infinite alternate; } -.Drop.dragged-image-over.is-empty .drop-placeholder { +.Drop.drag-over.is-empty .drop-placeholder { color:#3498db; animation: none; } -.Drop.dragged-image-over { +.Drop.drag-over { border: 4px solid #3498db; animation: none; } @@ -52,4 +52,3 @@ @keyframes blink { 50% { border-color: #3498db; color: #3498db } } - diff --git a/core/drag/drag.info/sample/ui/main.reel/main.css b/core/drag/drag.info/sample/ui/main.reel/main.css index 04276c3e95..7155d2d735 100644 --- a/core/drag/drag.info/sample/ui/main.reel/main.css +++ b/core/drag/drag.info/sample/ui/main.reel/main.css @@ -74,7 +74,7 @@ h4 { margin-left: 8px; } -.samples .montage-draggable-placeholder { +.samples .montage-drag-placeholder { border: 2px dashed #9b59b6; } @@ -100,3 +100,7 @@ h4 { border-radius: 25px; background: #9b59b6; } + +.invalid-drop-target { + cursor: not-allowed; +} From 8509b4f8b656ad25d554088a5b2a04bac0e0ada0 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 13:27:05 -0400 Subject: [PATCH 36/65] Add some comments --- core/drag/drag-event.js | 1 + core/drag/drag-manager.js | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index 4edff0ee3d..3f60d0d12b 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -260,6 +260,7 @@ if (typeof window !== "undefined") { */ fromDataTransfer: { value: function (dataTransfer) { + // can't be re used it for security purposes. var montageDataTransfer = new DataTransfer(); montageDataTransfer.items = dataTransfer.items; diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 8fe3ec6094..be03a525e5 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -533,10 +533,10 @@ var DragManager = exports.DragManager = Montage.specialize({ var element = document.elementFromPoint(positionX, positionY), component = null; - if (element) { - while (element && !(component = element.component)) { - element = element.parentElement; - } + // that is done at several place in the framework + // we should re-organize that + while (element && !(component = element.component)) { + element = element.parentElement; } return component; @@ -690,6 +690,7 @@ var DragManager = exports.DragManager = Montage.specialize({ captureDragenter: { value: function (event) { + // check if event._event it's an instance of the custom dragEvent instead of checking if types contains files. if (!this._draggingOperationContext) { var types = event.dataTransfer.types; @@ -752,7 +753,6 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, - // maybe not needed here captureDrop: { value: function (event) { event.preventDefault(); From f011da41980c0a7c116149d6e5b6e51712c19a9e Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 13:28:42 -0400 Subject: [PATCH 37/65] Renames candidateDropTargets to dropTargetCandidates --- core/drag/drag-event.js | 8 ++++---- core/drag/drag-manager.js | 10 +++++----- .../drag.info/sample/ui/drop-file.reel/drop-file.js | 2 +- .../drag.info/sample/ui/drop-inner.reel/drop-inner.js | 2 +- .../drag.info/sample/ui/drop-outer.reel/drop-outer.js | 2 +- core/drag/drag.info/sample/ui/drop.reel/drop.js | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index 3f60d0d12b..b0ac87c0e4 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -109,15 +109,15 @@ if (typeof window !== "undefined") { value: null }, - _candidateDropTargets: { + _dropTargetCandidates: { value: null, enumerable: false }, - candidateDropTargets: { + dropTargetCandidates: { get: function () { - return this._candidateDropTargets || - (this._candidateDropTargets = new Set()); + return this._dropTargetCandidates || + (this._dropTargetCandidates = new Set()); } }, diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index be03a525e5..cea30e4609 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -330,11 +330,11 @@ var DragManager = exports.DragManager = Montage.specialize({ this._rootComponent.application.dispatchEvent(dragStartEvent); } - this._draggingOperationContext.candidateDropTargets = ( - dragStartEvent.dataTransfer.candidateDropTargets + this._draggingOperationContext.dropTargetCandidates = ( + dragStartEvent.dataTransfer.dropTargetCandidates ); - this._draggingOperationContext.candidateDropTargets.forEach( + this._draggingOperationContext.dropTargetCandidates.forEach( function (droppable) { droppable.classList.add('valid-drop-target'); } @@ -353,7 +353,7 @@ var DragManager = exports.DragManager = Montage.specialize({ */ _dispatchDragEnd: { value: function (draggingOperationContext) { - draggingOperationContext.candidateDropTargets.forEach(function (droppable) { + draggingOperationContext.dropTargetCandidates.forEach(function (droppable) { droppable.classList.remove('valid-drop-target'); }); @@ -890,7 +890,7 @@ var DragManager = exports.DragManager = Montage.specialize({ ); if (droppable && - !draggingOperationContext.candidateDropTargets.has( + !draggingOperationContext.dropTargetCandidates.has( droppable ) ) { diff --git a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js index bf9872f338..0539c505d4 100644 --- a/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js +++ b/core/drag/drag.info/sample/ui/drop-file.reel/drop-file.js @@ -35,7 +35,7 @@ exports.DropFile = Component.specialize(/** @lends DropFile# */ { event.dataTransfer.types.indexOf('Files') > -1); if (shouldAccept) { - event.dataTransfer.candidateDropTargets.add(this); + event.dataTransfer.dropTargetCandidates.add(this); this._addEventListeners(); } } diff --git a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js index d12a69b8b8..ef1972ba74 100644 --- a/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js +++ b/core/drag/drag.info/sample/ui/drop-inner.reel/drop-inner.js @@ -27,7 +27,7 @@ exports.DropInner = Component.specialize(/** @lends DropInner# */ { handleDragstart: { value: function (event) { - event.dataTransfer.candidateDropTargets.add(this); + event.dataTransfer.dropTargetCandidates.add(this); this._addEventListeners(); } }, diff --git a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js index 0935c73749..9c440d0c2e 100644 --- a/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js +++ b/core/drag/drag.info/sample/ui/drop-outer.reel/drop-outer.js @@ -27,7 +27,7 @@ exports.DropOuter = Component.specialize(/** @lends DropOuter# */ { handleDragstart: { value: function (event) { - event.dataTransfer.candidateDropTargets.add(this); + event.dataTransfer.dropTargetCandidates.add(this); this._addEventListeners(); } }, diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.js b/core/drag/drag.info/sample/ui/drop.reel/drop.js index 5994257771..f9a475238f 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.js +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.js @@ -45,7 +45,7 @@ exports.Drop = Component.specialize(/** @lends Drop# */ { } if (shouldAddToCandidate) { - event.dataTransfer.candidateDropTargets.add(this); + event.dataTransfer.dropTargetCandidates.add(this); this._addEventListeners(); } } From 0e11590446884de22add4b36e2a60abc6a3a7594 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 14:00:27 -0400 Subject: [PATCH 38/65] Add draggedObject to the DataTransfer --- core/drag/drag-event.js | 11 +++++++++++ core/drag/drag.info/sample/ui/drop.reel/drop.js | 2 ++ core/drag/drag.info/sample/ui/square.reel/square.js | 2 ++ 3 files changed, 15 insertions(+) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index b0ac87c0e4..b4a4830962 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -4,6 +4,8 @@ var MutableEvent = require("../event/mutable-event").MutableEvent, // XXX Does not presently function server-side if (typeof window !== "undefined") { + var OBJECT_MINE_TYPE = 'application/object'; + var DataTransfer = exports.DataTransfer = Montage.specialize({ __data: { @@ -125,6 +127,15 @@ if (typeof window !== "undefined") { value: 'hidden' }, + draggedObject: { + set: function (object) { + this._data.set(OBJECT_MINE_TYPE, object); + }, + get: function () { + return this._data.get(OBJECT_MINE_TYPE); + } + }, + clearData: { value: function () { return this._data.clear(); diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.js b/core/drag/drag.info/sample/ui/drop.reel/drop.js index f9a475238f..59159742d8 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.js +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.js @@ -69,6 +69,8 @@ exports.Drop = Component.specialize(/** @lends Drop# */ { } } } + + console.log(event.dataTransfer.draggedObject) } }, diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js index 86f4d185ab..d95e73f403 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.js +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -49,6 +49,8 @@ exports.Square = Component.specialize(/** @lends Square# */ { this.draggableContainer = null; } + event.dataTransfer.draggedObject = { secret: "montage" }; + if (this.enableVisiblePlaceholder) { event.dataTransfer.draggablePlaceholderStrategy = "visible"; } From 9e8f1be8280e5bf8825bbd8fdcc218701960c285 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 14:00:40 -0400 Subject: [PATCH 39/65] Remove unused code --- core/drag/drag-manager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index cea30e4609..f4791ac770 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -7,7 +7,6 @@ var Montage = require("../core").Montage, var DRAGGABLE = 0; var DROPABBLE = 1; var TOUCH_POINTER = "touch"; -var NOT_ALLOWED_CURSOR = "not-allowed"; var PX = "px"; var DragManager = exports.DragManager = Montage.specialize({ From 7ce671d85da695bedbe2682afb631e1d5e5963f3 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 14:07:23 -0400 Subject: [PATCH 40/65] Rename dragabblePlaceholderStrategy to showPlaceholder --- core/drag/drag-event.js | 4 ++-- core/drag/drag-manager.js | 16 +++++++--------- .../drag.info/sample/ui/square.reel/square.js | 2 +- core/drag/dragging-operation-context.js | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index b4a4830962..d067ed37d9 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -123,8 +123,8 @@ if (typeof window !== "undefined") { } }, - draggablePlaceholderStrategy: { - value: 'hidden' + showPlaceholder: { + value: false }, draggedObject: { diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index f4791ac770..65605bb391 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -806,8 +806,8 @@ var DragManager = exports.DragManager = Montage.specialize({ this._draggingOperationContext.dataTransfer = dragStartEvent.dataTransfer; this._draggingOperationContext.dragEffect = dragStartEvent.dataTransfer.dragEffect; - this._draggingOperationContext.draggablePlaceholderStrategy = ( - dragStartEvent.dataTransfer.draggablePlaceholderStrategy + this._draggingOperationContext.showPlaceholder = ( + dragStartEvent.dataTransfer.showPlaceholder ); if (!(draggedImage = dragStartEvent.dataTransfer.getDragImage())) { @@ -1055,7 +1055,9 @@ var DragManager = exports.DragManager = Montage.specialize({ this._shouldRemovePlaceholder = true; this._rootComponent.needsDraw = true; // Wait for the next draw cycle to remove the placeholder, - // allowing the receiver to perform any necessary clean-up. + // or in order to be synchronised with the draw cyle when + // the draggable component will become visible again. + // Plus it allows the receiver to perform any necessary clean-up. return void 0; } else { this._draggingOperationContext = null; @@ -1082,9 +1084,7 @@ var DragManager = exports.DragManager = Montage.specialize({ this._oldDraggableDisplayStyle = draggableElement.style.display; draggableElement.style.display = 'none'; - if ( - draggingOperationContext.draggablePlaceholderStrategy === "visible" - ) { + if (draggingOperationContext.showPlaceholder) { var placeholderElement = document.createElement('div'); placeholderElement.style.width = ( draggedImageBoundingRect.width + PX @@ -1123,9 +1123,7 @@ var DragManager = exports.DragManager = Montage.specialize({ var draggableElement = draggingOperationContext.draggable.element; draggableElement.style.display = this._oldDraggableDisplayStyle; - if ( - draggingOperationContext.draggablePlaceholderStrategy === "visible" - ) { + if (draggingOperationContext.showPlaceholder) { draggableElement.parentNode.removeChild( this._placeholderElement ); diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js index d95e73f403..a0962f8cc7 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.js +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -52,7 +52,7 @@ exports.Square = Component.specialize(/** @lends Square# */ { event.dataTransfer.draggedObject = { secret: "montage" }; if (this.enableVisiblePlaceholder) { - event.dataTransfer.draggablePlaceholderStrategy = "visible"; + event.dataTransfer.showPlaceholder = true; } event.dataTransfer.setData("text/plain", this.value); diff --git a/core/drag/dragging-operation-context.js b/core/drag/dragging-operation-context.js index 9d9724a303..36d12fb8a8 100644 --- a/core/drag/dragging-operation-context.js +++ b/core/drag/dragging-operation-context.js @@ -34,8 +34,8 @@ exports.DraggingOperationContext = Montage.specialize({ value: 0 }, - dragabblePlaceholderStrategy: { - value: 'hidden' + showPlaceholder: { + value: false }, dragEffect: { From 196d98bfad9910ed80b8cd204831952464427ea0 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 14:59:42 -0400 Subject: [PATCH 41/65] Can specified the x and y offset for the dragged image --- core/drag/drag-event.js | 16 +++++++++ core/drag/drag-manager.js | 34 +++++++++++++++++-- .../drag.info/sample/ui/square.reel/square.js | 20 +++++++---- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index d067ed37d9..faeaa8adb3 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -160,10 +160,26 @@ if (typeof window !== "undefined") { } }, + dragImageXOffset: { + value: null + }, + + dragImageYOffset: { + value: null + }, + setDragImage: { value: function (img, xOffset, yOffset) { if (!this._dragImage) { this._dragImage = img; + + if (xOffset >= 0) { + this.dragImageXOffset = xOffset; + } + + if (yOffset >= 0) { + this.dragImageYOffset = yOffset; + } } } }, diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 65605bb391..366696f53b 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -1073,12 +1073,40 @@ var DragManager = exports.DragManager = Montage.specialize({ var draggingOperationContext = this._draggingOperationContext; if (!draggedImage.parentElement) { - var draggedImageBoundingRect = this._draggedImageBoundingRect; - draggedImage.style.top = draggedImageBoundingRect.top + PX; - draggedImage.style.left = draggedImageBoundingRect.left + PX; + var draggedImageBoundingRect = this._draggedImageBoundingRect, + top = 0, left = 0; draggedImage.style.width = draggedImageBoundingRect.width + PX; draggedImage.style.height = draggedImageBoundingRect.height + PX; + + if (draggingOperationContext.dataTransfer.dragImageXOffset !== null) { + left = draggingOperationContext.startPositionX; + + if (draggingOperationContext.dataTransfer.dragImageXOffset > draggedImageBoundingRect.width) { + left -= draggedImageBoundingRect.width; + } else { + left -= draggingOperationContext.dataTransfer.dragImageXOffset; + } + + } else { + left = draggedImageBoundingRect.left; + } + + if (draggingOperationContext.dataTransfer.dragImageXOffset !== null) { + top = draggingOperationContext.startPositionY; + + if (draggingOperationContext.dataTransfer.dragImageYOffset > draggedImageBoundingRect.height) { + top -= draggedImageBoundingRect.height; + } else { + top -= draggingOperationContext.dataTransfer.dragImageYOffset; + } + } else { + top = draggedImageBoundingRect.top; + } + + draggedImage.style.top = top + PX; + draggedImage.style.left = left + PX; + if (draggingOperationContext.dragEffect === "move") { var draggableElement = draggingOperationContext.draggable.element; this._oldDraggableDisplayStyle = draggableElement.style.display; diff --git a/core/drag/drag.info/sample/ui/square.reel/square.js b/core/drag/drag.info/sample/ui/square.reel/square.js index a0962f8cc7..96fdc9c617 100644 --- a/core/drag/drag.info/sample/ui/square.reel/square.js +++ b/core/drag/drag.info/sample/ui/square.reel/square.js @@ -59,14 +59,20 @@ exports.Square = Component.specialize(/** @lends Square# */ { if (this.switchDraggedImage) { var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), - circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); + rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + + svg.style.height = "50px"; + svg.style.width = "50px"; - circle.setAttributeNS(null, 'cx', 25); - circle.setAttributeNS(null, 'cy', 25); - circle.setAttributeNS(null, 'r', 25); - circle.setAttributeNS(null, 'style', 'fill: #e74c3c;'); - svg.appendChild(circle); - event.dataTransfer.setDragImage(svg, 50, 50); + rect.setAttributeNS(null, 'x', 0); + rect.setAttributeNS(null, 'y', 0); + rect.setAttributeNS(null, 'width', 50); + rect.setAttributeNS(null, 'height', 50); + rect.setAttributeNS(null, 'style', 'fill: #e74c3c;'); + + svg.appendChild(rect); + + event.dataTransfer.setDragImage(svg, 25, 25); // center } } } From 20cbcd8726ac9c3f75512739c01b650b4aab5914 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Sun, 24 Jun 2018 15:08:58 -0400 Subject: [PATCH 42/65] Cleaning up --- core/drag/drag-manager.js | 71 ++++++++++++------------- core/drag/dragging-operation-context.js | 8 +++ 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 366696f53b..852ca054b0 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -31,10 +31,6 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, - _dropDestination: { - value: null - }, - __rootComponent: { value: null }, @@ -85,10 +81,6 @@ var DragManager = exports.DragManager = Montage.specialize({ value: null }, - _isDragging: { - value: false - }, - _willTerminateDraggingOperation: { value: false }, @@ -375,11 +367,11 @@ var DragManager = exports.DragManager = Montage.specialize({ */ _dispatchDrop: { value: function (draggingOperationContext) { - if (this._dropDestination) { - this._dropDestination.classList.remove("drag-enter"); - this._dropDestination.classList.remove("drag-over"); + if (draggingOperationContext.currentDropTarget) { + draggingOperationContext.currentDropTarget.classList.remove("drag-enter"); + draggingOperationContext.currentDropTarget.classList.remove("drag-over"); - this._dropDestination.dispatchEvent(this._createDragEvent( + draggingOperationContext.currentDropTarget.dispatchEvent(this._createDragEvent( "drop", draggingOperationContext )); } @@ -393,13 +385,13 @@ var DragManager = exports.DragManager = Montage.specialize({ */ _dispatchDragEnter: { value: function (draggingOperationContext) { - if (this._dropDestination) { - this._dropDestination.classList.add("drag-enter"); + if (draggingOperationContext.currentDropTarget) { + draggingOperationContext.currentDropTarget.classList.add("drag-enter"); var dragEnterEvent = this._createDragEvent( "dragenter", draggingOperationContext ); - this._dropDestination.dispatchEvent(dragEnterEvent); + draggingOperationContext.currentDropTarget.dispatchEvent(dragEnterEvent); draggingOperationContext.dropEffect = ( dragEnterEvent.dataTransfer.dropEffect || "default" ); @@ -414,13 +406,13 @@ var DragManager = exports.DragManager = Montage.specialize({ */ _dispatchDragOver: { value: function (draggingOperationContext) { - if (this._dropDestination) { - this._dropDestination.classList.add("drag-over"); + if (draggingOperationContext.currentDropTarget) { + draggingOperationContext.currentDropTarget.classList.add("drag-over"); var dragOverEvent = this._createDragEvent( "dragover", draggingOperationContext ); - this._dropDestination.dispatchEvent(dragOverEvent); + draggingOperationContext.currentDropTarget.dispatchEvent(dragOverEvent); draggingOperationContext.dropEffect = ( dragOverEvent.dataTransfer.dropEffect || "default" ); @@ -437,11 +429,11 @@ var DragManager = exports.DragManager = Montage.specialize({ */ _dispatchDragLeave: { value: function (draggingOperationContext) { - if (this._dropDestination) { - this._dropDestination.classList.remove("drag-over"); - this._dropDestination.classList.remove("drag-enter"); + if (draggingOperationContext.currentDropTarget) { + draggingOperationContext.currentDropTarget.classList.remove("drag-over"); + draggingOperationContext.currentDropTarget.classList.remove("drag-enter"); - this._dropDestination.dispatchEvent(this._createDragEvent( + draggingOperationContext.currentDropTarget.dispatchEvent(this._createDragEvent( "dragleave", draggingOperationContext )); } @@ -606,7 +598,7 @@ var DragManager = exports.DragManager = Montage.specialize({ this._removeTranslateListeners(); this._removeDragListeners(); this._dragEnterCounter = 0; - this._isDragging = false; + this._draggingOperationContext.isDragging = false; this.__translateComposer.translateX = 0; this.__translateComposer.translateY = 0; this._oldDraggableDisplayStyle = null; @@ -714,7 +706,7 @@ var DragManager = exports.DragManager = Montage.specialize({ ); this._addDragListeners(); - this._isDragging = true; + draggingOperationContext.isDragging = true; this._rootComponent.needsDraw = true; } } @@ -725,7 +717,7 @@ var DragManager = exports.DragManager = Montage.specialize({ captureDragover: { value: function (event) { - if (this._dropDestination) { + if (this._draggingOperationContext.currentDropTarget) { event.preventDefault(); } @@ -819,7 +811,7 @@ var DragManager = exports.DragManager = Montage.specialize({ ); this._addTranslateListeners(); - this._isDragging = true; + draggingOperationContext.isDragging = true; this._rootComponent.needsDraw = true; } else { this._translateComposer._cancel(); @@ -850,7 +842,7 @@ var DragManager = exports.DragManager = Montage.specialize({ handleTranslateCancel: { value: function () { - this._dropDestination = null; + this.draggingOperationContext.currentDropTarget = null; this._willTerminateDraggingOperation = true; this._rootComponent.needsDraw = true; } @@ -864,8 +856,9 @@ var DragManager = exports.DragManager = Montage.specialize({ value: function () { var draggingOperationContext; - if (this._isDragging && - (draggingOperationContext = this._draggingOperationContext) + if ( + (draggingOperationContext = this._draggingOperationContext) && + draggingOperationContext.isDragging ) { var draggable = draggingOperationContext.draggable; @@ -907,14 +900,14 @@ var DragManager = exports.DragManager = Montage.specialize({ )); } - if (droppable !== this._dropDestination) { - if (this._dropDestination) { + if (droppable !== draggingOperationContext.currentDropTarget) { + if (draggingOperationContext.currentDropTarget) { this._dispatchDragLeave( draggingOperationContext ); } - this._dropDestination = droppable; + draggingOperationContext.currentDropTarget = droppable; if (droppable) { this._dispatchDragEnter( @@ -926,7 +919,7 @@ var DragManager = exports.DragManager = Montage.specialize({ draggingOperationContext ); } else { - this._dropDestination = null; + draggingOperationContext.currentDropTarget = null; } if (droppable) { @@ -943,7 +936,11 @@ var DragManager = exports.DragManager = Montage.specialize({ value: function () { var draggingOperationContext = this._draggingOperationContext; - if (this._isDragging && !this._willTerminateDraggingOperation) { + if ( + draggingOperationContext && + draggingOperationContext.isDragging && + !this._willTerminateDraggingOperation + ) { var draggedImage = draggingOperationContext.draggedImage; if (draggedImage) { @@ -1035,9 +1032,9 @@ var DragManager = exports.DragManager = Montage.specialize({ document.body.removeChild(draggingOperationContext.draggedImage); } - if (this._dropDestination) { + if (draggingOperationContext.currentDropTarget) { draggingOperationContext.hasBeenDrop = true; - draggingOperationContext.droppable = this._dropDestination; + draggingOperationContext.droppable = draggingOperationContext.currentDropTarget; } this._dispatchDrop( @@ -1045,7 +1042,7 @@ var DragManager = exports.DragManager = Montage.specialize({ ); this._resetTranslateContext(); - this._dropDestination = null; + draggingOperationContext.currentDropTarget = null; this._dispatchDragEnd(draggingOperationContext); if ( diff --git a/core/drag/dragging-operation-context.js b/core/drag/dragging-operation-context.js index 36d12fb8a8..e90368dc90 100644 --- a/core/drag/dragging-operation-context.js +++ b/core/drag/dragging-operation-context.js @@ -60,6 +60,14 @@ exports.DraggingOperationContext = Montage.specialize({ dragTarget: { value: null + }, + + currentDropTarget: { + value: null + }, + + _isDragging: { + value: false } }); From a2014c4490b5330e6431208643b768f4aafa0989 Mon Sep 17 00:00:00 2001 From: thibault zanini Date: Mon, 25 Jun 2018 11:29:49 -0400 Subject: [PATCH 43/65] Better checking for outside drag & drop --- core/drag/drag-manager.js | 44 ++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 852ca054b0..d1509ecfad 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -681,34 +681,30 @@ var DragManager = exports.DragManager = Montage.specialize({ captureDragenter: { value: function (event) { - // check if event._event it's an instance of the custom dragEvent instead of checking if types contains files. - if (!this._draggingOperationContext) { - var types = event.dataTransfer.types; + if (!this._draggingOperationContext && !(event instanceof DragEvent)) { + var types = event.dataTransfer.types, + draggingOperationContext; - if (types.indexOf("Files") > -1) { - var draggingOperationContext; - - this._draggingOperationContext = (draggingOperationContext = ( - this._createDraggingOperationContextWithDraggableAndPosition( - null, - event - ) - )); + this._draggingOperationContext = (draggingOperationContext = ( + this._createDraggingOperationContextWithDraggableAndPosition( + null, + event + ) + )); - draggingOperationContext.dataTransfer = ( - DataTransfer.fromDataTransfer(event.dataTransfer) - ); + draggingOperationContext.dataTransfer = ( + DataTransfer.fromDataTransfer(event.dataTransfer) + ); - var dragStartEvent = this._dispatchDragStart(); + var dragStartEvent = this._dispatchDragStart(); - draggingOperationContext.dragEffect = ( - dragStartEvent.dataTransfer.dragEffect - ); - - this._addDragListeners(); - draggingOperationContext.isDragging = true; - this._rootComponent.needsDraw = true; - } + draggingOperationContext.dragEffect = ( + dragStartEvent.dataTransfer.dragEffect + ); + + this._addDragListeners(); + draggingOperationContext.isDragging = true; + this._rootComponent.needsDraw = true; } this._dragEnterCounter++; From 70ab8446931c6e5cfdfe1f9ecfbc5b7b0825a98c Mon Sep 17 00:00:00 2001 From: Harold Thetiot Date: Mon, 25 Jun 2018 20:05:03 -0700 Subject: [PATCH 44/65] fix montage@17.2.1: wanted: {"node":"=<4.x","npm":"=<2.x"} (current: {"node":"4.9.1","npm":"2.15.11"}) --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 705a8dfb36..df6ac76bd0 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ }, "main": "montage", "engines": { - "node": "=<4.x", - "npm": "=<2.x" + "node": "<=4.9.1", + "npm": "<=2.15.11" }, "overlay": { "browser": { From 7009a4268a95aeeadab1ffdc7d5684148ace8f4d Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Thu, 28 Jun 2018 16:03:59 -0400 Subject: [PATCH 45/65] Refactor the swipe composer. --- composer/swipe-composer.js | 551 ++++++++++++++++++++++++++----------- 1 file changed, 384 insertions(+), 167 deletions(-) diff --git a/composer/swipe-composer.js b/composer/swipe-composer.js index 099e023be8..e1e4dcbc4a 100644 --- a/composer/swipe-composer.js +++ b/composer/swipe-composer.js @@ -4,235 +4,452 @@ * @requires montage/composer/composer */ var Montage = require("../core/core").Montage, - Composer = require("./composer").Composer; + Composer = require("./composer").Composer, + MutableEvent = require("../core/event/mutable-event").MutableEvent, + TranslateComposer = require("./translate-composer").TranslateComposer; -/** - * @class SwipeComposer - * @classdesc `Composer` for detecting swipe gestures. - * @extends Composer - */ -exports.SwipeComposer = Composer.specialize( /** @lends SwipeComposer# */ { +var DIRECTION_LEFT = 'left', + DIRECTION_RIGHT = 'right', + DIRECTION_UP = 'up', + DIRECTION_DOWN = 'down', + SWIPE = 'swipe'; - load: { - value: function () { - document.addEventListener("touchstart", this, true); - } +var SwipeEvent = exports.SwipeEvent = MutableEvent.specialize({ + + /** + * @public + * @type {String} + * @default "swipe" + * @description Name of the swipe event. + * + * Possible values: + * - "swipe" + * - "swipeUp" + * - "swipeRight" + * - "swipeDown" + * - "swipeLeft" + */ + type: { + value: SWIPE }, - unload: { - value: function () { - document.removeEventListener("touchstart", this, true); + _event: { + enumerable: false, + value: null + }, + + event: { + get: function () { + return this._event; + }, + set: function (value) { + this._event = value; } }, - _startX: { - enumerable: false, - value: 0 + bubbles: { + value: true }, - _startY: { - enumerable: false, - value: 0 + /** + * @public + * @type {String} + * @default null + * @description The direction of a swipe gesture. + * Possible values: + * - "up" + * - "right" + * - "down" + * - "left" + */ + direction: { + value: null }, - _deltaX: { - enumerable: false, - value: 0 + /** + * @public + * @type {Number} + * @default null + * @description The angle of a swipe gesture. + */ + angle: { + value: null }, - _deltaY: { - enumerable: false, - value: 0 + /** + * @public + * @type {Number} + * @default null + * @description The distance traveled of a swipe gesture. + */ + distance: { + value: null + }, + + /** + * @public + * @type {Number} + * @default null + * @description The velocity of a swipe gesture. + */ + velocity: { + value: null + }, + + /** + * @public + * @type {Number} + * @default null + * @description Start x coordinate of a swipe gesture. + */ + startPositionX: { + value: null + }, + + /** + * @public + * @type {Number} + * @default null + * @description Start y coordinate of a swipe gesture. + */ + startPositionY: { + value: null + }, + + /** + * @public + * @type {Number} + * @default null + * @description End x coordinate of a swipe gesture. + */ + endPositionX: { + value: null }, /** - * The number of pixels a gesture must continue to be recognized as a - * swipe. - * @type {number} + * @public + * @type {Number} + * @default null + * @description End y coordinate of a swipe gesture. */ - _threshold: { - enumerable: false, - value: 50 + endPositionY: { + value: null + }, + + constructor: { + value: function (type, eventInit) { + this._event = new CustomEvent(type, eventInit); + this.type = type; + } + } + +}); + +/** + * @class SwipeComposer + * @classdesc `Composer` for detecting swipe gestures. + * @extends Composer + */ +exports.SwipeComposer = Composer.specialize( /** @lends SwipeComposer# */ { + + /** + * @private + * @type {Number} + * @default null + * @description Start x coordinate of a swipe gesture. + */ + _startPositionX: { + value: null }, /** - * The maximum angle (in degrees) away from horizontal or vertical - * for a gesture to be recognized as a swipe. - * @type {number} + * @private + * @type {Number} + * @default null + * @description Start y coordinate of a swipe gesture. */ - _thresholdSwipeAngle: { - enumerable: false, - value: 20 + _startPositionY: { + value: null }, + /** + * @private + * @type {Number} + * @default null + * @description Start Timestamp of a swipe gesture. + */ _startTimestamp: { - enumerable: false, - value: 0 + value: null }, - captureTouchstart: { - value: function (event) { - this._reset(); - var touches = event.touches, - touch = touches[0]; - this._startX = touch.clientX; - this._startY = touch.clientY; - this._startTimestamp = event.timeStamp; - document.addEventListener("touchmove", this, true); - document.addEventListener("touchend", this, true); - document.addEventListener("touchcancel", this, true); + __translateComposer: { + value: null + }, + + /** + * @private + * @typedef {Object} TranslateComposer + * @readOnly + * @default null + * @description SwipeComposer's translate composer. + */ + _translateComposer: { + get: function () { + if (!this.__translateComposer) { + this.__translateComposer = new TranslateComposer(); + this.__translateComposer.hasMomentum = false; + } + + return this.__translateComposer; } }, - _reset: { - enumerable: false, + /** + * @public + * @type {Number} + * @default 10 + * @description Minimal distance required before recognizing. (px) + */ + minDistance: { + value: 10 + }, + + /** + * @public + * @type {Number} + * @default 0.3 + * @description Minimal velocity required before recognizing.(px per ms) + */ + minVelocity: { + value: 0.3 + }, + + /** + * @public + * @function load + * @description load the swipe composer. + */ + load: { value: function () { - this._startX = 0; - this._startY = 0; - this._deltaX = 0; - this._deltaY = 0; - this._startSwipeAngle = null; + debugger + this.component.addComposerForElement( + this._translateComposer, this.element + ); + this._translateComposer.load(); + this._translateComposer.addEventListener( + "translateStart", this, false + ); } }, - _startSwipeAngle: { - enumerable: false, - value: null + /** + * @public + * @function unload + * @description unload the swipe composer. + */ + unload: { + value: function () { + this.component.unloadComposer(this._translateComposer); + this._translateComposer.unload(); + this._translateComposer.removeEventListener( + "translateStart", this, false + ); + } }, - captureTouchcancel: { + handleTranslateStart: { value: function (event) { - document.removeEventListener("touchmove", this, true); - document.removeEventListener("touchend", this, true); - document.removeEventListener("touchcancel", this, true); + console.log(event) + this._startPositionX = this._translateComposer.pointerStartEventPosition.pageX; + this._startPositionY = this._translateComposer.pointerStartEventPosition.pageY; + this._startTimestamp = event.timeStamp; + this._addTranslateEventListeners(); } }, - captureTouchmove: { + handleTranslateEnd: { value: function (event) { - event.preventDefault(); - var touches = event.changedTouches[0], swipeEvent, direction; - - this._deltaX = touches.clientX - this._startX; - this._deltaY = touches.clientY - this._startY; - - var dX = this._deltaX, - dY = this._deltaY, - threshold = this._threshold, - swipeAngle = this._findSwipeAngle(dX, dY); - - if ( - this._startSwipeAngle !== null && - Math.abs(this._startSwipeAngle - swipeAngle) > this._thresholdSwipeAngle - ) { - //Direction changed; Abort touch - //this.captureTouchcancel(); - this._startSwipeAngle = null; - } - - if (this._startSwipeAngle === null) { - this._startSwipeAngle = swipeAngle; - this._startX = touches.clientX; - this._startY = touches.clientY; - this._deltaX = 0; - this._deltaY = 0; - } - - if (dX > threshold && dY > threshold) { - direction = "DIAGONAL"; - } else if (dX > threshold && dY < threshold) { - if (this._deltaX > 0) { - direction = "RIGHT"; - } else { - direction = "LEFT"; - } - } else if (dX < threshold && dY > threshold) { - if (this._deltaY > 0) { - direction = "DOWN"; - } else { - direction = "UP"; + var distance = this._findDistance( + event.translateX, event.translateY + ); + + debugger + + if (distance >= this.minDistance) { + var velocity = this._findVelocity( + distance, + event.timeStamp - this._startTimestamp + ); + + if (velocity > this.minVelocity) { + var angle = this._findAngle( + 0, 0, event.translateX, event.translateY + ), direction; + + if ( + angle >= 0 && angle <= 45 || + angle >= 315 && angle <= 360 + ) { + direction = DIRECTION_RIGHT; + } else if (angle > 45 && angle < 165) { + direction = DIRECTION_UP; + } else if (angle > 165 && angle < 225) { + direction = DIRECTION_LEFT; + } else { + direction = DIRECTION_DOWN; + } + + this._dispatchSwipeEvent( + distance, velocity, angle, direction + ); } } - if (dX !== 0 || dY !== 0) { - swipeEvent = document.createEvent("CustomEvent"); - swipeEvent.initCustomEvent("swipemove", true, false, null); - swipeEvent.direction = direction; - swipeEvent.angle = this._startSwipeAngle; - swipeEvent.velocity = this._findVelocity((event.timeStamp - this._startTimestamp)); - swipeEvent.startX = this._startX; - swipeEvent.startY = this._startY; - swipeEvent.dX = this._deltaX; - swipeEvent.dY = this._deltaY; - - this.dispatchEvent(swipeEvent); - } + this._resetComposerState(); } }, - _findSwipeAngle: { - enumerable: false, - value: function (dX, dY) { - var swipeAngle = -1 * (Math.atan2(dY, dX) * 180 / 3.14); - return swipeAngle.toFixed(2); + handleTranslateCancel: { + value: function () { + this._resetComposerState(); } }, - captureTouchend: { - value: function (event) { - - if (!event) { - return; + /** + * @private + * @function _findAngle + * @param p1x - start x coordinate + * @param p1y - start y coordinate + * @param p2x - end x coordinate + * @param p2y - end y coordinate + * @description Find the angle of a swipe gesture + * @returns Number + */ + _findAngle: { + value: function (p1x, p1y, p2x, p2y) { + var arctangent = ( + (Math.atan2(p2y - p1y, p2x - p1x) * -180) / Math.PI + ); + + if (arctangent < 0) { + arctangent = 360 + arctangent; } - var deltaX = Math.abs(this._deltaX), - deltaY = Math.abs(this._deltaY), - threshold = this._threshold, - direction, - swipeEvent; + return arctangent; + } + }, - if (deltaX < threshold && deltaY < threshold) { - this.captureTouchcancel(); - return; + /** + * @private + * @function _findVelocity + * @param distance - distance traveled by the swipe gesture. + * @param deltaTime - the time difference between the begining and + * the end of the translate gesture. + * @description Find the velocity of a swipe gesture. + * @returns Number + */ + _findVelocity: { + value: function (distance, deltaTime) { + if (deltaTime > 300) { + return 0; } - document.removeEventListener("touchmove", this, true); + return distance / deltaTime; + } + }, - if (deltaX > threshold && deltaY > threshold) { - direction = "DIAGONAL"; - } else if (deltaX > threshold && deltaY < threshold) { - if (this._deltaX > 0) { - direction = "RIGHT"; - } else { - direction = "LEFT"; - } - } else if (deltaX < threshold && deltaY > threshold) { - if (this._deltaY > 0) { - direction = "DOWN"; - } else { - direction = "UP"; - } - } + /** + * @private + * @function _findDistance + * @param deltaX - the difference between the two x coordinates. + * @param deltaY - the difference between the two y coordinates. + * @description Find the distance of a swipe gesture. + * @returns Number + */ + _findDistance: { + value: function (deltaX, deltaY) { + return Math.sqrt( + (deltaX * deltaX) + + (deltaY * deltaY) + ); + } + }, - swipeEvent = document.createEvent("CustomEvent"); - swipeEvent.initCustomEvent("swipe", true, false, null); - swipeEvent.direction = direction; - swipeEvent.angle = this._startSwipeAngle; - swipeEvent.velocity = this._findVelocity((event.timeStamp - this._startTimestamp)); - swipeEvent.startX = this._startX; - swipeEvent.startY = this._startY; - swipeEvent.dX = this._deltaX; - swipeEvent.dY = this._deltaY; + /** + * @private + * @function _dispatchSwipeEvent + * @param distance - the distance of a swipe gesture. + * @param velocity - the velocity of a swipe gesture. + * @param angle - the angle of a swipe gesture. + * @param direction - the direction of a swipe gesture. + * @description Dispatch two swipe events. + */ + _dispatchSwipeEvent: { + value: function (distance, velocity, angle, direction, endPositionX, endPositionY) { + var swipeEvent = new SwipeEvent(SWIPE), + swipeDirectionEvent = new SwipeEvent( + SWIPE + direction.toCapitalized() + ); + + swipeEvent.distance = swipeDirectionEvent.distance = distance; + swipeEvent.velocity = swipeDirectionEvent.velocity = velocity; + swipeEvent.angle = swipeDirectionEvent.angle = angle; + swipeEvent.direction = swipeDirectionEvent.direction = direction; + swipeEvent.startPositionX = swipeDirectionEvent.startPositionX = this._startPositionX; + swipeEvent.startPositionY = swipeDirectionEvent.startPositionY = this._startPositionY; + swipeEvent.endPositionX = swipeDirectionEvent.endPositionX = endPositionX; + swipeEvent.endPositionY = swipeDirectionEvent.endPositionY = endPositionY; this.dispatchEvent(swipeEvent); + this.dispatchEvent(swipeDirectionEvent); } }, - _findVelocity: { - enumerable: false, - value: function (deltaTime) { - return (Math.sqrt(/*xSquare*/(this._deltaX * this._deltaX) + /*ySquare*/(this._deltaY * this._deltaY)) / /*deltaTime*/(deltaTime)); + /** + * @private + * @function _addTranslateEventListeners + * @description add the translate event listeners + */ + _addTranslateEventListeners: { + value: function () { + this._translateComposer.addEventListener( + "translateCancel", this + ); + this._translateComposer.addEventListener( + "translateEnd", this + ); + } + }, + /** + * @private + * @function _removeTranslateEventListeners + * @description remove the translate event listeners + */ + _removeTranslateEventListeners: { + value: function () { + this._translateComposer.removeEventListener( + "translateCancel", this + ); + this._translateComposer.removeEventListener( + "translateEnd", this + ); + } + }, + + /** + * @private + * @function _resetComposerState + * @description Reset the swipe composer state. + */ + _resetComposerState: { + value: function () { + this._startPositionX = 0; + this._startPositionY = 0; + this._direction = null; + this.__translateComposer.translateX = 0; + this.__translateComposer.translateY = 0; + this._removeTranslateEventListeners(); } } From 760d937291a6b3ec1800e515728d0efe884d3ea6 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Thu, 28 Jun 2018 16:04:18 -0400 Subject: [PATCH 46/65] Add swipe composer sample --- .../swipe-composer.info/sample/index.html | 19 +++ .../swipe-composer.info/sample/package.json | 10 ++ .../sample/ui/main.reel/main.css | 29 ++++ .../sample/ui/main.reel/main.html | 79 +++++++++ .../sample/ui/main.reel/main.js | 160 ++++++++++++++++++ index.html | 1 + 6 files changed, 298 insertions(+) create mode 100644 composer/swipe-composer.info/sample/index.html create mode 100644 composer/swipe-composer.info/sample/package.json create mode 100644 composer/swipe-composer.info/sample/ui/main.reel/main.css create mode 100644 composer/swipe-composer.info/sample/ui/main.reel/main.html create mode 100644 composer/swipe-composer.info/sample/ui/main.reel/main.js diff --git a/composer/swipe-composer.info/sample/index.html b/composer/swipe-composer.info/sample/index.html new file mode 100644 index 0000000000..a46f50ad2f --- /dev/null +++ b/composer/swipe-composer.info/sample/index.html @@ -0,0 +1,19 @@ + + + + + Swipe Composer Sample + + + + + + + + diff --git a/composer/swipe-composer.info/sample/package.json b/composer/swipe-composer.info/sample/package.json new file mode 100644 index 0000000000..c2602bb824 --- /dev/null +++ b/composer/swipe-composer.info/sample/package.json @@ -0,0 +1,10 @@ +{ + "name": "swipe-composer-sample", + "version": "0.0.1", + "dependencies": { + "montage": "*" + }, + "mappings": { + "montage": "../../../" + } +} diff --git a/composer/swipe-composer.info/sample/ui/main.reel/main.css b/composer/swipe-composer.info/sample/ui/main.reel/main.css new file mode 100644 index 0000000000..0ad5005214 --- /dev/null +++ b/composer/swipe-composer.info/sample/ui/main.reel/main.css @@ -0,0 +1,29 @@ +html, body { + padding: 0; + margin: 0; + font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.Main { + padding: 20px; +} + +header { + margin: 40px 0; + font-size: 2rem; + text-align: center; + color: #33495d; + height: 40px; +} + +.HitBox { + margin: auto; + width: 400px; + height: 400px; + border: 1px solid black; +} diff --git a/composer/swipe-composer.info/sample/ui/main.reel/main.html b/composer/swipe-composer.info/sample/ui/main.reel/main.html new file mode 100644 index 0000000000..e06dcea786 --- /dev/null +++ b/composer/swipe-composer.info/sample/ui/main.reel/main.html @@ -0,0 +1,79 @@ + + + + + + + + + +
+
Swipe Composer Sample
+
+ + + +
+
+

+ Direction: + +

+

+ Distance: + +

+

+ Velocity: + +

+

+ Angle: + +

+
+
+ + diff --git a/composer/swipe-composer.info/sample/ui/main.reel/main.js b/composer/swipe-composer.info/sample/ui/main.reel/main.js new file mode 100644 index 0000000000..4c5cbb8962 --- /dev/null +++ b/composer/swipe-composer.info/sample/ui/main.reel/main.js @@ -0,0 +1,160 @@ +var Component = require("montage/ui/component").Component, + SwipeComposer = require("montage/composer/swipe-composer").SwipeComposer; + +exports.Main = Component.specialize({ + + _x1: { + value: 0 + }, + + _y1: { + value: 0 + }, + + _x2: { + value: 0 + }, + + _y2: { + value: 0 + }, + + __swipeComposer: { + value: null + }, + + _swipeComposer: { + get: function () { + if (!this.__swipeComposer) { + this.__swipeComposer = new SwipeComposer(); + this.addComposerForElement(this.__swipeComposer, this._hitBox); + } + + return this.__swipeComposer; + } + }, + + _translateComposer: { + get: function () { + return this._swipeComposer._translateComposer; + } + }, + + enterDocument: { + value: function (firstTime) { + if (firstTime) { + this._translateComposer.addEventListener("translateStart", this); + this._swipeComposer.addEventListener("swipe", this); + this._swipeComposer.addEventListener("swipeUp", this); + this._swipeComposer.addEventListener("swipeRight", this); + this._swipeComposer.addEventListener("swipeLeft", this); + this._swipeComposer.addEventListener("swipeDown", this); + } + } + }, + + handleTranslateStart: { + value: function () { + this._x1 = ( + this._translateComposer.pointerStartEventPosition.pageX - + this._hitBoxRect.left + ); + + this._y1 = ( + this._translateComposer.pointerStartEventPosition.pageY - + this._hitBoxRect.top + ); + + this._translateComposer.addEventListener("translate", this); + this._translateComposer.addEventListener("translateEnd", this); + this._translateComposer.addEventListener("translateCancel", this); + } + }, + + handleTranslate: { + value: function (event) { + this._x2 = this._x1 + event.translateX; + this._y2 = this._y1 + event.translateY; + this.needsDraw = true; + } + }, + + handleTranslateEnd: { + value: function () { + this._reset(); + } + }, + + handleTranslateCancel: { + value: function () { + this._reset(); + } + }, + + handleSwipe: { + value: function (event) { + this.swipeVelocity = event.velocity.toFixed(2); + this.swipeAngle = event.angle.toFixed(2); + this.swipeDistance = event.distance.toFixed(2); + } + }, + + handleSwipeUp: { + value: function (event) { + this.swipeDirection = event.direction; + } + }, + + handleSwipeLeft: { + value: function (event) { + this.swipeDirection = event.direction; + } + }, + + handleSwipeRight: { + value: function (event) { + this.swipeDirection = event.direction; + } + }, + + handleSwipeDown: { + value: function (event) { + this.swipeDirection = event.direction; + } + }, + + _reset: { + value: function () { + this._translateComposer.removeEventListener("translate", this); + this._translateComposer.removeEventListener("translateEnd", this); + this._translateComposer.removeEventListener("translateCancel", this); + + this._x1 = 0; + this._x2 = 0; + this._y1 = 0; + this._y2 = 0; + + this.needsDraw = true; + } + }, + + willDraw: { + value: function () { + if (!this._hitBoxRect && this._hitBox) { + this._hitBoxRect = this._hitBox.getBoundingClientRect(); + } + } + }, + + draw: { + value: function () { + if (this._hitBoxRect && this._hitBox) { + this._line.setAttribute("x1", this._x1); + this._line.setAttribute("y1", this._y1); + this._line.setAttribute("x2", this._x2); + this._line.setAttribute("y2", this._y2); + } + } + } + +}); diff --git a/index.html b/index.html index 177fc4c519..6e83f2d509 100644 --- a/index.html +++ b/index.html @@ -23,6 +23,7 @@

Composers:

Press Composer Translate Composer + Swipe Composer

Components:

Anchor From f5e07f6e8132acf9c3b7a1d29db670116227a282 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Thu, 28 Jun 2018 16:49:26 -0400 Subject: [PATCH 47/65] Remove debuggers --- composer/swipe-composer.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/composer/swipe-composer.js b/composer/swipe-composer.js index e1e4dcbc4a..9671e9e946 100644 --- a/composer/swipe-composer.js +++ b/composer/swipe-composer.js @@ -231,7 +231,6 @@ exports.SwipeComposer = Composer.specialize( /** @lends SwipeComposer# */ { */ load: { value: function () { - debugger this.component.addComposerForElement( this._translateComposer, this.element ); @@ -259,7 +258,6 @@ exports.SwipeComposer = Composer.specialize( /** @lends SwipeComposer# */ { handleTranslateStart: { value: function (event) { - console.log(event) this._startPositionX = this._translateComposer.pointerStartEventPosition.pageX; this._startPositionY = this._translateComposer.pointerStartEventPosition.pageY; this._startTimestamp = event.timeStamp; @@ -273,8 +271,6 @@ exports.SwipeComposer = Composer.specialize( /** @lends SwipeComposer# */ { event.translateX, event.translateY ); - debugger - if (distance >= this.minDistance) { var velocity = this._findVelocity( distance, From cb94e757d16fc3baf8995cea09b62175dacc4f79 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Thu, 28 Jun 2018 16:49:42 -0400 Subject: [PATCH 48/65] Little optimisation with the translate composer --- composer/translate-composer.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/composer/translate-composer.js b/composer/translate-composer.js index 351c973d81..6802be5689 100644 --- a/composer/translate-composer.js +++ b/composer/translate-composer.js @@ -958,7 +958,7 @@ var TranslateComposer = exports.TranslateComposer = Composer.specialize(/** @len isNegativeDeltaX, deltaX, deltaY; - + if (event.type === "wheel" || event.type === "mousewheel") { if (this._axis !== "vertical") { deltaX = ((event.wheelDeltaX || -event.deltaX || 0) * 20) / 120; @@ -1069,9 +1069,12 @@ var TranslateComposer = exports.TranslateComposer = Composer.specialize(/** @len this.endX = this.posX = this.startX=this._translateX; this.endY=this.posY=this.startY=this._translateY; - var velocity = event.velocity; + var velocity; - if ((this._hasMomentum) && ((velocity.speed>40) || this.translateStrideX || this.translateStrideY)) { + if ( + this._hasMomentum && (velocity = event.velocity) && ((velocity.speed > 40) + || this.translateStrideX || this.translateStrideY) + ) { if (this._axis !== "vertical") { this.momentumX = velocity.x * this._pointerSpeedMultiplier * (this._invertXAxis ? 1 : -1); } else { From c0ada97a18810f276b9b681394f340d7028c0653 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Thu, 28 Jun 2018 16:49:56 -0400 Subject: [PATCH 49/65] Add specs for the swipe composer --- test/spec/composer/composer-spec.js | 128 ++++++++++++++++++++++------ test/spec/composer/swipe/swipe.js | 27 +++++- 2 files changed, 126 insertions(+), 29 deletions(-) diff --git a/test/spec/composer/composer-spec.js b/test/spec/composer/composer-spec.js index bdb3612dc8..b1aeea99a2 100644 --- a/test/spec/composer/composer-spec.js +++ b/test/spec/composer/composer-spec.js @@ -98,43 +98,119 @@ TestPageLoader.queueTest("composer-programmatic-lazyload", {src: "spec/composer/ }); TestPageLoader.queueTest("swipe-composer", {src:"spec/composer/swipe/swipe.html", firstDraw: false}, function (testPage) { - var test; + var test, swipeElement; beforeEach(function () { test = testPage.test; + swipeElement = test.dummyComponent.element; }); + + //FIXME: should be removed when will provide a pollyfil for the pointer events + function dispatchPointerEvent(element, type, positionX, positionY) { + var eventInit = { + clientX: positionX, + clientY: positionY, + bubbles: true, + pointerType: "mouse" + }; + + if (window.PointerEvent) { + element.dispatchEvent(new PointerEvent(type, eventInit)); + } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { + if (type === "pointerdown") { + type = "MSPointerDown"; + } else if (type === "pointermove") { + type = "MSPointerMove"; + } else { + type = "MSPointerUp"; + } + element.dispatchEvent(new MSPointerEvent(type, eventInit)); + } else { + if (type === "pointerdown") { + type = "mousedown"; + } else if (type === "pointermove") { + type = "mousemove"; + } else { + type = "mouseup"; + } + element.dispatchEvent(new MouseEvent(type, eventInit)); + } + } + describe("composer-spec", function () { describe("swipe right",function () { it("shouldn't emit swipe event or swipemove event if no move", function () { - //simulate touch events spyOn(test, 'handleSwipe').and.callThrough(); - spyOn(test, 'handleSwipemove').and.callThrough(); - testPage.touchEvent(new EventInfo().initWithElementAndPosition(null, -100, 100), "touchstart", function () { - testPage.touchEvent(new EventInfo().initWithElementAndPosition(null, -100, 100), "touchmove", function () { - testPage.touchEvent(new EventInfo().initWithElementAndPosition(null, -100, 100), "touchend", function () { - expect(test.handleSwipemove).not.toHaveBeenCalled(); - expect(test.handleSwipe).not.toHaveBeenCalled(); - }); - }); - }); + dispatchPointerEvent(swipeElement, "pointerdown", -100, 100); + dispatchPointerEvent(swipeElement, "pointermove", -100, 100); + dispatchPointerEvent(swipeElement, "pointermove", -100, 100); + dispatchPointerEvent(swipeElement, "pointerup", -100, 100); + expect(test.handleSwipe).not.toHaveBeenCalled(); }); - it("should emit swipe event and swipemove event", function () { - //simulate touch events + it("should emit swipe event and swipeDown event", function () { spyOn(test, 'handleSwipe').and.callThrough(); - spyOn(test, 'handleSwipemove').and.callThrough(); - testPage.touchEvent(new EventInfo().initWithElementAndPosition(null, 0, 0), "touchstart", function () { - testPage.touchEvent(new EventInfo().initWithElementAndPosition(null, 0, 50), "touchmove", function () { - testPage.touchEvent(new EventInfo().initWithElementAndPosition(null, 0, 100), "touchmove", function () { - testPage.touchEvent(new EventInfo().initWithElementAndPosition(null, 50, 50), "touchend", function () { - expect(test.handleSwipemove).toHaveBeenCalled(); - expect(test.handleSwipe).toHaveBeenCalled(); - }); - }); - }); - }); + spyOn(test, 'handleSwipeDown').and.callThrough(); + dispatchPointerEvent(swipeElement, "pointerdown", 0, 0); + dispatchPointerEvent(swipeElement, "pointermove", 0, 50); + dispatchPointerEvent(swipeElement, "pointermove", 0, 80); + dispatchPointerEvent(swipeElement, "pointerup", 0, 80); + expect(test.handleSwipeDown).toHaveBeenCalled(); + expect(test.handleSwipe).toHaveBeenCalled(); + + var event = test.handleSwipe.calls.argsFor(0)[0]; + expect(event.direction).toBe('down'); + expect(event.angle).toBe(270); + expect(event.distance).toBe(80); + }); + + it("should emit swipe event and swipeUp event", function () { + spyOn(test, 'handleSwipe').and.callThrough(); + spyOn(test, 'handleSwipeUp').and.callThrough(); + dispatchPointerEvent(swipeElement, "pointerdown", 50, 50); + dispatchPointerEvent(swipeElement, "pointermove", 50, 40); + dispatchPointerEvent(swipeElement, "pointermove", 50, 30); + dispatchPointerEvent(swipeElement, "pointerup", 50, 30); + expect(test.handleSwipeUp).toHaveBeenCalled(); + expect(test.handleSwipeUp).toHaveBeenCalled(); + expect(test.handleSwipe).toHaveBeenCalled(); + + var event = test.handleSwipe.calls.argsFor(0)[0]; + expect(event.direction).toBe('up'); + expect(event.angle).toBe(90); + expect(event.distance).toBe(20); + }); + + it("should emit swipe event and swipeRight event", function () { + spyOn(test, 'handleSwipe').and.callThrough(); + spyOn(test, 'handleSwipeRight').and.callThrough(); + dispatchPointerEvent(swipeElement, "pointerdown", 0, 0); + dispatchPointerEvent(swipeElement, "pointermove", 50, 0); + dispatchPointerEvent(swipeElement, "pointermove", 80, 0); + dispatchPointerEvent(swipeElement, "pointerup", 80, 0); + expect(test.handleSwipeRight).toHaveBeenCalled(); + expect(test.handleSwipe).toHaveBeenCalled(); + + var event = test.handleSwipe.calls.argsFor(0)[0]; + expect(event.direction).toBe('right'); + expect(event.angle).toBe(0); + expect(event.distance).toBe(80); + }); + + it("should emit swipe event and swipeLeft event", function () { + spyOn(test, 'handleSwipe').and.callThrough(); + spyOn(test, 'handleSwipeLeft').and.callThrough(); + dispatchPointerEvent(swipeElement, "pointerdown", 100, 0); + dispatchPointerEvent(swipeElement, "pointermove", 80, 0); + dispatchPointerEvent(swipeElement, "pointermove", 50, 0); + dispatchPointerEvent(swipeElement, "pointerup", 50, 0); + expect(test.handleSwipeLeft).toHaveBeenCalled(); + expect(test.handleSwipe).toHaveBeenCalled(); + + var event = test.handleSwipe.calls.argsFor(0)[0]; + expect(event.direction).toBe('left'); + expect(event.angle).toBe(180); + expect(event.distance).toBe(50); }); }); }); }); - - diff --git a/test/spec/composer/swipe/swipe.js b/test/spec/composer/swipe/swipe.js index d08bc43ada..397bb0dbdc 100644 --- a/test/spec/composer/swipe/swipe.js +++ b/test/spec/composer/swipe/swipe.js @@ -6,25 +6,46 @@ exports.Swipe = Montage.specialize( { deserializedFromTemplate: { value: function () { - var dummyComponent = new Component(); + var dummyComponent = this.dummyComponent = new Component(); dummyComponent.hasTemplate = false; dummyComponent.element = document.body; + dummyComponent.element.style.height = "400px"; + dummyComponent.element.style.width = "400px"; dummyComponent.attachToParentComponent(); dummyComponent.needsDraw = true; this.swipeComposer = new SwipeComposer(); this.swipeComposer.lazyLoad = false; dummyComponent.addComposer(this.swipeComposer); this.swipeComposer.addEventListener("swipe", this, false); - this.swipeComposer.addEventListener("swipemove", this, false); + this.swipeComposer.addEventListener("swipeLeft", this, false); + this.swipeComposer.addEventListener("swipeRight", this, false); + this.swipeComposer.addEventListener("swipeDown", this, false); + this.swipeComposer.addEventListener("swipeUp", this, false); } }, handleSwipe: { value: function (event) { + console.log(event.direction) } }, - handleSwipemove: { + handleSwipeUp: { + value: function (event) { + } + }, + + handleSwipeRight: { + value: function (event) { + } + }, + + handleSwipeDown: { + value: function (event) { + } + }, + + handleSwipeLeft: { value: function (event) { } } From 04309f2394e76fdd7062bae39627f01bf8f44c24 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Thu, 28 Jun 2018 16:52:54 -0400 Subject: [PATCH 50/65] Fix JShint warning --- composer/translate-composer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer/translate-composer.js b/composer/translate-composer.js index 6802be5689..4edba8276f 100644 --- a/composer/translate-composer.js +++ b/composer/translate-composer.js @@ -1072,8 +1072,8 @@ var TranslateComposer = exports.TranslateComposer = Composer.specialize(/** @len var velocity; if ( - this._hasMomentum && (velocity = event.velocity) && ((velocity.speed > 40) - || this.translateStrideX || this.translateStrideY) + this._hasMomentum && (velocity = event.velocity) && + ((velocity.speed > 40) || this.translateStrideX || this.translateStrideY) ) { if (this._axis !== "vertical") { this.momentumX = velocity.x * this._pointerSpeedMultiplier * (this._invertXAxis ? 1 : -1); From 4cd0a0c82d23c47d86a123295a25e281d3eaf947 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Thu, 28 Jun 2018 17:02:27 -0400 Subject: [PATCH 51/65] Fix JSLint warning --- core/drag/drag.info/sample/ui/drop.reel/drop.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/drag/drag.info/sample/ui/drop.reel/drop.js b/core/drag/drag.info/sample/ui/drop.reel/drop.js index 59159742d8..9e45c4c3e8 100644 --- a/core/drag/drag.info/sample/ui/drop.reel/drop.js +++ b/core/drag/drag.info/sample/ui/drop.reel/drop.js @@ -70,7 +70,7 @@ exports.Drop = Component.specialize(/** @lends Drop# */ { } } - console.log(event.dataTransfer.draggedObject) + console.log(event.dataTransfer.draggedObject); } }, From c4b4a3389cb278c27fe55b504382045df45c83c3 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Fri, 29 Jun 2018 12:52:02 -0400 Subject: [PATCH 52/65] Remove Swipe Direction events --- .../sample/ui/main.reel/main.js | 29 +------------------ composer/swipe-composer.js | 22 ++++++-------- test/spec/composer/composer-spec.js | 9 ------ test/spec/composer/swipe/swipe.js | 24 --------------- 4 files changed, 10 insertions(+), 74 deletions(-) diff --git a/composer/swipe-composer.info/sample/ui/main.reel/main.js b/composer/swipe-composer.info/sample/ui/main.reel/main.js index 4c5cbb8962..42034bf458 100644 --- a/composer/swipe-composer.info/sample/ui/main.reel/main.js +++ b/composer/swipe-composer.info/sample/ui/main.reel/main.js @@ -45,10 +45,6 @@ exports.Main = Component.specialize({ if (firstTime) { this._translateComposer.addEventListener("translateStart", this); this._swipeComposer.addEventListener("swipe", this); - this._swipeComposer.addEventListener("swipeUp", this); - this._swipeComposer.addEventListener("swipeRight", this); - this._swipeComposer.addEventListener("swipeLeft", this); - this._swipeComposer.addEventListener("swipeDown", this); } } }, @@ -93,36 +89,13 @@ exports.Main = Component.specialize({ handleSwipe: { value: function (event) { + this.swipeDirection = event.direction; this.swipeVelocity = event.velocity.toFixed(2); this.swipeAngle = event.angle.toFixed(2); this.swipeDistance = event.distance.toFixed(2); } }, - handleSwipeUp: { - value: function (event) { - this.swipeDirection = event.direction; - } - }, - - handleSwipeLeft: { - value: function (event) { - this.swipeDirection = event.direction; - } - }, - - handleSwipeRight: { - value: function (event) { - this.swipeDirection = event.direction; - } - }, - - handleSwipeDown: { - value: function (event) { - this.swipeDirection = event.direction; - } - }, - _reset: { value: function () { this._translateComposer.removeEventListener("translate", this); diff --git a/composer/swipe-composer.js b/composer/swipe-composer.js index 9671e9e946..d43410fd76 100644 --- a/composer/swipe-composer.js +++ b/composer/swipe-composer.js @@ -382,22 +382,18 @@ exports.SwipeComposer = Composer.specialize( /** @lends SwipeComposer# */ { */ _dispatchSwipeEvent: { value: function (distance, velocity, angle, direction, endPositionX, endPositionY) { - var swipeEvent = new SwipeEvent(SWIPE), - swipeDirectionEvent = new SwipeEvent( - SWIPE + direction.toCapitalized() - ); + var swipeEvent = new SwipeEvent(SWIPE); - swipeEvent.distance = swipeDirectionEvent.distance = distance; - swipeEvent.velocity = swipeDirectionEvent.velocity = velocity; - swipeEvent.angle = swipeDirectionEvent.angle = angle; - swipeEvent.direction = swipeDirectionEvent.direction = direction; - swipeEvent.startPositionX = swipeDirectionEvent.startPositionX = this._startPositionX; - swipeEvent.startPositionY = swipeDirectionEvent.startPositionY = this._startPositionY; - swipeEvent.endPositionX = swipeDirectionEvent.endPositionX = endPositionX; - swipeEvent.endPositionY = swipeDirectionEvent.endPositionY = endPositionY; + swipeEvent.distance = distance; + swipeEvent.velocity = velocity; + swipeEvent.angle = angle; + swipeEvent.direction = direction; + swipeEvent.startPositionX = this._startPositionX; + swipeEvent.startPositionY = this._startPositionY; + swipeEvent.endPositionX = endPositionX; + swipeEvent.endPositionY = endPositionY; this.dispatchEvent(swipeEvent); - this.dispatchEvent(swipeDirectionEvent); } }, diff --git a/test/spec/composer/composer-spec.js b/test/spec/composer/composer-spec.js index b1aeea99a2..ee5ebe951e 100644 --- a/test/spec/composer/composer-spec.js +++ b/test/spec/composer/composer-spec.js @@ -149,12 +149,10 @@ TestPageLoader.queueTest("swipe-composer", {src:"spec/composer/swipe/swipe.html" it("should emit swipe event and swipeDown event", function () { spyOn(test, 'handleSwipe').and.callThrough(); - spyOn(test, 'handleSwipeDown').and.callThrough(); dispatchPointerEvent(swipeElement, "pointerdown", 0, 0); dispatchPointerEvent(swipeElement, "pointermove", 0, 50); dispatchPointerEvent(swipeElement, "pointermove", 0, 80); dispatchPointerEvent(swipeElement, "pointerup", 0, 80); - expect(test.handleSwipeDown).toHaveBeenCalled(); expect(test.handleSwipe).toHaveBeenCalled(); var event = test.handleSwipe.calls.argsFor(0)[0]; @@ -165,13 +163,10 @@ TestPageLoader.queueTest("swipe-composer", {src:"spec/composer/swipe/swipe.html" it("should emit swipe event and swipeUp event", function () { spyOn(test, 'handleSwipe').and.callThrough(); - spyOn(test, 'handleSwipeUp').and.callThrough(); dispatchPointerEvent(swipeElement, "pointerdown", 50, 50); dispatchPointerEvent(swipeElement, "pointermove", 50, 40); dispatchPointerEvent(swipeElement, "pointermove", 50, 30); dispatchPointerEvent(swipeElement, "pointerup", 50, 30); - expect(test.handleSwipeUp).toHaveBeenCalled(); - expect(test.handleSwipeUp).toHaveBeenCalled(); expect(test.handleSwipe).toHaveBeenCalled(); var event = test.handleSwipe.calls.argsFor(0)[0]; @@ -182,12 +177,10 @@ TestPageLoader.queueTest("swipe-composer", {src:"spec/composer/swipe/swipe.html" it("should emit swipe event and swipeRight event", function () { spyOn(test, 'handleSwipe').and.callThrough(); - spyOn(test, 'handleSwipeRight').and.callThrough(); dispatchPointerEvent(swipeElement, "pointerdown", 0, 0); dispatchPointerEvent(swipeElement, "pointermove", 50, 0); dispatchPointerEvent(swipeElement, "pointermove", 80, 0); dispatchPointerEvent(swipeElement, "pointerup", 80, 0); - expect(test.handleSwipeRight).toHaveBeenCalled(); expect(test.handleSwipe).toHaveBeenCalled(); var event = test.handleSwipe.calls.argsFor(0)[0]; @@ -198,12 +191,10 @@ TestPageLoader.queueTest("swipe-composer", {src:"spec/composer/swipe/swipe.html" it("should emit swipe event and swipeLeft event", function () { spyOn(test, 'handleSwipe').and.callThrough(); - spyOn(test, 'handleSwipeLeft').and.callThrough(); dispatchPointerEvent(swipeElement, "pointerdown", 100, 0); dispatchPointerEvent(swipeElement, "pointermove", 80, 0); dispatchPointerEvent(swipeElement, "pointermove", 50, 0); dispatchPointerEvent(swipeElement, "pointerup", 50, 0); - expect(test.handleSwipeLeft).toHaveBeenCalled(); expect(test.handleSwipe).toHaveBeenCalled(); var event = test.handleSwipe.calls.argsFor(0)[0]; diff --git a/test/spec/composer/swipe/swipe.js b/test/spec/composer/swipe/swipe.js index 397bb0dbdc..3aff2b82e2 100644 --- a/test/spec/composer/swipe/swipe.js +++ b/test/spec/composer/swipe/swipe.js @@ -17,10 +17,6 @@ exports.Swipe = Montage.specialize( { this.swipeComposer.lazyLoad = false; dummyComponent.addComposer(this.swipeComposer); this.swipeComposer.addEventListener("swipe", this, false); - this.swipeComposer.addEventListener("swipeLeft", this, false); - this.swipeComposer.addEventListener("swipeRight", this, false); - this.swipeComposer.addEventListener("swipeDown", this, false); - this.swipeComposer.addEventListener("swipeUp", this, false); } }, @@ -28,26 +24,6 @@ exports.Swipe = Montage.specialize( { value: function (event) { console.log(event.direction) } - }, - - handleSwipeUp: { - value: function (event) { - } - }, - - handleSwipeRight: { - value: function (event) { - } - }, - - handleSwipeDown: { - value: function (event) { - } - }, - - handleSwipeLeft: { - value: function (event) { - } } }); From bb2443beba6af31b9d49a3527076801be92fd9c4 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 2 Jul 2018 14:20:13 -0400 Subject: [PATCH 53/65] Fix Typo --- core/drag/drag-event.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index faeaa8adb3..ba73834c64 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -4,7 +4,7 @@ var MutableEvent = require("../event/mutable-event").MutableEvent, // XXX Does not presently function server-side if (typeof window !== "undefined") { - var OBJECT_MINE_TYPE = 'application/object'; + var OBJECT_MIME_TYPE = 'application/object'; var DataTransfer = exports.DataTransfer = Montage.specialize({ @@ -129,10 +129,10 @@ if (typeof window !== "undefined") { draggedObject: { set: function (object) { - this._data.set(OBJECT_MINE_TYPE, object); + this._data.set(OBJECT_MIME_TYPE, object); }, get: function () { - return this._data.get(OBJECT_MINE_TYPE); + return this._data.get(OBJECT_MIME_TYPE); } }, From 031d4d6c14e862e686a4c07bb29cad64791151a6 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 2 Jul 2018 14:21:45 -0400 Subject: [PATCH 54/65] Rename _setUpDraggedImageIfNeeded to _drawDraggedImageIfNeeded --- core/drag/drag-manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index d1509ecfad..57b8619999 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -943,7 +943,7 @@ var DragManager = exports.DragManager = Montage.specialize({ var translateX = draggingOperationContext.deltaX, translateY = draggingOperationContext.deltaY; - this._setUpDraggedImageIfNeeded(draggedImage); + this._drawDraggedImageIfNeeded(draggedImage); if (!this._needsToWaitforDraggedImageBoundaries) { draggedImage.style.visibility = "visible"; @@ -1061,7 +1061,7 @@ var DragManager = exports.DragManager = Montage.specialize({ } }, - _setUpDraggedImageIfNeeded: { + _drawDraggedImageIfNeeded: { value: function (draggedImage) { var draggingOperationContext = this._draggingOperationContext; From cb93f85edde161178a84d5962072a64649d8f442 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 2 Jul 2018 14:26:21 -0400 Subject: [PATCH 55/65] Small performance improvements --- core/drag/drag-manager.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 57b8619999..863fff9481 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -1097,8 +1097,11 @@ var DragManager = exports.DragManager = Montage.specialize({ top = draggedImageBoundingRect.top; } - draggedImage.style.top = top + PX; - draggedImage.style.left = left + PX; + top += PX; + left += PX; + + draggedImage.style.top = top; + draggedImage.style.left = left; if (draggingOperationContext.dragEffect === "move") { var draggableElement = draggingOperationContext.draggable.element; @@ -1106,13 +1109,12 @@ var DragManager = exports.DragManager = Montage.specialize({ draggableElement.style.display = 'none'; if (draggingOperationContext.showPlaceholder) { - var placeholderElement = document.createElement('div'); - placeholderElement.style.width = ( - draggedImageBoundingRect.width + PX - ); - placeholderElement.style.height = ( - draggedImageBoundingRect.height + PX - ); + var placeholderElement = document.createElement('div'), + width = draggedImageBoundingRect.width + PX, + height = draggedImageBoundingRect.height + PX; + + placeholderElement.style.width = width; + placeholderElement.style.height = height; placeholderElement.style.boxSizing = "border-box"; placeholderElement.classList.add( 'montage-drag-placeholder' From 892e18c2bfec4acafe85019f4597c0f5d042416d Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 2 Jul 2018 14:30:24 -0400 Subject: [PATCH 56/65] Call only once the remove method of the classList object. --- core/drag/drag-manager.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/drag/drag-manager.js b/core/drag/drag-manager.js index 863fff9481..af30800db4 100644 --- a/core/drag/drag-manager.js +++ b/core/drag/drag-manager.js @@ -430,8 +430,9 @@ var DragManager = exports.DragManager = Montage.specialize({ _dispatchDragLeave: { value: function (draggingOperationContext) { if (draggingOperationContext.currentDropTarget) { - draggingOperationContext.currentDropTarget.classList.remove("drag-over"); - draggingOperationContext.currentDropTarget.classList.remove("drag-enter"); + draggingOperationContext.currentDropTarget.classList.remove( + "drag-over", "drag-enter" + ); draggingOperationContext.currentDropTarget.dispatchEvent(this._createDragEvent( "dragleave", draggingOperationContext From 5575fc3b7cfcc866f8130d2e5497597cd478bd32 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 2 Jul 2018 14:53:30 -0400 Subject: [PATCH 57/65] Small improvements --- core/drag/drag-event.js | 60 +++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index ba73834c64..716c70f63d 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -31,7 +31,7 @@ if (typeof window !== "undefined") { dragEffect: { set: function (effect) { - if (DataTransfer.ALLOWED_EFFECTS.indexOf(effect) > -1) { + if (this.isEffectAllowed(effect)) { this._dragEffect = effect; } }, @@ -48,7 +48,7 @@ if (typeof window !== "undefined") { set: function (effect) { if ( effect && - DataTransfer.ALLOWED_EFFECTS.indexOf(effect) > -1 && + this.isEffectAllowed(effect) && DataTransfer.isDropEffectAllowed( effect, this.effectAllowed ) @@ -60,17 +60,13 @@ if (typeof window !== "undefined") { }, get: function () { if (!this._dropEffect) { - var index; - if ( this.effectAllowed === DataTransfer.All || this.effectAllowed.startsWith('c') ) { this._dropEffect = DataTransfer.Copy; - } else if ((index = DataTransfer.ALLOWED_EFFECTS.indexOf( - this.effectAllowed)) > -1 - ) { - this._dropEffect = DataTransfer.ALLOWED_EFFECTS[index]; + } else if (this.isEffectAllowed(this.effectAllowed)) { + this._dropEffect = this.effectAllowed; } else { this._dropEffect = DataTransfer.Link; } @@ -86,7 +82,7 @@ if (typeof window !== "undefined") { effectAllowed: { set: function (effect) { - if (DataTransfer.ALLOWED_DROP_EFFECTS.indexOf(effect) > -1) { + if (!!DataTransfer.allowedDropEffectsMap[effect]) { this._effectAllowed = effect; } }, @@ -190,6 +186,12 @@ if (typeof window !== "undefined") { } }, + isEffectAllowed: { + value: function (effect) { + return !!DataTransfer.allowedEffectsMap[effect]; + } + } + }, { Default: { value: "default" @@ -223,41 +225,41 @@ if (typeof window !== "undefined") { value: "all" }, - _ALLOWED_EFFECTS: { + _allowedEffectsMap: { value: null }, - ALLOWED_EFFECTS: { + allowedEffectsMap: { get: function () { - if (!this._ALLOWED_EFFECTS) { - this._ALLOWED_EFFECTS = [ - this.Default, - this.Copy, - this.Link, - this.Move - ]; + if (!this._allowedEffectsMap) { + this._allowedEffectsMap = { + [this.Default]: true, + [this.Copy]: true, + [this.Link]: true, + [this.Move]: true + }; } - return this._ALLOWED_EFFECTS; + return this._allowedEffectsMap; } }, - _ALLOWED_DROP_EFFECTS: { + _allowedDropEffectsMap: { value: null }, - ALLOWED_DROP_EFFECTS: { + allowedDropEffectsMap: { get: function () { - if (!this._ALLOWED_DROP_EFFECTS) { - this._ALLOWED_DROP_EFFECTS = this.ALLOWED_EFFECTS.concat([ - this.All, - this.CopyMove, - this.CopyLink, - this.LinkMove - ]); + if (!this._allowedDropEffectsMap) { + this._allowedDropEffectsMap = Object.assign({ + [this.All]: true, + [this.CopyMove]: true, + [this.CopyLink]: true, + [this.LinkMove]: true + }, this._allowedEffectsMap); } - return this._ALLOWED_DROP_EFFECTS; + return this._allowedDropEffectsMap; } }, From 71f174a34af33b0304b6fec4f605c03e6e4a2ed8 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Mon, 2 Jul 2018 15:01:12 -0400 Subject: [PATCH 58/65] Remove ES6 code Fix JShint warning: `computed property names only supported by ES6` --- core/drag/drag-event.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/core/drag/drag-event.js b/core/drag/drag-event.js index 716c70f63d..8a8ca4c365 100644 --- a/core/drag/drag-event.js +++ b/core/drag/drag-event.js @@ -232,12 +232,11 @@ if (typeof window !== "undefined") { allowedEffectsMap: { get: function () { if (!this._allowedEffectsMap) { - this._allowedEffectsMap = { - [this.Default]: true, - [this.Copy]: true, - [this.Link]: true, - [this.Move]: true - }; + this._allowedEffectsMap = {}; + this._allowedEffectsMap[this.Default] = true; + this._allowedEffectsMap[this.Copy] = true; + this._allowedEffectsMap[this.Link] = true; + this._allowedEffectsMap[this.Move] = true; } return this._allowedEffectsMap; @@ -251,12 +250,15 @@ if (typeof window !== "undefined") { allowedDropEffectsMap: { get: function () { if (!this._allowedDropEffectsMap) { - this._allowedDropEffectsMap = Object.assign({ - [this.All]: true, - [this.CopyMove]: true, - [this.CopyLink]: true, - [this.LinkMove]: true - }, this._allowedEffectsMap); + var tmp = {}; + tmp[this.All] = true; + tmp[this.CopyMove] = true; + tmp[this.CopyLink] = true; + tmp[this.LinkMove] = true; + + this._allowedDropEffectsMap = Object.assign( + tmp, this._allowedEffectsMap + ); } return this._allowedDropEffectsMap; From db49f920370931a12372fa51d3ac957478701801 Mon Sep 17 00:00:00 2001 From: Thomas Jaede Date: Tue, 10 Jul 2018 18:05:46 -0700 Subject: [PATCH 59/65] Bump collections version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index df6ac76bd0..df66264f8f 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "production": true, "dependencies": { "bluebird": "~3.5.0", - "collections": "~5.0.x", + "collections": "~5.1.x", "frb": "~4.0.x", "htmlparser2": "~3.0.5", "q-io": "^1.13.3", From 37c132844db3b28715a9c6ed36204c9dccf6bc41 Mon Sep 17 00:00:00 2001 From: Benoit Marchant Date: Mon, 30 Jul 2018 17:51:25 -0700 Subject: [PATCH 60/65] changes deprecate blueprint warnings to once --- core/meta/model.js | 14 ++--- core/meta/object-descriptor.js | 54 +++++++++--------- core/meta/property-descriptor.js | 94 ++++++++++++++++---------------- 3 files changed, 81 insertions(+), 81 deletions(-) diff --git a/core/meta/model.js b/core/meta/model.js index a14fc53557..9b4539312a 100644 --- a/core/meta/model.js +++ b/core/meta/model.js @@ -236,7 +236,7 @@ var Model = exports.Model = Montage.specialize( /** @lends Model.prototype # */ objectDescriptorForPrototype: { value: deprecate.deprecateMethod(void 0, function (prototypeName) { return this.objectDescriptorForName(prototypeName); - }, "objectDescriptorForPrototype", "objectDescriptorForName") + }, "objectDescriptorForPrototype", "objectDescriptorForName", true) }, /** @@ -297,7 +297,7 @@ var Model = exports.Model = Montage.specialize( /** @lends Model.prototype # */ blueprints: { get: deprecate.deprecateMethod(void 0, function () { return this.objectDescriptors; - }, "blueprints", "objectDescriptors") + }, "blueprints", "objectDescriptors", true) }, /** @@ -309,7 +309,7 @@ var Model = exports.Model = Montage.specialize( /** @lends Model.prototype # */ addBlueprint: { value: deprecate.deprecateMethod(void 0, function (blueprint) { return this.addObjectDescriptor(blueprint); - }, "addBlueprint", "addObjectDescriptor") + }, "addBlueprint", "addObjectDescriptor", true) }, /** @@ -321,7 +321,7 @@ var Model = exports.Model = Montage.specialize( /** @lends Model.prototype # */ removeBlueprint: { value: deprecate.deprecateMethod(void 0, function (blueprint) { return this.removeObjectDescriptor(blueprint); - }, "removeBlueprint", "removeObjectDescriptor") + }, "removeBlueprint", "removeObjectDescriptor", true) }, /** @@ -334,7 +334,7 @@ var Model = exports.Model = Montage.specialize( /** @lends Model.prototype # */ addBlueprintNamed: { value: deprecate.deprecateMethod(void 0, function (name) { return this.addObjectDescriptorNamed(name); - }, "addBlueprintNamed", "addObjectDescriptorNamed") + }, "addBlueprintNamed", "addObjectDescriptorNamed", true) }, /** @@ -348,7 +348,7 @@ var Model = exports.Model = Montage.specialize( /** @lends Model.prototype # */ blueprintForPrototype: { value: deprecate.deprecateMethod(void 0, function (prototypeName) { return this.blueprintForName(prototypeName); - }, "blueprintForPrototype", "blueprintForName") + }, "blueprintForPrototype", "blueprintForName", true) }, /** @@ -359,7 +359,7 @@ var Model = exports.Model = Montage.specialize( /** @lends Model.prototype # */ blueprintForName: { value: deprecate.deprecateMethod(void 0, function (name) { return this.objectDescriptorForName(name); - }, "blueprintForName", "objectDescriptorForName") + }, "blueprintForName", "objectDescriptorForName", true) }, blueprintModuleId: require("../core")._objectDescriptorModuleIdDescriptor, diff --git a/core/meta/object-descriptor.js b/core/meta/object-descriptor.js index c323836bda..5b6a927b61 100644 --- a/core/meta/object-descriptor.js +++ b/core/meta/object-descriptor.js @@ -410,7 +410,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends isReady = true, descriptor, i, n; if (!this._propertyDescriptorsAreCached) { - + for (i = 0, n = ownDescriptors.length; i < n && isReady; ++i) { descriptor = ownDescriptors[i]; isReady = !!(descriptor && descriptor.name); @@ -1004,7 +1004,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends if (!this._userInterfaceDescriptor) { if (this.userInterfaceDescriptorModules && this.userInterfaceDescriptorModules["*"]) { - + Montage.defineProperty(this, "_userInterfaceDescriptor", { enumerable: false, value: this.userInterfaceDescriptorModules["*"].require.async( @@ -1094,7 +1094,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends addEventBlueprintNamed: { value: deprecate.deprecateMethod(void 0, function (name) { return this.addEventDescriptorNamed(name); - }, "addEventBlueprintNamed", "addEventDescriptorNamed") + }, "addEventBlueprintNamed", "addEventDescriptorNamed", true) }, /** @@ -1111,7 +1111,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends addPropertyBlueprint: { value: deprecate.deprecateMethod(void 0, function (propertyBlueprint) { this.addPropertyDescriptor(propertyBlueprint); - }, "addPropertyBlueprint", "addPropertyDescriptor") + }, "addPropertyBlueprint", "addPropertyDescriptor", true) }, /** @@ -1123,7 +1123,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends addPropertyBlueprintGroupNamed: { value: deprecate.deprecateMethod(void 0, function (groupName) { this.addPropertyDescriptorGroupNamed(groupName); - }, "addPropertyBlueprintGroupNamed", "addPropertyDescriptorGroupNamed") + }, "addPropertyBlueprintGroupNamed", "addPropertyDescriptorGroupNamed", true) }, /** @@ -1137,7 +1137,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends addPropertyBlueprintToGroupNamed: { value: deprecate.deprecateMethod(void 0, function (propertyBlueprint, groupName) { this.addPropertyDescriptorToGroupNamed(propertyBlueprint, groupName); - }, "addPropertyBlueprintToGroupNamed", "addPropertyDescriptorToGroupNamed") + }, "addPropertyBlueprintToGroupNamed", "addPropertyDescriptorToGroupNamed", true) }, /** @@ -1146,7 +1146,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends addToOnePropertyBlueprintNamed: { value: deprecate.deprecateMethod(void 0, function (name) { return this.addToOnePropertyDescriptorNamed(name); - }, "addToOnePropertyBlueprintNamed", "addToOnePropertyDescriptorNamed") + }, "addToOnePropertyBlueprintNamed", "addToOnePropertyDescriptorNamed", true) }, /** @@ -1155,7 +1155,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends addToManyPropertyBlueprintNamed: { value: deprecate.deprecateMethod(void 0, function (name) { return this.addToManyPropertyDescriptorNamed(name); - }, "addToManyPropertyBlueprintNamed", "addToManyPropertyDescriptorNamed") + }, "addToManyPropertyBlueprintNamed", "addToManyPropertyDescriptorNamed", true) }, /** @@ -1167,10 +1167,10 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends serializable: false, get: deprecate.deprecateMethod(void 0, function () { return this.objectDescriptorInstanceModule; - }, "blueprintInstanceModule.get", "objectDescriptorInstanceModule.get"), + }, "blueprintInstanceModule.get", "objectDescriptorInstanceModule.get", true), set: deprecate.deprecateMethod(void 0, function (value) { this.objectDescriptorInstanceModule = value; - }, "blueprintInstanceModule.set", "objectDescriptorInstanceModule.set") + }, "blueprintInstanceModule.set", "objectDescriptorInstanceModule.set", true) }, /** @@ -1182,10 +1182,10 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends serializable: false, get: deprecate.deprecateMethod(void 0, function () { return this.model; - }, "binder.get", "model.get"), + }, "binder.get", "model.get", true), set: deprecate.deprecateMethod(void 0, function (value) { this.model = value; - }, "binder.set", "model.set") + }, "binder.set", "model.set", true) }, /** @@ -1197,7 +1197,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends eventBlueprintForName: { value: deprecate.deprecateMethod(void 0, function (name) { return this.eventDescriptorForName(name); - }, "eventBlueprintForName", "eventDescriptorForName") + }, "eventBlueprintForName", "eventDescriptorForName", true) }, /** @@ -1207,10 +1207,10 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends // value: null get: deprecate.deprecateMethod(void 0, function () { return this.eventDescriptors; - }, "eventBlueprints.get", "eventDescriptors.get"), + }, "eventBlueprints.get", "eventDescriptors.get", true), set: deprecate.deprecateMethod(void 0, function (value) { this.eventDescriptors = value; - }, "eventBlueprints.set", "eventDescriptors.set") + }, "eventBlueprints.set", "eventDescriptors.set", true) }, /** @@ -1243,7 +1243,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends newDerivedPropertyBlueprint: { value: deprecate.deprecateMethod(void 0, function (name, cardinality) { return this.newDerivedDescriptor(name, cardinality); - }, "newDerivedPropertyBlueprint", "newDerivedDescriptor") + }, "newDerivedPropertyBlueprint", "newDerivedDescriptor", true) }, /** @@ -1271,7 +1271,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends newEventBlueprint: { value: deprecate.deprecateMethod(void 0, function (name) { return this.newEventDescriptor(name); - }, "newEventBlueprint", "newEventDescriptor") + }, "newEventBlueprint", "newEventDescriptor", true) }, /** @@ -1287,7 +1287,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends newPropertyBlueprint: { value: deprecate.deprecateMethod(void 0, function (name, cardinality) { return this.newPropertyDescriptor(name, cardinality); - }, "newPropertyBlueprint", "newPropertyDescriptor") + }, "newPropertyBlueprint", "newPropertyDescriptor", true) }, /** @@ -1299,7 +1299,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends propertyBlueprintForName: { value: deprecate.deprecateMethod(void 0, function (name) { return this.propertyDescriptorForName(name); - }, "propertyBlueprintForName", "propertyDescriptorForName") + }, "propertyBlueprintForName", "propertyDescriptorForName", true) }, /** @@ -1310,7 +1310,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends propertyBlueprintGroups: { get: deprecate.deprecateMethod(void 0, function () { return this.propertyDescriptorGroups; - }, "propertyBlueprintGroups", "propertyDescriptorGroups") + }, "propertyBlueprintGroups", "propertyDescriptorGroups", true) }, /** @@ -1322,7 +1322,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends propertyBlueprintGroupForName: { value: deprecate.deprecateMethod(void 0, function (groupName) { return this.propertyDescriptorGroupForName(groupName); - }, "propertyBlueprintGroupForName", "propertyDescriptorForName") + }, "propertyBlueprintGroupForName", "propertyDescriptorForName", true) }, /** @@ -1332,7 +1332,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends propertyBlueprints: { get: deprecate.deprecateMethod(void 0, function () { return this.propertyDescriptors; - }, "propertyBlueprints", "propertyDescriptors") + }, "propertyBlueprints", "propertyDescriptors", true) }, /** @@ -1346,7 +1346,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends removeEventBlueprint: { value: deprecate.deprecateMethod(void 0, function (eventBlueprint) { this.removeEventDescriptor(eventBlueprint); - }, "removeEventBlueprint", "removeEventDescriptor") + }, "removeEventBlueprint", "removeEventDescriptor", true) }, /** @@ -1362,7 +1362,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends removePropertyBlueprint: { value: deprecate.deprecateMethod(void 0, function (propertyBlueprint) { this.removePropertyDescriptor(propertyBlueprint); - }, "removePropertyBlueprint", "removePropertyDescriptor") + }, "removePropertyBlueprint", "removePropertyDescriptor", true) }, /** @@ -1376,7 +1376,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends removePropertyBlueprintFromGroupNamed: { value: deprecate.deprecateMethod(void 0, function (propertyBlueprint, groupName) { this.removePropertyDescriptorFromGroupNamed(propertyBlueprint, groupName); - }, "removePropertyBlueprintFromGroupNamed", "removePropertyDescriptorGroupNamed") + }, "removePropertyBlueprintFromGroupNamed", "removePropertyDescriptorGroupNamed", true) }, /** @@ -1389,7 +1389,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends removePropertyBlueprintGroupNamed: { value: deprecate.deprecateMethod(void 0, function (groupName) { this.removePropertyDescriptorGroupNamed(groupName); - }, "removePropertyBlueprintGroupNamed", "removePropertyDescriptorGroupNamed") + }, "removePropertyBlueprintGroupNamed", "removePropertyDescriptorGroupNamed", true) }, /** @@ -1419,7 +1419,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends createDefaultBlueprintForObject: { value: deprecate.deprecateMethod(void 0, function (object) { return ObjectDescriptor.createDefaultObjectDescriptorForObject(object); - }, "Blueprint.createDefaultBlueprintForObject", "ObjectDescriptor.createDefaultObjectDescriptorForObject") + }, "Blueprint.createDefaultBlueprintForObject", "ObjectDescriptor.createDefaultObjectDescriptorForObject", true) }, /** diff --git a/core/meta/property-descriptor.js b/core/meta/property-descriptor.js index 7ae0ccc1bc..c68640be27 100644 --- a/core/meta/property-descriptor.js +++ b/core/meta/property-descriptor.js @@ -54,7 +54,7 @@ var Defaults = { * @class PropertyDescriptor */ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# */ { - + /** * Initialize a newly allocated property descriptor. * @function @@ -71,7 +71,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# return this; } }, - + /** * Initialize a newly allocated property descriptor. * @deprecated @@ -84,9 +84,9 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# initWithNameBlueprintAndCardinality: { value: deprecate.deprecateMethod(void 0, function (name, blueprint, cardinality) { return this.initWithNameObjectDescriptorAndCardinality(name, blueprint, cardinality); - }, "new PropertyBlueprint().initWithNameBlueprintAndCardinality", "new PropertyDescriptor().initWithNameObjectDescriptorAndCardinality") + }, "new PropertyBlueprint().initWithNameBlueprintAndCardinality", "new PropertyDescriptor().initWithNameObjectDescriptorAndCardinality", true) }, - + serializeSelf: { value:function (serializer) { serializer.setProperty("name", this.name); @@ -110,10 +110,10 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# this._setPropertyWithDefaults(serializer, "defaultValue", this.defaultValue); this._setPropertyWithDefaults(serializer, "helpKey", this.helpKey); this._setPropertyWithDefaults(serializer, "definition", this.definition); - + } }, - + deserializeSelf: { value:function (deserializer) { var value; @@ -125,13 +125,13 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# if (value !== void 0) { this._owner = value; } - + this._overridePropertyWithDefaults(deserializer, "cardinality"); - + if (this.cardinality === -1) { this.cardinality = Infinity; } - + this._overridePropertyWithDefaults(deserializer, "mandatory"); this._overridePropertyWithDefaults(deserializer, "readOnly"); this._overridePropertyWithDefaults(deserializer, "denyDelete"); @@ -146,7 +146,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# this._overridePropertyWithDefaults(deserializer, "definition"); } }, - + _setPropertyWithDefaults: { value: function (serializer, propertyName, value) { if (value !== null && value !== Defaults[propertyName]) { @@ -154,7 +154,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# } } }, - + _getPropertyWithDefaults: { value:function (deserializer) { var propertyNames = Array.prototype.slice.call(arguments).slice(1, Infinity), @@ -165,7 +165,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# return value || Defaults[propertyNames[0]]; } }, - + /** * Applies a property from the deserializer to the object. If no such * property is defined on the deserializer, then the current value @@ -185,25 +185,25 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# _overridePropertyWithDefaults: { value: function (deserializer, objectKey /*, deserializerKeys... */) { var propertyNames, value, i, n; - + if (arguments.length > 2) { propertyNames = Array.prototype.slice.call(arguments, 2, Infinity); } else { propertyNames = [objectKey]; } - + for (i = 0, n = propertyNames.length; i < n && !value; i++) { value = deserializer.getProperty(propertyNames[i]); } - + this[objectKey] = value === undefined ? Defaults[propertyNames[0]] : value; } }, - + _owner: { value: null }, - + /** * Component description attached to this property descriptor. */ @@ -212,11 +212,11 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# return this._owner; } }, - + _name: { value: null }, - + /** * Name of the object. The name is used to define the property on the * object. @@ -229,7 +229,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# return this._name; } }, - + /** * The identifier is the name of the descriptor, dot, the name of the * property descriptor, and is used to make the serialization of property @@ -245,7 +245,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# ].join("_"); } }, - + /** * Cardinality of the property descriptor. * @@ -260,7 +260,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# cardinality: { value: Defaults["cardinality"] }, - + /** * @type {boolean} * @default false @@ -268,7 +268,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# mandatory: { value: Defaults["mandatory"] }, - + /** * @type {boolean} * @default false @@ -276,7 +276,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# denyDelete: { value: Defaults["denyDelete"] }, - + /** * @type {boolean} * @default false @@ -284,7 +284,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# readOnly: { value: Defaults["readOnly"] }, - + /** * Returns true if the cardinality is more than one. * @readonly @@ -296,7 +296,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# return this.cardinality === Infinity || this.cardinality > 1; } }, - + /** * @type {boolean} * @default false @@ -306,7 +306,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# return false; } }, - + /** * @type {string} * Definition can be used to express a property as the result of evaluating an expression @@ -322,7 +322,7 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# definition: { value: null }, - + /** * @type {string} * TODO: This is semantically similar to valueDescriptor @@ -332,28 +332,28 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# valueType: { value: Defaults["valueType"] }, - + /** * @type {string} */ collectionValueType: { value: Defaults["collectionValueType"] }, - + /** * @type {string} */ valueObjectPrototypeName: { value: Defaults["valueObjectPrototypeName"] }, - + /** * @type {string} */ valueObjectModuleId: { value: Defaults["valueObjectModuleId"] }, - + /** * Promise for the descriptor targeted by this association. * @@ -377,15 +377,15 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# this._valueDescriptorReference = descriptor; } }, - + _targetObjectDescriptorReference: { value: null }, - + _enumValues: { value:null }, - + /** * List of values for enumerated value types * @type {Array} @@ -403,18 +403,18 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# } } }, - + defaultValue: { value: Defaults["defaultValue"] }, - + helpKey:{ value: Defaults["helpKey"] }, - + objectDescriptorModuleId:require("../core")._objectDescriptorModuleIdDescriptor, objectDescriptor:require("../core")._objectDescriptorDescriptor, - + /** * @type {boolean} * possible values are: "reference" | "value" | "auto" | true | false, @@ -423,11 +423,11 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# serializable: { value: true }, - + /******************************************************** * Deprecated functions */ - + /** * @deprecated * @readonly @@ -438,19 +438,19 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# isAssociationBlueprint: { get: deprecate.deprecateMethod(void 0, function () { return !!this._valueDescriptorReference; - }, "isAssociationBlueprint", "No analog") + }, "isAssociationBlueprint", "No analog", true) }, - + targetBlueprint: { get: deprecate.deprecateMethod(void 0, function () { return this.valueDescriptor; - }, "targetBlueprint.get", "valueDescriptor.get"), + }, "targetBlueprint.get", "valueDescriptor.get", true), set: deprecate.deprecateMethod(void 0, function (value) { this.valueDescriptor = value; - }, "targetBlueprint.get", "valueDescriptor.set") + }, "targetBlueprint.get", "valueDescriptor.set", true) }, - + blueprintDescriptorModuleId: require("../core")._objectDescriptorModuleIdDescriptor, blueprint: require("../core")._objectDescriptorDescriptor - + }); From 51077ca8886e7059c84bb6511ada8fcec75196ed Mon Sep 17 00:00:00 2001 From: Benoit Marchant Date: Mon, 30 Jul 2018 18:02:38 -0700 Subject: [PATCH 61/65] Fixes model constructor name --- data/service/data-service.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/data/service/data-service.js b/data/service/data-service.js index 61a2137b57..413f4a61a7 100644 --- a/data/service/data-service.js +++ b/data/service/data-service.js @@ -56,7 +56,7 @@ exports.DataService = Montage.specialize(/** @lends DataService.prototype */ { deserializeSelf: { value:function (deserializer) { var self = this, - result = null, + result = null, value; value = deserializer.getProperty("childServices"); @@ -86,7 +86,7 @@ exports.DataService = Montage.specialize(/** @lends DataService.prototype */ { if (value) { this.delegate = value; } - + return result; } }, @@ -485,7 +485,7 @@ exports.DataService = Montage.specialize(/** @lends DataService.prototype */ { value: function (type) { var descriptor = this._constructorToObjectDescriptorMap.get(type) || typeof type === "string" && this._moduleIdToObjectDescriptorMap[type]; - + return descriptor || type; } }, @@ -834,7 +834,7 @@ exports.DataService = Montage.specialize(/** @lends DataService.prototype */ { }, /** - * Performs whatever tasks are necessary to authorize + * Performs whatever tasks are necessary to authorize * this service and returns a Promise that resolves with * an Authorization object. * @@ -968,6 +968,11 @@ exports.DataService = Montage.specialize(/** @lends DataService.prototype */ { prototype = this._dataObjectPrototypes.get(type); if (type && !prototype) { prototype = Object.create(type.objectPrototype || Montage.prototype); + prototype.constuctor = type.objectPrototype.constructor; + if(prototype.constuctor.name === "constructor" ) { + Object.defineProperty(prototype.constuctor, "name", { value: type.typeName }); + } + this._dataObjectPrototypes.set(type, prototype); if (type instanceof ObjectDescriptor || type instanceof DataObjectDescriptor) { triggers = DataTrigger.addTriggers(this, type, prototype); @@ -1178,7 +1183,7 @@ exports.DataService = Montage.specialize(/** @lends DataService.prototype */ { var self = this, propertyName = propertiesToRequest.shift(), promise = this.getObjectProperties(object, propertyName); - + if (promise) { return promise.then(function () { var result = null; @@ -1309,7 +1314,7 @@ exports.DataService = Montage.specialize(/** @lends DataService.prototype */ { mapping = objectDescriptor && this.mappingWithType(objectDescriptor), data = {}, result; - + if (mapping) { Object.assign(data, this.snapshotForObject(object)); From 8f483c4a50d81dde26bd8189d5a8878eae52e288 Mon Sep 17 00:00:00 2001 From: Benoit Marchant Date: Thu, 20 Sep 2018 21:52:12 -0700 Subject: [PATCH 62/65] backward compatible fix for deserializing a mjson with a locationId that addresses aregression --- core/serialization/deserializer/montage-deserializer.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/serialization/deserializer/montage-deserializer.js b/core/serialization/deserializer/montage-deserializer.js index 9c25b4978c..68bd878adb 100644 --- a/core/serialization/deserializer/montage-deserializer.js +++ b/core/serialization/deserializer/montage-deserializer.js @@ -32,7 +32,12 @@ var MontageDeserializer = exports.MontageDeserializer = Montage.specialize({ this._serializationString = JSON.stringify(serialization); } this._require = _require; - this._locationId = locationId; + this._locationId = locationId + ? locationId.indexOf(_require.location) === 0 + ? locationId + : _require.location + locationId + : locationId; + this._reviver = new MontageReviver().init( _require, objectRequires, this.constructor ); From b275bff702a45060d8902a8931ff54a824a2210c Mon Sep 17 00:00:00 2001 From: Benoit Marchant Date: Thu, 20 Sep 2018 21:52:12 -0700 Subject: [PATCH 63/65] backward compatible fix for deserializing a mjson with a locationId that addresses aregression --- core/serialization/deserializer/montage-deserializer.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/serialization/deserializer/montage-deserializer.js b/core/serialization/deserializer/montage-deserializer.js index 9c25b4978c..68bd878adb 100644 --- a/core/serialization/deserializer/montage-deserializer.js +++ b/core/serialization/deserializer/montage-deserializer.js @@ -32,7 +32,12 @@ var MontageDeserializer = exports.MontageDeserializer = Montage.specialize({ this._serializationString = JSON.stringify(serialization); } this._require = _require; - this._locationId = locationId; + this._locationId = locationId + ? locationId.indexOf(_require.location) === 0 + ? locationId + : _require.location + locationId + : locationId; + this._reviver = new MontageReviver().init( _require, objectRequires, this.constructor ); From 2722bcb5014849abd1e8028489ebaf0eff6f70e5 Mon Sep 17 00:00:00 2001 From: Benoit Marchant Date: Thu, 20 Sep 2018 23:48:06 -0700 Subject: [PATCH 64/65] fixes formatting --- core/serialization/deserializer/montage-deserializer.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/core/serialization/deserializer/montage-deserializer.js b/core/serialization/deserializer/montage-deserializer.js index 68bd878adb..499d603d4f 100644 --- a/core/serialization/deserializer/montage-deserializer.js +++ b/core/serialization/deserializer/montage-deserializer.js @@ -32,11 +32,7 @@ var MontageDeserializer = exports.MontageDeserializer = Montage.specialize({ this._serializationString = JSON.stringify(serialization); } this._require = _require; - this._locationId = locationId - ? locationId.indexOf(_require.location) === 0 - ? locationId - : _require.location + locationId - : locationId; + this._locationId = locationId ? locationId.indexOf(_require.location) === 0 ? locationId : _require.location + locationId : locationId; this._reviver = new MontageReviver().init( _require, objectRequires, this.constructor From 58c39f744d5255be785618f2b0df59495829ed10 Mon Sep 17 00:00:00 2001 From: Thomas Jaede Date: Wed, 10 Oct 2018 11:29:39 -0700 Subject: [PATCH 65/65] Fix HtmlFragment attribute removal Reset shouldRemoveAttribute in HtmlFragment#_sanitizeNode() each time a new attribute is considered. --- ui/html-fragment.reel/html-fragment.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/html-fragment.reel/html-fragment.js b/ui/html-fragment.reel/html-fragment.js index d47654c3c0..2297b9da03 100644 --- a/ui/html-fragment.reel/html-fragment.js +++ b/ui/html-fragment.reel/html-fragment.js @@ -87,11 +87,11 @@ var HtmlFragment = exports.HtmlFragment = Component.specialize(/** @lends HtmlFr l--; } else { childAttributes = child.attributes; - shouldRemoveAttribute = false; allowedAttributesForTag = allowedAttributes[childTagName] || allowedAttributes['*']; for (ii = 0, ll = childAttributes.length; ii < ll; ii++) { + shouldRemoveAttribute = false; attribute = childAttributes[ii]; attributeName = attribute.name; attributeValue = attribute.value;