aboutsummaryrefslogtreecommitdiff
path: root/node_modules/montage/ui/composer/press-composer.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/montage/ui/composer/press-composer.js')
-rw-r--r--node_modules/montage/ui/composer/press-composer.js434
1 files changed, 434 insertions, 0 deletions
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 @@
1/* <copyright>
2 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
3 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
4 (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
5 </copyright> */
6/*global require, exports*/
7/**
8 @module montage/ui/composer/press-composer
9 @requires montage
10 @requires montage/ui/composer/composer
11*/
12var Montage = require("montage").Montage,
13 Composer = require("ui/composer/composer").Composer,
14 MutableEvent = require("core/event/mutable-event").MutableEvent;
15/**
16 @class module:montage/ui/composer/press-composer.PressComposer
17 @extends module:montage/ui/composer/composer.Composer
18*/
19var PressComposer = exports.PressComposer = Montage.create(Composer,/** @lends module:montage/ui/event/composer/press-composer.PressComposer# */ {
20
21 /**
22 @event
23 @name pressstart
24 @param {Event} event
25
26 Dispatched when a press begins. It is ended by either a {@link press} or
27 {@link presscancel} event.
28 */
29
30 /**
31 @event
32 @name press
33 @param {Event} event
34
35 Dispatched when a press is complete.
36 */
37
38 /**
39 @event
40 @name presscancel
41 @param {Event} event
42
43 Dispatched when a press is canceled. This could be because the pointer
44 left the element, was claimed by another component or maybe a phone call
45 came in.
46 */
47
48 // Load/unload
49
50 load: {
51 value: function() {
52 if (window.Touch) {
53 this._element.addEventListener("touchstart", this);
54 } else {
55 this._element.addEventListener("mousedown", this);
56 }
57 }
58 },
59
60 unload: {
61 value: function() {
62 if (window.Touch) {
63 this._element.removeEventListener("touchstart", this);
64 } else {
65 this._element.removeEventListener("mousedown", this);
66 }
67 }
68 },
69
70 UNPRESSED: {
71 value: 0
72 },
73 PRESSED: {
74 value: 1
75 },
76 CANCELLED: {
77 value: 2
78 },
79
80 _state: {
81 enumerable: false,
82 value: 0
83 },
84 state: {
85 get: function() {
86 return this._state;
87 }
88 },
89
90 // Magic
91
92 /**
93 @default null
94 @private
95 */
96 _observedPointer: {
97 enumerable: false,
98 value: null
99 },
100
101 // TODO: maybe this should be split and moved into handleTouchstart
102 // and handleMousedown
103 _startInteraction: {
104 enumerable: false,
105 value: function(event) {
106 if ("disabled" in this.component && this.component.disabled) {
107 return false;
108 }
109
110 var i = 0, changedTouchCount;
111
112 if (event.type === "touchstart") {
113 changedTouchCount = event.changedTouches.length;
114 for (; i < changedTouchCount; i++) {
115 if (!this.component.eventManager.componentClaimingPointer(event.changedTouches[i].identifier)) {
116 this._observedPointer = event.changedTouches[i].identifier;
117 break;
118 }
119 }
120
121 if (this._observedPointer === null) {
122 // All touches have been claimed
123 return false;
124 }
125
126 document.addEventListener("touchend", this);
127 document.addEventListener("touchcancel", this);
128 } else if (event.type === "mousedown") {
129 this._observedPointer = "mouse";
130 // Needed to cancel action event dispatch is mouseup'd when
131 // not on the component
132 document.addEventListener("mouseup", this);
133 // Needed to preventDefault if another component has claimed
134 // the pointer
135 document.addEventListener("click", this);
136 }
137
138 this.component.eventManager.claimPointer(this._observedPointer, this);
139
140 this._dispatchPressstart(event);
141 }
142 },
143
144 /**
145 Decides what should be done based on an interaction.
146
147 @param {Event} event The event that caused this to be called.
148 */
149 _interpretInteraction: {
150 value: function(event) {
151 // TODO maybe the code should be moved out to handleClick and
152 // handleMouseup
153 var isSurrendered, target, isTarget;
154
155 if (this._observedPointer === null) {
156 this._endInteraction(event);
157 return;
158 }
159
160 isSurrendered = !this.component.eventManager.isPointerClaimedByComponent(this._observedPointer, this);
161 target = event.target;
162 while (target !== this._element && target && target.parentNode) {
163 target = target.parentNode;
164 }
165 isTarget = target === this.component.element;
166
167 if (isSurrendered && event.type === "click") {
168 // Pointer surrendered, so prevent the default action
169 event.preventDefault();
170 // No need to dispatch an event as presscancel was dispatched
171 // in surrenderPointer, just end the interaction.
172 this._endInteraction(event);
173 return;
174 }
175
176 if (!isSurrendered && isTarget && event.type === "mouseup") {
177 this._dispatchPress(event);
178 this._endInteraction(event);
179 return;
180 }
181
182 if (!isSurrendered && !isTarget && event.type === "mouseup") {
183 this._dispatchPresscancel(event);
184 this._endInteraction(event);
185 return;
186 }
187 }
188 },
189
190 /**
191 Remove event listeners after an interaction has finished.
192 */
193 _endInteraction: {
194 value: function(event) {
195 if (!event || event.type === "touchend" || event.type === "touchcancel") {
196 document.removeEventListener("touchend", this);
197 document.removeEventListener("touchcancel", this);
198 } else if (!event || event.type === "click" || event.type === "mouseup") {
199 document.removeEventListener("click", this);
200 document.removeEventListener("mouseup", this);
201 }
202
203 if (this.component.eventManager.isPointerClaimedByComponent(this._observedPointer, this)) {
204 this.component.eventManager.forfeitPointer(this._observedPointer, this);
205 }
206 this._observedPointer = null;
207 this._state = PressComposer.UNPRESSED;
208 }
209 },
210
211 /**
212 Checks if we are observing one of the changed touches. Returns the index
213 of the changed touch if one matches, otherwise returns false. Make sure
214 to check against <code>!== false</code> or <code>=== false</code> as the
215 matching index might be 0.
216
217 @function
218 @private
219 @returns {Number,Boolean} The index of the matching touch, or false
220 */
221 _changedTouchisObserved: {
222 value: function(changedTouches) {
223 if (this._observedPointer === null) {
224 return false;