Index: sdk/lib/html/dart2js/html_dart2js.dart |
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart |
index 06869b4f5f5eb528e46dc852563729ace9dea4e6..5da857794df1a15b7aab6a1e93b7c715f762c30e 100644 |
--- a/sdk/lib/html/dart2js/html_dart2js.dart |
+++ b/sdk/lib/html/dart2js/html_dart2js.dart |
@@ -8460,6 +8460,23 @@ abstract class Element extends Node implements ElementTraversal native "*Element |
@Creates('Null') // Set from Dart code; does not instantiate a native type. |
var xtag; |
+ static const EventStreamProvider<WheelEvent> mouseWheelEvent = |
+ const _CustomEventStreamProvider<WheelEvent>( |
+ Element._determineMouseWheelEventType); |
+ |
+ static String _determineMouseWheelEventType(EventTarget e) { |
+ if (JS('bool', '#.onwheel !== undefined', e)) { |
+ // W3C spec, and should be IE9+, but IE has a bug exposing onwheel. |
+ return 'wheel'; |
+ } else if (JS('bool', '#.onmousewheel !== undefined', e)) { |
+ // Chrome & IE |
+ return 'mousewheel'; |
+ } else { |
+ // Firefox |
+ return 'DOMMouseScroll'; |
+ } |
+ } |
+ |
/** |
* Creates a text node and inserts it into the DOM at the specified location. |
* |
@@ -9013,6 +9030,8 @@ abstract class Element extends Node implements ElementTraversal native "*Element |
Stream<MouseEvent> get onMouseUp => mouseUpEvent.forTarget(this); |
+ Stream<WheelEvent> get onMouseWheel => mouseWheelEvent.forTarget(this); |
+ |
Stream<Event> get onPaste => pasteEvent.forTarget(this); |
Stream<Event> get onReset => resetEvent.forTarget(this); |
@@ -23887,13 +23906,75 @@ class WebSocketEvents extends Events { |
@DomName('WheelEvent') |
class WheelEvent extends MouseEvent native "*WheelEvent" { |
+ factory WheelEvent(String type, Window view, int wheelDeltaX, int wheelDeltaY, |
+ int detail, int screenX, int screenY, int clientX, int clientY, |
+ int button, |
+ [bool canBubble = true, bool cancelable = true, bool ctrlKey = false, |
+ bool altKey = false, bool shiftKey = false, bool metaKey = false, |
+ EventTarget relatedTarget = null]) { |
+ |
+ var eventType = 'WheelEvent'; |
+ if (_Device.isFirefox) { |
+ eventType = 'MouseScrollEvents'; |
+ } |
+ final event = document.$dom_createEvent(eventType); |
+ if (event._hasInitWheelEvent) { |
+ var modifiers = []; |
+ if (ctrlKey) { |
+ modifiers.push('Control'); |
+ } |
+ if (altKey) { |
+ modifiers.push('Alt'); |
+ } |
+ if (shiftKey) { |
+ modifiers.push('Shift'); |
+ } |
+ if (metaKey) { |
+ modifiers.push('Meta'); |
+ } |
+ event._initWheelEvent(type, canBubble, cancelable, view, detail, screenX, |
+ screenY, clientX, clientY, button, relatedTarget, modifiers.join(' '), |
+ wheelDeltaX, wheelDeltaY, 0, 0); |
+ } else if (event._hasInitMouseScrollEvent) { |
+ var axis = 0; |
+ var detail = 0; |
+ if (wheelDeltaX != 0 && wheelDeltaY != 0) { |
+ throw UnsupportedError( |
+ 'Cannot modify wheelDeltaX and wheelDeltaY simultaneously'); |
+ } |
+ if (wheelDeltaY != 0) { |
+ detail = wheelDeltaY; |
+ axis = JS('int', 'MouseScrollEvent.VERTICAL_AXIS'); |
+ } else if (wheelDeltaX != 0) { |
+ detail = wheelDeltaX; |
+ axis = JS('int', 'MouseScrollEvent.HORIZONTAL_AXIS'); |
+ } |
+ event._initMouseScrollEvent(type, canBubble, cancelable, view, detail, |
+ screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, |
+ metaKey, button, relatedTarget, axis); |
+ } else { |
+ // Fallthrough for Dartium. |
+ event.$dom_initMouseEvent(type, canBubble, cancelable, view, detail, |
+ screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, |
+ metaKey, button, relatedTarget); |
+ event.$dom_initWebKitWheelEvent(wheelDeltaX, |
+ (wheelDeltaY / 120).toInt(), // Chrome does an auto-convert to pixels. |
+ view, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, |
+ metaKey); |
+ } |
+ |
+ return event; |
+ } |
+ |
+ |
/// @docsEditable true |
@DomName('WheelEvent.webkitDirectionInvertedFromDevice') |
final bool webkitDirectionInvertedFromDevice; |
/// @docsEditable true |
+ @JSName('initWebKitWheelEvent') |
@DomName('WheelEvent.initWebKitWheelEvent') |
- void initWebKitWheelEvent(int wheelDeltaX, int wheelDeltaY, Window view, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey) native; |
+ void $dom_initWebKitWheelEvent(int wheelDeltaX, int wheelDeltaY, Window view, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey) native; |
@DomName('WheelEvent.deltaY') |
@@ -23938,7 +24019,8 @@ class WheelEvent extends MouseEvent native "*WheelEvent" { |
// Handle DOMMouseScroll case where it uses detail and the axis to |
// differentiate. |
- if (JS('bool', '#.axis !== undefined && #.axis == MouseScrollEvent.HORIZONTAL_AXIS', this, this)) { |
+ if (JS('bool', '#.axis !== undefined && ' |
+ '#.axis == MouseScrollEvent.HORIZONTAL_AXIS', this, this)) { |
var detail = this._detail; |
// Firefox is normally the number of lines to scale (normally 3) |
// so multiply it by 40 to get pixels to move, matching IE & WebKit. |
@@ -23968,6 +24050,49 @@ class WheelEvent extends MouseEvent native "*WheelEvent" { |
num get _detail => JS('num', '#.detail', this); |
int get _deltaMode => JS('int', '#.deltaMode', this); |
+ bool get _hasInitMouseScrollEvent => |
+ JS('bool', '!!(#.initMouseScrollEvent)', this); |
+ |
+ @JSName('initMouseScrollEvent') |
+ void _initMouseScrollEvent( |
+ String type, |
+ bool canBubble, |
+ bool cancelable, |
+ Window view, |
+ int detail, |
+ int screenX, |
+ int screenY, |
+ int clientX, |
+ int clientY, |
+ bool ctrlKey, |
+ bool altKey, |
+ bool shiftKey, |
+ bool metaKey, |
+ int button, |
+ EventTarget relatedTarget, |
+ int axis) native; |
+ |
+ bool get _hasInitWheelEvent => |
+ JS('bool', '!!(#.initWheelEvent)', this); |
+ @JSName('initWheelEvent') |
+ void _initWheelEvent( |
+ String eventType, |
+ bool canBubble, |
+ bool cancelable, |
+ Window view, |
+ int detail, |
+ int screenX, |
+ int screenY, |
+ int clientX, |
+ int clientY, |
+ int button, |
+ EventTarget relatedTarget, |
+ String modifiersList, |
+ int deltaX, |
+ int deltaY, |
+ int deltaZ, |
+ int deltaMode) native; |
+ |
} |
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
@@ -27820,6 +27945,21 @@ class EventStreamProvider<T extends Event> { |
return new _EventStream(e, _eventType, useCapture); |
} |
} |
+ |
+/** |
+ * A factory to expose DOM events as streams, where the DOM event name has to |
+ * be determined on the fly (for example, mouse wheel events). |
+ */ |
+class _CustomEventStreamProvider<T extends Event> |
+ implements EventStreamProvider<T> { |
+ |
+ final _eventTypeGetter; |
+ const _CustomEventStreamProvider(this._eventTypeGetter); |
+ |
+ Stream<T> forTarget(EventTarget e, {bool useCapture: false}) { |
+ return new _EventStream(e, _eventTypeGetter(e), useCapture); |
+ } |
+} |
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |