From d52aca45e0357b5597e13d9b74998abb75fabea5 Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Thu, 16 Feb 2012 10:54:48 -0800 Subject: integrating the latest montage fixes for v0.6 into master Signed-off-by: Valerio Virgillito --- node_modules/montage/ui/composer/composer.js | 1 - node_modules/montage/ui/composer/press-composer.js | 434 +++++++++++++++++++++ 2 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 node_modules/montage/ui/composer/press-composer.js (limited to 'node_modules/montage/ui/composer') diff --git a/node_modules/montage/ui/composer/composer.js b/node_modules/montage/ui/composer/composer.js index eee7be67..52027a7c 100644 --- a/node_modules/montage/ui/composer/composer.js +++ b/node_modules/montage/ui/composer/composer.js @@ -47,7 +47,6 @@ exports.Composer = Montage.create(Montage, /** @lends module:montage/ui/composer * cycle after addComposer has been called on its associated component. If * `true` loading of the composer is delayed until its associated component * has prepareForActivationEvents called. - * @property * @default false */ lazyLoad: { diff --git a/node_modules/montage/ui/composer/press-composer.js b/node_modules/montage/ui/composer/press-composer.js new file mode 100644 index 00000000..942de162 --- /dev/null +++ b/node_modules/montage/ui/composer/press-composer.js @@ -0,0 +1,434 @@ +/* + This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ +/*global require, exports*/ +/** + @module montage/ui/composer/press-composer + @requires montage + @requires montage/ui/composer/composer +*/ +var Montage = require("montage").Montage, + Composer = require("ui/composer/composer").Composer, + MutableEvent = require("core/event/mutable-event").MutableEvent; +/** + @class module:montage/ui/composer/press-composer.PressComposer + @extends module:montage/ui/composer/composer.Composer +*/ +var PressComposer = exports.PressComposer = Montage.create(Composer,/** @lends module:montage/ui/event/composer/press-composer.PressComposer# */ { + + /** + @event + @name pressstart + @param {Event} event + + Dispatched when a press begins. It is ended by either a {@link press} or + {@link presscancel} event. + */ + + /** + @event + @name press + @param {Event} event + + Dispatched when a press is complete. + */ + + /** + @event + @name presscancel + @param {Event} event + + Dispatched when a press is canceled. This could be because the pointer + left the element, was claimed by another component or maybe a phone call + came in. + */ + + // Load/unload + + load: { + value: function() { + if (window.Touch) { + this._element.addEventListener("touchstart", this); + } else { + this._element.addEventListener("mousedown", this); + } + } + }, + + unload: { + value: function() { + if (window.Touch) { + this._element.removeEventListener("touchstart", this); + } else { + this._element.removeEventListener("mousedown", this); + } + } + }, + + UNPRESSED: { + value: 0 + }, + PRESSED: { + value: 1 + }, + CANCELLED: { + value: 2 + }, + + _state: { + enumerable: false, + value: 0 + }, + state: { + get: function() { + return this._state; + } + }, + + // Magic + + /** + @default null + @private + */ + _observedPointer: { + enumerable: false, + value: null + }, + + // TODO: maybe this should be split and moved into handleTouchstart + // and handleMousedown + _startInteraction: { + enumerable: false, + value: function(event) { + if ("disabled" in this.component && this.component.disabled) { + return false; + } + + var i = 0, changedTouchCount; + + if (event.type === "touchstart") { + changedTouchCount = event.changedTouches.length; + for (; i < changedTouchCount; i++) { + if (!this.component.eventManager.componentClaimingPointer(event.changedTouches[i].identifier)) { + this._observedPointer = event.changedTouches[i].identifier; + break; + } + } + + if (this._observedPointer === null) { + // All touches have been claimed + return false; + } + + document.addEventListener("touchend", this); + document.addEventListener("touchcancel", this); + } else if (event.type === "mousedown") { + this._observedPointer = "mouse"; + // Needed to cancel action event dispatch is mouseup'd when + // not on the component + document.addEventListener("mouseup", this); + // Needed to preventDefault if another component has claimed + // the pointer + document.addEventListener("click", this); + } + + this.component.eventManager.claimPointer(this._observedPointer, this); + + this._dispatchPressstart(event); + } + }, + + /** + Decides what should be done based on an interaction. + + @param {Event} event The event that caused this to be called. + */ + _interpretInteraction: { + value: function(event) { + // TODO maybe the code should be moved out to handleClick and + // handleMouseup + var isSurrendered, target, isTarget; + + if (this._observedPointer === null) { + this._endInteraction(event); + return; + } + + isSurrendered = !this.component.eventManager.isPointerClaimedByComponent(this._observedPointer, this); + target = event.target; + while (target !== this._element && target && target.parentNode) { + target = target.parentNode; + } + isTarget = target === this.component.element; + + if (isSurrendered && event.type === "click") { + // Pointer surrendered, so prevent the default action + event.preventDefault(); + // No need to dispatch an event as presscancel was dispatched + // in surrenderPointer, just end the interaction. + this._endInteraction(event); + return; + } + + if (!isSurrendered && isTarget && event.type === "mouseup") { + this._dispatchPress(event); + this._endInteraction(event); + return; + } + + if (!isSurrendered && !isTarget && event.type === "mouseup") { + this._dispatchPresscancel(event); + this._endInteraction(event); + return; + } + } + }, + + /** + Remove event listeners after an interaction has finished. + */ + _endInteraction: { + value: function(event) { + if (!event || event.type === "touchend" || event.type === "touchcancel") { + document.removeEventListener("touchend", this); + document.removeEventListener("touchcancel", this); + } else if (!event || event.type === "click" || event.type === "mouseup") { + document.removeEventListener("click", this); + document.removeEventListener("mouseup", this); + } + + if (this.component.eventManager.isPointerClaimedByComponent(this._observedPointer, this)) { + this.component.eventManager.forfeitPointer(this._observedPointer, this); + } + this._observedPointer = null; + this._state = PressComposer.UNPRESSED; + } + }, + + /** + Checks if we are observing one of the changed touches. Returns the index + of the changed touch if one matches, otherwise returns false. Make sure + to check against !== false or === false as the + matching index might be 0. + + @function + @private + @returns {Number,Boolean} The index of the matching touch, or false + */ + _changedTouchisObserved: { + value: function(changedTouches) { + if (this._observedPointer === null) { + return false; + } + + var i = 0, changedTouchCount = event.changedTouches.length; + + for (; i < changedTouchCount; i++) { + if (event.changedTouches[i].identifier === this._observedPointer) { + return i; + } + } + return false; + } + }, + + // Surrender pointer + + surrenderPointer: { + value: function(pointer, component) { + var shouldSurrender = this.callDelegateMethod("surrenderPointer", pointer, component); + if (typeof shouldSurrender !== "undefined" && shouldSurrender === false) { + return false; + } + + this._dispatchPresscancel(); + return true; + } + }, + + // Handlers + + handleTouchstart: { + value: function(event) { + this._startInteraction(event); + } + }, + handleTouchend: { + value: function(event) { + if (this._observedPointer === null) { + this._endInteraction(event); + return; + } + + if (this._changedTouchisObserved(event.changedTouches) !== false) { + if (this.component.eventManager.isPointerClaimedByComponent(this._observedPointer, this)) { + this._dispatchPress(event); + } else { + event.preventDefault(); + } + this._endInteraction(event); + } + } + }, + handleTouchcancel: { + value: function(event) { + if (this._observedPointer === null || this._changedTouchisObserved(event.changedTouches) !== false) { + if (this.component.eventManager.isPointerClaimedByComponent(this._observedPointer, this)) { + this._dispatchPresscancel(event); + } + this._endInteraction(event); + } + } + }, + + handleMousedown: { + value: function(event) { + this._startInteraction(event); + } + }, + handleClick: { + value: function(event) { + this._interpretInteraction(event); + } + }, + handleMouseup: { + value: function(event) { + this._interpretInteraction(event); + } + }, + + // Event dispatch + + _createPressEvent: { + enumerable: false, + value: function(name, event) { + var pressEvent, detail, index; + + if (!event) { + event = document.createEvent("CustomEvent"); + event.initCustomEvent(name, true, true, null); + } + + pressEvent = PressEvent.create(); + pressEvent.event = event; + pressEvent.type = name; + pressEvent.pointer = this._observedPointer; + + if (event.changedTouches && + (index = this._changedTouchisObserved(event.changedTouches)) !== false + ) { + pressEvent.touch = event.changedTouches[index]; + } + + return pressEvent; + } + }, + + /** + Dispatch the pressstart event + @private + */ + _dispatchPressstart: { + enumerable: false, + value: function (event) { + this._state = PressComposer.PRESSED; + this.dispatchEvent(this._createPressEvent("pressstart", event)); + } + }, + + /** + Dispatch the press event + @private + */ + _dispatchPress: { + enumerable: false, + value: function (event) { + this.dispatchEvent(this._createPressEvent("press", event)); + this._state = PressComposer.UNPRESSED; + } + }, + + /** + Dispatch the presscancel event + @private + */ + _dispatchPresscancel: { + enumerable: false, + value: function (event) { + this._state = PressComposer.CANCELLED; + this.dispatchEvent(this._createPressEvent("presscancel", event)); + } + } + +}); + + +var PressEvent = (function(){ + var value, eventProps, typeProps, eventPropDescriptor, typePropDescriptor, i; + + value = Montage.create(Montage, { + type: { + value: "press" + }, + _event: { + enumerable: false, + value: null + }, + event: { + get: function() { + return this._event; + }, + set: function(value) { + this._event = value; + } + }, + _touch: { + enumerable: false, + value: null + }, + touch: { + get: function() { + return this._touch; + }, + set: function(value) { + this._touch = value; + } + } + }); + + // These properties are available directly on the event + eventProps = ["altKey", "ctrlKey", "metaKey", "shiftKey", + "cancelBubble", "clipboardData", "currentTarget", "defaultPrevented", + "eventPhase", "returnValue", "srcElement", "timeStamp", "preventDefault", + "stopImmediatePropagation", "stopPropagation"]; + // These properties are available on the event in the case of mouse, and + // on the _touch in the case of touch + typeProps = ["clientX", "clientY", "pageX", "pageY", "screenX", "screenY", "target"]; + + eventPropDescriptor = function(prop) { + return { + get: function() { + return this._event[prop]; + } + }; + }; + typePropDescriptor = function(prop) { + return { + get: function() { + return (this._touch) ? this._touch[prop] : this._event[prop]; + } + }; + }; + + for (i = eventProps.length - 1; i >= 0; i--) { + Montage.defineProperty(value, eventProps[i], eventPropDescriptor(eventProps[i])); + } + for (i = typeProps.length - 1; i >= 0; i--) { + Montage.defineProperty(value, typeProps[i], typePropDescriptor(typeProps[i])); + } + + return value; +}()); -- cgit v1.2.3