71e4e96699
Review URL: https://codereview.chromium.org//64553010 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@30307 260f80e4-7a28-3924-810f-c04153c831b5
398 lines
13 KiB
Plaintext
398 lines
13 KiB
Plaintext
// 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.
|
|
|
|
part of $LIBRARYNAME;
|
|
|
|
@DocsEditable()
|
|
$if DART2JS
|
|
$(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS native "Window,DOMWindow" {
|
|
$else
|
|
$(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
|
|
$endif
|
|
|
|
/**
|
|
* Returns a Future that completes just before the window is about to
|
|
* repaint so the user can draw an animation frame.
|
|
*
|
|
* If you need to later cancel this animation, use [requestAnimationFrame]
|
|
* instead.
|
|
*
|
|
* The [Future] completes to a timestamp that represents a floating
|
|
* point value of the number of milliseconds that have elapsed since the page
|
|
* started to load (which is also the timestamp at this call to
|
|
* animationFrame).
|
|
*
|
|
* Note: The code that runs when the future completes should call
|
|
* [animationFrame] again for the animation to continue.
|
|
*/
|
|
Future<num> get animationFrame {
|
|
var completer = new Completer<num>();
|
|
requestAnimationFrame((time) {
|
|
completer.complete(time);
|
|
});
|
|
return completer.future;
|
|
}
|
|
|
|
$if DART2JS
|
|
/**
|
|
* The newest document in this window.
|
|
*
|
|
* ## Other resources
|
|
*
|
|
* * [Loading web pages]
|
|
* (http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html)
|
|
* from WHATWG.
|
|
*/
|
|
Document get document => JS('Document', '#.document', this);
|
|
|
|
WindowBase _open2(url, name) => JS('Window', '#.open(#,#)', this, url, name);
|
|
|
|
WindowBase _open3(url, name, options) =>
|
|
JS('Window', '#.open(#,#,#)', this, url, name, options);
|
|
|
|
/**
|
|
* Opens a new window.
|
|
*
|
|
* ## Other resources
|
|
*
|
|
* * [Window.open]
|
|
* (https://developer.mozilla.org/en-US/docs/Web/API/Window.open) from MDN.
|
|
* * [Window open]
|
|
* (http://docs.webplatform.org/wiki/dom/methods/open) from WebPlatform.org.
|
|
*/
|
|
WindowBase open(String url, String name, [String options]) {
|
|
if (options == null) {
|
|
return _DOMWindowCrossFrame._createSafe(_open2(url, name));
|
|
} else {
|
|
return _DOMWindowCrossFrame._createSafe(_open3(url, name, options));
|
|
}
|
|
}
|
|
|
|
// API level getter and setter for Location.
|
|
// TODO: The cross domain safe wrapper can be inserted here or folded into
|
|
// _LocationWrapper.
|
|
/**
|
|
* The current location of this window.
|
|
*
|
|
* Location currentLocation = window.location;
|
|
* print(currentLocation.href); // 'http://www.example.com:80/'
|
|
*/
|
|
Location get location {
|
|
// Firefox work-around for Location. The Firefox location object cannot be
|
|
// made to behave like a Dart object so must be wrapped.
|
|
var result = _location;
|
|
if (_isDartLocation(result)) return result; // e.g. on Chrome.
|
|
if (null == _location_wrapper) {
|
|
_location_wrapper = new _LocationWrapper(result);
|
|
}
|
|
return _location_wrapper;
|
|
}
|
|
|
|
// TODO: consider forcing users to do: window.location.assign('string').
|
|
/**
|
|
* Sets the window's location, which causes the browser to navigate to the new
|
|
* location. [value] may be a Location object or a string.
|
|
*/
|
|
void set location(value) {
|
|
if (value is _LocationWrapper) {
|
|
_location = value._ptr;
|
|
} else {
|
|
_location = value;
|
|
}
|
|
}
|
|
|
|
_LocationWrapper _location_wrapper; // Cached wrapped Location object.
|
|
|
|
// Native getter and setter to access raw Location object.
|
|
dynamic get _location => JS('Location|=Object', '#.location', this);
|
|
void set _location(value) {
|
|
JS('void', '#.location = #', this, value);
|
|
}
|
|
// Prevent compiled from thinking 'location' property is available for a Dart
|
|
// member.
|
|
@JSName('location')
|
|
_protect_location() native;
|
|
|
|
static _isDartLocation(thing) {
|
|
// On Firefox the code that implements 'is Location' fails to find the patch
|
|
// stub on Object.prototype and throws an exception.
|
|
try {
|
|
return thing is Location;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called to draw an animation frame and then request the window to repaint
|
|
* after [callback] has finished (creating the animation).
|
|
*
|
|
* Use this method only if you need to later call [cancelAnimationFrame]. If
|
|
* not, the preferred Dart idiom is to set animation frames by calling
|
|
* [animationFrame], which returns a Future.
|
|
*
|
|
* Returns a non-zero valued integer to represent the request id for this
|
|
* request. This value only needs to be saved if you intend to call
|
|
* [cancelAnimationFrame] so you can specify the particular animation to
|
|
* cancel.
|
|
*
|
|
* Note: The supplied [callback] needs to call [requestAnimationFrame] again
|
|
* for the animation to continue.
|
|
*/
|
|
@DomName('Window.requestAnimationFrame')
|
|
int requestAnimationFrame(RequestAnimationFrameCallback callback) {
|
|
_ensureRequestAnimationFrame();
|
|
return _requestAnimationFrame(_wrapZone(callback));
|
|
}
|
|
|
|
/**
|
|
* Cancels an animation frame request.
|
|
*
|
|
* ## Other resources
|
|
*
|
|
* * [Window.cancelAnimationFrame]
|
|
* (https://developer.mozilla.org/en-US/docs/Web/API/Window.cancelAnimationFrame) from MDN.
|
|
*/
|
|
void cancelAnimationFrame(int id) {
|
|
_ensureRequestAnimationFrame();
|
|
_cancelAnimationFrame(id);
|
|
}
|
|
|
|
@JSName('requestAnimationFrame')
|
|
int _requestAnimationFrame(RequestAnimationFrameCallback callback) native;
|
|
|
|
@JSName('cancelAnimationFrame')
|
|
void _cancelAnimationFrame(int id) native;
|
|
|
|
_ensureRequestAnimationFrame() {
|
|
if (JS('bool',
|
|
'!!(#.requestAnimationFrame && #.cancelAnimationFrame)', this, this))
|
|
return;
|
|
|
|
JS('void',
|
|
r"""
|
|
(function($this) {
|
|
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
|
for (var i = 0; i < vendors.length && !$this.requestAnimationFrame; ++i) {
|
|
$this.requestAnimationFrame = $this[vendors[i] + 'RequestAnimationFrame'];
|
|
$this.cancelAnimationFrame =
|
|
$this[vendors[i]+'CancelAnimationFrame'] ||
|
|
$this[vendors[i]+'CancelRequestAnimationFrame'];
|
|
}
|
|
if ($this.requestAnimationFrame && $this.cancelAnimationFrame) return;
|
|
$this.requestAnimationFrame = function(callback) {
|
|
return window.setTimeout(function() {
|
|
callback(Date.now());
|
|
}, 16 /* 16ms ~= 60fps */);
|
|
};
|
|
$this.cancelAnimationFrame = function(id) { clearTimeout(id); }
|
|
})(#)""",
|
|
this);
|
|
}
|
|
|
|
/**
|
|
* Gets an instance of the Indexed DB factory to being using Indexed DB.
|
|
*
|
|
* Use [indexed_db.IdbFactory.supported] to check if Indexed DB is supported on the
|
|
* current platform.
|
|
*/
|
|
@SupportedBrowser(SupportedBrowser.CHROME, '23.0')
|
|
@SupportedBrowser(SupportedBrowser.FIREFOX, '15.0')
|
|
@SupportedBrowser(SupportedBrowser.IE, '10.0')
|
|
@Experimental()
|
|
IdbFactory get indexedDB =>
|
|
JS('IdbFactory|Null', // If not supported, returns null.
|
|
'#.indexedDB || #.webkitIndexedDB || #.mozIndexedDB',
|
|
this, this, this);
|
|
|
|
/// The debugging console for this window.
|
|
@DomName('Window.console')
|
|
Console get console => Console._safeConsole;
|
|
|
|
$else
|
|
/**
|
|
* Called to draw an animation frame and then request the window to repaint
|
|
* after [callback] has finished (creating the animation).
|
|
*
|
|
* Use this method only if you need to later call [cancelAnimationFrame]. If
|
|
* not, the preferred Dart idiom is to set animation frames by calling
|
|
* [animationFrame], which returns a Future.
|
|
*
|
|
* Returns a non-zero valued integer to represent the request id for this
|
|
* request. This value only needs to be saved if you intend to call
|
|
* [cancelAnimationFrame] so you can specify the particular animation to
|
|
* cancel.
|
|
*
|
|
* Note: The supplied [callback] needs to call [requestAnimationFrame] again
|
|
* for the animation to continue.
|
|
*/
|
|
@DomName('Window.requestAnimationFrame')
|
|
int requestAnimationFrame(RequestAnimationFrameCallback callback) {
|
|
return _requestAnimationFrame(_wrapZone(callback));
|
|
}
|
|
$endif
|
|
|
|
/**
|
|
* Access a sandboxed file system of the specified `size`. If `persistent` is
|
|
* true, the application will request permission from the user to create
|
|
* lasting storage. This storage cannot be freed without the user's
|
|
* permission. Returns a [Future] whose value stores a reference to the
|
|
* sandboxed file system for use. Because the file system is sandboxed,
|
|
* applications cannot access file systems created in other web pages.
|
|
*/
|
|
Future<FileSystem> requestFileSystem(int size, {bool persistent: false}) {
|
|
return _requestFileSystem(persistent? 1 : 0, size);
|
|
}
|
|
|
|
/**
|
|
* Converts a point from node coordinates to this window's coordinates.
|
|
*
|
|
* ## Other resources
|
|
*
|
|
* * [webkitConvertPointFromPageToNode]
|
|
* (https://developer.apple.com/library/safari/documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html#//apple_ref/javascript/instm/DOMWindow/webkitConvertPointFromNodeToPage)
|
|
* from Safari Development Library.
|
|
*/
|
|
@DomName('Window.convertPointFromNodeToPage')
|
|
@SupportedBrowser(SupportedBrowser.CHROME)
|
|
@SupportedBrowser(SupportedBrowser.SAFARI)
|
|
@Experimental()
|
|
Point convertPointFromNodeToPage(Node node, Point point) {
|
|
var result = _convertPointFromNodeToPage(node,
|
|
new _DomPoint(point.x, point.y));
|
|
return new Point(result.x, result.y);
|
|
}
|
|
|
|
/**
|
|
* Converts a point from this window's coordinates to node coordinates.
|
|
*
|
|
* ## Other resources
|
|
*
|
|
* * [webkitConvertPointFromPageToNode]
|
|
* (https://developer.apple.com/library/safari/documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html#//apple_ref/javascript/instm/DOMWindow/webkitConvertPointFromPageToNode)
|
|
* from Safari Development Library.
|
|
*/
|
|
@DomName('Window.convertPointFromPageToNode')
|
|
@SupportedBrowser(SupportedBrowser.CHROME)
|
|
@SupportedBrowser(SupportedBrowser.SAFARI)
|
|
@Experimental()
|
|
Point convertPointFromPageToNode(Node node, Point point) {
|
|
var result = _convertPointFromPageToNode(node,
|
|
new _DomPoint(point.x, point.y));
|
|
return new Point(result.x, result.y);
|
|
}
|
|
|
|
/**
|
|
* Checks whether [convertPointFromNodeToPage] and
|
|
* [convertPointFromPageToNode] are supported on the current platform.
|
|
*/
|
|
static bool get supportsPointConversions => _DomPoint.supported;
|
|
$!MEMBERS
|
|
|
|
/**
|
|
* Static factory designed to expose `beforeunload` events to event
|
|
* handlers that are not necessarily instances of [Window].
|
|
*
|
|
* See [EventStreamProvider] for usage information.
|
|
*/
|
|
@DomName('Window.beforeunloadEvent')
|
|
static const EventStreamProvider<BeforeUnloadEvent> beforeUnloadEvent =
|
|
const _BeforeUnloadEventStreamProvider('beforeunload');
|
|
|
|
/// Stream of `beforeunload` events handled by this [Window].
|
|
@DomName('Window.onbeforeunload')
|
|
Stream<Event> get onBeforeUnload => beforeUnloadEvent.forTarget(this);
|
|
|
|
/**
|
|
* Moves this window to a specific position.
|
|
*
|
|
* x and y can be negative.
|
|
*
|
|
* ## Other resources
|
|
*
|
|
* * [Window.moveTo]
|
|
* (https://developer.mozilla.org/en-US/docs/Web/API/Window.moveTo) from MDN.
|
|
* * [Window.moveTo]
|
|
* (http://dev.w3.org/csswg/cssom-view/#dom-window-moveto) from W3C.
|
|
*/
|
|
void moveTo(Point p) {
|
|
_moveTo(p.x, p.y);
|
|
}
|
|
|
|
$if DART2JS
|
|
/**
|
|
* The distance this window has been scrolled horizontally.
|
|
*
|
|
* ## Other resources
|
|
*
|
|
* * [The Screen interface specification]
|
|
* (http://www.w3.org/TR/cssom-view/#screen) from W3C.
|
|
* * [scrollX]
|
|
* (https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollX) from MDN.
|
|
*/
|
|
int get scrollX => JS('bool', '("scrollX" in #)', this) ? JS('int',
|
|
'#.scrollX', this) : document.documentElement.scrollLeft;
|
|
|
|
/**
|
|
* The distance this window has been scrolled vertically.
|
|
*
|
|
* ## Other resources
|
|
*
|
|
* * [The Screen interface specification]
|
|
* (http://www.w3.org/TR/cssom-view/#screen) from W3C.
|
|
* * [scrollY]
|
|
* (https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY) from MDN.
|
|
*/
|
|
int get scrollY => JS('bool', '("scrollY" in #)', this) ? JS('int',
|
|
'#.scrollY', this) : document.documentElement.scrollTop;
|
|
$endif
|
|
}
|
|
|
|
$if DART2JS
|
|
class _BeforeUnloadEvent extends _WrappedEvent implements BeforeUnloadEvent {
|
|
String _returnValue;
|
|
|
|
_BeforeUnloadEvent(Event base): super(base);
|
|
|
|
String get returnValue => _returnValue;
|
|
|
|
void set returnValue(String value) {
|
|
_returnValue = value;
|
|
// FF and IE use the value as the return value, Chrome will return this from
|
|
// the event callback function.
|
|
if (JS('bool', '("returnValue" in #)', wrapped)) {
|
|
JS('void', '#.returnValue = #', wrapped, value);
|
|
}
|
|
}
|
|
}
|
|
$endif
|
|
|
|
class _BeforeUnloadEventStreamProvider implements
|
|
EventStreamProvider<BeforeUnloadEvent> {
|
|
final String _eventType;
|
|
|
|
const _BeforeUnloadEventStreamProvider(this._eventType);
|
|
|
|
Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
|
|
var stream = new _EventStream(e, _eventType, useCapture);
|
|
$if DART2JS
|
|
var controller = new StreamController(sync: true);
|
|
|
|
stream.listen((event) {
|
|
var wrapped = new _BeforeUnloadEvent(event);
|
|
controller.add(wrapped);
|
|
return wrapped.returnValue;
|
|
});
|
|
|
|
return controller.stream;
|
|
$else
|
|
return stream;
|
|
$endif
|
|
}
|
|
|
|
String getEventType(EventTarget target) {
|
|
return _eventType;
|
|
}
|
|
}
|