// 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. // WARNING: Do not edit - generated code. part of $LIBRARYNAME; $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS { $!MEMBERS $if DART2JS @DomName('Document.body') BodyElement body; $else @DomName('Document.body') BodyElement get body => _body; @DomName('Document.body') set body(BodyElement value) { _body = value; } $endif /// UNSTABLE: Chrome-only - create a Range from the given point. @DomName('Document.caretRangeFromPoint') @Unstable() Range caretRangeFromPoint(int x, int y) { return _caretRangeFromPoint(x, y); } @DomName('Document.elementFromPoint') Element elementFromPoint(int x, int y) { return _elementFromPoint(x, y); } /** * Checks if the getCssCanvasContext API is supported on the current platform. * * See also: * * * [getCssCanvasContext] */ $if DART2JS static bool get supportsCssCanvasContext => JS('bool', '!!(document.getCSSCanvasContext)'); $else static bool get supportsCssCanvasContext => true; $endif /** * Gets a CanvasRenderingContext which can be used as the CSS background of an * element. * * CSS: * * background: -webkit-canvas(backgroundCanvas) * * Generate the canvas: * * var context = document.getCssCanvasContext('2d', 'backgroundCanvas', * 100, 100); * context.fillStyle = 'red'; * context.fillRect(0, 0, 100, 100); * * See also: * * * [supportsCssCanvasContext] * * [CanvasElement.getContext] */ @SupportedBrowser(SupportedBrowser.CHROME) @SupportedBrowser(SupportedBrowser.SAFARI) @Experimental() @DomName('Document.getCSSCanvasContext') CanvasRenderingContext getCssCanvasContext(String contextId, String name, int width, int height) { return _getCssCanvasContext(contextId, name, width, height); } @DomName('Document.head') HeadElement get head => _head; @DomName('Document.lastModified') String get lastModified => _lastModified; @DomName('Document.preferredStylesheetSet') String get preferredStylesheetSet => _preferredStylesheetSet; @DomName('Document.referrer') String get referrer => _referrer; @DomName('Document.selectedStylesheetSet') String get selectedStylesheetSet => _selectedStylesheetSet; set selectedStylesheetSet(String value) { _selectedStylesheetSet = value; } @DomName('Document.styleSheets') List get styleSheets => _styleSheets; @DomName('Document.title') String get title => _title; @DomName('Document.title') set title(String value) { _title = value; } /** * Returns page to standard layout. * * Has no effect if the page is not in fullscreen mode. * * ## Other resources * * * [Using the fullscreen * API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api) * from WebPlatform.org. * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C. */ @DomName('Document.webkitExitFullscreen') @SupportedBrowser(SupportedBrowser.CHROME) @SupportedBrowser(SupportedBrowser.SAFARI) @Experimental() void exitFullscreen() { _webkitExitFullscreen(); } $if DARTIUM /** * Internal routine to find the DOM JS class name being extended for custom * elements. */ String _getJSClassName(ClassMirror classMirror) { var jsClassName = null; var isElement = false; while (classMirror.superclass != null) { var fullName = classMirror.superclass.qualifiedName; isElement = isElement || (fullName == #dart.dom.html.Element || fullName == #dart.dom.svg.Element); var domLibrary = MirrorSystem.getName(fullName).startsWith('dart.dom.'); if (jsClassName == null && domLibrary) { // Lookup JS class name (if not found). var metadatas = classMirror.metadata; for (var metadata in metadatas) { var metaDataMirror = metadata.reflectee; var metaType = reflectClass(metaDataMirror.runtimeType); if (MirrorSystem.getName(metaType.simpleName) == 'DomName' && (metaDataMirror.name.startsWith('HTML') || metaDataMirror.name.startsWith('SVG'))) { jsClassName = metadata.reflectee.name; } } } classMirror = classMirror.superclass; } // If we're an element then everything is okay. return isElement ? jsClassName : null; } // Get the first class that's a super of a dart.dom library. ClassMirror _getDartHtmlClassName(ClassMirror classMirror) { while (classMirror.superclass != null) { var fullName = classMirror.superclass.qualifiedName; var domLibrary = MirrorSystem.getName(fullName).startsWith('dart.dom.'); if (domLibrary) { return classMirror.superclass; } classMirror = classMirror.superclass; } return null; } /** * Get the class that immediately derived from a class in dart:html or * dart:svg (has an attribute DomName of either HTML* or SVG*). */ ClassMirror _getDomSuperClass(ClassMirror classMirror) { var isElement = false; var foundSuperElement = null; while (classMirror.superclass != null) { var fullName = classMirror.superclass.qualifiedName; isElement = isElement || (fullName == #dart.dom.html.Element || fullName == #dart.dom.svg.Element); var domLibrary = MirrorSystem.getName(fullName).startsWith('dart.dom.'); if (domLibrary) { if (foundSuperElement == null) { foundSuperElement = classMirror.superclass; } // Lookup JS class (if not found). var metadatas = classMirror.metadata; for (var metadata in metadatas) { var metaDataMirror = metadata.reflectee; var metaType = reflectClass(metaDataMirror.runtimeType); if (MirrorSystem.getName(metaType.simpleName) == 'DomName' && (metaDataMirror.name.startsWith('HTML') || metaDataMirror.name.startsWith('SVG'))) { if (isElement) return foundSuperElement; } } } classMirror = classMirror.superclass; } return null; } /** * Does this CustomElement class have: * * - a created constructor with no arguments? * - a created constructor with a super.created() initializer? * * e.g., MyCustomClass.created() : super.created(); */ bool _hasCreatedConstructor(ClassMirror classToRegister) { var htmlClassMirror = _getDomSuperClass(classToRegister); var classMirror = classToRegister; while (classMirror != null && classMirror != htmlClassMirror) { var createdParametersValid = false; var superCreatedCalled = false; var className = MirrorSystem.getName(classMirror.simpleName); var methodMirror = classMirror.declarations[new Symbol("$className.created")]; if (methodMirror != null && methodMirror.isConstructor) { createdParametersValid = true; // Assume no parameters. if (methodMirror.parameters.length != 0) { // If any parameters each one must be optional. methodMirror.parameters.forEach((parameter) { createdParametersValid = createdParametersValid && parameter.isOptional; }); } } if (!createdParametersValid) { throw new DomException.jsInterop('created constructor must have no parameters'); } classMirror = classMirror.superclass; while (classMirror != classMirror.mixin) { // Skip the mixins. classMirror = classMirror.superclass; } } return true; } $endif @Experimental() /** * Register a custom subclass of Element to be instantiatable by the DOM. * * This is necessary to allow the construction of any custom elements. * * The class being registered must either subclass HtmlElement or SvgElement. * If they subclass these directly then they can be used as: * * class FooElement extends HtmlElement{ * void created() { * print('FooElement created!'); * } * } * * main() { * document.registerElement('x-foo', FooElement); * var myFoo = new Element.tag('x-foo'); * // prints 'FooElement created!' to the console. * } * * The custom element can also be instantiated via HTML using the syntax * `` * * Other elements can be subclassed as well: * * class BarElement extends InputElement{ * void created() { * print('BarElement created!'); * } * } * * main() { * document.registerElement('x-bar', BarElement); * var myBar = new Element.tag('input', 'x-bar'); * // prints 'BarElement created!' to the console. * } * * This custom element can also be instantiated via HTML using the syntax * `` * */ void registerElement(String tag, Type customElementClass, {String extendsTag}) { $if DART2JS _registerCustomElement(JS('', 'window'), this, tag, customElementClass, extendsTag); $else // Hack to setup an interceptor for HTMLElement so it isn't changed when a custom element is created. var jsHTMLElementPrototype = js.JsNative.getProperty(js.JsNative.getProperty(js.context, 'HTMLElement'),'prototype'); _blink.Blink_Utils.defineInterceptor(jsHTMLElementPrototype, HtmlElement.instanceRuntimeType); // Figure out which DOM class is being extended from the user's Dart class. var classMirror = reflectClass(customElementClass); var locationUri = classMirror.location.sourceUri.toString(); if (locationUri == 'dart:html' || locationUri == 'dart:svg') { throw new DomException.jsInterop("HierarchyRequestError: Cannot register an existing dart:html or dart:svg type."); } if (classMirror.isAbstract) { throw new DomException.jsInterop("HierarchyRequestError: Cannot register an abstract class."); } var jsClassName = _getJSClassName(classMirror); if (jsClassName == null) { // Only components derived from HTML* can be extended. throw new DomException.jsInterop("HierarchyRequestError: Only HTML elements can be customized."); } var customClassType = _getDartHtmlClassName(classMirror); if (extendsTag != null) { var nativeElement = document.createElement(extendsTag); // Trying to extend a native element is it the Dart class consistent with the // extendsTag? if (nativeElement.runtimeType != customClassType.reflectedType) { var nativeElementClassMirror = reflectClass(nativeElement.runtimeType); var customClassNativeElement = MirrorSystem.getName(customClassType.simpleName); var extendsNativeElement = MirrorSystem.getName(nativeElementClassMirror.simpleName); throw new DomException.jsInterop("HierarchyRequestError: Custom class type ($customClassNativeElement) and extendsTag class ($extendsNativeElement) don't match ."); } } else if (customClassType.reflectedType != HtmlElement && customClassType.reflectedType != svg.SvgElement) { var customClassName = MirrorSystem.getName(classMirror.simpleName); var customClassElement = MirrorSystem.getName(customClassType.simpleName); throw new DomException.jsInterop("HierarchyRequestError: Custom element $customClassName is a native $customClassElement should be derived from HtmlElement or SvgElement."); } if (_hasCreatedConstructor(classMirror)) { // Start the hookup the JS way create an element that extends the // custom element. Inherit its prototype and signal what tag is // inherited: // // var myProto = Object.create(HTMLElement.prototype); // var myElement = document.registerElement('x-foo', {prototype: myProto}); var baseElement = js.JsNative.getProperty(js.context, jsClassName); if (baseElement == null) { // Couldn't find the HTML element so use a generic one. baseElement = js.JsNative.getProperty(js.context, 'HTMLElement'); } var elemProto = js.JsNative.callMethod(js.JsNative.getProperty(js.context, 'Object'), "create", [js.JsNative.getProperty(baseElement, 'prototype')]); // TODO(terry): Hack to stop recursion re-creating custom element when the // created() constructor of the custom element does e.g., // // MyElement.created() : super.created() { // this.innerHtml = "I'm an x-foo-with-markup!"; // } // // sanitizing causes custom element to created recursively // until stack overflow. // // See https://github.com/dart-lang/sdk/issues/23666 int creating = 0; // TODO(jacobr): I think I broke thise case. Will fix monday. // If any JS code is hooked we want to call it too. var oldCreatedCallback = js.JsNative.getProperty(elemProto, 'createdCallback'); var oldAttributeChangedCallback = js.JsNative.getProperty(elemProto, 'attributeChangedCallback'); var oldAttachedCallback = js.JsNative.getProperty(elemProto, 'attachedCallback'); var oldDetachedCallback = js.JsNative.getProperty(elemProto, 'detachedCallback'); js.JsNative.setProperty(elemProto, 'createdCallback', js.allowInteropCaptureThis(($this) { // The created callback has already been called by the very act of passing a JS // custom element from JS to Dart. // Make element's interceptor a CustomElementClass. _blink.Blink_Utils.setInstanceInterceptorCustomUpgrade($this); if (oldCreatedCallback != null) oldCreatedCallback.apply([], thisArg: $this); })); js.JsNative.setProperty(elemProto, 'attributeChangedCallback', js.allowInteropCaptureThis(($this, attrName, oldVal, newVal) { $this.attributeChanged(attrName, oldVal, newVal); if (oldAttributeChangedCallback != null) oldAttributeChangedCallback.apply([], thisArg: $this); })); js.JsNative.setProperty(elemProto, 'attachedCallback', js.allowInteropCaptureThis(($this) { $this.attached(); if (oldAttachedCallback != null) oldAttachedCallback.apply([], thisArg: $this); })); js.JsNative.setProperty(elemProto, 'detachedCallback', js.allowInteropCaptureThis(($this) { $this.detached(); if (oldDetachedCallback != null) oldDetachedCallback.apply([], thisArg: $this); })); // document.registerElement('x-foo', {prototype: elemProto, extends: extendsTag}); var jsMap = new js.JsObject.jsify({'prototype': elemProto, 'extends': extendsTag}); _blink.Blink_Utils.defineInterceptorCustomElement(elemProto, customElementClass); js.JsNative.callMethod(document, 'registerElement', [tag, jsMap]); } $endif } /** *Deprecated*: use [registerElement] instead. */ @deprecated @Experimental() void register(String tag, Type customElementClass, {String extendsTag}) { return registerElement(tag, customElementClass, extendsTag: extendsTag); } /** * Static factory designed to expose `visibilitychange` events to event * handlers that are not necessarily instances of [Document]. * * See [EventStreamProvider] for usage information. */ @DomName('Document.visibilityChange') @SupportedBrowser(SupportedBrowser.CHROME) @SupportedBrowser(SupportedBrowser.FIREFOX) @SupportedBrowser(SupportedBrowser.IE, '10') @Experimental() static const EventStreamProvider visibilityChangeEvent = const _CustomEventStreamProvider( _determineVisibilityChangeEventType); static String _determineVisibilityChangeEventType(EventTarget e) { $if DART2JS if (JS('bool', '(typeof #.hidden !== "undefined")', e)) { // Opera 12.10 and Firefox 18 and later support return 'visibilitychange'; } else if (JS('bool', '(typeof #.mozHidden !== "undefined")', e)) { return 'mozvisibilitychange'; } else if (JS('bool', '(typeof #.msHidden !== "undefined")', e)) { return 'msvisibilitychange'; } else if (JS('bool', '(typeof #.webkitHidden !== "undefined")', e)) { return 'webkitvisibilitychange'; } return 'visibilitychange'; $else return 'webkitvisibilitychange'; $endif } @SupportedBrowser(SupportedBrowser.CHROME) @SupportedBrowser(SupportedBrowser.FIREFOX) @SupportedBrowser(SupportedBrowser.IE, '10') @Experimental() Stream get onVisibilityChange => visibilityChangeEvent.forTarget(this); /// Creates an element upgrader which can be used to change the Dart wrapper /// type for elements. /// /// The type specified must be a subclass of HtmlElement, when an element is /// upgraded then the created constructor will be invoked on that element. /// /// If the type is not a direct subclass of HtmlElement then the extendsTag /// parameter must be provided. @Experimental() ElementUpgrader createElementUpgrader(Type type, {String extendsTag}) { $if DART2JS return new _JSElementUpgrader(this, type, extendsTag); $else return new _VMElementUpgrader(this, type, extendsTag); $endif } }