├── .gitignore ├── .test_config ├── AUTHORS ├── CHANGELOG.md ├── LICENSE ├── PATENTS ├── README.md ├── codereview.settings ├── e2e_test └── html_imports │ ├── lib │ └── theme.html │ ├── pubspec.yaml │ └── test │ ├── basic_test.dart │ └── basic_test.html ├── lib ├── CustomElements.js ├── CustomElements.min.js ├── HTMLImports.js ├── HTMLImports.min.js ├── MutationObserver.js ├── MutationObserver.min.js ├── README.md ├── ShadowDOM.js ├── ShadowDOM.min.js ├── bower.json ├── build.log ├── build │ ├── common.dart │ ├── html_import_annotation_recorder.dart │ ├── import_crawler.dart │ ├── import_inliner.dart │ ├── messages.dart │ ├── mirrors_remover.dart │ ├── script_compactor.dart │ ├── test_compatibility.dart │ └── web_components.dart ├── custom_element_proxy.dart ├── dart_support.js ├── html_import_annotation.dart ├── init.dart ├── interop.dart ├── interop_support.html ├── interop_support.js ├── package.json ├── polyfill.dart ├── src │ ├── custom_element.dart │ ├── init.dart │ ├── mirror_initializer.dart │ ├── normalize_path.dart │ └── static_initializer.dart ├── transformer.dart ├── web_components.dart ├── webcomponents-lite.js ├── webcomponents-lite.min.js ├── webcomponents.js └── webcomponents.min.js ├── pubspec.yaml └── test ├── build ├── common.dart ├── html_import_annotation_recorder_test.dart ├── import_crawler_test.dart ├── import_inliner_test.dart ├── mirrors_remover_test.dart ├── script_compactor_test.dart ├── test_compatibility_test.dart └── transformer_test.dart ├── custom_element_proxy_test.dart ├── custom_element_proxy_test.html ├── custom_element_test.dart ├── custom_element_test.html ├── deps ├── a.dart ├── a.html ├── b.dart ├── b.html └── c.html ├── foo ├── bar.dart └── bar.html ├── html_import_annotation_test.dart ├── html_import_annotation_test.html ├── init_web_components_test.dart ├── init_web_components_test.html ├── interop_test.dart ├── interop_test.html ├── location_wrapper_test.dart ├── location_wrapper_test.html └── my_import.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Don’t commit the following directories created by pub. 2 | .pub 3 | /build/ 4 | packages 5 | .packages 6 | 7 | # Or the files created by dart2js. 8 | *.dart.js 9 | *.dart.precompiled.js 10 | *.js_ 11 | *.js.deps 12 | *.js.map 13 | *.sw? 14 | .idea/ 15 | .pub/ 16 | 17 | # Include when developing application packages. 18 | pubspec.lock 19 | -------------------------------------------------------------------------------- /.test_config: -------------------------------------------------------------------------------- 1 | { 2 | "test_package": { 3 | "platforms": ["vm", "dartium"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Names should be added to this file with this pattern: 2 | # 3 | # For individuals: 4 | # Name 5 | # 6 | # For organizations: 7 | # Organization 8 | # 9 | Google Inc. <*@google.com> 10 | Matias Meno 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | #### 0.12.5 2 | * Update to not use deprecated analyzer apis. 3 | * Update analyzer minimum version to 0.27.1. 4 | 5 | #### 0.12.4 6 | * Update to JS version 7 | [0.7.23](https://github.com/webcomponents/webcomponentsjs/tree/v0.7.23). 8 | * Update `analyzer`, `code_transformers`, and `html` version constraints. 9 | 10 | #### 0.12.3 11 | * Update to JS version 12 | [0.7.21](https://github.com/webcomponents/webcomponentsjs/tree/v0.7.21). 13 | 14 | #### 0.12.2+2 15 | 16 | * Update to transformer_test `0.2.x`. 17 | 18 | #### 0.12.2+2 19 | 20 | * Add support for code_transformers `0.4.x`. 21 | 22 | #### 0.12.2+1 23 | * Allow periods in package names (but can't end or begin with one). 24 | 25 | #### 0.12.2 26 | * Update to JS version 27 | [0.7.20](https://github.com/webcomponents/webcomponentsjs/tree/v0.7.20). 28 | 29 | #### 0.12.1 30 | * Update analyzer to `^0.27.0` and update to the test package. 31 | 32 | #### 0.12.0+4 33 | * The transformer will now give an informative error on package names with 34 | hyphens. 35 | 36 | #### 0.12.0+3 37 | * Update analyzer dependency to `<0.27.0` and fix up some tests. 38 | 39 | #### 0.12.0+2 40 | * Don't create new resolvers each time the transformer runs on a file. 41 | 42 | #### 0.12.0+1 43 | * Fix hang on reload with the `web_components` transformer in pub serve, 44 | [27](https://github.com/dart-lang/web-components/issues/27). 45 | 46 | #### 0.12.0 47 | * Update to js version 48 | [0.7.3](https://github.com/webcomponents/webcomponentsjs/tree/v0.7.3). 49 | * Some release notes 50 | (here)[http://webcomponents.org/articles/polyfills-0-6-0/]. 51 | * Also added all the individual polyfills as well as the 52 | `webcomponents-lite.js` version, which does not include shadow dom. 53 | 54 | #### 0.11.4+2 55 | * Don't inline type="css" imports. 56 | 57 | #### 0.11.4+1 58 | * Fix erroneous messages about invalid package paths in html imports 59 | [72](https://github.com/dart-lang/polymer-dart/issues/72). 60 | 61 | #### 0.11.4 62 | * Update to analyzer `<0.26.0`. 63 | 64 | #### 0.11.3+1 65 | * Fix bootstrap to return the result of the original main. 66 | 67 | #### 0.11.3 68 | * Add support for the new `link[rel="x-dart-test"]` tags from the `test` 69 | package to the transformer. 70 | 71 | #### 0.11.2 72 | * Copied `DomProxyMixin` from `custom_element_apigen` to this package and 73 | renamed it `CustomElementProxyMixin`. This can be mixed into any class that 74 | is using the `@CustomElementProxy` annotation and provides easy access to 75 | the underlying javascript element via the `jsElement` getter. For instance 76 | the following is a simple example of a dart class that wraps a custom 77 | javascript element `foo-element` with a method `doFoo` and a property `foo`. 78 | 79 | @CustomElementProxy('foo-element') 80 | class FooElement extends HtmlElement with CustomElementProxyMixin { 81 | FooElement.created() : super.created(); 82 | 83 | void doFoo(int arg1) => jsElement.callMethod('doFoo', [arg1]); 84 | 85 | int get foo => jsElement['foo']; 86 | void set foo(int newFoo) { 87 | jsElement['foo'] = newFoo; 88 | } 89 | } 90 | 91 | #### 0.11.1+3 92 | * Switch `html5lib` package dependency to `html`. 93 | 94 | #### 0.11.1+2 95 | * Added a runtime warning about bad packages paths in html imports to 96 | `initWebComponents`. 97 | 98 | #### 0.11.1+1 99 | * fixes unknown HTML elements if using interop_support.js 100 | 101 | #### 0.11.1 102 | * Added `initWebComponents` function which performs html import aware 103 | initialization of an application. This is done by crawling all imported 104 | documents for dart script tags and initializing them. Any applications using 105 | this package should switch to this method instead of calling `run` from the 106 | `initialize` package directly. 107 | * You may also now just export `package:web_components/init.dart` to 108 | initialize your app, and then stick your startup code inside a method marked 109 | with `@initMethod`, for instance: 110 | 111 | library my_app; 112 | export 'package:web_components/init.dart'; 113 | 114 | @initMethod 115 | void startup() { 116 | // custom app code here. 117 | } 118 | 119 | #### 0.11.0 120 | * Add `bindingStartDelimiters` option to the `ImportInlinerTransformer`. Any 121 | urls which contain any of the supplied delimiters before the first `/` will 122 | be left alone since they can't be reasoned about. If you want these urls to 123 | be treated as relative to the current path you should add a `./` in front. 124 | * The `ScriptCompactorTransformer` now names its bootstrap file based on the 125 | entry point html file, instead of the original dart file. This is ensure it 126 | is the original package. 127 | 128 | #### 0.10.5+3 129 | * Fix normalization of relative paths inside of deep relative imports, 130 | https://github.com/dart-lang/polymer-dart/issues/30. 131 | * Update analyzer and code_transformers versions and use new mock sdk from 132 | code_transformers. 133 | 134 | #### 0.10.5+2 135 | * Append html imports in front of the dart script tag, if one exists in 136 | `document.head`. 137 | 138 | #### 0.10.5+1 139 | * Fix @HtmlImport with relative paths from within folders in deployment mode. 140 | 141 | #### 0.10.5 142 | * Update `ImportCrawler` with support for pre-parsed initial documents. This 143 | allows it to work better with other transformers in the same step (you can 144 | pass in a modified document). 145 | 146 | #### 0.10.4+2 147 | * Fix `@CustomElement` test in internet explorer. 148 | 149 | #### 0.10.4+1 150 | * Update `initialize` lower bound to get bug fixes. 151 | * Make sure to always use `path.url` in transformers. 152 | 153 | #### 0.10.4 154 | * Added `CustomElement` annotation. This can be added to any class to register 155 | it with a tag in the main document. 156 | * Added a `web_components.dart` file which exports all the annotations 157 | provided by this package. Note that in later breaking releases 158 | `html_import_annotation.dart` and `custom_element_proxy.dart` will likely 159 | move into the `src` folder, so switching to the `web_components.dart` import 160 | is recommended. 161 | 162 | #### 0.10.3 163 | * Added `generateWebComponentsBootstrap` method to the main `web_components` 164 | transformer file which accepts a `Transform` and a `Resolver`. You can use 165 | this function from any transformer and share the resolver you already have. 166 | * Fixed up the bootstrap call in `ScriptCompactor` to not use `=>` syntax 167 | since it has a declared return type of `void`. This could previously cause 168 | a checked mode error if the original program returned something from `main`. 169 | 170 | #### 0.10.2+1 171 | * Minor cleanup to changelog and tests. 172 | * ImportInliner now throws warnings instead of errors. 173 | 174 | #### 0.10.2 175 | * Added the `HtmlImport` annotation. This can be added to any library 176 | declaration and it will inject an html import to the specified path into the 177 | head of the current document, which allows dart files to declare their html 178 | dependencies. Paths can be relative to the current dart file or they can be 179 | in `package:` form. 180 | 181 | *Note*: Html imports included this way cannot contain dart script tags. The 182 | mirror based implementation injects the imports dynamically and dart script 183 | tags are not allowed to be injected in that way. 184 | 185 | *Note*: Relative urls cannot be used in inlined script tags. Either move 186 | the script code to a Dart file, use a `package:` url, or use a normal HTML 187 | import. See https://github.com/dart-lang/web-components/issues/6. 188 | 189 | * Added a `web_components` transformer. This should be used in place of the 190 | `initialize` transformer if that already exists in your application (it will 191 | call that transformer). This will inline html imports (including @HtmlImport 192 | annotations) into the head of your document at compile time, it can be used 193 | like this: 194 | 195 | transformers: 196 | - web_components: 197 | entry_points: 198 | - web/index.html 199 | 200 | If no `entry_points` option is supplied then any html file under `web` or 201 | `test` will be treated as an entry point. 202 | 203 | #### 0.10.1 204 | * Added the `CustomElementProxy` annotation. This can be added to any class 205 | which proxies a javascript custom element and is the equivalent of calling 206 | `registerDartType`. In order to use this you will need to be using the 207 | `initialize` package, and call its `run` method from your main function. It 208 | is also recommended that you include the transformer from that package to 209 | remove the use of mirrors at runtime, see 210 | [initialize](https://github.com/dart-lang/initialize) for more information. 211 | 212 | #### 0.10.0 213 | * Updated to the `0.5.1` js version. 214 | * **Breaking Change** To remain consistent with the js repository all the 215 | `platform.js` has been replaced with `webcomponents.js`. Also, the default 216 | file is now unminified, and the minified version is called 217 | `webcomponents.min.js`. 218 | 219 | #### 0.9.0+1 220 | * Remove all `.map` and `.concat.js` files during release mode. 221 | 222 | #### 0.9.0 223 | * Updated to platform version 0.4.2, internally a deprecated API was removed, 224 | hence the bump in the version number. 225 | 226 | * split dart_support.js in two. dart_support.js only contains what is 227 | necessary in order to use platform.js, 228 | interop_support.js/interop_support.html can be imported separately when 229 | providing Dart APIs for js custom elements. 230 | 231 | #### 0.8.0 232 | * Re-apply changes from 0.7.1+1 and also cherry pick 233 | [efdbbc](https://github.com/polymer/CustomElements/commit/efdbbc) to fix 234 | the customElementsTakeRecords function. 235 | * **Breaking Change** The customElementsTakeRecords function now has an 236 | an optional argument `node`. There is no longer a single global observer, 237 | but one for each ShadowRoot and one for the main document. The observer that 238 | is actually used defaults to the main document, but if `node` is supplied 239 | then it will walk up the document tree and use the first observer that it 240 | finds. 241 | 242 | #### 0.7.1+2 243 | * Revert the change from 0.7.1+1 due to redness in FF/Safari/IE. 244 | 245 | #### 0.7.1+1 246 | * Cherry pick [f280d](https://github.com/Polymer/ShadowDOM/commit/f280d) and 247 | [165c3](https://github.com/Polymer/CustomElements/commit/165c3) to fix 248 | memory leaks. 249 | 250 | #### 0.7.1 251 | * Update to platform version 0.4.1-d214582. 252 | 253 | #### 0.7.0+1 254 | * Cherry pick https://github.com/Polymer/ShadowDOM/pull/506 to fix IOS 8. 255 | 256 | #### 0.7.0 257 | * Updated to 0.4.0-5a7353d release, with same cherry pick as 0.6.0+1. 258 | * Many features were moved into the polymer package, this package is now 259 | purely focused on polyfills. 260 | * Change Platform.deliverDeclarations to 261 | Platform.consumeDeclarations(callback). 262 | * Cherry pick https://github.com/Polymer/ShadowDOM/pull/505 to fix mem leak. 263 | 264 | #### 0.6.0+1 265 | * Cherry pick https://github.com/Polymer/ShadowDOM/pull/500 to fix 266 | http://dartbug.com/20141. Fixes getDefaultComputedStyle in firefox. 267 | 268 | #### 0.6.0 269 | * Upgrades to platform master as of 8/25/2014 (see lib/build.log for details). 270 | This is more recent than the 0.3.5 release as there were multiple breakages 271 | that required updating past that. 272 | * There is a bug in this version where selecting non-rendered elements doesn't 273 | work, but it shouldn't affect most people. See 274 | https://github.com/Polymer/ShadowDOM/issues/495. 275 | 276 | #### 0.5.0+1 277 | * Backward compatible change to prepare for upcoming change of the user agent 278 | in Dartium. 279 | 280 | #### 0.5.0 281 | * Upgrades to platform version 0.3.4-02a0f66 (see lib/build.log for details). 282 | 283 | #### 0.4.0 284 | * Adds `registerDartType` and updates to platform 0.3.3-29065bc 285 | (re-applies the changes in 0.3.5). 286 | 287 | #### 0.3.5+1 288 | * Reverts back to what we had in 0.3.4. (The platform.js updates in 0.3.5 had 289 | breaking changes so we are republishing it in 0.4.0) 290 | 291 | #### 0.3.5 292 | * Added `registerDartType` to register a Dart API for a custom-element written 293 | in Javascript. 294 | * Updated to platform 0.3.3-29065bc 295 | 296 | #### 0.3.4 297 | * Updated to platform 0.2.4 (see lib/build.log for details) 298 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Polymer Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Polymer project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Polymer, where such license applies only to those 11 | patent claims, both currently owned or controlled by Google and acquired 12 | in the future, licensable by Google that are necessarily infringed by 13 | this implementation of Polymer. This grant does not include claims 14 | that would be infringed only as a consequence of further modification of 15 | this implementation. If you or your agent or exclusive licensee 16 | institute or order or agree to the institution of patent litigation 17 | against any entity (including a cross-claim or counterclaim in a 18 | lawsuit) alleging that this implementation of Polymer or any code 19 | incorporated within this implementation of Polymer constitutes 20 | direct or contributory patent infringement, or inducement of patent 21 | infringement, then any patent rights granted to you under this License 22 | for this implementation of Polymer shall terminate as of the date 23 | such litigation is filed. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Web Components 2 | 3 | This package has the polyfills for 4 | [Shadow DOM](http://www.polymer-project.org/platform/shadow-dom.html), 5 | [Custom Elements](http://www.polymer-project.org/platform/custom-elements.html), 6 | and [HTML Imports](http://www.polymer-project.org/platform/html-imports.html). 7 | 8 | These features exist in dart:html, for example 9 | [Element.createShadowRoot](https://api.dartlang.org/apidocs/channels/stable/#dart-dom-html.Element@id_createShadowRoot) 10 | and [Document.register](https://api.dartlang.org/apidocs/channels/stable/#dart-dom-html.HtmlDocument@id_register). 11 | However those APIs are not supported on all browsers yet unless you 12 | load the polyfills, as indicated below. 13 | 14 | ## Getting started 15 | 16 | Include the polyfills in your HTML `` to enable Shadow DOM: 17 | 18 | ```html 19 | 20 | 21 | ``` 22 | 23 | You can also use an unminified version for development: 24 | 25 | ```html 26 | 27 | 28 | ``` 29 | 30 | Because the Shadow DOM polyfill does extensive DOM patching, webcomponents.js 31 | should be included **before** other script tags. Be sure to include 32 | dart_support.js too, it is required for the Shadow DOM polyfill to work with 33 | [dart2js](https://www.dartlang.org/docs/dart-up-and-running/contents/ch04-tools-dart2js.html). 34 | 35 | ## Custom Elements 36 | 37 | Custom Elements let authors define their own elements. Authors associate 38 | JavaScript or Dart code with custom tag names, and then use those custom tag 39 | names as they would any standard tag. 40 | 41 | For example, after registering a special kind of button called `super-button`, 42 | use the super button just like this: 43 | 44 | ```html 45 | 46 | ``` 47 | 48 | Custom elements are still elements. We can create, use, manipulate, and compose 49 | them just as easily as any standard `
` or `` today. 50 | 51 | See the Polymer [Custom Elements page](http://www.polymer-project.org/platform/custom-elements.html) 52 | for more information. 53 | 54 | ## Shadow DOM 55 | 56 | Shadow DOM is designed to provide encapsulation by hiding DOM subtrees under 57 | shadow roots. It provides a method of establishing and maintaining functional 58 | boundaries between DOM trees and how these trees interact with each other within 59 | a document, thus enabling better functional encapsulation within the DOM. 60 | 61 | See the Polymer [Shadow DOM page](http://www.polymer-project.org/platform/shadow-dom.html) 62 | for more information. 63 | 64 | 65 | ## Hacking on this package 66 | 67 | The `webcomponents.*` files in this package are developed 68 | [here](https://github.com/Polymer/webcomponentsjs). Follow the instructions 69 | there for how to build a new release and then copy the files into this package. 70 | -------------------------------------------------------------------------------- /codereview.settings: -------------------------------------------------------------------------------- 1 | CODE_REVIEW_SERVER: http://codereview.chromium.org/ 2 | VIEW_VC: https://github.com/dart-lang/web-components/commit/ 3 | CC_LIST: reviews@dartlang.org 4 | -------------------------------------------------------------------------------- /e2e_test/html_imports/lib/theme.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /e2e_test/html_imports/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: html_imports 2 | dependencies: 3 | initialize: any 4 | web_components: 5 | path: '../../' 6 | dev_dependencies: 7 | test: '^0.12.0' 8 | transformers: 9 | - web_components: 10 | $include: '**/*_test.html' 11 | entry_points: test/basic_test.html 12 | -------------------------------------------------------------------------------- /e2e_test/html_imports/test/basic_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | @TestOn('browser') 5 | @HtmlImport('packages/html_imports/theme.html') 6 | library e2e_test.html_imports.basic_test; 7 | 8 | import 'dart:html'; 9 | import 'package:initialize/initialize.dart' as init; 10 | import 'package:web_components/html_import_annotation.dart'; 11 | import 'package:test/test.dart'; 12 | 13 | main() async { 14 | // Waits until all html imports are loaded. 15 | await init.run(); 16 | 17 | test('text is red', () { 18 | var p = document.createElement('p'); 19 | document.body.append(p); 20 | expect(p.getComputedStyle().color, 'rgb(255, 0, 0)'); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /e2e_test/html_imports/test/basic_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/CustomElements.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 4 | * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5 | * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6 | * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7 | * Code distributed by Google as part of the polymer project is also 8 | * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9 | */ 10 | // @version 0.7.23 11 | "undefined"==typeof WeakMap&&!function(){var e=Object.defineProperty,t=Date.now()%1e9,n=function(){this.name="__st"+(1e9*Math.random()>>>0)+(t++ +"__")};n.prototype={set:function(t,n){var o=t[this.name];return o&&o[0]===t?o[1]=n:e(t,this.name,{value:[t,n],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return!(!t||t[0]!==e)&&(t[0]=t[1]=void 0,!0)},has:function(e){var t=e[this.name];return!!t&&t[0]===e}},window.WeakMap=n}(),function(e){function t(e){E.push(e),b||(b=!0,m(o))}function n(e){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(e)||e}function o(){b=!1;var e=E;E=[],e.sort(function(e,t){return e.uid_-t.uid_});var t=!1;e.forEach(function(e){var n=e.takeRecords();r(e),n.length&&(e.callback_(n,e),t=!0)}),t&&o()}function r(e){e.nodes_.forEach(function(t){var n=v.get(t);n&&n.forEach(function(t){t.observer===e&&t.removeTransientObservers()})})}function i(e,t){for(var n=e;n;n=n.parentNode){var o=v.get(n);if(o)for(var r=0;r0){var r=n[o-1],i=p(r,e);if(i)return void(n[o-1]=i)}else t(this.observer);n[o]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=v.get(e);t||v.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=v.get(e),n=0;n=0)){n.push(e);for(var o,r=e.querySelectorAll("link[rel="+a+"]"),d=0,s=r.length;d=0&&b(o,HTMLElement),o)}function w(e,t){var n=e[t];e[t]=function(){var e=n.apply(this,arguments);return h(e),e}}var m,v=(e.isIE,e.upgradeDocumentTree),h=e.upgradeAll,g=e.upgradeWithDefinition,b=e.implementPrototype,E=e.useNative,_=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"],y={},N="http://www.w3.org/1999/xhtml",M=document.createElement.bind(document),O=document.createElementNS.bind(document);m=Object.__proto__||E?function(e,t){return e instanceof t}:function(e,t){if(e instanceof t)return!0;for(var n=e;n;){if(n===t.prototype)return!0;n=n.__proto__}return!1},w(Node.prototype,"cloneNode"),w(document,"importNode"),document.registerElement=t,document.createElement=p,document.createElementNS=f,e.registry=y,e["instanceof"]=m,e.reservedTagList=_,e.getRegisteredDefinition=u,document.register=document.registerElement}),function(e){function t(){i(window.wrap(document)),window.CustomElements.ready=!0;var e=window.requestAnimationFrame||function(e){setTimeout(e,16)};e(function(){setTimeout(function(){window.CustomElements.readyTime=Date.now(),window.HTMLImports&&(window.CustomElements.elapsed=window.CustomElements.readyTime-window.HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})})}var n=e.useNative,o=e.initializeModules;e.isIE;if(n){var r=function(){};e.watchShadow=r,e.upgrade=r,e.upgradeAll=r,e.upgradeDocumentTree=r,e.upgradeSubtree=r,e.takeRecords=r,e["instanceof"]=function(e,t){return e instanceof t}}else o();var i=e.upgradeDocumentTree,a=e.upgradeDocument;if(window.wrap||(window.ShadowDOMPolyfill?(window.wrap=window.ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=window.ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}),window.HTMLImports&&(window.HTMLImports.__importsParsingHook=function(e){e["import"]&&a(wrap(e["import"]))}),"complete"===document.readyState||e.flags.eager)t();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var d=window.HTMLImports&&!window.HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(d,t)}else t()}(window.CustomElements); -------------------------------------------------------------------------------- /lib/MutationObserver.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 4 | * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5 | * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6 | * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7 | * Code distributed by Google as part of the polymer project is also 8 | * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9 | */ 10 | // @version 0.7.23 11 | if (typeof WeakMap === "undefined") { 12 | (function() { 13 | var defineProperty = Object.defineProperty; 14 | var counter = Date.now() % 1e9; 15 | var WeakMap = function() { 16 | this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__"); 17 | }; 18 | WeakMap.prototype = { 19 | set: function(key, value) { 20 | var entry = key[this.name]; 21 | if (entry && entry[0] === key) entry[1] = value; else defineProperty(key, this.name, { 22 | value: [ key, value ], 23 | writable: true 24 | }); 25 | return this; 26 | }, 27 | get: function(key) { 28 | var entry; 29 | return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined; 30 | }, 31 | "delete": function(key) { 32 | var entry = key[this.name]; 33 | if (!entry || entry[0] !== key) return false; 34 | entry[0] = entry[1] = undefined; 35 | return true; 36 | }, 37 | has: function(key) { 38 | var entry = key[this.name]; 39 | if (!entry) return false; 40 | return entry[0] === key; 41 | } 42 | }; 43 | window.WeakMap = WeakMap; 44 | })(); 45 | } 46 | 47 | (function(global) { 48 | if (global.JsMutationObserver) { 49 | return; 50 | } 51 | var registrationsTable = new WeakMap(); 52 | var setImmediate; 53 | if (/Trident|Edge/.test(navigator.userAgent)) { 54 | setImmediate = setTimeout; 55 | } else if (window.setImmediate) { 56 | setImmediate = window.setImmediate; 57 | } else { 58 | var setImmediateQueue = []; 59 | var sentinel = String(Math.random()); 60 | window.addEventListener("message", function(e) { 61 | if (e.data === sentinel) { 62 | var queue = setImmediateQueue; 63 | setImmediateQueue = []; 64 | queue.forEach(function(func) { 65 | func(); 66 | }); 67 | } 68 | }); 69 | setImmediate = function(func) { 70 | setImmediateQueue.push(func); 71 | window.postMessage(sentinel, "*"); 72 | }; 73 | } 74 | var isScheduled = false; 75 | var scheduledObservers = []; 76 | function scheduleCallback(observer) { 77 | scheduledObservers.push(observer); 78 | if (!isScheduled) { 79 | isScheduled = true; 80 | setImmediate(dispatchCallbacks); 81 | } 82 | } 83 | function wrapIfNeeded(node) { 84 | return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node; 85 | } 86 | function dispatchCallbacks() { 87 | isScheduled = false; 88 | var observers = scheduledObservers; 89 | scheduledObservers = []; 90 | observers.sort(function(o1, o2) { 91 | return o1.uid_ - o2.uid_; 92 | }); 93 | var anyNonEmpty = false; 94 | observers.forEach(function(observer) { 95 | var queue = observer.takeRecords(); 96 | removeTransientObserversFor(observer); 97 | if (queue.length) { 98 | observer.callback_(queue, observer); 99 | anyNonEmpty = true; 100 | } 101 | }); 102 | if (anyNonEmpty) dispatchCallbacks(); 103 | } 104 | function removeTransientObserversFor(observer) { 105 | observer.nodes_.forEach(function(node) { 106 | var registrations = registrationsTable.get(node); 107 | if (!registrations) return; 108 | registrations.forEach(function(registration) { 109 | if (registration.observer === observer) registration.removeTransientObservers(); 110 | }); 111 | }); 112 | } 113 | function forEachAncestorAndObserverEnqueueRecord(target, callback) { 114 | for (var node = target; node; node = node.parentNode) { 115 | var registrations = registrationsTable.get(node); 116 | if (registrations) { 117 | for (var j = 0; j < registrations.length; j++) { 118 | var registration = registrations[j]; 119 | var options = registration.options; 120 | if (node !== target && !options.subtree) continue; 121 | var record = callback(options); 122 | if (record) registration.enqueue(record); 123 | } 124 | } 125 | } 126 | } 127 | var uidCounter = 0; 128 | function JsMutationObserver(callback) { 129 | this.callback_ = callback; 130 | this.nodes_ = []; 131 | this.records_ = []; 132 | this.uid_ = ++uidCounter; 133 | } 134 | JsMutationObserver.prototype = { 135 | observe: function(target, options) { 136 | target = wrapIfNeeded(target); 137 | if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) { 138 | throw new SyntaxError(); 139 | } 140 | var registrations = registrationsTable.get(target); 141 | if (!registrations) registrationsTable.set(target, registrations = []); 142 | var registration; 143 | for (var i = 0; i < registrations.length; i++) { 144 | if (registrations[i].observer === this) { 145 | registration = registrations[i]; 146 | registration.removeListeners(); 147 | registration.options = options; 148 | break; 149 | } 150 | } 151 | if (!registration) { 152 | registration = new Registration(this, target, options); 153 | registrations.push(registration); 154 | this.nodes_.push(target); 155 | } 156 | registration.addListeners(); 157 | }, 158 | disconnect: function() { 159 | this.nodes_.forEach(function(node) { 160 | var registrations = registrationsTable.get(node); 161 | for (var i = 0; i < registrations.length; i++) { 162 | var registration = registrations[i]; 163 | if (registration.observer === this) { 164 | registration.removeListeners(); 165 | registrations.splice(i, 1); 166 | break; 167 | } 168 | } 169 | }, this); 170 | this.records_ = []; 171 | }, 172 | takeRecords: function() { 173 | var copyOfRecords = this.records_; 174 | this.records_ = []; 175 | return copyOfRecords; 176 | } 177 | }; 178 | function MutationRecord(type, target) { 179 | this.type = type; 180 | this.target = target; 181 | this.addedNodes = []; 182 | this.removedNodes = []; 183 | this.previousSibling = null; 184 | this.nextSibling = null; 185 | this.attributeName = null; 186 | this.attributeNamespace = null; 187 | this.oldValue = null; 188 | } 189 | function copyMutationRecord(original) { 190 | var record = new MutationRecord(original.type, original.target); 191 | record.addedNodes = original.addedNodes.slice(); 192 | record.removedNodes = original.removedNodes.slice(); 193 | record.previousSibling = original.previousSibling; 194 | record.nextSibling = original.nextSibling; 195 | record.attributeName = original.attributeName; 196 | record.attributeNamespace = original.attributeNamespace; 197 | record.oldValue = original.oldValue; 198 | return record; 199 | } 200 | var currentRecord, recordWithOldValue; 201 | function getRecord(type, target) { 202 | return currentRecord = new MutationRecord(type, target); 203 | } 204 | function getRecordWithOldValue(oldValue) { 205 | if (recordWithOldValue) return recordWithOldValue; 206 | recordWithOldValue = copyMutationRecord(currentRecord); 207 | recordWithOldValue.oldValue = oldValue; 208 | return recordWithOldValue; 209 | } 210 | function clearRecords() { 211 | currentRecord = recordWithOldValue = undefined; 212 | } 213 | function recordRepresentsCurrentMutation(record) { 214 | return record === recordWithOldValue || record === currentRecord; 215 | } 216 | function selectRecord(lastRecord, newRecord) { 217 | if (lastRecord === newRecord) return lastRecord; 218 | if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue; 219 | return null; 220 | } 221 | function Registration(observer, target, options) { 222 | this.observer = observer; 223 | this.target = target; 224 | this.options = options; 225 | this.transientObservedNodes = []; 226 | } 227 | Registration.prototype = { 228 | enqueue: function(record) { 229 | var records = this.observer.records_; 230 | var length = records.length; 231 | if (records.length > 0) { 232 | var lastRecord = records[length - 1]; 233 | var recordToReplaceLast = selectRecord(lastRecord, record); 234 | if (recordToReplaceLast) { 235 | records[length - 1] = recordToReplaceLast; 236 | return; 237 | } 238 | } else { 239 | scheduleCallback(this.observer); 240 | } 241 | records[length] = record; 242 | }, 243 | addListeners: function() { 244 | this.addListeners_(this.target); 245 | }, 246 | addListeners_: function(node) { 247 | var options = this.options; 248 | if (options.attributes) node.addEventListener("DOMAttrModified", this, true); 249 | if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true); 250 | if (options.childList) node.addEventListener("DOMNodeInserted", this, true); 251 | if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true); 252 | }, 253 | removeListeners: function() { 254 | this.removeListeners_(this.target); 255 | }, 256 | removeListeners_: function(node) { 257 | var options = this.options; 258 | if (options.attributes) node.removeEventListener("DOMAttrModified", this, true); 259 | if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true); 260 | if (options.childList) node.removeEventListener("DOMNodeInserted", this, true); 261 | if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true); 262 | }, 263 | addTransientObserver: function(node) { 264 | if (node === this.target) return; 265 | this.addListeners_(node); 266 | this.transientObservedNodes.push(node); 267 | var registrations = registrationsTable.get(node); 268 | if (!registrations) registrationsTable.set(node, registrations = []); 269 | registrations.push(this); 270 | }, 271 | removeTransientObservers: function() { 272 | var transientObservedNodes = this.transientObservedNodes; 273 | this.transientObservedNodes = []; 274 | transientObservedNodes.forEach(function(node) { 275 | this.removeListeners_(node); 276 | var registrations = registrationsTable.get(node); 277 | for (var i = 0; i < registrations.length; i++) { 278 | if (registrations[i] === this) { 279 | registrations.splice(i, 1); 280 | break; 281 | } 282 | } 283 | }, this); 284 | }, 285 | handleEvent: function(e) { 286 | e.stopImmediatePropagation(); 287 | switch (e.type) { 288 | case "DOMAttrModified": 289 | var name = e.attrName; 290 | var namespace = e.relatedNode.namespaceURI; 291 | var target = e.target; 292 | var record = new getRecord("attributes", target); 293 | record.attributeName = name; 294 | record.attributeNamespace = namespace; 295 | var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue; 296 | forEachAncestorAndObserverEnqueueRecord(target, function(options) { 297 | if (!options.attributes) return; 298 | if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) { 299 | return; 300 | } 301 | if (options.attributeOldValue) return getRecordWithOldValue(oldValue); 302 | return record; 303 | }); 304 | break; 305 | 306 | case "DOMCharacterDataModified": 307 | var target = e.target; 308 | var record = getRecord("characterData", target); 309 | var oldValue = e.prevValue; 310 | forEachAncestorAndObserverEnqueueRecord(target, function(options) { 311 | if (!options.characterData) return; 312 | if (options.characterDataOldValue) return getRecordWithOldValue(oldValue); 313 | return record; 314 | }); 315 | break; 316 | 317 | case "DOMNodeRemoved": 318 | this.addTransientObserver(e.target); 319 | 320 | case "DOMNodeInserted": 321 | var changedNode = e.target; 322 | var addedNodes, removedNodes; 323 | if (e.type === "DOMNodeInserted") { 324 | addedNodes = [ changedNode ]; 325 | removedNodes = []; 326 | } else { 327 | addedNodes = []; 328 | removedNodes = [ changedNode ]; 329 | } 330 | var previousSibling = changedNode.previousSibling; 331 | var nextSibling = changedNode.nextSibling; 332 | var record = getRecord("childList", e.target.parentNode); 333 | record.addedNodes = addedNodes; 334 | record.removedNodes = removedNodes; 335 | record.previousSibling = previousSibling; 336 | record.nextSibling = nextSibling; 337 | forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function(options) { 338 | if (!options.childList) return; 339 | return record; 340 | }); 341 | } 342 | clearRecords(); 343 | } 344 | }; 345 | global.JsMutationObserver = JsMutationObserver; 346 | if (!global.MutationObserver) { 347 | global.MutationObserver = JsMutationObserver; 348 | JsMutationObserver._isPolyfilled = true; 349 | } 350 | })(self); -------------------------------------------------------------------------------- /lib/MutationObserver.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 4 | * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5 | * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6 | * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7 | * Code distributed by Google as part of the polymer project is also 8 | * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9 | */ 10 | // @version 0.7.23 11 | "undefined"==typeof WeakMap&&!function(){var e=Object.defineProperty,t=Date.now()%1e9,r=function(){this.name="__st"+(1e9*Math.random()>>>0)+(t++ +"__")};r.prototype={set:function(t,r){var i=t[this.name];return i&&i[0]===t?i[1]=r:e(t,this.name,{value:[t,r],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return!(!t||t[0]!==e)&&(t[0]=t[1]=void 0,!0)},has:function(e){var t=e[this.name];return!!t&&t[0]===e}},window.WeakMap=r}(),function(e){function t(e){N.push(e),O||(O=!0,b(i))}function r(e){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(e)||e}function i(){O=!1;var e=N;N=[],e.sort(function(e,t){return e.uid_-t.uid_});var t=!1;e.forEach(function(e){var r=e.takeRecords();n(e),r.length&&(e.callback_(r,e),t=!0)}),t&&i()}function n(e){e.nodes_.forEach(function(t){var r=p.get(t);r&&r.forEach(function(t){t.observer===e&&t.removeTransientObservers()})})}function a(e,t){for(var r=e;r;r=r.parentNode){var i=p.get(r);if(i)for(var n=0;n0){var n=r[i-1],a=l(n,e);if(a)return void(r[i-1]=a)}else t(this.observer);r[i]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=p.get(e);t||p.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=p.get(e),r=0;r` tags in the main document block the loading of such imports. This is to ensure the imports have loaded and any registered elements in them have been upgraded. 79 | 80 | The webcomponents.js and webcomponents-lite.js polyfills parse element definitions and handle their upgrade asynchronously. If prematurely fetching the element from the DOM before it has an opportunity to upgrade, you'll be working with an `HTMLUnknownElement`. 81 | 82 | For these situations (or when you need an approximate replacement for the Polymer 0.5 `polymer-ready` behavior), you can use the `WebComponentsReady` event as a signal before interacting with the element. The criteria for this event to fire is all Custom Elements with definitions registered by the time HTML Imports available at load time have loaded have upgraded. 83 | 84 | ```js 85 | window.addEventListener('WebComponentsReady', function(e) { 86 | // imports are loaded and elements have been registered 87 | console.log('Components are ready'); 88 | }); 89 | ``` 90 | 91 | ## Known Issues 92 | 93 | * [Limited CSS encapsulation](#encapsulation) 94 | * [Element wrapping / unwrapping limitations](#wrapping) 95 | * [Custom element's constructor property is unreliable](#constructor) 96 | * [Contenteditable elements do not trigger MutationObserver](#contentedit) 97 | * [ShadowCSS: :host-context(...):host(...) doesn't work](#hostcontext) 98 | * [ShadowCSS: :host(.zot:not(.bar:nth-child(2))) doesn't work](#nestedparens) 99 | * [HTML imports: document.currentScript doesn't work as expected](#currentscript) 100 | * [execCommand isn't supported under Shadow DOM](#execcommand) 101 | 102 | ### Limited CSS encapsulation 103 | Under native Shadow DOM, CSS selectors cannot cross the shadow boundary. This means document level styles don't apply to shadow roots, and styles defined within a shadow root don't apply outside of that shadow root. [Several selectors](http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/) are provided to be able to deal with the shadow boundary. 104 | 105 | The Shadow DOM polyfill can't prevent document styles from leaking into shadow roots. It can, however, encapsulate styles within shadow roots to some extent. This behavior isn't automatically emulated by the Shadow DOM polyfill, but it can be achieved by manually using the included ShadowCSS shim: 106 | 107 | ``` 108 | WebComponents.ShadowCSS.shimStyling( shadowRoot, scope ); 109 | ``` 110 | 111 | ... where `shadowRoot` is the shadow root of a DOM element, and `scope` is the name of the scope used to prefix the selectors. This removes all ` 13 | 14 | 15 | 16 | 17 | 18 |

Running custom_element_proxy

19 |
20 | 21 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /test/custom_element_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | @TestOn('browser') 5 | library web_components.test.custom_element_test; 6 | 7 | import 'dart:async'; 8 | import 'dart:html'; 9 | import 'package:test/test.dart'; 10 | import 'package:web_components/web_components.dart'; 11 | 12 | @CustomElement('basic-element') 13 | class BasicElement extends HtmlElement { 14 | BasicElement.created() : super.created(); 15 | 16 | factory BasicElement() => document.createElement('basic-element'); 17 | } 18 | 19 | @CustomElement('child-element') 20 | class ChildElement extends BasicElement { 21 | ChildElement.created() : super.created(); 22 | 23 | factory ChildElement() => document.createElement('child-element'); 24 | } 25 | 26 | @CustomElement('extended-element', extendsTag: 'input') 27 | class ExtendedElement extends InputElement { 28 | ExtendedElement.created() : super.created(); 29 | 30 | factory ExtendedElement() => 31 | document.createElement('input', 'extended-element'); 32 | } 33 | 34 | main() { 35 | return initWebComponents().then((_) { 36 | var container = querySelector('#container') as DivElement; 37 | 38 | setUp(() { 39 | return new Future(() {}); 40 | }); 41 | 42 | tearDown(() { 43 | container.children.clear(); 44 | }); 45 | 46 | test('basic custom element', () { 47 | expect(document.querySelector('basic-element') is BasicElement, isTrue); 48 | container.append(new BasicElement()); 49 | container.appendHtml('', 50 | treeSanitizer: nullSanitizer); 51 | // elements are upgraded asynchronously 52 | return new Future(() {}).then((_) { 53 | var elements = container.querySelectorAll('basic-element'); 54 | expect(elements.length, 2); 55 | for (var element in elements) { 56 | expect(element is BasicElement, isTrue); 57 | } 58 | }); 59 | }); 60 | 61 | test('child custom element', () { 62 | expect(document.querySelector('child-element') is ChildElement, isTrue); 63 | container.append(new ChildElement()); 64 | container.appendHtml('', 65 | treeSanitizer: nullSanitizer); 66 | // elements are upgraded asynchronously 67 | return new Future(() {}).then((_) { 68 | var elements = container.querySelectorAll('child-element'); 69 | expect(elements.length, 2); 70 | for (var element in elements) { 71 | expect(element is ChildElement, isTrue); 72 | } 73 | }); 74 | }); 75 | 76 | test('extends input element', () { 77 | expect(document.querySelector('input') is ExtendedElement, isTrue); 78 | container.append(new ExtendedElement()); 79 | container.appendHtml('', 80 | treeSanitizer: nullSanitizer); 81 | // elements are upgraded asynchronously 82 | return new Future(() {}).then((_) { 83 | var elements = container.querySelectorAll('input'); 84 | expect(elements.length, 2); 85 | for (var element in elements) { 86 | expect(element is ExtendedElement, isTrue); 87 | } 88 | }); 89 | }); 90 | }); 91 | } 92 | 93 | class NullTreeSanitizer implements NodeTreeSanitizer { 94 | const NullTreeSanitizer(); 95 | void sanitizeTree(Node node) {} 96 | } 97 | 98 | final nullSanitizer = const NullTreeSanitizer(); 99 | -------------------------------------------------------------------------------- /test/custom_element_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | custom_element test 7 | 13 | 14 | 15 | 16 | 17 | 18 |

Running custom_element

19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /test/deps/a.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | @initializeTracker 5 | library web_components.test.deps.a; 6 | 7 | import 'package:initialize/src/initialize_tracker.dart'; 8 | -------------------------------------------------------------------------------- /test/deps/a.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/deps/b.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | @initializeTracker 5 | library web_components.test.deps.b; 6 | 7 | import 'package:initialize/src/initialize_tracker.dart'; 8 | -------------------------------------------------------------------------------- /test/deps/b.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/deps/c.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /test/foo/bar.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | @HtmlImport('bar.html') 5 | library web_components.test.foo.bar; 6 | 7 | import 'package:web_components/web_components.dart'; 8 | -------------------------------------------------------------------------------- /test/foo/bar.html: -------------------------------------------------------------------------------- 1 | bar 2 | -------------------------------------------------------------------------------- /test/html_import_annotation_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | @TestOn('browser') 5 | @HtmlImport(importPath) 6 | library web_components.test.html_import_annotation; 7 | 8 | import 'dart:html'; 9 | import 'package:test/test.dart'; 10 | import 'package:web_components/web_components.dart'; 11 | import 'foo/bar.dart' as foo_bar; 12 | 13 | const String importPath = 'my_import.html'; 14 | 15 | /// Uses [foo_bar]. 16 | main() async { 17 | await initWebComponents(); 18 | 19 | test('adds import to head', () { 20 | var my_import = document.head.querySelector('link[href="$importPath"]'); 21 | expect(my_import, isNotNull); 22 | expect(my_import.import.body.text, 'Hello world!\n'); 23 | 24 | var bar = document.head.querySelector('link[href="foo/bar.html"]'); 25 | expect(bar, isNotNull); 26 | expect(bar.import.body.text, 'bar\n'); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /test/html_import_annotation_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | custom_element_proxy test 7 | 13 | 14 | 15 | 16 | 17 | 18 |

Running html_import_annotation test

19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/init_web_components_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | @initializeTracker 5 | @TestOn('browser') 6 | library web_components.test.init_web_components_test; 7 | 8 | import 'package:test/test.dart'; 9 | import 'package:initialize/initialize.dart' show LibraryIdentifier; 10 | import 'package:initialize/src/initialize_tracker.dart'; 11 | import 'package:web_components/web_components.dart'; 12 | 13 | const String importPath = 'my_import.html'; 14 | 15 | main() { 16 | test('can initialize scripts from html imports', () { 17 | return initWebComponents().then((_) { 18 | var expectedInitializers = [ 19 | const LibraryIdentifier( 20 | #web_components.test.deps.b, null, 'deps/b.dart'), 21 | // This one changes based on deploy mode because its an inline script. 22 | const LibraryIdentifier( 23 | #web_components.test.deps.c, 24 | null, 25 | deployMode 26 | ? 'init_web_components_test.html.0.dart' 27 | : 'deps/c.html'), 28 | const LibraryIdentifier( 29 | #web_components.test.deps.a, null, 'deps/a.dart'), 30 | const LibraryIdentifier(#web_components.test.init_web_components_test, 31 | null, 'init_web_components_test.dart'), 32 | ]; 33 | expect(InitializeTracker.seen, expectedInitializers); 34 | }); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /test/init_web_components_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | init_web_components test 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |

Running init_web_components test

20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test/interop_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | @TestOn('browser') 5 | library template_wrappers_test; 6 | 7 | import 'dart:html'; 8 | import 'dart:js' show context, JsObject; 9 | import 'package:test/test.dart'; 10 | import 'package:web_components/interop.dart'; 11 | import 'package:web_components/polyfill.dart'; 12 | 13 | main() { 14 | setUp(() => customElementsReady); 15 | 16 | test('interop is supported', () { 17 | expect(isSupported, isTrue); 18 | }); 19 | 20 | test('previously created elements are not upgraded', () { 21 | var a = document.querySelector('x-a'); 22 | expect(a is HtmlElement, isTrue, reason: 'x-a is HtmlElement'); 23 | expect(a is XAWrapper, isFalse, reason: 'x-a should not be upgraded yet'); 24 | expect(_readX(a), 0); 25 | 26 | var b = document.querySelector('[is=x-b]'); 27 | expect(b is DivElement, isTrue, reason: 'x-b is DivElement'); 28 | expect(b is XBWrapper, isFalse, reason: 'x-b should not be upgraded yet'); 29 | expect(_readX(b), 1); 30 | 31 | var d = document.querySelector('x-d'); 32 | expect(d is HtmlElement, isTrue, reason: 'x-d is HtmlElement'); 33 | expect(d is XDWrapper, isFalse, reason: 'x-d should not be upgraded yet'); 34 | expect(_readX(d), 2); 35 | 36 | /// Note: this registration has a global side-effect and is assumed in the 37 | /// following tests. 38 | registerDartType('x-a', XAWrapper); 39 | registerDartType('x-b', XBWrapper, extendsTag: 'div'); 40 | registerDartType('x-c', XCWrapper); 41 | onlyUpgradeNewElements(); 42 | registerDartType('x-d', XDWrapper); // late on purpose. 43 | 44 | a = document.querySelector('x-a') as XAWrapper; 45 | expect(a is HtmlElement, isTrue, reason: 'x-a is HtmlElement'); 46 | expect(a is XAWrapper, isTrue, reason: 'x-a is upgraded to XAWrapper'); 47 | expect(a.x, 0); 48 | expect(a.wrapperCount, 0); 49 | 50 | b = document.querySelector('[is=x-b]') as XBWrapper; 51 | expect(b is DivElement, isTrue, reason: 'x-b is DivElement'); 52 | expect(b is XBWrapper, isTrue, reason: 'x-b is upgraded to XBWrapper'); 53 | expect(b.x, 1); 54 | expect(b.wrapperCount, 1); 55 | 56 | // x-d was not upgraded because its registration came after we stopped 57 | // upgrading old elements: 58 | d = document.querySelector('x-d'); 59 | expect(d is HtmlElement, isTrue, reason: 'x-d is HtmlElement'); 60 | expect(d is XDWrapper, isFalse, reason: 'x-d should not be upgraded yet'); 61 | expect(_readX(d), 2); 62 | 63 | var c = document.querySelector('x-c'); 64 | expect(c is HtmlElement, isTrue, reason: 'x-c is HtmlElement'); 65 | expect(c is XCWrapper, isFalse, reason: 'x-c should not be upgraded yet'); 66 | expect(_readX(c), null, reason: 'x-c has not been registered in JS yet'); 67 | }, skip: 'https://github.com/dart-lang/web-components/issues/38'); 68 | 69 | test('anything created after registering Dart type is upgraded', () { 70 | context.callMethod('addA'); 71 | var list = document.querySelectorAll('x-a'); 72 | expect(list.length, 2); 73 | var a = list[1]; 74 | expect(a is HtmlElement, isTrue, reason: 'x-a is HtmlElement'); 75 | expect(a is XAWrapper, isTrue, reason: 'x-a is upgraded to XAWrapper'); 76 | expect(a.x, 3); 77 | expect((a as XAWrapper).wrapperCount, 2); 78 | 79 | context.callMethod('addB'); 80 | list = document.querySelectorAll('[is=x-b]'); 81 | expect(list.length, 2); 82 | var b = list[1]; 83 | expect(b is DivElement, isTrue, reason: 'x-b is DivElement'); 84 | expect(b is XBWrapper, isTrue, reason: 'x-b is upgraded to XBWrapper'); 85 | expect(b.x, 4); 86 | expect((b as XBWrapper).wrapperCount, 3); 87 | 88 | // New instances of x-d should be upgraded regardless. 89 | context.callMethod('addD'); 90 | list = document.querySelectorAll('x-d'); 91 | expect(list.length, 2); 92 | var d = list[1]; 93 | expect(d is HtmlElement, isTrue, reason: 'x-d is HtmlElement'); 94 | expect(d is XDWrapper, isTrue, reason: 'x-d is upgraded to XDWrapper'); 95 | expect(d.x, 5); 96 | expect((d as XDWrapper).wrapperCount, 4); 97 | }, skip: 'https://github.com/dart-lang/web-components/issues/38'); 98 | 99 | test('events seen if Dart type is registered before registerElement', () { 100 | var c = document.querySelector('x-c'); 101 | expect(c is XCWrapper, isFalse); 102 | expect(_readX(c), null, reason: 'x-c has not been registered in JS yet'); 103 | 104 | context.callMethod('registerC'); 105 | c = document.querySelector('x-c'); 106 | expect(c is XCWrapper, isTrue); 107 | expect(c.x, 6); 108 | expect((c as XCWrapper).wrapperCount, 5); 109 | 110 | context.callMethod('addC'); 111 | var list = document.querySelectorAll('x-c'); 112 | expect(list.length, 2); 113 | expect(list[0], c); 114 | c = list[1]; 115 | expect(c is HtmlElement, isTrue, reason: 'x-c is HtmlElement'); 116 | expect(c is XCWrapper, isTrue, reason: 'x-c is upgraded to XCWrapper'); 117 | expect(c.x, 7); 118 | expect((c as XCWrapper).wrapperCount, 6); 119 | }, skip: 'https://github.com/dart-lang/web-components/issues/38'); 120 | 121 | test('element can extend another element', () { 122 | registerDartType('x-e', XEWrapper); 123 | context.callMethod('addE'); 124 | 125 | var e = document.querySelector('x-e'); 126 | expect(e is XEWrapper, isTrue); 127 | expect(e.x, 8); 128 | expect(e.y, 9); 129 | }, skip: 'https://github.com/dart-lang/web-components/issues/38'); 130 | } 131 | 132 | int _count = 0; 133 | 134 | abstract class Wrapper { 135 | int wrapperCount = _count++; 136 | int get x => _readX(this); 137 | } 138 | 139 | _readX(e) => new JsObject.fromBrowserObject(e)['x']; 140 | 141 | class XAWrapper extends HtmlElement with Wrapper { 142 | XAWrapper.created() : super.created(); 143 | } 144 | 145 | class XBWrapper extends DivElement with Wrapper { 146 | XBWrapper.created() : super.created(); 147 | } 148 | 149 | class XCWrapper extends HtmlElement with Wrapper { 150 | XCWrapper.created() : super.created(); 151 | } 152 | 153 | class XDWrapper extends HtmlElement with Wrapper { 154 | XDWrapper.created() : super.created(); 155 | } 156 | 157 | class XEWrapper extends HtmlElement with Wrapper { 158 | XEWrapper.created() : super.created(); 159 | 160 | int get y => new JsObject.fromBrowserObject(this)['y']; 161 | } 162 | -------------------------------------------------------------------------------- /test/interop_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | interop_test.html 7 | 13 | 14 | 15 | 16 | 17 | 18 |

Running interop_test

19 | 75 | 76 |
77 | 78 | 79 | 80 | 81 | 83 | 84 | -------------------------------------------------------------------------------- /test/location_wrapper_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | @TestOn('browser') 6 | library template_wrappers_test; 7 | 8 | import 'dart:html'; 9 | import 'package:test/test.dart'; 10 | 11 | main() { 12 | test('OK to access location with platform.js', () { 13 | expect(window.location.toString(), window.location.href); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /test/location_wrapper_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | location_wrappers_test 7 | 13 | 14 | 15 | 16 | 17 |

Running template_wrappers_test

18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/my_import.html: -------------------------------------------------------------------------------- 1 | Hello world! 2 | --------------------------------------------------------------------------------