|
1 (function() { |
|
2 |
|
3 var stateChangeListener, |
|
4 GLOBAL_ENV = YUI.Env, |
|
5 config = YUI.config, |
|
6 doc = config.doc, |
|
7 docElement = doc && doc.documentElement, |
|
8 EVENT_NAME = 'onreadystatechange', |
|
9 pollInterval = config.pollInterval || 40; |
|
10 |
|
11 if (docElement.doScroll && !GLOBAL_ENV._ieready) { |
|
12 GLOBAL_ENV._ieready = function() { |
|
13 GLOBAL_ENV._ready(); |
|
14 }; |
|
15 |
|
16 /*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */ |
|
17 // Internet Explorer: use the doScroll() method on the root element. |
|
18 // This isolates what appears to be a safe moment to manipulate the |
|
19 // DOM prior to when the document's readyState suggests it is safe to do so. |
|
20 if (self !== self.top) { |
|
21 stateChangeListener = function() { |
|
22 if (doc.readyState == 'complete') { |
|
23 GLOBAL_ENV.remove(doc, EVENT_NAME, stateChangeListener); |
|
24 GLOBAL_ENV.ieready(); |
|
25 } |
|
26 }; |
|
27 GLOBAL_ENV.add(doc, EVENT_NAME, stateChangeListener); |
|
28 } else { |
|
29 GLOBAL_ENV._dri = setInterval(function() { |
|
30 try { |
|
31 docElement.doScroll('left'); |
|
32 clearInterval(GLOBAL_ENV._dri); |
|
33 GLOBAL_ENV._dri = null; |
|
34 GLOBAL_ENV._ieready(); |
|
35 } catch (domNotReady) { } |
|
36 }, pollInterval); |
|
37 } |
|
38 } |
|
39 |
|
40 })(); |
|
41 YUI.add('event-base-ie', function (Y, NAME) { |
|
42 |
|
43 /* |
|
44 * Custom event engine, DOM event listener abstraction layer, synthetic DOM |
|
45 * events. |
|
46 * @module event |
|
47 * @submodule event-base |
|
48 */ |
|
49 |
|
50 function IEEventFacade() { |
|
51 // IEEventFacade.superclass.constructor.apply(this, arguments); |
|
52 Y.DOM2EventFacade.apply(this, arguments); |
|
53 } |
|
54 |
|
55 /* |
|
56 * (intentially left out of API docs) |
|
57 * Alternate Facade implementation that is based on Object.defineProperty, which |
|
58 * is partially supported in IE8. Properties that involve setup work are |
|
59 * deferred to temporary getters using the static _define method. |
|
60 */ |
|
61 function IELazyFacade(e) { |
|
62 var proxy = Y.config.doc.createEventObject(e), |
|
63 proto = IELazyFacade.prototype; |
|
64 |
|
65 // TODO: necessary? |
|
66 proxy.hasOwnProperty = function () { return true; }; |
|
67 |
|
68 proxy.init = proto.init; |
|
69 proxy.halt = proto.halt; |
|
70 proxy.preventDefault = proto.preventDefault; |
|
71 proxy.stopPropagation = proto.stopPropagation; |
|
72 proxy.stopImmediatePropagation = proto.stopImmediatePropagation; |
|
73 |
|
74 Y.DOM2EventFacade.apply(proxy, arguments); |
|
75 |
|
76 return proxy; |
|
77 } |
|
78 |
|
79 |
|
80 var imp = Y.config.doc && Y.config.doc.implementation, |
|
81 useLazyFacade = Y.config.lazyEventFacade, |
|
82 |
|
83 buttonMap = { |
|
84 0: 1, // left click |
|
85 4: 2, // middle click |
|
86 2: 3 // right click |
|
87 }, |
|
88 relatedTargetMap = { |
|
89 mouseout: 'toElement', |
|
90 mouseover: 'fromElement' |
|
91 }, |
|
92 |
|
93 resolve = Y.DOM2EventFacade.resolve, |
|
94 |
|
95 proto = { |
|
96 init: function() { |
|
97 |
|
98 IEEventFacade.superclass.init.apply(this, arguments); |
|
99 |
|
100 var e = this._event, |
|
101 x, y, d, b, de, t; |
|
102 |
|
103 this.target = resolve(e.srcElement); |
|
104 |
|
105 if (('clientX' in e) && (!x) && (0 !== x)) { |
|
106 x = e.clientX; |
|
107 y = e.clientY; |
|
108 |
|
109 d = Y.config.doc; |
|
110 b = d.body; |
|
111 de = d.documentElement; |
|
112 |
|
113 x += (de.scrollLeft || (b && b.scrollLeft) || 0); |
|
114 y += (de.scrollTop || (b && b.scrollTop) || 0); |
|
115 |
|
116 this.pageX = x; |
|
117 this.pageY = y; |
|
118 } |
|
119 |
|
120 if (e.type == "mouseout") { |
|
121 t = e.toElement; |
|
122 } else if (e.type == "mouseover") { |
|
123 t = e.fromElement; |
|
124 } |
|
125 |
|
126 // fallback to t.relatedTarget to support simulated events. |
|
127 // IE doesn't support setting toElement or fromElement on generic |
|
128 // events, so Y.Event.simulate sets relatedTarget instead. |
|
129 this.relatedTarget = resolve(t || e.relatedTarget); |
|
130 |
|
131 // which should contain the unicode key code if this is a key event. |
|
132 // For click events, which is normalized for which mouse button was |
|
133 // clicked. |
|
134 this.which = // chained assignment |
|
135 this.button = e.keyCode || buttonMap[e.button] || e.button; |
|
136 }, |
|
137 |
|
138 stopPropagation: function() { |
|
139 this._event.cancelBubble = true; |
|
140 this._wrapper.stopped = 1; |
|
141 this.stopped = 1; |
|
142 }, |
|
143 |
|
144 stopImmediatePropagation: function() { |
|
145 this.stopPropagation(); |
|
146 this._wrapper.stopped = 2; |
|
147 this.stopped = 2; |
|
148 }, |
|
149 |
|
150 preventDefault: function(returnValue) { |
|
151 this._event.returnValue = returnValue || false; |
|
152 this._wrapper.prevented = 1; |
|
153 this.prevented = 1; |
|
154 } |
|
155 }; |
|
156 |
|
157 Y.extend(IEEventFacade, Y.DOM2EventFacade, proto); |
|
158 |
|
159 Y.extend(IELazyFacade, Y.DOM2EventFacade, proto); |
|
160 IELazyFacade.prototype.init = function () { |
|
161 var e = this._event, |
|
162 overrides = this._wrapper.overrides, |
|
163 define = IELazyFacade._define, |
|
164 lazyProperties = IELazyFacade._lazyProperties, |
|
165 prop; |
|
166 |
|
167 this.altKey = e.altKey; |
|
168 this.ctrlKey = e.ctrlKey; |
|
169 this.metaKey = e.metaKey; |
|
170 this.shiftKey = e.shiftKey; |
|
171 this.type = (overrides && overrides.type) || e.type; |
|
172 this.clientX = e.clientX; |
|
173 this.clientY = e.clientY; |
|
174 this.keyCode = // chained assignment |
|
175 this.charCode = e.keyCode; |
|
176 this.which = // chained assignment |
|
177 this.button = e.keyCode || buttonMap[e.button] || e.button; |
|
178 |
|
179 for (prop in lazyProperties) { |
|
180 if (lazyProperties.hasOwnProperty(prop)) { |
|
181 define(this, prop, lazyProperties[prop]); |
|
182 } |
|
183 } |
|
184 |
|
185 if (this._touch) { |
|
186 this._touch(e, this._currentTarget, this._wrapper); |
|
187 } |
|
188 }; |
|
189 |
|
190 IELazyFacade._lazyProperties = { |
|
191 target: function () { |
|
192 return resolve(this._event.srcElement); |
|
193 }, |
|
194 relatedTarget: function () { |
|
195 var e = this._event, |
|
196 targetProp = relatedTargetMap[e.type] || 'relatedTarget'; |
|
197 |
|
198 // fallback to t.relatedTarget to support simulated events. |
|
199 // IE doesn't support setting toElement or fromElement on generic |
|
200 // events, so Y.Event.simulate sets relatedTarget instead. |
|
201 return resolve(e[targetProp] || e.relatedTarget); |
|
202 }, |
|
203 currentTarget: function () { |
|
204 return resolve(this._currentTarget); |
|
205 }, |
|
206 |
|
207 wheelDelta: function () { |
|
208 var e = this._event; |
|
209 |
|
210 if (e.type === "mousewheel" || e.type === "DOMMouseScroll") { |
|
211 return (e.detail) ? |
|
212 (e.detail * -1) : |
|
213 // wheelDelta between -80 and 80 result in -1 or 1 |
|
214 Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1); |
|
215 } |
|
216 }, |
|
217 |
|
218 pageX: function () { |
|
219 var e = this._event, |
|
220 val = e.pageX, |
|
221 doc, bodyScroll, docScroll; |
|
222 |
|
223 if (val === undefined) { |
|
224 doc = Y.config.doc; |
|
225 bodyScroll = doc.body && doc.body.scrollLeft; |
|
226 docScroll = doc.documentElement.scrollLeft; |
|
227 |
|
228 val = e.clientX + (docScroll || bodyScroll || 0); |
|
229 } |
|
230 |
|
231 return val; |
|
232 }, |
|
233 pageY: function () { |
|
234 var e = this._event, |
|
235 val = e.pageY, |
|
236 doc, bodyScroll, docScroll; |
|
237 |
|
238 if (val === undefined) { |
|
239 doc = Y.config.doc; |
|
240 bodyScroll = doc.body && doc.body.scrollTop; |
|
241 docScroll = doc.documentElement.scrollTop; |
|
242 |
|
243 val = e.clientY + (docScroll || bodyScroll || 0); |
|
244 } |
|
245 |
|
246 return val; |
|
247 } |
|
248 }; |
|
249 |
|
250 |
|
251 /** |
|
252 * Wrapper function for Object.defineProperty that creates a property whose |
|
253 * value will be calulated only when asked for. After calculating the value, |
|
254 * the getter wll be removed, so it will behave as a normal property beyond that |
|
255 * point. A setter is also assigned so assigning to the property will clear |
|
256 * the getter, so foo.prop = 'a'; foo.prop; won't trigger the getter, |
|
257 * overwriting value 'a'. |
|
258 * |
|
259 * Used only by the DOMEventFacades used by IE8 when the YUI configuration |
|
260 * <code>lazyEventFacade</code> is set to true. |
|
261 * |
|
262 * @method _define |
|
263 * @param o {DOMObject} A DOM object to add the property to |
|
264 * @param prop {String} The name of the new property |
|
265 * @param valueFn {Function} The function that will return the initial, default |
|
266 * value for the property. |
|
267 * @static |
|
268 * @private |
|
269 */ |
|
270 IELazyFacade._define = function (o, prop, valueFn) { |
|
271 function val(v) { |
|
272 var ret = (arguments.length) ? v : valueFn.call(this); |
|
273 |
|
274 delete o[prop]; |
|
275 Object.defineProperty(o, prop, { |
|
276 value: ret, |
|
277 configurable: true, |
|
278 writable: true |
|
279 }); |
|
280 return ret; |
|
281 } |
|
282 Object.defineProperty(o, prop, { |
|
283 get: val, |
|
284 set: val, |
|
285 configurable: true |
|
286 }); |
|
287 }; |
|
288 |
|
289 if (imp && (!imp.hasFeature('Events', '2.0'))) { |
|
290 if (useLazyFacade) { |
|
291 // Make sure we can use the lazy facade logic |
|
292 try { |
|
293 Object.defineProperty(Y.config.doc.createEventObject(), 'z', {}); |
|
294 } catch (e) { |
|
295 useLazyFacade = false; |
|
296 } |
|
297 } |
|
298 |
|
299 Y.DOMEventFacade = (useLazyFacade) ? IELazyFacade : IEEventFacade; |
|
300 } |
|
301 |
|
302 |
|
303 }, '@VERSION@', {"requires": ["node-base"]}); |