sproutcore 1.11.0.rc1 → 1.11.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/VERSION.yml +1 -1
- data/lib/frameworks/sproutcore/CHANGELOG.md +93 -65
- data/lib/frameworks/sproutcore/apps/showcase/controllers/source_tree_controller.js +17 -7
- data/lib/frameworks/sproutcore/apps/showcase/resources/main_page.js +22 -2
- data/lib/frameworks/sproutcore/apps/showcase/resources/stylesheet.css +14 -0
- data/lib/frameworks/sproutcore/apps/showcase/resources/views_page.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/ajax/system/request.js +20 -8
- data/lib/frameworks/sproutcore/frameworks/ajax/system/websocket.js +58 -43
- data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/action_support.js +192 -35
- data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/delegate_support.js +7 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/responder_context.js +27 -7
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/browser.js +20 -63
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/color.js +16 -7
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +279 -159
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/render_context.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +21 -10
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +32 -28
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/targetForAction.js +107 -90
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/touch.js +33 -25
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/touch.js +23 -15
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +12 -6
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +55 -33
- data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +7 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/methods.js +228 -72
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/touch.js +54 -100
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +15 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/button.js +57 -45
- data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +9 -16
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll_view.js +111 -44
- data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +2 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/system/module.js +51 -5
- data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +13 -10
- data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +28 -9
- data/lib/frameworks/sproutcore/frameworks/runtime/system/set.js +7 -5
- data/lib/frameworks/sproutcore/frameworks/statechart/ext/function.js +51 -46
- data/lib/frameworks/sproutcore/frameworks/statechart/system/state.js +8 -5
- data/lib/frameworks/sproutcore/frameworks/statechart/system/statechart.js +12 -3
- metadata +2 -2
@@ -71,12 +71,16 @@ SC.DelegateSupport = {
|
|
71
71
|
|
72
72
|
@param {Object} delegate a delegate object. May be null.
|
73
73
|
@param {String} methodName a method name
|
74
|
-
@param {Object...} args
|
74
|
+
@param {Object...} [args...] any additional arguments
|
75
75
|
|
76
76
|
@returns {Object} value returned by delegate
|
77
77
|
*/
|
78
|
-
invokeDelegateMethod: function(delegate, methodName
|
79
|
-
|
78
|
+
invokeDelegateMethod: function(delegate, methodName) {
|
79
|
+
// Fast arguments access.
|
80
|
+
// Accessing `arguments.length` is just a Number and doesn't materialize the `arguments` object, which is costly.
|
81
|
+
var args = new Array(arguments.length - 2); // SC.A(arguments).slice(2)
|
82
|
+
for (var i = 0, len = args.length; i < len; i++) { args[i] = arguments[i + 2]; }
|
83
|
+
|
80
84
|
if (!delegate || !delegate[methodName]) delegate = this ;
|
81
85
|
|
82
86
|
var method = delegate[methodName];
|
@@ -25,11 +25,8 @@ sc_require('system/responder');
|
|
25
25
|
*/
|
26
26
|
SC.ResponderContext = {
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
//
|
31
|
-
|
32
|
-
isResponderContext: YES,
|
28
|
+
//@if(debug)
|
29
|
+
/* BEGIN DEBUG ONLY PROPERTIES AND METHODS */
|
33
30
|
|
34
31
|
/** @property
|
35
32
|
|
@@ -38,6 +35,15 @@ SC.ResponderContext = {
|
|
38
35
|
*/
|
39
36
|
trace: NO,
|
40
37
|
|
38
|
+
/* END DEBUG ONLY PROPERTIES AND METHODS */
|
39
|
+
//@endif
|
40
|
+
|
41
|
+
// ..........................................................
|
42
|
+
// PROPERTIES
|
43
|
+
//
|
44
|
+
|
45
|
+
isResponderContext: YES,
|
46
|
+
|
41
47
|
/** @property
|
42
48
|
The default responder. Set this to point to a responder object that can
|
43
49
|
respond to events when no other view in the hierarchy handles them.
|
@@ -90,6 +96,7 @@ SC.ResponderContext = {
|
|
90
96
|
return responder._scrc_name || responder.toString(); // try again
|
91
97
|
},
|
92
98
|
|
99
|
+
/** @private */
|
93
100
|
_findResponderNamesFor: function(responder, level, path) {
|
94
101
|
var key, value;
|
95
102
|
|
@@ -122,21 +129,27 @@ SC.ResponderContext = {
|
|
122
129
|
makeFirstResponder: function(responder, evt) {
|
123
130
|
var current = this.get('firstResponder'),
|
124
131
|
last = this.get('nextResponder'),
|
132
|
+
//@if(debug)
|
125
133
|
trace = this.get('trace'),
|
134
|
+
//@endif
|
126
135
|
common ;
|
127
136
|
|
128
137
|
if (this._locked) {
|
138
|
+
//@if(debug)
|
129
139
|
if (trace) {
|
130
140
|
SC.Logger.log('%@: AFTER ACTION: makeFirstResponder => %@'.fmt(this, this.responderNameFor(responder)));
|
131
141
|
}
|
142
|
+
//@endif
|
132
143
|
|
133
144
|
this._pendingResponder = responder;
|
134
145
|
return ;
|
135
146
|
}
|
136
147
|
|
148
|
+
//@if(debug)
|
137
149
|
if (trace) {
|
138
150
|
SC.Logger.log('%@: makeFirstResponder => %@'.fmt(this, this.responderNameFor(responder)));
|
139
151
|
}
|
152
|
+
//@endif
|
140
153
|
|
141
154
|
if (responder) responder.set("becomingFirstResponder", YES);
|
142
155
|
|
@@ -167,7 +180,7 @@ SC.ResponderContext = {
|
|
167
180
|
if (responder) responder.set('isFirstResponder', YES);
|
168
181
|
|
169
182
|
this._notifyDidBecomeFirstResponder(responder, responder, common);
|
170
|
-
|
183
|
+
|
171
184
|
// now, tell everyone the good news!
|
172
185
|
this.endPropertyChanges();
|
173
186
|
|
@@ -220,20 +233,25 @@ SC.ResponderContext = {
|
|
220
233
|
|
221
234
|
@param {String} action name of action
|
222
235
|
@param {Object} sender object sending the action
|
223
|
-
@param {Object} context
|
236
|
+
@param {Object} [context] additional context info
|
224
237
|
@returns {SC.Responder} the responder that handled it or null
|
225
238
|
*/
|
226
239
|
sendAction: function(action, sender, context) {
|
227
240
|
var working = this.get('firstResponder'),
|
228
241
|
last = this.get('nextResponder'),
|
242
|
+
//@if(debug)
|
229
243
|
trace = this.get('trace'),
|
244
|
+
//@endif
|
230
245
|
handled = NO,
|
231
246
|
responder;
|
232
247
|
|
233
248
|
this._locked = YES;
|
249
|
+
|
250
|
+
//@if(debug)
|
234
251
|
if (trace) {
|
235
252
|
SC.Logger.log("%@: begin action '%@' (%@, %@)".fmt(this, action, sender, context));
|
236
253
|
}
|
254
|
+
//@endif
|
237
255
|
|
238
256
|
if (!handled && !working && this.tryToPerform) {
|
239
257
|
handled = this.tryToPerform(action, sender, context);
|
@@ -249,10 +267,12 @@ SC.ResponderContext = {
|
|
249
267
|
}
|
250
268
|
}
|
251
269
|
|
270
|
+
//@if(debug)
|
252
271
|
if (trace) {
|
253
272
|
if (!handled) SC.Logger.log("%@: action '%@' NOT HANDLED".fmt(this,action));
|
254
273
|
else SC.Logger.log("%@: action '%@' handled by %@".fmt(this, action, this.responderNameFor(working)));
|
255
274
|
}
|
275
|
+
//@endif
|
256
276
|
|
257
277
|
this._locked = NO ;
|
258
278
|
|
@@ -83,48 +83,6 @@ SC.mixin(SC.browser,
|
|
83
83
|
return 0;
|
84
84
|
},
|
85
85
|
|
86
|
-
/**
|
87
|
-
@deprecated Since 1.7. Use SC.browser.compare(version, otherVersion) instead.
|
88
|
-
|
89
|
-
Pass any number of arguments, and this will check them against the browser
|
90
|
-
version split on ".". If any of them are not equal, return the inequality.
|
91
|
-
If as many arguments as were passed in are equal, return 0. If something
|
92
|
-
is NaN, return 0.
|
93
|
-
*/
|
94
|
-
|
95
|
-
// Deprecation Note:
|
96
|
-
//
|
97
|
-
// This function forces the comparison against the value of
|
98
|
-
// SC.browser.version, but the old value of SC.browser.version would
|
99
|
-
// occasionally be the browser's version or the layout engine's version,
|
100
|
-
// which could cause unexpected results. As well, there was no way to
|
101
|
-
// compare the actual browser version or OS version.
|
102
|
-
compareVersion: function () {
|
103
|
-
//@if(debug)
|
104
|
-
SC.warn('Developer Warning: SC.browser.compareVersion() has been deprecated. Please ' +
|
105
|
-
'use SC.browser.compare() instead. Example: ' +
|
106
|
-
'SC.browser.compareVersion(16,0,912) < 0 becomes ' +
|
107
|
-
'SC.browser.compare(SC.browser.engineVersion, \'16.0.912\').');
|
108
|
-
//@endif
|
109
|
-
|
110
|
-
if (this._versionSplit === undefined) {
|
111
|
-
var coerce = function (part) {
|
112
|
-
return Number(part.match(/^[0-9]+/));
|
113
|
-
};
|
114
|
-
this._versionSplit = SC.A(this.version.split('.')).map(coerce);
|
115
|
-
}
|
116
|
-
|
117
|
-
var tests = SC.A(arguments).map(Number);
|
118
|
-
for (var i = 0; i < tests.length; i++) {
|
119
|
-
var check = this._versionSplit[i] - tests[i];
|
120
|
-
if (isNaN(check)) return 0;
|
121
|
-
if (check !== 0) return check;
|
122
|
-
}
|
123
|
-
|
124
|
-
return 0;
|
125
|
-
},
|
126
|
-
|
127
|
-
|
128
86
|
/**
|
129
87
|
This simple method allows you to more safely use experimental properties and
|
130
88
|
methods in current and future browsers.
|
@@ -180,19 +138,6 @@ SC.mixin(SC.browser,
|
|
180
138
|
@returns {string} The name of the property or method on the target or SC.UNSUPPORTED if no method found.
|
181
139
|
*/
|
182
140
|
experimentalNameFor: function (target, standardName, testValue) {
|
183
|
-
var cachedNames = this._cachedNames,
|
184
|
-
targetGuid = SC.guidFor(target);
|
185
|
-
|
186
|
-
// Fast path & cache initialization.
|
187
|
-
if (!cachedNames) {
|
188
|
-
cachedNames = this._cachedNames = {};
|
189
|
-
cachedNames[targetGuid] = {};
|
190
|
-
} else if (!cachedNames[targetGuid]) {
|
191
|
-
cachedNames[targetGuid] = {};
|
192
|
-
} else if (cachedNames[targetGuid][standardName]) {
|
193
|
-
return cachedNames[targetGuid][standardName];
|
194
|
-
}
|
195
|
-
|
196
141
|
// Test the property name.
|
197
142
|
var ret = standardName;
|
198
143
|
|
@@ -220,9 +165,6 @@ SC.mixin(SC.browser,
|
|
220
165
|
}
|
221
166
|
}
|
222
167
|
|
223
|
-
// Cache the experimental property name (even SC.UNSUPPORTED) for quick repeat access.
|
224
|
-
cachedNames[targetGuid][standardName] = ret;
|
225
|
-
|
226
168
|
return ret;
|
227
169
|
},
|
228
170
|
|
@@ -262,13 +204,28 @@ SC.mixin(SC.browser,
|
|
262
204
|
@returns {string} Future-proof style name for use in the current browser or SC.UNSUPPORTED if no style support found.
|
263
205
|
*/
|
264
206
|
experimentalStyleNameFor: function (standardStyleName, testValue) {
|
265
|
-
|
266
|
-
|
207
|
+
var cachedNames = this._sc_experimentalStyleNames,
|
208
|
+
ret;
|
209
|
+
|
210
|
+
// Fast path & cache initialization.
|
211
|
+
if (!cachedNames) {
|
212
|
+
cachedNames = this._sc_experimentalStyleNames = {};
|
213
|
+
}
|
214
|
+
|
215
|
+
if (cachedNames[standardStyleName]) {
|
216
|
+
ret = cachedNames[standardStyleName];
|
217
|
+
} else {
|
218
|
+
// Test the style name.
|
219
|
+
var el = this._testEl;
|
267
220
|
|
268
|
-
|
269
|
-
|
221
|
+
// Create a test element and cache it for repeated use.
|
222
|
+
if (!el) { el = this._testEl = document.createElement("div"); }
|
270
223
|
|
271
|
-
|
224
|
+
// Cache the experimental style name (even SC.UNSUPPORTED) for quick repeat access.
|
225
|
+
ret = cachedNames[standardStyleName] = this.experimentalNameFor(el.style, standardStyleName, testValue);
|
226
|
+
}
|
227
|
+
|
228
|
+
return ret;
|
272
229
|
},
|
273
230
|
|
274
231
|
/**
|
@@ -144,7 +144,7 @@
|
|
144
144
|
if (SC.Color.supportsARGB) {
|
145
145
|
var gradient = "progid:DXImageTransform.Microsoft.gradient";
|
146
146
|
css = ("-ms-filter:" + gradient + "(startColorstr=%@1,endColorstr=%@1);" +
|
147
|
-
"filter:" + gradient + "(startColorstr=%@1,endColorstr=%@1)" +
|
147
|
+
"filter:" + gradient + "(startColorstr=%@1,endColorstr=%@1)" +
|
148
148
|
"zoom: 1").fmt(color);
|
149
149
|
} else {
|
150
150
|
css = "background-color:" + color;
|
@@ -482,7 +482,7 @@ SC.Color = SC.Object.extend(
|
|
482
482
|
*/
|
483
483
|
cssText: function (key, value) {
|
484
484
|
// Getter.
|
485
|
-
if (value === undefined) {
|
485
|
+
if (value === undefined) {
|
486
486
|
// FAST PATH: Error.
|
487
487
|
if (this.get('isError')) return this.get('errorValue');
|
488
488
|
|
@@ -641,16 +641,22 @@ SC.Color.mixin(
|
|
641
641
|
|
642
642
|
/** @private Overrides create to support creation with {a, r, g, b} hash. */
|
643
643
|
create: function() {
|
644
|
-
var
|
645
|
-
len = args.length,
|
646
|
-
vals = {},
|
644
|
+
var vals = {},
|
647
645
|
hasVals = NO,
|
648
646
|
keys = ['a', 'r', 'g', 'b'],
|
647
|
+
args, len,
|
649
648
|
hash, i, k, key;
|
649
|
+
|
650
|
+
|
651
|
+
// Fast arguments access.
|
652
|
+
// Accessing `arguments.length` is just a Number and doesn't materialize the `arguments` object, which is costly.
|
653
|
+
args = new Array(arguments.length); // SC.A(arguments)
|
654
|
+
len = args.length;
|
655
|
+
|
650
656
|
// Loop through all arguments. If any of them contain numeric a, r, g or b arguments,
|
651
657
|
// clone the hash and move the value from (e.g.) a to _a.
|
652
658
|
for (i = 0; i < len; i++) {
|
653
|
-
hash =
|
659
|
+
hash = arguments[i];
|
654
660
|
if (SC.typeOf(hash.a) === SC.T_NUMBER
|
655
661
|
|| SC.typeOf(hash.r) === SC.T_NUMBER
|
656
662
|
|| SC.typeOf(hash.g) === SC.T_NUMBER
|
@@ -665,8 +671,11 @@ SC.Color.mixin(
|
|
665
671
|
delete hash[key];
|
666
672
|
}
|
667
673
|
}
|
674
|
+
} else {
|
675
|
+
args[i] = hash;
|
668
676
|
}
|
669
677
|
}
|
678
|
+
|
670
679
|
if (hasVals) args.push(vals);
|
671
680
|
return SC.Object.create.apply(this, args);
|
672
681
|
},
|
@@ -921,7 +930,7 @@ SC.Color.mixin(
|
|
921
930
|
|
922
931
|
// ..........................................................
|
923
932
|
// Regular expressions for accepted color types
|
924
|
-
//
|
933
|
+
//
|
925
934
|
PARSE_RGBA: /^rgba\(\s*([\d]+%?)\s*,\s*([\d]+%?)\s*,\s*([\d]+%?)\s*,\s*([.\d]+)\s*\)$/,
|
926
935
|
PARSE_RGB : /^rgb\(\s*([\d]+%?)\s*,\s*([\d]+%?)\s*,\s*([\d]+%?)\s*\)$/,
|
927
936
|
PARSE_HSLA: /^hsla\(\s*(-?[\d]+)\s*\s*,\s*([\d]+)%\s*,\s*([\d]+)%\s*,\s*([.\d]+)\s*\)$/,
|
@@ -28,90 +28,10 @@ sc_require('system/core_query') ;
|
|
28
28
|
@since SproutCore 1.0
|
29
29
|
*/
|
30
30
|
SC.Event = function(originalEvent) {
|
31
|
-
|
32
|
-
// copy properties from original event, if passed in.
|
33
|
-
if (originalEvent) {
|
34
|
-
this.originalEvent = originalEvent ;
|
35
|
-
var props = SC.Event._props, key;
|
36
|
-
len = props.length;
|
37
|
-
idx = len;
|
38
|
-
while(--idx >= 0) {
|
39
|
-
key = props[idx] ;
|
40
|
-
this[key] = originalEvent[key] ;
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
|
-
// Fix timeStamp
|
45
|
-
this.timeStamp = this.timeStamp || Date.now();
|
46
|
-
|
47
|
-
// Fix target property, if necessary
|
48
|
-
// Fixes #1925 where srcElement might not be defined either
|
49
|
-
if (!this.target) this.target = this.srcElement || document;
|
50
|
-
|
51
|
-
// check if target is a textnode (safari)
|
52
|
-
if (this.target.nodeType === 3 ) this.target = this.target.parentNode;
|
53
|
-
|
54
|
-
// Add relatedTarget, if necessary
|
55
|
-
if (!this.relatedTarget && this.fromElement) {
|
56
|
-
this.relatedTarget = (this.fromElement === this.target) ? this.toElement : this.fromElement;
|
57
|
-
}
|
58
|
-
|
59
|
-
// Calculate pageX/Y if missing and clientX/Y available
|
60
|
-
if (SC.none(this.pageX) && !SC.none(this.clientX)) {
|
61
|
-
var doc = document.documentElement, body = document.body;
|
62
|
-
this.pageX = this.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
|
63
|
-
this.pageY = this.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
|
64
|
-
}
|
65
|
-
|
66
|
-
// Add which for key events
|
67
|
-
if (!this.which && ((this.charCode || originalEvent.charCode === 0) ? this.charCode : this.keyCode)) {
|
68
|
-
this.which = this.charCode || this.keyCode;
|
69
|
-
}
|
70
|
-
|
71
|
-
// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
|
72
|
-
if (!this.metaKey && this.ctrlKey) this.metaKey = this.ctrlKey;
|
73
|
-
|
74
|
-
// Add which for click: 1 == left; 2 == middle; 3 == right
|
75
|
-
// Note: button is not normalized, so don't use it
|
76
|
-
if (!this.which && this.button) {
|
77
|
-
this.which = ((this.button & 1) ? 1 : ((this.button & 2) ? 3 : ( (this.button & 4) ? 2 : 0 ) ));
|
78
|
-
}
|
79
|
-
|
80
|
-
// Normalize wheel delta values for mousewheel events
|
81
|
-
if (this.type === 'mousewheel' || this.type === 'DOMMouseScroll' || this.type === 'MozMousePixelScroll') {
|
82
|
-
var deltaMultiplier = SC.Event.MOUSE_WHEEL_MULTIPLIER;
|
83
|
-
|
84
|
-
// normalize wheelDelta, wheelDeltaX, & wheelDeltaY for Safari
|
85
|
-
if (SC.browser.isWebkit && originalEvent.wheelDelta !== undefined) {
|
86
|
-
this.wheelDelta = 0-(originalEvent.wheelDeltaY || originalEvent.wheelDeltaX);
|
87
|
-
this.wheelDeltaY = 0-(originalEvent.wheelDeltaY||0);
|
88
|
-
this.wheelDeltaX = 0-(originalEvent.wheelDeltaX||0);
|
89
|
-
|
90
|
-
// normalize wheelDelta for Firefox (all Mozilla browsers)
|
91
|
-
// note that we multiple the delta on FF to make it's acceleration more
|
92
|
-
// natural.
|
93
|
-
} else if (!SC.none(originalEvent.detail) && SC.browser.isMozilla) {
|
94
|
-
if (originalEvent.axis && (originalEvent.axis === originalEvent.HORIZONTAL_AXIS)) {
|
95
|
-
this.wheelDeltaX = originalEvent.detail;
|
96
|
-
this.wheelDeltaY = this.wheelDelta = 0;
|
97
|
-
} else {
|
98
|
-
this.wheelDeltaY = this.wheelDelta = originalEvent.detail ;
|
99
|
-
this.wheelDeltaX = 0 ;
|
100
|
-
}
|
101
|
-
|
102
|
-
// handle all other legacy browser
|
103
|
-
} else {
|
104
|
-
this.wheelDelta = this.wheelDeltaY = SC.browser.isIE || SC.browser.isOpera ? 0-originalEvent.wheelDelta : originalEvent.wheelDelta ;
|
105
|
-
this.wheelDeltaX = 0 ;
|
106
|
-
}
|
107
|
-
|
108
|
-
this.wheelDelta *= deltaMultiplier;
|
109
|
-
this.wheelDeltaX *= deltaMultiplier;
|
110
|
-
this.wheelDeltaY *= deltaMultiplier;
|
111
|
-
}
|
31
|
+
this._sc_updateNormalizedEvent(originalEvent);
|
112
32
|
|
113
33
|
return this;
|
114
|
-
}
|
34
|
+
};
|
115
35
|
|
116
36
|
SC.mixin(SC.Event, /** @scope SC.Event */ {
|
117
37
|
|
@@ -187,7 +107,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
187
107
|
named element. You can optionally pass an additional context object which
|
188
108
|
will be included on the event in the event.data property.
|
189
109
|
|
190
|
-
When your handler function is called
|
110
|
+
When your handler function is called, the function's "this" property
|
191
111
|
will point to the element the event occurred on.
|
192
112
|
|
193
113
|
The click handler for this method must have a method signature like:
|
@@ -260,21 +180,24 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
260
180
|
|
261
181
|
// if target is a function, treat it as the method, with optional context
|
262
182
|
if (SC.typeOf(target) === SC.T_FUNCTION) {
|
263
|
-
context = method;
|
183
|
+
context = method;
|
184
|
+
method = target;
|
185
|
+
target = null;
|
264
186
|
|
265
187
|
// handle case where passed method is a key on the target.
|
266
188
|
} else if (target && SC.typeOf(method) === SC.T_STRING) {
|
267
|
-
method = target[method]
|
189
|
+
method = target[method];
|
268
190
|
}
|
269
191
|
|
270
192
|
// Get the handlers queue for this element/eventType. If the queue does
|
271
193
|
// not exist yet, create it and also setup the shared listener for this
|
272
194
|
// eventType.
|
273
|
-
var events = SC.data(elem, "sc_events") || SC.data(elem, "sc_events", {})
|
195
|
+
var events = SC.data(elem, "sc_events") || SC.data(elem, "sc_events", {}),
|
274
196
|
handlers = events[eventType];
|
197
|
+
|
275
198
|
if (!handlers) {
|
276
|
-
handlers = events[eventType] = {}
|
277
|
-
this._addEventListener(elem, eventType, useCapture)
|
199
|
+
handlers = events[eventType] = {};
|
200
|
+
this._addEventListener(elem, eventType, useCapture);
|
278
201
|
}
|
279
202
|
|
280
203
|
// Build the handler array and add to queue
|
@@ -420,7 +343,8 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
420
343
|
timeStamp: Date.now(),
|
421
344
|
bubbles: (this.NO_BUBBLE.indexOf(eventType)<0),
|
422
345
|
cancelled: NO,
|
423
|
-
normalized: YES
|
346
|
+
normalized: YES,
|
347
|
+
simulated: true
|
424
348
|
});
|
425
349
|
if (attrs) SC.mixin(ret, attrs) ;
|
426
350
|
return ret ;
|
@@ -445,18 +369,18 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
445
369
|
|
446
370
|
@param elem {Element} the target element
|
447
371
|
@param eventType {String} the event type
|
448
|
-
@param
|
372
|
+
@param event {SC.Event} [event] pre-normalized event to pass to handler
|
449
373
|
@param donative ??
|
450
374
|
@returns {Boolean} Return value of trigger or undefined if not fired
|
451
375
|
*/
|
452
|
-
trigger: function(elem, eventType,
|
376
|
+
trigger: function(elem, eventType, event, donative) {
|
453
377
|
|
454
378
|
// if a CQ object is passed in, either call add on each item in the
|
455
379
|
// matched set, or simply get the first element and use that.
|
456
380
|
if (elem && elem.isCoreQuery) {
|
457
381
|
if (elem.length > 0) {
|
458
382
|
elem.forEach(function(e) {
|
459
|
-
this.trigger(e, eventType,
|
383
|
+
this.trigger(e, eventType, event, donative);
|
460
384
|
}, this);
|
461
385
|
return this;
|
462
386
|
} else elem = elem[0];
|
@@ -466,25 +390,23 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
466
390
|
// don't do events on text and comment nodes
|
467
391
|
if ( elem.nodeType === 3 || elem.nodeType === 8 ) return undefined;
|
468
392
|
|
469
|
-
// Normalize
|
470
|
-
|
393
|
+
// Backwards-compatibility. Normalize from an Array.
|
394
|
+
if (SC.typeOf(event) === SC.T_ARRAY) { event = event[0]; }
|
471
395
|
|
472
396
|
var ret, fn = SC.typeOf(elem[eventType] || null) === SC.T_FUNCTION ,
|
473
|
-
|
397
|
+
current, onfoo, isClick;
|
474
398
|
|
475
399
|
// Get the event to pass, creating a fake one if necessary
|
476
|
-
event = args[0];
|
477
400
|
if (!event || !event.preventDefault) {
|
478
|
-
event = this.simulateEvent(elem, eventType)
|
479
|
-
args.unshift(event) ;
|
401
|
+
event = this.simulateEvent(elem, eventType);
|
480
402
|
}
|
481
403
|
|
482
|
-
event.type = eventType
|
404
|
+
event.type = eventType;
|
483
405
|
|
484
406
|
// Trigger the event - bubble if enabled
|
485
407
|
current = elem;
|
486
408
|
do {
|
487
|
-
ret = SC.Event.handle.
|
409
|
+
ret = SC.Event.handle.call(current, event);
|
488
410
|
current = (current===document) ? null : (current.parentNode || document);
|
489
411
|
} while(!ret && event.bubbles && current);
|
490
412
|
current = null ;
|
@@ -492,7 +414,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
492
414
|
// Handle triggering native .onfoo handlers
|
493
415
|
onfoo = elem["on" + eventType] ;
|
494
416
|
isClick = SC.$.nodeName(elem, 'a') && eventType === 'click';
|
495
|
-
if ((!fn || isClick) && onfoo && onfoo.
|
417
|
+
if ((!fn || isClick) && onfoo && onfoo.call(elem, event) === NO) ret = NO;
|
496
418
|
|
497
419
|
// Trigger the native events (except for clicks on links)
|
498
420
|
if (fn && donative !== NO && ret !== NO && !isClick) {
|
@@ -520,50 +442,55 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
520
442
|
Note that like other parts of this library, the handle function does not
|
521
443
|
support namespaces.
|
522
444
|
|
523
|
-
@param event {
|
445
|
+
@param event {DOMEvent} the event to handle
|
524
446
|
@returns {Boolean}
|
525
447
|
*/
|
526
|
-
handle: function(event) {
|
448
|
+
handle: function (event) {
|
527
449
|
|
528
450
|
// ignore events triggered after window is unloaded or if double-called
|
529
451
|
// from within a trigger.
|
530
|
-
if ((typeof SC === "undefined") || SC.Event.triggered) return
|
531
|
-
|
532
|
-
// returned undefined or NO
|
533
|
-
var val, ret, handlers, args, key, handler, method, target;
|
452
|
+
if ((typeof SC === "undefined") || SC.Event.triggered) return true;
|
534
453
|
|
535
|
-
//
|
536
|
-
|
537
|
-
args = SC.A(arguments);
|
538
|
-
args[0] = event = SC.Event.normalizeEvent(event || window.event);
|
454
|
+
// returned undefined or false
|
455
|
+
var val, ret, handlers, method, target;
|
539
456
|
|
540
457
|
// get the handlers for this event type
|
541
458
|
handlers = (SC.data(this, "sc_events") || {})[event.type];
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
//
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
459
|
+
|
460
|
+
// no handlers for the event
|
461
|
+
if (!handlers) {
|
462
|
+
val = false; // nothing to do
|
463
|
+
|
464
|
+
} else {
|
465
|
+
// normalize event across browsers. The new event will actually wrap the real event with a normalized API.
|
466
|
+
event = SC.Event.normalizeEvent(event || window.event);
|
467
|
+
|
468
|
+
// invoke all handlers
|
469
|
+
for (var key in handlers) {
|
470
|
+
var handler = handlers[key];
|
471
|
+
|
472
|
+
method = handler[1];
|
473
|
+
|
474
|
+
// Pass in a reference to the handler function itself so that we can remove it later.
|
475
|
+
event.handler = method;
|
476
|
+
event.data = event.context = handler[2];
|
477
|
+
|
478
|
+
target = handler[0] || this;
|
479
|
+
ret = method.call(target, event);
|
480
|
+
|
481
|
+
if (val !== false) val = ret;
|
482
|
+
|
483
|
+
// if method returned NO, do not continue. Stop propagation and
|
484
|
+
// return default. Note that we test explicitly for NO since
|
485
|
+
// if the handler returns no specific value, we do not want to stop.
|
486
|
+
if ( ret === false ) {
|
487
|
+
event.preventDefault();
|
488
|
+
event.stopPropagation();
|
489
|
+
}
|
566
490
|
}
|
491
|
+
|
492
|
+
// Clean up the cached normalized SC.Event so that it's not holding onto extra memory.
|
493
|
+
if (event.originalEvent && !event.originalEvent.simulated) { event._sc_clearNormalizedEvent(); }
|
567
494
|
}
|
568
495
|
|
569
496
|
return val;
|
@@ -619,12 +546,13 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
619
546
|
return YES;
|
620
547
|
},
|
621
548
|
|
622
|
-
handler: function(event) {
|
549
|
+
handler: function (event) {
|
623
550
|
// If we actually just moused on to a sub-element, ignore it
|
624
551
|
if ( SC.Event._withinElement(event, this) ) return YES;
|
625
552
|
// Execute the right handlers by setting the event type to mouseenter
|
626
553
|
event.type = "mouseenter";
|
627
|
-
|
554
|
+
|
555
|
+
return SC.Event.handle.call(this, event);
|
628
556
|
}
|
629
557
|
},
|
630
558
|
|
@@ -643,12 +571,12 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
643
571
|
return YES;
|
644
572
|
},
|
645
573
|
|
646
|
-
handler: function(event) {
|
574
|
+
handler: function (event) {
|
647
575
|
// If we actually just moused on to a sub-element, ignore it
|
648
576
|
if ( SC.Event._withinElement(event, this) ) return YES;
|
649
577
|
// Execute the right handlers by setting the event type to mouseleave
|
650
578
|
event.type = "mouseleave";
|
651
|
-
return SC.Event.handle.
|
579
|
+
return SC.Event.handle.call(this, event);
|
652
580
|
}
|
653
581
|
}
|
654
582
|
},
|
@@ -693,16 +621,17 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
693
621
|
@param eventType {String} the event type
|
694
622
|
*/
|
695
623
|
_addEventListener: function(elem, eventType, useCapture) {
|
696
|
-
var listener,
|
624
|
+
var listener,
|
625
|
+
special = this.special[eventType] ;
|
697
626
|
|
698
627
|
if (!useCapture) {
|
699
|
-
useCapture =
|
628
|
+
useCapture = false;
|
700
629
|
}
|
701
630
|
|
702
631
|
// Check for a special event handler
|
703
632
|
// Only use addEventListener/attachEvent if the special
|
704
|
-
// events handler returns
|
705
|
-
if ( !special || special.setup.call(elem)===
|
633
|
+
// events handler returns false
|
634
|
+
if ( !special || special.setup.call(elem) === false) {
|
706
635
|
|
707
636
|
// Save element in cache. This must be removed later to avoid
|
708
637
|
// memory leaks.
|
@@ -711,9 +640,9 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
711
640
|
|
712
641
|
// Either retrieve the previously cached listener or cache a new one.
|
713
642
|
listener = SC.data(elem, "listener") || SC.data(elem, "listener",
|
714
|
-
|
715
|
-
|
716
|
-
|
643
|
+
function handle_event (event) {
|
644
|
+
return SC.Event.handle.call(SC.Event._elements[guid], event);
|
645
|
+
});
|
717
646
|
|
718
647
|
// Bind the global event handler to the element
|
719
648
|
if (elem.addEventListener) {
|
@@ -723,13 +652,9 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
723
652
|
// there is currently a hack in request , but it needs to fixed here.
|
724
653
|
elem.attachEvent("on" + eventType, listener);
|
725
654
|
}
|
726
|
-
//
|
727
|
-
// else {
|
728
|
-
// elem.onreadystatechange = listener;
|
729
|
-
// }
|
730
655
|
}
|
731
656
|
|
732
|
-
elem = special = listener = null
|
657
|
+
elem = special = listener = null; // avoid memory leak
|
733
658
|
},
|
734
659
|
|
735
660
|
/** @private
|
@@ -764,24 +689,51 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
|
|
764
689
|
|
765
690
|
_elements: {},
|
766
691
|
|
692
|
+
_sc_normalizedEvents: null,
|
693
|
+
|
767
694
|
// implement preventDefault() in a cross platform way
|
768
695
|
|
769
696
|
/** @private Take an incoming event and convert it to a normalized event. */
|
770
|
-
normalizeEvent: function(event) {
|
771
|
-
|
772
|
-
|
773
|
-
|
697
|
+
normalizeEvent: function (event) {
|
698
|
+
var ret;
|
699
|
+
|
700
|
+
// Create the cache the first time.
|
701
|
+
if (!this._sc_normalizedEvents) { this._sc_normalizedEvents = {}; }
|
702
|
+
ret = this._sc_normalizedEvents[event.type];
|
703
|
+
|
704
|
+
// Create a new normalized SC.Event.
|
705
|
+
if (!ret) {
|
706
|
+
if (event === window.event) {
|
707
|
+
// IE can't do event.normalized on an Event object
|
708
|
+
ret = SC.Event.create(event) ;
|
709
|
+
} else {
|
710
|
+
ret = event.normalized ? event : SC.Event.create(event) ;
|
711
|
+
}
|
712
|
+
|
713
|
+
// When passed an SC.Event, don't re-normalize it.
|
714
|
+
// TODO: This is hacky nonsense left over from a whole pile of bad decisions in SC.Event—
|
715
|
+
} else if (event.normalized) {
|
716
|
+
ret = event;
|
717
|
+
|
718
|
+
// Update the cached normalized SC.Event with the new DOM event.
|
774
719
|
} else {
|
775
|
-
|
720
|
+
ret._sc_updateNormalizedEvent(event);
|
776
721
|
}
|
722
|
+
|
723
|
+
// Cache the normalized event object for this type of event. This allows us to avoid recreating
|
724
|
+
// SC.Event objects constantly for noisy events such as 'mousemove' or 'mousewheel'.
|
725
|
+
this._sc_normalizedEvents[event.type] = ret;
|
726
|
+
|
727
|
+
return ret;
|
777
728
|
},
|
778
729
|
|
779
730
|
_global: {},
|
780
731
|
|
781
732
|
/** @private properties to copy from native event onto the event */
|
782
|
-
|
733
|
+
// TODO: Remove this needless copy.
|
734
|
+
_props: ['altKey', 'attrChange', 'attrName', 'bubbles', 'button', 'cancelable', 'charCode', 'clientX', 'clientY', 'ctrlKey', 'currentTarget', 'data', 'detail', 'fromElement', 'handler', 'keyCode', 'metaKey', 'newValue', 'originalTarget', 'pageX', 'pageY', 'prevValue', 'relatedNode', 'relatedTarget', 'screenX', 'screenY', 'shiftKey', 'srcElement', 'target', 'timeStamp', 'toElement', 'type', 'view', 'which', 'touches', 'targetTouches', 'changedTouches', 'animationName', 'elapsedTime', 'dataTransfer']
|
783
735
|
|
784
|
-
})
|
736
|
+
});
|
785
737
|
|
786
738
|
SC.Event.prototype = {
|
787
739
|
|
@@ -792,7 +744,175 @@ SC.Event.prototype = {
|
|
792
744
|
|
793
745
|
@type Boolean
|
794
746
|
*/
|
795
|
-
hasCustomEventHandling:
|
747
|
+
hasCustomEventHandling: false,
|
748
|
+
|
749
|
+
/** @private Clear out the originalEvent from the SC.Event instance. */
|
750
|
+
_sc_clearNormalizedEvent: function () {
|
751
|
+
// Remove the original event.
|
752
|
+
this.originalEvent = null;
|
753
|
+
|
754
|
+
// Reset the custom event handling and normalized flag.
|
755
|
+
this.hasCustomEventHandling = false;
|
756
|
+
this.normalized = false;
|
757
|
+
|
758
|
+
// Remove non-primitive properties copied over from the original event. While these will
|
759
|
+
// be overwritten, it's best to quickly null them out to avoid any issues.
|
760
|
+
var props = SC.Event._props,
|
761
|
+
idx;
|
762
|
+
|
763
|
+
idx = props.length;
|
764
|
+
while(--idx >= 0) {
|
765
|
+
var key = props[idx];
|
766
|
+
this[key] = null;
|
767
|
+
}
|
768
|
+
|
769
|
+
// Remove the custom properties associated with the previous original event. While these will
|
770
|
+
// be overwritten, it's best to quickly null them out to avoid any issues.
|
771
|
+
this.timeStamp = null;
|
772
|
+
this.target = null;
|
773
|
+
this.relatedTarget = null;
|
774
|
+
this.pageX = null;
|
775
|
+
this.pageY = null;
|
776
|
+
this.which = null;
|
777
|
+
this.metaKey = null;
|
778
|
+
this.wheelDelta = null;
|
779
|
+
this.wheelDeltaY = null;
|
780
|
+
this.wheelDeltaX = null;
|
781
|
+
},
|
782
|
+
|
783
|
+
/** @private Update the SC.Event instance with the new originalEvent. */
|
784
|
+
_sc_updateNormalizedEvent: function (originalEvent) {
|
785
|
+
var idx, len;
|
786
|
+
|
787
|
+
// Flag.
|
788
|
+
this.normalized = true;
|
789
|
+
|
790
|
+
// copy properties from original event, if passed in.
|
791
|
+
if (originalEvent) {
|
792
|
+
this.originalEvent = originalEvent ;
|
793
|
+
var props = SC.Event._props,
|
794
|
+
key;
|
795
|
+
|
796
|
+
len = props.length;
|
797
|
+
idx = len;
|
798
|
+
while(--idx >= 0) {
|
799
|
+
key = props[idx] ;
|
800
|
+
this[key] = originalEvent[key] ;
|
801
|
+
}
|
802
|
+
}
|
803
|
+
|
804
|
+
// Fix timeStamp
|
805
|
+
this.timeStamp = this.timeStamp || Date.now();
|
806
|
+
|
807
|
+
// Fix target property, if necessary
|
808
|
+
// Fixes #1925 where srcElement might not be defined either
|
809
|
+
if (!this.target) this.target = this.srcElement || document;
|
810
|
+
|
811
|
+
// check if target is a textnode (safari)
|
812
|
+
if (this.target.nodeType === 3 ) this.target = this.target.parentNode;
|
813
|
+
|
814
|
+
// Add relatedTarget, if necessary
|
815
|
+
if (!this.relatedTarget && this.fromElement) {
|
816
|
+
this.relatedTarget = (this.fromElement === this.target) ? this.toElement : this.fromElement;
|
817
|
+
}
|
818
|
+
|
819
|
+
// Calculate pageX/Y if missing and clientX/Y available
|
820
|
+
if (SC.none(this.pageX) && !SC.none(this.clientX)) {
|
821
|
+
var doc = document.documentElement, body = document.body;
|
822
|
+
this.pageX = this.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
|
823
|
+
this.pageY = this.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
|
824
|
+
}
|
825
|
+
|
826
|
+
// Add which for key events
|
827
|
+
if (!this.which && ((this.charCode || originalEvent.charCode === 0) ? this.charCode : this.keyCode)) {
|
828
|
+
this.which = this.charCode || this.keyCode;
|
829
|
+
}
|
830
|
+
|
831
|
+
// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
|
832
|
+
if (!this.metaKey && this.ctrlKey) this.metaKey = this.ctrlKey;
|
833
|
+
|
834
|
+
// Add which for click: 1 == left; 2 == middle; 3 == right
|
835
|
+
// Note: button is not normalized, so don't use it
|
836
|
+
if (!this.which && this.button) {
|
837
|
+
this.which = ((this.button & 1) ? 1 : ((this.button & 2) ? 3 : ( (this.button & 4) ? 2 : 0 ) ));
|
838
|
+
}
|
839
|
+
|
840
|
+
// Normalize wheel delta values for mousewheel events.
|
841
|
+
/*
|
842
|
+
Taken from https://developer.mozilla.org/en-US/docs/Web/Events/mousewheel
|
843
|
+
IE and Opera (Presto) only support wheelDelta attribute and do not support horizontal scroll.
|
844
|
+
|
845
|
+
The wheelDeltaX attribute value indicates the wheelDelta attribute value along the horizontal axis. When a user operates the device for scrolling to right, the value is negative. Otherwise, i.e., if it's to left, the value is positive.
|
846
|
+
|
847
|
+
The wheelDeltaY attribute value indicates the wheelDelta attribute value along the vertical axis. The sign of the value is the same as the wheelDelta attribute value.
|
848
|
+
|
849
|
+
IE
|
850
|
+
|
851
|
+
The value is the same as the delta value of WM_MOUSEWHEEL or WM_MOUSEHWHEEL. It means that if the mouse wheel doesn't support high resolution scroll, the value is 120 per notch. The value isn't changed even if the scroll amount of system settings is page scroll.
|
852
|
+
|
853
|
+
## Chrome
|
854
|
+
|
855
|
+
On Windows, the value is the same as the delta value of WM_MOUSEWHEEL or WM_MOUSEHWHEEL. And also, the value isn't changed even if the scroll amount of system settings is page scroll, i.e., the value is the same as IE on Windows.
|
856
|
+
|
857
|
+
On Linux, the value is 120 or -120 per native wheel event. This makes the same behavior as IE and Chrome for Windows.
|
858
|
+
|
859
|
+
On Mac, the value is complicated. The value is changed if the device that causes the native wheel event supports continuous scroll.
|
860
|
+
|
861
|
+
If the device supports continuous scroll (e.g., trackpad of MacBook or mouse wheel which can be turned smoothly), the value is computed from accelerated scroll amount. In this case, the value is the same as Safari.
|
862
|
+
|
863
|
+
If the device does not support continuous scroll (typically, old mouse wheel which cannot be turned smoothly), the value is computed from non-accelerated scroll amount (120 per notch). In this case, the value is different from Safari.
|
864
|
+
|
865
|
+
This difference makes a serious issue for web application developers. That is, web developers cannot know if mousewheel event is caused by which device.
|
866
|
+
|
867
|
+
See WebInputEventFactory::mouseWheelEvent of the Chromium's source code for the detail.
|
868
|
+
|
869
|
+
## Safari
|
870
|
+
|
871
|
+
The value is always computed from accelerated scroll amount. This is really different from other browsers except Chrome with continuous scroll supported device.
|
872
|
+
|
873
|
+
Note: tested with the Windows package, the earliest available version was Safari 3.0 from 2007. It could be that earlier versions (on Mac) support the properties too.
|
874
|
+
|
875
|
+
## Opera (Presto)
|
876
|
+
|
877
|
+
The value is always the detail attribute value ✕ 40.
|
878
|
+
|
879
|
+
On Windows, since the detail attribute value is computed from actual scroll amount, the value is different from other browsers except the scroll amount per notch is 3 lines in system settings or a page.
|
880
|
+
|
881
|
+
On Linux, the value is 80 or -80 per native wheel event. This is different from other browsers.
|
882
|
+
|
883
|
+
On Mac, the detail attribute value is computed from accelerated scroll amout of native event. The value is usually much bigger than Safari's or Chrome's value.
|
884
|
+
*/
|
885
|
+
if (this.type === 'mousewheel' || this.type === 'DOMMouseScroll' || this.type === 'MozMousePixelScroll') {
|
886
|
+
var deltaMultiplier = SC.Event.MOUSE_WHEEL_MULTIPLIER;
|
887
|
+
|
888
|
+
// normalize wheelDelta, wheelDeltaX, & wheelDeltaY for Safari
|
889
|
+
if (SC.browser.isWebkit && originalEvent.wheelDelta !== undefined) {
|
890
|
+
this.wheelDelta = 0 - (originalEvent.wheelDeltaY || originalEvent.wheelDeltaX);
|
891
|
+
this.wheelDeltaY = 0 - (originalEvent.wheelDeltaY || 0);
|
892
|
+
this.wheelDeltaX = 0 - (originalEvent.wheelDeltaX || 0);
|
893
|
+
|
894
|
+
// normalize wheelDelta for Firefox (all Mozilla browsers)
|
895
|
+
// note that we multiple the delta on FF to make it's acceleration more natural.
|
896
|
+
} else if (!SC.none(originalEvent.detail) && SC.browser.isMozilla) {
|
897
|
+
if (originalEvent.axis && (originalEvent.axis === originalEvent.HORIZONTAL_AXIS)) {
|
898
|
+
this.wheelDeltaX = originalEvent.detail;
|
899
|
+
this.wheelDelta = this.wheelDeltaY = 0;
|
900
|
+
} else {
|
901
|
+
this.wheelDelta = this.wheelDeltaY = originalEvent.detail;
|
902
|
+
this.wheelDeltaX = 0;
|
903
|
+
}
|
904
|
+
|
905
|
+
// handle all other legacy browser
|
906
|
+
} else {
|
907
|
+
this.wheelDelta = this.wheelDeltaY = SC.browser.isIE || SC.browser.isOpera ? 0 - originalEvent.wheelDelta : originalEvent.wheelDelta;
|
908
|
+
this.wheelDeltaX = 0;
|
909
|
+
}
|
910
|
+
|
911
|
+
this.wheelDelta *= deltaMultiplier;
|
912
|
+
this.wheelDeltaX *= deltaMultiplier;
|
913
|
+
this.wheelDeltaY *= deltaMultiplier;
|
914
|
+
}
|
915
|
+
},
|
796
916
|
|
797
917
|
/**
|
798
918
|
Returns the touches owned by the supplied view.
|