From 126708ac37815e450e78c1f00d450006094716fc Mon Sep 17 00:00:00 2001 From: Philip Walton Date: Tue, 28 Oct 2014 12:32:28 -0700 Subject: [PATCH] Add files for new Google Analytics Demos & Tools site. --- .gitignore | 14 + CONTRIBUTING.md | 24 + LICENSE | 13 + README.md | 62 +- _config.yml | 10 - _prod.yml | 2 - app.yaml | 25 + assets/css/base/custom-media.css | 20 + assets/css/base/elements.css | 125 + assets/css/base/variables.css | 45 + .../components/account-explorer-results.css | 50 + .../components/account-explorer-search.css | 45 + assets/css/components/active-users.css | 66 + assets/css/components/auth-only.css | 55 + assets/css/components/box.css | 42 + assets/css/components/button.css | 34 + assets/css/components/chartjs.css | 51 + assets/css/components/content.css | 26 + assets/css/components/control.css | 33 + assets/css/components/dashboard.css | 105 + assets/css/components/date-range-selector.css | 55 + assets/css/components/flex-grid.css | 71 + assets/css/components/header.css | 204 ++ assets/css/components/icon.css | 23 + assets/css/components/logo.css | 75 + assets/css/components/nav-header.css | 71 + assets/css/components/nav.css | 96 + assets/css/components/screenshot.css | 35 + assets/css/components/site.css | 113 + assets/css/components/tech-info.css | 64 + assets/css/components/titles.css | 99 + assets/css/components/view-selector.css | 91 + assets/css/main.css | 57 + assets/css/utilities/media.css | 52 + assets/css/utilities/space.css | 20 + assets/css/vendor/explorer.css | 746 +++++ assets/css/vendor/highlight.css | 31 + assets/css/vendor/table-chart.css | 31 + .../screenshot.png | Bin 0 -> 41551 bytes assets/images/embed-api/screenshot.png | Bin 0 -> 52441 bytes .../images/enhanced-ecommerce/screenshot.png | Bin 0 -> 85462 bytes assets/images/explorer/arrow2.png | Bin 0 -> 195 bytes assets/images/explorer/big_roller.gif | Bin 0 -> 4176 bytes assets/images/explorer/bubble_point_white.png | Bin 0 -> 268 bytes assets/images/explorer/buttons3.3.png | Bin 0 -> 1949 bytes assets/images/explorer/check_no_box.png | Bin 0 -> 328 bytes assets/images/explorer/globe.png | Bin 0 -> 50598 bytes assets/images/explorer/had.mp3 | Bin 0 -> 5642 bytes assets/images/explorer/had.ogg | Bin 0 -> 13605 bytes assets/images/explorer/had.png | Bin 0 -> 111523 bytes assets/images/explorer/link.png | Bin 0 -> 431 bytes assets/images/explorer/small_roller.gif | Bin 0 -> 1456 bytes assets/images/ga-mark-white.svg | 3 + assets/images/google-analytics-partners.png | Bin 0 -> 77538 bytes assets/images/icons.svg | 60 + assets/images/polymer-elements/screenshot.png | Bin 0 -> 99541 bytes assets/javascript/account-explorer/index.js | 268 ++ assets/javascript/account-summaries.js | 312 ++ assets/javascript/analytics.js | 65 + assets/javascript/embed-api/active-users.js | 111 + .../embed-api/date-range-selector.js | 47 +- assets/javascript/embed-api/index.js | 62 + assets/javascript/embed-api/view-selector2.js | 327 +++ assets/javascript/explorer/ga-app.js | 45 + assets/javascript/explorer/ga-auth.js | 65 + assets/javascript/explorer/ga-coreapi.js | 537 ++++ assets/javascript/explorer/ga-dataquery.js | 162 + assets/javascript/explorer/ga-dropdown.js | 624 ++++ assets/javascript/explorer/ga-fun.js | 98 + assets/javascript/explorer/ga-loader.js | 74 + assets/javascript/explorer/ga-metadata.js | 283 ++ assets/javascript/explorer/ga-mgmt.js | 407 +++ assets/javascript/explorer/ga-pubsub.js | 76 + assets/javascript/explorer/ga-util.js | 182 ++ assets/javascript/explorer/ga-values.js | 231 ++ assets/javascript/explorer/index.js | 33 + assets/javascript/header.js | 56 + assets/javascript/highlighter.js | 34 + assets/javascript/index.js | 45 + assets/javascript/sidebar.js | 61 + favicon.ico | Bin 0 -> 8348 bytes gulpfile.js | 149 + index.yaml | 12 + lib/__init__.py | 0 lib/app.py | 37 + lib/controllers/__init__.py | 0 lib/controllers/base.py | 22 + lib/controllers/explorer_csv.py | 58 + lib/controllers/redirects.py | 20 + lib/csv_writer.py | 265 ++ lib/redirects.py | 20 + lib/template.py | 100 + meta.yaml | 106 + package.json | 38 + site/1-basic-dashboard.html | 123 - site/2-multiple-views.html | 165 -- site/3-custom-components.html | 218 -- site/4-interactive-charts.html | 212 -- site/5-third-party-visualizations.html | 417 --- site/6-pure-html-dashboards.html | 80 - site/assets/css/auth.css | 43 - site/assets/css/datachart.css | 32 - site/assets/css/main.css | 438 --- site/assets/html/polymer-body.html | 33 - site/assets/html/polymer.html | 11 - site/assets/images/ga-logo.png | Bin 4578 -> 0 bytes site/assets/js/chart.js | 1426 --------- site/assets/js/moment.js | 2610 ----------------- site/assets/js/platform.js | 17 - site/assets/js/platform.js.map | 1 - site/assets/js/polymer.js | 13 - site/assets/js/polymer.js.map | 1 - site/assets/js/promise.js | 364 --- site/components/active-users.js | 79 - site/components/viewpicker.js | 262 -- site/elements/ga-auth.html | 42 - site/elements/ga-chart.html | 94 - site/elements/ga-component.html | 48 - site/elements/ga-dashboard.html | 34 - site/elements/ga-datepicker.html | 68 - site/elements/ga-viewpicker.html | 59 - site/index.html | 95 - src/1-basic-dashboard.html | 88 - src/2-multiple-views.html | 130 - src/3-custom-components.html | 183 -- src/4-interactive-charts.html | 177 -- src/5-third-party-visualizations.html | 383 --- src/6-pure-html-dashboards.html | 79 - src/_includes/embed-api-snippet.html | 9 - src/_includes/ga-snippet.html | 11 - src/_includes/head.html | 8 - src/_includes/source-link.html | 6 - src/_layouts/default.html | 9 - src/_layouts/demo.html | 15 - src/assets/css/auth.css | 43 - src/assets/css/datachart.css | 32 - src/assets/css/main.css | 438 --- src/assets/html/polymer-body.html | 33 - src/assets/html/polymer.html | 11 - src/assets/images/ga-logo.png | Bin 4578 -> 0 bytes src/assets/js/chart.js | 1426 --------- src/assets/js/moment.js | 2610 ----------------- src/assets/js/platform.js | 17 - src/assets/js/platform.js.map | 1 - src/assets/js/polymer.js | 13 - src/assets/js/polymer.js.map | 1 - src/assets/js/promise.js | 364 --- src/components/active-users.js | 79 - src/components/datepicker.js | 124 - src/components/viewpicker.js | 262 -- src/elements/ga-auth.html | 42 - src/elements/ga-chart.html | 94 - src/elements/ga-component.html | 44 - src/elements/ga-dashboard.html | 34 - src/elements/ga-datepicker.html | 68 - src/elements/ga-viewpicker.html | 59 - src/index.html | 62 - templates/404.html | 10 + templates/_head.html | 10 + templates/_header.html | 29 + templates/_logo.html | 12 + templates/_nav-header.html | 13 + templates/_nav-project.html | 22 + templates/_nav.html | 29 + templates/_titles.html | 20 + templates/account-explorer/index.html | 52 + templates/base.html | 71 + .../dimensions-metrics-explorer/index.html | 35 + templates/embed-api/basic-dashboard.html | 65 + templates/embed-api/code/_basic-dashboard.js | 55 + .../embed-api/code/_custom-components.js | 144 + .../embed-api/code/_interactive-charts.js | 131 + .../embed-api/code/_multiple-date-ranges.js | 77 + templates/embed-api/code/_multiple-views.js | 94 + templates/embed-api/code/_snippet.js | 6 + .../code/_third-party-visualizations.js | 328 +++ templates/embed-api/custom-components.html | 110 + templates/embed-api/demo.html | 5 + .../dependencies/_custom-components.html | 5 + .../_third-party-visualizations.html | 13 + templates/embed-api/index.html | 32 + templates/embed-api/interactive-charts.html | 80 + templates/embed-api/multiple-date-ranges.html | 78 + templates/embed-api/multiple-views.html | 82 + .../embed-api/third-party-visualizations.html | 135 + templates/enhanced-ecommerce/index.html | 70 + templates/explorer/index.html | 132 + templates/index.html | 52 + templates/loginable.html | 32 + templates/polymer-elements/index.html | 43 + templates/spreadsheet-add-on/index.html | 36 + 191 files changed, 9919 insertions(+), 14005 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE delete mode 100644 _config.yml delete mode 100644 _prod.yml create mode 100644 app.yaml create mode 100644 assets/css/base/custom-media.css create mode 100644 assets/css/base/elements.css create mode 100644 assets/css/base/variables.css create mode 100644 assets/css/components/account-explorer-results.css create mode 100644 assets/css/components/account-explorer-search.css create mode 100644 assets/css/components/active-users.css create mode 100644 assets/css/components/auth-only.css create mode 100644 assets/css/components/box.css create mode 100644 assets/css/components/button.css create mode 100644 assets/css/components/chartjs.css create mode 100644 assets/css/components/content.css create mode 100644 assets/css/components/control.css create mode 100644 assets/css/components/dashboard.css create mode 100644 assets/css/components/date-range-selector.css create mode 100644 assets/css/components/flex-grid.css create mode 100644 assets/css/components/header.css create mode 100644 assets/css/components/icon.css create mode 100644 assets/css/components/logo.css create mode 100644 assets/css/components/nav-header.css create mode 100644 assets/css/components/nav.css create mode 100644 assets/css/components/screenshot.css create mode 100644 assets/css/components/site.css create mode 100644 assets/css/components/tech-info.css create mode 100644 assets/css/components/titles.css create mode 100644 assets/css/components/view-selector.css create mode 100644 assets/css/main.css create mode 100644 assets/css/utilities/media.css create mode 100644 assets/css/utilities/space.css create mode 100644 assets/css/vendor/explorer.css create mode 100644 assets/css/vendor/highlight.css create mode 100644 assets/css/vendor/table-chart.css create mode 100644 assets/images/dimensions-metrics-explorer/screenshot.png create mode 100644 assets/images/embed-api/screenshot.png create mode 100644 assets/images/enhanced-ecommerce/screenshot.png create mode 100644 assets/images/explorer/arrow2.png create mode 100644 assets/images/explorer/big_roller.gif create mode 100644 assets/images/explorer/bubble_point_white.png create mode 100644 assets/images/explorer/buttons3.3.png create mode 100644 assets/images/explorer/check_no_box.png create mode 100644 assets/images/explorer/globe.png create mode 100644 assets/images/explorer/had.mp3 create mode 100644 assets/images/explorer/had.ogg create mode 100644 assets/images/explorer/had.png create mode 100644 assets/images/explorer/link.png create mode 100644 assets/images/explorer/small_roller.gif create mode 100644 assets/images/ga-mark-white.svg create mode 100644 assets/images/google-analytics-partners.png create mode 100644 assets/images/icons.svg create mode 100644 assets/images/polymer-elements/screenshot.png create mode 100644 assets/javascript/account-explorer/index.js create mode 100644 assets/javascript/account-summaries.js create mode 100644 assets/javascript/analytics.js create mode 100644 assets/javascript/embed-api/active-users.js rename site/components/datepicker.js => assets/javascript/embed-api/date-range-selector.js (72%) create mode 100644 assets/javascript/embed-api/index.js create mode 100644 assets/javascript/embed-api/view-selector2.js create mode 100644 assets/javascript/explorer/ga-app.js create mode 100644 assets/javascript/explorer/ga-auth.js create mode 100644 assets/javascript/explorer/ga-coreapi.js create mode 100644 assets/javascript/explorer/ga-dataquery.js create mode 100644 assets/javascript/explorer/ga-dropdown.js create mode 100644 assets/javascript/explorer/ga-fun.js create mode 100644 assets/javascript/explorer/ga-loader.js create mode 100644 assets/javascript/explorer/ga-metadata.js create mode 100644 assets/javascript/explorer/ga-mgmt.js create mode 100644 assets/javascript/explorer/ga-pubsub.js create mode 100644 assets/javascript/explorer/ga-util.js create mode 100644 assets/javascript/explorer/ga-values.js create mode 100644 assets/javascript/explorer/index.js create mode 100644 assets/javascript/header.js create mode 100644 assets/javascript/highlighter.js create mode 100644 assets/javascript/index.js create mode 100644 assets/javascript/sidebar.js create mode 100644 favicon.ico create mode 100644 gulpfile.js create mode 100644 index.yaml create mode 100644 lib/__init__.py create mode 100644 lib/app.py create mode 100644 lib/controllers/__init__.py create mode 100644 lib/controllers/base.py create mode 100644 lib/controllers/explorer_csv.py create mode 100644 lib/controllers/redirects.py create mode 100644 lib/csv_writer.py create mode 100644 lib/redirects.py create mode 100644 lib/template.py create mode 100644 meta.yaml create mode 100644 package.json delete mode 100644 site/1-basic-dashboard.html delete mode 100644 site/2-multiple-views.html delete mode 100644 site/3-custom-components.html delete mode 100644 site/4-interactive-charts.html delete mode 100644 site/5-third-party-visualizations.html delete mode 100644 site/6-pure-html-dashboards.html delete mode 100644 site/assets/css/auth.css delete mode 100644 site/assets/css/datachart.css delete mode 100644 site/assets/css/main.css delete mode 100644 site/assets/html/polymer-body.html delete mode 100644 site/assets/html/polymer.html delete mode 100644 site/assets/images/ga-logo.png delete mode 100755 site/assets/js/chart.js delete mode 100644 site/assets/js/moment.js delete mode 100644 site/assets/js/platform.js delete mode 100644 site/assets/js/platform.js.map delete mode 100644 site/assets/js/polymer.js delete mode 100644 site/assets/js/polymer.js.map delete mode 100644 site/assets/js/promise.js delete mode 100644 site/components/active-users.js delete mode 100644 site/components/viewpicker.js delete mode 100644 site/elements/ga-auth.html delete mode 100644 site/elements/ga-chart.html delete mode 100644 site/elements/ga-component.html delete mode 100644 site/elements/ga-dashboard.html delete mode 100644 site/elements/ga-datepicker.html delete mode 100644 site/elements/ga-viewpicker.html delete mode 100644 site/index.html delete mode 100644 src/1-basic-dashboard.html delete mode 100644 src/2-multiple-views.html delete mode 100644 src/3-custom-components.html delete mode 100644 src/4-interactive-charts.html delete mode 100644 src/5-third-party-visualizations.html delete mode 100644 src/6-pure-html-dashboards.html delete mode 100644 src/_includes/embed-api-snippet.html delete mode 100644 src/_includes/ga-snippet.html delete mode 100644 src/_includes/head.html delete mode 100644 src/_includes/source-link.html delete mode 100644 src/_layouts/default.html delete mode 100644 src/_layouts/demo.html delete mode 100644 src/assets/css/auth.css delete mode 100644 src/assets/css/datachart.css delete mode 100644 src/assets/css/main.css delete mode 100644 src/assets/html/polymer-body.html delete mode 100644 src/assets/html/polymer.html delete mode 100644 src/assets/images/ga-logo.png delete mode 100755 src/assets/js/chart.js delete mode 100644 src/assets/js/moment.js delete mode 100644 src/assets/js/platform.js delete mode 100644 src/assets/js/platform.js.map delete mode 100644 src/assets/js/polymer.js delete mode 100644 src/assets/js/polymer.js.map delete mode 100644 src/assets/js/promise.js delete mode 100644 src/components/active-users.js delete mode 100644 src/components/datepicker.js delete mode 100644 src/components/viewpicker.js delete mode 100644 src/elements/ga-auth.html delete mode 100644 src/elements/ga-chart.html delete mode 100644 src/elements/ga-component.html delete mode 100644 src/elements/ga-dashboard.html delete mode 100644 src/elements/ga-datepicker.html delete mode 100644 src/elements/ga-viewpicker.html delete mode 100644 src/index.html create mode 100644 templates/404.html create mode 100644 templates/_head.html create mode 100644 templates/_header.html create mode 100644 templates/_logo.html create mode 100644 templates/_nav-header.html create mode 100644 templates/_nav-project.html create mode 100644 templates/_nav.html create mode 100644 templates/_titles.html create mode 100644 templates/account-explorer/index.html create mode 100644 templates/base.html create mode 100644 templates/dimensions-metrics-explorer/index.html create mode 100644 templates/embed-api/basic-dashboard.html create mode 100644 templates/embed-api/code/_basic-dashboard.js create mode 100644 templates/embed-api/code/_custom-components.js create mode 100644 templates/embed-api/code/_interactive-charts.js create mode 100644 templates/embed-api/code/_multiple-date-ranges.js create mode 100644 templates/embed-api/code/_multiple-views.js create mode 100644 templates/embed-api/code/_snippet.js create mode 100644 templates/embed-api/code/_third-party-visualizations.js create mode 100644 templates/embed-api/custom-components.html create mode 100644 templates/embed-api/demo.html create mode 100644 templates/embed-api/dependencies/_custom-components.html create mode 100644 templates/embed-api/dependencies/_third-party-visualizations.html create mode 100644 templates/embed-api/index.html create mode 100644 templates/embed-api/interactive-charts.html create mode 100644 templates/embed-api/multiple-date-ranges.html create mode 100644 templates/embed-api/multiple-views.html create mode 100644 templates/embed-api/third-party-visualizations.html create mode 100644 templates/enhanced-ecommerce/index.html create mode 100644 templates/explorer/index.html create mode 100644 templates/index.html create mode 100644 templates/loginable.html create mode 100644 templates/polymer-elements/index.html create mode 100644 templates/spreadsheet-add-on/index.html diff --git a/.gitignore b/.gitignore index e43b0f988..f0778c540 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,15 @@ +# OS or Editor folders .DS_Store +Thumbs.db +.cache + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# npm stuff +node_modules +npm-debug.log + +# Built files +public/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..1ba853922 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,24 @@ +Want to contribute? Great! First, read this page (including the small print at the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. We +use Github pull requests for this purpose. + +### The small print +Contributions made by corporations are covered by a different agreement than +the one above, the Software Grant and Corporate Contributor License Agreement. diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..fd1718006 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md index 225637180..36eb68187 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,39 @@ -Google Analytics Embed API Demos +Google Analytics Demos and Tools ================================ -This repo showcases many of the things that are possible with the [Embed API](https://developers.google.com/analytics/devguides/reporting/embed/v1/). Each demo builds on ideas presented in the previous demo, so you should check them out in order. If you're curious how anything is done, browse around in the code to see for yourself. +A showcase of demos and tools built with the various Google Analytics APIs and Libraries. +**[View the Site (https://ga-dev-tools.appspot.com)](https://ga-dev-tools.appspot.com)** -#### [View Demos](http://ga-dev-tools.appspot.com/demos/embed-api/) → +## Submitting Feedback / Reporting Bugs -## Demos Source Code +If a demo or tool is not working as you'd expect, or if you encounter an error while using the site, please [file an issue](https://github.com/googleanalytics/ga-dev-tools/issues/new) so we can fix it. -* [Basic Dashboard](https://github.com/googleanalytics/embed-api-demos/blob/master/site/1-basic-dashboard.html) -* [Multiple Views](https://github.com/googleanalytics/embed-api-demos/blob/master/site/2-multiple-views.html) -* [Multiple Date Ranges](https://github.com/googleanalytics/embed-api-demos/blob/master/site/3-multiple-dates.html) -* [Interactive Charts](https://github.com/googleanalytics/embed-api-demos/blob/master/site/4-interactive-charts.html) -* [Third-Party Visualizations](https://github.com/googleanalytics/embed-api-demos/blob/master/site/5-third-party-visualizations.html) -* [Pure HTML Dashboards](https://github.com/googleanalytics/embed-api-demos/blob/master/site/6-pure-html-dashboards.html) +If you've discovered a bug in one of the underlying APIs (i.e. not with the site itself), please submit a bug report on the [Google Analytics issue tracker](https://code.google.com/p/analytics-issues/). -## Custom Components Source Code +If you have general analytics questions, please ask them on Stack Overflow with either the [google-analytics](http://stackoverflow.com/questions/tagged/google-analytics) or [google-analytics-api](http://stackoverflow.com/questions/tagged/google-analytics-api) tag, or on one of the [Google Analytics developer forums](https://developers.google.com/analytics/community/#developer-discussion-groups). -* [Datepicker](https://github.com/googleanalytics/embed-api-demos/blob/master/site/components/datepicker.js) -* [Viewpicker](https://github.com/googleanalytics/embed-api-demos/blob/master/site/components/viewpicker.js) -* [Active Users](https://github.com/googleanalytics/embed-api-demos/blob/master/site/components/active-users.js) +## Building and Running the Site Locally -## Running the Demos Yourself +The Google Analytics demos and tools site runs on [Google App Engine](https://cloud.google.com/appengine/) and is built with [node.js](http://nodejs.org/). To run the site locally you'll need to install App Engine and node if you don't already have them. -To run the demos yourself, all you have to do is download the repo, navigate to the site folder, and start up a local server. Here's a really easy way: +Once App Engine and node are installed on your system, follow these steps to build and run the site locally: ```sh -# Clone the repo and cd into the site directory. -git clone git@github.com:googleanalytics/embed-api-demos.git -cd embed-api-demos/site/ +# Clone the repository. +git clone https://github.com/googleanalytics/ga-dev-tools.git +cd ga-dev-tools -# Start running a local server at http://localhost:4000 -python -m SimpleHTTPServer 4000 -``` - -Now just go to [http://localhost:4000](http://localhost:4000) in your browser and you should see the site. - -Alternatively you can copy and paste the files manually or use FTP to transfer them to a remote server, though if you do that you'll have to [change the client ID](https://developers.google.com/analytics/devguides/reporting/embed/v1/devguide#client-id) to one with your site's domain set as an approved origin. - -**Note:** if you copy the files into a folder that is not at the root of your server, most of the links will not work and the page will probably look broken. +# Install the build dependencies. +npm install +npm run build -### Building the site using Jekyll - -If you're familiar with [Jekyll](http://jekyllrb.com) it can make running the demos locally or deploying them to a remote server much easier. It's actually how this repo is built and how the demo app is deployed. +# Run the local App Engine server. +path/to/dev_appserver.py . +``` -```sh -# Clone the repo and cd into the repo directory. -git clone git@github.com:googleanalytics/embed-api-demos.git -cd embed-api-demos +Now you should be able to load [http://localhost:8080/](http://localhost:8080/) in your browser and see the site. (Note, the client ID associated with this project has the origin `localhost:8080` whitelisted. If you load the site on another port, authentication may not work property.) -# Run the site locally using Jekyll -jekyll serve -``` +If you're running App Engine on Windows or Mac, you can use the App Engine Launcher GUI to run the site as an alternative to running the above command. -The `jekyll serve` command will build all the files and load up a server on your local machine. Then you can go to [http://localhost:4000](http://localhost:4000) and everything should work fine. If you run `jekyll serve -w` it will also watch for changes to your source files and rebuild the site on the fly. This makes it easy to change a few things and see the results immediately. +To have your system watch for changes and automatically rebuild the source files, you can run `npm run watch` in place of the `npm run build` command shown above. -If you need to change any of the configuration settings (like your client ID) you can set them in the [_config.yml](https://github.com/googleanalytics/embed-api-demos/blob/master/_config.yml) file and rerun the `jekyll serve` command. diff --git a/_config.yml b/_config.yml deleted file mode 100644 index a3ef67562..000000000 --- a/_config.yml +++ /dev/null @@ -1,10 +0,0 @@ -source: ./src -destination: ./site - -# For running locally the path string should be empty. -path: - -# Update this with your client ID. -# https://developers.google.com/analytics/devguides/reporting/embed/v1/devguide#client-id -client_id: 623325626209-j1jm9d78ge0v4uf8b9cor31qsirungrq.apps.googleusercontent.com - diff --git a/_prod.yml b/_prod.yml deleted file mode 100644 index 5606cb67f..000000000 --- a/_prod.yml +++ /dev/null @@ -1,2 +0,0 @@ -path: /demos/embed-api -env: prod diff --git a/app.yaml b/app.yaml new file mode 100644 index 000000000..67d60e163 --- /dev/null +++ b/app.yaml @@ -0,0 +1,25 @@ +application: google.com:ga-dev-tools +version: 2-4 +runtime: python27 +api_version: 1 +threadsafe: yes + +libraries: +- name: webapp2 + version: "2.5.2" +- name: jinja2 + version: "2.6" +- name: yaml + version: "3.10" + +handlers: +- url: /favicon\.ico + static_files: favicon.ico + upload: favicon\.ico + secure: always +- url: /public + static_dir: public + secure: always +- url: /.* + script: lib.app.router + secure: always diff --git a/assets/css/base/custom-media.css b/assets/css/base/custom-media.css new file mode 100644 index 000000000..e77c39046 --- /dev/null +++ b/assets/css/base/custom-media.css @@ -0,0 +1,20 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@custom-media --break-sm (min-width: 420px); +@custom-media --break-md (min-width: 570px); +@custom-media --break-lg (min-width: 1024px); diff --git a/assets/css/base/elements.css b/assets/css/base/elements.css new file mode 100644 index 000000000..46d9bdc58 --- /dev/null +++ b/assets/css/base/elements.css @@ -0,0 +1,125 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import "normalize.css"; +@import "./variables"; + +*, +*:after, +*:before { + box-sizing: inherit; +} + +html { + box-sizing: border-box; + height: 100%; +} + +body { + color: var(--text-color); + font: 0.875em/1.4 'Open Sans', sans-serif; + text-rendering: optimizeLegibility; +} + +section { + max-width: 52em; +} + +ul { + list-style: square; + padding: 0 0 0 var(--gap); +} + +p, ul, ol, pre { + margin: 0 0 var(--gap); +} + +h1, h2 { + color: var(--text-color-faded); + font-weight: 300; +} + +h1 { + font-size: 2.5em; + margin: 0 0 calc(var(--gap)/2.5); +} + +h2 { + font-size: 1.75em; + margin: 1em 0; +} + +h3 { + color: #666; + font-size: 1.25em; + margin: 0 0 calc(var(--gap)/1.25); +} + +i { + display: inline-block; + font: inherit; +} + +a { + color: var(--ga-orange-dark); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +b, +strong { + font-weight: 600; +} + +code { + background: rgba(0, 0, 0, 0.075); + border-radius: 2px; + color: #000; + font-family: "Menlo", monospace; + font-size: .9em; + padding: 2px 5px 1px; +} + +figure { + margin: 0; +} + +img { + max-width: 100%; + height: auto; +} + +input, +select { + border: 1px solid var(--border-color); + border-radius: 4px; + box-sizing: border-box; + font: inherit; + font-weight: 400; + height: calc(34em/14); /* 34px @ 14px body font */ + line-height: calc(20em/14); /* 20px @ 14px body font */ + padding: calc(6em/14); /* 6px @ 14px body font */ +} + +input:focus, +select:focus { + border-color: #4d90fe; + outline: 0; +} diff --git a/assets/css/base/variables.css b/assets/css/base/variables.css new file mode 100644 index 000000000..921c28fff --- /dev/null +++ b/assets/css/base/variables.css @@ -0,0 +1,45 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +:root { + + --gap: 1.5em; + --gap-lg: 2em; + + --text-color: #333; + --text-color-light: #ddd; + --text-color-faded: #777; + --text-color-faint: #aaa; + + --bg-color-dark: #333; + --bg-color-dark-faded: #444; + --bg-color-light: #f4f2f0; + + --border-color: #d4d2d0; + + --ga-gray: #75787d; + --ga-orange-dark: #f05721; + --ga-orange-light: #f7991c; + + --ga-logo-height: 32px; + --ga-logo-width: 316px; + + --sidebar-width: 260px; + --sidebar-width-md: 280px; + + --quantum-timing: cubic-bezier(.4,0,.2,1); +} diff --git a/assets/css/components/account-explorer-results.css b/assets/css/components/account-explorer-results.css new file mode 100644 index 000000000..281e535db --- /dev/null +++ b/assets/css/components/account-explorer-results.css @@ -0,0 +1,50 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.AccountExplorerResults { + padding-top: var(--gap); +} + +.AccountExplorerResults-title { + font-size: 1.4em; + font-weight: 300; + margin: 0 0 var(--gap-lg); + text-align: center; +} + +.AccountExplorerResults table { + width: 100%; + table-layout: fixed; +} + +.AccountExplorerResults th, +.AccountExplorerResults td { + text-align: left; + padding: .75em 1em; + vertical-align: top; +} + +.AccountExplorerResults td { + border-top: 1px solid #e8e8e8; + word-break: break-word; +} + +.AccountExplorerResults-id { + color: var(--text-color-faded); + font-size: .9em; + margin-top: .5em; +} diff --git a/assets/css/components/account-explorer-search.css b/assets/css/components/account-explorer-search.css new file mode 100644 index 000000000..93874f48a --- /dev/null +++ b/assets/css/components/account-explorer-search.css @@ -0,0 +1,45 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import './control'; + +.AccountExplorerSearch { + padding: 1.5em; +} + +.AccountExplorerSearch-title { + font-size: 1.4em; + font-weight: 300; + margin: 0 0 var(--gap-lg); + text-align: center; +} + +.AccountExplorerSearch-control { + display: block; + height: auto; + margin: 0 auto 3em; + max-width: 32em; + padding: .75em 1em; +} + +.AccountExplorerSearch-icon { + /display: inline-block; + display: none; + font-size: 1.3em; + margin-right: 0.5em; + vertical-align: middle; +} diff --git a/assets/css/components/active-users.css b/assets/css/components/active-users.css new file mode 100644 index 000000000..714100d1c --- /dev/null +++ b/assets/css/components/active-users.css @@ -0,0 +1,66 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import './site'; + +/** + * ActiveUsers Component + */ + +.ActiveUsers { + background: var(--bg-color-light); + border: 1px solid var(--border-color); + border-radius: 4px; + font-weight: 300; + padding: .5em var(--gap); + white-space: nowrap; +} + +.ActiveUsers-value { + display: inline-block; + font-weight: 600; + margin-right: -.25em; +} + +.ActiveUsers.is-increasing { + animation: increase 3s; +} + +.ActiveUsers.is-decreasing { + animation: decrease 3s; +} + +@keyframes increase { + 0% {} + 10% { + background-color: hsl(120, 100%, 96%); + border-color: hsla(120, 100%, 25%, .5); + color: hsla(120, 100%, 25%, 1); + } + 100% {} +} + +@keyframes decrease { + 0% {} + 10% { + background-color: hsl(0, 100%, 96%); + border-color: hsla(0, 100%, 50%, .5); + color: hsl(0, 100%, 50%); + } + 100% {} +} + diff --git a/assets/css/components/auth-only.css b/assets/css/components/auth-only.css new file mode 100644 index 000000000..7cc0e5a4f --- /dev/null +++ b/assets/css/components/auth-only.css @@ -0,0 +1,55 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.AuthOnly { + height: 100%; + display: table; + position: relative; + width: 100%; +} + +.AuthOnly:after { + color: var(--text-color-faded); + content: 'Authorize to view this demo...'; + font-size: 1.1em; + font-weight: 300; + left: var(--gap); + line-height: 1.4em; + margin-top: -.7em; + position: absolute; + right: var(--gap); + text-align: center; + top: 50%; + z-index: 2; +} + +.AuthOnly--tool:after { + content: 'Authorize to use this tool...'; +} + +.AuthOnly > * { + visibility: hidden; +} + +.Site.is-authorized .AuthOnly::after, +.Site.is-authorized .AuthOnly::before { + content: none; +} + +.Site.is-authorized .AuthOnly > * { + visibility: visible; +} diff --git a/assets/css/components/box.css b/assets/css/components/box.css new file mode 100644 index 000000000..a37bfb318 --- /dev/null +++ b/assets/css/components/box.css @@ -0,0 +1,42 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.Box { + background: #fff; + border: 1px solid var(--border-color); + border-radius: 4px; + margin-bottom: var(--gap); + padding: var(--gap); +} + + +.Box-header { + border-bottom: 1px solid var(--border-color); + margin: -var(--gap) -var(--gap) var(--gap); + padding: var(--gap); +} + +@media (--break-lg) { + .Box { + margin-bottom: var(--gap-lg); + padding: var(--gap-lg); + } + .Box-header { + margin: -var(--gap-lg) -var(--gap-lg) var(--gap-lg); + padding: var(--gap-lg); + } +} diff --git a/assets/css/components/button.css b/assets/css/components/button.css new file mode 100644 index 000000000..98e3906fe --- /dev/null +++ b/assets/css/components/button.css @@ -0,0 +1,34 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.Button { + border: 1px solid #2F5BB7; + border-radius: 2px; + background: #498cf6; + color: #fff; + cursor: pointer; + font: inherit; + font-weight: bold; + margin-left: 1em; + min-width: 72px; + padding: 6px 12px; +} +.Button:focus { + box-shadow: inset 0 0 0 1px #FFF; + outline: none; +} + diff --git a/assets/css/components/chartjs.css b/assets/css/components/chartjs.css new file mode 100644 index 000000000..f386b401f --- /dev/null +++ b/assets/css/components/chartjs.css @@ -0,0 +1,51 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.Chartjs { + font-size: .85em; +} + +.Chartjs-figure { + height: 250px; +} + +.Chartjs-legend { + list-style: none; + margin: 0; + padding: 1em 0 0; + text-align: center; +} + +.Chartjs-legend > li { + display: inline-block; + padding: .25em .5em +} + +.Chartjs-legend > li > i { + display: inline-block; + height: 1em; + margin-right: .5em; + vertical-align: -.1em; + width: 1em; +} + +@media (--break-md) { + .Chartjs-figure { + /* Add some breathing room. */ + margin-right: var(--gap); + } +} diff --git a/assets/css/components/content.css b/assets/css/components/content.css new file mode 100644 index 000000000..d5b35362c --- /dev/null +++ b/assets/css/components/content.css @@ -0,0 +1,26 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.Content { + margin: var(--gap); +} + +@media (--break-lg) { + .Content { + margin: calc(var(--gap-lg)*1.5); + } +} diff --git a/assets/css/components/control.css b/assets/css/components/control.css new file mode 100644 index 000000000..d49581a87 --- /dev/null +++ b/assets/css/components/control.css @@ -0,0 +1,33 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.Control { + border: 1px solid var(--border-color); + border-radius: 4px; + box-sizing: border-box; + font: inherit; + font-weight: 400; + height: calc(34em/14); /* 34px @ 14px body font */ + line-height: calc(20em/14); /* 20px @ 14px body font */ + padding: calc(6em/14); /* 6px @ 14px body font */ + width: 100%; +} + +.Control:focus { + border-color: #4d90fe; + outline: 0; +} diff --git a/assets/css/components/dashboard.css b/assets/css/components/dashboard.css new file mode 100644 index 000000000..819f666a2 --- /dev/null +++ b/assets/css/components/dashboard.css @@ -0,0 +1,105 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import './site'; + +:root { + --Dashboard-maxWidth: 52em; +} + +/** + * Dashboard groups one or more items into a single view. + * It is also sign-in aware, so it shows a message to authorize + * if the user is not signed in. + */ + +.Dashboard { + background: hsla(0,0%,100%,.75); + border: 1px solid hsla(0,0%,0%,.075); + border-radius: 4px; + min-height: 10em; + margin-bottom: var(--gap); + max-width: var(--Dashboard-maxWidth); + padding: var(--gap); + position: relative; +} + +.Dashboard > * { + opacity: .03; +} + +.Dashboard::after { + color: var(--text-color-faded); + content: 'Authorize to view demo...'; + font-size: 1.1em; + font-weight: 300; + left: var(--gap); + line-height: 1.4em; + margin-top: -.7em; + position: absolute; + right: var(--gap); + text-align: center; + top: 50%; + z-index: 2; +} + +.Dashboard-header { + border-bottom: 1px solid var(--border-color); + margin: -var(--gap) -var(--gap) var(--gap); + padding: var(--gap); +} + +.Dashboard-footer { + border-top: 1px solid var(--border-color); + margin: -var(--gap) -var(--gap) var(--gap); + padding: var(--gap); +} + +.Dashboard--full { + max-width: 100%; +} + +.Site.is-authorized .Dashboard { + background: #fff; + border-color: var(--border-color); + min-height: 0; + position: static; +} +.Site.is-authorized .Dashboard > * { + opacity: 1; +} +.Site.is-authorized .Dashboard::after { + content: none; +} + +@media (--break-lg) { + .Dashboard { + margin-bottom: var(--gap-lg); + padding: var(--gap-lg); + } + .Dashboard-header { + margin: -var(--gap-lg) -var(--gap-lg) var(--gap-lg); + padding: var(--gap-lg); + } + .Dashboard-footer { + margin: -var(--gap-lg) -var(--gap-lg) var(--gap-lg); + padding: var(--gap); + } +} + + + diff --git a/assets/css/components/date-range-selector.css b/assets/css/components/date-range-selector.css new file mode 100644 index 000000000..26d6d54a7 --- /dev/null +++ b/assets/css/components/date-range-selector.css @@ -0,0 +1,55 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import '../base/custom-media'; + +/** + * DateRangeSelector Component + */ + +:root { + --DateRangeSelector-itemMinWidth: 150px; +} + +.DateRangeSelector { + display: flex; + flex-wrap: wrap; + margin: 0 0 -1em -1em; +} + +.DateRangeSelector-item { + margin: 0 0 1em 1em; + flex: 1 0 calc(100% - 1em); +} + +.DateRangeSelector-item > label { + font-weight: 700; + margin: 0 .25em .25em 0; + display: block; +} + +.DateRangeSelector-item > input { + width: 100%; +} + +@media (--break-md) { + .DateRangeSelector-item { + flex-basis: auto; + min-width: var(--DateRangeSelector-itemMinWidth); + } +} + diff --git a/assets/css/components/flex-grid.css b/assets/css/components/flex-grid.css new file mode 100644 index 000000000..f666e5084 --- /dev/null +++ b/assets/css/components/flex-grid.css @@ -0,0 +1,71 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import '../base/variables'; + + +:root { + --FlexGrid-gutter: var(--gap); + --FlexGrid-gutter-lg: var(--gap-lg); + --FlexGrid-itemMinWidth: 300px; + --FlexGrid-itemMinWidth-lg: 360px; +} + +.FlexGrid { + display: flex; + flex-wrap: wrap; + list-style: none; + margin: 0 0 -var(--FlexGrid-gutter) -var(--FlexGrid-gutter); + padding: 0; +} + +.FlexGrid-item { + flex: 1 0 calc(100% - var(--FlexGrid-gutter)); + margin: 0 0 var(--FlexGrid-gutter) var(--FlexGrid-gutter); +} + +.FlexGrid-item--fixed { + /* An `auto` flex-basis will use the size of the contents. */ + flex: 0 0 auto!important; +} + + +/** + * --halves modifier. + * Ensures that an item never takes up more than half of the width, i.e. + * no more that two items will ever be in a row. + */ +.FlexGrid--halves .FlexGrid-item { + flex-basis: 34%; +} + + +@media (--break-md) { + .FlexGrid-item { + flex-basis: var(--FlexGrid-itemMinWidth); + } +} + +@media (--break-lg) { + .FlexGrid { + margin: 0 0 -var(--FlexGrid-gutter-lg) -var(--FlexGrid-gutter-lg); + } + .FlexGrid-item { + flex-basis: var(--FlexGrid-itemMinWidth-lg); + margin: 0 0 var(--FlexGrid-gutter-lg) var(--FlexGrid-gutter-lg); + } +} diff --git a/assets/css/components/header.css b/assets/css/components/header.css new file mode 100644 index 000000000..22c05a485 --- /dev/null +++ b/assets/css/components/header.css @@ -0,0 +1,204 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import './site'; + +:root { + --Header-text-color-light: #eee; + --Header-text-color-light-faded: #bbb; + + --Header-text-color-dark: var(--text-color); + --Header-text-color-dark-faded: #999; + + --Header-overlay-color: rgba(0,0,0,.3); + --Header-overlay-color-light: rgba(0,0,0,.1); +} + +.Header { + position: relative; +} + +.Header-block { + background: var(--bg-color-dark); + box-shadow: 0 0 .5em rgba(0,0,0,.1); + padding: 1em var(--gap); + position: relative; +} + +.Header-menu { + border-radius: .333em; + color: #bbb; + font-size: 1.5em; + margin: calc(-1em/2-.333em) -.5em -.333em; + padding: .333em .5em; /* counter the margin */ + position: absolute; + top: 50%; +} + +.Header-menu:hover { + background: var(--Header-overlay-color); + color: #fff; +} + +.Header-user { + display: none; +} + +.Header-auth { + text-align: center; +} + +.Header-auth .gapi-analytics-auth-styles-signinbutton { + background: var(--ga-orange-light); + border-radius: 0; + display: block; + padding: 1em var(--gap); + transition: background-color .2s var(--quantum-timing); + width: auto; +} + +.Header-auth .gapi-analytics-auth-styles-signinbutton:hover { + background: var(--ga-orange-dark); + cursor: pointer; +} + +.Header-auth .gapi-analytics-auth-styles-signinbutton-image, +.Header-auth .gapi-analytics-auth-styles-signinbutton-buttonText { + display: inline-block; + vertical-align: middle; +} + +.Header-auth .gapi-analytics-auth-styles-signinbutton-image { + background: url('/public/images/ga-mark-white.svg') no-repeat 0 50%; + background-size: 1.5em; + border: 0; + height: 1.5em; + padding-left: 2.5em; + width: auto; +} + +.Header-auth .gapi-analytics-auth-styles-signinbutton-buttonText { + padding: 0; + font: inherit; +} + +.Header-logout { + display: none; +} + +/* The user is signed in + ========================================================================== */ + +.Site.is-authorized .Header-user { + border-radius: .333em; + color: var(--Header-text-color-light-faded); + display: inline-block; + font-size: 1.5em; + margin: calc(-1em/2-.333em) -.5em -.333em; + padding: .333em .5em; + position: absolute; + right: calc(var(--gap)/1.5); + text-align: right; + top: 50%; +} + +.Site.is-authorized .Header-user:hover { + background: var(--Header-overlay-color); + color: #fff; +} + +.Site.is-authorized .Header-auth { + display: none; +} + +/* The user has opened the header drawer (showing the user info). + ========================================================================== */ + +.Header.is-open .Header-auth { + background: #fff; + box-shadow: 0 0 .5em var(--Header-overlay-color-light); + color: var(--text-color-faded); + display: block; + padding: 1em var(--gap); + text-align: center; +} + +.Header.is-open .Header-embedApi, +.Header.is-open .Header-logout { + display: inline-block; + padding: 0 .5em; +} + +.Header.is-open .Header-user { + background: var(--Header-overlay-color); + color: #fff; +} + +.Header.is-open .Header-user::before { + border-color: transparent transparent currentColor; + border-width: 0 .333em .333em; +} + +@media (--break-lg) { + + .Header-block { + background: #fff; + padding: var(--gap-lg) calc(var(--gap-lg)*1.5) calc(var(--gap-lg)*1.5); + } + + .Header-menu { + display: none; + } + + .Site.is-authorized .Header-user { + color: var(--Header-text-color-dark-faded); + margin: 0; + padding: .333em .5em; + right: calc(var(--gap-lg)/1.5); + top: calc(var(--gap-lg)/1.5); + } + + .Site.is-authorized .Header-user:hover, + .Header.is-open .Header-user { + background: var(--Header-overlay-color-light); + color: var(--Header-text-color-dark); + } + + .Header.is-open .Header-auth { + background: #fff; + border-radius: .5em; + box-shadow: 0 0 0 1px var(--Header-overlay-color-light); + + padding: 0 .5em; + position: absolute; + line-height: 2.5em; + right: 6em; /* covers the width of the user icon + spacing */ + text-align: right; + top: 2em; + } + + .Header.is-open .Header-auth * { + vertical-align: baseline; + } + + .Header-auth .gapi-analytics-auth-styles-signinbutton { + font-size: 1em; + padding: 1.5em calc(var(--gap-lg)*1.5); + text-align: left; + } + +} diff --git a/assets/css/components/icon.css b/assets/css/components/icon.css new file mode 100644 index 000000000..2e28fda56 --- /dev/null +++ b/assets/css/components/icon.css @@ -0,0 +1,23 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.Icon { + display: inherit; + fill: currentColor; + height: 1em; + width: 1em; +} diff --git a/assets/css/components/logo.css b/assets/css/components/logo.css new file mode 100644 index 000000000..6ea1b7ef5 --- /dev/null +++ b/assets/css/components/logo.css @@ -0,0 +1,75 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.Logo { + margin: 0 3em; +} + +.Logo-full { + display: none; +} + +.Logo-partial { + text-align: center; +} + +.Logo-partial > svg { + fill: #aaa; + height: 16px; +} + +.Logo-partial::after { + content: 'Demos & Tools'; + color: #ddd; + display: block; + font-size: 1.4em; + font-weight: 300; + letter-spacing: -.03em; + line-height: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + word-spacing: .2em; +} + +@media (--break-sm) { + .Logo-partial > svg { + display: none; + } + .Logo-partial::after { + content: 'Google Analytics Demos & Tools'; + line-height: normal; + } +} + +@media (--break-lg) { + .Logo { + margin: 0; + } + .Logo-full { + display: block; + } + .Logo-full > svg { + display: inherit; + fill: var(--ga-gray); + height: var(--ga-logo-height); + width: var(--ga-logo-width); + } + .Logo-partial { + display: none; + } +} diff --git a/assets/css/components/nav-header.css b/assets/css/components/nav-header.css new file mode 100644 index 000000000..e9306dcef --- /dev/null +++ b/assets/css/components/nav-header.css @@ -0,0 +1,71 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.NavHeader { + padding: 1em var(--gap); + position: relative; +} + +.NavHeader-homeLink { + color: var(--text-color-faded); + line-height: var(--ga-logo-height); +} +.NavHeader-homeLink:hover { + text-decoration: none; + color: var(--text-color-light); +} + +.NavHeader-homeIcon { + font-size: 1.1em; + margin-right: 1em; +} + +.NavHeader-title { + color: inherit; + display: inline-block; + font-size: 1.1em; + font-weight: 300; + letter-spacing: .3em; + margin: 0 1em 0; + text-transform: uppercase; +} + +.NavHeader-controls { + border-radius: .333em; + color: #eee; + display: block; + font-size: 1.5em; + margin: calc(-1em/2-.333em) -.333em -.333em; + padding: .333em; + position: absolute; + right: calc(var(--gap)/1.5); + top: 50%; +} + +.NavHeader-controls:hover { + background: rgba(0,0,0,.2); +} + +@media (--break-lg) { + .NavHeader { + padding: var(--gap-lg); + } + + .NavHeader-controls { + display: none; + } +} diff --git a/assets/css/components/nav.css b/assets/css/components/nav.css new file mode 100644 index 000000000..9fc044008 --- /dev/null +++ b/assets/css/components/nav.css @@ -0,0 +1,96 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +:root { + --Nav-indent: 1.25em; + --Nav-linkPaddingV: .4em; +} + +.Nav { + +} + +.Nav ol { + list-style: none; + margin: 0; + padding: 0; +} + +.Nav-section { + border-top: 1px solid #555; + padding: var(--gap) 0; +} + +.Nav-category { + color: var(--text-color-light); + font-size: 1.3em; + font-weight: 400; + letter-spacing: .05em; + margin-bottom: .5em; + padding: 0 calc(var(--gap)/1.3); /* Account for font-size. */ +} + +.Nav-link { + color: var(--text-color-faint);; + display: block; + padding: var(--Nav-linkPaddingV) var(--gap); +} +.Nav-link:hover { + background-color: hsla(0,0%,0%,.15); + text-decoration: none; +} +.Nav-link--selected, +.Nav-link--selected:hover { + background-color: hsla(0,0%,100%,.075); + color: #fff; + cursor: default; + pointer-events: none; +} + +.Nav-link--nested { + padding-left: calc(var(--gap)+var(--Nav-indent)); +} + +.Nav-status { + color: var(--ga-orange-dark); + font-size: .8em; + font-weight: 700; + line-height: 0; + margin-left: .25em; + position: relative; + text-transform: capitalize; + top: -0.5em; + vertical-align: baseline; +} +.Nav-status:after { + content: '!'; +} + +@media (--break-lg) { + .Nav-category { + padding: 0 calc(var(--gap-lg)/1.3); /* Account for font-size. */ + } + + .Nav-link { + padding-left: var(--gap-lg); + padding-right: var(--gap-lg); + } + .Nav-link--nested { + padding-left: calc(var(--gap-lg)+var(--Nav-indent)); + } +} + diff --git a/assets/css/components/screenshot.css b/assets/css/components/screenshot.css new file mode 100644 index 000000000..a7a57307d --- /dev/null +++ b/assets/css/components/screenshot.css @@ -0,0 +1,35 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.Screenshot { + margin-bottom: var(--gap); +} + +.Screenshot img { + border: 1px solid var(--border-color); + border-radius: 4px; + height: auto; + max-width: 100%; +} + +.Screenshot figcaption { + color: var(--text-color-faint); + font-size: .85em; + font-style: italic; + padding: .5em 4px 0; + text-align: right; +} diff --git a/assets/css/components/site.css b/assets/css/components/site.css new file mode 100644 index 000000000..be3f8d434 --- /dev/null +++ b/assets/css/components/site.css @@ -0,0 +1,113 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import '../base/variables'; +@import '../base/custom-media'; + +.Site { + background: var(--bg-color-light); + min-height: 100%; + min-width: var(--sidebar-width); +} + +.Site-sidebar { + background: var(--bg-color-dark-faded); + bottom: 0; + box-shadow: 0 0 var(--gap) rgba(0, 0, 0, 0); + left: -var(--sidebar-width); + max-width: 100%; + min-width: var(--sidebar-width); + overflow-y: auto; + position: fixed; + top: 0; + transform: translate3d(0, 0, 0); + transition: transform .3s cubic-bezier(.4,0,.2,1); + width: var(--sidebar-width); + z-index: 1; +} + +.Site.is-expanded { + overflow: hidden; +} + +.Site.is-expanded .Site-sidebar { + box-shadow: 0 0 var(--gap) rgba(0, 0, 0, 0.5); + transform: translate3d(var(--sidebar-width), 0, 0); +} + + +.Site-main { + /* TODO(philipwalton): fallback for non-flexbox. + min-height: 100%; + */ +} + +@media (--break-md) { + .Site { + /* TODO(philipwalton): remove this once Query Explorer is responsive. */ + /* min-width: 768px; */ + } + .Site-sidebar { + left: -var(--sidebar-width-md); + min-width: var(--sidebar-width-md); + width: var(--sidebar-width-md); + } + .Site.is-expanded .Site-sidebar { + transform: translate3d(var(--sidebar-width-md), 0, 0); + } +} + +@media (--break-lg) { + .Site { + display: flex; + + /* TODO(philipwalton): add fallback for non-supporting browsers; */ + /* TODO(philipwalton): Two column, equal height hack for fallback. + background-image: linear-gradient( + to right, + var(--bg-color-dark-faded) 0%, + var(--bg-color-dark-faded) var(--sidebar-width-lg)); + background-size: var(--sidebar-width-lg) 1px; + background-repeat: repeat-y; + */ + } + + .Site-sidebar { + background: var(--bg-color-dark-faded); + border-top: .4em solid #222; + box-shadow: none; + overflow: visible; + position: static; + transition: none; + z-index: 0; + } + + .Site.is-expanded .Site-sidebar { + transform: none; + } + + .Site-main { + border-top: .4em solid #f7991c; + box-shadow: 0 0 1em rgba(0,0,0,.3); + flex: 1; + position: relative; /* To get it stacked above the sidebar */ + + /* TODO(philipwalton): fallback for non-flexbox + margin-left: var(--sidebar-width-lg); + */ + } +} diff --git a/assets/css/components/tech-info.css b/assets/css/components/tech-info.css new file mode 100644 index 000000000..3ca7a90b5 --- /dev/null +++ b/assets/css/components/tech-info.css @@ -0,0 +1,64 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +:root { + --TechInfo-color: hsl(200, 75%, 55%); +} + +.TechInfo { + background: #fff; + border: 1px solid var(--TechInfo-color); + border-radius: 4px; + display: flex; + margin: var(--gap) 0; + max-width: 52em; + padding: 1.25em; +} + +.TechInfo-icon { + fill: var(--TechInfo-color); + flex: 0 0 auto; + margin-right: 1em; + height: 1.5em; + overflow: visible; + width: 1.5em; +} + +.TechInfo-content { + color: var(--text-color-faded); + flex: 1; + font-size: .9em; + margin: 0; +} + +.TechInfo-title { + color: var(--TechInfo-color); + font-size: 1.2em; + font-weight: 600; + margin: 0 0 .5em; +} + +.TechInfo a { + color: var(--TechInfo-color); + text-decoration: underline; +} + +@media (--break-lg) { + .TechInfo { + margin: var(--gap-lg) 0; + } +} diff --git a/assets/css/components/titles.css b/assets/css/components/titles.css new file mode 100644 index 000000000..ca30f8e91 --- /dev/null +++ b/assets/css/components/titles.css @@ -0,0 +1,99 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import '../base/variables'; +@import '../base/custom-media'; + + +.Titles { + font-weight: 300; + /letter-spacing: -.03em; + line-height: 1.2; + margin: 0 0 var(--gap); + /word-spacing: .2em; +} +.Titles-main, +.Titles-sub { + color: inherit; + font: inherit; + margin: 0; +} +.Titles-main { + font-size: 1.4em; +} +.Titles-sub { + opacity: .6; + margin-top: .2em; +} +.Titles-action { + background: var(--ga-orange-dark); + border-radius: .25em; + color: #fff; + display: inline-block; + font-weight: 400; + margin-top: .8em; + padding: .3em .6em .2em; + vertical-align: .4em; +} +.Titles-action:focus, +.Titles-action:hover { + text-decoration: none; +} + + +/** + * `--hero` modifer + * Creates a bigger set of titles for use in page headers. Also + * inlines the main and subtitle in larger medias. + */ + +.Titles--hero { + color: var(--ga-gray); +} + +.Titles--hero .Titles-main { + font-size: 2.25em; +} +.Titles--hero .Titles-sub { + font-size: 1.25em; +} + +@media (--break-md) { + .Titles--hero { + margin: 1em 0 var(--gap); + } + .Titles--hero .Titles-main { + display: inline-block; + margin-right: .25em; + } + .Titles--hero .Titles-sub { + display: inline-block; + } +} + +@media (--break-lg) { + .Titles--hero { + margin: 4em 0 0; + } + .Titles--hero .Titles-main { + font-size: 3em; + margin-right: .5em; + } + .Titles--hero .Titles-sub { + font-size: 1.75em; + } +} diff --git a/assets/css/components/view-selector.css b/assets/css/components/view-selector.css new file mode 100644 index 000000000..21086ed31 --- /dev/null +++ b/assets/css/components/view-selector.css @@ -0,0 +1,91 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.ViewSelector, +.ViewSelector2 { + display: block +} + +.ViewSelector2-item, +/* For the old school view selector. */ +.ViewSelector table { + display: block; + margin-bottom: 1em; + width: 100%; +} + +.ViewSelector2-item > label, +/* For the old school view selector. */ +.ViewSelector td:first-child { + font-weight: 700; + margin: 0 .25em .25em 0; + display: block; +} + +.ViewSelector2-item > select { + width: 100%; +} + + +/* + * Additional hacks to get the native ViewSelector component (which uses + * closure widgets) to look like our custom ViewSelector extension. + */ + +.ViewSelector table, +.ViewSelector tbody, +.ViewSelector tr, +.ViewSelector td { + display: block; +} + +.ViewSelector table { + height: auto!important; + width: auto!important; +} + +.ViewSelector td { + width: auto!important; +} + +.ViewSelector td:last-child * { + display: block; + text-align: left; +} + +.ViewSelector td:last-child > div { + font-weight: 400; + margin: 0; +} + +@media (--break-md) { + .ViewSelector, + .ViewSelector2 { + display: flex; + margin: 0 0 -1em -1em; + width: calc(100% + 1em); + } + + .ViewSelector2-item, + /* For the old school view selector. */ + .ViewSelector table { + flex: 1 1 calc(100%/3 - 1em); + margin-left: 1em; + } +} + + diff --git a/assets/css/main.css b/assets/css/main.css new file mode 100644 index 000000000..d97ecff4a --- /dev/null +++ b/assets/css/main.css @@ -0,0 +1,57 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +/* External dependencies. */ +@import 'normalize.css'; + +/* Base styles, media queries, variables, etc. */ +@import './base/custom-media'; +@import './base/elements'; +@import './base/variables'; + +/* Components. */ +@import './components/account-explorer-results'; +@import './components/account-explorer-search'; +@import './components/active-users'; +@import './components/auth-only'; +@import './components/box'; +@import './components/button'; +@import './components/chartjs'; +@import './components/content'; +@import './components/control'; +@import './components/dashboard'; +@import './components/date-range-selector'; +@import './components/flex-grid'; +@import './components/header'; +@import './components/icon'; +@import './components/logo'; +@import './components/nav'; +@import './components/nav-header'; +@import './components/screenshot'; +@import './components/site'; +@import './components/tech-info'; +@import './components/titles'; +@import './components/view-selector'; + +/* Utilities. */ +@import './utilities/media.css'; +@import './utilities/space.css'; + +/* Vendor styles (which don't necessarily follow conventions) */ +@import './vendor/explorer'; +@import './vendor/highlight'; +@import './vendor/table-chart'; diff --git a/assets/css/utilities/media.css b/assets/css/utilities/media.css new file mode 100644 index 000000000..a80b03ea7 --- /dev/null +++ b/assets/css/utilities/media.css @@ -0,0 +1,52 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import '../base/custom-media'; + +.u-hidden { + display: none; +} +.u-block { + display: block; +} + +@media (--break-sm) { + .u-sm-hidden { + display: none; + } + .u-sm-block { + display: block; + } +} + +@media (--break-md) { + .u-md-hidden { + display: none; + } + .u-md-block { + display: block; + } +} + +@media (--break-lg) { + .u-lg-hidden { + display: none; + } + .u-lg-block { + display: block; + } +} diff --git a/assets/css/utilities/space.css b/assets/css/utilities/space.css new file mode 100644 index 000000000..c50212b00 --- /dev/null +++ b/assets/css/utilities/space.css @@ -0,0 +1,20 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +.u-spaceDouble { + margin: 0 0 calc(2*var(--gap)); +} diff --git a/assets/css/vendor/explorer.css b/assets/css/vendor/explorer.css new file mode 100644 index 000000000..f183874bf --- /dev/null +++ b/assets/css/vendor/explorer.css @@ -0,0 +1,746 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +#explorer { + box-sizing: content-box; + max-width: 1000px; +} + +.left { + float: left; +} + +.right { + float: right; +} + +.hidden { + position: absolute; + left: -2000px; +} +#intro { + padding-bottom: 1em; +} + +/* the bar above the query url, including auth buttons */ +#authBar, #resultBar { + width: 100%; + margin: 15px 0; + height: 30px; + clear: both; +} + +/* little description of number of results returned vs matched */ +#resultsInfo { + margin-top: 0; + font-size: 13px; +} + +/* title of the query url */ +#queryUrlHeading { + display: block; + float: left; + font-weight: normal; + margin: 12px 0 0 0; +} + +/* Button related stuffz */ +.buttonBar { + position: relative; +} + +#gaAuthLogin, #gaAuthLogout { + float: right; + display: none; +} + +#gaAuthLogout { + margin-top: 6px; + font-size: 13px; +} + +#gaAuthLogin { + margin-left: 15px; +} + +#gaAuthLogin, #getData, #csvDownload { + text-decoration: none; +} + +#gaAuthLogin .kd-tooltip { + left: -20px; +} + +#gaAuthLogin .pointer { + left: 80px; +} + +#queryUri .kd-tooltip { + left: -2px; +} + +#shareLink .kd-tooltip { + left: -9px; +} + +#shareLink .pointer { + margin: 0 0 0 1px; +} + +#shareLink .pointer, +#queryUri .pointer { + left: 37px; +} + +#deepDiv { + margin-left: 15px; +} + +/* Bubbles, not MJs */ +#shareBubble { + position: absolute; + width: 400px; +} + +#queryUriBubble { + position: absolute; + width: 542px; +} + +#queryUriText { + resize: none; + border: 1px solid var(--border-color); +} + +.ga-bubble { + top: 40px; +} + +/* Query Builder */ +#queryBuilder, #accountSelector { + /background-color: #E8EEFA; + font-size: 14px; + overflow: hidden; + padding: 5px 0; + position: relative; + width: 100%; +} + +#accountSelector { + margin-bottom: 15px; + border-top: 1px solid #ddd; +} + +#queryBuilder { + border-bottom: 1px solid #ddd; +} + +/* The div surrounding the Query Builder's Parameters */ +#queryParams { + float: left; + width: 520px; +} + +/*query explorer table */ +.qe-table, .table { + list-style-type: none; + margin :2px; + padding: 0; + width: 100% /* triggers hasLayout in IE */ +} +/* table rows */ +.qe-row, .row { + overflow: hidden; + padding: 2px 0; + position: relative; + width: 100% /* triggers hasLayout in IE */ +} + +/* table column 1 */ +.qe-table-c1, .asel-c1 { + padding: 5px 0 3px 15px; + float: left; + width: 95px; +} + +/* account select col 1 */ +.asel-c1 { + width: 110px; +} + + +/* table colum 2 */ +.qe-table-c2 { + padding-top: 4px; + float: left; + width: 15px; +} + +/* required asterix */ +.qe-asterisk { + color: var(--ga-orange-dark); + left: 4px; + padding-top: 4px; + position: absolute; +} + +/* input textbox for the query parameter */ +.queryInput { + background-color: white; + border: 1px solid var(--border-color); + float: left; + padding-top: 4px; + padding-bottom: 4px; /* right padding set by dd-dropInput */ + padding: 4px; +} + +.queryInput:active, +.queryInput:hover { + border: 1px solid #999; +} + +/* For status messages in input boxes */ +.inputStatusMsg { + color: #666; + font-style: italic; +} + +/* highlight style */ +.highlight { + background-color: rgba(0,0,0,.1); + /color: #E8EEFA; +} + +/* div to hold the account name drop down */ +#accountName { + color: #333; + float: left; + margin: 0 0 0 2px; + width: 267px; +} + +#gaStatus { + color: #333; + margin: 0 20px 0 520px; +} + +/* div for the help box */ +#gaHelp { + font-size: 14px; + height: 220px; + margin: 5px 0 0 15px; + padding: 8px 0; +} + +/* param name in in the help box */ +.name { + border-bottom: #666 solid 1px; + font-weight: bold; + margin: 0; + padding: 0; +} + +/* text if a parameter is required */ +#gaHelp .req { + margin-top: 0px; +} + +/* help link to documentation */ +#gaHelp .docLink { + bottom: 10px; + position: absolute; +} + +/* button to get data from the API*/ +#getData { + float: left; + display: none; +} + +/* Sampled Data message */ +#sampledData { + margin: 3px 0 0 37px; + display: none; + float: left; + font-size: smaller; + background-color: lightGoldenrodYellow; + padding: 5px; +} + +#gaOutput { + display: inline-block; +} + + +/* style of the main data loader img */ +#loader { + color: #999; + display: none; + font-size: 20px; + margin-left: 15px; +} + +/* background to desgniate loading of a dropdown */ +.small-loader { + background: white url('/public/images/explorer/small_roller.gif') no-repeat scroll right center; +} + +/* style of loader image */ +#loader img { + margin-right: 15px; + vertical-align: middle; +} + +/* Button Styles from: http://www.filamentgroup.com/ respect*/ +/* REQUIRED BUTTON STYLES: */ +button { + border: 0; + cursor: pointer; + position: relative; + padding: 0; + overflow: visible; /* removes extra side padding in IE */ +} + +button::-moz-focus-inner { + border: none; /* overrides extra padding in Firefox */ +} + +button span { + display: block; + position: relative; + white-space: nowrap; +} + +@media screen and (-webkit-min-device-pixel-ratio:0) { + /* Safari and Google Chrome only - fix margins */ + button span { + margin-top: -1px; + } +} + +/* OPTIONAL BUTTON STYLES for applying custom look and feel: */ +button.submitBtn { + background: transparent url('/public/images/explorer/buttons3.3.png') no-repeat right -96px; + display: none; + font-size: 14px; + height: 30px; + padding: 0 14px 0 0; + text-align: center; +} + +button.submitBtn span { + background: transparent url('/public/images/explorer/buttons3.3.png') no-repeat left top; + padding: 5px 0 0 13px; + height: 31px; +} + +/* the redundant class is used to apply the hover state with a script */ +button.submitBtn:hover, button.submitBtnHover { + background-position: right -142px; +} + +button.submitBtn:hover span, button.submitBtnHover span { + background-position: 0 -46px; +} + +/* + * Styles for the dropdown + */ +/* class to distinguish the drop down's input box */ +.dd-dropInput { + background: white url('/public/images/explorer/arrow2.png') no-repeat right 2px; + border: var(--border-color) solid 1px; +} + + +.dd-cursor { + cursor: pointer; +} + +.dd_click_space, +.dd-cursor { + padding-right: 21px; +} + +/* the drop down div */ +.dd-main { + background-color: white; + border: var(--border-color) solid 1px; + display: none; + height: 400px; + overflow: auto; + position: absolute; + width: 280px; +} + +/* group headings in the drop down */ +.dd-groupName { + background-color: var(--border-color); + font-size:14px; + padding:5px 0 3px 5px; +} + +/* rows in the drop down */ +.dd-row { + display: block; + font-size: 13px; + line-height: 125%; + padding: 3px 0; + position: relative; + overflow: hidden; + zoom: 1; /* triggers hasLayout in IE */ + +} + +/* indent for the account and segments dropdown */ +.dd-item, #segment-dd .dd-row { + padding: 2px 0 2px 15px; +} + +/* highlight in the dropdown */ +.dd-highlight { + background-color: #666; + color: white; +} + +/* checkbox in the drop down */ +.dd-check { + margin: 2px 5px 0 15px !important; + float: left; +} + +/* text in the drop down row */ +.dd-text { + float: left; +} + +.disabled { + background-color: #eee; +} + +.active { + cursor: pointer; +} + + +/*------------------------------------------------------------------ +@group Buttons +------------------------------------------------------------------*/ + +.kd-button { + min-width: 54px; + border:1px solid #DCDCDC; + border: 1px solid rgba(0,0,0,0.1); + text-align: center; + color: #444; + font-size: 13px; + height: 27px; + padding: 0 8px; + line-height: 27px; + -webkit-border-radius:2px; + -moz-border-radius: 2px; + border-radius: 2px; + -webkit-transition: all 0.218s; + -moz-transition: all 0.218s; + -o-transition: all 0.218s; + transition: all 0.218s; + background-color: #f5f5f5; + background-image: -webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#f1f1f1)); + background-image: -webkit-linear-gradient(top,#f5f5f5,#f1f1f1); + background-image: -moz-linear-gradient(top,#f5f5f5,#f1f1f1); + background-image: -ms-linear-gradient(top,#f5f5f5,#f1f1f1); + background-image: -o-linear-gradient(top,#f5f5f5,#f1f1f1); + background-image: linear-gradient(top,#f5f5f5,#f1f1f1); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f5f5f5',EndColorStr='#f1f1f1'); + -webkit-user-select:none; + -moz-user-select:none; +} + +.kd-button { + position:relative; + display:inline-block; +} + +.kd-button:hover, .kd-button.hover { + border: 1px solid #C6C6C6; + color: #222; + -webkit-transition: all 0.0s; + -moz-transition: all 0.0s; + -o-transition: all 0.0s; + transition: all 0.0s; + background-color: #f8f8f8; + background-image: -webkit-gradient(linear,left top,left bottom,from(#f8f8f8),to(#f1f1f1)); + background-image: -webkit-linear-gradient(top,#f8f8f8,#f1f1f1); + background-image: -moz-linear-gradient(top,#f8f8f8,#f1f1f1); + background-image: -ms-linear-gradient(top,#f8f8f8,#f1f1f1); + background-image: -o-linear-gradient(top,#f8f8f8,#f1f1f1); + background-image: linear-gradient(top,#f8f8f8,#f1f1f1); + -webkit-box-shadow: 0px 1px 1px rgba(0,0,0,0.1); + -moz-box-shadow: 0px 1px 1px rgba(0,0,0,0.1); + box-shadow: 0px 1px 1px rgba(0,0,0,0.1); +} +.kd-button:active, .kd-button.active { + background-color: #f6f6f6; + background-image: -webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#f1f1f1)); + background-image: -webkit-linear-gradient(top,#f6f6f6,#f1f1f1); + background-image: -moz-linear-gradient(top,#f6f6f6,#f1f1f1); + background-image: -ms-linear-gradient(top,#f6f6f6,#f1f1f1); + background-image: -o-linear-gradient(top,#f6f6f6,#f1f1f1); + background-image: linear-gradient(top,#f6f6f6,#f1f1f1); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f6f6f6',EndColorStr='#f1f1f1'); + -webkit-box-shadow: inset 0px 1px 2px rgba(0,0,0,0.1); + -moz-box-shadow: inset 0px 1px 2px rgba(0,0,0,0.1); + box-shadow: inset 0px 1px 2px rgba(0,0,0,0.1); +} +.kd-button.active{ + border: 1px solid #C6C6C6; + color: #333; +} +.kd-button img { + display: inline-block; + opacity: 0.667; + *margin:4px 0 0; /*IE7*/ + margin-top: 3px; +} +.kd-button.selected img { + opacity: 0.9; +} +.kd-button:hover img { + opacity: 0.9; +} +.kd-button:active img { + opacity: 1.0; +} + +.kd-tooltip { + white-space:nowrap; + visibility: hidden; + position: absolute; + background: #2d2d2d; + color: #FFF; + text-align: center; + outline: 1px solid rgba(255,255,255,0.5); + opacity: 0; + height: 29px; + line-height: 29px; + padding: 0 10px; + font-size: 11px; + font-weight: bold; + z-index: 1002; + top: 31px; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + -webkit-box-shadow: 0px 1px 4px rgba(0,0,0,0.2); + -moz-box-shadow: 0px 1px 4px rgba(0,0,0,0.2); + box-shadow: 1px 2px 4px rgba(0,0,0,0.2); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: opacity 0.13s, visibility 0s linear 0.13s; + -moz-transition: opacity 0.13s, visibility 0s linear 0.13s; + -o-transition: opacity 0.13s, visibility 0s linear 0.13s; + transition: opacity 0.13s, visibility 0s linear 0.13s; +} +.kd-tooltip.visible { + opacity: 1; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + color: green; + visibility:visible; +} +.kd-button:hover .kd-tooltip { + -webkit-transition: opacity 0.13s linear 0.5s, visibility 0s linear 0s; + -moz-transition: opacity 0.13s linear 0.5s, visibility 0s linear 0s; + -o-transition: opacity 0.13s linear 0.5s, visibility 0s linear 0s; + transition: opacity 0.13s linear 0.5s, visibility 0s linear 0s; + opacity: 1; + visibility: visible; +} +.kd-tooltip .pointer { + outline: none; + display: block; + position: absolute; + top: -5px; + left: 24px; + margin: 0 0 0 -5px; + width: 0; + height: 0; + line-height: 0px; + font-size: 0px; + /* This sets the tooptip pointer color */ + border-top: transparent; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #2d2d2d; +} +/*------------------------------------------------------------------ +@group bubble +------------------------------------------------------------------*/ +.kd-bubble { + display:block; + z-index:5; + position: relative; + background: #FFF; + border: 1px solid rgb(200,200,200); + border: 1px solid rgba(0,0,0,0.2); + -webkit-box-shadow: 0px 2px 4px rgba(0,0,0,0.2); + -moz-box-shadow: 0px 2px 4px rgba(0,0,0,0.2); + box-shadow: 0 2px 4px rgba(0,0,0,0.2); + padding: 16px; + width: 146px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + opacity: 1.0; + overflow: visible; + visibility: visible; + -webkit-transition: opacity 0.13s, visibility 0s linear 0s; + -moz-transition: opacity 0.13s, visibility 0s linear 0s; + -o-transition: opacity 0.13s, visibility 0s linear 0s; + transition: opacity 0.13s, visibility 0s linear 0s; +} + +.kd-bubble.hidden { + z-index: 0; + opacity: 0; + visibility: hidden; + -webkit-transition: opacity 0.13s, visibility 0s linear 0.13s; + -moz-transition: opacity 0.13s, visibility 0s linear 0.13s; + -o-transition: opacity 0.13s, visibility 0s linear 0.13s; + transition: opacity 0.13s, visibility 0s linear 0.13s; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; +} + +.kd-bubble .pointer { + z-index: 6; + outline: none; + display: block; + position: absolute; + top: -11px; + right: 24px; + width: 17px; + height: 11px; + background: url('/public/images/explorer/bubble_point_white.png'); +} + +.kd-bubble .pointer.left { + left: -27px; + top: 382px; + margin-bottom: -17px; + position: relative; + width: 11px; + height: 17px; + background: url('../images/left_bubble_point_white.png'); +} + +.kd-bubble p { + margin-bottom: 0; + color: #222; +} + +.kd-bubble p.links { + margin-top: 10px; +} +.kd-bubble p.links a:hover{ + text-decoration:underline; +} + +.kd-bubble.alert{ + background: #F9EDBE; + outline: 1px solid #f0c36d; +} +.kd-bubble.alert .pointer{ + background: url('../images/bubble_point_yellow.png'); +} + +.kd-profilebox{ + width:336px; +} +.kd-profilebox .kd-disclaimer{ + background:#F9EDBE; + padding:16px; + margin:-16px -16px 0 -16px; + border-bottom:1px solid #ddd8c0; +} +.kd-bubble.kd-profilebox .pointer{ + background: url('../images/bubble_point_yellow_grey.png'); +} +.kd-bubble .bottomlinks{ + margin:0 -16px; + padding:16px 16px 0; + border-top:1px solid #CCC; +} +.kd-bubble .bottomlinks a{ + float:right; +} +.kd-bubble .bottomlinks a:first-child{ + float:left; +} +#stickers .kd-bubble{ + margin-right:44px; + float:left; +} +/*------------------------------------------------------------------ +@group Checkbox and radio buttons +------------------------------------------------------------------*/ +input[type=checkbox], input[type=radio], .fakecheckbox, .fakeradio{ + -webkit-appearance: none; + width: 13px; + height: 13px; + border: 1px solid #CCC; + -webkit-border-radius:1px; + -moz-border-radius:1px; + border-radius:1px; + cursor:pointer; + position:relative; + background:#fff; + margin: 0; +} +input[type=checkbox]:active, input[type=radio]:active, .fakecheckbox:active, .fakeradio:active{ + border-color:#999; + background:#fff; +} +input[type=checkbox]:hover, input[type=radio]:hover, .fakecheckbox:hover, .fakeradio:hover{ + border-color:#999; + -webkit-box-shadow: inset 0px 1px 1px rgba(0,0,0,0.1); + -moz-box-shadow: inset 0px 1px 1px rgba(0,0,0,0.1); + box-shadow: inset 0px 1px 1px rgba(0,0,0,0.1); + background:#fff; +} + +input[type=checkbox]:checked::after, .fakecheckbox.checked::after { + content:url('/public/images/explorer/check_no_box.png'); + display:block; + position:absolute; + top:-6px; + left:-5px; +} + +input[type=checkbox]:focus, .fakecheckbox.focus { + outline: none; + border-color:#4d90fe; +} +.fakecheckbox, .fakeradio{ + display:inline-block; +} +form label input[type=checkbox]{ + margin-right:5px; +} + +/** Date Picker **/ +.ui-widget { font-size:73% !important;} diff --git a/assets/css/vendor/highlight.css b/assets/css/vendor/highlight.css new file mode 100644 index 000000000..85030ee7c --- /dev/null +++ b/assets/css/vendor/highlight.css @@ -0,0 +1,31 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import "highlight.js/styles/github"; + +/* Override the github styles. */ +.hljs { + background: #fff; + border: 1px solid var(--border-color); + border-radius: 4px; + font-family: Menlo, monospace; + font-size: .9em; + max-width: 52em; + overflow: auto; + padding: var(--gap); +} + diff --git a/assets/css/vendor/table-chart.css b/assets/css/vendor/table-chart.css new file mode 100644 index 000000000..e58d9e639 --- /dev/null +++ b/assets/css/vendor/table-chart.css @@ -0,0 +1,31 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +@import '../base/variables'; + +/** + * Styles for gapi analytics table. + */ + +.google-visualization-table-table { + margin-bottom: var(--gap)!important; +} + +.gapi-analytics-data-chart-table-styles-thr, +.gapi-analytics-data-chart-table-styles-tr { + font: inherit !important; +} diff --git a/assets/images/dimensions-metrics-explorer/screenshot.png b/assets/images/dimensions-metrics-explorer/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..af2c4ce674089c5e4efdb80417430c9b203bf163 GIT binary patch literal 41551 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 C1U;Pq literal 0 HcmV?d00001 diff --git a/assets/images/enhanced-ecommerce/screenshot.png b/assets/images/enhanced-ecommerce/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..edcd6ed0989ac72ebc74738dd9581e37ccad9069 GIT binary patch literal 85462 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ðH77Gg1|$lRy2!W0d?zaP!YCc#CBh%pPh%Vc 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 mjeOD&_3z1Y%uMnB3oroEz{hCq{{B1w0000{( zJaZG%Q-e|yQz{EjrrH1%i3a$DxHdO8XJuuzwY6Qja^=gHFKKCM|NsB*NcE5fDqt@O z@(TuXfq+5Eo7oL0Wa#PQ7*cU7Dd8}e1e?!{iK1*00U^eVI+S=4UBp~DjE$8#m7-5} j2)Gt<3Olkhu}CnS;9!gE$c(ZFYG&|s^>bP0l+XkKloUM? literal 0 HcmV?d00001 diff --git a/assets/images/explorer/big_roller.gif b/assets/images/explorer/big_roller.gif new file mode 100644 index 0000000000000000000000000000000000000000..d11019098dffc5e155832971fa95b2b9a29623ef GIT binary patch literal 4176 zcmb`KYgkjqy2n>mRo>mfDITeu+;_xMBA-cQE_`|Kt#k_ptM@sT2yS&qZV7*YTI2;x}WoP_k20?VLr^f z|99S*-}BDQyChGWzOYOLh=88};Khprb9M2@HPw?YAdSo@{S#@9OFbNPhb1ryDnJeDTE>&!0aJ z*zDiG|M20%0pZi9Prv)_yGxfY_4W1j_Vyk+bSPkR@#4jO`}Xzp^nCf{m#0sk4rs4k zyVl*^y?5{4ufF;!;BaPUrlX@{&z?O2$Ae#xtAJ)4`GJ9zM5!1CO=b3gw0Nx*<4vx zTUjA`bA4@Keh$&-0jtD6V)z3h0KYH+7OTx(SMPAT8XB9L z;5sB8+))<~Euh3(!HD_LE}Jj`O+|wUH?mMk>#*RF^RWKdNF0WlnYbMnu$&-G)ISnV za|5Sr@der<#KGc;M~?F*>Y;E6o$5eBqHbW~I8Qx(ecS;EEgzO1pXi>=M9fa1&YbvTMObDm`a)k7zv7GGO$zl{w z)kK-ejb*H?ZDnFO=`Ck#+CQx()d<91oOVG{ZXPM#5@Y0(Q)1-xVe+(!oJo=fT_@H` zb4*0|a!gXC>9F)#ELZxK&j67ZX^Dy3T&^Qo^JwvE#@0#i{)>&Ie>VE0kZDs57?

?j z=5!y-Bex+c@mLJ5S&gFeA>>PaXZmQ2Z!CS~yv;_HJBng?9oR^T-{rKlEW?Zn(^TQ@ zhB!1znrrG<7mZTt*ff>*v&B1YiuB}<06V2r!4UAV4yZRMPBfwd20@aG^;hFO0^E6w zsZ~i$lqu4V?xl;iJEE-WOaN}5^Z3eh7##=LwaNJ$6De-Ro(;FJIC;RB7(%BfW2Q_1 z%6j-@%ViRc`?mwa^y#-M2VK$nj}W0}2y}8Jkt=lWq9Km7NFeB&*spGi#rOBMn_}J= zK4Dza>h@LU$D-+Kh54w6I7p`0ka+(IYYS3vZo>#iGlri9GINuUM$vHjm4#hcMkJZ9=B39m!3KU2y_BAb%hn8Z>!G;P zsMv6N(ksq>hD4Hq(w1_r$(Mz2Bm;7~!AT9u7>Hd+BrNGlY&^diqRN9p zQA3~6HdrsmcMrdDqT@oJ3Mr~_ip?}6&cT!p15+f=TLUG)(@jTp6r8bLJ({f4hj7!T z-P==?3703 zGeho*69o0Rp-R+EG%P;>WGXk68+8=yL4N$e<=s@*S}VI`YU01F_P+NMYO3;kL1wfz zadLRk10|is%-AGcdMlVpUR}V-Py&~*$QEh0XiAdW!PGDC0mv!8H6qocYlX_l@xi+C zdHEfH))uwXQf=1Xz4sN&tz%*}8aj8}B}{j={AE6XMt8=Dm6LIK`G^#HuxNB}AbR2L z4`K}_!Wo@DbMk!=b&Xf}7MW)uw%R1Qt3`i85(Z&=;GVQlq2)`t&Zb>E1*MOc+03Ar zD4tq#9LaIZSJfn5s;TtFDFjsXcr9SD2<3$Uarbp#hfKSgFQR)vTF5VHYXFgv?syM9 zo`Ol-%OX+AY@&@nV@)L0vn~PYO7aC;G~MD3!p!z;K_1jSH4ebd2b+Y`RqN?gtJuo! zQp`Gg>jjMM)sD@Ti7#v6)9Gz0;QVVkIDg(Dov3l6)}h=|@{!UUS3tO9e3>&oTz(+2 ztJ-5U({J>>qxO@g#|laD)xn@vZR+OAauHhml!nX@Qz)?AJ7ir(HAFc5_kVs&uu61f z?TZyE5}f2%C93&dR$}}!l7GB-0H073ELXFgm8s{@Gx;qoFh#4t6nYJ8?fyH$Isj*f zV@H&kAb{Bl9bGM&*gKgnS3#-^2 zCf`9=omleu$zxVd`H{kkT$1rUFj*u=Jy6HRv*p^1T6>?;!ob&zzKLzxazxEduw=#@ z95lN8d&!-RZ%L?ma+2WfGYXw&r6pmF%9LB|og$GkI06M5QZb~9S3_-|wz5HRVW(GT z93-wy*eyoRQ~C%f-oz5j%nlX23h~kur{Y||`W!)aqEdC-O_Eu^Gxu#i!#2x;xxHDQ z^1QiKsXc}`!=0g~LK}33dhPy)%;+vG>)Gz#DLR7KH`k|EiHc$ z+SSJ~rgxaF#bz=^H>+O{_JUv3MQr6Gf0Cwuz_q}vS6uJb^OID|xuClhUaQSgE+n_Q zS-MzEQmTfn@F6$+o|VN*>Cr-mU~ZBc|A&LRb`{YFYF-tgJRE?bd zE5cmPJ`2R>_G95HzJnhWj4`q&?Ob{w?dPq&T#v{&S@e_GiYlFp5>g2sDVh0R$pMk# zv`L=|_^gABC`t!5467R(emH1tisp!s&G&~HWE<1iYZ6HS61%hJK{FbAjIMfh z0Vi~WZ|Bw?osw-cBJ|KmWmAl)bKhBE9F?PElU(O?L}y7QXn{|HYrA$7iXjJ+A9X3a zR?5BpDVfFVRDZ7T>bXjQ)MxzhP6i3Ybv>EvnDZ8)Xrtn7!$}>T5&kF-X|6b|6hgm& zz;fdaQxc`q=T8(5xyN3rSB&cFLhX_0fJx`}=B@aQ(e8V-v4UPl#ucyaGfodR;q7H= zv3Ex4s!RXdYrC5}G`pfRV$}ogC=Vb^Eh#XWFATZ`^p?Ws^gQKGq_E__TZv<;disMd zt__n{@yLjb{bLBgT2N-ANqm5XzE8%#%m`I?3{wQsmAU^{>IN=h5EsP5jXN!rP&yCy zG$Oq4Fe$s`@6NqZ62^l40H4ccHS){)tWcg-*KWai#q^?h7j@O@OuiN2Qt-gZtwj}b zt@^41(k`JBE>^S{!%{O5Cpm$WOLkpH<*|Cr2X!Dbg80lyEs9w-(f~tO3g%2h!0Ik6 z;Zd5&Vm1S!qC=vXd{3lsWmXM9+~|ReOg?uX$z>+UTh;5MlJ#~}KD5iBs?@oH7a{%X ziYYjqCiiTsSkV!2ket*x$2NCfNX{X>8MYm`vxF(kq0qcj>xOYKE`-K5i8K_O_2I!1 zUuBMGUfDRSTiW7XcbT5M-Gdw$M4H~VB{V9Et;7x{o8?z>4sUWq;7rrgVlDtOIojPf zjp7n9w0y&GRU$#=!3zxhL2ei5c^|8lJ^;2LJ_qf!|HsYjSpyi0eDoSE3SYGW~5k*j2M8wYvelU^UYN*3dIXH|{gtam|w_G$Xx zk_3QXfty+Y7L+Y$-q}Dblj`vH2DMZiNw%@5tfqI{0%Vs3km9l+nb!phvdM?Rcy7N1 z%t2#O8sehzN@c?iq-YHm9`b>cwRDmCiW8>LIWf>-2Oq!XLUu!s>@bLc@XYC-9x$_4 zuH}L%!FB~y0EwhqxA{&6Y7>-1LPS`l9imCp)BaCK_u3<}mEC>*d!3gMH9v}O(F`}s zBG~A&siA3&Ji-u`p{N+tBriq{RmPznh`lr_Eyk!`LSw6hnFCmdEssyp(OV?a6)3V9tGyIW@IyugUGLWdt64ft4}A^utCF0+U%Vl?t;Q@ z+KN%#T-45>Xv-S6DSr z1<%~X^wgl##FWaylc_d9Me96W978H@CE1j|5@A+7aOKLB#!ik>vlbBnqa}0O+n*au z&{MrWq0G>5BbTbGDx1RH*7FKtGLK>%dY2j*8S$JsbB0GqNGM@r`1-iU7kNoMjM56) z+NTd3VJXzGwziIIp1~o>z--XGAa3=6R1QDp3A~f0Okt6{(w8G}#(J+qr&0~u0S0Ml z=^F|G2b}j_JLuHKc!S5P_Lm9s;bwOJfB*mf{%&vi;Q9Ia{~doZGVw5k%}n2ApqBF) P=yC>6S3j3^P6HG_Gf4KKP_deg} z+|Tpe^E`}^35c~ z$;5B3Bz+uu^>Rv5bkgO-f8FR$I)*^Jl^yv-Y>+@8;BvWqK3^u235CMGzP{ex-k;hH z51NL>VsQa|jHHk)lQ816Ny@@dM~uV3qQI)y@!OM%pC^}@o!U9ud< zo8jx7EVcdT{@KOF#TUSQ)1U>*nQT|sI9kV3mMMocI5#&pIXPL}HFk$61&pgUn@u>j zVzpX9;~TwR&tx)}mX>Z4B!r$J61X6qSQ{A`Q7V;MtyU_Pf*?3HHU>dZW#4Qy-(12l z)(NdR!NQa7iLS1$XPg<8N;Nz@T-GyH)H!A{nMlBVM@NT9B;xUSfbmUFPtWrK+jG%k zU8l66dk8OHo}ZuBXfzF=9nwuqO--52=JD}yl4#aqvGDaPot>Q}ZR)2qKF_e`bUMkP zrM&S~TU#4J>Lg2SMXf{lPJqBx5Lhyzz%)HQO^`Usy0jb)r<^%b(*{0%2{izVr7!yM z1J(+b;Wj}$ZMI6sm#{4&9M@FWH&H_7KIct7APeVh%dZqhn_~snA))h!s=IZgqoY5w zWIX-K?Ck81jWW=9J%r$w z!UmYua!As_!9lrPj%N+#lEl#1LM~x|z?6#B<6OlQfj62*kyWur+f=KTMSI_fb6{X# zeSQ5>fKm?sS13I?A_g}9?*_sX(4`>|F0#t(FD6$wTT?_NG+x(h94l-Ac7ySE$Z#4y2`p6cljY zcjK0L35|K5tQO6mTlQg5J6(Sgv}_wG!(t7O-u52O^zZcu{Vj%I~3W-l_9-?sa2K%kXG zue=3@WV#j>tX&K$q>}UfeZ4;D_-9y#E3?>u-J9jz6#I@Yg!b>#=&Ir}L!x_C@yoiS z6}kJj-Wz6=&L>g6atwyt+;i+mw7V|yF{Tzt3`R$~$JQf>8_7}bu`bYOX!2c5tvZ{n z-nNsOX~G=#J$H5D?_XB4GQW0TExJB&mCdr*o%HL0I>)kf(;sO$`z)d|2JYgPgmF{m z{^QA>-xr&49a#ZY#enh}c2i2C6}6BLvx-<)s-1qt_Ym0MDFGiPjKj~)*}@1g*5S$(SReC4}f9X1NU;^XsFACQt` zN-_3J&UeYG);RiAam`7xN>1GOG%U8|n>wG;{%8RIRs4Hz!&b2mP8vvK1_Slkf;yPkr9 z4;|bJr6G4dgcXl0esDN1<97ITkB|#HVDj(N;9UJ-*Y|yi)lr|Pv;Padm*=0LLA5yx c5iW>#qGNi)-!H9!`xhcKC?b${>Qe510D{uf+5i9m literal 0 HcmV?d00001 diff --git a/assets/images/explorer/check_no_box.png b/assets/images/explorer/check_no_box.png new file mode 100644 index 0000000000000000000000000000000000000000..d049b55ac84628f9b0fdaf59eb29b25737fd4b0f GIT binary patch literal 328 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 b%}IXr?aevE3Kl)xePuz`3|-J%J|zDK6W!u* literal 0 HcmV?d00001 diff --git a/assets/images/explorer/had.png b/assets/images/explorer/had.png new file mode 100644 index 0000000000000000000000000000000000000000..23d692af53242e844a333f9abe54fcd114bc50d7 GIT binary patch literal 111523 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 literal 0 HcmV?d00001 diff --git a/assets/images/explorer/link.png b/assets/images/explorer/link.png new file mode 100644 index 0000000000000000000000000000000000000000..deb5a6e3c700a6382141353c2169d7bedaa1dbed GIT binary patch literal 431 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1|(OCFP#RY6p}rHd>I(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!t5-O<;Pfnj4`&F{d;Kt5w}kh>GZx^prwfgH9Z zZ+91l{~)+v?{bhdXMsm#F#`kN5fEmas?8@2)WYWJ;uunKD>*@eb#cS02Eop^yhm6a za+r=VIs9Sj2xlnN6{v4qHId;_ngSm~lAyvrh9m9`J48GD5AYn!w=Dr zkMauF7?KPX?(v42OLx3&_#qy0mS4e)`4P*CS?VYB_VSo2Fm+s4+UdpI&cB}FqqK&# ze1|&2M=^zOtehJhR7)CuFidJx*dW`%TOh&pDO6#Kt)Ntnm4WAsh2;wpGnsjn*;cI8 zs)#w&AW~u!;J(l$#7w}y(d~q!3A00&^ujkUBbtt|y|R#3xYs2UxO`zE%cmwm0d0rF zU%0L~M7+7rn#7-xqUm@wmidv6!o3b%&xuS9Cp+0^G1>JzI}_Ld3=jpQz$K+U<-lNK N@O1TaS?83{1ORLI@#*5F|vr7dO)AClk-d^W}Gbzw`e` zU6u%gq>jK5>;Z6ebOZo6I5;RTFIOlOTU%SBqoWH83wphtxYug6BO@aMfgmX)V4 zv9VF7)9vi+KnPu2Tsk{D8yXs_tE+c+clY=Ao12>_Cnv>XF_lWq&dy$1T3TOU@9XRH z^70A{43tPDb8~aU!^0sVA#rhWB9SOMI(lkqYHVyQJw3gvt7~Ipqp+~Bt*x!QySuly zH!CYEBO@axCr2)qFE1~bl$0DE9@f{_GZ+jXAD`6JR0@TXkdQDjF(DKR)6&vdEY|k+ z_Wb;OO-;?p%F5c>T4-pf(P%_bl+9+hx3?D+6~)BF`1|`86co(N%nS?+xVyU-7Z-bgZtf#>U3(?d_RNro6no{QUgI#YKa`;N;}w=H^B;`F{`RPgX?H z4e9M0x$Mtw-p*%B3#6Zaa!Z=)d-K!0TY&Qi1=tcm&XIjwWJ+>GSVE-0mv4EBxbh+2 zL4G2z$^QaCjP2&m#gxF_i3KQ=T29u`x?Z@Zv_hIh%?C2}L zg*pFNp3uM)N??f~&VcLWrKCZMh8`M*xJP0%Cga#iDAGt2^~&?%5&lssLSEd}MJ6jl zdjLn{@obQ)@f^g6NDsz)zERCW!wbk@Rwxz$Ixs)Z?Vmo8w={=;M9Rx>IplInF&c)V zKx`kEBqNx(!(}89ufn5a;*-_5E8nUSCnEuFnVPKh-IG$DN!SXBEXGzzfqA4iZ%qW$M49 zG?r3Y=!WAG24a@*TFg5&Ewv9ms30r6FKUs z;KM2)&A94!#%&(SbLbbeF;ZrRsX2NL#i{}_O+&j~V6YKG + + \ No newline at end of file diff --git a/assets/images/google-analytics-partners.png b/assets/images/google-analytics-partners.png new file mode 100644 index 0000000000000000000000000000000000000000..fef0571eeeeee3c0c3a30e5a65b99bf7083fd205 GIT binary patch literal 77538 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 Zws?4ddqrPqz)Pn$G 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 Bj3fX6 literal 0 HcmV?d00001 diff --git a/assets/images/icons.svg b/assets/images/icons.svg new file mode 100644 index 000000000..124fef996 --- /dev/null +++ b/assets/images/icons.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/polymer-elements/screenshot.png b/assets/images/polymer-elements/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..51608e742717bfdbee3cc3b8afe939a6492132c0 GIT binary patch literal 99541 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 z

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 literal 0 HcmV?d00001 diff --git a/assets/javascript/account-explorer/index.js b/assets/javascript/account-explorer/index.js new file mode 100644 index 000000000..c9a5c4cac --- /dev/null +++ b/assets/javascript/account-explorer/index.js @@ -0,0 +1,268 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global gapi */ +var $ = require('jquery'); +var accountSummaries = require('javascript-api-utils/lib/account-summaries'); + + +function setup() { + $('#search-box').on('input', handleSearch); + $('#search-box').trigger('focus'); + + accountSummaries.get().then(function(summaries) { + var urlHash = getMapFromHash(); + var validIds = returnValidIds(summaries, urlHash); + var allIds = getAllIds(summaries, validIds); + + setViewSelector(summaries, allIds.viewId); + }); +} + + +/** + * Handler for search box. Searches the user input for account, property, and + * view names and ids. Not case sensitive. Displays the results in the DOM. + */ +function handleSearch() { + + var searchTerm = $('#search-box').val().toLowerCase(); + + accountSummaries.get().then(function(summaries) { + var results = []; + if (searchTerm) { + for (var i = 0; i < summaries.all().length; i++) { + var account = summaries.all()[i]; + if (!account.webProperties) { + continue; + } + for (var j = 0; j < account.webProperties.length; j++) { + var property = account.webProperties[j]; + if (!property.profiles) { + continue; + } + for (var k = 0; k < property.profiles.length; k++) { + var view = property.profiles[k]; + var tableId = 'ga:' + view.id; + var match = tableId.indexOf(searchTerm) > -1 || + view.id.indexOf(searchTerm) > -1 || + view.name.toLowerCase().indexOf(searchTerm) > -1 || + property.id.toLowerCase().indexOf(searchTerm) > -1 || + property.name.toLowerCase().indexOf(searchTerm) > -1 || + account.id.indexOf(searchTerm) > -1 || + account.name.toLowerCase().indexOf(searchTerm) > -1; + if (match) { + results.push({account: account, property: property, view: view}); + } + } + } + } + } + updateResults(results, $('#search-box').val()); + }); +} + +/** + * Updates the DOM with a table of account, property, and view names and ids. + * @param {Array} results The results to be added to the DOM. + * @param {string} opt_query The user inputed search text. + */ +function updateResults(results, opt_query) { + $('#results-container').html('' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
AccountPropertyViewTable ID
'); + + function mark(text) { + if (opt_query) { + var regex = new RegExp('(' + opt_query + ')', 'ig'); + return text.replace(regex, '$1'); + } + else { + return text; + } + } + + var searchResults = $('#results-body'); + if (results.length === 0) { + searchResults.append('No results found'); + } + else { + for (var i = 0; i < results.length; i++) { + searchResults.append('' + + mark(results[i].account.name) + '

' + + mark(results[i].property.name) + '
' + + mark(results[i].property.id) + '
' + + mark(results[i].view.name) + '
' + + mark(results[i].view.id) + '
' + + mark('ga:' + results[i].view.id) + '
'); + } + } + + if (typeof opt_query == 'string') { + $('#results-title').text('Showing results for "' + opt_query + '"'); + } +} + +/** + * Creates and sets the viewSelector + * @param {Object} summaries The account summaries response. + * @param {String} viewId The view ID to set the viewSelector to + */ +function setViewSelector(summaries, viewId) { + var viewSelector = new gapi.analytics.ext.ViewSelector2({ + container: 'view-selector-container' + }).execute(); + viewSelector.set({viewId: viewId}); + + function getIdsAndUpdateResults() { + // Use a try/catch block in case we have sparse properties or accounts. + try { + var allIds = { + viewId: viewSelector.view.id, + propertyId: viewSelector.property.id, + accountId: viewSelector.account.id + }; + var allObjects = { + view: viewSelector.view, + property: viewSelector.property, + account: viewSelector.account + }; + updateResults([allObjects]); + $('#search-box').val(''); + $('#results-title').text('Showing view selected above'); + } + catch (e) {} + } + + viewSelector.on('change', getIdsAndUpdateResults); + $('#view-selector-container').on('focusout', getIdsAndUpdateResults); +} + + +/** + * Given a potentially invalid view and/or property and/or account ID(s), + * returns an object with only the valid view, property, and account IDs + * (among those given). + * @param {Object} summaries The account summaries response. + * @param {Object} ids An object with one or more of the following: viewId, + * property ID, account ID. + * @return {Object} An object with only the valid view, property, and account + * IDs (among those given). + */ +function returnValidIds(summaries, ids) { + if (ids.viewId) { + var view = summaries.getProfile(ids.viewId); + ids.viewId = view ? view.id : null; + } + if (ids.propertyId) { + var property = summaries.getProperty(ids.propertyId); + ids.propertyId = property ? property.id : null; + } + if (ids.accountId) { + var account = summaries.getAccount(ids.accountId); + ids.accountId = account ? account.id : null; + } + return ids; +} + + +/** + * Given a valid view and/or property and/or account ID(s), returns an + * object with the associated view, property, and account IDs. If no view is + * given, it will return the first view in the property. Similarly, if no + * property is given, it will return the first property in the account and the + * first view in the property. + * @param {Object} summaries The account summaries response. + * @param {Object} ids An object with the viewId, the property ID, and the + * account ID. + * @param {Boolean} returnObject If true, will return the view, property, and + * account object. If false, will return the IDs. + * @return {Object} All the associated view, property, and account IDs. If + * returnObject is true, will return the account objects, not the IDs. + */ +function getAllIds(summaries, ids, returnObject) { + var accountObject = {}; + if (ids.viewId) { + accountObject.view = summaries.getView(ids.viewId); + accountObject.property = summaries.getPropertyByViewId(ids.viewId); + accountObject.account = summaries.getAccountByViewId(ids.viewId); + } + else if (ids.propertyId) { + accountObject.property = summaries.getProperty(ids.propertyId); + accountObject.account = + summaries.getAccountByWebPropertyId(ids.propertyId); + // pick first profile + accountObject.view = accountObject.property.views[0]; + } + else if (ids.accountId) { + accountObject.account = summaries.getAccount(ids.accountId); + // pick first property and first profile + accountObject.property = accountObject.account.properties[0]; + accountObject.view = + summaries.getProperty(accountObject.property.id).views[0]; + } + else { + // pick first view property and account + accountObject.account = summaries.all()[0]; + accountObject.property = accountObject.account.properties[0]; + accountObject.view = accountObject.property.views[0]; + } + + return returnObject ? accountObject : {viewId: accountObject.view.id, + propertyId: accountObject.property.id, + accountId: accountObject.account.id}; +} + + +/** + * Gets the URL hash and returns it as an object with each parameter as the + * key and the parameter value as the value. + * E.g. getMapFromHash('#viewId=123&propertyId=UA-123-4') would return + * {viewId: '123', propertyId: 'UA-123-4'} + * @return {Object} An object containing the parameters and values in the hash + */ +function getMapFromHash() { + var urlHash = document.location.hash.substr(1); + var params = urlHash.split('&'); + var map = {}; + for (var i = 0, param; param = params[i]; i++) { + var fragment = param.split('='); + map[fragment[0]] = fragment[1]; + } + return map; +} + + +module.exports = { + init: function() { + gapi.analytics.ready(function() { + if (gapi.analytics.auth.isAuthorized()) { + setup(); + } + else { + gapi.analytics.auth.once('success', setup); + } + }); + } +}; diff --git a/assets/javascript/account-summaries.js b/assets/javascript/account-summaries.js new file mode 100644 index 000000000..96e6bd2bb --- /dev/null +++ b/assets/javascript/account-summaries.js @@ -0,0 +1,312 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* jshint boss: true, browser: true */ +/* global gapi, gaUtils, Promise, define, module, exports */ + +/** + * @module accountSummaries + * + * @requires Promise (or a Promise polyfill). + * @requires gapi.client.analytics (and the user to be authenticated). + */ +(function() { + + var promise; + + /** + * @constuctor AccountSummaries + */ + function AccountSummaries(summaries) { + this.summaries_ = summaries; + this.setup_(); + } + + /** + * `setup_` takes the multidimensional summaries_ array property and write + * the following new properties: `accountsById_`, `webPropertiesById_`, and + * `profilesById_`. Each of these contains an array of objects where the + * key is the entity ID and the value is an object containing the entity and + * the entity's parents. For example, an object in the `profilesById_` array + * might look like this: + * { + * "1234": { + * self: {...}, + * parent: {...}, + * grandParent: {...} + * } + * } + * + * It also aliases the properties `webProperties` to `properties` and + * `profiles` to `views`. + * + * @private + */ + AccountSummaries.prototype.setup_ = function() { + + this.accountsById_ = {}; + this.webPropertiesById_ = this.propertiesById_ = {}; + this.profilesById_ = this.viewsById_ = {}; + + for (var i = 0, account; account = this.summaries_[i]; i++) { + this.accountsById_[account.id] = { + self: account + }; + if (!account.webProperties) continue; + + // Add aliases. + account.properties = account.webProperties; + + for (var j = 0, webProperty; + webProperty = account.webProperties[j]; j++) { + this.webPropertiesById_[webProperty.id] = { + self: webProperty, + parent: account + }; + if (!webProperty.profiles) continue; + + // Add aliases. + webProperty.views = webProperty.profiles; + + for (var k = 0, profile; profile = webProperty.profiles[k]; k++) { + this.profilesById_[profile.id] = { + self: profile, + parent: webProperty, + grandParent: account + }; + } + } + } + }; + + /** + * Return the raw accountSummaries array as returned by the API. + * @return {Array} + */ + AccountSummaries.prototype.all = function() { + return this.summaries_; + }; + + + /** + * Returns an account, web property or profile given the passed ID in the + * `idData` object. The ID data object can contain only one of the + * following properties: "accountId", "webPropertyId", "propertyId", + * "profileId", or "viewId". If more than one key is passed, an error is + * thrown. + * + * @param {Object} obj An object with no more than one of the following + * keys: "accountId", "webPropertyId", "propertyId", "profileId" or + * "viewId". + * @return {Object|undefined} The matching account, web property, or + * profile. If none are found, undefined is returned. + */ + AccountSummaries.prototype.get = function(obj) { + if (!!obj.accountId + + !!obj.webPropertyId + + !!obj.propertyId + + !!obj.profileId + + !!obj.viewId > 1) { + + throw new Error('get() only accepts an object with a single ' + + 'property: either "accountId", "webPropertyId", "propertyId", ' + + '"profileId" or "viewId"'); + } + return this.getProfile(obj.profileIdi || obj.viewId) || + this.getWebProperty(obj.webPropertyId || obj.propertyId) || + this.getAccount(obj.accountId); + }; + + + /** + * Get an account given its ID. + * @param {string|number} accountId + * @return {Object} The account with the given ID. + */ + AccountSummaries.prototype.getAccount = function(accountId) { + return this.accountsById_[accountId] && + this.accountsById_[accountId].self; + }; + + + /** + * Get a web property given its ID. + * @param {string} webPropertyId + * @return {Object} The web property with the given ID. + */ + AccountSummaries.prototype.getWebProperty = function(webPropertyId) { + return this.webPropertiesById_[webPropertyId] && + this.webPropertiesById_[webPropertyId].self; + }; + + + /** + * Get a profile given its ID. + * @param {string|number} profileId + * @return {Object} The profile with the given ID. + */ + AccountSummaries.prototype.getProfile = function(profileId) { + return this.profilesById_[profileId] && + this.profilesById_[profileId].self; + }; + + + /** + * Get an account given the ID of one of its profiles. + * @param {string|number} profileId + * @return {Object} The account containing this profile. + */ + AccountSummaries.prototype.getAccountByProfileId = function(profileId) { + return this.profilesById_[profileId] && + this.profilesById_[profileId].grandParent; + }; + + + /** + * Get a web property given the ID of one of its profile. + * @param {string|number} profileId + * @return {Object} The web property containing this profile. + */ + AccountSummaries.prototype.getWebPropertyByProfileId = function(profileId) { + return this.profilesById_[profileId] && + this.profilesById_[profileId].parent; + }; + + + /** + * Get an account given the ID of one of its web properties. + * @param {string|number} webPropertyId + * @return {Object} The account containing this web property. + */ + AccountSummaries.prototype.getAccountByWebPropertyId = + function(webPropertyId) { + + return this.webPropertiesById_[webPropertyId] && + this.webPropertiesById_[webPropertyId].parent; + }; + + + /** + * Alias getWebProperty to getProperty. + */ + AccountSummaries.prototype.getProperty = + AccountSummaries.prototype.getWebProperty; + + + /** + * Alias getProfile to getView. + */ + AccountSummaries.prototype.getView = + AccountSummaries.prototype.getProfile; + + + /** + * Alias getWebPropertyByProfileId to getPropertyByViewId. + */ + AccountSummaries.prototype.getPropertyByViewId = + AccountSummaries.prototype.getWebPropertyByProfileId; + + + /** + * Alias getAccountByProfileId to getAccountByViewId. + */ + AccountSummaries.prototype.getAccountByViewId = + AccountSummaries.prototype.getAccountByProfileId; + + + /** + * Alias getWebPropertyByProfileId to getPropertyByViewId. + */ + AccountSummaries.prototype.getWebPropertyByProfileId = + AccountSummaries.prototype.getPropertyByViewId; + + + /** + * Make a request to the Management API's accountSummaries#list method. + * If the requests returns a partial, paginated response, query again + * until the full summaries are retrieved. + * @return {Promise} A promise that will be resolved once all requests + * are complete. + */ + function requestAccountSummaries() { + return new Promise(function(resolve) { + var summaries = []; + function makeRequest(startIndex) { + gapi.client.analytics.management.accountSummaries + .list({'start-index': startIndex || 1}) + .execute(ensureComplete); + } + function ensureComplete(resp) { + // Reject the promise if the API returns an error. + if (resp.error) throw new Error(resp.message); + + if (resp.items) { + summaries = summaries.concat(resp.items); + } + else { + throw new Error('You do not have any Google Analytics accounts. ' + + 'Go to http://google.com/analytics to sign up.'); + } + + if (resp.startIndex + resp.itemsPerPage <= resp.totalResults) { + makeRequest(resp.startIndex + resp.itemsPerPage); + } + else { + resolve(new AccountSummaries(summaries)); + } + } + makeRequest(); + }); + } + + var accountSummaries = { + + /** + * Expose the constructor in case anyone needs it. + */ + AccountSummaries: AccountSummaries, + + /** + * Return the `requestAccountSummaries` promise. If the promise exists, + * return it to avoid multiple requests. If the promise does not exist, + * initiate the request and cache the promise. + * + * @param {boolean} noCache When true make a request no matter what. + * @return {Promise} A promise fulfilled with the decorated summaries + * array. + */ + get: function(noCache) { + if (noCache) promise = null; + return promise || (promise = requestAccountSummaries()); + } + }; + + + // AMD Export. + if (typeof define === 'function' && define.amd) { + define([], accountSummaries); + } + // Node export. + else if (typeof exports === 'object') { + module.exports = accountSummaries; + } + // Browser global (default to `gaUtils.accountSummaries`). + else { + window.gaUtils = window.gaUtils || {}; + gaUtils.accountSummaries = accountSummaries; + } + +}(this)); + diff --git a/assets/javascript/analytics.js b/assets/javascript/analytics.js new file mode 100644 index 000000000..decad3de1 --- /dev/null +++ b/assets/javascript/analytics.js @@ -0,0 +1,65 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global ga */ + +var $ = require('jquery'); + + +function setupOutBoundLinkTracking() { + $(document).on('click', 'a', function() { + + if (location.hostname != this.hostname) { + // Opening links in an external tabs allows the ga beacon to send. + // When following links directly, sometimes they don't make it. + this.target = '_blank'; + var analyticsId = $(this).attr('data-analytics-id'); + var eventAction = analyticsId ? 'click:' + analyticsId : 'click'; + + ga('send', 'event', 'outbound link', eventAction, this.href); + } + }); +} + + +function setupUncaughtExceptionTracking() { + window.onerror = function(message, url, line, col) { + var desc = 'Uncaught error: ' + + message + ' (line: ' + line + ', url: ' + url + ', col: ' + col + ')'; + + ga('send', 'exception', { + exDescription: desc, + exFatal: false + }); + }; +} + + +function sendInitialPageview() { + ga('send', 'pageview'); +} + + +module.exports = { + track: function() { + ga('require', 'displayfeatures'); + ga('require', 'linkid', 'linkid.js'); + + setupOutBoundLinkTracking(); + setupUncaughtExceptionTracking(); + + ga('send', 'pageview'); + } +}; diff --git a/assets/javascript/embed-api/active-users.js b/assets/javascript/embed-api/active-users.js new file mode 100644 index 000000000..d687ce34b --- /dev/null +++ b/assets/javascript/embed-api/active-users.js @@ -0,0 +1,111 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global gapi */ + +gapi.analytics.ready(function() { + + gapi.analytics.createComponent('ActiveUsers', { + + initialize: function() { + this.activeUsers = 0; + }, + + execute: function() { + // Stop any polling currently going on. + if (this.polling_) { + this.stop(); + } + + this.render_(); + + // Wait until the user is authorized. + if (gapi.analytics.auth.isAuthorized()) { + this.getActiveUsers_(); + } + else { + gapi.analytics.auth.once('success', this.getActiveUsers_.bind(this)); + } + }, + + stop: function() { + clearTimeout(this.timeout_); + this.polling_ = false; + this.emit('stop', {activeUsers: this.activeUsers}); + }, + + render_: function() { + var opts = this.get(); + + // Render the component inside the container. + this.container = typeof opts.container == 'string' ? + document.getElementById(opts.container) : opts.container; + + this.container.innerHTML = opts.template || this.template; + this.container.querySelector('b').innerHTML = this.activeUsers; + }, + + getActiveUsers_: function() { + var options = this.get(); + var pollingInterval = (options.pollingInterval || 5) * 1000; + + if (isNaN(pollingInterval) || pollingInterval < 5000) { + throw new Error('Frequency must be 5 seconds or more.'); + } + + this.polling_ = true; + gapi.client.analytics.data.realtime + .get({ids:options.ids, metrics:'rt:activeUsers'}) + .execute(function(response) { + + var newValue = response.totalResults ? +response.rows[0][0] : 0; + var oldValue = this.activeUsers; + + this.emit('success', {activeUsers: this.activeUsers}); + + if (newValue != oldValue) { + this.activeUsers = newValue; + this.onChange_(newValue - oldValue); + } + + if (this.polling_ = true) { + this.timeout_ = setTimeout(this.getActiveUsers_.bind(this), + pollingInterval); + } + }.bind(this)); + }, + + onChange_: function(delta) { + var valueContainer = this.container.querySelector('b'); + if (valueContainer) valueContainer.innerHTML = this.activeUsers; + + this.emit('change', {activeUsers: this.activeUsers, delta: delta}); + if (delta > 0) { + this.emit('increase', {activeUsers: this.activeUsers, delta: delta}); + } + else { + this.emit('decrease', {activeUsers: this.activeUsers, delta: delta}); + } + }, + + template: + '
' + + 'Active Users: ' + + '
' + + }); + +}); + diff --git a/site/components/datepicker.js b/assets/javascript/embed-api/date-range-selector.js similarity index 72% rename from site/components/datepicker.js rename to assets/javascript/embed-api/date-range-selector.js index 0f2d58215..6ffb6dd29 100644 --- a/site/components/datepicker.js +++ b/assets/javascript/embed-api/date-range-selector.js @@ -1,3 +1,23 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global gapi */ + +/** + * A DateRangeSelector component for the Embed API. + */ gapi.analytics.ready(function() { var nDaysAgo = /(\d+)daysAgo/; @@ -11,15 +31,15 @@ gapi.analytics.ready(function() { */ function convertDate(str) { // If str is in the proper format, do nothing. - if (dateFormat.test(str)) return str + if (dateFormat.test(str)) return str; var match = nDaysAgo.exec(str); if (match) { - return daysAgo(+match[1]) + return daysAgo(+match[1]); } else if (str == 'today') { - return daysAgo(0) + return daysAgo(0); } else if (str == 'yesterday') { - return daysAgo(1) + return daysAgo(1); } else { throw new Error('Cannot convert date ' + str); } @@ -40,11 +60,11 @@ gapi.analytics.ready(function() { return date.getFullYear() + '-' + month + '-' + day; } - gapi.analytics.createComponent('Datepicker', { + gapi.analytics.createComponent('DateRangeSelector', { /** - * Initialize the Datepicker instance and render it to the page. - * @return {Datepicker} The instance. + * Initialize the DateRangeSelector instance and render it to the page. + * @return {DateRangeSelector} The instance. */ execute: function() { var options = this.get(); @@ -56,9 +76,9 @@ gapi.analytics.ready(function() { document.getElementById(options.container) : options.container; // Allow the template to be overridden. - if (options.template) this.template = options.template + if (options.template) this.template = options.template; - this.container.innerHTML = this.template + this.container.innerHTML = this.template; var dateInputs = this.container.querySelectorAll('input'); this.startDateInput = dateInputs[0]; @@ -77,7 +97,7 @@ gapi.analytics.ready(function() { * Emit a change event based on the currently selected dates. * Pass an object containing the start date and end date. */ - onChange: function(event) { + onChange: function() { this.setValues(); this.setMinMax(); this.emit('change', { @@ -109,12 +129,12 @@ gapi.analytics.ready(function() { * first will be the start date and the second will be the end date. */ template: - '
' + - '
' + + '
' + + '
' + ' ' + ' ' + '
' + - '
' + + '
' + ' ' + ' ' + '
' + @@ -122,3 +142,4 @@ gapi.analytics.ready(function() { }); }); + diff --git a/assets/javascript/embed-api/index.js b/assets/javascript/embed-api/index.js new file mode 100644 index 000000000..f45956a94 --- /dev/null +++ b/assets/javascript/embed-api/index.js @@ -0,0 +1,62 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global gapi */ + +var $ = require('jquery'); +var debounce = require('lodash').debounce; + +// +// IMPORTANT! +// +// The function below includes a few hacks so that the Embed API +// demos don't interfere with the Embed API code already on the page. +// In normal Embed API usage, these hacks aren't needed. +// +function monkeyPatchForDemos() { + + // `authorize` has already been called at this point, so we need to + // override the function so subsequent calls in the demo do nothing. + gapi.analytics.auth.authorize = function() { + // Overridden by client. + }; + + // Keep a reference to all created DataChart instances so they can be + // redrawn on resize. Do this here instead of in the demo code to + // avoid introducing unnecessary complexity. + var originalDataChart = gapi.analytics.googleCharts.DataChart; + var dataCharts = []; + + gapi.analytics.googleCharts.DataChart = function DataChart(options) { + var dataChart = new originalDataChart(options); + dataCharts.push(dataChart); + return dataChart; + }; + + $(window).on('resize', debounce(function() { + dataCharts.forEach(function(dataChart) { + // TODO(philipwalton): update the Embed API DataChart component + // to allow for a redraw method (or something like that). We shouldn't + // have to do an additional query just to redraw. + dataChart && dataChart.execute(); + }); + }, 200)); +} + +module.exports = { + init: function() { + gapi.analytics.ready(monkeyPatchForDemos); + } +}; diff --git a/assets/javascript/embed-api/view-selector2.js b/assets/javascript/embed-api/view-selector2.js new file mode 100644 index 000000000..a122a51b3 --- /dev/null +++ b/assets/javascript/embed-api/view-selector2.js @@ -0,0 +1,327 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global gapi */ + +var accountSummaries = require('javascript-api-utils/lib/account-summaries'); + +/** + * A ViewSelector2 component for the Embed API. + */ +gapi.analytics.ready(function() { + + gapi.analytics.createComponent('ViewSelector2', { + + /** + * Render the view selector instance on the page or update an existing + * instance if any options have changed. + * @return {ViewSelector2} The instance. + */ + execute: function() { + this.setup_(function() { + this.updateAccounts_(); + if (this.changed_) { + this.render_(); + this.onChange_(); + } + }.bind(this)); + + return this; + }, + + /** + * Extend the base `set` function with some error checking and handling of + * ID data. + * @extends gapi.analytics.Component.prototype.set + * @param {Object} opts The options to set. + * @return {ViewSelector2} + */ + set: function(opts) { + + if (!!opts.ids + + !!opts.viewId + + !!opts.propertyId + + !!opts.accountId > 1) { + + throw new Error('You cannot specify more than one of the following ' + + 'options: "ids", "viewId", "accountId", "propertyId"'); + } + + if (opts.container && this.container) { + throw new Error('You cannot change containers once a view selector ' + + 'has been rendered on the page.'); + } + + var prevOpts = this.get(); + + if (prevOpts.ids != opts.ids || + prevOpts.viewId != opts.viewId || + prevOpts.propertyId != opts.propertyId || + prevOpts.accountId != opts.accountId) { + + // If new ID data is being set, first unset all existing ID data. + // This prevents the problem where you set an account ID then set a + // view ID for a new view in a different account. Both IDs should not + // persist or there will be problems. + prevOpts.ids = null; + prevOpts.viewId = null; + prevOpts.propertyId = null; + prevOpts.accountId = null; + } + + // Call super. + return gapi.analytics.Component.prototype.set.call(this, opts); + }, + + /** + * Set up the view selector instance with values from the Management API's + * accountSummaries.list method via the `accountSummaries` module. + * If the user has not authorized, wait until that happens before + * requesting the account summaries. + * @param {Function} cb A function to be invoked once authorization has + * succeeded and the accountSummaries have been retrieved. + */ + setup_: function(cb) { + var self = this; + + function onAuthorize() { + accountSummaries.get().then( + function(summaries) { + self.summaries = summaries; + self.accounts = self.summaries.all(); + cb(); + }, + function(err) { + self.emit('error', err); + } + ); + } + + if (gapi.analytics.auth.isAuthorized()) { + onAuthorize(); + } + else { + gapi.analytics.auth.on('success', onAuthorize); + } + }, + + /** + * Update the view selector instance properties with new account + * information. + * @throws {Error} If the user has set an ID value for an account they + * don't have access to. + */ + updateAccounts_: function() { + + var opts = this.get(); + var ids = getIdProp(opts); + var view, account, property; + + // If there are no id props, set the defaults. + if (!ids) { + account = this.accounts[0]; + property = account && account.properties && account.properties[0]; + view = property && property.views && property.views[0]; + } + else { + switch (ids.prop) { + case 'viewId': + view = this.summaries.getProfile(ids.value); + account = this.summaries.getAccountByProfileId(ids.value); + property = this.summaries.getWebPropertyByProfileId(ids.value); + break; + case 'propertyId': + property = this.summaries.getWebProperty(ids.value); + account = this.summaries.getAccountByWebPropertyId(ids.value); + view = property && property.views && property.views[0]; + break; + case 'accountId': + account = this.summaries.getAccount(ids.value); + property = account && account.properties && account.properties[0]; + view = property && property.views && property.views[0]; + break; + } + } + + if (account || property || view) { + + // Only update if something has changed. + if (account != this.account || + property != this.property || + view != this.view) { + + // Store what value changed. + this.changed_ = { + account: account && account != this.account, + property: property && property != this.property, + view: view && view != this.view + }; + + this.account = account; + this.properties = account.properties; + this.property = property; + this.views = property && property.views; + this.view = view; + this.ids = view && 'ga:' + view.id; + } + } + else { + this.emit('error', new Error('You do not have access to ' + + ids.prop.slice(0, -2) + ' : ' + ids.value)); + } + }, + + /** + * Render the view selector based on the users accounts and the + * pre-defined template. Also add event handlers to watch for + * changes. + */ + render_: function() { + + var opts = this.get(); + + this.container = typeof opts.container == 'string' ? + document.getElementById(opts.container) : opts.container; + + this.container.innerHTML = opts.template || this.template; + var selects = this.container.querySelectorAll('select'); + + var accounts = this.accounts; + var properties = this.properties || [{name: '(Empty)', id: ''}]; + var views = this.views || [{name: '(Empty)', id: ''}]; + + updateSelect(selects[0], accounts, this.account.id); + updateSelect(selects[1], properties, this.property && this.property.id); + updateSelect(selects[2], views, this.view && this.view.id); + + selects[0].onchange = + this.onUserSelect_.bind(this, selects[0], 'accountId'); + selects[1].onchange = + this.onUserSelect_.bind(this, selects[1], 'propertyId'); + selects[2].onchange = + this.onUserSelect_.bind(this, selects[2], 'viewId'); + }, + + /** + * A callback that is invoked from the `execute` method whenever the ID + * data has changed. Most of the time this change happens when the user + * has selected a new view in the UI, but it can also happen + * programmatically via the `set` method. + */ + onChange_: function() { + + var props = { + account: this.account, + property: this.property, + view: this.view, + ids: this.view && 'ga:' + this.view.id + }; + + if (this.changed_) { + if (this.changed_.account) this.emit('accountChange', props); + if (this.changed_.property) this.emit('propertyChange', props); + if (this.changed_.view) { + this.emit('viewChange', props); + this.emit('idsChange', props); + + // For backwards compatibility with the original ViewSelector. + this.emit('change', props.ids); + } + } + + this.changed_ = null; + }, + + /** + * The handler assigned to the `onchange` method of each of the select + * elements. The context is bound to the view selector instance and it is + * invoked with the element and property as its arguments. + * @param {HTMLSelectElement} select The select element. + * @param {string} property The property key to be set on the instance. + */ + onUserSelect_: function(select, property) { + var data = {}; + data[property] = select.value; + + this.set(data); + this.execute(); + }, + + /** + * The html structure used to build the component. Developers can override + * this by passing it to the component constructor. The only requirement + * is that the structure contain three selects. The first will be the + * account select, the second will be the property select, and the third + * will be the view select. Order is important. + */ + template: + '
' + + '
' + + ' ' + + ' ' + + '
' + + '
' + + ' ' + + ' ' + + '
' + + '
' + + ' ' + + ' ' + + '
' + + '
' + }); + + + /** + * Update a select with the specified options and optionally choose the + * selected option based on the matching ID. + * @param {HTMLSelectElement} select The select element to update. + * @param {Array} options An Array of objects with the keys + * `name` and `id`. + * @param {string} [id] An optional value used to determine the selected + * option. + */ + function updateSelect(select, options, id) { + select.innerHTML = options.map(function(option) { + var selected = option.id == id ? 'selected ' : ' '; + return ''; + }).join(''); + } + + + /** + * Given an options object containing a single key that could be either + * "ids", "viewId", "propertyId", or "accountId", return a new object + * specifying that key in its `prop` property. If the passed property is + * "ids" convert it to "viewId". + * @param {Object} opts An options object. + * @return {Object} An object specifying what ID property and value were + * passed. + */ + function getIdProp(opts) { + if (opts.ids || opts.viewId) { + return {prop: 'viewId', value: opts.viewId || + (opts.ids && opts.ids.replace(/^ga:/, ''))}; + } + else if (opts.propertyId) { + return {prop: 'propertyId', value: opts.propertyId}; + } + else if (opts.accountId) { + return {prop: 'accountId', value: opts.accountId}; + } + } + +}); diff --git a/assets/javascript/explorer/ga-app.js b/assets/javascript/explorer/ga-app.js new file mode 100644 index 000000000..79535ae45 --- /dev/null +++ b/assets/javascript/explorer/ga-app.js @@ -0,0 +1,45 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// Commmon namespace. +var explorer = explorer || {}; + + +/** + * Runs the main application. This starts by requesting the latest column data + * from the Metadata API, which will be used to populate the dimensions and + * metrics dropdowns and help content. The run callback function name is passed + * as parameter so that it is called to init the rest of the application. + */ +explorer.run = function() { + explorer.getMetadata('explorer.runCallback'); +}; + + +/** + * Runs the main application. This starts by taking the Metadata API response, + * building the dimensions and metrics content and then loading the appropriate + * libraries. Once complete, the app is initialized. + * + * @param {Object} response The response from the Metadata API. + */ +explorer.runCallback = function(response) { + explorer.metadata.build(response); + explorer.coreapi.init(); + explorer.mgmt.init(); + explorer.auth.init(); + explorer.loader.loadLibs(); +}; + diff --git a/assets/javascript/explorer/ga-auth.js b/assets/javascript/explorer/ga-auth.js new file mode 100644 index 000000000..7bdd5e7e2 --- /dev/null +++ b/assets/javascript/explorer/ga-auth.js @@ -0,0 +1,65 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global explorer, gapi */ + +/** + * Auth Configuration + * @type {Object} + */ +explorer.auth = explorer.auth || {}; + + +/** + * Analytics API Key. + * @type {String} + */ +// TODO(philipwalton): Figure out how to assign this in the template. +explorer.auth.API_KEY = 'AIzaSyAuFQbCnospjGuTyjGTIgW_RoocFZ9KGus'; + +/** + * Analytics Client ID. + * @type {String} + */ +// explorer.auth.CLIENT_ID = '748720302078.apps.googleusercontent.com'; + + +/** + * Initialized the authorization UI and determines whether the user is + * already authorized. This should be called after the google-api-javascript + * client library has loaded. This method adds a click handler to the login + * button. It then makes a call to the authorization service to see whether + * the user is currently authorized. explorer.auth.handleAuthResult is executed + * once the authorization response returns. + */ +explorer.auth.init = function() { + explorer.pubsub.subscribe(explorer.pubsub.LIBS_LOADED, function() { + + gapi.analytics.ready(function() { + if (gapi.analytics.auth.isAuthorized()) { + explorer.pubsub.publish(explorer.pubsub.HAS_AUTH); + } + else { + gapi.analytics.auth.on('success', function() { + explorer.pubsub.publish(explorer.pubsub.HAS_AUTH); + }); + gapi.analytics.auth.on('error', function() { + explorer.pubsub.publish(explorer.pubsub.HAS_NO_AUTH); + }); + } + }); + }); +}; + diff --git a/assets/javascript/explorer/ga-coreapi.js b/assets/javascript/explorer/ga-coreapi.js new file mode 100644 index 000000000..47720cc2a --- /dev/null +++ b/assets/javascript/explorer/ga-coreapi.js @@ -0,0 +1,537 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global $, gapi, google */ + +/** + * @fileoverview This is the main file of the query explorer. It contains + * the login to have this tool live within an iFrame for security purposes. + * It also handles AuthSub token rediction. This file also provides a class + * to simplify constructing Google Analytics Data Export API Queries. JQuery + * must be referenced in order for the Explorer class to work. + * @author api.nickm@gmail.com (Nick Mihailovski) + */ + +// Create a namespace if not done already. +var explorer = explorer || {}; + +/** + * Core Reporting API query configuration + * @type {Object} + */ +explorer.coreapi = {}; + + +/** + * Dimension list dropdown. + * @type {explorer.CheckDropdown} + */ +explorer.coreapi.dimensionsDropdown = new explorer.CheckDropdown(); + + +/** + * Metric list dropdown. + * @type {explorer.CheckDropdown} + */ +explorer.coreapi.metricsDropdown = new explorer.CheckDropdown(); + + +/** + * Segment list dropdown. + * @type {explorer.SegmentsDropdown} + */ +explorer.coreapi.segmentDropdown = new explorer.SegmentsDropdown(); + + +/** + * Stores GA API query parameters. + * @type {explorer.DataQuery} + */ +explorer.coreapi.dataQuery = new explorer.DataQuery(); + + +/** + * Stores a blob of CSV data. Used for csv export. + * @type {Object} + */ +explorer.coreapi.csvBlob = {}; + + +/** + * Whether the download attribute of an anchor link is supported. + * This is calculated once and stored in this variable. + * @type {Boolean} + */ +explorer.coreapi.downloadSupported = false; + + +/** + * Default for the maximum number of query results. + * @type {number} + */ +explorer.coreapi.MAX_QUERY_RESULTS = '50'; + + +/** + * Initialize the Explorer + */ +explorer.coreapi.init = function() { + explorer.pubsub.subscribe(explorer.pubsub.HAS_AUTH, + explorer.coreapi.displayHasAuth); + explorer.pubsub.subscribe(explorer.pubsub.HAS_AUTH, + explorer.coreapi.queryForSegmentDropdown); + explorer.pubsub.subscribe(explorer.pubsub.DATA_QUERY_UPDATE, + explorer.coreapi.updateUiFromDataQuery); + + explorer.coreapi.displayUi(); + explorer.coreapi.createHelpText(); + explorer.coreapi.addFancyRollOvers(); + + explorer.coreapi.initDataQuery(); + + explorer.coreapi.dimensionsDropdown.init('dimensions', explorer.dimensionsHelp, 'gaHelp'); + explorer.coreapi.metricsDropdown.init('metrics', explorer.metricsHelp, 'gaHelp'); + explorer.coreapi.segmentDropdown.init('segment', explorer.segmentsHelp, 'gaHelp'); + + explorer.coreapi.setupUiLinkHandlers(); + explorer.coreapi.setupBubbleHandlers(); + $('#explorer').removeClass('hidden'); + + explorer.coreapi.displayDatePicker('start-date'); + explorer.coreapi.displayDatePicker('end-date'); + + explorer.coreapi.initCsvDownloadLink(); + +}; + + +/** + * Updates the display once a user has authenticated with the + * Google Analytics Authentication service. + */ +explorer.coreapi.displayHasAuth = function() { + $('#getData').show(); +}; + + +/** + * Handles all the work of adding the labels and query parameter + * input boxes for each parameter that exists in this class' dataQuery.query + * object. It uses the explorer.queryConfig[param].size value to set the width of + * each input box. This also adds a keyup handler to all the input boxes to + * update the value in the corresponding data query object's parameter. + */ +explorer.coreapi.displayUi = function() { + var html = ['
    ']; + for (var param in explorer.coreapi.dataQuery.query) { + var row = [ + '
  • ', + explorer.queryConfig[param].req ? '
    *
    ' : '', + '', + '
    =
    ', + '', + '
  • ' + ].join(''); + html.push(row); + } + html.push('
'); + $('#queryParams').html(html.join('')); + + // Add a click handler to all the inputboxes to update their + // respective query model params. + $('.queryInput').keyup(function() { + explorer.coreapi.dataQuery.setParam(this.id, this.value); + }); +}; + + +/** + * Executes a query to retrieve al the logged in user's segments. + */ +explorer.coreapi.queryForSegmentDropdown = function() { + $('#segment').addClass('small-loader').removeClass('dd-dropInput'); + gapi.client.analytics.management.segments.list().execute( + explorer.coreapi.handleSegmentResults); +}; + + +/** + * Handler for when the API returns with segment data. + * If an error occurs, it's displayed to the user. + * Otherwise, explorer.coreapi.SegmentsDropdown is initialized and bound to the + * segment input. + * @param {object} results The results returned from the segment + * query to the Management API. + */ +explorer.coreapi.handleSegmentResults = function(results) { + $('#segment').removeClass('small-loader').addClass('dd-dropInput'); + + if (results.error) { + var errorMsg = [ + results.code, ' : ', results.message, '
', + 'No drop down will be loaded for segments
', + 'You can now write your own segment expressions.
', + 'Refresh the page to try loading them again.' + ].join(''); + + var error_results = { + 'items': [{ + 'name': 'There was an error retrieving segments.', + 'segmentId': '' + }] + }; + explorer.coreapi.segmentDropdown.updateValues(error_results); + explorer.coreapi.displayErrorMessage(errorMsg); + } else { + explorer.coreapi.segmentDropdown.updateValues(results); + } +}; + + +/** + * Transforms the explorer.queryConfig.help parameter into an HTML string + * to display the text. Since there are many parts to describe each parameter, + * it's faster to add the HTML markup once and reference, than to create on the + * fly. To save space, the existing help text is overwritten. + */ +explorer.coreapi.createHelpText = function() { + if (!explorer.queryConfig) { + return; + } + + for (var param in explorer.queryConfig) { + var obj = explorer.queryConfig[param]; + obj.help = [ + '
', param, '
', + '(', + (obj.req) ? 'Required' : 'Optional', + ')
', + '

', obj.help, '

', + '

example
', obj.example, '

', + '
', + 'Read the reference for ', param, '' + ].join(''); + } +}; + + +/** + * Adds fancy mouse over effects to the rows in the query builder. + * On the mouseover event handler, the help information for the currently + * moused over parameter is displayed. This method also adds mouseover + * capability to the buttons on the page since IE doesn't know how to practice + * standards. + */ +explorer.coreapi.addFancyRollOvers = function() { + $('.qe-table li').mouseover(function() { + $(this).addClass('highlight'); + + // Update the help information. + var paramName = $(this).children('input').attr('id'); + $('#gaHelp').html(explorer.queryConfig[paramName].help).show(); + }).mouseout(function() { + $(this).removeClass('highlight'); + }); + + $('.submitBtn').hover(function() { + $(this).addClass('submitBtnHover'); + }, function() { + $(this).removeClass('submitBtnHover'); + }); +}; + +/** + * Initialize the Data Query. + */ +explorer.coreapi.initDataQuery = function() { + explorer.coreapi.dataQuery.setObj({ + 'max-results': explorer.coreapi.MAX_QUERY_RESULTS + }); + explorer.coreapi.dataQuery.setObjFromDeepLink(document.location.href); +}; + +/** + * Updates the UI based on the data query configuration. + */ +explorer.coreapi.updateUiFromDataQuery = function() { + var queryObj = explorer.coreapi.dataQuery.getQueryObj(); + for (var param in queryObj) { + document.getElementById(param).value = queryObj[param]; + } +}; + + +/** + * Adds JQuery datepicker control to the input text boxes. If a + * value exists in the input box, it is selected by default in the calendar. + * If there is no value the default date range is set as the last 14 days. + * @param {string} inputId the id of the input text to add a calendar to. + */ +explorer.coreapi.displayDatePicker = function(inputId) { + var input = document.getElementById(inputId); + $(input).datepicker({ + dateFormat: 'yy-mm-dd', + showButtonPanel: true, + changeMonth: true, + changeYear: true, + onSelect: function() { + $(input).keyup(); // Update the object and other controls. + } + }); + + // If a date exists in the input box. + if (!input.value) { + var defaultRange = (inputId == 'start-date') ? '-14' : '0'; + $(input).datepicker('setDate', defaultRange); + var myDate = $(input).datepicker('getDate'); + input.value = $.datepicker.formatDate('yy-mm-dd', myDate); + $(input).keyup(); // Update the object and other controls. + } +}; + + +/** + * Adds a click handler for the getData button. + */ +explorer.coreapi.setupUiLinkHandlers = function() { + $('#getData').click(explorer.coreapi.getApiData); +}; + +/** + * Sets up all the handlers for working with bubbles. + */ +explorer.coreapi.setupBubbleHandlers = function() { + /* + * Binds a click handler to the document to close bubbles. If a bubble + * is open, and a click occurs outsie the bubble, all bubbles close. + * If a bubble is opened, and a different bubble is clicked open, + * this first bubble is closed. + */ + $(document).bind('click.bub', function(e) { + var foundDivs = $(e.target).closest('#deepDiv,#queryUriDiv'); + if (foundDivs.length === 0) { + $('.ga-bubble').hide(); + } else { + if (foundDivs[0].id == 'deepDiv') { + $('#queryUriBubble').hide(); + } else { + $('#shareBubble').hide(); + } + } + }); + + // Auto select the entire deep link url. + $('#deepLinkUrl').click(function() { + $(this).select(); + }); + + // Handler for deep link. + $('#shareLink') + .mouseleave(function() { + // weak hack to not display the css tool tip when the bubble pops open. + $('.kd-tooltip').css({'visibility': 'visible'}); + }) + .click(explorer.coreapi.configureShare); + + // Auto select the entire query uri. + $('#queryUriText').click(function() { + $(this).select(); + }); + + // Handlers for the query uri button. + $('#queryUri') + .mouseleave(function() { + // weak hack to not display the css tool tip when the bubble pops open. + $('.kd-tooltip').css({'visibility': 'visible'}); + }) + .click(function() { + $('.kd-tooltip').css({'visibility': 'hidden'}); + $('#queryUriBubble').show(); + var queryUri = explorer.coreapi.dataQuery.getUri(); + $('#queryUriText').val(queryUri).select(); + }); +}; + +/** + * Configures the Share button + */ +explorer.coreapi.configureShare = function() { + $('.kd-tooltip').css({'visibility': 'hidden'}); + $('#shareBubble').show(); + var deepLink = explorer.coreapi.dataQuery.getDeepLink(explorer.selfUrl); + $('#deepLinkUrl').val(deepLink).select(); + + gapi.plusone.render('g-plus-div', { + 'size': 'medium', + 'annotation': 'bubble', + 'href': deepLink + }); + +}; + +/** + * Updates the UI and Queries the Core Reporting API + */ +explorer.coreapi.getApiData = function() { + if (explorer.coreapi.isRealQuery()) { + $('#gaOutput').hide(); // Hide existing results. + $('#loader').show(); // Show the ajax loader. + $('#sampledData').hide(); // Hide the sampled data msg box. + $('#csvDownload').hide(); // Hide download csv button. + + // Add a `_src` param to the query object to help track usage. + var dataParams = explorer.coreapi.dataQuery.getQueryObj(); + dataParams.access_token = gapi.auth.getToken().access_token; + dataParams._src = 'explorer'; + + // Manually make the request (rather than using `gapi.client`) + // so we can add the `_src` parameter to better track usage. + // The gapi client library strips out all unrecognized parameters. + $.ajax({ + url: 'https://content.googleapis.com/analytics/v3/data/ga', + type: 'GET', + data: dataParams, + dataType: 'json', + }) + .done(explorer.coreapi.displayResults) + .fail(explorer.coreapi.handleError); + } +}; + + +/** + * Extracts the error message from the XHR result and displays it. + * @param {jqXHR} jqXHR The jQuery XHR object. + */ +explorer.coreapi.handleError = function(jqXHR) { + var error = jqXHR.responseJSON.error; + var message = error.code + ' : ' + error.message; + explorer.coreapi.displayErrorMessage(message); +}; + + +/** + * Displays API error messages. It is called from the explorer api class. + * This also hides the sampling message if it was shown before. + * @param {String} errorMsg A message to return to the user. + */ +explorer.coreapi.displayErrorMessage = function(errorMsg) { + // Hide ajax loader. + $('#loader').hide(); + $('#sampledData').hide(); + $('#csvDownload').hide(); + $('#gaOutput').html([ + 'Ack! There was an error!

', + explorer.util.htmlEscape(errorMsg) + ].join('')).show(); +}; + + +/** + * Generates the HTML to display some metadata and data table for a Core + * Reporting API Query. + * @param {Object} results A JSON response from a Core Reporting API Query. + */ +explorer.coreapi.displayResults = function(results) { + + var rowLength = 0; + if (results.rows && results.rows.length) { + rowLength = results.rows.length; + } + + var conjunction = 'but'; + if (results.totalResults == rowLength) { + conjunction = 'and'; + } + + var html = [ + '

Your query matched ', results.totalResults, + ' results ', conjunction, ' the API only returned the following ', + rowLength, ' results:

'].join(''); + $('#gaOutput').html(html); + + + var dataTable = explorer.util.getDataTableFromCoreApi(results); + var tableViz = new google.visualization.Table( + document.getElementById('resultTable')); + + $('#loader').hide(); // hide ajax loader + + // Handle Sampled Data + if (results.containsSampledData) { + $('#sampledData').show(); + } else { + $('#sampledData').hide(); + } + + tableViz.draw(dataTable); + $('#gaOutput').show(); + + explorer.coreapi.download(); + $('#csvDownload').click(explorer.coreapi.download); +}; + +/** + * Generate the URL for the CSV Download link. + */ +explorer.coreapi.initCsvDownloadLink = function() { + if (document.createElement('a').download !== undefined) { + explorer.coreapi.downloadSupported = true; + window.URL = window.webkitURL || window.URL; + window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || + window.MozBlobBuilder; + + } +}; + +/** + * Generates the CSV download button + */ +explorer.coreapi.download = function() { + var token = gapi.auth.getToken(); + var access = token.access_token; + + var query = explorer.coreapi.dataQuery.getParamString(true); + query += '&access_token=' + access; + + var anchor = document.getElementById('csvDownload'); + anchor.href = '/explorer/csvhandler.csv?' + query; + $('#csvDownload').css('display', 'block'); +}; + +/** + * Checks for a Ken vs Ryu Query + * @return {Boolean} true if the query is legit, false if a haduken is needed. + */ +explorer.coreapi.isRealQuery = function() { + + var query = explorer.coreapi.dataQuery.getQueryObj(); + if (query.dimensions && + (query.dimensions.indexOf('ga:ryu') > -1 || + query.dimensions.indexOf('ga:ken') > -1)) { + + // Only support Chrome where there is a good experience. + if (typeof document.body.style.webkitTransition !== 'undefined') { + explorer.fun.haduken(); + return false; + } + } + + return true; +}; diff --git a/assets/javascript/explorer/ga-dataquery.js b/assets/javascript/explorer/ga-dataquery.js new file mode 100644 index 000000000..ec83a2f5d --- /dev/null +++ b/assets/javascript/explorer/ga-dataquery.js @@ -0,0 +1,162 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview This file provides a class to simplify constructing Google + * Analytics Data Export API Queries. It contains an object to hold all the + * important query parameters as well as methods to set and extract the feed + * url. + * @author api.nickm@google.com (Nick Mihailovski) + */ + +// create a namespace if not done already +var explorer = explorer || {}; + + +/** + * Class DataQuery holds all the parameters and values for a GA API data + * feed query. It also exposes methods to simplify setting and retrieving + * the parameters to be used with the API. + * @return {Object} A reference to this objecy. Useful for chaining. + * @constructor + */ +explorer.DataQuery = function() { + this.query = {}; + for (var param in explorer.queryConfig) { + this.query[param] = ''; + } + return this; +}; + + +/** + * Generic setter method for the parameters in the query object. Only + * parameters that exist in this Classes query object may be set. + * @param {string} param The parameter to modify. + * @param {string} value The value to set the parameter. + * @return {Object} A reference to this objecy. Useful for chaining. + */ +explorer.DataQuery.prototype.setParam = function(param, value) { + if (typeof this.query[param] === 'string') { + this.query[param] = value; + } + return this; +}; + + +/** + * This method sets all the parameters of the query object with the + * values of the parameter passed in. + * @param {Object} obj An object with members and values to be mapped + * to the query obejct. + * @return {Object} A reference to this objecy. Useful for chaining. + */ +explorer.DataQuery.prototype.setObj = function(obj) { + for (var param in obj) { + this.setParam(param, obj[param]); + } + explorer.pubsub.publish(explorer.pubsub.DATA_QUERY_UPDATE); + return this; +}; + + +/** + * This method sets the query object from the string generated from + * the getDeepLink method. + * @param {string} url The url generated from the deep link. + * @return {Object} A reference to this objecy. Useful for chaining. + */ +explorer.DataQuery.prototype.setObjFromDeepLink = function(url) { + // get query param + var query = url.split('?')[1]; + + // if there is an actual query parameter it will evaluate to true. + if (query) { + // remove hash + query = query.split('#')[0]; + var params = decodeURI(query).split('&'); + for (var i = 0; i < params.length; i++) { + var param = params[i].split('='); + this.setParam(param[0], decodeURIComponent(param[1])); + } + } + explorer.pubsub.publish(explorer.pubsub.DATA_QUERY_UPDATE); + return this; +}; + + +/** + * Returns the query parameters as a String to be used as a query for the + * Google Analytics API data feed. It also encodes the filter + * parameter. Only parameters that have values are returned. + * @return {String} URI encoded String. + */ +explorer.DataQuery.prototype.getUri = function() { + var params = this.getParamString(true); + return [explorer.CORE_REPORTING_API, '?', params].join(''); +}; + + +/** + * Returns the string to be used with deep linking to this query. + * @param {string} url The url to deep link this query to. + * @param {?boolean} opt_showIds Whether to include the ids parameter. + * @return {string} URI encoded String. + */ +explorer.DataQuery.prototype.getDeepLink = function(url, opt_showIds) { + var showIds = opt_showIds || false; + var params = this.getParamString(showIds); + return [url, '?', encodeURI(params)].join(''); +}; + + +/** + * This method returns all of the GA query parameters as a string to be used + * in a url. + * @param {boolean} showIds True when showing the account id parameter + * (ids) in the returned string. To be used with deep linking. + * @return {string} All the query parameters as a string to be used in a + * url. + */ +explorer.DataQuery.prototype.getParamString = function(showIds) { + var output = []; + for (var param in this.query) { + var value = this.query[param]; + if (param == 'ids' && !showIds) { + continue; + } + if (value) { + output.push([param, '=', encodeURIComponent(value)].join('')); + } + } + return output.join('&'); +}; + +/** + * Returns all of the GA query parameters as an object. + * @return {boolean} All the query parameters as an object. + */ +explorer.DataQuery.prototype.getQueryObj = function() { + var obj = {}; + for (var param in this.query) { + if (this.query[param] !== '') { + obj[param] = this.query[param]; + } + } + return obj; +}; + + + diff --git a/assets/javascript/explorer/ga-dropdown.js b/assets/javascript/explorer/ga-dropdown.js new file mode 100644 index 000000000..19851f1fc --- /dev/null +++ b/assets/javascript/explorer/ga-dropdown.js @@ -0,0 +1,624 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global $ */ + +/** + * @fileoverview This file contains classes to create the dropdowns for + * the GA Query Explorer. The first class is a drop down for the account + * selection. The second class subclasses the account dropdown and adds + * functionality to select different parameters. + * @author api.nickm@google.com (Nick Mihailovski) + */ + +// create a namespace if not done already +var explorer = explorer || {}; + + +/** + * Adds a click handler to the document to close certain elements if + * any clicks happen outside of those elements. This also closes any of + * the existing elements that are open. This is used for dropdowns. + */ +(function() { + // generic function to close all drop downs if a click event happens + $(document).bind('click.dd', function(e) { + if ($(e.target).closest('.dd-main,.dd-dropInput').length === 0) { + $('.dd-main').hide(); + } + }); +})(); + + + +/** + * Class Drop Down. This class creates a drop down for the account feed. + * @constructor + */ +explorer.Dropdown = function() { + this.input = {}; + this.values = {}; + this.output = {}; + this.dropdown = {}; + this.isInit = false; +}; + + +/** + * Runs all the initialization routines to construct the + * dropdown from the parameters passed into this method. Once complete + * the isInit member is set to true. + * @param {String} inputId The id of the text input box to bind this + * control to. + */ +explorer.Dropdown.prototype.init = function(inputId) { + this.input = document.getElementById(inputId); + + this.createHtmlContainer(); + this.addFocusHandler(this.input); + this.isInit = true; + $(this.input).addClass('dd-cursor'); +}; + + +/** + * Creates an HTML wrapper surrounding the dropdown code. + * The wrapper is then added to document.body. To update + * the dropdown, the innerHTML of the wrapper can be + * regenerated using the update method. + */ +explorer.Dropdown.prototype.createHtmlContainer = function() { + var titles = { + 'account': 'Select an account', + 'webproperty': 'Select a web property', + 'profile': 'Select a view (profile)' + }; + + var ddId = this.input.id + '-dd'; + var html = [ + '
', + '
', titles[this.input.id], '
', + '
', + '
' + ].join(''); + + $('body').append(html); + + this.dropdown = document.getElementById(ddId); +}; + + +/** + * Sets the position of the dropdown box's right most edge + * to align with the right most edge of the element passed in. It uses the + * getPosition method to determine the actual top and left positions of the + * page. + * @param {Object} elem The DOM element to align the dropdown with. + */ +explorer.Dropdown.prototype.setPosition = function(elem) { + var pos = this.getPosition(elem); + var iHeight = $(elem).outerHeight(); + var iWidth = $(elem).outerWidth(); + var ddWidth = $(this.dropdown).outerWidth(); + $(this.dropdown).css({ + 'top': pos.top + iHeight, + 'left': pos.left + iWidth - ddWidth + }); +}; + + +/** + * Adds a focus handler to open the drop down. + * @param {Object} inputControl The input box to listen when it receives focus. + */ +explorer.Dropdown.prototype.addFocusHandler = function(inputControl) { + var openHandler = explorer.util.bindMethod(this, explorer.Dropdown.prototype.open); + $(inputControl).focus(openHandler); +}; + + +/** + * Opens this dropdown. First all the other deop downs are hidden. + * Then the position of the dropdown is recalculated and moved to be + * under the input element. Finally the dropdown is shown. + */ +explorer.Dropdown.prototype.open = function() { + $('.dd-main').hide(); + this.setPosition(this.input); + $(this.dropdown).show(); +}; + + +/** + * Updates the dropdown with data returned from the analytics API. + * This redeners the content of the dropdown, then adds new row handlers + * to handle clicks, and mouseovers. + * @param {object} results Core Reporting API response. + */ +explorer.Dropdown.prototype.update = function(results) { + this.createDropdown(results); + this.addRowHandlers(); +}; + + +/** + * Creates the drop down and populates all the rows with values + * by going though all the elements in the values parameter. It also + * overwrites the values parameter with a simplified version of the result + * feed. + * @param {object} results Core Reporting API response. + */ +explorer.Dropdown.prototype.createDropdown = function(results) { + var html = []; + + results.items.sort(this.sortItemsByName); + + for (var i = 0, item; item = results.items[i]; ++i) { + html.push( + '
', + explorer.util.htmlEscape(item.name), + '
'); + } + + var ddId = '#' + this.input.id + '-dd-content'; + $(ddId).html(html.join('')); +}; + + +/** + * Compares two items and returns whether they are in alphabetical order. + * @param {string} a The first item in the set. + * @param {string} b The second item in the set. + * @return {number} -1 if they are in order, 1 if they are out of order, 0 + * if they are the same. + */ +explorer.Dropdown.prototype.sortItemsByName = function(a, b) { + var lowerA = a.name.toLowerCase(); + var lowerB = b.name.toLowerCase(); + + if (lowerA < lowerB) { + return -1; + } else if (lowerA > lowerB) { + return 1; + } + return 0; +}; + + +/** + * Adds handlers for each row in the drop down. It adds a click + * handler to update the bound input text box with the id of the current div. + * This id is the table id and set in the explorer.createDropdown method. This method + * also adds mouse overs to every row. + */ +explorer.Dropdown.prototype.addRowHandlers = function() { + var obj = this; + $('#' + this.dropdown.id + ' .dd-row') + .click(function() { + var entityName = obj.input.id; + var name = $(this).text(); + var id = $(this).attr('id'); + + //$(obj.input).val(name); + $(obj.dropdown).hide(); + + explorer.mgmt.updateUi(entityName, name, id); + + }).mouseenter(function() { + $(this).addClass('dd-highlight'); + + }).mouseout(function() { + $(this).removeClass('dd-highlight'); + }); +}; + + +/** + * Returns the exact position of an element. + * @param {string} obj The id of an element to get it's position. + * @return {Object} an object containing the top and the left position + * relative to the document. + */ +explorer.Dropdown.prototype.getPosition = function(obj) { + var curleft = 0; + var curtop = 0; + if (obj.offsetParent) { + do { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } while (obj = obj.offsetParent); + } + return {'top': curtop, 'left': curleft}; +}; + + + +/** + * Class Check Drop Down. This class dynamically creates a drop down from + * the parameters passed into the init's value parameter. The drop down + * has checkboxes to select multiple values and this class handles making + * sure the bound input box as well as the checkboxes stay in sync. + * @constructor + * @extends {explorer.Dropdownn} + */ +explorer.CheckDropdown = function() { + this.boxesChecked = {}; + this.form = {}; +}; + + +/** get access to the prototype of the explorer.Dropdown class */ +explorer.CheckDropdown.prototype = new explorer.Dropdown(); + + +/** + * Runs all the initialization routines to construct the + * dropdown from the parameters passed to this method. + * @param {string} inputId The id of the text input box to bind this + * control to. + * @param {Object} values An object representing the groupings and + * values to insert into the rows of the drop down. This object + * may also have help information. + * @param {string} output The id of the location to display any help + * information. + * @override + */ +explorer.CheckDropdown.prototype.init = function(inputId, values, output) { + this.input = document.getElementById(inputId); + this.values = values; + this.output = document.getElementById(output); + + // give the associated input box a dropInput class + $(this.input).addClass('dd-dropInput').addClass('dd-cursor'); + + this.createDropdown(); + this.addInputKeyupHandler(); + this.addFocusHandler(this.input); + this.addRowHandlers(); + this.setPosition(this.input); + + $(this.input).keyup(); // Set defaults from perma link. +}; + + +/** + * Creates all of the drop down controls based on this object's + * values parameter. + * @override + */ +explorer.CheckDropdown.prototype.createDropdown = function() { + // the new id of the drop down + var ddId = this.input.id + '-dd'; + var formId = this.input.id + '-form'; + + var html = ['
']; + html.push('
'); + + // add the group name + for (var groupName in this.values) { + html.push('
', + groupName, '
'); + + // add the property names + for (var property in this.values[groupName]) { + html.push(''); + } + html.push('
'); + } + html.push('
'); + $('body').append(html.join('')); + + // reference the newly created form and drop down from this object + this.form = document.getElementById(formId); + this.dropdown = document.getElementById(ddId); +}; + + +/** + * Adds a keyup event handler to the input text box to keep the + * drop down check boxes status' in sync with the modified text. This handler + * executes the CheckDropDown.updateCheckboxes method. + */ +explorer.CheckDropdown.prototype.addInputKeyupHandler = function() { + var obj = this; + $(this.input).keyup(function() { + obj.updateCheckboxes(); + }); +}; + + +/** + * Adds handlers for each row in the drop down. It adds a click + * handler to the checkboxes (using the label's "for" parameter achieves the + * effect of clicking a row to select the checkbox). When clicked, + * CheckDropdown.updateInput is called to update the input text box. Also + * mouse overs are added to each row to display the help information. + * @override + */ +explorer.CheckDropdown.prototype.addRowHandlers = function() { + var sel = ['#', this.dropdown.id, ' .dd-row'].join(''); + + // click handler for the checkboxes + var obj = this; + $(sel).mouseover(function() { + $(this).addClass('dd-highlight'); + var groupId = $(this).parent().children('.dd-groupName').text(); + var valueId = $(this).attr('for'); + obj.displayHelp(groupId, valueId); + }) + .mouseout(function() { + $(this).removeClass('dd-highlight'); + }) + .children('.dd-check') + .click(function() { + obj.updateInput(this.checked, this.value); + }); +}; + + +/** + * Displays information for the groupId and valueId passed + * into the method. The help text comes from this class's values object. + * The HTML markup for the help text is constructed on the fly since there + * can be many items in a list and only a subset of them selected at any + * given time so it slightly faster to build the string at run time. + * @param {string} groupId The group id of the particular element to display + * it's help information. + * @param {string} valueId The value id of the particular element to display + * it's help information. + */ +explorer.CheckDropdown.prototype.displayHelp = function(groupId, valueId) { + var html = ['
', valueId, '

', + '

', this.values[groupId][valueId], '

', + 'Read the ', this.input.id, + ' values reference'].join(''); + $(this.output).html(html).show(); +}; + + +/** + * Updates the checkboxes after the input text box has been + * modified. It goes through two passes. First it checks the boxes for all + * valid parameters in the text box. It then deselects any checkboxes that + * had previously been in the text box but were removed. + */ +explorer.CheckDropdown.prototype.updateCheckboxes = function() { + var tmpChecked = {}; + var id; + + // first check to see if new values were added that need to be checked + // in the CheckDropdown + var inputVals = this.input.value.split(','); + for (var i = 0; i < inputVals.length; i++) { + id = inputVals[i]; + // add into tmpChecked for later + tmpChecked[id] = true; + // check if this value is a checkbox in the form + if (this.form.elements[id]) { + // check if this value has not been checked through + // the boxesChecked object + if (!this.boxesChecked[id]) { + this.form.elements[id].checked = true; //check the box + this.boxesChecked[id] = true; //add to the boxes checked array + } + } + } + // if a value exists in the boxesChecked object but is not in the input box, + // then it has been removed and needs to be unselected + for (id in this.boxesChecked) { + if (!tmpChecked[id]) { + this.form.elements[id].checked = false; + delete this.boxesChecked[id]; + } + } +}; + + +/** + * Updates the input box's value with the checkbox's value. It is called from + * the CheckDropdown's checkboxes click event handler. + * If the checkbox is clicked, it's value is added to the input box. + * If the check box is unclicked, any instance of the checkbox's value + * in the input box is removed. + * @param {boolean} isChecked True if the checkbox was checked. + * @param {string} checkedValue The checkbox's value. + */ +explorer.CheckDropdown.prototype.updateInput = function(isChecked, checkedValue) { + // if checkbox was checked and the checkedValue to the input box. + if (isChecked) { + + if (this.input.value) { + this.input.value += ','; + } + this.input.value += checkedValue; + this.boxesChecked[checkedValue] = true; // for input handler + + } else { + // if the checkbox is unchecked, remove all instances of the value + + var str = this.input.value; + + // collapse all inner instances of the value to the list delimiter + var exp = [',(', checkedValue, ',)*'].join(''); + var regEx = new RegExp(exp, 'g'); + str = str.replace(regEx, ','); + + // remove beginning and ending instances of the value + exp = ['^', checkedValue, ',|,', checkedValue, '$'].join(''); + regEx = new RegExp(exp, 'g'); + str = str.replace(regEx, ''); + + // remove value if it is the only thing left + exp = ['^', checkedValue, '$'].join(''); + regEx = new RegExp(exp, 'g'); + str = str.replace(regEx, ''); + + this.input.value = str; + delete this.boxesChecked[checkedValue]; // For input handler. + } + $(this.input).keyup(); // Fire this input box's keyup event. +}; + + + +/** + * Class SegmentsDropdown. This class dynamically creates a drop down from + * the parameters passed into the init's value parameter. + * @constructor + * @extends {explorer.Dropdown} + */ +explorer.SegmentsDropdown = function() {}; + + +/** get access to the prototype of the explorer.Dropdown class */ +explorer.SegmentsDropdown.prototype = new explorer.Dropdown(); + + +/** + * Runs all the initialization routines to construct the + * dropdown from the parameters passed to this method. + * @param {string} inputId The id of the text input box to bind this control. + * @param {Object} values An object representing the groupings and values to + * insert into the rows of the drop down. + * @param {string} output The id of the location to display any help + * information. + * @override + */ +explorer.SegmentsDropdown.prototype.init = function(inputId, values, output) { + this.input = document.getElementById(inputId); + this.values = values; + this.output = document.getElementById(output); + + // give the associated input box a dropInput class + $(this.input).addClass('dd-dropInput').addClass('dd-cursor'); + + this.createDropdown(); + this.addFocusHandler(this.input); +}; + + +/** + * Creates all of the drop down controls based on this object's + * values parameter. + * @override + */ +explorer.SegmentsDropdown.prototype.createDropdown = function() { + // The new id of the drop down. + var ddId = this.input.id + '-dd'; + + // Create the HTML of the dropdown. + var html = ['
']; + $('body').append(html.join('')); + + // reference the newly created form and drop down from this object + this.dropdown = document.getElementById(ddId); + this.updateDropdown(); + this.addRowHandlers(); +}; + + +/** + * Updates the rows of the dropdown with the values object. + */ +explorer.SegmentsDropdown.prototype.updateDropdown = function() { + var html = []; + // Add the group name. + for (var groupName in this.values) { + html.push('
'); + html.push('
', groupName, '
'); + + // Add the segment names. + var segments = this.values[groupName]; + for (var segment in segments.values) { + html.push([ + '
', + explorer.util.htmlEscape(segment), + '
' + ].join('')); + } + html.push('
'); // End div group. + } + html.push('
'); // End div dropdown. + $(this.dropdown).html(html.join('')); +}; + + +/** + * Updates the dropdown to include the authorized user's segments. + * This method updates the explorer.segmentsHelp['Custom Segments'].values + * object. Each of segment names found in results are added as keys + * and the segment IDs are added as values. Finally this segment + * is rerendered and new row handlers are added. + * @param {object} results The results returned from the segments + * collection of the Management API. + */ +explorer.SegmentsDropdown.prototype.updateValues = function(results) { + var hasCustomSegments = false; + var customSegments = {}; + + if (results && results.items && results.items.length) { + var items = results.items; + for (var i = 0, segment; segment = items[i]; ++i) { + + // Default segment IDs are always < 0. Custom segments IDs are + // alphanumeric values. When you parseInt a custom segment ID you'll + // either get NaN or a positive integer. So to identify custom segments + // we use anything that is not a number or > -1. + var segmentId = parseInt(segment.id, 10); + if (!segmentId || (segmentId >= -1)) { + customSegments[segment.name] = segment.segmentId; + hasCustomSegments = true; + } + } + } + + if (!hasCustomSegments) { + customSegments['No custom segments for user'] = ''; + } + + explorer.segmentsHelp[explorer.customSegName].values = customSegments; + this.updateDropdown(); + this.addRowHandlers(); +}; + + +/** + * Adds handlers for each row in the drop down. + * @override + */ +explorer.SegmentsDropdown.prototype.addRowHandlers = function() { + var self = this; + $('#' + this.dropdown.id + ' .dd-row') + .click(function() { + var segmentTxt = $(this).attr('id'); + + // update input value and fire keyup to update query object + $(self.input).val(segmentTxt).keyup(); + $(self.input).focus(); + + }).mouseenter(function() { + $(this).addClass('dd-highlight'); + + }).mouseout(function() { + $(this).removeClass('dd-highlight'); + + }); +}; + diff --git a/assets/javascript/explorer/ga-fun.js b/assets/javascript/explorer/ga-fun.js new file mode 100644 index 000000000..a75e9613d --- /dev/null +++ b/assets/javascript/explorer/ga-fun.js @@ -0,0 +1,98 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +var explorer = explorer || {}; + +/** + * Configuration object for Fun stuff + */ +explorer.fun = explorer.fun || {}; + + +// Browser BS. you guys suck for making it difficult. +var transitionProperty = 'transitionProperty'; +var transitionDuration = 'transitionDuration'; +var transitionTimingFunction = 'transitionTimingFunction'; +var transitionEnd = 'transitionEnd'; + +if (typeof document.body.style.webkitTransitionProperty !== 'undefined') { + transitionProperty = 'webkitTransitionProperty'; + transitionDuration = 'webkitTransitionDuration'; + transitionTimingFunction = 'webkitTransitionTimingFunction'; + transitionEnd = 'webkitTransitionEnd'; +} +/*else if (typeof document.body.style.MozTransitionProperty !== 'undefined') { + transitionProperty = 'MozTransitionProperty'; + transitionDuration = 'MozTransitionDuration'; + transitionTimingFunction = 'MozTransitionTimingFunction'; + transitionEnd = 'transitionend'; +}*/ + +/** + * Creates the haduken experience + */ +explorer.fun.haduken = function() { + var img = document.createElement('img'); + var now = new Date(); + var id = now.getTime(); + var audioId = id + 'audio'; + var resourceDir = '/public/images/explorer/'; + + img.id = id; + img.src = resourceDir + 'had.png'; + + //img.style.left = '-225px'; + img.style.left = '0px'; + img.style.top = '275px'; + img.style.position = 'absolute'; + img.style[transitionProperty] = 'left'; + img.style[transitionDuration] = '2s'; + img.style[transitionTimingFunction] = 'ease-out'; + //return true; + + img.addEventListener(transitionEnd, function() { + // Remove image. + var had = document.getElementById(id); + had.parentNode.removeChild(had); + + // Remove audio. + var audio = document.getElementById(audioId); + audio.parentNode.removeChild(audio); + }); + + document.body.appendChild(img); + + window.setTimeout(function() { + if (typeof document.body.style.webkitTransitionProperty !== 'undefined') { + // play clip + var source1 = document.createElement('source'); + source1.src = resourceDir + 'had.mp3'; + var source2 = document.createElement('source'); + source2.src = resourceDir + 'had.ogg'; + var audio = document.createElement('audio'); + audio.id = audioId; + audio.autoplay = 'true'; + audio.appendChild(source2); + audio.appendChild(source1); + document.body.appendChild(audio); + } + + // do aninamtion + var endDistance = window.innerWidth + 225; + var had = document.getElementById(id); + had.style.left = endDistance + 'px'; + }, 1); +}; + diff --git a/assets/javascript/explorer/ga-loader.js b/assets/javascript/explorer/ga-loader.js new file mode 100644 index 000000000..cebff9af0 --- /dev/null +++ b/assets/javascript/explorer/ga-loader.js @@ -0,0 +1,74 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global explorer, google */ + +/** + * namespace + */ +explorer.loader = explorer.loader || {}; + +/** + * JS Library loader + */ +explorer.loader.JS_LOADER = ( + 'https://www.google.com/jsapi?callback=explorer.loader.jsapiCallback'); + +/** + * Asynchronously loads required libraries for the query explorer. Callback + * is executed once all the libraries have been loaded. + * Loads the Google API JavaScript client library. + * Loads the Visualization API Table library. + */ +explorer.loader.loadLibs = function() { + explorer.loader.loadJs(explorer.loader.JS_LOADER); +}; + + +/** + * Asynchronously loads a JavaScript library. Callback is executed once + * complete. + * @param {String} url The JavaScript resource to load. + */ +explorer.loader.loadJs = function(url) { + var js = document.createElement('script'); + js.async = true; + js.src = url; + var s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(js, s); +}; + + +/** + * Loads the gviz library + */ +explorer.loader.jsapiCallback = function() { + google.load('visualization', '1', { + 'callback': explorer.loader.handler, + 'packages': ['table']}); +}; + + +/** + * Main callback handler for all libraries. After the google loader has loaded, + * the loader is used to load the visualization API. Once all the libraries + * have loaded, the LIBS_LOADED message is published. + */ +explorer.loader.handler = function() { + // If all libraries are done loading. + if (window.google && window.google.visualization) { + explorer.pubsub.publish(explorer.pubsub.LIBS_LOADED); + } +}; diff --git a/assets/javascript/explorer/ga-metadata.js b/assets/javascript/explorer/ga-metadata.js new file mode 100644 index 000000000..e0b8df9e3 --- /dev/null +++ b/assets/javascript/explorer/ga-metadata.js @@ -0,0 +1,283 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global $ */ + +/** + * @fileoverview Contains all the dimension and metrics groupings and help + * text from the Metadata API. This is used to dynamically populate the query + * explorer with data form the Metadata API response. + * @author pfrisella@google.com (Pete Frisella) + */ + +// Default namespace. +var explorer = explorer || {}; + + +/** + * Namespace for metadata functionality. + * @type {Object} + */ +explorer.metadata = {}; + + +/** + * The type value for a dimension column. + * @type {string} + * @const + */ +explorer.metadata.DIMENSION = 'DIMENSION'; + + +/** + * The type value for a metric column. + * @type {string} + * @const + */ +explorer.metadata.METRIC = 'METRIC'; + + +/** + * The status value for a deprecated column. + * @type {string} + * @const + */ +explorer.metadata.DEPRECATED = 'DEPRECATED'; + + +/** + * An object to hold the Google Analytics API dimension descriptions. + * @type {Object} + */ +explorer.dimensionsHelp = {}; + + +/** + * An object to hold the Google Analytics API metric descriptions. + * @type {Object} + */ +explorer.metricsHelp = {}; + + +/** + * Metadata API request URL. + * @type {string} + * @const + */ +explorer.metadata.METADATA_API_URL = [ + 'https://www.googleapis.com/analytics/v3/metadata/ga/columns', + '?key=', explorer.auth.API_KEY].join(''); + + +/** + * Main initialization function. Querys the Metadata API + * and ensures that the browser response is not cached; jquery + * adds cache busting. Once loaded, the explorer.metadata.callback_ + * method is called. + * + * @param {string} callbackName The name of the function to execute and pass the + * Metadata API response to. + */ +explorer.getMetadata = function(callbackName) { + $.ajax(explorer.metadata.METADATA_API_URL, { + 'dataType': 'jsonp', + 'jsonpCallback': callbackName + }); +}; + + +/** + * Builds the metrics and dimensions groups that are used to populate the + * dropdowns and HTML help content for each column. Once the content is built, + * the metricsHelp and dimensionsHelp variables are set. These then get used in + * ga-core.js to populate the dropdowns and set the help text. + * + * @param {Object} response The response from the Metadata API. + */ +explorer.metadata.build = function(response) { + var groups = explorer.metadata.getColumnsByGroup_(response); + explorer.metricsHelp = groups[explorer.metadata.METRIC]; + explorer.dimensionsHelp = groups[explorer.metadata.DIMENSION]; +}; + + +/** + * Parses the Metadata API response and gets the HTML content to use for each + * column. Columns are organized by type, group name, and column ID. This object + * can then be used to populate the Query Explorer dimensions and metrics + * dropdowns and the help text for each column. Deprecated columns are + * excluded. + * + * @param {Object} response The response from the Metadata API. + * @return {Object} A collection of column HTML content organized by type, group + * name, and ID. Deprecated columns are excluded. + * E.g. ['DIMENSION']['Visitors']['ga:visitors'] = '{HTML Help Content}'. + * @private + **/ +explorer.metadata.getColumnsByGroup_ = function(response) { + var groups = {}; + groups[explorer.metadata.DIMENSION] = {}; + groups[explorer.metadata.METRIC] = {}; + + for (var i = 0, item; item = response.items[i]; ++i) { + var groupName = item.attributes.group; + var itemType = item.attributes.type; + var itemStatus = item.attributes.status; + + if (itemStatus != explorer.metadata.DEPRECATED) { + if (!groups[itemType][groupName]) { + groups[itemType][groupName] = {}; + } + groups[itemType][groupName][item.id] = explorer.metadata.getColumnHtml_(item); + } + } + return groups; +}; + + +/** + * Returns the HTML content to use for a column. This includes details about the + * column such as UI name, description, data type, if allowed in segments, and + * other attributes. + * + * @param {Object} item The column from which to get the HTML help content. + * @return {string} The HTML help content for the column. + * @private + */ +explorer.metadata.getColumnHtml_ = function(item) { + var html = []; + explorer.metadata.buildNameHtml_(item, html); + explorer.metadata.buildDescriptionHtml_(item, html); + explorer.metadata.buildCalculationHtml_(item, html); + explorer.metadata.buildRequiredAttributesHtml_(item, html); + explorer.metadata.buildIndexRangeHtml_(item, html); + explorer.metadata.buildPremiumIndexRangeHtml_(item, html); + return html.join(''); +}; + + +/** + * Builds HTML help content for the column web and app UI names. + * + * @param {Object} item The column from which to build the name help content. + * @param {Array} html HTML content is pushed to this array. + * @private + */ +explorer.metadata.buildNameHtml_ = function(item, html) { + html.push('Web View Name: ', item.attributes.uiName, '
'); + if (!!item.attributes.appUiName) { + html.push( + 'App View Name: ', item.attributes.appUiName, + '
'); + } + html.push('
'); +}; + + +/** + * Builds HTML help content for the column calculation attribute, if it + * exists. + * + * @param {Object} item The column from which to build the calculation help + * content. + * @param {Array} html HTML content is pushed to this array. + * @private + */ +explorer.metadata.buildCalculationHtml_ = function(item, html) { + if (!!item.attributes.calculation) { + html.push( + '

Calculation:
', + '', item.attributes.calculation, ''); + } +}; + + +/** + * Builds HTML help content for the column description attribute and replaces + * URLs in the description with live links that will open in a new window. + * + * @param {Object} item The column from which to build the description help + * content. + * @param {Array} html HTML content is pushed to this array. + * @private + */ +explorer.metadata.buildDescriptionHtml_ = function(item, html) { + var urlRegEx = /(https?:\/\/[^\s]+)/ig; + var description = item.attributes.description; + description = description.replace(urlRegEx, + function(url) { + return '' + url + ''; + }); + html.push(description); +}; + + +/** + * Builds HTML help content for column attributes that are expected to be + * included in every column: Data type and allowed in segments. + * + * @param {Object} item The column from which to build the attribute help + * content. + * @param {Array} html HTML content is pushed to this array. + * @private + */ +explorer.metadata.buildRequiredAttributesHtml_ = function(item, html) { + html.push( + '

Attributes:
', + 'Data Type: ', item.attributes.dataType, '
', + 'Allowed In Segments: '); + if (!!item.attributes.allowedInSegments) { + html.push('Yes'); + } else { + html.push('No'); + } + html.push('
'); +}; + + +/** + * Builds HTML help content for column template index range attribute. + * + * @param {Object} item The column from which to build the index range help + * content. + * @param {Array} html HTML content is pushed to this array. + * @private + */ +explorer.metadata.buildIndexRangeHtml_ = function(item, html) { + if (!!item.attributes.minTemplateIndex && + !!item.attributes.maxTemplateIndex) { + html.push( + 'Index Range: ', item.attributes.minTemplateIndex, ' to ', + item.attributes.maxTemplateIndex, '
'); + } +}; + + +/** + * Builds HTML help content for column template premium index range attribute. + * + * @param {Object} item The column from which to build the premium index range + * help content. + * @param {Array} html HTML content is pushed to this array. + * @private + */ +explorer.metadata.buildPremiumIndexRangeHtml_ = function(item, html) { + if (!!item.attributes.premiumMinTemplateIndex && + !!item.attributes.premiumMaxTemplateIndex) { + html.push( + 'Premium Index Range: ', item.attributes.premiumMinTemplateIndex, + ' to ', item.attributes.premiumMaxTemplateIndex, '
'); + } +}; diff --git a/assets/javascript/explorer/ga-mgmt.js b/assets/javascript/explorer/ga-mgmt.js new file mode 100644 index 000000000..01461bafb --- /dev/null +++ b/assets/javascript/explorer/ga-mgmt.js @@ -0,0 +1,407 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global $, gapi */ + +/** + * Namespace. + */ +var explorer = explorer || {}; + + +/** + * Config object for Management API queries + */ +explorer.mgmt = explorer.mgmt || {}; + + +/** + * Used for caching config values for mangement + */ +explorer.mgmt.STORAGE_KEY = 'mgmtData'; + + +/** + * true if previously selected account details are not available. + */ +explorer.mgmt.isNew = true; + + +/** + * Id of the last clicked management resource + */ +explorer.mgmt.clickedId = ''; + + +/** + * Object to store management query config details + */ +explorer.mgmt.cache = {}; + + +/** + * Details for the currently selected management resource. + */ +explorer.mgmt.data = { + 'accountId': '', + 'accountName': '', + 'webpropertyId': '', + 'webPropertyName': '', + 'profileId': '', + 'profileName': '' +}; + + +/** + * The Account dropdown + */ +explorer.mgmt.accountDd = new explorer.Dropdown(); + + +/** + * The Web Property dropdown + */ +explorer.mgmt.webpropertyDd = new explorer.Dropdown(); + + +/** + * The Profile dropdown + */ +explorer.mgmt.profileDd = new explorer.Dropdown(); + + +/** + * Initialized the UI for the account selection managemenet portion of the + * UI. The user can select an Account, WebProperty and a Profile. When + * selected, each are added to the explorer.mgmt.data object and stored locally. + * if the user returns, the data is loaded, then the previous + * selections are displayed. + * @param {String} userId The Id of the current user. + */ +explorer.mgmt.init = function() { + var data = explorer.mgmt.load(); + if (data) { + explorer.mgmt.isNew = false; + explorer.mgmt.data = data; + $('#account').val(explorer.mgmt.data.accountName); + $('#webproperty').val(explorer.mgmt.data.webpropertyName); + $('#profile').val(explorer.mgmt.data.profileName); + explorer.mgmt.updateIds(explorer.mgmt.data.profileId); + + } else { + $('#account') + .val('authorize to list accounts') + .addClass('inputStatusMsg'); + } + + explorer.pubsub.subscribe(explorer.pubsub.HAS_AUTH, explorer.mgmt.setupDropdowns); +}; + + +/** + * Generates account, property and profile dropdowns. + */ +explorer.mgmt.setupDropdowns = function() { + if (explorer.mgmt.isNew) { + explorer.mgmt.loadAccounts(); + } else { + $('#account').click(explorer.mgmt.handleAccountClick); + $('#webproperty').click(explorer.mgmt.handleWebpropertyClick); + $('#profile').click(explorer.mgmt.handleProfileClick); + } + $('#account').removeClass('inputStatusMsg'); +}; + + +/** + * Handles clicks on the account dropdown. + * @param {Object} event The event to be handled. + */ +explorer.mgmt.handleAccountClick = function(event) { + explorer.mgmt.clickedId = event.target.id; + explorer.mgmt.loadAccounts(); +}; + + +/** + * Handles clicks on the web property dropdown. + * @param {Object} event The event to be handled. + */ +explorer.mgmt.handleWebpropertyClick = function(event) { + explorer.mgmt.clickedId = event.target.id; + explorer.mgmt.loadWebproperties(); +}; + + +/** + * Handles clicks on the profile dropdown. + * @param {Object} event The event to be handled. + */ +explorer.mgmt.handleProfileClick = function(event) { + explorer.mgmt.clickedId = event.target.id; + explorer.mgmt.loadProfiles(); +}; + + +/** + * Queries the Management API for a list of Accounts for the + * current user. + */ +explorer.mgmt.loadAccounts = function() { + $('#account').addClass('small-loader'); + gapi.client.analytics.management.accounts.list().execute( + explorer.mgmt.handleAccounts); +}; + + +/** + * Handles the response from a query to the Management API for a list of + * accounts for the current user. + * @param {Object} results A Core Reporting API response. + */ +explorer.mgmt.handleAccounts = function(results) { + $('#account').removeClass('small-loader'); + if (results.error) { + explorer.mgmt.displayError(results); + + } else if (!results.items || !results.items.length) { + $('#account').val('No accounts found'); + + } else { + $('#account').addClass('dd-dropInput'); + + if (!explorer.mgmt.accountDd.isInit) { + if (!explorer.mgmt.isNew) { + $('#account').unbind('click'); + } + + explorer.mgmt.accountDd.init('account'); + + if (explorer.mgmt.clickedId == 'account') { + explorer.mgmt.accountDd.update(results); + explorer.mgmt.clickedId = ''; + explorer.mgmt.accountDd.open(); + return; + } + } + + explorer.mgmt.accountDd.update(results); + explorer.mgmt.updateUi('account', results.items[0].name, results.items[0].id); + + } +}; + + +/** + * Queries the Management API for a list of Properties for the + * current user and selected account. + */ +explorer.mgmt.loadWebproperties = function() { + // give the associated input box a dropInput class + $('#webproperty').addClass('small-loader').removeClass('dd-dropInput'); + + // Try to retrieve from cache. + var results = explorer.mgmt.cache[explorer.mgmt.data.accountId]; + if (results) { + explorer.mgmt.handleWebproperties(results); + + } else { + // Fetch from API. + gapi.client.analytics.management.webproperties.list({ + 'accountId': explorer.mgmt.data.accountId}).execute( + explorer.mgmt.handleWebproperties); + } +}; + + +/** + * Handles the response from a query to the Management API for a list of + * properties for the current user and selected account. + * @param {Object} results A Core Reporting API response. + */ +explorer.mgmt.handleWebproperties = function(results) { + $('#webproperty').removeClass('small-loader'); + + if (results.error) { + explorer.mgmt.displayError(results); + + } else if (!results.items || !results.items.length) { + $('#webproperty').val('No web properties found'); + + } else { + $('#webproperty').addClass('dd-dropInput'); + explorer.mgmt.cache[explorer.mgmt.data.accountId] = results; + + if (!explorer.mgmt.webpropertyDd.isInit) { + if (!explorer.mgmt.isNew) { + $('#webproperty').unbind('click'); + } + + explorer.mgmt.webpropertyDd.init('webproperty'); + + if (explorer.mgmt.clickedId == 'webproperty') { + explorer.mgmt.webpropertyDd.update(results); + explorer.mgmt.clickedId = ''; + explorer.mgmt.webpropertyDd.open(); + return; + } + } + + explorer.mgmt.webpropertyDd.update(results); + explorer.mgmt.updateUi('webproperty', results.items[0].name, + results.items[0].id); + + } +}; + + +/** + * Queries the Management API for a list of Profiles for the + * current use, selected account, and selected property. + */ +explorer.mgmt.loadProfiles = function() { + + $('#profile').addClass('small-loader').removeClass('dd-dropInput'); + + // Try to retrieve from cache. + var results = explorer.mgmt.cache[explorer.mgmt.data.webpropertyId]; + if (results) { + explorer.mgmt.handleProfiles(results); + + } else { + // Fetch from API. + gapi.client.analytics.management.profiles.list({ + 'accountId': explorer.mgmt.data.accountId, + 'webPropertyId': explorer.mgmt.data.webpropertyId}).execute( + explorer.mgmt.handleProfiles); + } + +}; + + +/** + * Handles the response from a query to the Management API for a list of + * profiles for the current user, selected account, and property. + * @param {Object} results A Core Reporting API response. + */ +explorer.mgmt.handleProfiles = function(results) { + $('#profile').removeClass('small-loader'); + + if (results.error) { + explorer.mgmt.displayError(results); + + } else if (!results.items || !results.items.length) { + $('#profile').val('No views (profiles) found'); + + } else { + $('#profile').addClass('dd-dropInput'); + explorer.mgmt.cache[explorer.mgmt.data.webpropertyId] = results; + + if (!explorer.mgmt.profileDd.isInit) { + if (!explorer.mgmt.isNew) { + $('#profile').unbind('click'); + } + + explorer.mgmt.profileDd.init('profile'); + + if (explorer.mgmt.clickedId == 'profile') { + explorer.mgmt.profileDd.update(results); + explorer.mgmt.clickedId = ''; + explorer.mgmt.profileDd.open(); + return; + } + } + + explorer.mgmt.profileDd.update(results); + explorer.mgmt.updateUi('profile', results.items[0].name, results.items[0].id); + } +}; + + +/** + * Updates the Explorer UI based on the currently selected Account, Property, + * and Profile. + * @param {String} entityName The entity type that needs updating. + * @param {String} name The name of the entity. + * @param {String} id The Id of the entity. + */ +explorer.mgmt.updateUi = function(entityName, name, id) { + switch (entityName) { + case 'account': + explorer.mgmt.data.accountId = id; + explorer.mgmt.data.accountName = name; + $('#account').val(explorer.mgmt.data.accountName); + explorer.mgmt.loadWebproperties(); + break; + + case 'webproperty': + explorer.mgmt.data.webpropertyId = id; + explorer.mgmt.data.webpropertyName = name; + $('#webproperty').val(explorer.mgmt.data.webpropertyName); + explorer.mgmt.loadProfiles(); + break; + + case 'profile': + explorer.mgmt.data.profileId = id; + explorer.mgmt.data.profileName = name; + $('#profile').val(explorer.mgmt.data.profileName); + explorer.mgmt.updateIds(explorer.mgmt.data.profileId); + explorer.mgmt.store(explorer.mgmt.data); + break; + } +}; + + +/** + * Updates the Ids field for the currently selected profile. + * @param {String} profileId The profile Id. + */ +explorer.mgmt.updateIds = function() { + $('#ids').val('ga:' + explorer.mgmt.data.profileId).keyup(); +}; + + +/** + * Displays an error message to the user. + * @param {Object} resultError The error to display. + */ +explorer.mgmt.displayError = function(resultError) { + var errorMsg = resultError.code + ' : ' + resultError.message; + explorer.coreapi.displayErrorMessage(errorMsg); +}; + + +/** + * Stores management data if storage is available. + * @param {Objet} data JSON data to store. + */ +explorer.mgmt.store = function(data) { + if (localStorage && JSON) { + localStorage.setItem(explorer.mgmt.STORAGE_KEY, JSON.stringify(data)); + } +}; + + +/** + * Load previously stored management data. + * @param {String} userId The Id of the user. + * @return {Object} JSON previously stored JSON data. + */ +explorer.mgmt.load = function() { + if (localStorage && JSON) { + return JSON.parse(localStorage.getItem(explorer.mgmt.STORAGE_KEY)); + } +}; + diff --git a/assets/javascript/explorer/ga-pubsub.js b/assets/javascript/explorer/ga-pubsub.js new file mode 100644 index 000000000..e5884303c --- /dev/null +++ b/assets/javascript/explorer/ga-pubsub.js @@ -0,0 +1,76 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global explorer */ + +/** + * Namespace for pubsub config object + */ +explorer.pubsub = explorer.pubsub || {}; + +/** + * Status for authorized. + */ +explorer.pubsub.HAS_AUTH = 'isAuthorized'; + + +/** + * Status for not authorized. + */ +explorer.pubsub.HAS_NO_AUTH = 'isNotAuthorized'; + + +/** + * Status for libraries successfult loaded. + */ +explorer.pubsub.LIBS_LOADED = 'libsLoaded'; + + +/** + * Status for a query updated. + */ +explorer.pubsub.DATA_QUERY_UPDATE = 'dataQueryUpdate'; + + +/** + * Config object + */ +explorer.pubsub.map = {}; + +/** + * Subscribes. + * @param {String} key The name of the function. + * @param {Object} func The function to subscribe to. + */ +explorer.pubsub.subscribe = function(key, func) { + if (!explorer.pubsub.map[key]) { + explorer.pubsub.map[key] = []; + } + explorer.pubsub.map[key].push(func); +}; + + +/** + * Publish + * @param {String} key The name of function to publish. + */ +explorer.pubsub.publish = function(key) { + if (explorer.pubsub.map[key] && explorer.pubsub.map[key].length) { + for (var i = 0, func; func = explorer.pubsub.map[key][i]; ++i) { + func(); + } + } +}; + diff --git a/assets/javascript/explorer/ga-util.js b/assets/javascript/explorer/ga-util.js new file mode 100644 index 000000000..fe78d66ed --- /dev/null +++ b/assets/javascript/explorer/ga-util.js @@ -0,0 +1,182 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global google */ + +// Namespaces. +var explorer = explorer || {}; + +/** + * Config object for util. + */ +explorer.util = explorer.util || {}; + + +/** + * Creates a DataTable object using a GA responseonse. + * @param {Object} results A Core Reporting API response. + * @return {Object} A Google DataTable object populated + * with the GA response data. + */ +explorer.util.getDataTableFromCoreApi = function(results) { + + var dataTable = new google.visualization.DataTable(); + + if (!(results.rows && results.rows.length)) { + dataTable.addColumn('string', '(none)'); + dataTable.addRows(1); + dataTable.setCell(0, 0, 'no results found'); + return dataTable; + } + + explorer.util.addColumns(dataTable, results); + explorer.util.addRows(dataTable, results); + explorer.util.addDateFormatter(dataTable, results); + return dataTable; +}; + +/** + * Looks at the response column headers to set names and types for each column. + * @param {Object} dataTable A Google DataTable. + * @param {Object} results A Core Reporting API response. + */ +explorer.util.addColumns = function(dataTable, results) { + for (var i = 0, header; header = results.columnHeaders[i]; ++i) { + var dataType; + + if (header.name == 'ga:date') { + dataType = 'date'; + } else if (header.columnType == 'DIMENSION') { + dataType = 'string'; + } else { + dataType = 'number'; + } + dataTable.addColumn(dataType, header.name); + } +}; + + +/** + * Looks at the row values and performs conversions before setting output cells. + * @param {Object} dataTable A Google DataTable. + * @param {Object} results A Core Reporting API response. + */ +explorer.util.addRows = function(dataTable, results) { + dataTable.addRows(results.rows.length); + + for (var i = 0, row; row = results.rows[i]; ++i) { + for (var j = 0, cellValue; cellValue = row[j]; ++j) { + + var header = results.columnHeaders[j]; + var tableValue = cellValue; + var dataType = header.dataType; + + // Perform conversions if necessary. + if (header.name == 'ga:date') { + tableValue = explorer.util.getDateObj(cellValue); + + } else if (dataType == 'INTEGER') { + tableValue = parseInt(cellValue, 10); + + } else if (dataType == 'CURRENCY') { + tableValue = parseFloat(cellValue); + + } else if (dataType == 'PERCENT' || dataType == 'TIME' || + dataType == 'FLOAT') { + tableValue = Math.round(cellValue * 100) / 100; + } + + dataTable.setCell(i, j, tableValue); + } + } +}; + + +/** + * Formats date values. + * @param {Object} dataTable A Google DataTable. + * @param {Object} results A Core Reporting API response. + */ +explorer.util.addDateFormatter = function(dataTable, results) { + var dateFormatter = new google.visualization.DateFormat({ + pattern: 'MM-dd-yyyy' + }); + + for (var i = 0, header; header = results.columnHeaders[i]; ++i) { + if (header.name == 'ga:date') { + dateFormatter.format(dataTable, i); + } + } +}; + + +/** + * Transforms the date string passed back from the GA API into a JavaScript + * Date object. + * @param {string} gaDate A date string passed back by the GA API. + * @return {Date} a JS Date Object representing the string passde to this + * method. + */ +explorer.util.getDateObj = function(gaDate) { + var date = new Date(); + var year = parseInt(gaDate.substring(0, 4), 10); + var month = parseInt(gaDate.substring(4, 6), 10) - 1; + var day = parseInt(gaDate.substring(6, 8), 10); + date.setFullYear(year); + date.setMonth(month, day); + return date; +}; + + +/** + * Binds a method to it's object. + * @param {Object} object The main object to bind to. + * @param {Object} method The method to bind to the object. + * @return {Function} the function passed in boound to the object parameter. + */ +explorer.util.bindMethod = function(object, method) { + return function() { + return method.apply(object, arguments); + }; +}; + + +/** + * HTML escapes the input string by converting the &, <, > and " characters + * to their HTML escaped version. Taken from the code in the closure string + * library. + * @param {String} str The string to convert. + * @return {String} The escaped string. + */ +explorer.util.htmlEscape = function(str) { + var allRe = /[&<>\"]/; + if (!allRe.test(str)) { + return str; + } + + if (str.indexOf('&') != -1) { + str = str.replace(/&/g, '&'); + } + if (str.indexOf('<') != -1) { + str = str.replace(/') != -1) { + str = str.replace(/>/g, '>'); + } + if (str.indexOf('"') != -1) { + str = str.replace(/"/g, '"'); + } + return str; +}; diff --git a/assets/javascript/explorer/ga-values.js b/assets/javascript/explorer/ga-values.js new file mode 100644 index 000000000..a218149c5 --- /dev/null +++ b/assets/javascript/explorer/ga-values.js @@ -0,0 +1,231 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +//namespace for the Explorer +var explorer = explorer || {}; + + +/** + * Google Analytics Service Name. + */ +explorer.SERVICE_NAME = 'query_explorer_v2.0'; + + +/** + * Core Reporting API endpoint. + */ +explorer.CORE_REPORTING_API = 'https://www.googleapis.com/analytics/v3/data/ga'; + + +/** + * Custom Segment name. + */ +explorer.customSegName = 'Custom Segments'; + + +/** + * Custom Segment UI labels. + */ +explorer.customSegVals = [ + 'Authorize to access your segments', + 'Click to list your segments' +]; + + +/** + * The URL to the core reporting api reference docs. + */ +explorer.coreapiRefUrl = '//developers.google.com/analytics/devguides/reporting/' + + 'core/v3/reference'; + + +/** + * The URL to the core reporting dimensions & metrics list. + */ +explorer.DIMS_METS_URL = '//developers.google.com/analytics/devguides/reporting/' + + 'core/dimsmets'; + + +/** + * This object holds all the definitions of the parameters in the query object + */ +explorer.queryConfig = { + 'ids': { + 'size': 125, + 'req': true, + 'help': 'The namespaced view (profile) ID of the view (profile) from ' + + 'which to request data. Use the view (profile) selector above ' + + 'to find this value.', + 'example': 'ga:1174 where 1174 is your view (profile) ID.', + 'anchor': '#ids'}, + 'dimensions': { + 'size': 365, + 'req': false, + 'help': 'The dimension data to be retrieved from the API. A single ' + + 'request is limited to a maximum of 7 dimensions.', + 'example': 'ga:source', + 'anchor': '#dimensions'}, + 'metrics': { + 'size': 365, + 'req': true, + 'help': 'The metrics data to be retrieved from the API. A single ' + + 'request is limited to a maximum of 10 metrics.', + 'example': 'ga:visits', + 'anchor': '#metrics'}, + 'segment': { + 'size': 365, + 'req': false, + 'help': 'Specifies a subset of visits based on either an expression or a ' + + 'filter. The subset of visits matched happens before dimensions ' + + 'and metrics are calculated.', + 'example': 'Dynamic: segment=dynamic::ga:source=~twitter
By ' + + 'ID: segment=gaid::-3', + 'anchor': '#segment'}, + 'filters': { + 'size': 325, + 'req': false, + 'help': 'Specifies a subset of all data matched in analytics. This tool ' + + 'automatically URI encodes the parameter.', + 'example': 'Equals: filters=ga:country==Canada
Regular ' + + 'Expression: filters=ga:city=~^New.*', + 'anchor': '#filters'}, + 'sort': { + 'size': 325, + 'req': false, + 'help': 'The order and direction to retrieve the results. Can have ' + + 'multiple dimensions and metrics.', + 'example': 'Ascending: ga:visits
Descending: -ga:visits', + 'anchor': '#sort'}, + 'start-date': { + 'size': 125, + 'req': true, + 'help': 'Beginning date to retrieve data in format YYYY-MM-DD.', + 'example': '2009-04-20', + 'anchor': '#startDate'}, + 'end-date': { + 'size': 125, + 'req': true, + 'help': 'Final date to retrieve data in format YYYY-MM-DD.', + 'example': '2009-04-21', + 'anchor': '#endDate'}, + 'start-index': { + 'size': 125, + 'req': false, + 'help': 'Use this parameter to request more rows from the API. For ' + + 'example if your query matches 100,000 rows, the API will only ' + + 'return a subset of them and you can use this parameter to ' + + 'request different subsets. The index starts from 1 and the ' + + 'default is 1.', + 'example': '50001', + 'anchor': '#startIndex'}, + 'max-results': { + 'size': 125, + 'req': false, + 'help': 'Maximum number of results to retrieve from the API. The ' + + 'default is 1,000 but can be set up to 10,000.', + 'example': '500', + 'anchor': '#maxResults'} +}; + + +/** + * An Object to hold pre canned queries + */ +explorer.cannedQueries = { + 'Visits and pageviews over time': { + 'dimensions': 'ga:date', + 'metrics': 'ga:visits,ga:pageviews', + 'sort': '', + 'filters': ''}, + 'Visits by traffic source': { + 'dimensions': 'ga:source,ga:medium', + 'metrics': 'ga:visits', + 'sort': '-ga:visits', + 'filters': ''}, + 'Visits by browser (including mobile phones)': { + 'dimensions': 'ga:browser', + 'metrics': 'ga:visits', + 'sort': '-ga:visits', + 'filters': ''}, + 'Language by country': { + 'dimensions': 'ga:language,ga:country', + 'metrics': 'ga:visits', + 'sort': '-ga:visits', + 'filters': ''}, + 'Top pages by pageviews': { + 'dimensions': 'ga:pagePath,ga:pageTitle', + 'metrics': 'ga:pageviews', + 'sort': '-ga:pageviews', + 'filters': ''}, + 'Top search refinements': { + 'dimensions': 'ga:searchKeyword,ga:searchKeywordRefinement,' + + 'ga:searchDestinationPage', + 'metrics': 'ga:searchRefinements', + 'sort': '-ga:searchRefinements', + 'filters': ''}, + 'First 3 days of data in view (profile)': { + 'dimensions': 'ga:date', + 'metrics': 'ga:visits', + 'sort': 'ga:date', + 'filters': 'ga:visits>1', + 'start-date': '2005-01-01', + 'max-results': '3'} +}; + + +/** + * Object to hold all segents drop down help data. + */ +explorer.segmentsHelp = { + 'Dynamic Segments': { + 'help': 'Allows the creation of segments on the fly.', + 'values': { + 'Write your own Segment': 'dynamic::' + } + }, + 'Custom Segments': { + 'help': 'Custom segments are built through the Google Analytics user ' + + 'interface and may be referenced through the API by ID. All ' + + 'Custom segment IDs are positive. Custom segments are also ' + + 'defined per user meaning each authorized user may have a ' + + 'different set of Custom Segments.', + 'values': { + 'Authorize to access your own segments': '' + // Dynamically added based on auth status or if account data has been + // retrieved. See Explorer.displayLogin, Explorer.displayLogout, + // explorer.SegmentsDropdownUpdateValues for details. + } + }, + 'Default Segments': { + 'help': 'Default segments are pre-built and defined for all users. ' + + 'Default segment IDs are negative.', + 'values': { + 'All Visits': 'gaid::-1', + 'New Visitors': 'gaid::-2', + 'Returning Visitors': 'gaid::-3', + 'Paid Search Traffic': 'gaid::-4', + 'Non-paid Search Traffic': 'gaid::-5', + 'Search Traffic': 'gaid::-6', + 'Direct Traffic': 'gaid::-7', + 'Referral Traffic': 'gaid::-8', + 'Visits with Conversions': 'gaid::-9', + 'Visits with Transactions': 'gaid::-10', + 'Mobile and Tablet Traffic': 'gaid::-11', + 'Non-bounce Visits': 'gaid::-12', + 'Tablet traffic': 'gaid::-13', + 'Mobile Traffic': 'gaid::-14' + } + } +}; diff --git a/assets/javascript/explorer/index.js b/assets/javascript/explorer/index.js new file mode 100644 index 000000000..c27f7f33f --- /dev/null +++ b/assets/javascript/explorer/index.js @@ -0,0 +1,33 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/* global explorer */ + +var jQuery = require('jquery'); + +module.exports = { + init: function() { + // The legacy query explorer code requires jQuery to be global. + window.jQuery = window.$ = jQuery; + + // The `explorer` variable isn't defined on the page yet, so we have to wait. + // Yeah, this isn't ideal. + // TODO(philipwalton): refactor legacy query explorer JS to use modules. + jQuery(function() { + explorer.selfUrl = location.protocol + '//' + location.host + location.pathname; + explorer.run(); + }); + } +}; diff --git a/assets/javascript/header.js b/assets/javascript/header.js new file mode 100644 index 000000000..fc43bd74e --- /dev/null +++ b/assets/javascript/header.js @@ -0,0 +1,56 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +var $ = require('jquery'); + +module.exports = { + + init: function() { + this.addOpenHandler(); + }, + + addOpenHandler: function() { + $(document).on('touchend.header click.header', + '#header-user', function(event) { + + event.preventDefault(); + $(document).off('.header'); + this.open(); + this.addCloseHandler(); + }.bind(this)); + }, + + addCloseHandler: function() { + $(document).on('touchend.header click.header', function(event) { + + // Only close if the user didn't click inside of #header-auth. + if (!$(event.target).closest('#header-auth').length) { + event.preventDefault(); + $(document).off('.header'); + this.close(); + this.addOpenHandler(); + } + }.bind(this)); + }, + + open: function() { + $('#header').addClass('is-open'); + }, + + close: function() { + $('#header').removeClass('is-open'); + } + +}; diff --git a/assets/javascript/highlighter.js b/assets/javascript/highlighter.js new file mode 100644 index 000000000..119b52dc8 --- /dev/null +++ b/assets/javascript/highlighter.js @@ -0,0 +1,34 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +var $ = require('jquery'); +var Highlight = require('highlight.js/lib/highlight'); +var hljs = new Highlight(); + +hljs.registerLanguage('xml', + require('highlight.js/lib/languages/xml.js')); + +hljs.registerLanguage('javascript', + require('highlight.js/lib/languages/javascript.js')); + +module.exports = { + + highlight: function(selector) { + $(selector).each(function() { + hljs.highlightBlock(this); + }); + } + +}; diff --git a/assets/javascript/index.js b/assets/javascript/index.js new file mode 100644 index 000000000..c7289a888 --- /dev/null +++ b/assets/javascript/index.js @@ -0,0 +1,45 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +require('svg4everybody'); + +var accountExplorer = require('./account-explorer'); +var analytics = require('./analytics'); +var embedApi = require('./embed-api'); +var explorer = require('./explorer'); +var header = require('./header'); +var highlighter = require('./highlighter'); +var router = require('router'); +var sidebar = require('./sidebar'); + + +// Initiaze the header functionality. +header.init(); + +// Initiaze the sidebar functionality. +sidebar.init(); + +// Highlight code blocks. +highlighter.highlight('pre'); + +// Setup Google Analytics tracking. +analytics.track(); + +// Add routes to initialize code based on the page the user is on. +router() + .case('/explorer/', explorer.init) + .case('/embed-api//', embedApi.init) + .case('/account-explorer/', accountExplorer.init) + .match(); diff --git a/assets/javascript/sidebar.js b/assets/javascript/sidebar.js new file mode 100644 index 000000000..764c6d6d8 --- /dev/null +++ b/assets/javascript/sidebar.js @@ -0,0 +1,61 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +var $ = require('jquery'); + +module.exports = { + + init: function() { + this.addOpenHandler(); + }, + + addOpenHandler: function() { + $(document).on('touchend.sidebar click.sidebar', + '#header-menu', function(event) { + + event.preventDefault(); + $(document).off('.sidebar'); + this.open(); + this.addCloseHandler(); + }.bind(this)); + }, + + addCloseHandler: function() { + $(document).on('touchend.sidebar click.sidebar', function(event) { + + var $target = $(event.target); + + // Close of the user clicked the close icon or clicked + // outside of the sidebar. + if ($target.closest('#sidebar-close').length || + !$target.closest('#sidebar').length) { + + event.preventDefault(); + $(document).off('.sidebar'); + this.close(); + this.addOpenHandler(); + } + }.bind(this)); + }, + + open: function() { + $(document.body).addClass('is-expanded'); + }, + + close: function() { + $(document.body).removeClass('is-expanded'); + } + +}; diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..23c553a2966ca4cecf146093f33d8114b4f1e368 GIT binary patch literal 8348 zcmeI0du&tJ8Ng3Vwv|ewX4Hu@my&|vCD%DN@CLnxyptBT_%HjatoYr7%N3zGPed#@ckvA><;HWecDU4&2}*2(h%gm&WgCftWj zkQfW;&mXr@0S&(csd+cjaImbXSy=NC<10}z(efGwgi=;B$dt=HkKYCvp-#3KX+qIu zxx$>zcwk+N=c%1^J9)sO44lmS0##~wzU(43f>wW-p_YXwj>s>3{gHI*^oo1lmJ!X*bw{3UBAKRut zUh5Uy4_94IIkdxC^v{_g%FjuEI+f&;9KQ3i+nK7pU_RivFjP_DTl-&gP_qr$nD=M{ z@z;C3#y5Jsh77svGQ4u$ZX)t}=e52{#Xvk;4qIxNh86kR$OhCAie%&e`U{r{ACQZ@ z-)1#sItef{2L za&U;nm+_lo@lbR7vat&^EcECsH)uSnhlht@etsV4LE5B`j#GW*iur~}xpYlTtc;FC{nl|LK^miZ0y3WU>MIM zmc}94VzEFx9?#&?4l+h;ggzvOeCI$ob=`tBp*&EtirH2xU z4a#KB)IMa{_YdYrnxq>-DrrQ>rfpYe8@|Nc-oHnG*L(HR$}d4Eo2&X@o1~9l@%@W) zU{%rv$`tBAOHJH+?zcv7`!T~x;=<#7@4R5T^5$-%Pz-NAYt+5{d;>R+9W24y&`;ZkZqFGQ6_)<35Z_$5V#ga#=N9985-M0KR*fl@h4M0BxWvbYQr6t zULtYBAMJ%iU>x|?U8z_Zyv1jg_VcZ^kO)pd_)jk`_~2MHZmybbloW?l)lnMrb~TAX zV&%#e+VLvM4!%js+%B6}N!=udFlN5Jv;yQm0sdW({6ny+{{$_b`%pI&q3%#p3R?q( z%3@zpafPo4-GA}ErIfU@j?gpfdgeyI);;S-otz(GefQbXvG3J6hbwD_0*YOuqb1V8 zpQm{(oT|g$!tcw;Ck6l>=mo$z0J@0f0^U0{x?+mD8}QB{9yV7qQ;&$5^%*fb@qUB& zX(O<{D-aZ493K;1xH%!}9+}vt8Sshs4os9)d132glTa=lIJv}MJyU_Y!ZFl62j9@l zggg2y{y~c&Vm0cMa@}r@bbn?HR4Sa|66p;nlMl_6D%_%EjCNRq)NBvx!R!t`@zUoW zKV#O#EhZy4>~?VU+rfg@_W_4Kt~zS<|3JjVMcZ#exy;pDUypq|xjpD&0#H{BHgrvM zI=z9nnTN~NCX?mf@DOU;!82-#gXGsw5CSSf22lJ>u8duE&igGuZq4lVZf*LH2%QqOqkv@O{w`Y}q~yWm0EP zeSP~Hau49ZBU@&hWwH5YG0dnGVN1^iztQFh>rIvj5$iQ;q^nyuSuXo`U~{E8DpuIS zA{kR5oC9o=_>jhfRX@QTs1KRm{@F31 zFKP1!w?51@R^I~kA%H*B0W^sKnyVIsv`_2;=zbUGR9pOTqUhV{{^UH=RQ2@S?`uaQ zEy`)Gsd}1IEedW&4lAe0Sg5h`nQXqaZ}RyEzX{FT?hmF3>0_QQT1V~jI$wc&1@aZh ZS0G=3d706zJ{{SaIO|Jj| literal 0 HcmV?d00001 diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 000000000..824b90db6 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,149 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var browserify = require('browserify'); +var buffer = require('vinyl-buffer'); +var cleancss = require('gulp-cleancss'); +var concat = require('gulp-concat'); +var gulp = require('gulp'); +var gulpIf = require('gulp-if'); +var inline = require('rework-plugin-inline'); +var jshint = require('gulp-jshint'); +var path = require('path'); +var prefix = require('gulp-autoprefixer'); +var rework = require('gulp-rework'); +var source = require('vinyl-source-stream'); +var sourcemaps = require('gulp-sourcemaps'); +var suit = require('rework-suit'); +var uglify = require('gulp-uglify'); + +function isProd(transform) { + // Assume prod unless NODE_ENV starts with 'dev'. + return gulpIf(!/^dev/.test(process.env.NODE_ENV), transform); +} + +gulp.task('css', function() { + gulp.src('./assets/css/main.css') + .pipe(rework(suit(), inline('./assets/images'), {sourcemap: true})) + .pipe(prefix('last 2 version', '> 2%', 'ie 9')) + .pipe(isProd(cleancss({keepSpecialComments: 0}))) + .pipe(gulp.dest('./public/css')); +}); + +gulp.task('images', function() { + gulp.src('./assets/images/**/*') + .pipe(gulp.dest('./public/images')); +}); + +gulp.task('lint', function() { + return gulp.src([ + './gulpfile.js', + './assets/javascript/**/*.js' + ]) + .pipe(jshint({ + browser: true, + boss: true, + expr: true, + node: true, + scripturl: true, + quotmark: 'single' + })) + .pipe(jshint.reporter('default')) + .pipe(jshint.reporter('fail')); +}); + +gulp.task('javascript:browserify', function() { + browserify('./assets/javascript', {debug: true}) + .bundle() + .pipe(source('bundle.js')) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(isProd(uglify())) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest('./public/javascript/')); +}); + +// TODO(philipwalton): refactor the explorer to use browserify. +gulp.task('javascript:explorer', function() { + gulp.src([ + './assets/javascript/explorer/ga-values.js', + './assets/javascript/explorer/ga-dropdown.js', + './assets/javascript/explorer/ga-dataquery.js', + './assets/javascript/explorer/ga-util.js', + './assets/javascript/explorer/ga-mgmt.js', + './assets/javascript/explorer/ga-fun.js', + './assets/javascript/explorer/ga-coreapi.js', + './assets/javascript/explorer/ga-loader.js', + './assets/javascript/explorer/ga-auth.js', + './assets/javascript/explorer/ga-pubsub.js', + './assets/javascript/explorer/ga-app.js', + './assets/javascript/explorer/ga-metadata.js' + ]) + .pipe(sourcemaps.init()) + .pipe(concat('explorer.js')) + .pipe(isProd(uglify())) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest('./public/javascript')); +}); + +gulp.task('javascript:static', function() { + // Utilties. + gulp.src([ + 'node_modules/moment/min/moment.min.js', + 'node_modules/chart.js/Chart.min.js' + ]) + .pipe(gulp.dest('./public/javascript')); + + // Embed API demo modules. + + // TODO(philipwalton): the following two should be combined into a single + // stream once this issue is solved: + // https://github.com/floridoo/gulp-sourcemaps/issues/37 + gulp.src('./assets/javascript/embed-api/active-users.js') + .pipe(sourcemaps.init()) + .pipe(concat('active-users.js')) + .pipe(uglify()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest('./public/javascript/embed-api')); + + gulp.src('./assets/javascript/embed-api/date-range-selector.js') + .pipe(sourcemaps.init()) + .pipe(concat('date-range-selector.js')) + .pipe(uglify()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest('./public/javascript/embed-api')); + + browserify('./assets/javascript/embed-api/view-selector2', {debug: true}) + .bundle() + .pipe(source('view-selector2.js')) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(isProd(uglify())) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest('./public/javascript/embed-api')); +}); + +gulp.task('javascript', [ + 'javascript:browserify', + 'javascript:static', + 'javascript:explorer', +]); + +gulp.task('watch', ['javascript', 'css', 'images'], function() { + gulp.watch('./assets/css/**/*.css', ['css']); + gulp.watch('./assets/images/**/*', ['images']); + gulp.watch('./assets/javascript/**/*.js', ['javascript']); +}); + +gulp.task('build', ['lint', 'javascript', 'css', 'images']); diff --git a/index.yaml b/index.yaml new file mode 100644 index 000000000..8e6046de9 --- /dev/null +++ b/index.yaml @@ -0,0 +1,12 @@ +indexes: + +# AUTOGENERATED + +# This index.yaml is automatically updated whenever the dev_appserver +# detects that a new type of query is run. If you want to manage the +# index.yaml file manually, remove the above marker line (the line +# saying "# AUTOGENERATED"). If you want to manage some indexes +# manually, move them above the marker line. The index.yaml file is +# automatically uploaded to the admin console when you next deploy +# your application using appcfg.py. + diff --git a/lib/__init__.py b/lib/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/app.py b/lib/app.py new file mode 100644 index 000000000..5a94d1b43 --- /dev/null +++ b/lib/app.py @@ -0,0 +1,37 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import webapp2 + +from webapp2_extras.routes import RedirectRoute +from lib.redirects import EmbedApiController +from lib.controllers.base import BaseController +from lib.controllers.explorer_csv import ExplorerCsvController + +router = webapp2.WSGIApplication([ + + # Redirects + (r'/demos/embed-api.*', EmbedApiController), + + # Main routes + (r'/explorer/csvhandler.*', ExplorerCsvController), + RedirectRoute(r'/', + handler=BaseController, name='Home', strict_slash=True), + RedirectRoute(r'//', + handler=BaseController, name='Project', strict_slash=True), + RedirectRoute(r'///', + handler=BaseController, name='Page', strict_slash=True), + +], debug=False) diff --git a/lib/controllers/__init__.py b/lib/controllers/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/controllers/base.py b/lib/controllers/base.py new file mode 100644 index 000000000..5b30eeb22 --- /dev/null +++ b/lib/controllers/base.py @@ -0,0 +1,22 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import webapp2 +import lib.template as template + +class BaseController(webapp2.RequestHandler): + def get(self, project='index', page='index'): + html = template.render(project, page) + self.response.write(html) diff --git a/lib/controllers/explorer_csv.py b/lib/controllers/explorer_csv.py new file mode 100644 index 000000000..112f2ed70 --- /dev/null +++ b/lib/controllers/explorer_csv.py @@ -0,0 +1,58 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import cStringIO +import json +import logging +import lib.csv_writer as csv_writer +from google.appengine.api import urlfetch +from lib.controllers.base import BaseController + +class ExplorerCsvController(BaseController): + + def get(self): + uri = ('https://www.googleapis.com/analytics/v3/data/ga?' + + self.request.query_string) + result = urlfetch.fetch(url=uri, deadline=60) + + if result.status_code == 200: + + response = json.loads(result.content) + output = cStringIO.StringIO() + writer = csv_writer.GetTsvStringPrinter(output) + writer.Output(response) + + out = output.getvalue() + + decoding = out.decode('utf-8') + encoding = decoding.encode('utf-16') + self.OutputCsv16(encoding) + + output.close() + + else: + logging.error('there was an error') + + def OutputCsv16(self, tsv_body): + """Renders TSV content. + + Args: + tsv_body: The TSV content to output. + """ + self.response.headers['Content-Type'] = ( + 'application/vnd.ms-excel; charset=UTF-16LE') + self.response.headers['Content-Disposition'] = ( + 'attachment; filename=query_explorer.tsv') + self.response.out.write(tsv_body) diff --git a/lib/controllers/redirects.py b/lib/controllers/redirects.py new file mode 100644 index 000000000..613009994 --- /dev/null +++ b/lib/controllers/redirects.py @@ -0,0 +1,20 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import webapp2 + +class EmbedApiHandler(webapp2.RequestHandler): + def get(self): + return webapp2.redirect('/embed-api/', True) diff --git a/lib/csv_writer.py b/lib/csv_writer.py new file mode 100644 index 000000000..d1afd7574 --- /dev/null +++ b/lib/csv_writer.py @@ -0,0 +1,265 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Utility to convert a Data Export API reponse into TSV. + +This provides utitlites to both print TSV files to the standard output +as well as directly to a file. This logic handles all the utf-8 conversion. + + GetTsvFilePrinter: Returns an instantiated object to output to files. + GetTsvScreenPrinter: Returns an instantiated object to output to the screen. + UnicodeWriter(): Utf-8 encodes output. + ExportPrinter(): Converts the Data Export API response into tabular data. +""" + +__author__ = 'api.nickm@ (Nick Mihailovski)' + + +import codecs +import csv +import StringIO +import sys +import types + + +# A list of special characters that need to be escaped. +SPECIAL_CHARS = ('+', '-', '/', '*', '=') +# TODO(nm): Test leading numbers. + + +def GetTsvFilePrinter(file_name): + """Returns a ExportPrinter object to output to file_name. + + Args: + file_name: string The name of the file to output to. + + Returns: + The newly created ExportPrinter object. + """ + my_handle = open(file_name) + writer = UnicodeWriter(my_handle, dialect='excel-tab') + return ExportPrinter(writer) + + +def GetTsvScreenPrinter(): + """Returns a ExportPrinter object to output to std.stdout.""" + writer = UnicodeWriter(sys.stdout, dialect='excel-tab') + return ExportPrinter(writer) + + +def GetTsvStringPrinter(f): + """Returns a ExportPrinter object to output to std.stdout.""" + writer = UnicodeWriter(f, dialect='excel-tab') + return ExportPrinter(writer) + + +# Wrapper to output to utf-8. Taken mostly / directly from Python docs: +# http://docs.python.org/library/csv.html +class UnicodeWriter(object): + """A CSV writer which uses the csv module to output csv compatible formats. + + Will write rows to CSV file "f", which is encoded in the given encoding. + """ + + def __init__(self, f, dialect=csv.excel, encoding='utf-8', **kwds): + # Redirect output to a queue + self.queue = StringIO.StringIO() + self.writer = csv.writer(self.queue, dialect=dialect, **kwds) + self.stream = f + self.encoder = codecs.getincrementalencoder(encoding)() + + # pylint: disable=g-bad-name + def writerow(self, row): + """Writes a CSV row. + + Args: + row: list The row to write to the CSV output. + """ + + self.writer.writerow([s.encode('utf-8') for s in row]) + # Fetch UTF-8 output from the queue ... + data = self.queue.getvalue() + data = data.decode('utf-8') + # ... and reencode it into the target encoding + data = self.encoder.encode(data) + # write to the target stream + self.stream.write(data) + # empty queue + self.queue.truncate(0) + + # pylint: disable=g-bad-name + def writerows(self, rows): + """Writes rows for CSV output. + + Args: + rows: list of rows to write. + """ + for row in rows: + self.writerow(row) + + +class ExportPrinter(object): + """Utility class to output a the data feed as tabular data.""" + + def __init__(self, writer): + """Initializes the class. + + Args: + writer: Typically an instance of UnicodeWriter. The interface for this + object provides two methods, writerow and writerow, which + accepts a list or a list of lists respectively and process them as + needed. + """ + self.writer = writer + + def Output(self, results): + """Outputs formatted rows of data retrieved from the Data Export API. + + This uses the writer object to output the data in the Data Export API. + + Args: + results: The response from the data export API. + """ + + if not results.get('rows'): + self.writer.writerow('No Results found') + + else: + self.OutputProfileName(results) + self.writer.writerow([]) + self.OutputContainsSampledData(results) + self.writer.writerow([]) + self.OutputQueryInfo(results) + self.writer.writerow([]) + + self.OutputHeaders(results) + self.OutputRows(results) + + self.writer.writerow([]) + self.OutputRowCounts(results) + self.OutputTotalsForAllResults(results) + + def OutputProfileName(self, results): + """Outputs the profile name along with the qurey.""" + profile_name = '' + info = results.get('profileInfo') + if info: + profile_name = info.get('profileName') + + self.writer.writerow(['Report For View (Profile): ', profile_name]) + + def OutputQueryInfo(self, results): + """Outputs the query used.""" + self.writer.writerow(['These query parameters were used:']) + + query = results.get('query') + for key, value in query.iteritems(): + if type(value) == types.ListType: + value = ','.join(value) + else: + value = str(value) + value = ExcelEscape(value) + self.writer.writerow([key, value]) + + def OutputContainsSampledData(self, results): + """Outputs whether the resuls have been sampled.""" + + sampled_text = 'do not' + if results.get('containsSampledData'): + sampled_text = 'do' + + row_text = 'These results %s contain sampled data.' % sampled_text + self.writer.writerow([row_text]) + + def OutputHeaders(self, results): + """Outputs all the dimension and metric names in order.""" + + row = [] + for header in results.get('columnHeaders'): + row.append(header.get('name')) + self.writer.writerow(row) + + def OutputRows(self, results): + """Outputs all the rows in the table.""" + + # Replace any first characters that have an = with '= + for row in results.get('rows'): + out_row = [] + for cell in row: + cell = ExcelEscape(cell) + out_row.append(cell) + self.writer.writerow(out_row) + + def OutputRowCounts(self, results): + """Outputs how many rows were returned vs rows that were matched.""" + + items = str(results.get('itemsPerPage')) + matched = str(results.get('totalResults')) + + output = [ + ['Rows Returned', items], + ['Rows Matched', matched] + ] + self.writer.writerows(output) + + def OutputTotalsForAllResults(self, results): + """Outputs the totals for all results matched by the query. + + This is not the sum of the values returned in the response. + This will align the metric totals in the same columns as + the headers are printed. The totals are stored as a dict, where the + key is the metric name and the value is the total. To align these + totals in the proper columns, a position index of the metric name + and it's position in the table is first created. Then the totals + are added by position to a row of empty strings. + + Args: + results: API Response from Core Reporting API. + """ + + # Create the metric position index. + metric_index = {} + headers = results.get('columnHeaders') + for index in range(0, len(headers)): + header = headers[index] + if header.get('columnType') == 'METRIC': + metric_index[header.get('name')] = index + + # Create a row of empty strings the same length as the header. + row = [''] * len(headers) + + # Use the position index to output the totals in the right columns. + totals = results.get('totalsForAllResults') + for metric_name, metric_total in totals.iteritems(): + index = metric_index[metric_name] + row[index] = metric_total + + self.writer.writerows([['Totals For All Rows Matched'], row]) + + +def ExcelEscape(input_value): + """Escapes the first character of a string if it is special in Excel. + + Args: + input_value: string The value to escape. + + Returns: + A string that has the first character escaped if it is special. + """ + if input_value and input_value[0] in SPECIAL_CHARS: + return "'" + input_value + + return input_value + diff --git a/lib/redirects.py b/lib/redirects.py new file mode 100644 index 000000000..319a6290b --- /dev/null +++ b/lib/redirects.py @@ -0,0 +1,20 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import webapp2 + +class EmbedApiController(webapp2.RequestHandler): + def get(self): + return webapp2.redirect('/embed-api/', True) diff --git a/lib/template.py b/lib/template.py new file mode 100644 index 000000000..fddbd85d0 --- /dev/null +++ b/lib/template.py @@ -0,0 +1,100 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import jinja2 +import os.path +import yaml + +JINJA_ENVIRONMENT = jinja2.Environment( + loader=jinja2.FileSystemLoader('templates'), + extensions=['jinja2.ext.autoescape'], + autoescape=True) + +# This only needs to be loaded once. +file = open('meta.yaml') +data = yaml.load(file.read()) +file.close() + + +# Generate the path data from the project and page slugs. +for project in data['projects']: + project['path'] = '/' + project['slug'] + '/' + if 'pages' in project: + for page in project['pages']: + page['path'] = project['path'] + page['slug'] + '/' + + +# Set environment data if it's not already present. +if not 'env' in data: + if (os.environ['SERVER_NAME'].rfind('googleplex.com') > -1 or + os.environ['SERVER_NAME'].rfind('localhost') > -1 or + os.environ['SERVER_NAME'].rfind('corp.google.com') > -1): + data['env'] = 'development' + else: + data['env'] = 'production' + + +# Group all demos together +data['demos'] = [i for i in data['projects'] if i['type'] == 'demo'] + + +# Group all tools together +data['tools'] = [i for i in data['projects'] if i['type'] == 'tool'] + + +def __get_project(project): + if project == 'index': + return { + 'title': data['title'], + 'slug': data['slug'], + 'path': data['path'], + } + else: + return [i for i in data['projects'] if i['slug'] == project][0] + + +def __get_page(project, page): + project = __get_project(project) + + if page == 'index': + return { + 'path': project['path'], + 'slug': project['slug'] + } + else: + return [i for i in project['pages'] if i['slug'] == page][0] + +def render(project='index', page='index'): + try: + template_data = { + 'site': data, + 'project': __get_project(project), + 'page': __get_page(project, page) + } + + if project == 'index': + template_file = 'index.html' + else: + template_file = project + '/' + page + '.html' + + template = JINJA_ENVIRONMENT.get_template(template_file) + return template.render(template_data) + except: + template = JINJA_ENVIRONMENT.get_template('404.html') + return template.render({ + 'site': data, + 'project': None, + 'page': None + }) diff --git a/meta.yaml b/meta.yaml new file mode 100644 index 000000000..2ee031998 --- /dev/null +++ b/meta.yaml @@ -0,0 +1,106 @@ +title: Google Analytics Tools and Demos +slug: '' +path: '/' +tracking_id: UA-41425441-5 +client_id: 793177639245-olst43lspv93vkoql0b9l26hmpf9kfmv.apps.googleusercontent.com + +# Google Analytics tech tags. Demos and tools should tag themselves with +# one or more of these to make tech more discoverable. +tech: + analyticsjs: + name: analytics.js + url: https://developers.google.com/analytics/devguides/collection/analyticsjs/ + core_reporting_api: + name: Core Reporting API + url: https://developers.google.com/analytics/devguides/reporting/core/ + ecjs: + name: Enhanced Ecommerce (ec.js) + url: https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce + embed_api: + name: Embed API + url: https://developers.google.com/analytics/devguides/reporting/embed/ + management_api: + name: Management API + url: https://developers.google.com/analytics/devguides/config/mgmt/ + mcf_reporting_api: + name: MCF Reporting API + url: https://developers.google.com/analytics/devguides/reporting/mcf/ + measurement_protocol: + name: Measurement Protocol + url: https://developers.google.com/analytics/devguides/collection/protocol/ + metadata_api: + name: Metadata API + url: https://developers.google.com/analytics/devguides/reporting/metadata/ + provisioning_api: + name: Provisioning API + url: https://developers.google.com/analytics/devguides/config/provisioning/ + real_time_reporting_api: + name: Real Time Reporting API + url: https://developers.google.com/analytics/devguides/reporting/realtime/ + +# Links represent external URLs that may frequently change. +# Setting them here makes it easier to update globally. +links: + devsite: http://developers.google.com/analytics + github: https://github.com/googleanalytics/ga-dev-tools + +projects: +- title: Account Explorer + type: tool + slug: account-explorer + status: new + tech: [embed_api, management_api] +- title: Dimensions & Metrics Explorer + type: tool + slug: dimensions-metrics-explorer + external: https://developers.google.com/analytics/devguides/reporting/core/dimsmets + tech: [metadata_api] +- title: Enhanced Ecommerce + type: demo + slug: enhanced-ecommerce + status: new + external: https://enhancedecommerce.appspot.com + tech: [analyticsjs, ecjs] +- title: Embed API + type: demo + slug: embed-api + pages: + - title: Basic Dashboard + slug: basic-dashboard + tech: [embed_api] + excerpt: 'This demos shows how to create a basic dashboard with a single timeline chart showing site traffic over the past week. You can update the chart to see data for any Google Analytics view you have access to.' + - title: Multiple Date Ranges + slug: multiple-date-ranges + tech: [embed_api] + excerpt: 'Displaying data side-by-side from multipe different date ranges is not currently possible through the Google Analytics website. This demo shows how easy it is to do this using the Embed API.' + - title: Multiple Views + slug: multiple-views + tech: [embed_api] + excerpt: 'Displaying two different views side-by-side is not currently possible through the Google Analytics website. This demo shows how easy it is to do this using the Embed API.' + - title: Interactive Charts + slug: interactive-charts + tech: [embed_api] + excerpt: 'This demo shows how you can build a dashboard that allows you to interactively explore your data. In this example you have a list of filters in one chart that you can click on and then a second chart will render showing just that filtered dataset.' + - title: Working with Custom Components + slug: custom-components + tech: [embed_api] + excerpt: 'The built-in components that ship with the Embed API are very nice, but sometimes you need to do more. This example shows how you can extend the Embed API to use your own custom components.' + - title: Third Party Visualizations + slug: third-party-visualizations + tech: [embed_api, real_time_reporting_api] + excerpt: 'The Embed API make it easy to query data and display it in a Google Chart. But it also allows you to access the raw data so you can display it however you want. This example uses the Chart.js visualization library.' +- title: Polymer Elements + type: demo + slug: polymer-elements + external: http://googlewebcomponents.github.io/google-analytics/components/google-analytics/demo.html + tech: [management_api, metadata_api] +- title: Query Explorer + type: tool + slug: explorer + tech: [core_reporting_api, management_api, metadata_api] +- title: Spreadsheet Add-on + type: tool + slug: spreadsheet-add-on + external: https://chrome.google.com/webstore/detail/google-analytics/fefimfimnhjjkomigakinmjileehfopp + tech: [core_reporting_api, management_api, mcf_reporting_api, metadata_api] + diff --git a/package.json b/package.json new file mode 100644 index 000000000..ef29a5c9b --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "ga-dev-tools", + "repository": { + "type": "git", + "url": "git://github.com/googleanalytics/ga-dev-tools.git" + }, + "scripts": { + "build": "./node_modules/.bin/gulp build", + "watch": "./node_modules/.bin/gulp watch" + }, + "devDependencies": { + "browserify": "^6.0.2", + "chart.js": "nnnick/Chart.js#v1.0.1-beta.4", + "gulp": "^3.8.7", + "gulp-autoprefixer": "0.0.8", + "gulp-cleancss": "^0.2.2", + "gulp-concat": "^2.4.0", + "gulp-if": "^1.2.5", + "gulp-jshint": "^1.8.5", + "gulp-rework": "^1.0.1", + "gulp-sourcemaps": "^1.2.4", + "gulp-uglify": "^1.0.1", + "gulp-util": "^3.0.0", + "highlight.js": "^8.2.0", + "javascript-api-utils": "googleanalytics/javascript-api-utils#0.1.0", + "jquery": "^2.1.1", + "lodash": "^2.4.1", + "moment": "^2.8.3", + "native-promise-only": "^0.7.6-a", + "normalize.css": "^3.0.1", + "rework-plugin-inline": "^1.0.1", + "rework-suit": "^4.0.0", + "router": "philipwalton/router#0.1.1", + "svg4everybody": "jonathantneal/svg4everybody#1.0.0", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.0.0" + } +} diff --git a/site/1-basic-dashboard.html b/site/1-basic-dashboard.html deleted file mode 100644 index d4abf03e8..000000000 --- a/site/1-basic-dashboard.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - Basic Dashboard — Embed API Demos - - - - - - - - - -
-
-

-
Last 7 days
-
-
-
-
- - - - - - - - - - - - - - - - - - - diff --git a/site/2-multiple-views.html b/site/2-multiple-views.html deleted file mode 100644 index f5404fc2d..000000000 --- a/site/2-multiple-views.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - Multiple Views — Embed API Demos - - - - - - - - - -
-
-

-
Last 30 days
-
-
-
- -
-

-
Last 30 days
-
-
-
-
- - - - - - - - - - - - - - - - - - - diff --git a/site/3-custom-components.html b/site/3-custom-components.html deleted file mode 100644 index d56b83315..000000000 --- a/site/3-custom-components.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - Using Custom Components — Embed API Demos - - - - - - - - - -
- -
-
-
- -
-
-

-
This Week
-
-
-
-
- -
-
-

-
Last Week
-
-
-
-
- -
- - - - - - - - - - - - - - - - - - - diff --git a/site/4-interactive-charts.html b/site/4-interactive-charts.html deleted file mode 100644 index cf3c45c6c..000000000 --- a/site/4-interactive-charts.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - Interactive Charts — Embed API Demos - - - - - - - - - -
-
-
-

Instructions

-
    -
  • Click on a row in the table below to see a timeline of sessions from that browser over the past week.
  • -
  • At any point you may pick a new view from the view selector and click "update" to interact with that view's data.
  • -
-
-
- -
-
- - -
-
- -
-
-

Top Browsers

-
-
-
-

Sessions Last Week

-
-
-
-
- - - - - - - - - - - - - - - - diff --git a/site/5-third-party-visualizations.html b/site/5-third-party-visualizations.html deleted file mode 100644 index 3ef367ff1..000000000 --- a/site/5-third-party-visualizations.html +++ /dev/null @@ -1,417 +0,0 @@ - - - - - - Third-Party Visualizations — Embed API Demos - - - - - - - - - -
-
-
-
-

- Active Users: - -

-
-
- -
-

This Week vs Last Week (Sessions)

-
-
    -
    - -
    -

    This Year vs Last Year (Sessions)

    -
    -
      -
      - -
      -

      Top Browsers

      -
      -
        -
        - -
        -

        Device Type

        -
        -
          -
          -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/6-pure-html-dashboards.html b/site/6-pure-html-dashboards.html deleted file mode 100644 index 42c30a496..000000000 --- a/site/6-pure-html-dashboards.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - Embed API Demos — Pure HTML Dashboards - - - - - - - - - - - - - - - - - -
          - - - -
          - -
          - - - - - - - - - - - -
          - -
          - - - - - diff --git a/site/assets/css/auth.css b/site/assets/css/auth.css deleted file mode 100644 index e30fd386b..000000000 --- a/site/assets/css/auth.css +++ /dev/null @@ -1,43 +0,0 @@ -.gapi-analytics-auth-styles-signinbutton { - display:inline-block; - background:#f7991c; - color:#fff; - width:200px; - border-radius:2px; - white-space:nowrap -} -.gapi-analytics-auth-styles-signinbutton:hover { - background:#ff9d27; - cursor:hand -} -.gapi-analytics-auth-styles-signinbutton-image { - background:url("//www.gstatic.com/analytics-api/access-analytics-iconv1.png") transparent 5px 50% no-repeat; - display:inline-block; - vertical-align:middle; - width:30px; - height:30px; - border-right:#db8321 1px solid -} -.gapi-analytics-auth-styles-signinbutton-buttonText { - display:inline-block; - vertical-align:middle; - padding-left:15px; - padding-right:15px; - font-size:12px; - font-weight:bold; - font-family:Roboto, arial, sans-serif -} -.gapi-analytics-auth-styles-userinfo { - width:200px; - height:30px; - font-size:12px; - font-weight:bold; - color:#0a5ae5; - font-family:Roboto, arial, sans-serif; - background:#f2f2f2; - text-align:center; - overflow:hidden; - text-overflow:ellipsis; - line-height:30px; - white-space:nowrap -} \ No newline at end of file diff --git a/site/assets/css/datachart.css b/site/assets/css/datachart.css deleted file mode 100644 index 02d2407fa..000000000 --- a/site/assets/css/datachart.css +++ /dev/null @@ -1,32 +0,0 @@ -.gapi-analytics-data-chart-table-styles-thr, -.gapi-analytics-data-chart-table-styles-tr { - font:inherit; - text-align:right -} -.gapi-analytics-data-chart-table-styles-thr { - font-weight:700 -} -.gapi-analytics-data-chart-table-styles-tr { - background:#f8f8f8 -} -.gapi-analytics-data-chart-table-styles-tr-hover { - background-color:#fffce8 -} -.gapi-analytics-data-chart-table-styles-tr-selected { - background-color:#e5f3f9 -} -.gapi-analytics-data-chart-table-styles-th { - border-bottom:1px solid #e8e8e8; - padding:12px 8px 3px!important -} -.gapi-analytics-data-chart-table-styles-td { - padding:8px 8px 7px!important -} -.gapi-analytics-data-chart-table-styles-th, -.gapi-analytics-data-chart-table-styles-td { - text-align:right -} -.gapi-analytics-data-chart-table-styles-th:first-child, -.gapi-analytics-data-chart-table-styles-td:first-child { - text-align:left -} diff --git a/site/assets/css/main.css b/site/assets/css/main.css deleted file mode 100644 index 9341c497a..000000000 --- a/site/assets/css/main.css +++ /dev/null @@ -1,438 +0,0 @@ -html { - background: #f4f2f0; -} -body { - color: #222; - font: 12px/1.4 'Open Sans', sans-serif; - margin: 0; - padding: 0; - text-rendering: optimizeLegibility; -} -body * { - /* Needed to override some Google Chart styles. */ - font-family: inherit!important; -} -section { - overflow: hidden; -} -ul { - list-style: square; - margin: 0; - padding: 0 0 0 1.5em; -} -i { - display: inline-block; - font: inherit; -} -a { - color: #f05721; - text-decoration: none; -} -a:hover { - text-decoration: underline; -} - -/** - * Hero Component - */ -.Hero { - background-color: #333; - box-sizing: border-box; - color: #fff; - font-kerning: auto; - line-height: 1; - padding: 3em 2em 4em; - text-align: center; - width: 100%; -} -.Hero-title { - font-size: 6em; - font-weight: 300; - letter-spacing: -0.02em; - margin: 0 0 .2em; - text-shadow: 0 0 1em rgba(0, 0, 0, 0.8); -} -.Hero-subtitle { - font-size: 1.8em; - font-weight: 300; - margin: 0; - opacity: 0.6; -} - -/** - * Partition Component - */ -.Partition { - background-color: transparent; -} -.Partition:nth-child(2n) { - background-color: #fff; -} -.Partition-content { - font-size: 1.25em; - margin: 0px auto; - max-width: 60em; - padding: 3em 2em; -} -.Partition h2 { - font-weight: 300; - font-size: 1.8em; - line-height: 1.1; - margin: 0 0 1em; - text-align: center; -} - -/** - * Demos - */ - -.Demos { - margin-left: -3em; - overflow: hidden; -} -.Demos-column { - box-sizing: border-box; - margin-bottom: -2em; - padding-left: 3em; -} -@media (min-width: 40em) { - .Demos-column { - float: left; - width: 50%; - } -} -.Demos h3 { - font-weight: 300; - font-size: 1.25em; - line-height: 1.2; - margin: 0 0 .667em; -} -.Demos a { - color: inherit; - display: block; - margin: 0 0 2em; - text-decoration: none; -} -.Demos a h3 { - color: #f05721; -} -.Demos a:hover h3 { - text-decoration: underline; -} -.Demos p { - font-size: .9em; - margin: 0; -} - -/** - * Next Steps Component - */ - -.NextSteps { - list-style: none; - margin: 0; - padding: 0; - text-align: center; -} -.NextSteps li { - line-height: 1.5; -} -@media (min-width: 48em) { - .NextSteps li { - border-left: 1px solid #aaa; - display: inline-block; - line-height: 1.5; - padding: 0 1em; - } - .NextSteps li:first-child { - border: 0; - } -} - -/** - * Banner Component - */ - -.Banner { - background-color: #333; - box-sizing: border-box; - color: #eee; - display: table; - margin-bottom: 1.5em; - padding: 1.2em 1.5em; - width: 100%; -} -.Banner-title { - display: table-cell; - font-size: 1.667em; - font-weight: 400; - margin: 0; - vertical-align: middle; - width: 100%; -} -.Banner-title a { - color: inherit; -} -.Banner-title em { - font-weight: 300; - font-size: .8em; - font-style: normal; - margin-left: .5em; - opacity: .6; -} -.Banner-auth { - color: #ccc; - display: table-cell; - font-size: 1.1em; - vertical-align: middle; - white-space: nowrap; -} - -/** - * Base Component - */ - -.Component { - background: #fff; - border: 1px solid #ccc; - display: none; - float: left; - margin: 0 0 1.5em 1.5em; - padding: 1.5em; -} -.is-authorized .Component { - display: block; -} - -/** - * Chart Component - */ - -.Chart {} -.Chart-title { - font: 300 1.4em/1.2 sans-serif; - margin: 0; -} -.Chart-subtitle { - font: 700 1.17em/1.2 sans-serif; - margin: 0.5em 0 0; -} -.Chart-controls { - border-top: 1px solid #ccc; - margin: 0 -1.5em -1.5em; - padding: 1.5em; - text-align: center; -} -.Chart--chartjs { - padding: 2em; -} -.Chart--chartjs .Chart-title { - font: 700 1.17em/1.2 sans-serif; - margin-bottom: 1.7em; - text-align: center; -} - -/** - * Legend Component - */ - -.Legend { - list-style: none; - margin: 0; - padding: 0; - text-align: center; -} -.Legend > li { - display: inline-block; - padding: 1em 1em 0 0; -} -.Legend > li > i { - display: inline-block; - height: 1em; - margin-right: .5em; - vertical-align: -.1em; - width: 1em; -} - -/** - * Viewpicker Component - */ - -.Viewpicker {} -.Viewpicker-item { - display: inline-block; - margin-right: 1em; -} -.Viewpicker-item:last-child { - margin-right: 0; -} -.Viewpicker-item > label { - font-weight: bold; - margin-right: 0.25em; -} -.Viewpicker-item select { - border: 1px solid #ccc; - border-radius: 4px; - box-sizing: border-box; - height: 34px; - line-height: 20px; - padding: 6px 12px; -} -.Viewpicker-item select:focus { - border-color: #4d90fe; - outline: 0; -} - - -/** - * Button component - */ - -.Button { - border: 1px solid #2F5BB7; - border-radius: 2px; - background: #498cf6; - color: #fff; - cursor: pointer; - font: inherit; - font-weight: bold; - margin-left: 1em; - min-width: 72px; - padding: 6px 12px; -} -.Button:focus { - box-shadow: inset 0 0 0 1px #FFF; - outline: none; -} - -/** - * Datepicker Component - */ - -.Datepicker {} -.Datepicker-item { - display: inline-block; - margin-right: 1em; -} -.Datepicker-item:last-child { - margin-right: 0; -} -.Datepicker-item label { - font-weight: bold; -} -.Datepicker-item input { - border: 1px solid #ccc; - border-radius: 4px; - box-sizing: border-box; - font: inherit; - font-weight: 400; - height: 34px; - line-height: 20px; - margin-right: 1em; - padding: 6px; - -} -.Datepicker-item input:focus { - border-color: #4d90fe; - outline: 0; -} - - -/** - * Instructions Component - */ - -.Instructions { - align-items: center; - clear: left; - display: none; - background: #fff; - border: 1px solid #ccc; - float: left; - margin: 0 0 1.5em 1.5em; - padding: 1.5em; -} -.Instructions > h2 { - font: 300 1.4em/1.2 sans-serif; - margin: 0 0 1em; -} -.Instructions ul li { - margin-bottom: .5em; -} -.is-authorized .Instructions { - display: block; -} - -/** - * SourceLink Component - */ -.SourceLink { - clear: both; - display: none; - padding: 0 1.5em 1.5em; - white-space: nowrap; -} -.is-authorized .SourceLink, -.ga-embed-authorized .SourceLink { - display: block; -} - -/** - * Realtime Component - */ - -.Realtime { -} -.Realtime-content { - font-size: 20px; - font-weight: 100; - line-height: 34px; - margin: 0 .25em; -} -.Realtime-value { - font-weight: 700; -} -.Realtime.increase { - -webkit-animation: increase 3s; - animation: increase 3s; -} -.Realtime.decrease { - -webkit-animation: decrease 3s; - animation: decrease 3s; -} -@-webkit-keyframes increase { - 0% {} - 10% { - background-color: hsl(120, 100%, 96%); - border-color: hsla(120, 100%, 25%, .5); - color: hsla(120, 100%, 25%, 1); - } - 100% {} -} -@keyframes increase { - 0% {} - 10% { - background-color: hsl(120, 100%, 96%); - border-color: hsla(120, 100%, 25%, .5); - color: hsla(120, 100%, 25%, 1); - } - 100% {} -} -@-webkit-keyframes decrease { - 0% {} - 10% { - background-color: hsl(0, 100%, 96%); - border-color: hsla(0, 100%, 50%, .5); - color: hsl(0, 100%, 50%); - } - 100% {} -} -@keyframes decrease { - 0% {} - 10% { - background-color: hsl(0, 100%, 96%); - border-color: hsla(0, 100%, 50%, .5); - color: hsl(0, 100%, 50%); - } - 100% {} -} diff --git a/site/assets/html/polymer-body.html b/site/assets/html/polymer-body.html deleted file mode 100644 index 5f07a017c..000000000 --- a/site/assets/html/polymer-body.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - \ No newline at end of file diff --git a/site/assets/html/polymer.html b/site/assets/html/polymer.html deleted file mode 100644 index 86a0bbc58..000000000 --- a/site/assets/html/polymer.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file diff --git a/site/assets/images/ga-logo.png b/site/assets/images/ga-logo.png deleted file mode 100644 index 8e4a4d000a621cc632e1cd58b86b8e0ae7325cf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4578 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 return t; - return -1 * (Math.sqrt(1 - (t/=1)*t) - 1); - }, - easeOutCirc: function (t) { - return 1 * Math.sqrt(1 - (t=t/1-1)*t); - }, - easeInOutCirc: function (t) { - if ((t/=1/2) < 1) return -1/2 * (Math.sqrt(1 - t*t) - 1); - return 1/2 * (Math.sqrt(1 - (t-=2)*t) + 1); - }, - easeInElastic: function (t) { - var s=1.70158;var p=0;var a=1; - if (t==0) return 0; if ((t/=1)==1) return 1; if (!p) p=1*.3; - if (a < Math.abs(1)) { a=1; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (1/a); - return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*1-s)*(2*Math.PI)/p )); - }, - easeOutElastic: function (t) { - var s=1.70158;var p=0;var a=1; - if (t==0) return 0; if ((t/=1)==1) return 1; if (!p) p=1*.3; - if (a < Math.abs(1)) { a=1; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (1/a); - return a*Math.pow(2,-10*t) * Math.sin( (t*1-s)*(2*Math.PI)/p ) + 1; - }, - easeInOutElastic: function (t) { - var s=1.70158;var p=0;var a=1; - if (t==0) return 0; if ((t/=1/2)==2) return 1; if (!p) p=1*(.3*1.5); - if (a < Math.abs(1)) { a=1; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (1/a); - if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*1-s)*(2*Math.PI)/p )); - return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*1-s)*(2*Math.PI)/p )*.5 + 1; - }, - easeInBack: function (t) { - var s = 1.70158; - return 1*(t/=1)*t*((s+1)*t - s); - }, - easeOutBack: function (t) { - var s = 1.70158; - return 1*((t=t/1-1)*t*((s+1)*t + s) + 1); - }, - easeInOutBack: function (t) { - var s = 1.70158; - if ((t/=1/2) < 1) return 1/2*(t*t*(((s*=(1.525))+1)*t - s)); - return 1/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2); - }, - easeInBounce: function (t) { - return 1 - animationOptions.easeOutBounce (1-t); - }, - easeOutBounce: function (t) { - if ((t/=1) < (1/2.75)) { - return 1*(7.5625*t*t); - } else if (t < (2/2.75)) { - return 1*(7.5625*(t-=(1.5/2.75))*t + .75); - } else if (t < (2.5/2.75)) { - return 1*(7.5625*(t-=(2.25/2.75))*t + .9375); - } else { - return 1*(7.5625*(t-=(2.625/2.75))*t + .984375); - } - }, - easeInOutBounce: function (t) { - if (t < 1/2) return animationOptions.easeInBounce (t*2) * .5; - return animationOptions.easeOutBounce (t*2-1) * .5 + 1*.5; - } - }; - - //Variables global to the chart - var width = context.canvas.width; - var height = context.canvas.height; - - - //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale. - if (window.devicePixelRatio) { - context.canvas.style.width = width + "px"; - context.canvas.style.height = height + "px"; - context.canvas.height = height * window.devicePixelRatio; - context.canvas.width = width * window.devicePixelRatio; - context.scale(window.devicePixelRatio, window.devicePixelRatio); - } - - this.PolarArea = function(data,options){ - - chart.PolarArea.defaults = { - scaleOverlay : true, - scaleOverride : false, - scaleSteps : null, - scaleStepWidth : null, - scaleStartValue : null, - scaleShowLine : true, - scaleLineColor : "rgba(0,0,0,.1)", - scaleLineWidth : 1, - scaleShowLabels : true, - scaleLabel : "<%=value%>", - scaleFontFamily : "'Arial'", - scaleFontSize : 12, - scaleFontStyle : "normal", - scaleFontColor : "#666", - scaleShowLabelBackdrop : true, - scaleBackdropColor : "rgba(255,255,255,0.75)", - scaleBackdropPaddingY : 2, - scaleBackdropPaddingX : 2, - segmentShowStroke : true, - segmentStrokeColor : "#fff", - segmentStrokeWidth : 2, - animation : true, - animationSteps : 100, - animationEasing : "easeOutBounce", - animateRotate : true, - animateScale : false, - onAnimationComplete : null - }; - - var config = (options)? mergeChartConfig(chart.PolarArea.defaults,options) : chart.PolarArea.defaults; - - return new PolarArea(data,config,context); - }; - - this.Radar = function(data,options){ - - chart.Radar.defaults = { - scaleOverlay : false, - scaleOverride : false, - scaleSteps : null, - scaleStepWidth : null, - scaleStartValue : null, - scaleShowLine : true, - scaleLineColor : "rgba(0,0,0,.1)", - scaleLineWidth : 1, - scaleShowLabels : false, - scaleLabel : "<%=value%>", - scaleFontFamily : "'Arial'", - scaleFontSize : 12, - scaleFontStyle : "normal", - scaleFontColor : "#666", - scaleShowLabelBackdrop : true, - scaleBackdropColor : "rgba(255,255,255,0.75)", - scaleBackdropPaddingY : 2, - scaleBackdropPaddingX : 2, - angleShowLineOut : true, - angleLineColor : "rgba(0,0,0,.1)", - angleLineWidth : 1, - pointLabelFontFamily : "'Arial'", - pointLabelFontStyle : "normal", - pointLabelFontSize : 12, - pointLabelFontColor : "#666", - pointDot : true, - pointDotRadius : 3, - pointDotStrokeWidth : 1, - datasetStroke : true, - datasetStrokeWidth : 2, - datasetFill : true, - animation : true, - animationSteps : 60, - animationEasing : "easeOutQuart", - onAnimationComplete : null - }; - - var config = (options)? mergeChartConfig(chart.Radar.defaults,options) : chart.Radar.defaults; - - return new Radar(data,config,context); - }; - - this.Pie = function(data,options){ - chart.Pie.defaults = { - segmentShowStroke : true, - segmentStrokeColor : "#fff", - segmentStrokeWidth : 2, - animation : true, - animationSteps : 100, - animationEasing : "easeOutBounce", - animateRotate : true, - animateScale : false, - onAnimationComplete : null - }; - - var config = (options)? mergeChartConfig(chart.Pie.defaults,options) : chart.Pie.defaults; - - return new Pie(data,config,context); - }; - - this.Doughnut = function(data,options){ - - chart.Doughnut.defaults = { - segmentShowStroke : true, - segmentStrokeColor : "#fff", - segmentStrokeWidth : 2, - percentageInnerCutout : 50, - animation : true, - animationSteps : 100, - animationEasing : "easeOutBounce", - animateRotate : true, - animateScale : false, - onAnimationComplete : null - }; - - var config = (options)? mergeChartConfig(chart.Doughnut.defaults,options) : chart.Doughnut.defaults; - - return new Doughnut(data,config,context); - - }; - - this.Line = function(data,options){ - - chart.Line.defaults = { - scaleOverlay : false, - scaleOverride : false, - scaleSteps : null, - scaleStepWidth : null, - scaleStartValue : null, - scaleLineColor : "rgba(0,0,0,.1)", - scaleLineWidth : 1, - scaleShowLabels : true, - scaleLabel : "<%=value%>", - scaleFontFamily : "'Arial'", - scaleFontSize : 12, - scaleFontStyle : "normal", - scaleFontColor : "#666", - scaleShowGridLines : true, - scaleGridLineColor : "rgba(0,0,0,.05)", - scaleGridLineWidth : 1, - bezierCurve : true, - pointDot : true, - pointDotRadius : 4, - pointDotStrokeWidth : 2, - datasetStroke : true, - datasetStrokeWidth : 2, - datasetFill : true, - animation : true, - animationSteps : 60, - animationEasing : "easeOutQuart", - onAnimationComplete : null - }; - var config = (options) ? mergeChartConfig(chart.Line.defaults,options) : chart.Line.defaults; - - return new Line(data,config,context); - } - - this.Bar = function(data,options){ - chart.Bar.defaults = { - scaleOverlay : false, - scaleOverride : false, - scaleSteps : null, - scaleStepWidth : null, - scaleStartValue : null, - scaleLineColor : "rgba(0,0,0,.1)", - scaleLineWidth : 1, - scaleShowLabels : true, - scaleLabel : "<%=value%>", - scaleFontFamily : "'Arial'", - scaleFontSize : 12, - scaleFontStyle : "normal", - scaleFontColor : "#666", - scaleShowGridLines : true, - scaleGridLineColor : "rgba(0,0,0,.05)", - scaleGridLineWidth : 1, - barShowStroke : true, - barStrokeWidth : 2, - barValueSpacing : 5, - barDatasetSpacing : 1, - animation : true, - animationSteps : 60, - animationEasing : "easeOutQuart", - onAnimationComplete : null - }; - var config = (options) ? mergeChartConfig(chart.Bar.defaults,options) : chart.Bar.defaults; - - return new Bar(data,config,context); - } - - var clear = function(c){ - c.clearRect(0, 0, width, height); - }; - - var PolarArea = function(data,config,ctx){ - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString; - - - calculateDrawingSizes(); - - valueBounds = getValueBounds(); - - labelTemplateString = (config.scaleShowLabels)? config.scaleLabel : null; - - //Check and set the scale - if (!config.scaleOverride){ - - calculatedScale = calculateScale(scaleHeight,valueBounds.maxSteps,valueBounds.minSteps,valueBounds.maxValue,valueBounds.minValue,labelTemplateString); - } - else { - calculatedScale = { - steps : config.scaleSteps, - stepValue : config.scaleStepWidth, - graphMin : config.scaleStartValue, - labels : [] - } - populateLabels(labelTemplateString, calculatedScale.labels,calculatedScale.steps,config.scaleStartValue,config.scaleStepWidth); - } - - scaleHop = maxSize/(calculatedScale.steps); - - //Wrap in an animation loop wrapper - animationLoop(config,drawScale,drawAllSegments,ctx); - - function calculateDrawingSizes(){ - maxSize = (Min([width,height])/2); - //Remove whatever is larger - the font size or line width. - - maxSize -= Max([config.scaleFontSize*0.5,config.scaleLineWidth*0.5]); - - labelHeight = config.scaleFontSize*2; - //If we're drawing the backdrop - add the Y padding to the label height and remove from drawing region. - if (config.scaleShowLabelBackdrop){ - labelHeight += (2 * config.scaleBackdropPaddingY); - maxSize -= config.scaleBackdropPaddingY*1.5; - } - - scaleHeight = maxSize; - //If the label height is less than 5, set it to 5 so we don't have lines on top of each other. - labelHeight = Default(labelHeight,5); - } - function drawScale(){ - for (var i=0; i upperValue) {upperValue = data[i].value;} - if (data[i].value < lowerValue) {lowerValue = data[i].value;} - }; - - var maxSteps = Math.floor((scaleHeight / (labelHeight*0.66))); - var minSteps = Math.floor((scaleHeight / labelHeight*0.5)); - - return { - maxValue : upperValue, - minValue : lowerValue, - maxSteps : maxSteps, - minSteps : minSteps - }; - - - } - } - - var Radar = function (data,config,ctx) { - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString; - - //If no labels are defined set to an empty array, so referencing length for looping doesn't blow up. - if (!data.labels) data.labels = []; - - calculateDrawingSizes(); - - var valueBounds = getValueBounds(); - - labelTemplateString = (config.scaleShowLabels)? config.scaleLabel : null; - - //Check and set the scale - if (!config.scaleOverride){ - - calculatedScale = calculateScale(scaleHeight,valueBounds.maxSteps,valueBounds.minSteps,valueBounds.maxValue,valueBounds.minValue,labelTemplateString); - } - else { - calculatedScale = { - steps : config.scaleSteps, - stepValue : config.scaleStepWidth, - graphMin : config.scaleStartValue, - labels : [] - } - populateLabels(labelTemplateString, calculatedScale.labels,calculatedScale.steps,config.scaleStartValue,config.scaleStepWidth); - } - - scaleHop = maxSize/(calculatedScale.steps); - - animationLoop(config,drawScale,drawAllDataPoints,ctx); - - //Radar specific functions. - function drawAllDataPoints(animationDecimal){ - var rotationDegree = (2*Math.PI)/data.datasets[0].data.length; - - ctx.save(); - //translate to the centre of the canvas. - ctx.translate(width/2,height/2); - - //We accept multiple data sets for radar charts, so show loop through each set - for (var i=0; i Math.PI){ - ctx.textAlign = "right"; - } - else{ - ctx.textAlign = "left"; - } - - ctx.textBaseline = "middle"; - - ctx.fillText(data.labels[k],opposite,-adjacent); - - } - ctx.restore(); - }; - function calculateDrawingSizes(){ - maxSize = (Min([width,height])/2); - - labelHeight = config.scaleFontSize*2; - - var labelLength = 0; - for (var i=0; ilabelLength) labelLength = textMeasurement; - } - - //Figure out whats the largest - the height of the text or the width of what's there, and minus it from the maximum usable size. - maxSize -= Max([labelLength,((config.pointLabelFontSize/2)*1.5)]); - - maxSize -= config.pointLabelFontSize; - maxSize = CapValue(maxSize, null, 0); - scaleHeight = maxSize; - //If the label height is less than 5, set it to 5 so we don't have lines on top of each other. - labelHeight = Default(labelHeight,5); - }; - function getValueBounds() { - var upperValue = Number.MIN_VALUE; - var lowerValue = Number.MAX_VALUE; - - for (var i=0; i upperValue){upperValue = data.datasets[i].data[j]} - if (data.datasets[i].data[j] < lowerValue){lowerValue = data.datasets[i].data[j]} - } - } - - var maxSteps = Math.floor((scaleHeight / (labelHeight*0.66))); - var minSteps = Math.floor((scaleHeight / labelHeight*0.5)); - - return { - maxValue : upperValue, - minValue : lowerValue, - maxSteps : maxSteps, - minSteps : minSteps - }; - - - } - } - - var Pie = function(data,config,ctx){ - var segmentTotal = 0; - - //In case we have a canvas that is not a square. Minus 5 pixels as padding round the edge. - var pieRadius = Min([height/2,width/2]) - 5; - - for (var i=0; i 0){ - ctx.save(); - ctx.textAlign = "right"; - } - else{ - ctx.textAlign = "center"; - } - ctx.fillStyle = config.scaleFontColor; - for (var i=0; i 0){ - ctx.translate(yAxisPosX + i*valueHop,xAxisPosY + config.scaleFontSize); - ctx.rotate(-(rotateLabels * (Math.PI/180))); - ctx.fillText(data.labels[i], 0,0); - ctx.restore(); - } - - else{ - ctx.fillText(data.labels[i], yAxisPosX + i*valueHop,xAxisPosY + config.scaleFontSize+3); - } - - ctx.beginPath(); - ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY+3); - - //Check i isnt 0, so we dont go over the Y axis twice. - if(config.scaleShowGridLines && i>0){ - ctx.lineWidth = config.scaleGridLineWidth; - ctx.strokeStyle = config.scaleGridLineColor; - ctx.lineTo(yAxisPosX + i * valueHop, 5); - } - else{ - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY+3); - } - ctx.stroke(); - } - - //Y axis - ctx.lineWidth = config.scaleLineWidth; - ctx.strokeStyle = config.scaleLineColor; - ctx.beginPath(); - ctx.moveTo(yAxisPosX,xAxisPosY+5); - ctx.lineTo(yAxisPosX,5); - ctx.stroke(); - - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; - for (var j=0; j longestText)? measuredText : longestText; - } - //Add a little extra padding from the y axis - longestText +=10; - } - xAxisLength = width - longestText - widestXLabel; - valueHop = Math.floor(xAxisLength/(data.labels.length-1)); - - yAxisPosX = width-widestXLabel/2-xAxisLength; - xAxisPosY = scaleHeight + config.scaleFontSize/2; - } - function calculateDrawingSizes(){ - maxSize = height; - - //Need to check the X axis first - measure the length of each text metric, and figure out if we need to rotate by 45 degrees. - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize+"px " + config.scaleFontFamily; - widestXLabel = 1; - for (var i=0; i widestXLabel)? textLength : widestXLabel; - } - if (width/data.labels.length < widestXLabel){ - rotateLabels = 45; - if (width/data.labels.length < Math.cos(rotateLabels) * widestXLabel){ - rotateLabels = 90; - maxSize -= widestXLabel; - } - else{ - maxSize -= Math.sin(rotateLabels) * widestXLabel; - } - } - else{ - maxSize -= config.scaleFontSize; - } - - //Add a little padding between the x line and the text - maxSize -= 5; - - - labelHeight = config.scaleFontSize; - - maxSize -= labelHeight; - //Set 5 pixels greater than the font size to allow for a little padding from the X axis. - - scaleHeight = maxSize; - - //Then get the area above we can safely draw on. - - } - function getValueBounds() { - var upperValue = Number.MIN_VALUE; - var lowerValue = Number.MAX_VALUE; - for (var i=0; i upperValue) { upperValue = data.datasets[i].data[j] }; - if ( data.datasets[i].data[j] < lowerValue) { lowerValue = data.datasets[i].data[j] }; - } - }; - - var maxSteps = Math.floor((scaleHeight / (labelHeight*0.66))); - var minSteps = Math.floor((scaleHeight / labelHeight*0.5)); - - return { - maxValue : upperValue, - minValue : lowerValue, - maxSteps : maxSteps, - minSteps : minSteps - }; - - - } - - - } - - var Bar = function(data,config,ctx){ - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop,widestXLabel, xAxisLength,yAxisPosX,xAxisPosY,barWidth, rotateLabels = 0; - - calculateDrawingSizes(); - - valueBounds = getValueBounds(); - //Check and set the scale - labelTemplateString = (config.scaleShowLabels)? config.scaleLabel : ""; - if (!config.scaleOverride){ - - calculatedScale = calculateScale(scaleHeight,valueBounds.maxSteps,valueBounds.minSteps,valueBounds.maxValue,valueBounds.minValue,labelTemplateString); - } - else { - calculatedScale = { - steps : config.scaleSteps, - stepValue : config.scaleStepWidth, - graphMin : config.scaleStartValue, - labels : [] - } - populateLabels(labelTemplateString, calculatedScale.labels,calculatedScale.steps,config.scaleStartValue,config.scaleStepWidth); - } - - scaleHop = Math.floor(scaleHeight/calculatedScale.steps); - calculateXAxisSize(); - animationLoop(config,drawScale,drawBars,ctx); - - function drawBars(animPc){ - ctx.lineWidth = config.barStrokeWidth; - for (var i=0; i 0){ - ctx.save(); - ctx.textAlign = "right"; - } - else{ - ctx.textAlign = "center"; - } - ctx.fillStyle = config.scaleFontColor; - for (var i=0; i 0){ - ctx.translate(yAxisPosX + i*valueHop,xAxisPosY + config.scaleFontSize); - ctx.rotate(-(rotateLabels * (Math.PI/180))); - ctx.fillText(data.labels[i], 0,0); - ctx.restore(); - } - - else{ - ctx.fillText(data.labels[i], yAxisPosX + i*valueHop + valueHop/2,xAxisPosY + config.scaleFontSize+3); - } - - ctx.beginPath(); - ctx.moveTo(yAxisPosX + (i+1) * valueHop, xAxisPosY+3); - - //Check i isnt 0, so we dont go over the Y axis twice. - ctx.lineWidth = config.scaleGridLineWidth; - ctx.strokeStyle = config.scaleGridLineColor; - ctx.lineTo(yAxisPosX + (i+1) * valueHop, 5); - ctx.stroke(); - } - - //Y axis - ctx.lineWidth = config.scaleLineWidth; - ctx.strokeStyle = config.scaleLineColor; - ctx.beginPath(); - ctx.moveTo(yAxisPosX,xAxisPosY+5); - ctx.lineTo(yAxisPosX,5); - ctx.stroke(); - - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; - for (var j=0; j longestText)? measuredText : longestText; - } - //Add a little extra padding from the y axis - longestText +=10; - } - xAxisLength = width - longestText - widestXLabel; - valueHop = Math.floor(xAxisLength/(data.labels.length)); - - barWidth = (valueHop - config.scaleGridLineWidth*2 - (config.barValueSpacing*2) - (config.barDatasetSpacing*data.datasets.length-1) - ((config.barStrokeWidth/2)*data.datasets.length-1))/data.datasets.length; - - yAxisPosX = width-widestXLabel/2-xAxisLength; - xAxisPosY = scaleHeight + config.scaleFontSize/2; - } - function calculateDrawingSizes(){ - maxSize = height; - - //Need to check the X axis first - measure the length of each text metric, and figure out if we need to rotate by 45 degrees. - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize+"px " + config.scaleFontFamily; - widestXLabel = 1; - for (var i=0; i widestXLabel)? textLength : widestXLabel; - } - if (width/data.labels.length < widestXLabel){ - rotateLabels = 45; - if (width/data.labels.length < Math.cos(rotateLabels) * widestXLabel){ - rotateLabels = 90; - maxSize -= widestXLabel; - } - else{ - maxSize -= Math.sin(rotateLabels) * widestXLabel; - } - } - else{ - maxSize -= config.scaleFontSize; - } - - //Add a little padding between the x line and the text - maxSize -= 5; - - - labelHeight = config.scaleFontSize; - - maxSize -= labelHeight; - //Set 5 pixels greater than the font size to allow for a little padding from the X axis. - - scaleHeight = maxSize; - - //Then get the area above we can safely draw on. - - } - function getValueBounds() { - var upperValue = Number.MIN_VALUE; - var lowerValue = Number.MAX_VALUE; - for (var i=0; i upperValue) { upperValue = data.datasets[i].data[j] }; - if ( data.datasets[i].data[j] < lowerValue) { lowerValue = data.datasets[i].data[j] }; - } - }; - - var maxSteps = Math.floor((scaleHeight / (labelHeight*0.66))); - var minSteps = Math.floor((scaleHeight / labelHeight*0.5)); - - return { - maxValue : upperValue, - minValue : lowerValue, - maxSteps : maxSteps, - minSteps : minSteps - }; - - - } - } - - function calculateOffset(val,calculatedScale,scaleHop){ - var outerValue = calculatedScale.steps * calculatedScale.stepValue; - var adjustedValue = val - calculatedScale.graphMin; - var scalingFactor = CapValue(adjustedValue/outerValue,1,0); - return (scaleHop*calculatedScale.steps) * scalingFactor; - } - - function animationLoop(config,drawScale,drawData,ctx){ - var animFrameAmount = (config.animation)? 1/CapValue(config.animationSteps,Number.MAX_VALUE,1) : 1, - easingFunction = animationOptions[config.animationEasing], - percentAnimComplete =(config.animation)? 0 : 1; - - - - if (typeof drawScale !== "function") drawScale = function(){}; - - requestAnimFrame(animLoop); - - function animateFrame(){ - var easeAdjustedAnimationPercent =(config.animation)? CapValue(easingFunction(percentAnimComplete),null,0) : 1; - clear(ctx); - if(config.scaleOverlay){ - drawData(easeAdjustedAnimationPercent); - drawScale(); - } else { - drawScale(); - drawData(easeAdjustedAnimationPercent); - } - } - function animLoop(){ - //We need to check if the animation is incomplete (less than 1), or complete (1). - percentAnimComplete += animFrameAmount; - animateFrame(); - //Stop the loop continuing forever - if (percentAnimComplete <= 1){ - requestAnimFrame(animLoop); - } - else{ - if (typeof config.onAnimationComplete == "function") config.onAnimationComplete(); - } - - } - - } - - //Declare global functions to be called within this namespace here. - - - // shim layer with setTimeout fallback - var requestAnimFrame = (function(){ - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function(callback) { - window.setTimeout(callback, 1000 / 60); - }; - })(); - - function calculateScale(drawingHeight,maxSteps,minSteps,maxValue,minValue,labelTemplateString){ - var graphMin,graphMax,graphRange,stepValue,numberOfSteps,valueRange,rangeOrderOfMagnitude,decimalNum; - - valueRange = maxValue - minValue; - - rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange); - - graphMin = Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude); - - graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude); - - graphRange = graphMax - graphMin; - - stepValue = Math.pow(10, rangeOrderOfMagnitude); - - numberOfSteps = Math.round(graphRange / stepValue); - - //Compare number of steps to the max and min for that size graph, and add in half steps if need be. - while(numberOfSteps < minSteps || numberOfSteps > maxSteps) { - if (numberOfSteps < minSteps){ - stepValue /= 2; - numberOfSteps = Math.round(graphRange/stepValue); - } - else{ - stepValue *=2; - numberOfSteps = Math.round(graphRange/stepValue); - } - }; - - var labels = []; - populateLabels(labelTemplateString, labels, numberOfSteps, graphMin, stepValue); - - return { - steps : numberOfSteps, - stepValue : stepValue, - graphMin : graphMin, - labels : labels - - } - - function calculateOrderOfMagnitude(val){ - return Math.floor(Math.log(val) / Math.LN10); - } - - - } - - //Populate an array of all the labels by interpolating the string. - function populateLabels(labelTemplateString, labels, numberOfSteps, graphMin, stepValue) { - if (labelTemplateString) { - //Fix floating point errors by setting to fixed the on the same decimal as the stepValue. - for (var i = 1; i < numberOfSteps + 1; i++) { - labels.push(tmpl(labelTemplateString, {value: (graphMin + (stepValue * i)).toFixed(getDecimalPlaces(stepValue))})); - } - } - } - - //Max value from array - function Max( array ){ - return Math.max.apply( Math, array ); - }; - //Min value from array - function Min( array ){ - return Math.min.apply( Math, array ); - }; - //Default if undefined - function Default(userDeclared,valueIfFalse){ - if(!userDeclared){ - return valueIfFalse; - } else { - return userDeclared; - } - }; - //Is a number function - function isNumber(n) { - return !isNaN(parseFloat(n)) && isFinite(n); - } - //Apply cap a value at a high or low number - function CapValue(valueToCap, maxValue, minValue){ - if(isNumber(maxValue)) { - if( valueToCap > maxValue ) { - return maxValue; - } - } - if(isNumber(minValue)){ - if ( valueToCap < minValue ){ - return minValue; - } - } - return valueToCap; - } - function getDecimalPlaces (num){ - var numberOfDecimalPlaces; - if (num%1!=0){ - return num.toString().split(".")[1].length - } - else{ - return 0; - } - - } - - function mergeChartConfig(defaults,userDefined){ - var returnObj = {}; - for (var attrname in defaults) { returnObj[attrname] = defaults[attrname]; } - for (var attrname in userDefined) { returnObj[attrname] = userDefined[attrname]; } - return returnObj; - } - - //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/ - var cache = {}; - - function tmpl(str, data){ - // Figure out if we're getting a template, or if we need to - // load the template - and be sure to cache the result. - var fn = !/\W/.test(str) ? - cache[str] = cache[str] || - tmpl(document.getElementById(str).innerHTML) : - - // Generate a reusable function that will serve as a template - // generator (and which will be cached). - new Function("obj", - "var p=[],print=function(){p.push.apply(p,arguments);};" + - - // Introduce the data as local variables using with(){} - "with(obj){p.push('" + - - // Convert the template into pure JavaScript - str - .replace(/[\r\t\n]/g, " ") - .split("<%").join("\t") - .replace(/((^|%>)[^\t]*)'/g, "$1\r") - .replace(/\t=(.*?)%>/g, "',$1,'") - .split("\t").join("');") - .split("%>").join("p.push('") - .split("\r").join("\\'") - + "');}return p.join('');"); - - // Provide some basic currying to the user - return data ? fn( data ) : fn; - }; -} - - diff --git a/site/assets/js/moment.js b/site/assets/js/moment.js deleted file mode 100644 index 83282c6fd..000000000 --- a/site/assets/js/moment.js +++ /dev/null @@ -1,2610 +0,0 @@ -//! moment.js -//! version : 2.7.0 -//! authors : Tim Wood, Iskren Chernev, Moment.js contributors -//! license : MIT -//! momentjs.com - -(function (undefined) { - - /************************************ - Constants - ************************************/ - - var moment, - VERSION = "2.7.0", - // the global-scope this is NOT the global object in Node.js - globalScope = typeof global !== 'undefined' ? global : this, - oldGlobalMoment, - round = Math.round, - i, - - YEAR = 0, - MONTH = 1, - DATE = 2, - HOUR = 3, - MINUTE = 4, - SECOND = 5, - MILLISECOND = 6, - - // internal storage for language config files - languages = {}, - - // moment internal properties - momentProperties = { - _isAMomentObject: null, - _i : null, - _f : null, - _l : null, - _strict : null, - _tzm : null, - _isUTC : null, - _offset : null, // optional. Combine with _isUTC - _pf : null, - _lang : null // optional - }, - - // check for nodeJS - hasModule = (typeof module !== 'undefined' && module.exports), - - // ASP.NET json date format regex - aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, - aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, - - // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html - // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere - isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, - - // format tokens - formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, - localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, - - // parsing token regexes - parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 - parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 - parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999 - parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 - parseTokenDigits = /\d+/, // nonzero number of digits - parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. - parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z - parseTokenT = /T/i, // T (ISO separator) - parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 - parseTokenOrdinal = /\d{1,2}/, - - //strict parsing regexes - parseTokenOneDigit = /\d/, // 0 - 9 - parseTokenTwoDigits = /\d\d/, // 00 - 99 - parseTokenThreeDigits = /\d{3}/, // 000 - 999 - parseTokenFourDigits = /\d{4}/, // 0000 - 9999 - parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999 - parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf - - // iso 8601 regex - // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) - isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, - - isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', - - isoDates = [ - ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], - ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], - ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], - ['GGGG-[W]WW', /\d{4}-W\d{2}/], - ['YYYY-DDD', /\d{4}-\d{3}/] - ], - - // iso time formats and regexes - isoTimes = [ - ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], - ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], - ['HH:mm', /(T| )\d\d:\d\d/], - ['HH', /(T| )\d\d/] - ], - - // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"] - parseTimezoneChunker = /([\+\-]|\d\d)/gi, - - // getter and setter names - proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), - unitMillisecondFactors = { - 'Milliseconds' : 1, - 'Seconds' : 1e3, - 'Minutes' : 6e4, - 'Hours' : 36e5, - 'Days' : 864e5, - 'Months' : 2592e6, - 'Years' : 31536e6 - }, - - unitAliases = { - ms : 'millisecond', - s : 'second', - m : 'minute', - h : 'hour', - d : 'day', - D : 'date', - w : 'week', - W : 'isoWeek', - M : 'month', - Q : 'quarter', - y : 'year', - DDD : 'dayOfYear', - e : 'weekday', - E : 'isoWeekday', - gg: 'weekYear', - GG: 'isoWeekYear' - }, - - camelFunctions = { - dayofyear : 'dayOfYear', - isoweekday : 'isoWeekday', - isoweek : 'isoWeek', - weekyear : 'weekYear', - isoweekyear : 'isoWeekYear' - }, - - // format function strings - formatFunctions = {}, - - // default relative time thresholds - relativeTimeThresholds = { - s: 45, //seconds to minutes - m: 45, //minutes to hours - h: 22, //hours to days - dd: 25, //days to month (month == 1) - dm: 45, //days to months (months > 1) - dy: 345 //days to year - }, - - // tokens to ordinalize and pad - ordinalizeTokens = 'DDD w W M D d'.split(' '), - paddedTokens = 'M D H h m s w W'.split(' '), - - formatTokenFunctions = { - M : function () { - return this.month() + 1; - }, - MMM : function (format) { - return this.lang().monthsShort(this, format); - }, - MMMM : function (format) { - return this.lang().months(this, format); - }, - D : function () { - return this.date(); - }, - DDD : function () { - return this.dayOfYear(); - }, - d : function () { - return this.day(); - }, - dd : function (format) { - return this.lang().weekdaysMin(this, format); - }, - ddd : function (format) { - return this.lang().weekdaysShort(this, format); - }, - dddd : function (format) { - return this.lang().weekdays(this, format); - }, - w : function () { - return this.week(); - }, - W : function () { - return this.isoWeek(); - }, - YY : function () { - return leftZeroFill(this.year() % 100, 2); - }, - YYYY : function () { - return leftZeroFill(this.year(), 4); - }, - YYYYY : function () { - return leftZeroFill(this.year(), 5); - }, - YYYYYY : function () { - var y = this.year(), sign = y >= 0 ? '+' : '-'; - return sign + leftZeroFill(Math.abs(y), 6); - }, - gg : function () { - return leftZeroFill(this.weekYear() % 100, 2); - }, - gggg : function () { - return leftZeroFill(this.weekYear(), 4); - }, - ggggg : function () { - return leftZeroFill(this.weekYear(), 5); - }, - GG : function () { - return leftZeroFill(this.isoWeekYear() % 100, 2); - }, - GGGG : function () { - return leftZeroFill(this.isoWeekYear(), 4); - }, - GGGGG : function () { - return leftZeroFill(this.isoWeekYear(), 5); - }, - e : function () { - return this.weekday(); - }, - E : function () { - return this.isoWeekday(); - }, - a : function () { - return this.lang().meridiem(this.hours(), this.minutes(), true); - }, - A : function () { - return this.lang().meridiem(this.hours(), this.minutes(), false); - }, - H : function () { - return this.hours(); - }, - h : function () { - return this.hours() % 12 || 12; - }, - m : function () { - return this.minutes(); - }, - s : function () { - return this.seconds(); - }, - S : function () { - return toInt(this.milliseconds() / 100); - }, - SS : function () { - return leftZeroFill(toInt(this.milliseconds() / 10), 2); - }, - SSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - SSSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - Z : function () { - var a = -this.zone(), - b = "+"; - if (a < 0) { - a = -a; - b = "-"; - } - return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2); - }, - ZZ : function () { - var a = -this.zone(), - b = "+"; - if (a < 0) { - a = -a; - b = "-"; - } - return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); - }, - z : function () { - return this.zoneAbbr(); - }, - zz : function () { - return this.zoneName(); - }, - X : function () { - return this.unix(); - }, - Q : function () { - return this.quarter(); - } - }, - - lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; - - // Pick the first defined of two or three arguments. dfl comes from - // default. - function dfl(a, b, c) { - switch (arguments.length) { - case 2: return a != null ? a : b; - case 3: return a != null ? a : b != null ? b : c; - default: throw new Error("Implement me"); - } - } - - function defaultParsingFlags() { - // We need to deep clone this object, and es5 standard is not very - // helpful. - return { - empty : false, - unusedTokens : [], - unusedInput : [], - overflow : -2, - charsLeftOver : 0, - nullInput : false, - invalidMonth : null, - invalidFormat : false, - userInvalidated : false, - iso: false - }; - } - - function deprecate(msg, fn) { - var firstTime = true; - function printMsg() { - if (moment.suppressDeprecationWarnings === false && - typeof console !== 'undefined' && console.warn) { - console.warn("Deprecation warning: " + msg); - } - } - return extend(function () { - if (firstTime) { - printMsg(); - firstTime = false; - } - return fn.apply(this, arguments); - }, fn); - } - - function padToken(func, count) { - return function (a) { - return leftZeroFill(func.call(this, a), count); - }; - } - function ordinalizeToken(func, period) { - return function (a) { - return this.lang().ordinal(func.call(this, a), period); - }; - } - - while (ordinalizeTokens.length) { - i = ordinalizeTokens.pop(); - formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); - } - while (paddedTokens.length) { - i = paddedTokens.pop(); - formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); - } - formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); - - - /************************************ - Constructors - ************************************/ - - function Language() { - - } - - // Moment prototype object - function Moment(config) { - checkOverflow(config); - extend(this, config); - } - - // Duration Constructor - function Duration(duration) { - var normalizedInput = normalizeObjectUnits(duration), - years = normalizedInput.year || 0, - quarters = normalizedInput.quarter || 0, - months = normalizedInput.month || 0, - weeks = normalizedInput.week || 0, - days = normalizedInput.day || 0, - hours = normalizedInput.hour || 0, - minutes = normalizedInput.minute || 0, - seconds = normalizedInput.second || 0, - milliseconds = normalizedInput.millisecond || 0; - - // representation for dateAddRemove - this._milliseconds = +milliseconds + - seconds * 1e3 + // 1000 - minutes * 6e4 + // 1000 * 60 - hours * 36e5; // 1000 * 60 * 60 - // Because of dateAddRemove treats 24 hours as different from a - // day when working around DST, we need to store them separately - this._days = +days + - weeks * 7; - // It is impossible translate months into days without knowing - // which months you are are talking about, so we have to store - // it separately. - this._months = +months + - quarters * 3 + - years * 12; - - this._data = {}; - - this._bubble(); - } - - /************************************ - Helpers - ************************************/ - - - function extend(a, b) { - for (var i in b) { - if (b.hasOwnProperty(i)) { - a[i] = b[i]; - } - } - - if (b.hasOwnProperty("toString")) { - a.toString = b.toString; - } - - if (b.hasOwnProperty("valueOf")) { - a.valueOf = b.valueOf; - } - - return a; - } - - function cloneMoment(m) { - var result = {}, i; - for (i in m) { - if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) { - result[i] = m[i]; - } - } - - return result; - } - - function absRound(number) { - if (number < 0) { - return Math.ceil(number); - } else { - return Math.floor(number); - } - } - - // left zero fill a number - // see http://jsperf.com/left-zero-filling for performance comparison - function leftZeroFill(number, targetLength, forceSign) { - var output = '' + Math.abs(number), - sign = number >= 0; - - while (output.length < targetLength) { - output = '0' + output; - } - return (sign ? (forceSign ? '+' : '') : '-') + output; - } - - // helper function for _.addTime and _.subtractTime - function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { - var milliseconds = duration._milliseconds, - days = duration._days, - months = duration._months; - updateOffset = updateOffset == null ? true : updateOffset; - - if (milliseconds) { - mom._d.setTime(+mom._d + milliseconds * isAdding); - } - if (days) { - rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding); - } - if (months) { - rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding); - } - if (updateOffset) { - moment.updateOffset(mom, days || months); - } - } - - // check if is an array - function isArray(input) { - return Object.prototype.toString.call(input) === '[object Array]'; - } - - function isDate(input) { - return Object.prototype.toString.call(input) === '[object Date]' || - input instanceof Date; - } - - // compare two arrays, return the number of differences - function compareArrays(array1, array2, dontConvert) { - var len = Math.min(array1.length, array2.length), - lengthDiff = Math.abs(array1.length - array2.length), - diffs = 0, - i; - for (i = 0; i < len; i++) { - if ((dontConvert && array1[i] !== array2[i]) || - (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { - diffs++; - } - } - return diffs + lengthDiff; - } - - function normalizeUnits(units) { - if (units) { - var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); - units = unitAliases[units] || camelFunctions[lowered] || lowered; - } - return units; - } - - function normalizeObjectUnits(inputObject) { - var normalizedInput = {}, - normalizedProp, - prop; - - for (prop in inputObject) { - if (inputObject.hasOwnProperty(prop)) { - normalizedProp = normalizeUnits(prop); - if (normalizedProp) { - normalizedInput[normalizedProp] = inputObject[prop]; - } - } - } - - return normalizedInput; - } - - function makeList(field) { - var count, setter; - - if (field.indexOf('week') === 0) { - count = 7; - setter = 'day'; - } - else if (field.indexOf('month') === 0) { - count = 12; - setter = 'month'; - } - else { - return; - } - - moment[field] = function (format, index) { - var i, getter, - method = moment.fn._lang[field], - results = []; - - if (typeof format === 'number') { - index = format; - format = undefined; - } - - getter = function (i) { - var m = moment().utc().set(setter, i); - return method.call(moment.fn._lang, m, format || ''); - }; - - if (index != null) { - return getter(index); - } - else { - for (i = 0; i < count; i++) { - results.push(getter(i)); - } - return results; - } - }; - } - - function toInt(argumentForCoercion) { - var coercedNumber = +argumentForCoercion, - value = 0; - - if (coercedNumber !== 0 && isFinite(coercedNumber)) { - if (coercedNumber >= 0) { - value = Math.floor(coercedNumber); - } else { - value = Math.ceil(coercedNumber); - } - } - - return value; - } - - function daysInMonth(year, month) { - return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); - } - - function weeksInYear(year, dow, doy) { - return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; - } - - function daysInYear(year) { - return isLeapYear(year) ? 366 : 365; - } - - function isLeapYear(year) { - return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; - } - - function checkOverflow(m) { - var overflow; - if (m._a && m._pf.overflow === -2) { - overflow = - m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : - m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : - m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : - m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : - m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : - m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : - -1; - - if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { - overflow = DATE; - } - - m._pf.overflow = overflow; - } - } - - function isValid(m) { - if (m._isValid == null) { - m._isValid = !isNaN(m._d.getTime()) && - m._pf.overflow < 0 && - !m._pf.empty && - !m._pf.invalidMonth && - !m._pf.nullInput && - !m._pf.invalidFormat && - !m._pf.userInvalidated; - - if (m._strict) { - m._isValid = m._isValid && - m._pf.charsLeftOver === 0 && - m._pf.unusedTokens.length === 0; - } - } - return m._isValid; - } - - function normalizeLanguage(key) { - return key ? key.toLowerCase().replace('_', '-') : key; - } - - // Return a moment from input, that is local/utc/zone equivalent to model. - function makeAs(input, model) { - return model._isUTC ? moment(input).zone(model._offset || 0) : - moment(input).local(); - } - - /************************************ - Languages - ************************************/ - - - extend(Language.prototype, { - - set : function (config) { - var prop, i; - for (i in config) { - prop = config[i]; - if (typeof prop === 'function') { - this[i] = prop; - } else { - this['_' + i] = prop; - } - } - }, - - _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), - months : function (m) { - return this._months[m.month()]; - }, - - _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), - monthsShort : function (m) { - return this._monthsShort[m.month()]; - }, - - monthsParse : function (monthName) { - var i, mom, regex; - - if (!this._monthsParse) { - this._monthsParse = []; - } - - for (i = 0; i < 12; i++) { - // make the regex if we don't have it already - if (!this._monthsParse[i]) { - mom = moment.utc([2000, i]); - regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); - this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._monthsParse[i].test(monthName)) { - return i; - } - } - }, - - _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), - weekdays : function (m) { - return this._weekdays[m.day()]; - }, - - _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), - weekdaysShort : function (m) { - return this._weekdaysShort[m.day()]; - }, - - _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), - weekdaysMin : function (m) { - return this._weekdaysMin[m.day()]; - }, - - weekdaysParse : function (weekdayName) { - var i, mom, regex; - - if (!this._weekdaysParse) { - this._weekdaysParse = []; - } - - for (i = 0; i < 7; i++) { - // make the regex if we don't have it already - if (!this._weekdaysParse[i]) { - mom = moment([2000, 1]).day(i); - regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); - this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._weekdaysParse[i].test(weekdayName)) { - return i; - } - } - }, - - _longDateFormat : { - LT : "h:mm A", - L : "MM/DD/YYYY", - LL : "MMMM D YYYY", - LLL : "MMMM D YYYY LT", - LLLL : "dddd, MMMM D YYYY LT" - }, - longDateFormat : function (key) { - var output = this._longDateFormat[key]; - if (!output && this._longDateFormat[key.toUpperCase()]) { - output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { - return val.slice(1); - }); - this._longDateFormat[key] = output; - } - return output; - }, - - isPM : function (input) { - // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays - // Using charAt should be more compatible. - return ((input + '').toLowerCase().charAt(0) === 'p'); - }, - - _meridiemParse : /[ap]\.?m?\.?/i, - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'pm' : 'PM'; - } else { - return isLower ? 'am' : 'AM'; - } - }, - - _calendar : { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[Last] dddd [at] LT', - sameElse : 'L' - }, - calendar : function (key, mom) { - var output = this._calendar[key]; - return typeof output === 'function' ? output.apply(mom) : output; - }, - - _relativeTime : { - future : "in %s", - past : "%s ago", - s : "a few seconds", - m : "a minute", - mm : "%d minutes", - h : "an hour", - hh : "%d hours", - d : "a day", - dd : "%d days", - M : "a month", - MM : "%d months", - y : "a year", - yy : "%d years" - }, - relativeTime : function (number, withoutSuffix, string, isFuture) { - var output = this._relativeTime[string]; - return (typeof output === 'function') ? - output(number, withoutSuffix, string, isFuture) : - output.replace(/%d/i, number); - }, - pastFuture : function (diff, output) { - var format = this._relativeTime[diff > 0 ? 'future' : 'past']; - return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); - }, - - ordinal : function (number) { - return this._ordinal.replace("%d", number); - }, - _ordinal : "%d", - - preparse : function (string) { - return string; - }, - - postformat : function (string) { - return string; - }, - - week : function (mom) { - return weekOfYear(mom, this._week.dow, this._week.doy).week; - }, - - _week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - }, - - _invalidDate: 'Invalid date', - invalidDate: function () { - return this._invalidDate; - } - }); - - // Loads a language definition into the `languages` cache. The function - // takes a key and optionally values. If not in the browser and no values - // are provided, it will load the language file module. As a convenience, - // this function also returns the language values. - function loadLang(key, values) { - values.abbr = key; - if (!languages[key]) { - languages[key] = new Language(); - } - languages[key].set(values); - return languages[key]; - } - - // Remove a language from the `languages` cache. Mostly useful in tests. - function unloadLang(key) { - delete languages[key]; - } - - // Determines which language definition to use and returns it. - // - // With no parameters, it will return the global language. If you - // pass in a language key, such as 'en', it will return the - // definition for 'en', so long as 'en' has already been loaded using - // moment.lang. - function getLangDefinition(key) { - var i = 0, j, lang, next, split, - get = function (k) { - if (!languages[k] && hasModule) { - try { - require('./lang/' + k); - } catch (e) { } - } - return languages[k]; - }; - - if (!key) { - return moment.fn._lang; - } - - if (!isArray(key)) { - //short-circuit everything else - lang = get(key); - if (lang) { - return lang; - } - key = [key]; - } - - //pick the language from the array - //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each - //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root - while (i < key.length) { - split = normalizeLanguage(key[i]).split('-'); - j = split.length; - next = normalizeLanguage(key[i + 1]); - next = next ? next.split('-') : null; - while (j > 0) { - lang = get(split.slice(0, j).join('-')); - if (lang) { - return lang; - } - if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { - //the next array item is better than a shallower substring of this one - break; - } - j--; - } - i++; - } - return moment.fn._lang; - } - - /************************************ - Formatting - ************************************/ - - - function removeFormattingTokens(input) { - if (input.match(/\[[\s\S]/)) { - return input.replace(/^\[|\]$/g, ""); - } - return input.replace(/\\/g, ""); - } - - function makeFormatFunction(format) { - var array = format.match(formattingTokens), i, length; - - for (i = 0, length = array.length; i < length; i++) { - if (formatTokenFunctions[array[i]]) { - array[i] = formatTokenFunctions[array[i]]; - } else { - array[i] = removeFormattingTokens(array[i]); - } - } - - return function (mom) { - var output = ""; - for (i = 0; i < length; i++) { - output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; - } - return output; - }; - } - - // format date using native date object - function formatMoment(m, format) { - - if (!m.isValid()) { - return m.lang().invalidDate(); - } - - format = expandFormat(format, m.lang()); - - if (!formatFunctions[format]) { - formatFunctions[format] = makeFormatFunction(format); - } - - return formatFunctions[format](m); - } - - function expandFormat(format, lang) { - var i = 5; - - function replaceLongDateFormatTokens(input) { - return lang.longDateFormat(input) || input; - } - - localFormattingTokens.lastIndex = 0; - while (i >= 0 && localFormattingTokens.test(format)) { - format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); - localFormattingTokens.lastIndex = 0; - i -= 1; - } - - return format; - } - - - /************************************ - Parsing - ************************************/ - - - // get the regex to find the next token - function getParseRegexForToken(token, config) { - var a, strict = config._strict; - switch (token) { - case 'Q': - return parseTokenOneDigit; - case 'DDDD': - return parseTokenThreeDigits; - case 'YYYY': - case 'GGGG': - case 'gggg': - return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; - case 'Y': - case 'G': - case 'g': - return parseTokenSignedNumber; - case 'YYYYYY': - case 'YYYYY': - case 'GGGGG': - case 'ggggg': - return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; - case 'S': - if (strict) { return parseTokenOneDigit; } - /* falls through */ - case 'SS': - if (strict) { return parseTokenTwoDigits; } - /* falls through */ - case 'SSS': - if (strict) { return parseTokenThreeDigits; } - /* falls through */ - case 'DDD': - return parseTokenOneToThreeDigits; - case 'MMM': - case 'MMMM': - case 'dd': - case 'ddd': - case 'dddd': - return parseTokenWord; - case 'a': - case 'A': - return getLangDefinition(config._l)._meridiemParse; - case 'X': - return parseTokenTimestampMs; - case 'Z': - case 'ZZ': - return parseTokenTimezone; - case 'T': - return parseTokenT; - case 'SSSS': - return parseTokenDigits; - case 'MM': - case 'DD': - case 'YY': - case 'GG': - case 'gg': - case 'HH': - case 'hh': - case 'mm': - case 'ss': - case 'ww': - case 'WW': - return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; - case 'M': - case 'D': - case 'd': - case 'H': - case 'h': - case 'm': - case 's': - case 'w': - case 'W': - case 'e': - case 'E': - return parseTokenOneOrTwoDigits; - case 'Do': - return parseTokenOrdinal; - default : - a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i")); - return a; - } - } - - function timezoneMinutesFromString(string) { - string = string || ""; - var possibleTzMatches = (string.match(parseTokenTimezone) || []), - tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], - parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], - minutes = +(parts[1] * 60) + toInt(parts[2]); - - return parts[0] === '+' ? -minutes : minutes; - } - - // function to convert string input to date - function addTimeToArrayFromToken(token, input, config) { - var a, datePartArray = config._a; - - switch (token) { - // QUARTER - case 'Q': - if (input != null) { - datePartArray[MONTH] = (toInt(input) - 1) * 3; - } - break; - // MONTH - case 'M' : // fall through to MM - case 'MM' : - if (input != null) { - datePartArray[MONTH] = toInt(input) - 1; - } - break; - case 'MMM' : // fall through to MMMM - case 'MMMM' : - a = getLangDefinition(config._l).monthsParse(input); - // if we didn't find a month name, mark the date as invalid. - if (a != null) { - datePartArray[MONTH] = a; - } else { - config._pf.invalidMonth = input; - } - break; - // DAY OF MONTH - case 'D' : // fall through to DD - case 'DD' : - if (input != null) { - datePartArray[DATE] = toInt(input); - } - break; - case 'Do' : - if (input != null) { - datePartArray[DATE] = toInt(parseInt(input, 10)); - } - break; - // DAY OF YEAR - case 'DDD' : // fall through to DDDD - case 'DDDD' : - if (input != null) { - config._dayOfYear = toInt(input); - } - - break; - // YEAR - case 'YY' : - datePartArray[YEAR] = moment.parseTwoDigitYear(input); - break; - case 'YYYY' : - case 'YYYYY' : - case 'YYYYYY' : - datePartArray[YEAR] = toInt(input); - break; - // AM / PM - case 'a' : // fall through to A - case 'A' : - config._isPm = getLangDefinition(config._l).isPM(input); - break; - // 24 HOUR - case 'H' : // fall through to hh - case 'HH' : // fall through to hh - case 'h' : // fall through to hh - case 'hh' : - datePartArray[HOUR] = toInt(input); - break; - // MINUTE - case 'm' : // fall through to mm - case 'mm' : - datePartArray[MINUTE] = toInt(input); - break; - // SECOND - case 's' : // fall through to ss - case 'ss' : - datePartArray[SECOND] = toInt(input); - break; - // MILLISECOND - case 'S' : - case 'SS' : - case 'SSS' : - case 'SSSS' : - datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); - break; - // UNIX TIMESTAMP WITH MS - case 'X': - config._d = new Date(parseFloat(input) * 1000); - break; - // TIMEZONE - case 'Z' : // fall through to ZZ - case 'ZZ' : - config._useUTC = true; - config._tzm = timezoneMinutesFromString(input); - break; - // WEEKDAY - human - case 'dd': - case 'ddd': - case 'dddd': - a = getLangDefinition(config._l).weekdaysParse(input); - // if we didn't get a weekday name, mark the date as invalid - if (a != null) { - config._w = config._w || {}; - config._w['d'] = a; - } else { - config._pf.invalidWeekday = input; - } - break; - // WEEK, WEEK DAY - numeric - case 'w': - case 'ww': - case 'W': - case 'WW': - case 'd': - case 'e': - case 'E': - token = token.substr(0, 1); - /* falls through */ - case 'gggg': - case 'GGGG': - case 'GGGGG': - token = token.substr(0, 2); - if (input) { - config._w = config._w || {}; - config._w[token] = toInt(input); - } - break; - case 'gg': - case 'GG': - config._w = config._w || {}; - config._w[token] = moment.parseTwoDigitYear(input); - } - } - - function dayOfYearFromWeekInfo(config) { - var w, weekYear, week, weekday, dow, doy, temp, lang; - - w = config._w; - if (w.GG != null || w.W != null || w.E != null) { - dow = 1; - doy = 4; - - // TODO: We need to take the current isoWeekYear, but that depends on - // how we interpret now (local, utc, fixed offset). So create - // a now version of current config (take local/utc/offset flags, and - // create now). - weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year); - week = dfl(w.W, 1); - weekday = dfl(w.E, 1); - } else { - lang = getLangDefinition(config._l); - dow = lang._week.dow; - doy = lang._week.doy; - - weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); - week = dfl(w.w, 1); - - if (w.d != null) { - // weekday -- low day numbers are considered next week - weekday = w.d; - if (weekday < dow) { - ++week; - } - } else if (w.e != null) { - // local weekday -- counting starts from begining of week - weekday = w.e + dow; - } else { - // default to begining of week - weekday = dow; - } - } - temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); - - config._a[YEAR] = temp.year; - config._dayOfYear = temp.dayOfYear; - } - - // convert an array to a date. - // the array should mirror the parameters below - // note: all values past the year are optional and will default to the lowest possible value. - // [year, month, day , hour, minute, second, millisecond] - function dateFromConfig(config) { - var i, date, input = [], currentDate, yearToUse; - - if (config._d) { - return; - } - - currentDate = currentDateArray(config); - - //compute day of the year from weeks and weekdays - if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { - dayOfYearFromWeekInfo(config); - } - - //if the day of the year is set, figure out what it is - if (config._dayOfYear) { - yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); - - if (config._dayOfYear > daysInYear(yearToUse)) { - config._pf._overflowDayOfYear = true; - } - - date = makeUTCDate(yearToUse, 0, config._dayOfYear); - config._a[MONTH] = date.getUTCMonth(); - config._a[DATE] = date.getUTCDate(); - } - - // Default to current date. - // * if no year, month, day of month are given, default to today - // * if day of month is given, default month and year - // * if month is given, default only year - // * if year is given, don't default anything - for (i = 0; i < 3 && config._a[i] == null; ++i) { - config._a[i] = input[i] = currentDate[i]; - } - - // Zero out whatever was not defaulted, including time - for (; i < 7; i++) { - config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; - } - - config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); - // Apply timezone offset from input. The actual zone can be changed - // with parseZone. - if (config._tzm != null) { - config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm); - } - } - - function dateFromObject(config) { - var normalizedInput; - - if (config._d) { - return; - } - - normalizedInput = normalizeObjectUnits(config._i); - config._a = [ - normalizedInput.year, - normalizedInput.month, - normalizedInput.day, - normalizedInput.hour, - normalizedInput.minute, - normalizedInput.second, - normalizedInput.millisecond - ]; - - dateFromConfig(config); - } - - function currentDateArray(config) { - var now = new Date(); - if (config._useUTC) { - return [ - now.getUTCFullYear(), - now.getUTCMonth(), - now.getUTCDate() - ]; - } else { - return [now.getFullYear(), now.getMonth(), now.getDate()]; - } - } - - // date from string and format string - function makeDateFromStringAndFormat(config) { - - if (config._f === moment.ISO_8601) { - parseISO(config); - return; - } - - config._a = []; - config._pf.empty = true; - - // This array is used to make a Date, either with `new Date` or `Date.UTC` - var lang = getLangDefinition(config._l), - string = '' + config._i, - i, parsedInput, tokens, token, skipped, - stringLength = string.length, - totalParsedInputLength = 0; - - tokens = expandFormat(config._f, lang).match(formattingTokens) || []; - - for (i = 0; i < tokens.length; i++) { - token = tokens[i]; - parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; - if (parsedInput) { - skipped = string.substr(0, string.indexOf(parsedInput)); - if (skipped.length > 0) { - config._pf.unusedInput.push(skipped); - } - string = string.slice(string.indexOf(parsedInput) + parsedInput.length); - totalParsedInputLength += parsedInput.length; - } - // don't parse if it's not a known token - if (formatTokenFunctions[token]) { - if (parsedInput) { - config._pf.empty = false; - } - else { - config._pf.unusedTokens.push(token); - } - addTimeToArrayFromToken(token, parsedInput, config); - } - else if (config._strict && !parsedInput) { - config._pf.unusedTokens.push(token); - } - } - - // add remaining unparsed input length to the string - config._pf.charsLeftOver = stringLength - totalParsedInputLength; - if (string.length > 0) { - config._pf.unusedInput.push(string); - } - - // handle am pm - if (config._isPm && config._a[HOUR] < 12) { - config._a[HOUR] += 12; - } - // if is 12 am, change hours to 0 - if (config._isPm === false && config._a[HOUR] === 12) { - config._a[HOUR] = 0; - } - - dateFromConfig(config); - checkOverflow(config); - } - - function unescapeFormat(s) { - return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { - return p1 || p2 || p3 || p4; - }); - } - - // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript - function regexpEscape(s) { - return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - } - - // date from string and array of format strings - function makeDateFromStringAndArray(config) { - var tempConfig, - bestMoment, - - scoreToBeat, - i, - currentScore; - - if (config._f.length === 0) { - config._pf.invalidFormat = true; - config._d = new Date(NaN); - return; - } - - for (i = 0; i < config._f.length; i++) { - currentScore = 0; - tempConfig = extend({}, config); - tempConfig._pf = defaultParsingFlags(); - tempConfig._f = config._f[i]; - makeDateFromStringAndFormat(tempConfig); - - if (!isValid(tempConfig)) { - continue; - } - - // if there is any input that was not parsed add a penalty for that format - currentScore += tempConfig._pf.charsLeftOver; - - //or tokens - currentScore += tempConfig._pf.unusedTokens.length * 10; - - tempConfig._pf.score = currentScore; - - if (scoreToBeat == null || currentScore < scoreToBeat) { - scoreToBeat = currentScore; - bestMoment = tempConfig; - } - } - - extend(config, bestMoment || tempConfig); - } - - // date from iso format - function parseISO(config) { - var i, l, - string = config._i, - match = isoRegex.exec(string); - - if (match) { - config._pf.iso = true; - for (i = 0, l = isoDates.length; i < l; i++) { - if (isoDates[i][1].exec(string)) { - // match[5] should be "T" or undefined - config._f = isoDates[i][0] + (match[6] || " "); - break; - } - } - for (i = 0, l = isoTimes.length; i < l; i++) { - if (isoTimes[i][1].exec(string)) { - config._f += isoTimes[i][0]; - break; - } - } - if (string.match(parseTokenTimezone)) { - config._f += "Z"; - } - makeDateFromStringAndFormat(config); - } else { - config._isValid = false; - } - } - - // date from iso format or fallback - function makeDateFromString(config) { - parseISO(config); - if (config._isValid === false) { - delete config._isValid; - moment.createFromInputFallback(config); - } - } - - function makeDateFromInput(config) { - var input = config._i, - matched = aspNetJsonRegex.exec(input); - - if (input === undefined) { - config._d = new Date(); - } else if (matched) { - config._d = new Date(+matched[1]); - } else if (typeof input === 'string') { - makeDateFromString(config); - } else if (isArray(input)) { - config._a = input.slice(0); - dateFromConfig(config); - } else if (isDate(input)) { - config._d = new Date(+input); - } else if (typeof(input) === 'object') { - dateFromObject(config); - } else if (typeof(input) === 'number') { - // from milliseconds - config._d = new Date(input); - } else { - moment.createFromInputFallback(config); - } - } - - function makeDate(y, m, d, h, M, s, ms) { - //can't just apply() to create a date: - //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply - var date = new Date(y, m, d, h, M, s, ms); - - //the date constructor doesn't accept years < 1970 - if (y < 1970) { - date.setFullYear(y); - } - return date; - } - - function makeUTCDate(y) { - var date = new Date(Date.UTC.apply(null, arguments)); - if (y < 1970) { - date.setUTCFullYear(y); - } - return date; - } - - function parseWeekday(input, language) { - if (typeof input === 'string') { - if (!isNaN(input)) { - input = parseInt(input, 10); - } - else { - input = language.weekdaysParse(input); - if (typeof input !== 'number') { - return null; - } - } - } - return input; - } - - /************************************ - Relative Time - ************************************/ - - - // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize - function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { - return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); - } - - function relativeTime(milliseconds, withoutSuffix, lang) { - var seconds = round(Math.abs(milliseconds) / 1000), - minutes = round(seconds / 60), - hours = round(minutes / 60), - days = round(hours / 24), - years = round(days / 365), - args = seconds < relativeTimeThresholds.s && ['s', seconds] || - minutes === 1 && ['m'] || - minutes < relativeTimeThresholds.m && ['mm', minutes] || - hours === 1 && ['h'] || - hours < relativeTimeThresholds.h && ['hh', hours] || - days === 1 && ['d'] || - days <= relativeTimeThresholds.dd && ['dd', days] || - days <= relativeTimeThresholds.dm && ['M'] || - days < relativeTimeThresholds.dy && ['MM', round(days / 30)] || - years === 1 && ['y'] || ['yy', years]; - args[2] = withoutSuffix; - args[3] = milliseconds > 0; - args[4] = lang; - return substituteTimeAgo.apply({}, args); - } - - - /************************************ - Week of Year - ************************************/ - - - // firstDayOfWeek 0 = sun, 6 = sat - // the day of the week that starts the week - // (usually sunday or monday) - // firstDayOfWeekOfYear 0 = sun, 6 = sat - // the first week is the week that contains the first - // of this day of the week - // (eg. ISO weeks use thursday (4)) - function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { - var end = firstDayOfWeekOfYear - firstDayOfWeek, - daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), - adjustedMoment; - - - if (daysToDayOfWeek > end) { - daysToDayOfWeek -= 7; - } - - if (daysToDayOfWeek < end - 7) { - daysToDayOfWeek += 7; - } - - adjustedMoment = moment(mom).add('d', daysToDayOfWeek); - return { - week: Math.ceil(adjustedMoment.dayOfYear() / 7), - year: adjustedMoment.year() - }; - } - - //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday - function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { - var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; - - d = d === 0 ? 7 : d; - weekday = weekday != null ? weekday : firstDayOfWeek; - daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); - dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; - - return { - year: dayOfYear > 0 ? year : year - 1, - dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear - }; - } - - /************************************ - Top Level Functions - ************************************/ - - function makeMoment(config) { - var input = config._i, - format = config._f; - - if (input === null || (format === undefined && input === '')) { - return moment.invalid({nullInput: true}); - } - - if (typeof input === 'string') { - config._i = input = getLangDefinition().preparse(input); - } - - if (moment.isMoment(input)) { - config = cloneMoment(input); - - config._d = new Date(+input._d); - } else if (format) { - if (isArray(format)) { - makeDateFromStringAndArray(config); - } else { - makeDateFromStringAndFormat(config); - } - } else { - makeDateFromInput(config); - } - - return new Moment(config); - } - - moment = function (input, format, lang, strict) { - var c; - - if (typeof(lang) === "boolean") { - strict = lang; - lang = undefined; - } - // object construction must be done this way. - // https://github.com/moment/moment/issues/1423 - c = {}; - c._isAMomentObject = true; - c._i = input; - c._f = format; - c._l = lang; - c._strict = strict; - c._isUTC = false; - c._pf = defaultParsingFlags(); - - return makeMoment(c); - }; - - moment.suppressDeprecationWarnings = false; - - moment.createFromInputFallback = deprecate( - "moment construction falls back to js Date. This is " + - "discouraged and will be removed in upcoming major " + - "release. Please refer to " + - "https://github.com/moment/moment/issues/1407 for more info.", - function (config) { - config._d = new Date(config._i); - }); - - // Pick a moment m from moments so that m[fn](other) is true for all - // other. This relies on the function fn to be transitive. - // - // moments should either be an array of moment objects or an array, whose - // first element is an array of moment objects. - function pickBy(fn, moments) { - var res, i; - if (moments.length === 1 && isArray(moments[0])) { - moments = moments[0]; - } - if (!moments.length) { - return moment(); - } - res = moments[0]; - for (i = 1; i < moments.length; ++i) { - if (moments[i][fn](res)) { - res = moments[i]; - } - } - return res; - } - - moment.min = function () { - var args = [].slice.call(arguments, 0); - - return pickBy('isBefore', args); - }; - - moment.max = function () { - var args = [].slice.call(arguments, 0); - - return pickBy('isAfter', args); - }; - - // creating with utc - moment.utc = function (input, format, lang, strict) { - var c; - - if (typeof(lang) === "boolean") { - strict = lang; - lang = undefined; - } - // object construction must be done this way. - // https://github.com/moment/moment/issues/1423 - c = {}; - c._isAMomentObject = true; - c._useUTC = true; - c._isUTC = true; - c._l = lang; - c._i = input; - c._f = format; - c._strict = strict; - c._pf = defaultParsingFlags(); - - return makeMoment(c).utc(); - }; - - // creating with unix timestamp (in seconds) - moment.unix = function (input) { - return moment(input * 1000); - }; - - // duration - moment.duration = function (input, key) { - var duration = input, - // matching against regexp is expensive, do it on demand - match = null, - sign, - ret, - parseIso; - - if (moment.isDuration(input)) { - duration = { - ms: input._milliseconds, - d: input._days, - M: input._months - }; - } else if (typeof input === 'number') { - duration = {}; - if (key) { - duration[key] = input; - } else { - duration.milliseconds = input; - } - } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { - sign = (match[1] === "-") ? -1 : 1; - duration = { - y: 0, - d: toInt(match[DATE]) * sign, - h: toInt(match[HOUR]) * sign, - m: toInt(match[MINUTE]) * sign, - s: toInt(match[SECOND]) * sign, - ms: toInt(match[MILLISECOND]) * sign - }; - } else if (!!(match = isoDurationRegex.exec(input))) { - sign = (match[1] === "-") ? -1 : 1; - parseIso = function (inp) { - // We'd normally use ~~inp for this, but unfortunately it also - // converts floats to ints. - // inp may be undefined, so careful calling replace on it. - var res = inp && parseFloat(inp.replace(',', '.')); - // apply sign while we're at it - return (isNaN(res) ? 0 : res) * sign; - }; - duration = { - y: parseIso(match[2]), - M: parseIso(match[3]), - d: parseIso(match[4]), - h: parseIso(match[5]), - m: parseIso(match[6]), - s: parseIso(match[7]), - w: parseIso(match[8]) - }; - } - - ret = new Duration(duration); - - if (moment.isDuration(input) && input.hasOwnProperty('_lang')) { - ret._lang = input._lang; - } - - return ret; - }; - - // version number - moment.version = VERSION; - - // default format - moment.defaultFormat = isoFormat; - - // constant that refers to the ISO standard - moment.ISO_8601 = function () {}; - - // Plugins that add properties should also add the key here (null value), - // so we can properly clone ourselves. - moment.momentProperties = momentProperties; - - // This function will be called whenever a moment is mutated. - // It is intended to keep the offset in sync with the timezone. - moment.updateOffset = function () {}; - - // This function allows you to set a threshold for relative time strings - moment.relativeTimeThreshold = function(threshold, limit) { - if (relativeTimeThresholds[threshold] === undefined) { - return false; - } - relativeTimeThresholds[threshold] = limit; - return true; - }; - - // This function will load languages and then set the global language. If - // no arguments are passed in, it will simply return the current global - // language key. - moment.lang = function (key, values) { - var r; - if (!key) { - return moment.fn._lang._abbr; - } - if (values) { - loadLang(normalizeLanguage(key), values); - } else if (values === null) { - unloadLang(key); - key = 'en'; - } else if (!languages[key]) { - getLangDefinition(key); - } - r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); - return r._abbr; - }; - - // returns language data - moment.langData = function (key) { - if (key && key._lang && key._lang._abbr) { - key = key._lang._abbr; - } - return getLangDefinition(key); - }; - - // compare moment object - moment.isMoment = function (obj) { - return obj instanceof Moment || - (obj != null && obj.hasOwnProperty('_isAMomentObject')); - }; - - // for typechecking Duration objects - moment.isDuration = function (obj) { - return obj instanceof Duration; - }; - - for (i = lists.length - 1; i >= 0; --i) { - makeList(lists[i]); - } - - moment.normalizeUnits = function (units) { - return normalizeUnits(units); - }; - - moment.invalid = function (flags) { - var m = moment.utc(NaN); - if (flags != null) { - extend(m._pf, flags); - } - else { - m._pf.userInvalidated = true; - } - - return m; - }; - - moment.parseZone = function () { - return moment.apply(null, arguments).parseZone(); - }; - - moment.parseTwoDigitYear = function (input) { - return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); - }; - - /************************************ - Moment Prototype - ************************************/ - - - extend(moment.fn = Moment.prototype, { - - clone : function () { - return moment(this); - }, - - valueOf : function () { - return +this._d + ((this._offset || 0) * 60000); - }, - - unix : function () { - return Math.floor(+this / 1000); - }, - - toString : function () { - return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); - }, - - toDate : function () { - return this._offset ? new Date(+this) : this._d; - }, - - toISOString : function () { - var m = moment(this).utc(); - if (0 < m.year() && m.year() <= 9999) { - return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - } else { - return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - } - }, - - toArray : function () { - var m = this; - return [ - m.year(), - m.month(), - m.date(), - m.hours(), - m.minutes(), - m.seconds(), - m.milliseconds() - ]; - }, - - isValid : function () { - return isValid(this); - }, - - isDSTShifted : function () { - - if (this._a) { - return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; - } - - return false; - }, - - parsingFlags : function () { - return extend({}, this._pf); - }, - - invalidAt: function () { - return this._pf.overflow; - }, - - utc : function () { - return this.zone(0); - }, - - local : function () { - this.zone(0); - this._isUTC = false; - return this; - }, - - format : function (inputString) { - var output = formatMoment(this, inputString || moment.defaultFormat); - return this.lang().postformat(output); - }, - - add : function (input, val) { - var dur; - // switch args to support add('s', 1) and add(1, 's') - if (typeof input === 'string' && typeof val === 'string') { - dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input); - } else if (typeof input === 'string') { - dur = moment.duration(+val, input); - } else { - dur = moment.duration(input, val); - } - addOrSubtractDurationFromMoment(this, dur, 1); - return this; - }, - - subtract : function (input, val) { - var dur; - // switch args to support subtract('s', 1) and subtract(1, 's') - if (typeof input === 'string' && typeof val === 'string') { - dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input); - } else if (typeof input === 'string') { - dur = moment.duration(+val, input); - } else { - dur = moment.duration(input, val); - } - addOrSubtractDurationFromMoment(this, dur, -1); - return this; - }, - - diff : function (input, units, asFloat) { - var that = makeAs(input, this), - zoneDiff = (this.zone() - that.zone()) * 6e4, - diff, output; - - units = normalizeUnits(units); - - if (units === 'year' || units === 'month') { - // average number of days in the months in the given dates - diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 - // difference in months - output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); - // adjust by taking difference in days, average number of days - // and dst in the given months. - output += ((this - moment(this).startOf('month')) - - (that - moment(that).startOf('month'))) / diff; - // same as above but with zones, to negate all dst - output -= ((this.zone() - moment(this).startOf('month').zone()) - - (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff; - if (units === 'year') { - output = output / 12; - } - } else { - diff = (this - that); - output = units === 'second' ? diff / 1e3 : // 1000 - units === 'minute' ? diff / 6e4 : // 1000 * 60 - units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 - units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst - units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst - diff; - } - return asFloat ? output : absRound(output); - }, - - from : function (time, withoutSuffix) { - return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); - }, - - fromNow : function (withoutSuffix) { - return this.from(moment(), withoutSuffix); - }, - - calendar : function (time) { - // We want to compare the start of today, vs this. - // Getting start-of-today depends on whether we're zone'd or not. - var now = time || moment(), - sod = makeAs(now, this).startOf('day'), - diff = this.diff(sod, 'days', true), - format = diff < -6 ? 'sameElse' : - diff < -1 ? 'lastWeek' : - diff < 0 ? 'lastDay' : - diff < 1 ? 'sameDay' : - diff < 2 ? 'nextDay' : - diff < 7 ? 'nextWeek' : 'sameElse'; - return this.format(this.lang().calendar(format, this)); - }, - - isLeapYear : function () { - return isLeapYear(this.year()); - }, - - isDST : function () { - return (this.zone() < this.clone().month(0).zone() || - this.zone() < this.clone().month(5).zone()); - }, - - day : function (input) { - var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); - if (input != null) { - input = parseWeekday(input, this.lang()); - return this.add({ d : input - day }); - } else { - return day; - } - }, - - month : makeAccessor('Month', true), - - startOf: function (units) { - units = normalizeUnits(units); - // the following switch intentionally omits break keywords - // to utilize falling through the cases. - switch (units) { - case 'year': - this.month(0); - /* falls through */ - case 'quarter': - case 'month': - this.date(1); - /* falls through */ - case 'week': - case 'isoWeek': - case 'day': - this.hours(0); - /* falls through */ - case 'hour': - this.minutes(0); - /* falls through */ - case 'minute': - this.seconds(0); - /* falls through */ - case 'second': - this.milliseconds(0); - /* falls through */ - } - - // weeks are a special case - if (units === 'week') { - this.weekday(0); - } else if (units === 'isoWeek') { - this.isoWeekday(1); - } - - // quarters are also special - if (units === 'quarter') { - this.month(Math.floor(this.month() / 3) * 3); - } - - return this; - }, - - endOf: function (units) { - units = normalizeUnits(units); - return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1); - }, - - isAfter: function (input, units) { - units = typeof units !== 'undefined' ? units : 'millisecond'; - return +this.clone().startOf(units) > +moment(input).startOf(units); - }, - - isBefore: function (input, units) { - units = typeof units !== 'undefined' ? units : 'millisecond'; - return +this.clone().startOf(units) < +moment(input).startOf(units); - }, - - isSame: function (input, units) { - units = units || 'ms'; - return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); - }, - - min: deprecate( - "moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548", - function (other) { - other = moment.apply(null, arguments); - return other < this ? this : other; - } - ), - - max: deprecate( - "moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548", - function (other) { - other = moment.apply(null, arguments); - return other > this ? this : other; - } - ), - - // keepTime = true means only change the timezone, without affecting - // the local hour. So 5:31:26 +0300 --[zone(2, true)]--> 5:31:26 +0200 - // It is possible that 5:31:26 doesn't exist int zone +0200, so we - // adjust the time as needed, to be valid. - // - // Keeping the time actually adds/subtracts (one hour) - // from the actual represented time. That is why we call updateOffset - // a second time. In case it wants us to change the offset again - // _changeInProgress == true case, then we have to adjust, because - // there is no such time in the given timezone. - zone : function (input, keepTime) { - var offset = this._offset || 0; - if (input != null) { - if (typeof input === "string") { - input = timezoneMinutesFromString(input); - } - if (Math.abs(input) < 16) { - input = input * 60; - } - this._offset = input; - this._isUTC = true; - if (offset !== input) { - if (!keepTime || this._changeInProgress) { - addOrSubtractDurationFromMoment(this, - moment.duration(offset - input, 'm'), 1, false); - } else if (!this._changeInProgress) { - this._changeInProgress = true; - moment.updateOffset(this, true); - this._changeInProgress = null; - } - } - } else { - return this._isUTC ? offset : this._d.getTimezoneOffset(); - } - return this; - }, - - zoneAbbr : function () { - return this._isUTC ? "UTC" : ""; - }, - - zoneName : function () { - return this._isUTC ? "Coordinated Universal Time" : ""; - }, - - parseZone : function () { - if (this._tzm) { - this.zone(this._tzm); - } else if (typeof this._i === 'string') { - this.zone(this._i); - } - return this; - }, - - hasAlignedHourOffset : function (input) { - if (!input) { - input = 0; - } - else { - input = moment(input).zone(); - } - - return (this.zone() - input) % 60 === 0; - }, - - daysInMonth : function () { - return daysInMonth(this.year(), this.month()); - }, - - dayOfYear : function (input) { - var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; - return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); - }, - - quarter : function (input) { - return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); - }, - - weekYear : function (input) { - var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year; - return input == null ? year : this.add("y", (input - year)); - }, - - isoWeekYear : function (input) { - var year = weekOfYear(this, 1, 4).year; - return input == null ? year : this.add("y", (input - year)); - }, - - week : function (input) { - var week = this.lang().week(this); - return input == null ? week : this.add("d", (input - week) * 7); - }, - - isoWeek : function (input) { - var week = weekOfYear(this, 1, 4).week; - return input == null ? week : this.add("d", (input - week) * 7); - }, - - weekday : function (input) { - var weekday = (this.day() + 7 - this.lang()._week.dow) % 7; - return input == null ? weekday : this.add("d", input - weekday); - }, - - isoWeekday : function (input) { - // behaves the same as moment#day except - // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) - // as a setter, sunday should belong to the previous week. - return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); - }, - - isoWeeksInYear : function () { - return weeksInYear(this.year(), 1, 4); - }, - - weeksInYear : function () { - var weekInfo = this._lang._week; - return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); - }, - - get : function (units) { - units = normalizeUnits(units); - return this[units](); - }, - - set : function (units, value) { - units = normalizeUnits(units); - if (typeof this[units] === 'function') { - this[units](value); - } - return this; - }, - - // If passed a language key, it will set the language for this - // instance. Otherwise, it will return the language configuration - // variables for this instance. - lang : function (key) { - if (key === undefined) { - return this._lang; - } else { - this._lang = getLangDefinition(key); - return this; - } - } - }); - - function rawMonthSetter(mom, value) { - var dayOfMonth; - - // TODO: Move this out of here! - if (typeof value === 'string') { - value = mom.lang().monthsParse(value); - // TODO: Another silent failure? - if (typeof value !== 'number') { - return mom; - } - } - - dayOfMonth = Math.min(mom.date(), - daysInMonth(mom.year(), value)); - mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); - return mom; - } - - function rawGetter(mom, unit) { - return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); - } - - function rawSetter(mom, unit, value) { - if (unit === 'Month') { - return rawMonthSetter(mom, value); - } else { - return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); - } - } - - function makeAccessor(unit, keepTime) { - return function (value) { - if (value != null) { - rawSetter(this, unit, value); - moment.updateOffset(this, keepTime); - return this; - } else { - return rawGetter(this, unit); - } - }; - } - - moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false); - moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false); - moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false); - // Setting the hour should keep the time, because the user explicitly - // specified which hour he wants. So trying to maintain the same hour (in - // a new timezone) makes sense. Adding/subtracting hours does not follow - // this rule. - moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true); - // moment.fn.month is defined separately - moment.fn.date = makeAccessor('Date', true); - moment.fn.dates = deprecate("dates accessor is deprecated. Use date instead.", makeAccessor('Date', true)); - moment.fn.year = makeAccessor('FullYear', true); - moment.fn.years = deprecate("years accessor is deprecated. Use year instead.", makeAccessor('FullYear', true)); - - // add plural methods - moment.fn.days = moment.fn.day; - moment.fn.months = moment.fn.month; - moment.fn.weeks = moment.fn.week; - moment.fn.isoWeeks = moment.fn.isoWeek; - moment.fn.quarters = moment.fn.quarter; - - // add aliased format methods - moment.fn.toJSON = moment.fn.toISOString; - - /************************************ - Duration Prototype - ************************************/ - - - extend(moment.duration.fn = Duration.prototype, { - - _bubble : function () { - var milliseconds = this._milliseconds, - days = this._days, - months = this._months, - data = this._data, - seconds, minutes, hours, years; - - // The following code bubbles up values, see the tests for - // examples of what that means. - data.milliseconds = milliseconds % 1000; - - seconds = absRound(milliseconds / 1000); - data.seconds = seconds % 60; - - minutes = absRound(seconds / 60); - data.minutes = minutes % 60; - - hours = absRound(minutes / 60); - data.hours = hours % 24; - - days += absRound(hours / 24); - data.days = days % 30; - - months += absRound(days / 30); - data.months = months % 12; - - years = absRound(months / 12); - data.years = years; - }, - - weeks : function () { - return absRound(this.days() / 7); - }, - - valueOf : function () { - return this._milliseconds + - this._days * 864e5 + - (this._months % 12) * 2592e6 + - toInt(this._months / 12) * 31536e6; - }, - - humanize : function (withSuffix) { - var difference = +this, - output = relativeTime(difference, !withSuffix, this.lang()); - - if (withSuffix) { - output = this.lang().pastFuture(difference, output); - } - - return this.lang().postformat(output); - }, - - add : function (input, val) { - // supports only 2.0-style add(1, 's') or add(moment) - var dur = moment.duration(input, val); - - this._milliseconds += dur._milliseconds; - this._days += dur._days; - this._months += dur._months; - - this._bubble(); - - return this; - }, - - subtract : function (input, val) { - var dur = moment.duration(input, val); - - this._milliseconds -= dur._milliseconds; - this._days -= dur._days; - this._months -= dur._months; - - this._bubble(); - - return this; - }, - - get : function (units) { - units = normalizeUnits(units); - return this[units.toLowerCase() + 's'](); - }, - - as : function (units) { - units = normalizeUnits(units); - return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's'](); - }, - - lang : moment.fn.lang, - - toIsoString : function () { - // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js - var years = Math.abs(this.years()), - months = Math.abs(this.months()), - days = Math.abs(this.days()), - hours = Math.abs(this.hours()), - minutes = Math.abs(this.minutes()), - seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); - - if (!this.asSeconds()) { - // this is the same as C#'s (Noda) and python (isodate)... - // but not other JS (goog.date) - return 'P0D'; - } - - return (this.asSeconds() < 0 ? '-' : '') + - 'P' + - (years ? years + 'Y' : '') + - (months ? months + 'M' : '') + - (days ? days + 'D' : '') + - ((hours || minutes || seconds) ? 'T' : '') + - (hours ? hours + 'H' : '') + - (minutes ? minutes + 'M' : '') + - (seconds ? seconds + 'S' : ''); - } - }); - - function makeDurationGetter(name) { - moment.duration.fn[name] = function () { - return this._data[name]; - }; - } - - function makeDurationAsGetter(name, factor) { - moment.duration.fn['as' + name] = function () { - return +this / factor; - }; - } - - for (i in unitMillisecondFactors) { - if (unitMillisecondFactors.hasOwnProperty(i)) { - makeDurationAsGetter(i, unitMillisecondFactors[i]); - makeDurationGetter(i.toLowerCase()); - } - } - - makeDurationAsGetter('Weeks', 6048e5); - moment.duration.fn.asMonths = function () { - return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12; - }; - - - /************************************ - Default Lang - ************************************/ - - - // Set default language, other languages will inherit from English. - moment.lang('en', { - ordinal : function (number) { - var b = number % 10, - output = (toInt(number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - return number + output; - } - }); - - /* EMBED_LANGUAGES */ - - /************************************ - Exposing Moment - ************************************/ - - function makeGlobal(shouldDeprecate) { - /*global ender:false */ - if (typeof ender !== 'undefined') { - return; - } - oldGlobalMoment = globalScope.moment; - if (shouldDeprecate) { - globalScope.moment = deprecate( - "Accessing Moment through the global scope is " + - "deprecated, and will be removed in an upcoming " + - "release.", - moment); - } else { - globalScope.moment = moment; - } - } - - // CommonJS module is defined - if (hasModule) { - module.exports = moment; - } else if (typeof define === "function" && define.amd) { - define("moment", function (require, exports, module) { - if (module.config && module.config() && module.config().noGlobal === true) { - // release the global variable - globalScope.moment = oldGlobalMoment; - } - - return moment; - }); - makeGlobal(true); - } else { - makeGlobal(); - } -}).call(this); diff --git a/site/assets/js/platform.js b/site/assets/js/platform.js deleted file mode 100644 index 8448813fe..000000000 --- a/site/assets/js/platform.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ -// @version: 0.2.3 - -window.Platform=window.Platform||{},window.logFlags=window.logFlags||{},function(a){var b=a.flags||{};location.search.slice(1).split("&").forEach(function(a){a=a.split("="),a[0]&&(b[a[0]]=a[1]||!0)});var c=document.currentScript||document.querySelector('script[src*="platform.js"]');if(c)for(var d,e=c.attributes,f=0;f1&&console.warn("platform.js is not the first script on the page. See http://www.polymer-project.org/docs/start/platform.html#setup for details."),b.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=b.register),b.imports&&(window.HTMLImports=window.HTMLImports||{flags:{}},window.HTMLImports.flags.imports=b.imports),a.flags=b}(Platform),"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),function(global){"use strict";function detectObjectObserve(){function a(a){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={},d=[];return Object.observe(c,a),Array.observe(d,a),c.id=1,c.id=2,delete c.id,d.push(1,2),d.length=0,Object.deliverChangeRecords(a),5!==b.length?!1:"add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type||"splice"!=b[3].type||"splice"!=b[4].type?!1:(Object.unobserve(c,a),Array.unobserve(d,a),!0)}function detectEval(){if(global.document&&"securityPolicy"in global.document&&!global.document.securityPolicy.allowsEval)return!1;if("undefined"!=typeof chrome&&chrome.app&&chrome.app.runtime)return!1;try{var a=new Function("","return true;");return a()}catch(b){return!1}}function isIndex(a){return+a===a>>>0}function toNumber(a){return+a}function isObject(a){return a===Object(a)}function areSameValue(a,b){return a===b?0!==a||1/a===1/b:numberIsNaN(a)&&numberIsNaN(b)?!0:a!==a&&b!==b}function isPathValid(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:pathRegExp.test(a))}function Path(a,b){if(b!==constructorIsPrivate)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:isIndex(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),void(hasEval&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn())))}function getPath(a){if(a instanceof Path)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=pathCache[a];if(b)return b;if(!isPathValid(a))return invalidPath;var b=new Path(a,constructorIsPrivate);return pathCache[a]=b,b}function dirtyCheck(a){for(var b=0;MAX_DIRTY_CHECK_CYCLES>b&&a.check_();)b++;return global.testingExposeCycleCount&&(global.dirtyCheckCycleCount=b),b>0}function objectIsEmpty(a){for(var b in a)return!1;return!0}function diffIsEmpty(a){return objectIsEmpty(a.added)&&objectIsEmpty(a.removed)&&objectIsEmpty(a.changed)}function diffObjectFromOldObject(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function runEOMTasks(){if(!eomTasks.length)return!1;for(var a=0;a0)){for(var a=0;ab||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function mergeSplice(a,b,c,d){for(var e=newSplice(b,c,d),f=!1,g=0,h=0;h=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.indexi.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.indexf)continue;mergeSplice(c,f,[e.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(e))}}return c}function projectArraySplices(a,b){var c=[];return createInitialSplices(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?void(b.removed[0]!==a[b.index]&&c.push(b)):void(c=c.concat(calcSplices(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)))}),c}var hasObserve=detectObjectObserve(),hasEval=detectEval(),numberIsNaN=global.Number.isNaN||function(a){return"number"==typeof a&&global.isNaN(a)},createObject="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},identStart="[$_a-zA-Z]",identPart="[$_a-zA-Z0-9]",ident=identStart+"+"+identPart+"*",elementIndex="(?:[0-9]|[1-9]+[0-9]+)",identOrElementIndex="(?:"+ident+"|"+elementIndex+")",path="(?:"+identOrElementIndex+")(?:\\s*\\.\\s*"+identOrElementIndex+")*",pathRegExp=new RegExp("^"+path+"$"),constructorIsPrivate={},pathCache={};Path.get=getPath,Path.prototype=createObject({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a){for(var b=0;bcycles&&anyChanged);global.testingExposeCycleCount&&(global.dirtyCheckCycleCount=cycles),runningMicrotaskCheckpoint=!1}}},collectObservers&&(global.Platform.clearObservers=function(){allObservers=[]}),ObjectObserver.prototype=createObject({__proto__:Observer.prototype,arrayObserve:!1,connect_:function(){hasObserve?this.directObserver_=getObservedObject(this,this.value_,this.arrayObserve):this.oldObject_=this.copyObject(this.value_)},copyObject:function(a){var b=Array.isArray(a)?[]:{};for(var c in a)b[c]=a[c];return Array.isArray(a)&&(b.length=a.length),b},check_:function(a){var b,c;if(hasObserve){if(!a)return!1;c={},b=diffObjectFromChangeRecords(this.value_,a,c)}else c=this.oldObject_,b=diffObjectFromOldObject(this.value_,this.oldObject_);return diffIsEmpty(b)?!1:(hasObserve||(this.oldObject_=this.copyObject(this.value_)),this.report_([b.added||{},b.removed||{},b.changed||{},function(a){return c[a]}]),!0)},disconnect_:function(){hasObserve?(this.directObserver_.close(),this.directObserver_=void 0):this.oldObject_=void 0},deliver:function(){this.state_==OPENED&&(hasObserve?this.directObserver_.deliver(!1):dirtyCheck(this))},discardChanges:function(){return this.directObserver_?this.directObserver_.deliver(!0):this.oldObject_=this.copyObject(this.value_),this.value_}}),ArrayObserver.prototype=createObject({__proto__:ObjectObserver.prototype,arrayObserve:!0,copyObject:function(a){return a.slice()},check_:function(a){var b;if(hasObserve){if(!a)return!1;b=projectArraySplices(this.value_,a)}else b=calcSplices(this.value_,0,this.value_.length,this.oldObject_,0,this.oldObject_.length);return b&&b.length?(hasObserve||(this.oldObject_=this.copyObject(this.value_)),this.report_([b]),!0):!1}}),ArrayObserver.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;ej;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(EDIT_LEAVE):(e.push(EDIT_UPDATE),d=g),b--,c--):f==h?(e.push(EDIT_DELETE),b--,d=h):(e.push(EDIT_ADD),c--,d=i)}else e.push(EDIT_DELETE),b--;else e.push(EDIT_ADD),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,c-b==0&&f-e==0)return[];if(b==c){for(var j=newSplice(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[newSplice(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;od;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var arraySplice=new ArraySplice;global.Observer=Observer,global.Observer.runEOM_=runEOM,global.Observer.observerSentinel_=observerSentinel,global.Observer.hasObjectObserve=hasObserve,global.ArrayObserver=ArrayObserver,global.ArrayObserver.calculateSplices=function(a,b){return arraySplice.calculateSplices(a,b)},global.ArraySplice=ArraySplice,global.ObjectObserver=ObjectObserver,global.PathObserver=PathObserver,global.CompoundObserver=CompoundObserver,global.Path=Path,global.ObserverTransform=ObserverTransform}("undefined"!=typeof global&&global&&"undefined"!=typeof module&&module?global:this||window),Platform.flags.shadow?(window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){for(var c=M(b),d=0;d=0;b--)if(!c(a[b]))return a[b];return null}function i(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var m=null;if(g.length){if(c(i)&&(m=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(l(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,m,e)}a=b(a)?a.host:a.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a,b){return M(a)===M(b)}function m(a){if(!T.get(a)&&(T.set(a,!0),o(Q(a),Q(a.target)),K)){var b=K;throw K=null,b}}function n(a){switch(a.type){case"beforeunload":case"load":case"unload":return!0}return!1}function o(b,c){if(U.get(b))throw new Error("InvalidStateError");U.set(b,!0),a.renderAllPending();var d=g(c);return 2===d.length&&d[0].target instanceof R.Document&&n(b)&&d.shift(),ab.set(b,d),p(b,d)&&q(b,d)&&r(b,d),Y.set(b,u.NONE),W.delete(b,null),U.delete(b),b.defaultPrevented}function p(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=u.CAPTURING_PHASE,!s(b[d],a,c)))return!1}return!0}function q(a,b){var c=u.AT_TARGET;return s(b[0],a,c)}function r(a,b){for(var c,d=a.bubbles,e=1;e=f;f++){var g=b[f].currentTarget,h=M(g);h.contains(e)&&(f!==d||g instanceof R.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){Z.set(this,!0)},stopImmediatePropagation:function(){Z.set(this,!0),$.set(this,!0)}},O(bb,u,document.createEvent("Event"));var cb=w("UIEvent",u),db=w("CustomEvent",u),eb={get relatedTarget(){var a=X.get(this);return void 0!==a?a:Q(P(this).relatedTarget)}},fb=N({initMouseEvent:x("initMouseEvent",14)},eb),gb=N({initFocusEvent:x("initFocusEvent",5)},eb),hb=w("MouseEvent",cb,fb),ib=w("FocusEvent",cb,gb),jb=Object.create(null),kb=function(){try{new window.FocusEvent("focus")}catch(a){return!1}return!0}();if(!kb){var lb=function(a,b,c){if(c){var d=jb[c];b=N(N({},d),b)}jb[a]=b};lb("Event",{bubbles:!1,cancelable:!1}),lb("CustomEvent",{detail:null},"Event"),lb("UIEvent",{view:null,detail:0},"Event"),lb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),lb("FocusEvent",{relatedTarget:null},"UIEvent")}var mb=window.BeforeUnloadEvent;z.prototype=Object.create(u.prototype),N(z.prototype,{get returnValue(){return this.impl.returnValue},set returnValue(a){this.impl.returnValue=a}}),mb&&O(mb,z);var nb=window.EventTarget,ob=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;ob.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),C.prototype={addEventListener:function(a,b,c){if(A(b)&&!B(a)){var d=new t(a,b,c),e=S.get(this);if(e){for(var f=0;fd;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap,g={enumerable:!1};c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(window.ShadowDOMPolyfill),function(a){"use strict";a.wrapHTMLCollection=a.wrapNodeList,a.wrappers.HTMLCollection=a.wrappers.NodeList}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){A(a instanceof w)}function c(a){var b=new y;return b[0]=a,b.length=1,b}function d(a,b,c){C(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){C(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);O=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;O=!1;for(var g=0;ge;e++)d.appendChild(J(b[e]));return d}function q(a){if(void 0!==a.firstChild_)for(var b=a.firstChild_;b;){var c=b;b=b.nextSibling_,c.parentNode_=c.previousSibling_=c.nextSibling_=void 0}a.firstChild_=a.lastChild_=void 0}function r(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){A(b.parentNode===a);var c=b.nextSibling,d=J(b),e=d.parentNode;e&&V.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=J(a),g=f.firstChild;g;)c=g.nextSibling,V.call(f,g),g=c}function s(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function t(a){for(var b,c=0;c>>0}function c(a){d.call(this,a)}var d=a.wrappers.CharacterData,e=(a.enqueueMutation,a.mixin),f=a.registerWrapper,g=window.Text;c.prototype=Object.create(d.prototype),e(c.prototype,{splitText:function(a){a=b(a);var c=this.data;if(a>c.length)throw new Error("IndexSizeError");var d=c.slice(0,a),e=c.slice(a);this.data=d;var f=this.ownerDocument.createTextNode(e);return this.parentNode&&this.parentNode.insertBefore(f,this.nextSibling),f}}),f(g,c,document.createTextNode("")),a.wrappers.Text=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface,k=(a.addWrapNodeListMethod,a.enqueueMutation),l=a.mixin,m=(a.oneOf,a.registerWrapper),n=a.wrappers,o=window.Element,p=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(a){return o.prototype[a]}),q=p[0],r=o.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new n.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),p.forEach(function(a){"matches"!==a&&(d.prototype[a]=function(a){return this.matches(a)})}),o.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),m(o,d,document.createElementNS(null,"x")),a.matchesNames=p,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";case" ":return" "}}function c(a){return a.replace(z,b)}function d(a){return a.replace(A,b)}function e(a){for(var b={},c=0;c";case Node.TEXT_NODE:var k=a.data;return b&&C[b.localName]?k:d(k);case Node.COMMENT_NODE:return"";default:throw console.error(a),new Error("not implemented")}}function g(a){a instanceof y.HTMLTemplateElement&&(a=a.content);for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=f(c,a);return b}function h(a,b,c){var d=c||"div";a.textContent="";var e=w(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(x(f))}function i(a){o.call(this,a)}function j(a,b){var c=w(a.cloneNode(!1));c.innerHTML=b;for(var d,e=w(document.createDocumentFragment());d=c.firstChild;)e.appendChild(d);return x(e)}function k(b){return function(){return a.renderAllPending(),this.impl[b]}}function l(a){p(i,a,k(a))}function m(b){Object.defineProperty(i.prototype,b,{get:k(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function n(b){Object.defineProperty(i.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var o=a.wrappers.Element,p=a.defineGetter,q=a.enqueueMutation,r=a.mixin,s=a.nodesWereAdded,t=a.nodesWereRemoved,u=a.registerWrapper,v=a.snapshotNodeList,w=a.unwrap,x=a.wrap,y=a.wrappers,z=/[&\u00A0"]/g,A=/[&\u00A0<>]/g,B=e(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),C=e(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),D=/MSIE/.test(navigator.userAgent),E=window.HTMLElement,F=window.HTMLTemplateElement;i.prototype=Object.create(o.prototype),r(i.prototype,{get innerHTML(){return g(this)},set innerHTML(a){if(D&&C[this.localName])return void(this.textContent=a);var b=v(this.childNodes);this.invalidateShadowRenderer()?this instanceof y.HTMLTemplateElement?h(this.content,a):h(this,a,this.tagName):!F&&this instanceof y.HTMLTemplateElement?h(this.content,a):this.impl.innerHTML=a;var c=v(this.childNodes);q(this,"childList",{addedNodes:c,removedNodes:b}),t(b),s(c,this)},get outerHTML(){return f(this,this.parentNode)},set outerHTML(a){var b=this.parentNode;if(b){b.invalidateShadowRenderer();var c=j(b,a);b.replaceChild(c,this)}},insertAdjacentHTML:function(a,b){var c,d;switch(String(a).toLowerCase()){case"beforebegin":c=this.parentNode,d=this;break;case"afterend":c=this.parentNode,d=this.nextSibling;break;case"afterbegin":c=this,d=this.firstChild;break;case"beforeend":c=this,d=null;break;default:return}var e=j(c,b);c.insertBefore(e,d)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(l),["scrollLeft","scrollTop"].forEach(m),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(n),u(E,i,document.createElement("b")),a.wrappers.HTMLElement=i,a.getInnerHTML=g,a.setInnerHTML=h}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=k.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);k.set(a,b)}return b}function c(a){for(var c,d=b(a.ownerDocument),e=h(d.createDocumentFragment());c=a.firstChild;)e.appendChild(c);return e}function d(a){if(e.call(this,a),!l){var b=c(a);j.set(this,i(b))}}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.unwrap,i=a.wrap,j=new WeakMap,k=new WeakMap,l=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),f(d.prototype,{get content(){return l?i(this.impl.content):j.get(this)}}),l&&g(l,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.wrap,h=window.HTMLSelectElement;b.prototype=Object.create(c.prototype),d(b.prototype,{add:function(a,b){"object"==typeof b&&(b=f(b)),f(this).add(f(a),b)},remove:function(a){return void 0===a?void c.prototype.remove.call(this):("object"==typeof a&&(a=f(a)),void f(this).remove(a))},get form(){return g(f(this).form)}}),e(h,b,document.createElement("select")),a.wrappers.HTMLSelectElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.wrap,h=a.wrapHTMLCollection,i=window.HTMLTableElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get caption(){return g(f(this).caption)},createCaption:function(){return g(f(this).createCaption())},get tHead(){return g(f(this).tHead)},createTHead:function(){return g(f(this).createTHead())},createTFoot:function(){return g(f(this).createTFoot())},get tFoot(){return g(f(this).tFoot)},get tBodies(){return h(f(this).tBodies)},createTBody:function(){return g(f(this).createTBody())},get rows(){return h(f(this).rows)},insertRow:function(a){return g(f(this).insertRow(a))}}),e(i,b,document.createElement("table")),a.wrappers.HTMLTableElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrapHTMLCollection,g=a.unwrap,h=a.wrap,i=window.HTMLTableSectionElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get rows(){return f(g(this).rows)},insertRow:function(a){return h(g(this).insertRow(a))}}),e(i,b,document.createElement("thead")),a.wrappers.HTMLTableSectionElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrapHTMLCollection,g=a.unwrap,h=a.wrap,i=window.HTMLTableRowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get cells(){return f(g(this).cells)},insertCell:function(a){return h(g(this).insertCell(a))}}),e(i,b,document.createElement("tr")),a.wrappers.HTMLTableRowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement,g=(a.mixin,a.registerWrapper),h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.registerObject,c="http://www.w3.org/2000/svg",d=document.createElementNS(c,"title"),e=b(d),f=Object.getPrototypeOf(e.prototype).constructor;a.wrappers.SVGElement=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){m.call(this,a)}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.SVGUseElement,h="http://www.w3.org/2000/svg",i=f(document.createElementNS(h,"g")),j=document.createElementNS(h,"use"),k=i.constructor,l=Object.getPrototypeOf(k.prototype),m=l.constructor;b.prototype=Object.create(l),"instanceRoot"in j&&c(b.prototype,{get instanceRoot(){return f(e(this).instanceRoot)},get animatedInstanceRoot(){return f(e(this).animatedInstanceRoot)}}),d(g,b,j),a.wrappers.SVGUseElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.SVGElementInstance;g&&(b.prototype=Object.create(c.prototype),d(b.prototype,{get correspondingElement(){return f(this.impl.correspondingElement)},get correspondingUseElement(){return f(this.impl.correspondingUseElement)},get parentNode(){return f(this.impl.parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return f(this.impl.firstChild)},get lastChild(){return f(this.impl.lastChild)},get previousSibling(){return f(this.impl.previousSibling)},get nextSibling(){return f(this.impl.nextSibling)}}),e(g,b),a.wrappers.SVGElementInstance=b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(g){c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents()) -},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))},toString:function(){return this.impl.toString()}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createComment(""));a.wrappers.Comment=h,a.wrappers.DocumentFragment=g}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=k(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),i(b,this),this.treeScope_=new d(this,g(a));var e=a.shadowRoot;m.set(this,e),l.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.TreeScope,e=a.elementFromPoint,f=a.getInnerHTML,g=a.getTreeScope,h=a.mixin,i=a.rewrap,j=a.setInnerHTML,k=a.unwrap,l=new WeakMap,m=new WeakMap,n=/[ \t\n\r\f]/;b.prototype=Object.create(c.prototype),h(b.prototype,{get innerHTML(){return f(this)},set innerHTML(a){j(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return m.get(this)||null},get host(){return l.get(this)||null},invalidateShadowRenderer:function(){return l.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return e(this,this.ownerDocument,a,b)},getElementById:function(a){return n.test(a)?null:this.querySelector('[id="'+a+'"]')}}),a.wrappers.ShadowRoot=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){var b=I.get(a);return b||I.set(a,b=[]),b}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof z))return!1;if("*"===c||c===a.localName)return!0;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;ap;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m=0;k--)j=Object.create(j);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(j[a]=function(){A(this)instanceof d||y(this),b.apply(A(this),arguments)})});var l={prototype:j};f&&(l.extends=f),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(j,d),a.nativePrototypeTable.set(e,j);F.call(z(this),b,l);return d},t([window.HTMLDocument||window.Document],["registerElement"])}t([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"].concat(u)),t([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById","getSelection"]),v(b.prototype,j),v(b.prototype,l),v(b.prototype,n),v(b.prototype,{get implementation(){var a=C.get(this);return a?a:(a=new g(z(this).implementation),C.set(this,a),a)}}),w(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&w(window.HTMLDocument,b),B([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),w(window.DOMImplementation,g),t([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.wrappers.Selection,e=a.mixin,f=a.registerWrapper,g=a.renderAllPending,h=a.unwrap,i=a.unwrapIfNeeded,j=a.wrap,k=window.Window,l=window.getComputedStyle,m=window.getSelection;b.prototype=Object.create(c.prototype),k.prototype.getComputedStyle=function(a,b){return j(this||window).getComputedStyle(i(a),b)},k.prototype.getSelection=function(){return j(this||window).getSelection()},delete window.getComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){k.prototype[a]=function(){var b=j(this||window);return b[a].apply(b,arguments)},delete window[a]}),e(b.prototype,{getComputedStyle:function(a,b){return g(),l.call(h(this),i(a),b)},getSelection:function(){return g(),new d(m.call(h(this)))}}),f(k,b),a.wrappers.Window=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.unwrap,c=window.DataTransfer||window.Clipboard,d=c.prototype.setDragImage;c.prototype.setDragImage=function(a,c,e){d.call(this,b(a),c,e)}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}var c=(a.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",base:"HTMLBaseElement",body:"HTMLBodyElement",br:"HTMLBRElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",content:"HTMLContentElement",data:"HTMLDataElement",datalist:"HTMLDataListElement",del:"HTMLModElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",dl:"HTMLDListElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",h1:"HTMLHeadingElement",head:"HTMLHeadElement",hr:"HTMLHRElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",img:"HTMLImageElement",input:"HTMLInputElement",keygen:"HTMLKeygenElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",li:"HTMLLIElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",object:"HTMLObjectElement",ol:"HTMLOListElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",shadow:"HTMLShadowElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",table:"HTMLTableElement",tbody:"HTMLTableSectionElement",template:"HTMLTemplateElement",textarea:"HTMLTextAreaElement",thead:"HTMLTableSectionElement",time:"HTMLTimeElement",title:"HTMLTitleElement",tr:"HTMLTableRowElement",track:"HTMLTrackElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]})}(window.ShadowDOMPolyfill),function(){window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded,Object.defineProperty(Element.prototype,"webkitShadowRoot",Object.getOwnPropertyDescriptor(Element.prototype,"shadowRoot"));var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b},Element.prototype.webkitCreateShadowRoot=Element.prototype.createShadowRoot}(),function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(l,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=[];if(b.sheet)try{d=b.sheet.cssRules}catch(e){}else console.warn("sheet not found",b);return b.parentNode.removeChild(b),d}function e(){v.initialized=!0,document.body.appendChild(v);var a=v.contentDocument,b=a.createElement("base");b.href=document.baseURI,a.head.appendChild(b)}function f(a){v.initialized||e(),document.body.appendChild(v),a(v.contentDocument),document.body.removeChild(v)}function g(a,b){if(b){var e;if(a.match("@import")&&x){var g=c(a);f(function(a){a.head.appendChild(g.impl),e=g.sheet.cssRules,b(e)})}else e=d(a),b(e)}}function h(a){a&&j().appendChild(document.createTextNode(a))}function i(a,b){var d=c(a);d.setAttribute(b,""),d.setAttribute(z,""),document.head.appendChild(d)}function j(){return w||(w=document.createElement("style"),w.setAttribute(z,""),w[z]=!0),w}var k={strictStyling:!1,registry:{},shimStyling:function(a,c,d){var e=this.prepareRoot(a,c,d),f=this.isTypeExtension(d),g=this.makeScopeSelector(c,f),h=b(e,!0);h=this.scopeCssText(h,g),a&&(a.shimmedStyle=h),this.addCssToDocument(h,c)},shimStyle:function(a,b){return this.shimCssText(a.textContent,b)},shimCssText:function(a,b){return a=this.insertDirectives(a),this.scopeCssText(a,b)},makeScopeSelector:function(a,b){return a?b?"[is="+a+"]":a:""},isTypeExtension:function(a){return a&&a.indexOf("-")<0},prepareRoot:function(a,b,c){var d=this.registerRoot(a,b,c);return this.replaceTextInStyles(d.rootStyles,this.insertDirectives),this.removeStyles(a,d.rootStyles),this.strictStyling&&this.applyScopeToContent(a,b),d.scopeStyles},removeStyles:function(a,b){for(var c,d=0,e=b.length;e>d&&(c=b[d]);d++)c.parentNode.removeChild(c)},registerRoot:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=this.findStyles(a);d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return f&&(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},findStyles:function(a){if(!a)return[];var b=a.querySelectorAll("style");return Array.prototype.filter.call(b,function(a){return!a.hasAttribute(A)})},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertDirectives:function(a){return a=this.insertPolyfillDirectivesInCssText(a),this.insertPolyfillRulesInCssText(a)},insertPolyfillDirectivesInCssText:function(a){return a=a.replace(m,function(a,b){return b.slice(0,-2)+"{"}),a.replace(n,function(a,b){return b+" {"})},insertPolyfillRulesInCssText:function(a){return a=a.replace(o,function(a,b){return b.slice(0,-1)}),a.replace(p,function(a,b,c,d){var e=a.replace(b,"").replace(c,"");return d+e})},scopeCssText:function(a,b){var c=this.extractUnscopedRulesFromCssText(a);if(a=this.insertPolyfillHostInCssText(a),a=this.convertColonHost(a),a=this.convertColonHostContext(a),a=this.convertCombinators(a),b){var a,d=this;g(a,function(c){a=d.scopeRules(c,b)})}return a=a+"\n"+c,a.trim()},extractUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";for(;b=r.exec(a);)c+=b[0].replace(b[2],"").replace(b[1],b[3])+"\n\n";return c},convertColonHost:function(a){return this.convertColonRule(a,cssColonHostRe,this.colonHostPartReplacer)},convertColonHostContext:function(a){return this.convertColonRule(a,cssColonHostContextRe,this.colonHostContextPartReplacer)},convertColonRule:function(a,b,c){return a.replace(b,function(a,b,d,e){if(b=polyfillHostNoCombinator,d){for(var f,g=d.split(","),h=[],i=0,j=g.length;j>i&&(f=g[i]);i++)f=f.trim(),h.push(c(b,f,e));return h.join(",")}return b+e})},colonHostContextPartReplacer:function(a,b,c){return b.match(s)?this.colonHostPartReplacer(a,b,c):a+b+c+", "+b+" "+a+c},colonHostPartReplacer:function(a,b,c){return a+b.replace(s,"")+c},convertCombinators:function(a){for(var b=0;b","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(polyfillHostRe,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(colonHostContextRe,t).replace(colonHostRe,s)},propertiesFromRule:function(a){var b=a.style.cssText;a.style.content&&!a.style.content.match(/['"]+|attr/)&&(b=b.replace(/content:[^;]*;/g,"content: '"+a.style.content+"';"));var c=a.style;for(var d in c)"initial"===c[d]&&(b+=d+": initial; ");return b},replaceTextInStyles:function(a,b){a&&b&&(a instanceof Array||(a=[a]),Array.prototype.forEach.call(a,function(a){a.textContent=b.call(this,a.textContent)},this))},addCssToDocument:function(a,b){a.match("@import")?i(a,b):h(a)}},l=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,m=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,n=/polyfill-next-selector[^}]*content\:[\s]*'([^']*)'[^}]*}([^{]*?){/gim,o=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,p=/(polyfill-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*}/gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/(polyfill-unscoped-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*}/gim,s="-shadowcsshost",t="-shadowcsscontext",u=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)";cssColonHostRe=new RegExp("("+s+u,"gim"),cssColonHostContextRe=new RegExp("("+t+u,"gim"),selectorReSuffix="([>\\s~+[.,{:][\\s\\S]*)?$",colonHostRe=/\:host/gim,colonHostContextRe=/\:host-context/gim,polyfillHostNoCombinator=s+"-no-combinator",polyfillHostRe=new RegExp(s,"gim"),polyfillHostContextRe=new RegExp(t,"gim"),combinatorsRe=[/\^\^/g,/\^/g,/\/shadow\//g,/\/shadow-deep\//g,/::shadow/g,/\/deep\//g];var v=document.createElement("iframe");v.style.display="none";var w,x=navigator.userAgent.match("Chrome"),y="shim-shadowdom",z="shim-shadowdom-css",A="no-shim";if(window.ShadowDOMPolyfill){h("style { display: none !important; }\n");var B=wrap(document),C=B.querySelector("head");C.insertBefore(j(),C.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){var b=a.urlResolver;if(window.HTMLImports&&!HTMLImports.useNative){var c="link[rel=stylesheet]["+y+"]",d="style["+y+"]";HTMLImports.importer.documentPreloadSelectors+=","+c,HTMLImports.importer.importsPreloadSelectors+=","+c,HTMLImports.parser.documentSelectors=[HTMLImports.parser.documentSelectors,c,d].join(",");var e=HTMLImports.parser.parseGeneric;HTMLImports.parser.parseGeneric=function(a){if(!a[z]){var c=a.__importElement||a;if(!c.hasAttribute(y))return void e.call(this,a);a.__resource?(c=a.ownerDocument.createElement("style"),c.textContent=b.resolveCssText(a.__resource,a.href)):b.resolveStyle(c),c.textContent=k.shimStyle(c),c.removeAttribute(y,""),c.setAttribute(z,""),c[z]=!0,c.parentNode!==C&&(a.parentNode===C?C.replaceChild(c,a):C.appendChild(c)),c.__importParsed=!0,this.markParsingComplete(a)}};var f=HTMLImports.parser.hasResource;HTMLImports.parser.hasResource=function(a){return"link"===a.localName&&"stylesheet"===a.rel&&a.hasAttribute(y)?a.__resource:f.call(this,a)}}})}a.ShadowCSS=k}(window.Platform)):!function(){window.templateContent=window.templateContent||function(a){return a.content},window.wrap=window.unwrap=function(a){return a},addEventListener("DOMContentLoaded",function(){if(CustomElements.useNative===!1){var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b}}}),window.templateContent=function(a){if(window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(a),!a.content&&!a._content){for(var b=document.createDocumentFragment();a.firstChild;)b.appendChild(a.firstChild);a._content=b}return a.content||a._content}}(),function(a){"use strict";function b(a){return void 0!==m[a]}function c(){h.call(this),this._isInvalid=!0}function d(a){return""==a&&c.call(this),a.toLowerCase()}function e(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,63,96].indexOf(b)?a:encodeURIComponent(a)}function f(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,96].indexOf(b)?a:encodeURIComponent(a)}function g(a,g,h){function i(a){t.push(a)}var j=g||"scheme start",k=0,l="",r=!1,s=!1,t=[];a:for(;(a[k-1]!=o||0==k)&&!this._isInvalid;){var u=a[k];switch(j){case"scheme start":if(!u||!p.test(u)){if(g){i("Invalid scheme.");break a}l="",j="no scheme";continue}l+=u.toLowerCase(),j="scheme";break;case"scheme":if(u&&q.test(u))l+=u.toLowerCase();else{if(":"!=u){if(g){if(o==u)break a;i("Code point not allowed in scheme: "+u);break a}l="",k=0,j="no scheme";continue}if(this._scheme=l,l="",g)break a;b(this._scheme)&&(this._isRelative=!0),j="file"==this._scheme?"relative":this._isRelative&&h&&h._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==u?(query="?",j="query"):"#"==u?(this._fragment="#",j="fragment"):o!=u&&" "!=u&&"\n"!=u&&"\r"!=u&&(this._schemeData+=e(u));break;case"no scheme":if(h&&b(h._scheme)){j="relative";continue}i("Missing scheme."),c.call(this);break;case"relative or authority":if("/"!=u||"/"!=a[k+1]){i("Expected /, got: "+u),j="relative";continue}j="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=h._scheme),o==u){this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query;break a}if("/"==u||"\\"==u)"\\"==u&&i("\\ is an invalid code point."),j="relative slash";else if("?"==u)this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query="?",j="query";else{if("#"!=u){var v=a[k+1],w=a[k+2];("file"!=this._scheme||!p.test(u)||":"!=v&&"|"!=v||o!=w&&"/"!=w&&"\\"!=w&&"?"!=w&&"#"!=w)&&(this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._path.pop()),j="relative path";continue}this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query,this._fragment="#",j="fragment"}break;case"relative slash":if("/"!=u&&"\\"!=u){"file"!=this._scheme&&(this._host=h._host,this._port=h._port),j="relative path";continue}"\\"==u&&i("\\ is an invalid code point."),j="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=u){i("Expected '/', got: "+u),j="authority ignore slashes";continue}j="authority second slash";break;case"authority second slash":if(j="authority ignore slashes","/"!=u){i("Expected '/', got: "+u);continue}break;case"authority ignore slashes":if("/"!=u&&"\\"!=u){j="authority";continue}i("Expected authority, got: "+u);break;case"authority":if("@"==u){r&&(i("@ already seen."),l+="%40"),r=!0;for(var x=0;x')})}),a.createDOM=b}(window.Platform),window.templateContent=window.templateContent||function(a){return a.content},function(a){a=a||(window.Inspector={});var b;window.sinspect=function(a,d){b||(b=window.open("","ShadowDOM Inspector",null,!0),b.document.write(c),b.api={shadowize:shadowize}),f(a||wrap(document.body),d)};var c=["",""," "," ShadowDOM Inspector"," "," "," ",'
            ',"
          ",'
          '," ",""].join("\n"),d=[],e=function(){var a=b.document,c=a.querySelector("#crumbs");c.textContent="";for(var e,g=0;e=d[g];g++){var h=a.createElement("a");h.href="#",h.textContent=e.localName,h.idx=g,h.onclick=function(a){for(var b;d.length>this.idx;)b=d.pop();f(b.shadow||b,b),a.preventDefault()},c.appendChild(a.createElement("li")).appendChild(h)}},f=function(a,c){var f=b.document;k=[];var g=c||a;d.push(g),e(),f.body.querySelector("#tree").innerHTML="
          "+j(a,a.childNodes)+"
          "},g=Array.prototype.forEach.call.bind(Array.prototype.forEach),h={STYLE:1,SCRIPT:1,"#comment":1,TEMPLATE:1},i=function(a){return h[a.nodeName]},j=function(a,b,c){if(i(a))return"";var d=c||"";if(a.localName||11==a.nodeType){var e=a.localName||"shadow-root",f=d+l(a);"content"==e&&(b=a.getDistributedNodes()),f+="
          ";var h=d+"  ";g(b,function(a){f+=j(a,a.childNodes,h)}),f+=d,{br:1}[e]||(f+="</"+e+">",f+="
          ")}else{var k=a.textContent.trim();f=k?d+'"'+k+'"
          ':""}return f},k=[],l=function(a){var b="<",c=a.localName||"shadow-root";return a.webkitShadowRoot||a.shadowRoot?(b+=' ",k.push(a)):b+=c||"shadow-root",a.attributes&&g(a.attributes,function(a){b+=" "+a.name+(a.value?'="'+a.value+'"':"")}),b+=">"};shadowize=function(){var a=Number(this.attributes.idx.value),b=k[a];b?f(b.webkitShadowRoot||b.shadowRoot,b):(console.log("bad shadowize node"),console.dir(this))},a.output=j}(window.Inspector),function(){var a=document.createElement("style");a.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; } \n";var b=document.querySelector("head");b.insertBefore(a,b.firstChild)}(Platform),function(a){function b(a,b){return b=b||[],b.map||(b=[b]),a.apply(this,b.map(d))}function c(a,c,d){var e;switch(arguments.length){case 0:return;case 1:e=null;break;case 2:e=c.apply(this);break;default:e=b(d,c)}f[a]=e}function d(a){return f[a]}function e(a,c){HTMLImports.whenImportsReady(function(){b(c,a)})}var f={};a.marshal=d,a.module=c,a.using=e}(window),function(a){function b(a){f.textContent=d++,e.push(a)}function c(){for(;e.length;)e.shift()()}var d=0,e=[],f=document.createTextNode("");new(window.MutationObserver||JsMutationObserver)(c).observe(f,{characterData:!0}),a.endOfMicrotask=b}(Platform),function(a){function b(a,b,d){return a.replace(d,function(a,d,e,f){var g=e.replace(/["']/g,"");return g=c(b,g),d+"'"+g+"'"+f})}function c(a,b){var c=new URL(b,a);return d(c.href)}function d(a){var b=document.location,c=new URL(a,b);return c.host===b.host&&c.port===b.port&&c.protocol===b.protocol?e(b.pathname,c.pathname):a}function e(a,b){for(var c=a.split("/"),d=b.split("/");c.length&&c[0]===d[0];)c.shift(),d.shift();for(var e=0,f=c.length-1;f>e;e++)d.unshift("..");return d.join("/")}var f={resolveDom:function(a,b){b=b||a.ownerDocument.baseURI,this.resolveAttributes(a,b),this.resolveStyles(a,b);var c=a.querySelectorAll("template");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)d.content&&this.resolveDom(d.content,b)},resolveTemplate:function(a){this.resolveDom(a.content,a.ownerDocument.baseURI)},resolveStyles:function(a,b){var c=a.querySelectorAll("style");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveStyle(d,b)},resolveStyle:function(a,b){b=b||a.ownerDocument.baseURI,a.textContent=this.resolveCssText(a.textContent,b)},resolveCssText:function(a,c){return a=b(a,c,g),b(a,c,h)},resolveAttributes:function(a,b){a.hasAttributes&&a.hasAttributes()&&this.resolveElementAttributes(a,b);var c=a&&a.querySelectorAll(j);if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveElementAttributes(d,b)},resolveElementAttributes:function(a,d){d=d||a.ownerDocument.baseURI,i.forEach(function(e){var f,h=a.attributes[e],i=h&&h.value;i&&i.search(k)<0&&(f="style"===e?b(i,d,g):c(d,i),h.value=f)})}},g=/(url\()([^)]*)(\))/g,h=/(@import[\s]+(?!url\())([^;]*)(;)/g,i=["href","src","action","style"],j="["+i.join("],[")+"]",k="{{.*}}";a.urlResolver=f}(Platform),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e0){var e=c[d-1],f=n(e,a);if(f)return void(c[d-1]=f)}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;cc&&(b=a[c]);c++)this.require(b);this.checkDone()},addNode:function(a){this.inflight++,this.require(a),this.checkDone()},require:function(a){var b=a.src||a.href;a.__nodeUrl=b,this.dedupe(b,a)||this.fetch(b,a)},dedupe:function(a,b){if(this.pending[a])return this.pending[a].push(b),!0;return this.cache[a]?(this.onload(a,b,this.cache[a]),this.tail(),!0):(this.pending[a]=[b],!1)},fetch:function(a,d){if(c.load&&console.log("fetch",a,d),a.match(/^data:/)){var e=a.split(","),f=e[0],g=e[1];g=f.indexOf(";base64")>-1?atob(g):decodeURIComponent(g),setTimeout(function(){this.receive(a,d,null,g)}.bind(this),0)}else{var h=function(b,c){this.receive(a,d,b,c)}.bind(this);b.load(a,h)}},receive:function(a,b,c,d){this.cache[a]=d;for(var e,f=this.pending[a],g=0,h=f.length;h>g&&(e=f[g]);g++)this.onload(a,e,d),this.tail();this.pending[a]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}},b=b||{async:!0,ok:function(a){return a.status>=200&&a.status<300||304===a.status||0===a.status},load:function(c,d,e){var f=new XMLHttpRequest;return(a.flags.debug||a.flags.bust)&&(c+="?"+Math.random()),f.open("GET",c,b.async),f.addEventListener("readystatechange",function(){4===f.readyState&&d.call(e,!b.ok(f)&&f,f.response||f.responseText,c)}),f.send(),f},loadDocument:function(a,b,c){this.load(a,b,c).responseType="document"}},a.xhr=b,a.Loader=d}(window.HTMLImports),function(a){function b(a){return"link"===a.localName&&a.rel===g}function c(a){var b,c=d(a);try{b=btoa(c)}catch(e){b=btoa(unescape(encodeURIComponent(c))),console.warn("Script contained non-latin characters that were forced to latin. Some characters may be wrong.",a)}return"data:text/javascript;base64,"+b}function d(a){return a.textContent+e(a)}function e(a){var b=a.__nodeUrl;if(!b){b=a.ownerDocument.baseURI;var c="["+Math.floor(1e3*(Math.random()+1))+"]",d=a.textContent.match(/Polymer\(['"]([^'"]*)/);c=d&&d[1]||c,b+="/"+c+".js"}return"\n//# sourceURL="+b+"\n"}function f(a){var b=a.ownerDocument.createElement("style");return b.textContent=a.textContent,n.resolveUrlsInStyle(b),b}var g="import",h=a.flags,i=/Trident/.test(navigator.userAgent),j=window.ShadowDOMPolyfill?window.ShadowDOMPolyfill.wrapIfNeeded(document):document,k={documentSelectors:"link[rel="+g+"]",importsSelectors:["link[rel="+g+"]","link[rel=stylesheet]","style","script:not([type])",'script[type="text/javascript"]'].join(","),map:{link:"parseLink",script:"parseScript",style:"parseStyle"},parseNext:function(){var a=this.nextToParse();a&&this.parse(a)},parse:function(a){if(this.isParsed(a))return void(h.parse&&console.log("[%s] is already parsed",a.localName));var b=this[this.map[a.localName]];b&&(this.markParsing(a),b.call(this,a))},markParsing:function(a){h.parse&&console.log("parsing",a),this.parsingElement=a},markParsingComplete:function(a){a.__importParsed=!0,a.__importElement&&(a.__importElement.__importParsed=!0),this.parsingElement=null,h.parse&&console.log("completed",a),this.parseNext()},parseImport:function(a){if(a.import.__importParsed=!0,HTMLImports.__importsParsingHook&&HTMLImports.__importsParsingHook(a),a.dispatchEvent(a.__resource?new CustomEvent("load",{bubbles:!1}):new CustomEvent("error",{bubbles:!1})),a.__pending)for(var b;a.__pending.length;)b=a.__pending.shift(),b&&b({target:a});this.markParsingComplete(a)},parseLink:function(a){b(a)?this.parseImport(a):(a.href=a.href,this.parseGeneric(a))},parseStyle:function(a){var b=a;a=f(a),a.__importElement=b,this.parseGeneric(a)},parseGeneric:function(a){this.trackElement(a),document.head.appendChild(a)},trackElement:function(a,b){var c=this,d=function(d){b&&b(d),c.markParsingComplete(a)};if(a.addEventListener("load",d),a.addEventListener("error",d),i&&"style"===a.localName){var e=!1;if(-1==a.textContent.indexOf("@import"))e=!0;else if(a.sheet){e=!0;for(var f,g=a.sheet.cssRules,h=g?g.length:0,j=0;h>j&&(f=g[j]);j++)f.type===CSSRule.IMPORT_RULE&&(e=e&&Boolean(f.styleSheet))}e&&a.dispatchEvent(new CustomEvent("load",{bubbles:!1}))}},parseScript:function(b){var d=document.createElement("script");d.__importElement=b,d.src=b.src?b.src:c(b),a.currentScript=b,this.trackElement(d,function(){d.parentNode.removeChild(d),a.currentScript=null}),document.head.appendChild(d)},nextToParse:function(){return!this.parsingElement&&this.nextToParseInDoc(j)},nextToParseInDoc:function(a,c){for(var d,e=a.querySelectorAll(this.parseSelectorsForNode(a)),f=0,g=e.length;g>f&&(d=e[f]);f++)if(!this.isParsed(d))return this.hasResource(d)?b(d)?this.nextToParseInDoc(d.import,d):d:void 0;return c},parseSelectorsForNode:function(a){var b=a.ownerDocument||a;return b===j?this.documentSelectors:this.importsSelectors},isParsed:function(a){return a.__importParsed},hasResource:function(a){return b(a)&&!a.import?!1:!0}},l=/(url\()([^)]*)(\))/g,m=/(@import[\s]+(?!url\())([^;]*)(;)/g,n={resolveUrlsInStyle:function(a){var b=a.ownerDocument,c=b.createElement("a");return a.textContent=this.resolveUrlsInCssText(a.textContent,c),a},resolveUrlsInCssText:function(a,b){var c=this.replaceUrls(a,b,l);return c=this.replaceUrls(c,b,m)},replaceUrls:function(a,b,c){return a.replace(c,function(a,c,d,e){var f=d.replace(/["']/g,"");return b.href=f,f=b.href,c+"'"+f+"'"+e})}};a.parser=k,a.path=n,a.isIE=i}(HTMLImports),function(a){function b(a){return c(a,m)}function c(a,b){return"link"===a.localName&&a.getAttribute("rel")===b}function d(a,b){var c=a;c instanceof Document||(c=document.implementation.createHTMLDocument(m)),c._URL=b;var d=c.createElement("base");d.setAttribute("href",b),c.baseURI||(c.baseURI=b);var e=c.createElement("meta");return e.setAttribute("charset","utf-8"),c.head.appendChild(e),c.head.appendChild(d),a instanceof Document||(c.body.innerHTML=a),window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(c),c}function e(a,b){b=b||n,g(function(){h(a,b)},b)}function f(a){return"complete"===a.readyState||a.readyState===u}function g(a,b){if(f(b))a&&a();else{var c=function(){("complete"===b.readyState||b.readyState===u)&&(b.removeEventListener(v,c),g(a,b))};b.addEventListener(v,c)}}function h(a,b){function c(){f==g&&requestAnimationFrame(a)}function d(){f++,c()}var e=b.querySelectorAll("link[rel=import]"),f=0,g=e.length;if(g)for(var h,j=0;g>j&&(h=e[j]);j++)i(h)?d.call(h):(h.addEventListener("load",d),h.addEventListener("error",d));else c()}function i(a){return k?a.import&&"loading"!==a.import.readyState:a.__importParsed}var j="import"in document.createElement("link"),k=j,l=a.flags,m="import",n=window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(document):document;if(k)var o={};else var p=(a.xhr,a.Loader),q=a.parser,o={documents:{},documentPreloadSelectors:"link[rel="+m+"]",importsPreloadSelectors:["link[rel="+m+"]"].join(","),loadNode:function(a){r.addNode(a)},loadSubtree:function(a){var b=this.marshalNodes(a);r.addNodes(b)},marshalNodes:function(a){return a.querySelectorAll(this.loadSelectorsForNode(a))},loadSelectorsForNode:function(a){var b=a.ownerDocument||a;return b===n?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(a,c,e){if(l.load&&console.log("loaded",a,c),c.__resource=e,b(c)){var f=this.documents[a];f||(f=d(e,a),f.__importLink=c,this.bootDocument(f),this.documents[a]=f),c.import=f}q.parseNext()},bootDocument:function(a){this.loadSubtree(a),this.observe(a),q.parseNext()},loadedAll:function(){q.parseNext()}},r=new p(o.loaded.bind(o),o.loadedAll.bind(o));var s={get:function(){return HTMLImports.currentScript||document.currentScript},configurable:!0};if(Object.defineProperty(document,"_currentScript",s),Object.defineProperty(n,"_currentScript",s),!document.baseURI){var t={get:function(){return window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",t),Object.defineProperty(n,"baseURI",t)}var u=HTMLImports.isIE?"complete":"interactive",v="readystatechange";a.hasNative=j,a.useNative=k,a.importer=o,a.whenImportsReady=e,a.IMPORT_LINK_TYPE=m,a.isImportLoaded=i,a.importLoader=r}(window.HTMLImports),function(a){function b(a){for(var b,d=0,e=a.length;e>d&&(b=a[d]);d++)"childList"===b.type&&b.addedNodes.length&&c(b.addedNodes)}function c(a){for(var b,e=0,g=a.length;g>e&&(b=a[e]);e++)d(b)&&f.loadNode(b),b.children&&b.children.length&&c(b.children)}function d(a){return 1===a.nodeType&&g.call(a,f.loadSelectorsForNode(a))}function e(a){h.observe(a,{childList:!0,subtree:!0})}var f=(a.IMPORT_LINK_TYPE,a.importer),g=HTMLElement.prototype.matches||HTMLElement.prototype.matchesSelector||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector,h=new MutationObserver(b);a.observe=e,f.observe=e}(HTMLImports),function(){function a(){HTMLImports.importer.bootDocument(b)}"function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a,b){var c=document.createEvent("HTMLEvents");return c.initEvent(a,b.bubbles===!1?!1:!0,b.cancelable===!1?!1:!0,b.detail),c});var b=window.ShadowDOMPolyfill?window.ShadowDOMPolyfill.wrapIfNeeded(document):document;HTMLImports.whenImportsReady(function(){HTMLImports.ready=!0,HTMLImports.readyTime=(new Date).getTime(),b.dispatchEvent(new CustomEvent("HTMLImportsLoaded",{bubbles:!0}))}),HTMLImports.useNative||("complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?a():document.addEventListener("DOMContentLoaded",a))}(),window.CustomElements=window.CustomElements||{flags:{}},function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:void c(a,d)}),c(a,d)}function e(a){return h(a)?(i(a),!0):void l(a)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return A.dom&&console.group("upgrade:",b.localName),a.upgrade(b),A.dom&&console.groupEnd(),!0}}function i(a){l(a),r(a)&&d(a,function(a){l(a)})}function j(a){if(E.push(a),!D){D=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){D=!1;for(var a,b=E,c=0,d=b.length;d>c&&(a=b[c]);c++)a();E=[]}function l(a){C?j(function(){m(a)}):m(a)}function m(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("inserted:",a.localName),r(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?A.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.attachedCallback&&(A.dom&&console.log("inserted:",a.localName),a.attachedCallback())),A.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){C?j(function(){p(a)}):p(a)}function p(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("removed:",a.localName),r(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?A.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.detachedCallback&&a.detachedCallback()),A.dom&&console.groupEnd())}function q(a){return window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(a):a}function r(a){for(var b=a,c=q(document);b;){if(b==c)return!0;b=b.parentNode||b.host}}function s(a){if(a.shadowRoot&&!a.shadowRoot.__watched){A.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)t(b),b=b.olderShadowRoot}}function t(a){a.__watched||(w(a),a.__watched=!0)}function u(a){if(A.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(G(a.addedNodes,function(a){a.localName&&g(a)}),G(a.removedNodes,function(a){a.localName&&n(a)}))}),A.dom&&console.groupEnd()}function v(){u(F.takeRecords()),k()}function w(a){F.observe(a,{childList:!0,subtree:!0})}function x(a){w(a)}function y(a){A.dom&&console.group("upgradeDocument: ",a.baseURI.split("/").pop()),g(a),A.dom&&console.groupEnd()}function z(a){a=q(a);for(var b,c=a.querySelectorAll("link[rel="+B+"]"),d=0,e=c.length;e>d&&(b=c[d]);d++)b.import&&b.import.__parsed&&z(b.import);y(a)}var A=window.logFlags||{},B=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",C=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=C;var D=!1,E=[],F=new MutationObserver(u),G=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.IMPORT_LINK_TYPE=B,a.watchShadow=s,a.upgradeDocumentTree=z,a.upgradeAll=g,a.upgradeSubtree=f,a.insertedNode=i,a.observeDocument=x,a.upgradeDocument=y,a.takeRecords=v}(window.CustomElements),function(a){function b(b,g){var h=g||{};if(!b)throw new Error("document.registerElement: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(c(b))throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '"+String(b)+"'. The type name is invalid.");if(n(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!h.prototype)throw new Error("Options missing required prototype property");return h.__name=b.toLowerCase(),h.lifecycle=h.lifecycle||{},h.ancestry=d(h.extends),e(h),f(h),l(h.prototype),o(h.__name,h),h.ctor=p(h),h.ctor.prototype=h.prototype,h.prototype.constructor=h.ctor,a.ready&&a.upgradeDocumentTree(document),h.ctor}function c(a){for(var b=0;b=0&&i(d,HTMLElement),d}function s(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=n(b||a.localName);if(c){if(b&&c.tag==a.localName)return h(a,c);if(!b&&!c.extends)return h(a,c)}}}function t(b){var c=D.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var u=a.flags,v=Boolean(document.registerElement),w=!u.register&&v&&!window.ShadowDOMPolyfill;if(w){var x=function(){};a.registry={},a.upgradeElement=x,a.watchShadow=x,a.upgrade=x,a.upgradeAll=x,a.upgradeSubtree=x,a.observeDocument=x,a.upgradeDocument=x,a.upgradeDocumentTree=x,a.takeRecords=x,a.reservedTagList=[]}else{var y=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"],z={},A="http://www.w3.org/1999/xhtml",B=document.createElement.bind(document),C=document.createElementNS.bind(document),D=Node.prototype.cloneNode;document.registerElement=b,document.createElement=r,document.createElementNS=q,Node.prototype.cloneNode=t,a.registry=z,a.upgrade=s}var E;E=Object.__proto__||w?function(a,b){return a instanceof b}:function(a,b){for(var c=a;c;){if(c===b.prototype)return!0;c=c.__proto__}return!1},a.instanceof=E,a.reservedTagList=y,document.register=document.registerElement,a.hasNative=v,a.useNative=w}(window.CustomElements),function(a){function b(a){return"link"===a.localName&&a.getAttribute("rel")===c}var c=a.IMPORT_LINK_TYPE,d={selectors:["link[rel="+c+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(d.selectors);e(b,function(a){d[d.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(a){b(a)&&this.parseImport(a)},parseImport:function(a){a.import&&d.parse(a.import)}},e=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.parser=d,a.IMPORT_LINK_TYPE=c}(window.CustomElements),function(a){function b(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0})),window.HTMLImports&&(HTMLImports.__importsParsingHook=function(a){CustomElements.parser.parse(a.import)})})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||a.flags.eager)b(); -else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports&&!HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){if(window.ShadowDOMPolyfill){var a=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],b={};a.forEach(function(a){b[a]=CustomElements[a]}),a.forEach(function(a){CustomElements[a]=function(c){return b[a](wrap(c))}})}}(),function(a){function b(a){this.regex=a}var c=a.endOfMicrotask;b.prototype={extractUrls:function(a,b){for(var c,d,e=[];c=this.regex.exec(a);)d=new URL(c[1],b),e.push({matched:c[0],url:d.href});return e},process:function(a,b,c){var d=this.extractUrls(a,b);this.fetch(d,{},c)},fetch:function(a,b,d){var e=a.length;if(!e)return d(b);for(var f,g,h,i=function(){0===--e&&d(b)},j=function(a,c){var d=c.match,e=d.url;if(a)return b[e]="",i();var f=c.response||c.responseText;b[e]=f,this.fetch(this.extractUrls(f,e),b,i)},k=0;e>k;k++)f=a[k],h=f.url,b[h]?c(i):(g=this.xhr(h,j,this),g.match=f,b[h]=g)},xhr:function(a,b,c){var d=new XMLHttpRequest;return d.open("GET",a,!0),d.send(),d.onload=function(){b.call(c,null,d)},d.onerror=function(){b.call(c,null,d)},d}},a.Loader=b}(window.Platform),function(a){function b(){this.loader=new d(this.regex)}var c=a.urlResolver,d=a.Loader;b.prototype={regex:/@import\s+(?:url)?["'\(]*([^'"\)]*)['"\)]*;/g,resolve:function(a,b,c){var d=function(d){c(this.flatten(a,b,d))}.bind(this);this.loader.process(a,b,d)},resolveNode:function(a,b){var c=a.textContent,d=a.ownerDocument.baseURI,e=function(c){a.textContent=c,b(a)};this.resolve(c,d,e)},flatten:function(a,b,d){for(var e,f,g,h=this.loader.extractUrls(a,b),i=0;ig&&(d=a[g]);g++)this.resolveNode(d,c)}};var e=new b;a.styleResolver=e}(window.Platform),function(){"use strict";function a(a){for(;a.parentNode;)a=a.parentNode;return"function"==typeof a.getElementById?a:null}function b(a,b,c){var d=a.bindings_;return d||(d=a.bindings_={}),d[b]&&c[b].close(),d[b]=c}function c(a,b,c){return c}function d(a){return null==a?"":a}function e(a,b){a.data=d(b)}function f(a){return function(b){return e(a,b)}}function g(a,b,c,e){return c?void(e?a.setAttribute(b,""):a.removeAttribute(b)):void a.setAttribute(b,d(e))}function h(a,b,c){return function(d){g(a,b,c,d)}}function i(a){switch(a.type){case"checkbox":return u;case"radio":case"select-multiple":case"select-one":return"change";case"range":if(/Trident|MSIE/.test(navigator.userAgent))return"change";default:return"input"}}function j(a,b,c,e){a[b]=(e||d)(c)}function k(a,b,c){return function(d){return j(a,b,d,c)}}function l(){}function m(a,b,c,d){function e(){c.setValue(a[b]),c.discardChanges(),(d||l)(a),Platform.performMicrotaskCheckpoint()}var f=i(a);return a.addEventListener(f,e),{close:function(){a.removeEventListener(f,e),c.close()},observable_:c}}function n(a){return Boolean(a)}function o(b){if(b.form)return s(b.form.elements,function(a){return a!=b&&"INPUT"==a.tagName&&"radio"==a.type&&a.name==b.name});var c=a(b);if(!c)return[];var d=c.querySelectorAll('input[type="radio"][name="'+b.name+'"]');return s(d,function(a){return a!=b&&!a.form})}function p(a){"INPUT"===a.tagName&&"radio"===a.type&&o(a).forEach(function(a){var b=a.bindings_.checked;b&&b.observable_.setValue(!1)})}function q(a,b){var c,e,f,g=a.parentNode;g instanceof HTMLSelectElement&&g.bindings_&&g.bindings_.value&&(c=g,e=c.bindings_.value,f=c.value),a.value=d(b),c&&c.value!=f&&(e.observable_.setValue(c.value),e.observable_.discardChanges(),Platform.performMicrotaskCheckpoint())}function r(a){return function(b){q(a,b)}}var s=Array.prototype.filter.call.bind(Array.prototype.filter);Node.prototype.bind=function(a,b){console.error("Unhandled binding to Node: ",this,a,b)},Node.prototype.bindFinished=function(){};var t=c;Object.defineProperty(Platform,"enableBindingsReflection",{get:function(){return t===b},set:function(a){return t=a?b:c,a},configurable:!0}),Text.prototype.bind=function(a,b,c){if("textContent"!==a)return Node.prototype.bind.call(this,a,b,c);if(c)return e(this,b);var d=b;return e(this,d.open(f(this))),t(this,a,d)},Element.prototype.bind=function(a,b,c){var d="?"==a[a.length-1];if(d&&(this.removeAttribute(a),a=a.slice(0,-1)),c)return g(this,a,d,b);var e=b;return g(this,a,d,e.open(h(this,a,d))),t(this,a,e)};var u;!function(){var a=document.createElement("div"),b=a.appendChild(document.createElement("input"));b.setAttribute("type","checkbox");var c,d=0;b.addEventListener("click",function(){d++,c=c||"click"}),b.addEventListener("change",function(){d++,c=c||"change"});var e=document.createEvent("MouseEvent");e.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),b.dispatchEvent(e),u=1==d?"change":c}(),HTMLInputElement.prototype.bind=function(a,c,e){if("value"!==a&&"checked"!==a)return HTMLElement.prototype.bind.call(this,a,c,e);this.removeAttribute(a);var f="checked"==a?n:d,g="checked"==a?p:l;if(e)return j(this,a,c,f);var h=c,i=m(this,a,h,g);return j(this,a,h.open(k(this,a,f)),f),b(this,a,i)},HTMLTextAreaElement.prototype.bind=function(a,b,c){if("value"!==a)return HTMLElement.prototype.bind.call(this,a,b,c);if(this.removeAttribute("value"),c)return j(this,"value",b);var e=b,f=m(this,"value",e);return j(this,"value",e.open(k(this,"value",d))),t(this,a,f)},HTMLOptionElement.prototype.bind=function(a,b,c){if("value"!==a)return HTMLElement.prototype.bind.call(this,a,b,c);if(this.removeAttribute("value"),c)return q(this,b);var d=b,e=m(this,"value",d);return q(this,d.open(r(this))),t(this,a,e)},HTMLSelectElement.prototype.bind=function(a,c,d){if("selectedindex"===a&&(a="selectedIndex"),"selectedIndex"!==a&&"value"!==a)return HTMLElement.prototype.bind.call(this,a,c,d);if(this.removeAttribute(a),d)return j(this,a,c);var e=c,f=m(this,a,e);return j(this,a,e.open(k(this,a))),b(this,a,f)}}(this),function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a){for(var b;b=a.parentNode;)a=b;return a}function d(a,b){if(b){for(var d,e="#"+b;!d&&(a=c(a),a.protoContent_?d=a.protoContent_.querySelector(e):a.getElementById&&(d=a.getElementById(b)),!d&&a.templateCreator_);)a=a.templateCreator_;return d}}function e(a){return"template"==a.tagName&&"http://www.w3.org/2000/svg"==a.namespaceURI}function f(a){return"TEMPLATE"==a.tagName&&"http://www.w3.org/1999/xhtml"==a.namespaceURI}function g(a){return Boolean(L[a.tagName]&&a.hasAttribute("template"))}function h(a){return void 0===a.isTemplate_&&(a.isTemplate_="TEMPLATE"==a.tagName||g(a)),a.isTemplate_}function i(a,b){var c=a.querySelectorAll(N);h(a)&&b(a),G(c,b)}function j(a){function b(a){HTMLTemplateElement.decorate(a)||j(a.content)}i(a,b)}function k(a,b){Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))})}function l(a){var b=a.ownerDocument;if(!b.defaultView)return b;var c=b.templateContentsOwner_;if(!c){for(c=b.implementation.createHTMLDocument("");c.lastChild;)c.removeChild(c.lastChild);b.templateContentsOwner_=c}return c}function m(a){if(!a.stagingDocument_){var b=a.ownerDocument;if(!b.stagingDocument_){b.stagingDocument_=b.implementation.createHTMLDocument(""),b.stagingDocument_.isStagingDocument=!0;var c=b.stagingDocument_.createElement("base");c.href=document.baseURI,b.stagingDocument_.head.appendChild(c),b.stagingDocument_.stagingDocument_=b.stagingDocument_}a.stagingDocument_=b.stagingDocument_}return a.stagingDocument_}function n(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];K[e.name]&&("template"!==e.name&&b.setAttribute(e.name,e.value),a.removeAttribute(e.name))}return b}function o(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];b.setAttribute(e.name,e.value),a.removeAttribute(e.name)}return a.parentNode.removeChild(a),b}function p(a,b,c){var d=a.content;if(c)return void d.appendChild(b);for(var e;e=b.firstChild;)d.appendChild(e)}function q(a){P?a.__proto__=HTMLTemplateElement.prototype:k(a,HTMLTemplateElement.prototype)}function r(a){a.setModelFn_||(a.setModelFn_=function(){a.setModelFnScheduled_=!1;var b=z(a,a.delegate_&&a.delegate_.prepareBinding);w(a,b,a.model_)}),a.setModelFnScheduled_||(a.setModelFnScheduled_=!0,Observer.runEOM_(a.setModelFn_))}function s(a,b,c,d){if(a&&a.length){for(var e,f=a.length,g=0,h=0,i=0,j=!0;f>h;){var g=a.indexOf("{{",h),k=a.indexOf("[[",h),l=!1,m="}}";if(k>=0&&(0>g||g>k)&&(g=k,l=!0,m="]]"),i=0>g?-1:a.indexOf(m,g+2),0>i){if(!e)return;e.push(a.slice(h));break}e=e||[],e.push(a.slice(h,g));var n=a.slice(g+2,i).trim();e.push(l),j=j&&l;var o=d&&d(n,b,c);e.push(null==o?Path.get(n):null),e.push(o),h=i+2}return h===f&&e.push(""),e.hasOnePath=5===e.length,e.isSimplePath=e.hasOnePath&&""==e[0]&&""==e[4],e.onlyOneTime=j,e.combinator=function(a){for(var b=e[0],c=1;cc?(this.keys.push(a),this.values.push(b)):this.values[c]=b},get:function(a){var b=this.keys.indexOf(a);if(!(0>b))return this.values[b]},"delete":function(a){var b=this.keys.indexOf(a);return 0>b?!1:(this.keys.splice(b,1),this.values.splice(b,1),!0)},forEach:function(a,b){for(var c=0;cb;)this.reportInstanceMoved(b),b++},closeInstanceBindings:function(a){for(var b=a.bindings_,c=0;c 1) {\n console.warn('platform.js is not the first script on the page. ' +\n 'See http://www.polymer-project.org/docs/start/platform.html#setup ' +\n 'for details.');\n }\n\n // CustomElements polyfill flag\n if (flags.register) {\n window.CustomElements = window.CustomElements || {flags: {}};\n window.CustomElements.flags.register = flags.register;\n }\n\n if (flags.imports) {\n window.HTMLImports = window.HTMLImports || {flags: {}};\n window.HTMLImports.flags.imports = flags.imports;\n }\n\n // export\n scope.flags = flags;\n})(Platform);\n","/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nif (typeof WeakMap === 'undefined') {\n (function() {\n var defineProperty = Object.defineProperty;\n var counter = Date.now() % 1e9;\n\n var WeakMap = function() {\n this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');\n };\n\n WeakMap.prototype = {\n set: function(key, value) {\n var entry = key[this.name];\n if (entry && entry[0] === key)\n entry[1] = value;\n else\n defineProperty(key, this.name, {value: [key, value], writable: true});\n },\n get: function(key) {\n var entry;\n return (entry = key[this.name]) && entry[0] === key ?\n entry[1] : undefined;\n },\n delete: function(key) {\n this.set(key, undefined);\n }\n };\n\n window.WeakMap = WeakMap;\n })();\n}\n","// Copyright 2012 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(global) {\n 'use strict';\n\n // Detect and do basic sanity checking on Object/Array.observe.\n function detectObjectObserve() {\n if (typeof Object.observe !== 'function' ||\n typeof Array.observe !== 'function') {\n return false;\n }\n\n var records = [];\n\n function callback(recs) {\n records = recs;\n }\n\n var test = {};\n var arr = [];\n Object.observe(test, callback);\n Array.observe(arr, callback);\n test.id = 1;\n test.id = 2;\n delete test.id;\n arr.push(1, 2);\n arr.length = 0;\n\n Object.deliverChangeRecords(callback);\n if (records.length !== 5)\n return false;\n\n if (records[0].type != 'add' ||\n records[1].type != 'update' ||\n records[2].type != 'delete' ||\n records[3].type != 'splice' ||\n records[4].type != 'splice') {\n return false;\n }\n\n Object.unobserve(test, callback);\n Array.unobserve(arr, callback);\n\n return true;\n }\n\n var hasObserve = detectObjectObserve();\n\n function detectEval() {\n // don't test for eval if document has CSP securityPolicy object and we can see that\n // eval is not supported. This avoids an error message in console even when the exception\n // is caught\n if (global.document &&\n 'securityPolicy' in global.document &&\n !global.document.securityPolicy.allowsEval) {\n return false;\n }\n\n // Don't test for eval if we're running in a Chrome App environment.\n // We check for APIs set that only exist in a Chrome App context.\n if (typeof chrome !== 'undefined' && chrome.app && chrome.app.runtime) {\n return false;\n }\n\n try {\n var f = new Function('', 'return true;');\n return f();\n } catch (ex) {\n return false;\n }\n }\n\n var hasEval = detectEval();\n\n function isIndex(s) {\n return +s === s >>> 0;\n }\n\n function toNumber(s) {\n return +s;\n }\n\n function isObject(obj) {\n return obj === Object(obj);\n }\n\n var numberIsNaN = global.Number.isNaN || function isNaN(value) {\n return typeof value === 'number' && global.isNaN(value);\n }\n\n function areSameValue(left, right) {\n if (left === right)\n return left !== 0 || 1 / left === 1 / right;\n if (numberIsNaN(left) && numberIsNaN(right))\n return true;\n\n return left !== left && right !== right;\n }\n\n var createObject = ('__proto__' in {}) ?\n function(obj) { return obj; } :\n function(obj) {\n var proto = obj.__proto__;\n if (!proto)\n return obj;\n var newObject = Object.create(proto);\n Object.getOwnPropertyNames(obj).forEach(function(name) {\n Object.defineProperty(newObject, name,\n Object.getOwnPropertyDescriptor(obj, name));\n });\n return newObject;\n };\n\n var identStart = '[\\$_a-zA-Z]';\n var identPart = '[\\$_a-zA-Z0-9]';\n var ident = identStart + '+' + identPart + '*';\n var elementIndex = '(?:[0-9]|[1-9]+[0-9]+)';\n var identOrElementIndex = '(?:' + ident + '|' + elementIndex + ')';\n var path = '(?:' + identOrElementIndex + ')(?:\\\\s*\\\\.\\\\s*' + identOrElementIndex + ')*';\n var pathRegExp = new RegExp('^' + path + '$');\n\n function isPathValid(s) {\n if (typeof s != 'string')\n return false;\n s = s.trim();\n\n if (s == '')\n return true;\n\n if (s[0] == '.')\n return false;\n\n return pathRegExp.test(s);\n }\n\n var constructorIsPrivate = {};\n\n function Path(s, privateToken) {\n if (privateToken !== constructorIsPrivate)\n throw Error('Use Path.get to retrieve path objects');\n\n if (s.trim() == '')\n return this;\n\n if (isIndex(s)) {\n this.push(s);\n return this;\n }\n\n s.split(/\\s*\\.\\s*/).filter(function(part) {\n return part;\n }).forEach(function(part) {\n this.push(part);\n }, this);\n\n if (hasEval && this.length) {\n this.getValueFrom = this.compiledGetValueFromFn();\n }\n }\n\n // TODO(rafaelw): Make simple LRU cache\n var pathCache = {};\n\n function getPath(pathString) {\n if (pathString instanceof Path)\n return pathString;\n\n if (pathString == null)\n pathString = '';\n\n if (typeof pathString !== 'string')\n pathString = String(pathString);\n\n var path = pathCache[pathString];\n if (path)\n return path;\n if (!isPathValid(pathString))\n return invalidPath;\n var path = new Path(pathString, constructorIsPrivate);\n pathCache[pathString] = path;\n return path;\n }\n\n Path.get = getPath;\n\n Path.prototype = createObject({\n __proto__: [],\n valid: true,\n\n toString: function() {\n return this.join('.');\n },\n\n getValueFrom: function(obj, directObserver) {\n for (var i = 0; i < this.length; i++) {\n if (obj == null)\n return;\n obj = obj[this[i]];\n }\n return obj;\n },\n\n iterateObjects: function(obj, observe) {\n for (var i = 0; i < this.length; i++) {\n if (i)\n obj = obj[this[i - 1]];\n if (!isObject(obj))\n return;\n observe(obj, this[0]);\n }\n },\n\n compiledGetValueFromFn: function() {\n var accessors = this.map(function(ident) {\n return isIndex(ident) ? '[\"' + ident + '\"]' : '.' + ident;\n });\n\n var str = '';\n var pathString = 'obj';\n str += 'if (obj != null';\n var i = 0;\n for (; i < (this.length - 1); i++) {\n var ident = this[i];\n pathString += accessors[i];\n str += ' &&\\n ' + pathString + ' != null';\n }\n str += ')\\n';\n\n pathString += accessors[i];\n\n str += ' return ' + pathString + ';\\nelse\\n return undefined;';\n return new Function('obj', str);\n },\n\n setValueFrom: function(obj, value) {\n if (!this.length)\n return false;\n\n for (var i = 0; i < this.length - 1; i++) {\n if (!isObject(obj))\n return false;\n obj = obj[this[i]];\n }\n\n if (!isObject(obj))\n return false;\n\n obj[this[i]] = value;\n return true;\n }\n });\n\n var invalidPath = new Path('', constructorIsPrivate);\n invalidPath.valid = false;\n invalidPath.getValueFrom = invalidPath.setValueFrom = function() {};\n\n var MAX_DIRTY_CHECK_CYCLES = 1000;\n\n function dirtyCheck(observer) {\n var cycles = 0;\n while (cycles < MAX_DIRTY_CHECK_CYCLES && observer.check_()) {\n cycles++;\n }\n if (global.testingExposeCycleCount)\n global.dirtyCheckCycleCount = cycles;\n\n return cycles > 0;\n }\n\n function objectIsEmpty(object) {\n for (var prop in object)\n return false;\n return true;\n }\n\n function diffIsEmpty(diff) {\n return objectIsEmpty(diff.added) &&\n objectIsEmpty(diff.removed) &&\n objectIsEmpty(diff.changed);\n }\n\n function diffObjectFromOldObject(object, oldObject) {\n var added = {};\n var removed = {};\n var changed = {};\n\n for (var prop in oldObject) {\n var newValue = object[prop];\n\n if (newValue !== undefined && newValue === oldObject[prop])\n continue;\n\n if (!(prop in object)) {\n removed[prop] = undefined;\n continue;\n }\n\n if (newValue !== oldObject[prop])\n changed[prop] = newValue;\n }\n\n for (var prop in object) {\n if (prop in oldObject)\n continue;\n\n added[prop] = object[prop];\n }\n\n if (Array.isArray(object) && object.length !== oldObject.length)\n changed.length = object.length;\n\n return {\n added: added,\n removed: removed,\n changed: changed\n };\n }\n\n var eomTasks = [];\n function runEOMTasks() {\n if (!eomTasks.length)\n return false;\n\n for (var i = 0; i < eomTasks.length; i++) {\n eomTasks[i]();\n }\n eomTasks.length = 0;\n return true;\n }\n\n var runEOM = hasObserve ? (function(){\n var eomObj = { pingPong: true };\n var eomRunScheduled = false;\n\n Object.observe(eomObj, function() {\n runEOMTasks();\n eomRunScheduled = false;\n });\n\n return function(fn) {\n eomTasks.push(fn);\n if (!eomRunScheduled) {\n eomRunScheduled = true;\n eomObj.pingPong = !eomObj.pingPong;\n }\n };\n })() :\n (function() {\n return function(fn) {\n eomTasks.push(fn);\n };\n })();\n\n var observedObjectCache = [];\n\n function newObservedObject() {\n var observer;\n var object;\n var discardRecords = false;\n var first = true;\n\n function callback(records) {\n if (observer && observer.state_ === OPENED && !discardRecords)\n observer.check_(records);\n }\n\n return {\n open: function(obs) {\n if (observer)\n throw Error('ObservedObject in use');\n\n if (!first)\n Object.deliverChangeRecords(callback);\n\n observer = obs;\n first = false;\n },\n observe: function(obj, arrayObserve) {\n object = obj;\n if (arrayObserve)\n Array.observe(object, callback);\n else\n Object.observe(object, callback);\n },\n deliver: function(discard) {\n discardRecords = discard;\n Object.deliverChangeRecords(callback);\n discardRecords = false;\n },\n close: function() {\n observer = undefined;\n Object.unobserve(object, callback);\n observedObjectCache.push(this);\n }\n };\n }\n\n /*\n * The observedSet abstraction is a perf optimization which reduces the total\n * number of Object.observe observations of a set of objects. The idea is that\n * groups of Observers will have some object dependencies in common and this\n * observed set ensures that each object in the transitive closure of\n * dependencies is only observed once. The observedSet acts as a write barrier\n * such that whenever any change comes through, all Observers are checked for\n * changed values.\n *\n * Note that this optimization is explicitly moving work from setup-time to\n * change-time.\n *\n * TODO(rafaelw): Implement \"garbage collection\". In order to move work off\n * the critical path, when Observers are closed, their observed objects are\n * not Object.unobserve(d). As a result, it's possible that if the observedSet\n * is kept open, but some Observers have been closed, it could cause \"leaks\"\n * (prevent otherwise collectable objects from being collected). At some\n * point, we should implement incremental \"gc\" which keeps a list of\n * observedSets which may need clean-up and does small amounts of cleanup on a\n * timeout until all is clean.\n */\n\n function getObservedObject(observer, object, arrayObserve) {\n var dir = observedObjectCache.pop() || newObservedObject();\n dir.open(observer);\n dir.observe(object, arrayObserve);\n return dir;\n }\n\n var observedSetCache = [];\n\n function newObservedSet() {\n var observerCount = 0;\n var observers = [];\n var objects = [];\n var rootObj;\n var rootObjProps;\n\n function observe(obj, prop) {\n if (!obj)\n return;\n\n if (obj === rootObj)\n rootObjProps[prop] = true;\n\n if (objects.indexOf(obj) < 0) {\n objects.push(obj);\n Object.observe(obj, callback);\n }\n\n observe(Object.getPrototypeOf(obj), prop);\n }\n\n function allRootObjNonObservedProps(recs) {\n for (var i = 0; i < recs.length; i++) {\n var rec = recs[i];\n if (rec.object !== rootObj ||\n rootObjProps[rec.name] ||\n rec.type === 'setPrototype') {\n return false;\n }\n }\n return true;\n }\n\n function callback(recs) {\n if (allRootObjNonObservedProps(recs))\n return;\n\n var observer;\n for (var i = 0; i < observers.length; i++) {\n observer = observers[i];\n if (observer.state_ == OPENED) {\n observer.iterateObjects_(observe);\n }\n }\n\n for (var i = 0; i < observers.length; i++) {\n observer = observers[i];\n if (observer.state_ == OPENED) {\n observer.check_();\n }\n }\n }\n\n var record = {\n object: undefined,\n objects: objects,\n open: function(obs, object) {\n if (!rootObj) {\n rootObj = object;\n rootObjProps = {};\n }\n\n observers.push(obs);\n observerCount++;\n obs.iterateObjects_(observe);\n },\n close: function(obs) {\n observerCount--;\n if (observerCount > 0) {\n return;\n }\n\n for (var i = 0; i < objects.length; i++) {\n Object.unobserve(objects[i], callback);\n Observer.unobservedCount++;\n }\n\n observers.length = 0;\n objects.length = 0;\n rootObj = undefined;\n rootObjProps = undefined;\n observedSetCache.push(this);\n }\n };\n\n return record;\n }\n\n var lastObservedSet;\n\n function getObservedSet(observer, obj) {\n if (!lastObservedSet || lastObservedSet.object !== obj) {\n lastObservedSet = observedSetCache.pop() || newObservedSet();\n lastObservedSet.object = obj;\n }\n lastObservedSet.open(observer, obj);\n return lastObservedSet;\n }\n\n var UNOPENED = 0;\n var OPENED = 1;\n var CLOSED = 2;\n var RESETTING = 3;\n\n var nextObserverId = 1;\n\n function Observer() {\n this.state_ = UNOPENED;\n this.callback_ = undefined;\n this.target_ = undefined; // TODO(rafaelw): Should be WeakRef\n this.directObserver_ = undefined;\n this.value_ = undefined;\n this.id_ = nextObserverId++;\n }\n\n Observer.prototype = {\n open: function(callback, target) {\n if (this.state_ != UNOPENED)\n throw Error('Observer has already been opened.');\n\n addToAll(this);\n this.callback_ = callback;\n this.target_ = target;\n this.connect_();\n this.state_ = OPENED;\n return this.value_;\n },\n\n close: function() {\n if (this.state_ != OPENED)\n return;\n\n removeFromAll(this);\n this.disconnect_();\n this.value_ = undefined;\n this.callback_ = undefined;\n this.target_ = undefined;\n this.state_ = CLOSED;\n },\n\n deliver: function() {\n if (this.state_ != OPENED)\n return;\n\n dirtyCheck(this);\n },\n\n report_: function(changes) {\n try {\n this.callback_.apply(this.target_, changes);\n } catch (ex) {\n Observer._errorThrownDuringCallback = true;\n console.error('Exception caught during observer callback: ' +\n (ex.stack || ex));\n }\n },\n\n discardChanges: function() {\n this.check_(undefined, true);\n return this.value_;\n }\n }\n\n var collectObservers = !hasObserve;\n var allObservers;\n Observer._allObserversCount = 0;\n\n if (collectObservers) {\n allObservers = [];\n }\n\n function addToAll(observer) {\n Observer._allObserversCount++;\n if (!collectObservers)\n return;\n\n allObservers.push(observer);\n }\n\n function removeFromAll(observer) {\n Observer._allObserversCount--;\n }\n\n var runningMicrotaskCheckpoint = false;\n\n var hasDebugForceFullDelivery = hasObserve && (function() {\n try {\n eval('%RunMicrotasks()');\n return true;\n } catch (ex) {\n return false;\n }\n })();\n\n global.Platform = global.Platform || {};\n\n global.Platform.performMicrotaskCheckpoint = function() {\n if (runningMicrotaskCheckpoint)\n return;\n\n if (hasDebugForceFullDelivery) {\n eval('%RunMicrotasks()');\n return;\n }\n\n if (!collectObservers)\n return;\n\n runningMicrotaskCheckpoint = true;\n\n var cycles = 0;\n var anyChanged, toCheck;\n\n do {\n cycles++;\n toCheck = allObservers;\n allObservers = [];\n anyChanged = false;\n\n for (var i = 0; i < toCheck.length; i++) {\n var observer = toCheck[i];\n if (observer.state_ != OPENED)\n continue;\n\n if (observer.check_())\n anyChanged = true;\n\n allObservers.push(observer);\n }\n if (runEOMTasks())\n anyChanged = true;\n } while (cycles < MAX_DIRTY_CHECK_CYCLES && anyChanged);\n\n if (global.testingExposeCycleCount)\n global.dirtyCheckCycleCount = cycles;\n\n runningMicrotaskCheckpoint = false;\n };\n\n if (collectObservers) {\n global.Platform.clearObservers = function() {\n allObservers = [];\n };\n }\n\n function ObjectObserver(object) {\n Observer.call(this);\n this.value_ = object;\n this.oldObject_ = undefined;\n }\n\n ObjectObserver.prototype = createObject({\n __proto__: Observer.prototype,\n\n arrayObserve: false,\n\n connect_: function(callback, target) {\n if (hasObserve) {\n this.directObserver_ = getObservedObject(this, this.value_,\n this.arrayObserve);\n } else {\n this.oldObject_ = this.copyObject(this.value_);\n }\n\n },\n\n copyObject: function(object) {\n var copy = Array.isArray(object) ? [] : {};\n for (var prop in object) {\n copy[prop] = object[prop];\n };\n if (Array.isArray(object))\n copy.length = object.length;\n return copy;\n },\n\n check_: function(changeRecords, skipChanges) {\n var diff;\n var oldValues;\n if (hasObserve) {\n if (!changeRecords)\n return false;\n\n oldValues = {};\n diff = diffObjectFromChangeRecords(this.value_, changeRecords,\n oldValues);\n } else {\n oldValues = this.oldObject_;\n diff = diffObjectFromOldObject(this.value_, this.oldObject_);\n }\n\n if (diffIsEmpty(diff))\n return false;\n\n if (!hasObserve)\n this.oldObject_ = this.copyObject(this.value_);\n\n this.report_([\n diff.added || {},\n diff.removed || {},\n diff.changed || {},\n function(property) {\n return oldValues[property];\n }\n ]);\n\n return true;\n },\n\n disconnect_: function() {\n if (hasObserve) {\n this.directObserver_.close();\n this.directObserver_ = undefined;\n } else {\n this.oldObject_ = undefined;\n }\n },\n\n deliver: function() {\n if (this.state_ != OPENED)\n return;\n\n if (hasObserve)\n this.directObserver_.deliver(false);\n else\n dirtyCheck(this);\n },\n\n discardChanges: function() {\n if (this.directObserver_)\n this.directObserver_.deliver(true);\n else\n this.oldObject_ = this.copyObject(this.value_);\n\n return this.value_;\n }\n });\n\n function ArrayObserver(array) {\n if (!Array.isArray(array))\n throw Error('Provided object is not an Array');\n ObjectObserver.call(this, array);\n }\n\n ArrayObserver.prototype = createObject({\n\n __proto__: ObjectObserver.prototype,\n\n arrayObserve: true,\n\n copyObject: function(arr) {\n return arr.slice();\n },\n\n check_: function(changeRecords) {\n var splices;\n if (hasObserve) {\n if (!changeRecords)\n return false;\n splices = projectArraySplices(this.value_, changeRecords);\n } else {\n splices = calcSplices(this.value_, 0, this.value_.length,\n this.oldObject_, 0, this.oldObject_.length);\n }\n\n if (!splices || !splices.length)\n return false;\n\n if (!hasObserve)\n this.oldObject_ = this.copyObject(this.value_);\n\n this.report_([splices]);\n return true;\n }\n });\n\n ArrayObserver.applySplices = function(previous, current, splices) {\n splices.forEach(function(splice) {\n var spliceArgs = [splice.index, splice.removed.length];\n var addIndex = splice.index;\n while (addIndex < splice.index + splice.addedCount) {\n spliceArgs.push(current[addIndex]);\n addIndex++;\n }\n\n Array.prototype.splice.apply(previous, spliceArgs);\n });\n };\n\n function PathObserver(object, path) {\n Observer.call(this);\n\n this.object_ = object;\n this.path_ = getPath(path);\n this.directObserver_ = undefined;\n }\n\n PathObserver.prototype = createObject({\n __proto__: Observer.prototype,\n\n connect_: function() {\n if (hasObserve)\n this.directObserver_ = getObservedSet(this, this.object_);\n\n this.check_(undefined, true);\n },\n\n disconnect_: function() {\n this.value_ = undefined;\n\n if (this.directObserver_) {\n this.directObserver_.close(this);\n this.directObserver_ = undefined;\n }\n },\n\n iterateObjects_: function(observe) {\n this.path_.iterateObjects(this.object_, observe);\n },\n\n check_: function(changeRecords, skipChanges) {\n var oldValue = this.value_;\n this.value_ = this.path_.getValueFrom(this.object_);\n if (skipChanges || areSameValue(this.value_, oldValue))\n return false;\n\n this.report_([this.value_, oldValue]);\n return true;\n },\n\n setValue: function(newValue) {\n if (this.path_)\n this.path_.setValueFrom(this.object_, newValue);\n }\n });\n\n function CompoundObserver(reportChangesOnOpen) {\n Observer.call(this);\n\n this.reportChangesOnOpen_ = reportChangesOnOpen;\n this.value_ = [];\n this.directObserver_ = undefined;\n this.observed_ = [];\n }\n\n var observerSentinel = {};\n\n CompoundObserver.prototype = createObject({\n __proto__: Observer.prototype,\n\n connect_: function() {\n if (hasObserve) {\n var object;\n var needsDirectObserver = false;\n for (var i = 0; i < this.observed_.length; i += 2) {\n object = this.observed_[i]\n if (object !== observerSentinel) {\n needsDirectObserver = true;\n break;\n }\n }\n\n if (needsDirectObserver)\n this.directObserver_ = getObservedSet(this, object);\n }\n\n this.check_(undefined, !this.reportChangesOnOpen_);\n },\n\n disconnect_: function() {\n for (var i = 0; i < this.observed_.length; i += 2) {\n if (this.observed_[i] === observerSentinel)\n this.observed_[i + 1].close();\n }\n this.observed_.length = 0;\n this.value_.length = 0;\n\n if (this.directObserver_) {\n this.directObserver_.close(this);\n this.directObserver_ = undefined;\n }\n },\n\n addPath: function(object, path) {\n if (this.state_ != UNOPENED && this.state_ != RESETTING)\n throw Error('Cannot add paths once started.');\n\n var path = getPath(path);\n this.observed_.push(object, path);\n if (!this.reportChangesOnOpen_)\n return;\n var index = this.observed_.length / 2 - 1;\n this.value_[index] = path.getValueFrom(object);\n },\n\n addObserver: function(observer) {\n if (this.state_ != UNOPENED && this.state_ != RESETTING)\n throw Error('Cannot add observers once started.');\n\n this.observed_.push(observerSentinel, observer);\n if (!this.reportChangesOnOpen_)\n return;\n var index = this.observed_.length / 2 - 1;\n this.value_[index] = observer.open(this.deliver, this);\n },\n\n startReset: function() {\n if (this.state_ != OPENED)\n throw Error('Can only reset while open');\n\n this.state_ = RESETTING;\n this.disconnect_();\n },\n\n finishReset: function() {\n if (this.state_ != RESETTING)\n throw Error('Can only finishReset after startReset');\n this.state_ = OPENED;\n this.connect_();\n\n return this.value_;\n },\n\n iterateObjects_: function(observe) {\n var object;\n for (var i = 0; i < this.observed_.length; i += 2) {\n object = this.observed_[i]\n if (object !== observerSentinel)\n this.observed_[i + 1].iterateObjects(object, observe)\n }\n },\n\n check_: function(changeRecords, skipChanges) {\n var oldValues;\n for (var i = 0; i < this.observed_.length; i += 2) {\n var object = this.observed_[i];\n var path = this.observed_[i+1];\n var value;\n if (object === observerSentinel) {\n var observable = path;\n value = this.state_ === UNOPENED ?\n observable.open(this.deliver, this) :\n observable.discardChanges();\n } else {\n value = path.getValueFrom(object);\n }\n\n if (skipChanges) {\n this.value_[i / 2] = value;\n continue;\n }\n\n if (areSameValue(value, this.value_[i / 2]))\n continue;\n\n oldValues = oldValues || [];\n oldValues[i / 2] = this.value_[i / 2];\n this.value_[i / 2] = value;\n }\n\n if (!oldValues)\n return false;\n\n // TODO(rafaelw): Having observed_ as the third callback arg here is\n // pretty lame API. Fix.\n this.report_([this.value_, oldValues, this.observed_]);\n return true;\n }\n });\n\n function identFn(value) { return value; }\n\n function ObserverTransform(observable, getValueFn, setValueFn,\n dontPassThroughSet) {\n this.callback_ = undefined;\n this.target_ = undefined;\n this.value_ = undefined;\n this.observable_ = observable;\n this.getValueFn_ = getValueFn || identFn;\n this.setValueFn_ = setValueFn || identFn;\n // TODO(rafaelw): This is a temporary hack. PolymerExpressions needs this\n // at the moment because of a bug in it's dependency tracking.\n this.dontPassThroughSet_ = dontPassThroughSet;\n }\n\n ObserverTransform.prototype = {\n open: function(callback, target) {\n this.callback_ = callback;\n this.target_ = target;\n this.value_ =\n this.getValueFn_(this.observable_.open(this.observedCallback_, this));\n return this.value_;\n },\n\n observedCallback_: function(value) {\n value = this.getValueFn_(value);\n if (areSameValue(value, this.value_))\n return;\n var oldValue = this.value_;\n this.value_ = value;\n this.callback_.call(this.target_, this.value_, oldValue);\n },\n\n discardChanges: function() {\n this.value_ = this.getValueFn_(this.observable_.discardChanges());\n return this.value_;\n },\n\n deliver: function() {\n return this.observable_.deliver();\n },\n\n setValue: function(value) {\n value = this.setValueFn_(value);\n if (!this.dontPassThroughSet_ && this.observable_.setValue)\n return this.observable_.setValue(value);\n },\n\n close: function() {\n if (this.observable_)\n this.observable_.close();\n this.callback_ = undefined;\n this.target_ = undefined;\n this.observable_ = undefined;\n this.value_ = undefined;\n this.getValueFn_ = undefined;\n this.setValueFn_ = undefined;\n }\n }\n\n var expectedRecordTypes = {\n add: true,\n update: true,\n delete: true\n };\n\n var updateRecord = {\n object: undefined,\n type: 'update',\n name: undefined,\n oldValue: undefined\n };\n\n function notify(object, name, value, oldValue) {\n if (areSameValue(value, oldValue))\n return;\n\n // TODO(rafaelw): Hack hack hack. This entire code really needs to move\n // out of observe-js into polymer.\n if (typeof object.propertyChanged_ == 'function')\n object.propertyChanged_(name, value, oldValue);\n\n if (!hasObserve)\n return;\n\n var notifier = object.notifier_;\n if (!notifier)\n notifier = object.notifier_ = Object.getNotifier(object);\n\n updateRecord.object = object;\n updateRecord.name = name;\n updateRecord.oldValue = oldValue;\n\n notifier.notify(updateRecord);\n }\n\n Observer.createBindablePrototypeAccessor = function(proto, name) {\n var privateName = name + '_';\n var privateObservable = name + 'Observable_';\n\n proto[privateName] = proto[name];\n\n Object.defineProperty(proto, name, {\n get: function() {\n var observable = this[privateObservable];\n if (observable)\n observable.deliver();\n\n return this[privateName];\n },\n set: function(value) {\n var observable = this[privateObservable];\n if (observable) {\n observable.setValue(value);\n return;\n }\n\n var oldValue = this[privateName];\n this[privateName] = value;\n notify(this, name, value, oldValue);\n\n return value;\n },\n configurable: true\n });\n }\n\n Observer.bindToInstance = function(instance, name, observable, resolveFn) {\n var privateName = name + '_';\n var privateObservable = name + 'Observable_';\n\n instance[privateObservable] = observable;\n var oldValue = instance[privateName];\n var value = observable.open(function(value, oldValue) {\n instance[privateName] = value;\n notify(instance, name, value, oldValue);\n });\n\n if (resolveFn && !areSameValue(oldValue, value)) {\n var resolvedValue = resolveFn(oldValue, value);\n if (!areSameValue(value, resolvedValue)) {\n value = resolvedValue;\n if (observable.setValue)\n observable.setValue(value);\n }\n }\n\n instance[privateName] = value;\n notify(instance, name, value, oldValue);\n\n return {\n close: function() {\n observable.close();\n instance[privateObservable] = undefined;\n }\n };\n }\n\n function diffObjectFromChangeRecords(object, changeRecords, oldValues) {\n var added = {};\n var removed = {};\n\n for (var i = 0; i < changeRecords.length; i++) {\n var record = changeRecords[i];\n if (!expectedRecordTypes[record.type]) {\n console.error('Unknown changeRecord type: ' + record.type);\n console.error(record);\n continue;\n }\n\n if (!(record.name in oldValues))\n oldValues[record.name] = record.oldValue;\n\n if (record.type == 'update')\n continue;\n\n if (record.type == 'add') {\n if (record.name in removed)\n delete removed[record.name];\n else\n added[record.name] = true;\n\n continue;\n }\n\n // type = 'delete'\n if (record.name in added) {\n delete added[record.name];\n delete oldValues[record.name];\n } else {\n removed[record.name] = true;\n }\n }\n\n for (var prop in added)\n added[prop] = object[prop];\n\n for (var prop in removed)\n removed[prop] = undefined;\n\n var changed = {};\n for (var prop in oldValues) {\n if (prop in added || prop in removed)\n continue;\n\n var newValue = object[prop];\n if (oldValues[prop] !== newValue)\n changed[prop] = newValue;\n }\n\n return {\n added: added,\n removed: removed,\n changed: changed\n };\n }\n\n function newSplice(index, removed, addedCount) {\n return {\n index: index,\n removed: removed,\n addedCount: addedCount\n };\n }\n\n var EDIT_LEAVE = 0;\n var EDIT_UPDATE = 1;\n var EDIT_ADD = 2;\n var EDIT_DELETE = 3;\n\n function ArraySplice() {}\n\n ArraySplice.prototype = {\n\n // Note: This function is *based* on the computation of the Levenshtein\n // \"edit\" distance. The one change is that \"updates\" are treated as two\n // edits - not one. With Array splices, an update is really a delete\n // followed by an add. By retaining this, we optimize for \"keeping\" the\n // maximum array items in the original array. For example:\n //\n // 'xxxx123' -> '123yyyy'\n //\n // With 1-edit updates, the shortest path would be just to update all seven\n // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This\n // leaves the substring '123' intact.\n calcEditDistances: function(current, currentStart, currentEnd,\n old, oldStart, oldEnd) {\n // \"Deletion\" columns\n var rowCount = oldEnd - oldStart + 1;\n var columnCount = currentEnd - currentStart + 1;\n var distances = new Array(rowCount);\n\n // \"Addition\" rows. Initialize null column.\n for (var i = 0; i < rowCount; i++) {\n distances[i] = new Array(columnCount);\n distances[i][0] = i;\n }\n\n // Initialize null row\n for (var j = 0; j < columnCount; j++)\n distances[0][j] = j;\n\n for (var i = 1; i < rowCount; i++) {\n for (var j = 1; j < columnCount; j++) {\n if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))\n distances[i][j] = distances[i - 1][j - 1];\n else {\n var north = distances[i - 1][j] + 1;\n var west = distances[i][j - 1] + 1;\n distances[i][j] = north < west ? north : west;\n }\n }\n }\n\n return distances;\n },\n\n // This starts at the final weight, and walks \"backward\" by finding\n // the minimum previous weight recursively until the origin of the weight\n // matrix.\n spliceOperationsFromEditDistances: function(distances) {\n var i = distances.length - 1;\n var j = distances[0].length - 1;\n var current = distances[i][j];\n var edits = [];\n while (i > 0 || j > 0) {\n if (i == 0) {\n edits.push(EDIT_ADD);\n j--;\n continue;\n }\n if (j == 0) {\n edits.push(EDIT_DELETE);\n i--;\n continue;\n }\n var northWest = distances[i - 1][j - 1];\n var west = distances[i - 1][j];\n var north = distances[i][j - 1];\n\n var min;\n if (west < north)\n min = west < northWest ? west : northWest;\n else\n min = north < northWest ? north : northWest;\n\n if (min == northWest) {\n if (northWest == current) {\n edits.push(EDIT_LEAVE);\n } else {\n edits.push(EDIT_UPDATE);\n current = northWest;\n }\n i--;\n j--;\n } else if (min == west) {\n edits.push(EDIT_DELETE);\n i--;\n current = west;\n } else {\n edits.push(EDIT_ADD);\n j--;\n current = north;\n }\n }\n\n edits.reverse();\n return edits;\n },\n\n /**\n * Splice Projection functions:\n *\n * A splice map is a representation of how a previous array of items\n * was transformed into a new array of items. Conceptually it is a list of\n * tuples of\n *\n * \n *\n * which are kept in ascending index order of. The tuple represents that at\n * the |index|, |removed| sequence of items were removed, and counting forward\n * from |index|, |addedCount| items were added.\n */\n\n /**\n * Lacking individual splice mutation information, the minimal set of\n * splices can be synthesized given the previous state and final state of an\n * array. The basic approach is to calculate the edit distance matrix and\n * choose the shortest path through it.\n *\n * Complexity: O(l * p)\n * l: The length of the current array\n * p: The length of the old array\n */\n calcSplices: function(current, currentStart, currentEnd,\n old, oldStart, oldEnd) {\n var prefixCount = 0;\n var suffixCount = 0;\n\n var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);\n if (currentStart == 0 && oldStart == 0)\n prefixCount = this.sharedPrefix(current, old, minLength);\n\n if (currentEnd == current.length && oldEnd == old.length)\n suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);\n\n currentStart += prefixCount;\n oldStart += prefixCount;\n currentEnd -= suffixCount;\n oldEnd -= suffixCount;\n\n if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)\n return [];\n\n if (currentStart == currentEnd) {\n var splice = newSplice(currentStart, [], 0);\n while (oldStart < oldEnd)\n splice.removed.push(old[oldStart++]);\n\n return [ splice ];\n } else if (oldStart == oldEnd)\n return [ newSplice(currentStart, [], currentEnd - currentStart) ];\n\n var ops = this.spliceOperationsFromEditDistances(\n this.calcEditDistances(current, currentStart, currentEnd,\n old, oldStart, oldEnd));\n\n var splice = undefined;\n var splices = [];\n var index = currentStart;\n var oldIndex = oldStart;\n for (var i = 0; i < ops.length; i++) {\n switch(ops[i]) {\n case EDIT_LEAVE:\n if (splice) {\n splices.push(splice);\n splice = undefined;\n }\n\n index++;\n oldIndex++;\n break;\n case EDIT_UPDATE:\n if (!splice)\n splice = newSplice(index, [], 0);\n\n splice.addedCount++;\n index++;\n\n splice.removed.push(old[oldIndex]);\n oldIndex++;\n break;\n case EDIT_ADD:\n if (!splice)\n splice = newSplice(index, [], 0);\n\n splice.addedCount++;\n index++;\n break;\n case EDIT_DELETE:\n if (!splice)\n splice = newSplice(index, [], 0);\n\n splice.removed.push(old[oldIndex]);\n oldIndex++;\n break;\n }\n }\n\n if (splice) {\n splices.push(splice);\n }\n return splices;\n },\n\n sharedPrefix: function(current, old, searchLength) {\n for (var i = 0; i < searchLength; i++)\n if (!this.equals(current[i], old[i]))\n return i;\n return searchLength;\n },\n\n sharedSuffix: function(current, old, searchLength) {\n var index1 = current.length;\n var index2 = old.length;\n var count = 0;\n while (count < searchLength && this.equals(current[--index1], old[--index2]))\n count++;\n\n return count;\n },\n\n calculateSplices: function(current, previous) {\n return this.calcSplices(current, 0, current.length, previous, 0,\n previous.length);\n },\n\n equals: function(currentValue, previousValue) {\n return currentValue === previousValue;\n }\n };\n\n var arraySplice = new ArraySplice();\n\n function calcSplices(current, currentStart, currentEnd,\n old, oldStart, oldEnd) {\n return arraySplice.calcSplices(current, currentStart, currentEnd,\n old, oldStart, oldEnd);\n }\n\n function intersect(start1, end1, start2, end2) {\n // Disjoint\n if (end1 < start2 || end2 < start1)\n return -1;\n\n // Adjacent\n if (end1 == start2 || end2 == start1)\n return 0;\n\n // Non-zero intersect, span1 first\n if (start1 < start2) {\n if (end1 < end2)\n return end1 - start2; // Overlap\n else\n return end2 - start2; // Contained\n } else {\n // Non-zero intersect, span2 first\n if (end2 < end1)\n return end2 - start1; // Overlap\n else\n return end1 - start1; // Contained\n }\n }\n\n function mergeSplice(splices, index, removed, addedCount) {\n\n var splice = newSplice(index, removed, addedCount);\n\n var inserted = false;\n var insertionOffset = 0;\n\n for (var i = 0; i < splices.length; i++) {\n var current = splices[i];\n current.index += insertionOffset;\n\n if (inserted)\n continue;\n\n var intersectCount = intersect(splice.index,\n splice.index + splice.removed.length,\n current.index,\n current.index + current.addedCount);\n\n if (intersectCount >= 0) {\n // Merge the two splices\n\n splices.splice(i, 1);\n i--;\n\n insertionOffset -= current.addedCount - current.removed.length;\n\n splice.addedCount += current.addedCount - intersectCount;\n var deleteCount = splice.removed.length +\n current.removed.length - intersectCount;\n\n if (!splice.addedCount && !deleteCount) {\n // merged splice is a noop. discard.\n inserted = true;\n } else {\n var removed = current.removed;\n\n if (splice.index < current.index) {\n // some prefix of splice.removed is prepended to current.removed.\n var prepend = splice.removed.slice(0, current.index - splice.index);\n Array.prototype.push.apply(prepend, removed);\n removed = prepend;\n }\n\n if (splice.index + splice.removed.length > current.index + current.addedCount) {\n // some suffix of splice.removed is appended to current.removed.\n var append = splice.removed.slice(current.index + current.addedCount - splice.index);\n Array.prototype.push.apply(removed, append);\n }\n\n splice.removed = removed;\n if (current.index < splice.index) {\n splice.index = current.index;\n }\n }\n } else if (splice.index < current.index) {\n // Insert splice here.\n\n inserted = true;\n\n splices.splice(i, 0, splice);\n i++;\n\n var offset = splice.addedCount - splice.removed.length\n current.index += offset;\n insertionOffset += offset;\n }\n }\n\n if (!inserted)\n splices.push(splice);\n }\n\n function createInitialSplices(array, changeRecords) {\n var splices = [];\n\n for (var i = 0; i < changeRecords.length; i++) {\n var record = changeRecords[i];\n switch(record.type) {\n case 'splice':\n mergeSplice(splices, record.index, record.removed.slice(), record.addedCount);\n break;\n case 'add':\n case 'update':\n case 'delete':\n if (!isIndex(record.name))\n continue;\n var index = toNumber(record.name);\n if (index < 0)\n continue;\n mergeSplice(splices, index, [record.oldValue], 1);\n break;\n default:\n console.error('Unexpected record type: ' + JSON.stringify(record));\n break;\n }\n }\n\n return splices;\n }\n\n function projectArraySplices(array, changeRecords) {\n var splices = [];\n\n createInitialSplices(array, changeRecords).forEach(function(splice) {\n if (splice.addedCount == 1 && splice.removed.length == 1) {\n if (splice.removed[0] !== array[splice.index])\n splices.push(splice);\n\n return\n };\n\n splices = splices.concat(calcSplices(array, splice.index, splice.index + splice.addedCount,\n splice.removed, 0, splice.removed.length));\n });\n\n return splices;\n }\n\n global.Observer = Observer;\n global.Observer.runEOM_ = runEOM;\n global.Observer.observerSentinel_ = observerSentinel; // for testing.\n global.Observer.hasObjectObserve = hasObserve;\n global.ArrayObserver = ArrayObserver;\n global.ArrayObserver.calculateSplices = function(current, previous) {\n return arraySplice.calculateSplices(current, previous);\n };\n\n global.ArraySplice = ArraySplice;\n global.ObjectObserver = ObjectObserver;\n global.PathObserver = PathObserver;\n global.CompoundObserver = CompoundObserver;\n global.Path = Path;\n global.ObserverTransform = ObserverTransform;\n})(typeof global !== 'undefined' && global && typeof module !== 'undefined' && module ? global : this || window);\n","// select ShadowDOM impl\r\nif (Platform.flags.shadow) {\r\n","// Copyright 2012 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\nwindow.ShadowDOMPolyfill = {};\n\n(function(scope) {\n 'use strict';\n\n var constructorTable = new WeakMap();\n var nativePrototypeTable = new WeakMap();\n var wrappers = Object.create(null);\n\n // Don't test for eval if document has CSP securityPolicy object and we can\n // see that eval is not supported. This avoids an error message in console\n // even when the exception is caught\n var hasEval = !('securityPolicy' in document) ||\n document.securityPolicy.allowsEval;\n\n if (typeof chrome !== 'undefined' && chrome.app && chrome.app.runtime) {\n hasEval = false;\n }\n\n if (hasEval) {\n try {\n var f = new Function('', 'return true;');\n hasEval = f();\n } catch (ex) {\n hasEval = false;\n }\n }\n\n function assert(b) {\n if (!b)\n throw new Error('Assertion failed');\n };\n\n var defineProperty = Object.defineProperty;\n var getOwnPropertyNames = Object.getOwnPropertyNames;\n var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n\n function mixin(to, from) {\n var names = getOwnPropertyNames(from);\n for (var i = 0; i < names.length; i++) {\n var name = names[i];\n defineProperty(to, name, getOwnPropertyDescriptor(from, name));\n }\n return to;\n };\n\n function mixinStatics(to, from) {\n var names = getOwnPropertyNames(from);\n for (var i = 0; i < names.length; i++) {\n var name = names[i];\n switch (name) {\n case 'arguments':\n case 'caller':\n case 'length':\n case 'name':\n case 'prototype':\n case 'toString':\n continue;\n }\n defineProperty(to, name, getOwnPropertyDescriptor(from, name));\n }\n return to;\n };\n\n function oneOf(object, propertyNames) {\n for (var i = 0; i < propertyNames.length; i++) {\n if (propertyNames[i] in object)\n return propertyNames[i];\n }\n }\n\n var nonEnumerableDataDescriptor = {\n value: undefined,\n configurable: true,\n enumerable: false,\n writable: true\n };\n\n function defineNonEnumerableDataProperty(object, name, value) {\n nonEnumerableDataDescriptor.value = value;\n defineProperty(object, name, nonEnumerableDataDescriptor);\n }\n\n // Mozilla's old DOM bindings are bretty busted:\n // https://bugzilla.mozilla.org/show_bug.cgi?id=855844\n // Make sure they are create before we start modifying things.\n getOwnPropertyNames(window);\n\n function getWrapperConstructor(node) {\n var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);\n var wrapperConstructor = constructorTable.get(nativePrototype);\n if (wrapperConstructor)\n return wrapperConstructor;\n\n var parentWrapperConstructor = getWrapperConstructor(nativePrototype);\n\n var GeneratedWrapper = createWrapperConstructor(parentWrapperConstructor);\n registerInternal(nativePrototype, GeneratedWrapper, node);\n\n return GeneratedWrapper;\n }\n\n function addForwardingProperties(nativePrototype, wrapperPrototype) {\n installProperty(nativePrototype, wrapperPrototype, true);\n }\n\n function registerInstanceProperties(wrapperPrototype, instanceObject) {\n installProperty(instanceObject, wrapperPrototype, false);\n }\n\n var isFirefox = /Firefox/.test(navigator.userAgent);\n\n // This is used as a fallback when getting the descriptor fails in\n // installProperty.\n var dummyDescriptor = {\n get: function() {},\n set: function(v) {},\n configurable: true,\n enumerable: true\n };\n\n function isEventHandlerName(name) {\n return /^on[a-z]+$/.test(name);\n }\n\n function isIdentifierName(name) {\n return /^\\w[a-zA-Z_0-9]*$/.test(name);\n }\n\n function getGetter(name) {\n return hasEval && isIdentifierName(name) ?\n new Function('return this.impl.' + name) :\n function() { return this.impl[name]; };\n }\n\n function getSetter(name) {\n return hasEval && isIdentifierName(name) ?\n new Function('v', 'this.impl.' + name + ' = v') :\n function(v) { this.impl[name] = v; };\n }\n\n function getMethod(name) {\n return hasEval && isIdentifierName(name) ?\n new Function('return this.impl.' + name +\n '.apply(this.impl, arguments)') :\n function() { return this.impl[name].apply(this.impl, arguments); };\n }\n\n function getDescriptor(source, name) {\n try {\n return Object.getOwnPropertyDescriptor(source, name);\n } catch (ex) {\n // JSC and V8 both use data properties instead of accessors which can\n // cause getting the property desciptor to throw an exception.\n // https://bugs.webkit.org/show_bug.cgi?id=49739\n return dummyDescriptor;\n }\n }\n\n function installProperty(source, target, allowMethod, opt_blacklist) {\n var names = getOwnPropertyNames(source);\n for (var i = 0; i < names.length; i++) {\n var name = names[i];\n if (name === 'polymerBlackList_')\n continue;\n\n if (name in target)\n continue;\n\n if (source.polymerBlackList_ && source.polymerBlackList_[name])\n continue;\n\n if (isFirefox) {\n // Tickle Firefox's old bindings.\n source.__lookupGetter__(name);\n }\n var descriptor = getDescriptor(source, name);\n var getter, setter;\n if (allowMethod && typeof descriptor.value === 'function') {\n target[name] = getMethod(name);\n continue;\n }\n\n var isEvent = isEventHandlerName(name);\n if (isEvent)\n getter = scope.getEventHandlerGetter(name);\n else\n getter = getGetter(name);\n\n if (descriptor.writable || descriptor.set) {\n if (isEvent)\n setter = scope.getEventHandlerSetter(name);\n else\n setter = getSetter(name);\n }\n\n defineProperty(target, name, {\n get: getter,\n set: setter,\n configurable: descriptor.configurable,\n enumerable: descriptor.enumerable\n });\n }\n }\n\n /**\n * @param {Function} nativeConstructor\n * @param {Function} wrapperConstructor\n * @param {Object=} opt_instance If present, this is used to extract\n * properties from an instance object.\n */\n function register(nativeConstructor, wrapperConstructor, opt_instance) {\n var nativePrototype = nativeConstructor.prototype;\n registerInternal(nativePrototype, wrapperConstructor, opt_instance);\n mixinStatics(wrapperConstructor, nativeConstructor);\n }\n\n function registerInternal(nativePrototype, wrapperConstructor, opt_instance) {\n var wrapperPrototype = wrapperConstructor.prototype;\n assert(constructorTable.get(nativePrototype) === undefined);\n\n constructorTable.set(nativePrototype, wrapperConstructor);\n nativePrototypeTable.set(wrapperPrototype, nativePrototype);\n\n addForwardingProperties(nativePrototype, wrapperPrototype);\n if (opt_instance)\n registerInstanceProperties(wrapperPrototype, opt_instance);\n\n defineNonEnumerableDataProperty(\n wrapperPrototype, 'constructor', wrapperConstructor);\n // Set it again. Some VMs optimizes objects that are used as prototypes.\n wrapperConstructor.prototype = wrapperPrototype;\n }\n\n function isWrapperFor(wrapperConstructor, nativeConstructor) {\n return constructorTable.get(nativeConstructor.prototype) ===\n wrapperConstructor;\n }\n\n /**\n * Creates a generic wrapper constructor based on |object| and its\n * constructor.\n * @param {Node} object\n * @return {Function} The generated constructor.\n */\n function registerObject(object) {\n var nativePrototype = Object.getPrototypeOf(object);\n\n var superWrapperConstructor = getWrapperConstructor(nativePrototype);\n var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor);\n registerInternal(nativePrototype, GeneratedWrapper, object);\n\n return GeneratedWrapper;\n }\n\n function createWrapperConstructor(superWrapperConstructor) {\n function GeneratedWrapper(node) {\n superWrapperConstructor.call(this, node);\n }\n var p = Object.create(superWrapperConstructor.prototype);\n p.constructor = GeneratedWrapper;\n GeneratedWrapper.prototype = p;\n\n return GeneratedWrapper;\n }\n\n var OriginalDOMImplementation = window.DOMImplementation;\n var OriginalEventTarget = window.EventTarget;\n var OriginalEvent = window.Event;\n var OriginalNode = window.Node;\n var OriginalWindow = window.Window;\n var OriginalRange = window.Range;\n var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;\n var OriginalWebGLRenderingContext = window.WebGLRenderingContext;\n var OriginalSVGElementInstance = window.SVGElementInstance;\n\n function isWrapper(object) {\n return object instanceof wrappers.EventTarget ||\n object instanceof wrappers.Event ||\n object instanceof wrappers.Range ||\n object instanceof wrappers.DOMImplementation ||\n object instanceof wrappers.CanvasRenderingContext2D ||\n wrappers.WebGLRenderingContext &&\n object instanceof wrappers.WebGLRenderingContext;\n }\n\n function isNative(object) {\n return OriginalEventTarget && object instanceof OriginalEventTarget ||\n object instanceof OriginalNode ||\n object instanceof OriginalEvent ||\n object instanceof OriginalWindow ||\n object instanceof OriginalRange ||\n object instanceof OriginalDOMImplementation ||\n object instanceof OriginalCanvasRenderingContext2D ||\n OriginalWebGLRenderingContext &&\n object instanceof OriginalWebGLRenderingContext ||\n OriginalSVGElementInstance &&\n object instanceof OriginalSVGElementInstance;\n }\n\n /**\n * Wraps a node in a WrapperNode. If there already exists a wrapper for the\n * |node| that wrapper is returned instead.\n * @param {Node} node\n * @return {WrapperNode}\n */\n function wrap(impl) {\n if (impl === null)\n return null;\n\n assert(isNative(impl));\n return impl.polymerWrapper_ ||\n (impl.polymerWrapper_ = new (getWrapperConstructor(impl))(impl));\n }\n\n /**\n * Unwraps a wrapper and returns the node it is wrapping.\n * @param {WrapperNode} wrapper\n * @return {Node}\n */\n function unwrap(wrapper) {\n if (wrapper === null)\n return null;\n assert(isWrapper(wrapper));\n return wrapper.impl;\n }\n\n /**\n * Unwraps object if it is a wrapper.\n * @param {Object} object\n * @return {Object} The native implementation object.\n */\n function unwrapIfNeeded(object) {\n return object && isWrapper(object) ? unwrap(object) : object;\n }\n\n /**\n * Wraps object if it is not a wrapper.\n * @param {Object} object\n * @return {Object} The wrapper for object.\n */\n function wrapIfNeeded(object) {\n return object && !isWrapper(object) ? wrap(object) : object;\n }\n\n /**\n * Overrides the current wrapper (if any) for node.\n * @param {Node} node\n * @param {WrapperNode=} wrapper If left out the wrapper will be created as\n * needed next time someone wraps the node.\n */\n function rewrap(node, wrapper) {\n if (wrapper === null)\n return;\n assert(isNative(node));\n assert(wrapper === undefined || isWrapper(wrapper));\n node.polymerWrapper_ = wrapper;\n }\n\n var getterDescriptor = {\n get: undefined,\n configurable: true,\n enumerable: true\n };\n\n function defineGetter(constructor, name, getter) {\n getterDescriptor.get = getter;\n defineProperty(constructor.prototype, name, getterDescriptor);\n }\n\n function defineWrapGetter(constructor, name) {\n defineGetter(constructor, name, function() {\n return wrap(this.impl[name]);\n });\n }\n\n /**\n * Forwards existing methods on the native object to the wrapper methods.\n * This does not wrap any of the arguments or the return value since the\n * wrapper implementation already takes care of that.\n * @param {Array.} constructors\n * @parem {Array.} names\n */\n function forwardMethodsToWrapper(constructors, names) {\n constructors.forEach(function(constructor) {\n names.forEach(function(name) {\n constructor.prototype[name] = function() {\n var w = wrapIfNeeded(this);\n return w[name].apply(w, arguments);\n };\n });\n });\n }\n\n scope.assert = assert;\n scope.constructorTable = constructorTable;\n scope.defineGetter = defineGetter;\n scope.defineWrapGetter = defineWrapGetter;\n scope.forwardMethodsToWrapper = forwardMethodsToWrapper;\n scope.isWrapper = isWrapper;\n scope.isWrapperFor = isWrapperFor;\n scope.mixin = mixin;\n scope.nativePrototypeTable = nativePrototypeTable;\n scope.oneOf = oneOf;\n scope.registerObject = registerObject;\n scope.registerWrapper = register;\n scope.rewrap = rewrap;\n scope.unwrap = unwrap;\n scope.unwrapIfNeeded = unwrapIfNeeded;\n scope.wrap = wrap;\n scope.wrapIfNeeded = wrapIfNeeded;\n scope.wrappers = wrappers;\n\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(context) {\n 'use strict';\n\n var OriginalMutationObserver = window.MutationObserver;\n var callbacks = [];\n var pending = false;\n var timerFunc;\n\n function handle() {\n pending = false;\n var copies = callbacks.slice(0);\n callbacks = [];\n for (var i = 0; i < copies.length; i++) {\n (0, copies[i])();\n }\n }\n\n if (OriginalMutationObserver) {\n var counter = 1;\n var observer = new OriginalMutationObserver(handle);\n var textNode = document.createTextNode(counter);\n observer.observe(textNode, {characterData: true});\n\n timerFunc = function() {\n counter = (counter + 1) % 2;\n textNode.data = counter;\n };\n\n } else {\n timerFunc = window.setImmediate || window.setTimeout;\n }\n\n function setEndOfMicrotask(func) {\n callbacks.push(func);\n if (pending)\n return;\n pending = true;\n timerFunc(handle, 0);\n }\n\n context.setEndOfMicrotask = setEndOfMicrotask;\n\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n 'use strict';\n\n var setEndOfMicrotask = scope.setEndOfMicrotask\n var wrapIfNeeded = scope.wrapIfNeeded\n var wrappers = scope.wrappers;\n\n var registrationsTable = new WeakMap();\n var globalMutationObservers = [];\n var isScheduled = false;\n\n function scheduleCallback(observer) {\n if (isScheduled)\n return;\n setEndOfMicrotask(notifyObservers);\n isScheduled = true;\n }\n\n // http://dom.spec.whatwg.org/#mutation-observers\n function notifyObservers() {\n isScheduled = false;\n\n do {\n var notifyList = globalMutationObservers.slice();\n var anyNonEmpty = false;\n for (var i = 0; i < notifyList.length; i++) {\n var mo = notifyList[i];\n var queue = mo.takeRecords();\n removeTransientObserversFor(mo);\n if (queue.length) {\n mo.callback_(queue, mo);\n anyNonEmpty = true;\n }\n }\n } while (anyNonEmpty);\n }\n\n /**\n * @param {string} type\n * @param {Node} target\n * @constructor\n */\n function MutationRecord(type, target) {\n this.type = type;\n this.target = target;\n this.addedNodes = new wrappers.NodeList();\n this.removedNodes = new wrappers.NodeList();\n this.previousSibling = null;\n this.nextSibling = null;\n this.attributeName = null;\n this.attributeNamespace = null;\n this.oldValue = null;\n }\n\n /**\n * Registers transient observers to ancestor and its ancesors for the node\n * which was removed.\n * @param {!Node} ancestor\n * @param {!Node} node\n */\n function registerTransientObservers(ancestor, node) {\n for (; ancestor; ancestor = ancestor.parentNode) {\n var registrations = registrationsTable.get(ancestor);\n if (!registrations)\n continue;\n for (var i = 0; i < registrations.length; i++) {\n var registration = registrations[i];\n if (registration.options.subtree)\n registration.addTransientObserver(node);\n }\n }\n }\n\n function removeTransientObserversFor(observer) {\n for (var i = 0; i < observer.nodes_.length; i++) {\n var node = observer.nodes_[i];\n var registrations = registrationsTable.get(node);\n if (!registrations)\n return;\n for (var j = 0; j < registrations.length; j++) {\n var registration = registrations[j];\n if (registration.observer === observer)\n registration.removeTransientObservers();\n }\n }\n }\n\n // http://dom.spec.whatwg.org/#queue-a-mutation-record\n function enqueueMutation(target, type, data) {\n // 1.\n var interestedObservers = Object.create(null);\n var associatedStrings = Object.create(null);\n\n // 2.\n for (var node = target; node; node = node.parentNode) {\n // 3.\n var registrations = registrationsTable.get(node);\n if (!registrations)\n continue;\n for (var j = 0; j < registrations.length; j++) {\n var registration = registrations[j];\n var options = registration.options;\n // 1.\n if (node !== target && !options.subtree)\n continue;\n\n // 2.\n if (type === 'attributes' && !options.attributes)\n continue;\n\n // 3. If type is \"attributes\", options's attributeFilter is present, and\n // either options's attributeFilter does not contain name or namespace\n // is non-null, continue.\n if (type === 'attributes' && options.attributeFilter &&\n (data.namespace !== null ||\n options.attributeFilter.indexOf(data.name) === -1)) {\n continue;\n }\n\n // 4.\n if (type === 'characterData' && !options.characterData)\n continue;\n\n // 5.\n if (type === 'childList' && !options.childList)\n continue;\n\n // 6.\n var observer = registration.observer;\n interestedObservers[observer.uid_] = observer;\n\n // 7. If either type is \"attributes\" and options's attributeOldValue is\n // true, or type is \"characterData\" and options's characterDataOldValue\n // is true, set the paired string of registered observer's observer in\n // interested observers to oldValue.\n if (type === 'attributes' && options.attributeOldValue ||\n type === 'characterData' && options.characterDataOldValue) {\n associatedStrings[observer.uid_] = data.oldValue;\n }\n }\n }\n\n var anyRecordsEnqueued = false;\n\n // 4.\n for (var uid in interestedObservers) {\n var observer = interestedObservers[uid];\n var record = new MutationRecord(type, target);\n\n // 2.\n if ('name' in data && 'namespace' in data) {\n record.attributeName = data.name;\n record.attributeNamespace = data.namespace;\n }\n\n // 3.\n if (data.addedNodes)\n record.addedNodes = data.addedNodes;\n\n // 4.\n if (data.removedNodes)\n record.removedNodes = data.removedNodes;\n\n // 5.\n if (data.previousSibling)\n record.previousSibling = data.previousSibling;\n\n // 6.\n if (data.nextSibling)\n record.nextSibling = data.nextSibling;\n\n // 7.\n if (associatedStrings[uid] !== undefined)\n record.oldValue = associatedStrings[uid];\n\n // 8.\n observer.records_.push(record);\n\n anyRecordsEnqueued = true;\n }\n\n if (anyRecordsEnqueued)\n scheduleCallback();\n }\n\n var slice = Array.prototype.slice;\n\n /**\n * @param {!Object} options\n * @constructor\n */\n function MutationObserverOptions(options) {\n this.childList = !!options.childList;\n this.subtree = !!options.subtree;\n\n // 1. If either options' attributeOldValue or attributeFilter is present\n // and options' attributes is omitted, set options' attributes to true.\n if (!('attributes' in options) &&\n ('attributeOldValue' in options || 'attributeFilter' in options)) {\n this.attributes = true;\n } else {\n this.attributes = !!options.attributes;\n }\n\n // 2. If options' characterDataOldValue is present and options'\n // characterData is omitted, set options' characterData to true.\n if ('characterDataOldValue' in options && !('characterData' in options))\n this.characterData = true;\n else\n this.characterData = !!options.characterData;\n\n // 3. & 4.\n if (!this.attributes &&\n (options.attributeOldValue || 'attributeFilter' in options) ||\n // 5.\n !this.characterData && options.characterDataOldValue) {\n throw new TypeError();\n }\n\n this.characterData = !!options.characterData;\n this.attributeOldValue = !!options.attributeOldValue;\n this.characterDataOldValue = !!options.characterDataOldValue;\n if ('attributeFilter' in options) {\n if (options.attributeFilter == null ||\n typeof options.attributeFilter !== 'object') {\n throw new TypeError();\n }\n this.attributeFilter = slice.call(options.attributeFilter);\n } else {\n this.attributeFilter = null;\n }\n }\n\n var uidCounter = 0;\n\n /**\n * The class that maps to the DOM MutationObserver interface.\n * @param {Function} callback.\n * @constructor\n */\n function MutationObserver(callback) {\n this.callback_ = callback;\n this.nodes_ = [];\n this.records_ = [];\n this.uid_ = ++uidCounter;\n\n // This will leak. There is no way to implement this without WeakRefs :'(\n globalMutationObservers.push(this);\n }\n\n MutationObserver.prototype = {\n // http://dom.spec.whatwg.org/#dom-mutationobserver-observe\n observe: function(target, options) {\n target = wrapIfNeeded(target);\n\n var newOptions = new MutationObserverOptions(options);\n\n // 6.\n var registration;\n var registrations = registrationsTable.get(target);\n if (!registrations)\n registrationsTable.set(target, registrations = []);\n\n for (var i = 0; i < registrations.length; i++) {\n if (registrations[i].observer === this) {\n registration = registrations[i];\n // 6.1.\n registration.removeTransientObservers();\n // 6.2.\n registration.options = newOptions;\n }\n }\n\n // 7.\n if (!registration) {\n registration = new Registration(this, target, newOptions);\n registrations.push(registration);\n this.nodes_.push(target);\n }\n },\n\n // http://dom.spec.whatwg.org/#dom-mutationobserver-disconnect\n disconnect: function() {\n this.nodes_.forEach(function(node) {\n var registrations = registrationsTable.get(node);\n for (var i = 0; i < registrations.length; i++) {\n var registration = registrations[i];\n if (registration.observer === this) {\n registrations.splice(i, 1);\n // Each node can only have one registered observer associated with\n // this observer.\n break;\n }\n }\n }, this);\n this.records_ = [];\n },\n\n takeRecords: function() {\n var copyOfRecords = this.records_;\n this.records_ = [];\n return copyOfRecords;\n }\n };\n\n /**\n * Class used to represent a registered observer.\n * @param {MutationObserver} observer\n * @param {Node} target\n * @param {MutationObserverOptions} options\n * @constructor\n */\n function Registration(observer, target, options) {\n this.observer = observer;\n this.target = target;\n this.options = options;\n this.transientObservedNodes = [];\n }\n\n Registration.prototype = {\n /**\n * Adds a transient observer on node. The transient observer gets removed\n * next time we deliver the change records.\n * @param {Node} node\n */\n addTransientObserver: function(node) {\n // Don't add transient observers on the target itself. We already have all\n // the required listeners set up on the target.\n if (node === this.target)\n return;\n\n this.transientObservedNodes.push(node);\n var registrations = registrationsTable.get(node);\n if (!registrations)\n registrationsTable.set(node, registrations = []);\n\n // We know that registrations does not contain this because we already\n // checked if node === this.target.\n registrations.push(this);\n },\n\n removeTransientObservers: function() {\n var transientObservedNodes = this.transientObservedNodes;\n this.transientObservedNodes = [];\n\n for (var i = 0; i < transientObservedNodes.length; i++) {\n var node = transientObservedNodes[i];\n var registrations = registrationsTable.get(node);\n for (var j = 0; j < registrations.length; j++) {\n if (registrations[j] === this) {\n registrations.splice(j, 1);\n // Each node can only have one registered observer associated with\n // this observer.\n break;\n }\n }\n }\n }\n };\n\n scope.enqueueMutation = enqueueMutation;\n scope.registerTransientObservers = registerTransientObservers;\n scope.wrappers.MutationObserver = MutationObserver;\n scope.wrappers.MutationRecord = MutationRecord;\n\n})(window.ShadowDOMPolyfill);\n","/**\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n 'use strict';\n\n /**\n * A tree scope represents the root of a tree. All nodes in a tree point to\n * the same TreeScope object. The tree scope of a node get set the first time\n * it is accessed or when a node is added or remove to a tree.\n * @constructor\n */\n function TreeScope(root, parent) {\n this.root = root;\n this.parent = parent;\n }\n\n TreeScope.prototype = {\n get renderer() {\n if (this.root instanceof scope.wrappers.ShadowRoot) {\n return scope.getRendererForHost(this.root.host);\n }\n return null;\n },\n\n contains: function(treeScope) {\n for (; treeScope; treeScope = treeScope.parent) {\n if (treeScope === this)\n return true;\n }\n return false;\n }\n };\n\n function setTreeScope(node, treeScope) {\n if (node.treeScope_ !== treeScope) {\n node.treeScope_ = treeScope;\n for (var sr = node.shadowRoot; sr; sr = sr.olderShadowRoot) {\n sr.treeScope_.parent = treeScope;\n }\n for (var child = node.firstChild; child; child = child.nextSibling) {\n setTreeScope(child, treeScope);\n }\n }\n }\n\n function getTreeScope(node) {\n if (node.treeScope_)\n return node.treeScope_;\n var parent = node.parentNode;\n var treeScope;\n if (parent)\n treeScope = getTreeScope(parent);\n else\n treeScope = new TreeScope(node, null);\n return node.treeScope_ = treeScope;\n }\n\n scope.TreeScope = TreeScope;\n scope.getTreeScope = getTreeScope;\n scope.setTreeScope = setTreeScope;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;\n var getTreeScope = scope.getTreeScope;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n var wrappers = scope.wrappers;\n\n var wrappedFuns = new WeakMap();\n var listenersTable = new WeakMap();\n var handledEventsTable = new WeakMap();\n var currentlyDispatchingEvents = new WeakMap();\n var targetTable = new WeakMap();\n var currentTargetTable = new WeakMap();\n var relatedTargetTable = new WeakMap();\n var eventPhaseTable = new WeakMap();\n var stopPropagationTable = new WeakMap();\n var stopImmediatePropagationTable = new WeakMap();\n var eventHandlersTable = new WeakMap();\n var eventPathTable = new WeakMap();\n\n function isShadowRoot(node) {\n return node instanceof wrappers.ShadowRoot;\n }\n\n function isInsertionPoint(node) {\n var localName = node.localName;\n return localName === 'content' || localName === 'shadow';\n }\n\n function isShadowHost(node) {\n return !!node.shadowRoot;\n }\n\n function getEventParent(node) {\n var dv;\n return node.parentNode || (dv = node.defaultView) && wrap(dv) || null;\n }\n\n // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-parent\n function calculateParents(node, context, ancestors) {\n if (ancestors.length)\n return ancestors.shift();\n\n // 1.\n if (isShadowRoot(node))\n return getInsertionParent(node) || node.host;\n\n // 2.\n var eventParents = scope.eventParentsTable.get(node);\n if (eventParents) {\n // Copy over the remaining event parents for next iteration.\n for (var i = 1; i < eventParents.length; i++) {\n ancestors[i - 1] = eventParents[i];\n }\n return eventParents[0];\n }\n\n // 3.\n if (context && isInsertionPoint(node)) {\n var parentNode = node.parentNode;\n if (parentNode && isShadowHost(parentNode)) {\n var trees = scope.getShadowTrees(parentNode);\n var p = getInsertionParent(context);\n for (var i = 0; i < trees.length; i++) {\n if (trees[i].contains(p))\n return p;\n }\n }\n }\n\n return getEventParent(node);\n }\n\n // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#event-retargeting\n function retarget(node) {\n var stack = []; // 1.\n var ancestor = node; // 2.\n var targets = [];\n var ancestors = [];\n while (ancestor) { // 3.\n var context = null; // 3.2.\n // TODO(arv): Change order of these. If the stack is empty we always end\n // up pushing ancestor, no matter what.\n if (isInsertionPoint(ancestor)) { // 3.1.\n context = topMostNotInsertionPoint(stack); // 3.1.1.\n var top = stack[stack.length - 1] || ancestor; // 3.1.2.\n stack.push(top);\n } else if (!stack.length) {\n stack.push(ancestor); // 3.3.\n }\n var target = stack[stack.length - 1]; // 3.4.\n targets.push({target: target, currentTarget: ancestor}); // 3.5.\n if (isShadowRoot(ancestor)) // 3.6.\n stack.pop(); // 3.6.1.\n\n ancestor = calculateParents(ancestor, context, ancestors); // 3.7.\n }\n return targets;\n }\n\n function topMostNotInsertionPoint(stack) {\n for (var i = stack.length - 1; i >= 0; i--) {\n if (!isInsertionPoint(stack[i]))\n return stack[i];\n }\n return null;\n }\n\n // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-related-target\n function adjustRelatedTarget(target, related) {\n var ancestors = [];\n while (target) { // 3.\n var stack = []; // 3.1.\n var ancestor = related; // 3.2.\n var last = undefined; // 3.3. Needs to be reset every iteration.\n while (ancestor) {\n var context = null;\n if (!stack.length) {\n stack.push(ancestor);\n } else {\n if (isInsertionPoint(ancestor)) { // 3.4.3.\n context = topMostNotInsertionPoint(stack);\n // isDistributed is more general than checking whether last is\n // assigned into ancestor.\n if (isDistributed(last)) { // 3.4.3.2.\n var head = stack[stack.length - 1];\n stack.push(head);\n }\n }\n }\n\n if (inSameTree(ancestor, target)) // 3.4.4.\n return stack[stack.length - 1];\n\n if (isShadowRoot(ancestor)) // 3.4.5.\n stack.pop();\n\n last = ancestor; // 3.4.6.\n ancestor = calculateParents(ancestor, context, ancestors); // 3.4.7.\n }\n if (isShadowRoot(target)) // 3.5.\n target = target.host;\n else\n target = target.parentNode; // 3.6.\n }\n }\n\n function getInsertionParent(node) {\n return scope.insertionParentTable.get(node);\n }\n\n function isDistributed(node) {\n return getInsertionParent(node);\n }\n\n function inSameTree(a, b) {\n return getTreeScope(a) === getTreeScope(b);\n }\n\n // pendingError is used to rethrow the first error we got during an event\n // dispatch. The browser actually reports all errors but to do that we would\n // need to rethrow the error asynchronously.\n var pendingError;\n\n function dispatchOriginalEvent(originalEvent) {\n // Make sure this event is only dispatched once.\n if (handledEventsTable.get(originalEvent))\n return;\n handledEventsTable.set(originalEvent, true);\n dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));\n if (pendingError) {\n var err = pendingError;\n pendingError = null;\n throw err;\n }\n }\n\n function isLoadLikeEvent(event) {\n switch (event.type) {\n case 'beforeunload':\n case 'load':\n case 'unload':\n return true;\n }\n return false;\n }\n\n function dispatchEvent(event, originalWrapperTarget) {\n if (currentlyDispatchingEvents.get(event))\n throw new Error('InvalidStateError')\n currentlyDispatchingEvents.set(event, true);\n\n // Render to ensure that the event path is correct.\n scope.renderAllPending();\n var eventPath = retarget(originalWrapperTarget);\n\n // For window \"load\" events the \"load\" event is dispatched at the window but\n // the target is set to the document.\n //\n // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end\n //\n // TODO(arv): Find a less hacky way to do this.\n if (eventPath.length === 2 &&\n eventPath[0].target instanceof wrappers.Document &&\n isLoadLikeEvent(event)) {\n eventPath.shift();\n }\n\n eventPathTable.set(event, eventPath);\n\n if (dispatchCapturing(event, eventPath)) {\n if (dispatchAtTarget(event, eventPath)) {\n dispatchBubbling(event, eventPath);\n }\n }\n\n eventPhaseTable.set(event, Event.NONE);\n currentTargetTable.delete(event, null);\n currentlyDispatchingEvents.delete(event);\n\n return event.defaultPrevented;\n }\n\n function dispatchCapturing(event, eventPath) {\n var phase;\n\n for (var i = eventPath.length - 1; i > 0; i--) {\n var target = eventPath[i].target;\n var currentTarget = eventPath[i].currentTarget;\n if (target === currentTarget)\n continue;\n\n phase = Event.CAPTURING_PHASE;\n if (!invoke(eventPath[i], event, phase))\n return false;\n }\n\n return true;\n }\n\n function dispatchAtTarget(event, eventPath) {\n var phase = Event.AT_TARGET;\n return invoke(eventPath[0], event, phase);\n }\n\n function dispatchBubbling(event, eventPath) {\n var bubbles = event.bubbles;\n var phase;\n\n for (var i = 1; i < eventPath.length; i++) {\n var target = eventPath[i].target;\n var currentTarget = eventPath[i].currentTarget;\n if (target === currentTarget)\n phase = Event.AT_TARGET;\n else if (bubbles && !stopImmediatePropagationTable.get(event))\n phase = Event.BUBBLING_PHASE;\n else\n continue;\n\n if (!invoke(eventPath[i], event, phase))\n return;\n }\n }\n\n function invoke(tuple, event, phase) {\n var target = tuple.target;\n var currentTarget = tuple.currentTarget;\n\n var listeners = listenersTable.get(currentTarget);\n if (!listeners)\n return true;\n\n if ('relatedTarget' in event) {\n var originalEvent = unwrap(event);\n var unwrappedRelatedTarget = originalEvent.relatedTarget;\n\n // X-Tag sets relatedTarget on a CustomEvent. If they do that there is no\n // way to have relatedTarget return the adjusted target but worse is that\n // the originalEvent might not have a relatedTarget so we hit an assert\n // when we try to wrap it.\n if (unwrappedRelatedTarget) {\n // In IE we can get objects that are not EventTargets at this point.\n // Safari does not have an EventTarget interface so revert to checking\n // for addEventListener as an approximation.\n if (unwrappedRelatedTarget instanceof Object &&\n unwrappedRelatedTarget.addEventListener) {\n var relatedTarget = wrap(unwrappedRelatedTarget);\n\n var adjusted = adjustRelatedTarget(currentTarget, relatedTarget);\n if (adjusted === target)\n return true;\n } else {\n adjusted = null;\n }\n relatedTargetTable.set(event, adjusted);\n }\n }\n\n eventPhaseTable.set(event, phase);\n var type = event.type;\n\n var anyRemoved = false;\n targetTable.set(event, target);\n currentTargetTable.set(event, currentTarget);\n\n for (var i = 0; i < listeners.length; i++) {\n var listener = listeners[i];\n if (listener.removed) {\n anyRemoved = true;\n continue;\n }\n\n if (listener.type !== type ||\n !listener.capture && phase === Event.CAPTURING_PHASE ||\n listener.capture && phase === Event.BUBBLING_PHASE) {\n continue;\n }\n\n try {\n if (typeof listener.handler === 'function')\n listener.handler.call(currentTarget, event);\n else\n listener.handler.handleEvent(event);\n\n if (stopImmediatePropagationTable.get(event))\n return false;\n\n } catch (ex) {\n if (!pendingError)\n pendingError = ex;\n }\n }\n\n if (anyRemoved) {\n var copy = listeners.slice();\n listeners.length = 0;\n for (var i = 0; i < copy.length; i++) {\n if (!copy[i].removed)\n listeners.push(copy[i]);\n }\n }\n\n return !stopPropagationTable.get(event);\n }\n\n function Listener(type, handler, capture) {\n this.type = type;\n this.handler = handler;\n this.capture = Boolean(capture);\n }\n Listener.prototype = {\n equals: function(that) {\n return this.handler === that.handler && this.type === that.type &&\n this.capture === that.capture;\n },\n get removed() {\n return this.handler === null;\n },\n remove: function() {\n this.handler = null;\n }\n };\n\n var OriginalEvent = window.Event;\n OriginalEvent.prototype.polymerBlackList_ = {\n returnValue: true,\n // TODO(arv): keyLocation is part of KeyboardEvent but Firefox does not\n // support constructable KeyboardEvent so we keep it here for now.\n keyLocation: true\n };\n\n /**\n * Creates a new Event wrapper or wraps an existin native Event object.\n * @param {string|Event} type\n * @param {Object=} options\n * @constructor\n */\n function Event(type, options) {\n if (type instanceof OriginalEvent) {\n var impl = type;\n if (!OriginalBeforeUnloadEvent && impl.type === 'beforeunload')\n return new BeforeUnloadEvent(impl);\n this.impl = impl;\n } else {\n return wrap(constructEvent(OriginalEvent, 'Event', type, options));\n }\n }\n Event.prototype = {\n get target() {\n return targetTable.get(this);\n },\n get currentTarget() {\n return currentTargetTable.get(this);\n },\n get eventPhase() {\n return eventPhaseTable.get(this);\n },\n get path() {\n var nodeList = new wrappers.NodeList();\n var eventPath = eventPathTable.get(this);\n if (eventPath) {\n var index = 0;\n var lastIndex = eventPath.length - 1;\n var baseRoot = getTreeScope(currentTargetTable.get(this));\n\n for (var i = 0; i <= lastIndex; i++) {\n var currentTarget = eventPath[i].currentTarget;\n var currentRoot = getTreeScope(currentTarget);\n if (currentRoot.contains(baseRoot) &&\n // Make sure we do not add Window to the path.\n (i !== lastIndex || currentTarget instanceof wrappers.Node)) {\n nodeList[index++] = currentTarget;\n }\n }\n nodeList.length = index;\n }\n return nodeList;\n },\n stopPropagation: function() {\n stopPropagationTable.set(this, true);\n },\n stopImmediatePropagation: function() {\n stopPropagationTable.set(this, true);\n stopImmediatePropagationTable.set(this, true);\n }\n };\n registerWrapper(OriginalEvent, Event, document.createEvent('Event'));\n\n function unwrapOptions(options) {\n if (!options || !options.relatedTarget)\n return options;\n return Object.create(options, {\n relatedTarget: {value: unwrap(options.relatedTarget)}\n });\n }\n\n function registerGenericEvent(name, SuperEvent, prototype) {\n var OriginalEvent = window[name];\n var GenericEvent = function(type, options) {\n if (type instanceof OriginalEvent)\n this.impl = type;\n else\n return wrap(constructEvent(OriginalEvent, name, type, options));\n };\n GenericEvent.prototype = Object.create(SuperEvent.prototype);\n if (prototype)\n mixin(GenericEvent.prototype, prototype);\n if (OriginalEvent) {\n // - Old versions of Safari fails on new FocusEvent (and others?).\n // - IE does not support event constructors.\n // - createEvent('FocusEvent') throws in Firefox.\n // => Try the best practice solution first and fallback to the old way\n // if needed.\n try {\n registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent('temp'));\n } catch (ex) {\n registerWrapper(OriginalEvent, GenericEvent,\n document.createEvent(name));\n }\n }\n return GenericEvent;\n }\n\n var UIEvent = registerGenericEvent('UIEvent', Event);\n var CustomEvent = registerGenericEvent('CustomEvent', Event);\n\n var relatedTargetProto = {\n get relatedTarget() {\n var relatedTarget = relatedTargetTable.get(this);\n // relatedTarget can be null.\n if (relatedTarget !== undefined)\n return relatedTarget;\n return wrap(unwrap(this).relatedTarget);\n }\n };\n\n function getInitFunction(name, relatedTargetIndex) {\n return function() {\n arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]);\n var impl = unwrap(this);\n impl[name].apply(impl, arguments);\n };\n }\n\n var mouseEventProto = mixin({\n initMouseEvent: getInitFunction('initMouseEvent', 14)\n }, relatedTargetProto);\n\n var focusEventProto = mixin({\n initFocusEvent: getInitFunction('initFocusEvent', 5)\n }, relatedTargetProto);\n\n var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto);\n var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto);\n\n // In case the browser does not support event constructors we polyfill that\n // by calling `createEvent('Foo')` and `initFooEvent` where the arguments to\n // `initFooEvent` are derived from the registered default event init dict.\n var defaultInitDicts = Object.create(null);\n\n var supportsEventConstructors = (function() {\n try {\n new window.FocusEvent('focus');\n } catch (ex) {\n return false;\n }\n return true;\n })();\n\n /**\n * Constructs a new native event.\n */\n function constructEvent(OriginalEvent, name, type, options) {\n if (supportsEventConstructors)\n return new OriginalEvent(type, unwrapOptions(options));\n\n // Create the arguments from the default dictionary.\n var event = unwrap(document.createEvent(name));\n var defaultDict = defaultInitDicts[name];\n var args = [type];\n Object.keys(defaultDict).forEach(function(key) {\n var v = options != null && key in options ?\n options[key] : defaultDict[key];\n if (key === 'relatedTarget')\n v = unwrap(v);\n args.push(v);\n });\n event['init' + name].apply(event, args);\n return event;\n }\n\n if (!supportsEventConstructors) {\n var configureEventConstructor = function(name, initDict, superName) {\n if (superName) {\n var superDict = defaultInitDicts[superName];\n initDict = mixin(mixin({}, superDict), initDict);\n }\n\n defaultInitDicts[name] = initDict;\n };\n\n // The order of the default event init dictionary keys is important, the\n // arguments to initFooEvent is derived from that.\n configureEventConstructor('Event', {bubbles: false, cancelable: false});\n configureEventConstructor('CustomEvent', {detail: null}, 'Event');\n configureEventConstructor('UIEvent', {view: null, detail: 0}, 'Event');\n configureEventConstructor('MouseEvent', {\n screenX: 0,\n screenY: 0,\n clientX: 0,\n clientY: 0,\n ctrlKey: false,\n altKey: false,\n shiftKey: false,\n metaKey: false,\n button: 0,\n relatedTarget: null\n }, 'UIEvent');\n configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent');\n }\n\n // Safari 7 does not yet have BeforeUnloadEvent.\n // https://bugs.webkit.org/show_bug.cgi?id=120849\n var OriginalBeforeUnloadEvent = window.BeforeUnloadEvent;\n\n function BeforeUnloadEvent(impl) {\n Event.call(this, impl);\n }\n BeforeUnloadEvent.prototype = Object.create(Event.prototype);\n mixin(BeforeUnloadEvent.prototype, {\n get returnValue() {\n return this.impl.returnValue;\n },\n set returnValue(v) {\n this.impl.returnValue = v;\n }\n });\n\n if (OriginalBeforeUnloadEvent)\n registerWrapper(OriginalBeforeUnloadEvent, BeforeUnloadEvent);\n\n function isValidListener(fun) {\n if (typeof fun === 'function')\n return true;\n return fun && fun.handleEvent;\n }\n\n function isMutationEvent(type) {\n switch (type) {\n case 'DOMAttrModified':\n case 'DOMAttributeNameChanged':\n case 'DOMCharacterDataModified':\n case 'DOMElementNameChanged':\n case 'DOMNodeInserted':\n case 'DOMNodeInsertedIntoDocument':\n case 'DOMNodeRemoved':\n case 'DOMNodeRemovedFromDocument':\n case 'DOMSubtreeModified':\n return true;\n }\n return false;\n }\n\n var OriginalEventTarget = window.EventTarget;\n\n /**\n * This represents a wrapper for an EventTarget.\n * @param {!EventTarget} impl The original event target.\n * @constructor\n */\n function EventTarget(impl) {\n this.impl = impl;\n }\n\n // Node and Window have different internal type checks in WebKit so we cannot\n // use the same method as the original function.\n var methodNames = [\n 'addEventListener',\n 'removeEventListener',\n 'dispatchEvent'\n ];\n\n [Node, Window].forEach(function(constructor) {\n var p = constructor.prototype;\n methodNames.forEach(function(name) {\n Object.defineProperty(p, name + '_', {value: p[name]});\n });\n });\n\n function getTargetToListenAt(wrapper) {\n if (wrapper instanceof wrappers.ShadowRoot)\n wrapper = wrapper.host;\n return unwrap(wrapper);\n }\n\n EventTarget.prototype = {\n addEventListener: function(type, fun, capture) {\n if (!isValidListener(fun) || isMutationEvent(type))\n return;\n\n var listener = new Listener(type, fun, capture);\n var listeners = listenersTable.get(this);\n if (!listeners) {\n listeners = [];\n listenersTable.set(this, listeners);\n } else {\n // Might have a duplicate.\n for (var i = 0; i < listeners.length; i++) {\n if (listener.equals(listeners[i]))\n return;\n }\n }\n\n listeners.push(listener);\n\n var target = getTargetToListenAt(this);\n target.addEventListener_(type, dispatchOriginalEvent, true);\n },\n removeEventListener: function(type, fun, capture) {\n capture = Boolean(capture);\n var listeners = listenersTable.get(this);\n if (!listeners)\n return;\n var count = 0, found = false;\n for (var i = 0; i < listeners.length; i++) {\n if (listeners[i].type === type && listeners[i].capture === capture) {\n count++;\n if (listeners[i].handler === fun) {\n found = true;\n listeners[i].remove();\n }\n }\n }\n\n if (found && count === 1) {\n var target = getTargetToListenAt(this);\n target.removeEventListener_(type, dispatchOriginalEvent, true);\n }\n },\n dispatchEvent: function(event) {\n // We want to use the native dispatchEvent because it triggers the default\n // actions (like checking a checkbox). However, if there are no listeners\n // in the composed tree then there are no events that will trigger and\n // listeners in the non composed tree that are part of the event path are\n // not notified.\n //\n // If we find out that there are no listeners in the composed tree we add\n // a temporary listener to the target which makes us get called back even\n // in that case.\n\n var nativeEvent = unwrap(event);\n var eventType = nativeEvent.type;\n\n // Allow dispatching the same event again. This is safe because if user\n // code calls this during an existing dispatch of the same event the\n // native dispatchEvent throws (that is required by the spec).\n handledEventsTable.set(nativeEvent, false);\n\n // Force rendering since we prefer native dispatch and that works on the\n // composed tree.\n scope.renderAllPending();\n\n var tempListener;\n if (!hasListenerInAncestors(this, eventType)) {\n tempListener = function() {};\n this.addEventListener(eventType, tempListener, true);\n }\n\n try {\n return unwrap(this).dispatchEvent_(nativeEvent);\n } finally {\n if (tempListener)\n this.removeEventListener(eventType, tempListener, true);\n }\n }\n };\n\n function hasListener(node, type) {\n var listeners = listenersTable.get(node);\n if (listeners) {\n for (var i = 0; i < listeners.length; i++) {\n if (!listeners[i].removed && listeners[i].type === type)\n return true;\n }\n }\n return false;\n }\n\n function hasListenerInAncestors(target, type) {\n for (var node = unwrap(target); node; node = node.parentNode) {\n if (hasListener(wrap(node), type))\n return true;\n }\n return false;\n }\n\n if (OriginalEventTarget)\n registerWrapper(OriginalEventTarget, EventTarget);\n\n function wrapEventTargetMethods(constructors) {\n forwardMethodsToWrapper(constructors, methodNames);\n }\n\n var originalElementFromPoint = document.elementFromPoint;\n\n function elementFromPoint(self, document, x, y) {\n scope.renderAllPending();\n\n var element = wrap(originalElementFromPoint.call(document.impl, x, y));\n var targets = retarget(element, this)\n for (var i = 0; i < targets.length; i++) {\n var target = targets[i];\n if (target.currentTarget === self)\n return target.target;\n }\n return null;\n }\n\n /**\n * Returns a function that is to be used as a getter for `onfoo` properties.\n * @param {string} name\n * @return {Function}\n */\n function getEventHandlerGetter(name) {\n return function() {\n var inlineEventHandlers = eventHandlersTable.get(this);\n return inlineEventHandlers && inlineEventHandlers[name] &&\n inlineEventHandlers[name].value || null;\n };\n }\n\n /**\n * Returns a function that is to be used as a setter for `onfoo` properties.\n * @param {string} name\n * @return {Function}\n */\n function getEventHandlerSetter(name) {\n var eventType = name.slice(2);\n return function(value) {\n var inlineEventHandlers = eventHandlersTable.get(this);\n if (!inlineEventHandlers) {\n inlineEventHandlers = Object.create(null);\n eventHandlersTable.set(this, inlineEventHandlers);\n }\n\n var old = inlineEventHandlers[name];\n if (old)\n this.removeEventListener(eventType, old.wrapped, false);\n\n if (typeof value === 'function') {\n var wrapped = function(e) {\n var rv = value.call(this, e);\n if (rv === false)\n e.preventDefault();\n else if (name === 'onbeforeunload' && typeof rv === 'string')\n e.returnValue = rv;\n // mouseover uses true for preventDefault but preventDefault for\n // mouseover is ignored by browsers these day.\n };\n\n this.addEventListener(eventType, wrapped, false);\n inlineEventHandlers[name] = {\n value: value,\n wrapped: wrapped\n };\n }\n };\n }\n\n scope.adjustRelatedTarget = adjustRelatedTarget;\n scope.elementFromPoint = elementFromPoint;\n scope.getEventHandlerGetter = getEventHandlerGetter;\n scope.getEventHandlerSetter = getEventHandlerSetter;\n scope.wrapEventTargetMethods = wrapEventTargetMethods;\n scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;\n scope.wrappers.CustomEvent = CustomEvent;\n scope.wrappers.Event = Event;\n scope.wrappers.EventTarget = EventTarget;\n scope.wrappers.FocusEvent = FocusEvent;\n scope.wrappers.MouseEvent = MouseEvent;\n scope.wrappers.UIEvent = UIEvent;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2012 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var wrap = scope.wrap;\n\n var nonEnumDescriptor = {enumerable: false};\n\n function nonEnum(obj, prop) {\n Object.defineProperty(obj, prop, nonEnumDescriptor);\n }\n\n function NodeList() {\n this.length = 0;\n nonEnum(this, 'length');\n }\n NodeList.prototype = {\n item: function(index) {\n return this[index];\n }\n };\n nonEnum(NodeList.prototype, 'item');\n\n function wrapNodeList(list) {\n if (list == null)\n return list;\n var wrapperList = new NodeList();\n for (var i = 0, length = list.length; i < length; i++) {\n wrapperList[i] = wrap(list[i]);\n }\n wrapperList.length = length;\n return wrapperList;\n }\n\n function addWrapNodeListMethod(wrapperConstructor, name) {\n wrapperConstructor.prototype[name] = function() {\n return wrapNodeList(this.impl[name].apply(this.impl, arguments));\n };\n }\n\n scope.wrappers.NodeList = NodeList;\n scope.addWrapNodeListMethod = addWrapNodeListMethod;\n scope.wrapNodeList = wrapNodeList;\n\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n 'use strict';\n\n // TODO(arv): Implement.\n\n scope.wrapHTMLCollection = scope.wrapNodeList;\n scope.wrappers.HTMLCollection = scope.wrappers.NodeList;\n\n})(window.ShadowDOMPolyfill);\n","/**\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n 'use strict';\n\n var EventTarget = scope.wrappers.EventTarget;\n var NodeList = scope.wrappers.NodeList;\n var TreeScope = scope.TreeScope;\n var assert = scope.assert;\n var defineWrapGetter = scope.defineWrapGetter;\n var enqueueMutation = scope.enqueueMutation;\n var getTreeScope = scope.getTreeScope;\n var isWrapper = scope.isWrapper;\n var mixin = scope.mixin;\n var registerTransientObservers = scope.registerTransientObservers;\n var registerWrapper = scope.registerWrapper;\n var setTreeScope = scope.setTreeScope;\n var unwrap = scope.unwrap;\n var unwrapIfNeeded = scope.unwrapIfNeeded;\n var wrap = scope.wrap;\n var wrapIfNeeded = scope.wrapIfNeeded;\n var wrappers = scope.wrappers;\n\n function assertIsNodeWrapper(node) {\n assert(node instanceof Node);\n }\n\n function createOneElementNodeList(node) {\n var nodes = new NodeList();\n nodes[0] = node;\n nodes.length = 1;\n return nodes;\n }\n\n var surpressMutations = false;\n\n /**\n * Called before node is inserted into a node to enqueue its removal from its\n * old parent.\n * @param {!Node} node The node that is about to be removed.\n * @param {!Node} parent The parent node that the node is being removed from.\n * @param {!NodeList} nodes The collected nodes.\n */\n function enqueueRemovalForInsertedNodes(node, parent, nodes) {\n enqueueMutation(parent, 'childList', {\n removedNodes: nodes,\n previousSibling: node.previousSibling,\n nextSibling: node.nextSibling\n });\n }\n\n function enqueueRemovalForInsertedDocumentFragment(df, nodes) {\n enqueueMutation(df, 'childList', {\n removedNodes: nodes\n });\n }\n\n /**\n * Collects nodes from a DocumentFragment or a Node for removal followed\n * by an insertion.\n *\n * This updates the internal pointers for node, previousNode and nextNode.\n */\n function collectNodes(node, parentNode, previousNode, nextNode) {\n if (node instanceof DocumentFragment) {\n var nodes = collectNodesForDocumentFragment(node);\n\n // The extra loop is to work around bugs with DocumentFragments in IE.\n surpressMutations = true;\n for (var i = nodes.length - 1; i >= 0; i--) {\n node.removeChild(nodes[i]);\n nodes[i].parentNode_ = parentNode;\n }\n surpressMutations = false;\n\n for (var i = 0; i < nodes.length; i++) {\n nodes[i].previousSibling_ = nodes[i - 1] || previousNode;\n nodes[i].nextSibling_ = nodes[i + 1] || nextNode;\n }\n\n if (previousNode)\n previousNode.nextSibling_ = nodes[0];\n if (nextNode)\n nextNode.previousSibling_ = nodes[nodes.length - 1];\n\n return nodes;\n }\n\n var nodes = createOneElementNodeList(node);\n var oldParent = node.parentNode;\n if (oldParent) {\n // This will enqueue the mutation record for the removal as needed.\n oldParent.removeChild(node);\n }\n\n node.parentNode_ = parentNode;\n node.previousSibling_ = previousNode;\n node.nextSibling_ = nextNode;\n if (previousNode)\n previousNode.nextSibling_ = node;\n if (nextNode)\n nextNode.previousSibling_ = node;\n\n return nodes;\n }\n\n function collectNodesNative(node) {\n if (node instanceof DocumentFragment)\n return collectNodesForDocumentFragment(node);\n\n var nodes = createOneElementNodeList(node);\n var oldParent = node.parentNode;\n if (oldParent)\n enqueueRemovalForInsertedNodes(node, oldParent, nodes);\n return nodes;\n }\n\n function collectNodesForDocumentFragment(node) {\n var nodes = new NodeList();\n var i = 0;\n for (var child = node.firstChild; child; child = child.nextSibling) {\n nodes[i++] = child;\n }\n nodes.length = i;\n enqueueRemovalForInsertedDocumentFragment(node, nodes);\n return nodes;\n }\n\n function snapshotNodeList(nodeList) {\n // NodeLists are not live at the moment so just return the same object.\n return nodeList;\n }\n\n // http://dom.spec.whatwg.org/#node-is-inserted\n function nodeWasAdded(node, treeScope) {\n setTreeScope(node, treeScope);\n node.nodeIsInserted_();\n }\n\n function nodesWereAdded(nodes, parent) {\n var treeScope = getTreeScope(parent);\n for (var i = 0; i < nodes.length; i++) {\n nodeWasAdded(nodes[i], treeScope);\n }\n }\n\n // http://dom.spec.whatwg.org/#node-is-removed\n function nodeWasRemoved(node) {\n setTreeScope(node, new TreeScope(node, null));\n }\n\n function nodesWereRemoved(nodes) {\n for (var i = 0; i < nodes.length; i++) {\n nodeWasRemoved(nodes[i]);\n }\n }\n\n function ensureSameOwnerDocument(parent, child) {\n var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ?\n parent : parent.ownerDocument;\n if (ownerDoc !== child.ownerDocument)\n ownerDoc.adoptNode(child);\n }\n\n function adoptNodesIfNeeded(owner, nodes) {\n if (!nodes.length)\n return;\n\n var ownerDoc = owner.ownerDocument;\n\n // All nodes have the same ownerDocument when we get here.\n if (ownerDoc === nodes[0].ownerDocument)\n return;\n\n for (var i = 0; i < nodes.length; i++) {\n scope.adoptNodeNoRemove(nodes[i], ownerDoc);\n }\n }\n\n function unwrapNodesForInsertion(owner, nodes) {\n adoptNodesIfNeeded(owner, nodes);\n var length = nodes.length;\n\n if (length === 1)\n return unwrap(nodes[0]);\n\n var df = unwrap(owner.ownerDocument.createDocumentFragment());\n for (var i = 0; i < length; i++) {\n df.appendChild(unwrap(nodes[i]));\n }\n return df;\n }\n\n function clearChildNodes(wrapper) {\n if (wrapper.firstChild_ !== undefined) {\n var child = wrapper.firstChild_;\n while (child) {\n var tmp = child;\n child = child.nextSibling_;\n tmp.parentNode_ = tmp.previousSibling_ = tmp.nextSibling_ = undefined;\n }\n }\n wrapper.firstChild_ = wrapper.lastChild_ = undefined;\n }\n\n function removeAllChildNodes(wrapper) {\n if (wrapper.invalidateShadowRenderer()) {\n var childWrapper = wrapper.firstChild;\n while (childWrapper) {\n assert(childWrapper.parentNode === wrapper);\n var nextSibling = childWrapper.nextSibling;\n var childNode = unwrap(childWrapper);\n var parentNode = childNode.parentNode;\n if (parentNode)\n originalRemoveChild.call(parentNode, childNode);\n childWrapper.previousSibling_ = childWrapper.nextSibling_ =\n childWrapper.parentNode_ = null;\n childWrapper = nextSibling;\n }\n wrapper.firstChild_ = wrapper.lastChild_ = null;\n } else {\n var node = unwrap(wrapper);\n var child = node.firstChild;\n var nextSibling;\n while (child) {\n nextSibling = child.nextSibling;\n originalRemoveChild.call(node, child);\n child = nextSibling;\n }\n }\n }\n\n function invalidateParent(node) {\n var p = node.parentNode;\n return p && p.invalidateShadowRenderer();\n }\n\n function cleanupNodes(nodes) {\n for (var i = 0, n; i < nodes.length; i++) {\n n = nodes[i];\n n.parentNode.removeChild(n);\n }\n }\n\n var originalImportNode = document.importNode;\n var originalCloneNode = window.Node.prototype.cloneNode;\n\n function cloneNode(node, deep, opt_doc) {\n var clone;\n if (opt_doc)\n clone = wrap(originalImportNode.call(opt_doc, node.impl, false));\n else\n clone = wrap(originalCloneNode.call(node.impl, false));\n\n if (deep) {\n for (var child = node.firstChild; child; child = child.nextSibling) {\n clone.appendChild(cloneNode(child, true, opt_doc));\n }\n\n if (node instanceof wrappers.HTMLTemplateElement) {\n var cloneContent = clone.content;\n for (var child = node.content.firstChild;\n child;\n child = child.nextSibling) {\n cloneContent.appendChild(cloneNode(child, true, opt_doc));\n }\n }\n }\n // TODO(arv): Some HTML elements also clone other data like value.\n return clone;\n }\n\n function contains(self, child) {\n if (!child || getTreeScope(self) !== getTreeScope(child))\n return false;\n\n for (var node = child; node; node = node.parentNode) {\n if (node === self)\n return true;\n }\n return false;\n }\n\n var OriginalNode = window.Node;\n\n /**\n * This represents a wrapper of a native DOM node.\n * @param {!Node} original The original DOM node, aka, the visual DOM node.\n * @constructor\n * @extends {EventTarget}\n */\n function Node(original) {\n assert(original instanceof OriginalNode);\n\n EventTarget.call(this, original);\n\n // These properties are used to override the visual references with the\n // logical ones. If the value is undefined it means that the logical is the\n // same as the visual.\n\n /**\n * @type {Node|undefined}\n * @private\n */\n this.parentNode_ = undefined;\n\n /**\n * @type {Node|undefined}\n * @private\n */\n this.firstChild_ = undefined;\n\n /**\n * @type {Node|undefined}\n * @private\n */\n this.lastChild_ = undefined;\n\n /**\n * @type {Node|undefined}\n * @private\n */\n this.nextSibling_ = undefined;\n\n /**\n * @type {Node|undefined}\n * @private\n */\n this.previousSibling_ = undefined;\n\n this.treeScope_ = undefined;\n }\n\n var OriginalDocumentFragment = window.DocumentFragment;\n var originalAppendChild = OriginalNode.prototype.appendChild;\n var originalCompareDocumentPosition =\n OriginalNode.prototype.compareDocumentPosition;\n var originalInsertBefore = OriginalNode.prototype.insertBefore;\n var originalRemoveChild = OriginalNode.prototype.removeChild;\n var originalReplaceChild = OriginalNode.prototype.replaceChild;\n\n var isIe = /Trident/.test(navigator.userAgent);\n\n var removeChildOriginalHelper = isIe ?\n function(parent, child) {\n try {\n originalRemoveChild.call(parent, child);\n } catch (ex) {\n if (!(parent instanceof OriginalDocumentFragment))\n throw ex;\n }\n } :\n function(parent, child) {\n originalRemoveChild.call(parent, child);\n };\n\n Node.prototype = Object.create(EventTarget.prototype);\n mixin(Node.prototype, {\n appendChild: function(childWrapper) {\n return this.insertBefore(childWrapper, null);\n },\n\n insertBefore: function(childWrapper, refWrapper) {\n assertIsNodeWrapper(childWrapper);\n\n var refNode;\n if (refWrapper) {\n if (isWrapper(refWrapper)) {\n refNode = unwrap(refWrapper);\n } else {\n refNode = refWrapper;\n refWrapper = wrap(refNode);\n }\n } else {\n refWrapper = null;\n refNode = null;\n }\n\n refWrapper && assert(refWrapper.parentNode === this);\n\n var nodes;\n var previousNode =\n refWrapper ? refWrapper.previousSibling : this.lastChild;\n\n var useNative = !this.invalidateShadowRenderer() &&\n !invalidateParent(childWrapper);\n\n if (useNative)\n nodes = collectNodesNative(childWrapper);\n else\n nodes = collectNodes(childWrapper, this, previousNode, refWrapper);\n\n if (useNative) {\n ensureSameOwnerDocument(this, childWrapper);\n clearChildNodes(this);\n originalInsertBefore.call(this.impl, unwrap(childWrapper), refNode);\n } else {\n if (!previousNode)\n this.firstChild_ = nodes[0];\n if (!refWrapper)\n this.lastChild_ = nodes[nodes.length - 1];\n\n var parentNode = refNode ? refNode.parentNode : this.impl;\n\n // insertBefore refWrapper no matter what the parent is?\n if (parentNode) {\n originalInsertBefore.call(parentNode,\n unwrapNodesForInsertion(this, nodes), refNode);\n } else {\n adoptNodesIfNeeded(this, nodes);\n }\n }\n\n enqueueMutation(this, 'childList', {\n addedNodes: nodes,\n nextSibling: refWrapper,\n previousSibling: previousNode\n });\n\n nodesWereAdded(nodes, this);\n\n return childWrapper;\n },\n\n removeChild: function(childWrapper) {\n assertIsNodeWrapper(childWrapper);\n if (childWrapper.parentNode !== this) {\n // IE has invalid DOM trees at times.\n var found = false;\n var childNodes = this.childNodes;\n for (var ieChild = this.firstChild; ieChild;\n ieChild = ieChild.nextSibling) {\n if (ieChild === childWrapper) {\n found = true;\n break;\n }\n }\n if (!found) {\n // TODO(arv): DOMException\n throw new Error('NotFoundError');\n }\n }\n\n var childNode = unwrap(childWrapper);\n var childWrapperNextSibling = childWrapper.nextSibling;\n var childWrapperPreviousSibling = childWrapper.previousSibling;\n\n if (this.invalidateShadowRenderer()) {\n // We need to remove the real node from the DOM before updating the\n // pointers. This is so that that mutation event is dispatched before\n // the pointers have changed.\n var thisFirstChild = this.firstChild;\n var thisLastChild = this.lastChild;\n\n var parentNode = childNode.parentNode;\n if (parentNode)\n removeChildOriginalHelper(parentNode, childNode);\n\n if (thisFirstChild === childWrapper)\n this.firstChild_ = childWrapperNextSibling;\n if (thisLastChild === childWrapper)\n this.lastChild_ = childWrapperPreviousSibling;\n if (childWrapperPreviousSibling)\n childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling;\n if (childWrapperNextSibling) {\n childWrapperNextSibling.previousSibling_ =\n childWrapperPreviousSibling;\n }\n\n childWrapper.previousSibling_ = childWrapper.nextSibling_ =\n childWrapper.parentNode_ = undefined;\n } else {\n clearChildNodes(this);\n removeChildOriginalHelper(this.impl, childNode);\n }\n\n if (!surpressMutations) {\n enqueueMutation(this, 'childList', {\n removedNodes: createOneElementNodeList(childWrapper),\n nextSibling: childWrapperNextSibling,\n previousSibling: childWrapperPreviousSibling\n });\n }\n\n registerTransientObservers(this, childWrapper);\n\n return childWrapper;\n },\n\n replaceChild: function(newChildWrapper, oldChildWrapper) {\n assertIsNodeWrapper(newChildWrapper);\n\n var oldChildNode;\n if (isWrapper(oldChildWrapper)) {\n oldChildNode = unwrap(oldChildWrapper);\n } else {\n oldChildNode = oldChildWrapper;\n oldChildWrapper = wrap(oldChildNode);\n }\n\n if (oldChildWrapper.parentNode !== this) {\n // TODO(arv): DOMException\n throw new Error('NotFoundError');\n }\n\n var nextNode = oldChildWrapper.nextSibling;\n var previousNode = oldChildWrapper.previousSibling;\n var nodes;\n\n var useNative = !this.invalidateShadowRenderer() &&\n !invalidateParent(newChildWrapper);\n\n if (useNative) {\n nodes = collectNodesNative(newChildWrapper);\n } else {\n if (nextNode === newChildWrapper)\n nextNode = newChildWrapper.nextSibling;\n nodes = collectNodes(newChildWrapper, this, previousNode, nextNode);\n }\n\n if (!useNative) {\n if (this.firstChild === oldChildWrapper)\n this.firstChild_ = nodes[0];\n if (this.lastChild === oldChildWrapper)\n this.lastChild_ = nodes[nodes.length - 1];\n\n oldChildWrapper.previousSibling_ = oldChildWrapper.nextSibling_ =\n oldChildWrapper.parentNode_ = undefined;\n\n // replaceChild no matter what the parent is?\n if (oldChildNode.parentNode) {\n originalReplaceChild.call(\n oldChildNode.parentNode,\n unwrapNodesForInsertion(this, nodes),\n oldChildNode);\n }\n } else {\n ensureSameOwnerDocument(this, newChildWrapper);\n clearChildNodes(this);\n originalReplaceChild.call(this.impl, unwrap(newChildWrapper),\n oldChildNode);\n }\n\n enqueueMutation(this, 'childList', {\n addedNodes: nodes,\n removedNodes: createOneElementNodeList(oldChildWrapper),\n nextSibling: nextNode,\n previousSibling: previousNode\n });\n\n nodeWasRemoved(oldChildWrapper);\n nodesWereAdded(nodes, this);\n\n return oldChildWrapper;\n },\n\n /**\n * Called after a node was inserted. Subclasses override this to invalidate\n * the renderer as needed.\n * @private\n */\n nodeIsInserted_: function() {\n for (var child = this.firstChild; child; child = child.nextSibling) {\n child.nodeIsInserted_();\n }\n },\n\n hasChildNodes: function() {\n return this.firstChild !== null;\n },\n\n /** @type {Node} */\n get parentNode() {\n // If the parentNode has not been overridden, use the original parentNode.\n return this.parentNode_ !== undefined ?\n this.parentNode_ : wrap(this.impl.parentNode);\n },\n\n /** @type {Node} */\n get firstChild() {\n return this.firstChild_ !== undefined ?\n this.firstChild_ : wrap(this.impl.firstChild);\n },\n\n /** @type {Node} */\n get lastChild() {\n return this.lastChild_ !== undefined ?\n this.lastChild_ : wrap(this.impl.lastChild);\n },\n\n /** @type {Node} */\n get nextSibling() {\n return this.nextSibling_ !== undefined ?\n this.nextSibling_ : wrap(this.impl.nextSibling);\n },\n\n /** @type {Node} */\n get previousSibling() {\n return this.previousSibling_ !== undefined ?\n this.previousSibling_ : wrap(this.impl.previousSibling);\n },\n\n get parentElement() {\n var p = this.parentNode;\n while (p && p.nodeType !== Node.ELEMENT_NODE) {\n p = p.parentNode;\n }\n return p;\n },\n\n get textContent() {\n // TODO(arv): This should fallback to this.impl.textContent if there\n // are no shadow trees below or above the context node.\n var s = '';\n for (var child = this.firstChild; child; child = child.nextSibling) {\n if (child.nodeType != Node.COMMENT_NODE) {\n s += child.textContent;\n }\n }\n return s;\n },\n set textContent(textContent) {\n var removedNodes = snapshotNodeList(this.childNodes);\n\n if (this.invalidateShadowRenderer()) {\n removeAllChildNodes(this);\n if (textContent !== '') {\n var textNode = this.impl.ownerDocument.createTextNode(textContent);\n this.appendChild(textNode);\n }\n } else {\n clearChildNodes(this);\n this.impl.textContent = textContent;\n }\n\n var addedNodes = snapshotNodeList(this.childNodes);\n\n enqueueMutation(this, 'childList', {\n addedNodes: addedNodes,\n removedNodes: removedNodes\n });\n\n nodesWereRemoved(removedNodes);\n nodesWereAdded(addedNodes, this);\n },\n\n get childNodes() {\n var wrapperList = new NodeList();\n var i = 0;\n for (var child = this.firstChild; child; child = child.nextSibling) {\n wrapperList[i++] = child;\n }\n wrapperList.length = i;\n return wrapperList;\n },\n\n cloneNode: function(deep) {\n return cloneNode(this, deep);\n },\n\n contains: function(child) {\n return contains(this, wrapIfNeeded(child));\n },\n\n compareDocumentPosition: function(otherNode) {\n // This only wraps, it therefore only operates on the composed DOM and not\n // the logical DOM.\n return originalCompareDocumentPosition.call(this.impl,\n unwrapIfNeeded(otherNode));\n },\n\n normalize: function() {\n var nodes = snapshotNodeList(this.childNodes);\n var remNodes = [];\n var s = '';\n var modNode;\n\n for (var i = 0, n; i < nodes.length; i++) {\n n = nodes[i];\n if (n.nodeType === Node.TEXT_NODE) {\n if (!modNode && !n.data.length)\n this.removeNode(n);\n else if (!modNode)\n modNode = n;\n else {\n s += n.data;\n remNodes.push(n);\n }\n } else {\n if (modNode && remNodes.length) {\n modNode.data += s;\n cleanUpNodes(remNodes);\n }\n remNodes = [];\n s = '';\n modNode = null;\n if (n.childNodes.length)\n n.normalize();\n }\n }\n\n // handle case where >1 text nodes are the last children\n if (modNode && remNodes.length) {\n modNode.data += s;\n cleanupNodes(remNodes);\n }\n }\n });\n\n defineWrapGetter(Node, 'ownerDocument');\n\n // We use a DocumentFragment as a base and then delete the properties of\n // DocumentFragment.prototype from the wrapper Node. Since delete makes\n // objects slow in some JS engines we recreate the prototype object.\n registerWrapper(OriginalNode, Node, document.createDocumentFragment());\n delete Node.prototype.querySelector;\n delete Node.prototype.querySelectorAll;\n Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype);\n\n scope.cloneNode = cloneNode;\n scope.nodeWasAdded = nodeWasAdded;\n scope.nodeWasRemoved = nodeWasRemoved;\n scope.nodesWereAdded = nodesWereAdded;\n scope.nodesWereRemoved = nodesWereRemoved;\n scope.snapshotNodeList = snapshotNodeList;\n scope.wrappers.Node = Node;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLCollection = scope.wrappers.HTMLCollection;\n var NodeList = scope.wrappers.NodeList;\n\n function findOne(node, selector) {\n var m, el = node.firstElementChild;\n while (el) {\n if (el.matches(selector))\n return el;\n m = findOne(el, selector);\n if (m)\n return m;\n el = el.nextElementSibling;\n }\n return null;\n }\n\n function matchesSelector(el, selector) {\n return el.matches(selector);\n }\n\n var XHTML_NS = 'http://www.w3.org/1999/xhtml';\n\n function matchesTagName(el, localName, localNameLowerCase) {\n var ln = el.localName;\n return ln === localName ||\n ln === localNameLowerCase && el.namespaceURI === XHTML_NS;\n }\n\n function matchesEveryThing() {\n return true;\n }\n\n function matchesLocalName(el, localName) {\n return el.localName === localName;\n }\n\n function matchesNameSpace(el, ns) {\n return el.namespaceURI === ns;\n }\n\n function matchesLocalNameNS(el, ns, localName) {\n return el.namespaceURI === ns && el.localName === localName;\n }\n\n function findElements(node, result, p, arg0, arg1) {\n var el = node.firstElementChild;\n while (el) {\n if (p(el, arg0, arg1))\n result[result.length++] = el;\n findElements(el, result, p, arg0, arg1);\n el = el.nextElementSibling;\n }\n return result;\n }\n\n // find and findAll will only match Simple Selectors,\n // Structural Pseudo Classes are not guarenteed to be correct\n // http://www.w3.org/TR/css3-selectors/#simple-selectors\n\n var SelectorsInterface = {\n querySelector: function(selector) {\n return findOne(this, selector);\n },\n querySelectorAll: function(selector) {\n return findElements(this, new NodeList(), matchesSelector, selector);\n }\n };\n\n var GetElementsByInterface = {\n getElementsByTagName: function(localName) {\n var result = new HTMLCollection();\n if (localName === '*')\n return findElements(this, result, matchesEveryThing);\n\n return findElements(this, result,\n matchesTagName,\n localName,\n localName.toLowerCase());\n },\n\n getElementsByClassName: function(className) {\n // TODO(arv): Check className?\n return this.querySelectorAll('.' + className);\n },\n\n getElementsByTagNameNS: function(ns, localName) {\n var result = new HTMLCollection();\n\n if (ns === '') {\n ns = null;\n } else if (ns === '*') {\n if (localName === '*')\n return findElements(this, result, matchesEveryThing);\n return findElements(this, result, matchesLocalName, localName);\n }\n\n if (localName === '*')\n return findElements(this, result, matchesNameSpace, ns);\n\n return findElements(this, result, matchesLocalNameNS, ns, localName);\n }\n };\n\n scope.GetElementsByInterface = GetElementsByInterface;\n scope.SelectorsInterface = SelectorsInterface;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var NodeList = scope.wrappers.NodeList;\n\n function forwardElement(node) {\n while (node && node.nodeType !== Node.ELEMENT_NODE) {\n node = node.nextSibling;\n }\n return node;\n }\n\n function backwardsElement(node) {\n while (node && node.nodeType !== Node.ELEMENT_NODE) {\n node = node.previousSibling;\n }\n return node;\n }\n\n var ParentNodeInterface = {\n get firstElementChild() {\n return forwardElement(this.firstChild);\n },\n\n get lastElementChild() {\n return backwardsElement(this.lastChild);\n },\n\n get childElementCount() {\n var count = 0;\n for (var child = this.firstElementChild;\n child;\n child = child.nextElementSibling) {\n count++;\n }\n return count;\n },\n\n get children() {\n var wrapperList = new NodeList();\n var i = 0;\n for (var child = this.firstElementChild;\n child;\n child = child.nextElementSibling) {\n wrapperList[i++] = child;\n }\n wrapperList.length = i;\n return wrapperList;\n },\n\n remove: function() {\n var p = this.parentNode;\n if (p)\n p.removeChild(this);\n }\n };\n\n var ChildNodeInterface = {\n get nextElementSibling() {\n return forwardElement(this.nextSibling);\n },\n\n get previousElementSibling() {\n return backwardsElement(this.previousSibling);\n }\n };\n\n scope.ChildNodeInterface = ChildNodeInterface;\n scope.ParentNodeInterface = ParentNodeInterface;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var ChildNodeInterface = scope.ChildNodeInterface;\n var Node = scope.wrappers.Node;\n var enqueueMutation = scope.enqueueMutation;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n\n var OriginalCharacterData = window.CharacterData;\n\n function CharacterData(node) {\n Node.call(this, node);\n }\n CharacterData.prototype = Object.create(Node.prototype);\n mixin(CharacterData.prototype, {\n get textContent() {\n return this.data;\n },\n set textContent(value) {\n this.data = value;\n },\n get data() {\n return this.impl.data;\n },\n set data(value) {\n var oldValue = this.impl.data;\n enqueueMutation(this, 'characterData', {\n oldValue: oldValue\n });\n this.impl.data = value;\n }\n });\n\n mixin(CharacterData.prototype, ChildNodeInterface);\n\n registerWrapper(OriginalCharacterData, CharacterData,\n document.createTextNode(''));\n\n scope.wrappers.CharacterData = CharacterData;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var CharacterData = scope.wrappers.CharacterData;\n var enqueueMutation = scope.enqueueMutation;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n\n function toUInt32(x) {\n return x >>> 0;\n }\n\n var OriginalText = window.Text;\n\n function Text(node) {\n CharacterData.call(this, node);\n }\n Text.prototype = Object.create(CharacterData.prototype);\n mixin(Text.prototype, {\n splitText: function(offset) {\n offset = toUInt32(offset);\n var s = this.data;\n if (offset > s.length)\n throw new Error('IndexSizeError');\n var head = s.slice(0, offset);\n var tail = s.slice(offset);\n this.data = head;\n var newTextNode = this.ownerDocument.createTextNode(tail);\n if (this.parentNode)\n this.parentNode.insertBefore(newTextNode, this.nextSibling);\n return newTextNode;\n }\n });\n\n registerWrapper(OriginalText, Text, document.createTextNode(''));\n\n scope.wrappers.Text = Text;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var ChildNodeInterface = scope.ChildNodeInterface;\n var GetElementsByInterface = scope.GetElementsByInterface;\n var Node = scope.wrappers.Node;\n var ParentNodeInterface = scope.ParentNodeInterface;\n var SelectorsInterface = scope.SelectorsInterface;\n var addWrapNodeListMethod = scope.addWrapNodeListMethod;\n var enqueueMutation = scope.enqueueMutation;\n var mixin = scope.mixin;\n var oneOf = scope.oneOf;\n var registerWrapper = scope.registerWrapper;\n var wrappers = scope.wrappers;\n\n var OriginalElement = window.Element;\n\n var matchesNames = [\n 'matches', // needs to come first.\n 'mozMatchesSelector',\n 'msMatchesSelector',\n 'webkitMatchesSelector',\n ].filter(function(name) {\n return OriginalElement.prototype[name];\n });\n\n var matchesName = matchesNames[0];\n\n var originalMatches = OriginalElement.prototype[matchesName];\n\n function invalidateRendererBasedOnAttribute(element, name) {\n // Only invalidate if parent node is a shadow host.\n var p = element.parentNode;\n if (!p || !p.shadowRoot)\n return;\n\n var renderer = scope.getRendererForHost(p);\n if (renderer.dependsOnAttribute(name))\n renderer.invalidate();\n }\n\n function enqueAttributeChange(element, name, oldValue) {\n // This is not fully spec compliant. We should use localName (which might\n // have a different case than name) and the namespace (which requires us\n // to get the Attr object).\n enqueueMutation(element, 'attributes', {\n name: name,\n namespace: null,\n oldValue: oldValue\n });\n }\n\n function Element(node) {\n Node.call(this, node);\n }\n Element.prototype = Object.create(Node.prototype);\n mixin(Element.prototype, {\n createShadowRoot: function() {\n var newShadowRoot = new wrappers.ShadowRoot(this);\n this.impl.polymerShadowRoot_ = newShadowRoot;\n\n var renderer = scope.getRendererForHost(this);\n renderer.invalidate();\n\n return newShadowRoot;\n },\n\n get shadowRoot() {\n return this.impl.polymerShadowRoot_ || null;\n },\n\n setAttribute: function(name, value) {\n var oldValue = this.impl.getAttribute(name);\n this.impl.setAttribute(name, value);\n enqueAttributeChange(this, name, oldValue);\n invalidateRendererBasedOnAttribute(this, name);\n },\n\n removeAttribute: function(name) {\n var oldValue = this.impl.getAttribute(name);\n this.impl.removeAttribute(name);\n enqueAttributeChange(this, name, oldValue);\n invalidateRendererBasedOnAttribute(this, name);\n },\n\n matches: function(selector) {\n return originalMatches.call(this.impl, selector);\n }\n });\n\n matchesNames.forEach(function(name) {\n if (name !== 'matches') {\n Element.prototype[name] = function(selector) {\n return this.matches(selector);\n };\n }\n });\n\n if (OriginalElement.prototype.webkitCreateShadowRoot) {\n Element.prototype.webkitCreateShadowRoot =\n Element.prototype.createShadowRoot;\n }\n\n /**\n * Useful for generating the accessor pair for a property that reflects an\n * attribute.\n */\n function setterDirtiesAttribute(prototype, propertyName, opt_attrName) {\n var attrName = opt_attrName || propertyName;\n Object.defineProperty(prototype, propertyName, {\n get: function() {\n return this.impl[propertyName];\n },\n set: function(v) {\n this.impl[propertyName] = v;\n invalidateRendererBasedOnAttribute(this, attrName);\n },\n configurable: true,\n enumerable: true\n });\n }\n\n setterDirtiesAttribute(Element.prototype, 'id');\n setterDirtiesAttribute(Element.prototype, 'className', 'class');\n\n mixin(Element.prototype, ChildNodeInterface);\n mixin(Element.prototype, GetElementsByInterface);\n mixin(Element.prototype, ParentNodeInterface);\n mixin(Element.prototype, SelectorsInterface);\n\n registerWrapper(OriginalElement, Element,\n document.createElementNS(null, 'x'));\n\n // TODO(arv): Export setterDirtiesAttribute and apply it to more bindings\n // that reflect attributes.\n scope.matchesNames = matchesNames;\n scope.wrappers.Element = Element;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var Element = scope.wrappers.Element;\n var defineGetter = scope.defineGetter;\n var enqueueMutation = scope.enqueueMutation;\n var mixin = scope.mixin;\n var nodesWereAdded = scope.nodesWereAdded;\n var nodesWereRemoved = scope.nodesWereRemoved;\n var registerWrapper = scope.registerWrapper;\n var snapshotNodeList = scope.snapshotNodeList;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n var wrappers = scope.wrappers;\n\n /////////////////////////////////////////////////////////////////////////////\n // innerHTML and outerHTML\n\n // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString\n var escapeAttrRegExp = /[&\\u00A0\"]/g;\n var escapeDataRegExp = /[&\\u00A0<>]/g;\n\n function escapeReplace(c) {\n switch (c) {\n case '&':\n return '&';\n case '<':\n return '<';\n case '>':\n return '>';\n case '\"':\n return '"'\n case '\\u00A0':\n return ' ';\n }\n }\n\n function escapeAttr(s) {\n return s.replace(escapeAttrRegExp, escapeReplace);\n }\n\n function escapeData(s) {\n return s.replace(escapeDataRegExp, escapeReplace);\n }\n\n function makeSet(arr) {\n var set = {};\n for (var i = 0; i < arr.length; i++) {\n set[arr[i]] = true;\n }\n return set;\n }\n\n // http://www.whatwg.org/specs/web-apps/current-work/#void-elements\n var voidElements = makeSet([\n 'area',\n 'base',\n 'br',\n 'col',\n 'command',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'keygen',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr'\n ]);\n\n var plaintextParents = makeSet([\n 'style',\n 'script',\n 'xmp',\n 'iframe',\n 'noembed',\n 'noframes',\n 'plaintext',\n 'noscript'\n ]);\n\n function getOuterHTML(node, parentNode) {\n switch (node.nodeType) {\n case Node.ELEMENT_NODE:\n var tagName = node.tagName.toLowerCase();\n var s = '<' + tagName;\n var attrs = node.attributes;\n for (var i = 0, attr; attr = attrs[i]; i++) {\n s += ' ' + attr.name + '=\"' + escapeAttr(attr.value) + '\"';\n }\n s += '>';\n if (voidElements[tagName])\n return s;\n\n return s + getInnerHTML(node) + '';\n\n case Node.TEXT_NODE:\n var data = node.data;\n if (parentNode && plaintextParents[parentNode.localName])\n return data;\n return escapeData(data);\n\n case Node.COMMENT_NODE:\n return '';\n\n default:\n console.error(node);\n throw new Error('not implemented');\n }\n }\n\n function getInnerHTML(node) {\n if (node instanceof wrappers.HTMLTemplateElement)\n node = node.content;\n\n var s = '';\n for (var child = node.firstChild; child; child = child.nextSibling) {\n s += getOuterHTML(child, node);\n }\n return s;\n }\n\n function setInnerHTML(node, value, opt_tagName) {\n var tagName = opt_tagName || 'div';\n node.textContent = '';\n var tempElement = unwrap(node.ownerDocument.createElement(tagName));\n tempElement.innerHTML = value;\n var firstChild;\n while (firstChild = tempElement.firstChild) {\n node.appendChild(wrap(firstChild));\n }\n }\n\n // IE11 does not have MSIE in the user agent string.\n var oldIe = /MSIE/.test(navigator.userAgent);\n\n var OriginalHTMLElement = window.HTMLElement;\n var OriginalHTMLTemplateElement = window.HTMLTemplateElement;\n\n function HTMLElement(node) {\n Element.call(this, node);\n }\n HTMLElement.prototype = Object.create(Element.prototype);\n mixin(HTMLElement.prototype, {\n get innerHTML() {\n return getInnerHTML(this);\n },\n set innerHTML(value) {\n // IE9 does not handle set innerHTML correctly on plaintextParents. It\n // creates element children. For example\n //\n // scriptElement.innerHTML = 'test'\n //\n // Creates a single HTMLAnchorElement child.\n if (oldIe && plaintextParents[this.localName]) {\n this.textContent = value;\n return;\n }\n\n var removedNodes = snapshotNodeList(this.childNodes);\n\n if (this.invalidateShadowRenderer()) {\n if (this instanceof wrappers.HTMLTemplateElement)\n setInnerHTML(this.content, value);\n else\n setInnerHTML(this, value, this.tagName);\n\n // If we have a non native template element we need to handle this\n // manually since setting impl.innerHTML would add the html as direct\n // children and not be moved over to the content fragment.\n } else if (!OriginalHTMLTemplateElement &&\n this instanceof wrappers.HTMLTemplateElement) {\n setInnerHTML(this.content, value);\n } else {\n this.impl.innerHTML = value;\n }\n\n var addedNodes = snapshotNodeList(this.childNodes);\n\n enqueueMutation(this, 'childList', {\n addedNodes: addedNodes,\n removedNodes: removedNodes\n });\n\n nodesWereRemoved(removedNodes);\n nodesWereAdded(addedNodes, this);\n },\n\n get outerHTML() {\n return getOuterHTML(this, this.parentNode);\n },\n set outerHTML(value) {\n var p = this.parentNode;\n if (p) {\n p.invalidateShadowRenderer();\n var df = frag(p, value);\n p.replaceChild(df, this);\n }\n },\n\n insertAdjacentHTML: function(position, text) {\n var contextElement, refNode;\n switch (String(position).toLowerCase()) {\n case 'beforebegin':\n contextElement = this.parentNode;\n refNode = this;\n break;\n case 'afterend':\n contextElement = this.parentNode;\n refNode = this.nextSibling;\n break;\n case 'afterbegin':\n contextElement = this;\n refNode = this.firstChild;\n break;\n case 'beforeend':\n contextElement = this;\n refNode = null;\n break;\n default:\n return;\n }\n\n var df = frag(contextElement, text);\n contextElement.insertBefore(df, refNode);\n }\n });\n\n function frag(contextElement, html) {\n // TODO(arv): This does not work with SVG and other non HTML elements.\n var p = unwrap(contextElement.cloneNode(false));\n p.innerHTML = html;\n var df = unwrap(document.createDocumentFragment());\n var c;\n while (c = p.firstChild) {\n df.appendChild(c);\n }\n return wrap(df);\n }\n\n function getter(name) {\n return function() {\n scope.renderAllPending();\n return this.impl[name];\n };\n }\n\n function getterRequiresRendering(name) {\n defineGetter(HTMLElement, name, getter(name));\n }\n\n [\n 'clientHeight',\n 'clientLeft',\n 'clientTop',\n 'clientWidth',\n 'offsetHeight',\n 'offsetLeft',\n 'offsetTop',\n 'offsetWidth',\n 'scrollHeight',\n 'scrollWidth',\n ].forEach(getterRequiresRendering);\n\n function getterAndSetterRequiresRendering(name) {\n Object.defineProperty(HTMLElement.prototype, name, {\n get: getter(name),\n set: function(v) {\n scope.renderAllPending();\n this.impl[name] = v;\n },\n configurable: true,\n enumerable: true\n });\n }\n\n [\n 'scrollLeft',\n 'scrollTop',\n ].forEach(getterAndSetterRequiresRendering);\n\n function methodRequiresRendering(name) {\n Object.defineProperty(HTMLElement.prototype, name, {\n value: function() {\n scope.renderAllPending();\n return this.impl[name].apply(this.impl, arguments);\n },\n configurable: true,\n enumerable: true\n });\n }\n\n [\n 'getBoundingClientRect',\n 'getClientRects',\n 'scrollIntoView'\n ].forEach(methodRequiresRendering);\n\n // HTMLElement is abstract so we use a subclass that has no members.\n registerWrapper(OriginalHTMLElement, HTMLElement,\n document.createElement('b'));\n\n scope.wrappers.HTMLElement = HTMLElement;\n\n // TODO: Find a better way to share these two with WrapperShadowRoot.\n scope.getInnerHTML = getInnerHTML;\n scope.setInnerHTML = setInnerHTML\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var wrap = scope.wrap;\n\n var OriginalHTMLCanvasElement = window.HTMLCanvasElement;\n\n function HTMLCanvasElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLCanvasElement.prototype = Object.create(HTMLElement.prototype);\n\n mixin(HTMLCanvasElement.prototype, {\n getContext: function() {\n var context = this.impl.getContext.apply(this.impl, arguments);\n return context && wrap(context);\n }\n });\n\n registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement,\n document.createElement('canvas'));\n\n scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n\n var OriginalHTMLContentElement = window.HTMLContentElement;\n\n function HTMLContentElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLContentElement.prototype = Object.create(HTMLElement.prototype);\n mixin(HTMLContentElement.prototype, {\n get select() {\n return this.getAttribute('select');\n },\n set select(value) {\n this.setAttribute('select', value);\n },\n\n setAttribute: function(n, v) {\n HTMLElement.prototype.setAttribute.call(this, n, v);\n if (String(n).toLowerCase() === 'select')\n this.invalidateShadowRenderer(true);\n }\n\n // getDistributedNodes is added in ShadowRenderer\n\n // TODO: attribute boolean resetStyleInheritance;\n });\n\n if (OriginalHTMLContentElement)\n registerWrapper(OriginalHTMLContentElement, HTMLContentElement);\n\n scope.wrappers.HTMLContentElement = HTMLContentElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var rewrap = scope.rewrap;\n\n var OriginalHTMLImageElement = window.HTMLImageElement;\n\n function HTMLImageElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLImageElement.prototype = Object.create(HTMLElement.prototype);\n\n registerWrapper(OriginalHTMLImageElement, HTMLImageElement,\n document.createElement('img'));\n\n function Image(width, height) {\n if (!(this instanceof Image)) {\n throw new TypeError(\n 'DOM object constructor cannot be called as a function.');\n }\n\n var node = unwrap(document.createElement('img'));\n HTMLElement.call(this, node);\n rewrap(node, this);\n\n if (width !== undefined)\n node.width = width;\n if (height !== undefined)\n node.height = height;\n }\n\n Image.prototype = HTMLImageElement.prototype;\n\n scope.wrappers.HTMLImageElement = HTMLImageElement;\n scope.wrappers.Image = Image;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n\n var OriginalHTMLShadowElement = window.HTMLShadowElement;\n\n function HTMLShadowElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLShadowElement.prototype = Object.create(HTMLElement.prototype);\n mixin(HTMLShadowElement.prototype, {\n // TODO: attribute boolean resetStyleInheritance;\n });\n\n if (OriginalHTMLShadowElement)\n registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement);\n\n scope.wrappers.HTMLShadowElement = HTMLShadowElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n\n var contentTable = new WeakMap();\n var templateContentsOwnerTable = new WeakMap();\n\n // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner\n function getTemplateContentsOwner(doc) {\n if (!doc.defaultView)\n return doc;\n var d = templateContentsOwnerTable.get(doc);\n if (!d) {\n // TODO(arv): This should either be a Document or HTMLDocument depending\n // on doc.\n d = doc.implementation.createHTMLDocument('');\n while (d.lastChild) {\n d.removeChild(d.lastChild);\n }\n templateContentsOwnerTable.set(doc, d);\n }\n return d;\n }\n\n function extractContent(templateElement) {\n // templateElement is not a wrapper here.\n var doc = getTemplateContentsOwner(templateElement.ownerDocument);\n var df = unwrap(doc.createDocumentFragment());\n var child;\n while (child = templateElement.firstChild) {\n df.appendChild(child);\n }\n return df;\n }\n\n var OriginalHTMLTemplateElement = window.HTMLTemplateElement;\n\n function HTMLTemplateElement(node) {\n HTMLElement.call(this, node);\n if (!OriginalHTMLTemplateElement) {\n var content = extractContent(node);\n contentTable.set(this, wrap(content));\n }\n }\n HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype);\n\n mixin(HTMLTemplateElement.prototype, {\n get content() {\n if (OriginalHTMLTemplateElement)\n return wrap(this.impl.content);\n return contentTable.get(this);\n },\n\n // TODO(arv): cloneNode needs to clone content.\n\n });\n\n if (OriginalHTMLTemplateElement)\n registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement);\n\n scope.wrappers.HTMLTemplateElement = HTMLTemplateElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var registerWrapper = scope.registerWrapper;\n\n var OriginalHTMLMediaElement = window.HTMLMediaElement;\n\n function HTMLMediaElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLMediaElement.prototype = Object.create(HTMLElement.prototype);\n\n registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement,\n document.createElement('audio'));\n\n scope.wrappers.HTMLMediaElement = HTMLMediaElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLMediaElement = scope.wrappers.HTMLMediaElement;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var rewrap = scope.rewrap;\n\n var OriginalHTMLAudioElement = window.HTMLAudioElement;\n\n function HTMLAudioElement(node) {\n HTMLMediaElement.call(this, node);\n }\n HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype);\n\n registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement,\n document.createElement('audio'));\n\n function Audio(src) {\n if (!(this instanceof Audio)) {\n throw new TypeError(\n 'DOM object constructor cannot be called as a function.');\n }\n\n var node = unwrap(document.createElement('audio'));\n HTMLMediaElement.call(this, node);\n rewrap(node, this);\n\n node.setAttribute('preload', 'auto');\n if (src !== undefined)\n node.setAttribute('src', src);\n }\n\n Audio.prototype = HTMLAudioElement.prototype;\n\n scope.wrappers.HTMLAudioElement = HTMLAudioElement;\n scope.wrappers.Audio = Audio;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var rewrap = scope.rewrap;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n\n var OriginalHTMLOptionElement = window.HTMLOptionElement;\n\n function trimText(s) {\n return s.replace(/\\s+/g, ' ').trim();\n }\n\n function HTMLOptionElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLOptionElement.prototype = Object.create(HTMLElement.prototype);\n mixin(HTMLOptionElement.prototype, {\n get text() {\n return trimText(this.textContent);\n },\n set text(value) {\n this.textContent = trimText(String(value));\n },\n get form() {\n return wrap(unwrap(this).form);\n }\n });\n\n registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement,\n document.createElement('option'));\n\n function Option(text, value, defaultSelected, selected) {\n if (!(this instanceof Option)) {\n throw new TypeError(\n 'DOM object constructor cannot be called as a function.');\n }\n\n var node = unwrap(document.createElement('option'));\n HTMLElement.call(this, node);\n rewrap(node, this);\n\n if (text !== undefined)\n node.text = text;\n if (value !== undefined)\n node.setAttribute('value', value);\n if (defaultSelected === true)\n node.setAttribute('selected', '');\n node.selected = selected === true;\n }\n\n Option.prototype = HTMLOptionElement.prototype;\n\n scope.wrappers.HTMLOptionElement = HTMLOptionElement;\n scope.wrappers.Option = Option;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n\n var OriginalHTMLSelectElement = window.HTMLSelectElement;\n\n function HTMLSelectElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLSelectElement.prototype = Object.create(HTMLElement.prototype);\n mixin(HTMLSelectElement.prototype, {\n add: function(element, before) {\n if (typeof before === 'object') // also includes null\n before = unwrap(before);\n unwrap(this).add(unwrap(element), before);\n },\n\n remove: function(indexOrNode) {\n // Spec only allows index but implementations allow index or node.\n // remove() is also allowed which is same as remove(undefined)\n if (indexOrNode === undefined) {\n HTMLElement.prototype.remove.call(this);\n return;\n }\n\n if (typeof indexOrNode === 'object')\n indexOrNode = unwrap(indexOrNode);\n\n unwrap(this).remove(indexOrNode);\n },\n\n get form() {\n return wrap(unwrap(this).form);\n }\n });\n\n registerWrapper(OriginalHTMLSelectElement, HTMLSelectElement,\n document.createElement('select'));\n\n scope.wrappers.HTMLSelectElement = HTMLSelectElement;\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n var wrapHTMLCollection = scope.wrapHTMLCollection;\n\n var OriginalHTMLTableElement = window.HTMLTableElement;\n\n function HTMLTableElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLTableElement.prototype = Object.create(HTMLElement.prototype);\n mixin(HTMLTableElement.prototype, {\n get caption() {\n return wrap(unwrap(this).caption);\n },\n createCaption: function() {\n return wrap(unwrap(this).createCaption());\n },\n\n get tHead() {\n return wrap(unwrap(this).tHead);\n },\n createTHead: function() {\n return wrap(unwrap(this).createTHead());\n },\n\n createTFoot: function() {\n return wrap(unwrap(this).createTFoot());\n },\n get tFoot() {\n return wrap(unwrap(this).tFoot);\n },\n\n get tBodies() {\n return wrapHTMLCollection(unwrap(this).tBodies);\n },\n createTBody: function() {\n return wrap(unwrap(this).createTBody());\n },\n\n get rows() {\n return wrapHTMLCollection(unwrap(this).rows);\n },\n insertRow: function(index) {\n return wrap(unwrap(this).insertRow(index));\n }\n });\n\n registerWrapper(OriginalHTMLTableElement, HTMLTableElement,\n document.createElement('table'));\n\n scope.wrappers.HTMLTableElement = HTMLTableElement;\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var wrapHTMLCollection = scope.wrapHTMLCollection;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n\n var OriginalHTMLTableSectionElement = window.HTMLTableSectionElement;\n\n function HTMLTableSectionElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLTableSectionElement.prototype = Object.create(HTMLElement.prototype);\n mixin(HTMLTableSectionElement.prototype, {\n get rows() {\n return wrapHTMLCollection(unwrap(this).rows);\n },\n insertRow: function(index) {\n return wrap(unwrap(this).insertRow(index));\n }\n });\n\n registerWrapper(OriginalHTMLTableSectionElement, HTMLTableSectionElement,\n document.createElement('thead'));\n\n scope.wrappers.HTMLTableSectionElement = HTMLTableSectionElement;\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var wrapHTMLCollection = scope.wrapHTMLCollection;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n\n var OriginalHTMLTableRowElement = window.HTMLTableRowElement;\n\n function HTMLTableRowElement(node) {\n HTMLElement.call(this, node);\n }\n HTMLTableRowElement.prototype = Object.create(HTMLElement.prototype);\n mixin(HTMLTableRowElement.prototype, {\n get cells() {\n return wrapHTMLCollection(unwrap(this).cells);\n },\n\n insertCell: function(index) {\n return wrap(unwrap(this).insertCell(index));\n }\n });\n\n registerWrapper(OriginalHTMLTableRowElement, HTMLTableRowElement,\n document.createElement('tr'));\n\n scope.wrappers.HTMLTableRowElement = HTMLTableRowElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLContentElement = scope.wrappers.HTMLContentElement;\n var HTMLElement = scope.wrappers.HTMLElement;\n var HTMLShadowElement = scope.wrappers.HTMLShadowElement;\n var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n\n var OriginalHTMLUnknownElement = window.HTMLUnknownElement;\n\n function HTMLUnknownElement(node) {\n switch (node.localName) {\n case 'content':\n return new HTMLContentElement(node);\n case 'shadow':\n return new HTMLShadowElement(node);\n case 'template':\n return new HTMLTemplateElement(node);\n }\n HTMLElement.call(this, node);\n }\n HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype);\n registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement);\n scope.wrappers.HTMLUnknownElement = HTMLUnknownElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var registerObject = scope.registerObject;\n\n var SVG_NS = 'http://www.w3.org/2000/svg';\n var svgTitleElement = document.createElementNS(SVG_NS, 'title');\n var SVGTitleElement = registerObject(svgTitleElement);\n var SVGElement = Object.getPrototypeOf(SVGTitleElement.prototype).constructor;\n\n scope.wrappers.SVGElement = SVGElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n\n var OriginalSVGUseElement = window.SVGUseElement;\n\n // IE uses SVGElement as parent interface, SVG2 (Blink & Gecko) uses\n // SVGGraphicsElement. Use the element to get the right prototype.\n\n var SVG_NS = 'http://www.w3.org/2000/svg';\n var gWrapper = wrap(document.createElementNS(SVG_NS, 'g'));\n var useElement = document.createElementNS(SVG_NS, 'use');\n var SVGGElement = gWrapper.constructor;\n var parentInterfacePrototype = Object.getPrototypeOf(SVGGElement.prototype);\n var parentInterface = parentInterfacePrototype.constructor;\n\n function SVGUseElement(impl) {\n parentInterface.call(this, impl);\n }\n\n SVGUseElement.prototype = Object.create(parentInterfacePrototype);\n\n // Firefox does not expose instanceRoot.\n if ('instanceRoot' in useElement) {\n mixin(SVGUseElement.prototype, {\n get instanceRoot() {\n return wrap(unwrap(this).instanceRoot);\n },\n get animatedInstanceRoot() {\n return wrap(unwrap(this).animatedInstanceRoot);\n },\n });\n }\n\n registerWrapper(OriginalSVGUseElement, SVGUseElement, useElement);\n\n scope.wrappers.SVGUseElement = SVGUseElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var EventTarget = scope.wrappers.EventTarget;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var wrap = scope.wrap;\n\n var OriginalSVGElementInstance = window.SVGElementInstance;\n if (!OriginalSVGElementInstance)\n return;\n\n function SVGElementInstance(impl) {\n EventTarget.call(this, impl);\n }\n\n SVGElementInstance.prototype = Object.create(EventTarget.prototype);\n mixin(SVGElementInstance.prototype, {\n /** @type {SVGElement} */\n get correspondingElement() {\n return wrap(this.impl.correspondingElement);\n },\n\n /** @type {SVGUseElement} */\n get correspondingUseElement() {\n return wrap(this.impl.correspondingUseElement);\n },\n\n /** @type {SVGElementInstance} */\n get parentNode() {\n return wrap(this.impl.parentNode);\n },\n\n /** @type {SVGElementInstanceList} */\n get childNodes() {\n throw new Error('Not implemented');\n },\n\n /** @type {SVGElementInstance} */\n get firstChild() {\n return wrap(this.impl.firstChild);\n },\n\n /** @type {SVGElementInstance} */\n get lastChild() {\n return wrap(this.impl.lastChild);\n },\n\n /** @type {SVGElementInstance} */\n get previousSibling() {\n return wrap(this.impl.previousSibling);\n },\n\n /** @type {SVGElementInstance} */\n get nextSibling() {\n return wrap(this.impl.nextSibling);\n }\n });\n\n registerWrapper(OriginalSVGElementInstance, SVGElementInstance);\n\n scope.wrappers.SVGElementInstance = SVGElementInstance;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var unwrapIfNeeded = scope.unwrapIfNeeded;\n var wrap = scope.wrap;\n\n var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;\n\n function CanvasRenderingContext2D(impl) {\n this.impl = impl;\n }\n\n mixin(CanvasRenderingContext2D.prototype, {\n get canvas() {\n return wrap(this.impl.canvas);\n },\n\n drawImage: function() {\n arguments[0] = unwrapIfNeeded(arguments[0]);\n this.impl.drawImage.apply(this.impl, arguments);\n },\n\n createPattern: function() {\n arguments[0] = unwrap(arguments[0]);\n return this.impl.createPattern.apply(this.impl, arguments);\n }\n });\n\n registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D,\n document.createElement('canvas').getContext('2d'));\n\n scope.wrappers.CanvasRenderingContext2D = CanvasRenderingContext2D;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var unwrapIfNeeded = scope.unwrapIfNeeded;\n var wrap = scope.wrap;\n\n var OriginalWebGLRenderingContext = window.WebGLRenderingContext;\n\n // IE10 does not have WebGL.\n if (!OriginalWebGLRenderingContext)\n return;\n\n function WebGLRenderingContext(impl) {\n this.impl = impl;\n }\n\n mixin(WebGLRenderingContext.prototype, {\n get canvas() {\n return wrap(this.impl.canvas);\n },\n\n texImage2D: function() {\n arguments[5] = unwrapIfNeeded(arguments[5]);\n this.impl.texImage2D.apply(this.impl, arguments);\n },\n\n texSubImage2D: function() {\n arguments[6] = unwrapIfNeeded(arguments[6]);\n this.impl.texSubImage2D.apply(this.impl, arguments);\n }\n });\n\n // Blink/WebKit has broken DOM bindings. Usually we would create an instance\n // of the object and pass it into registerWrapper as a \"blueprint\" but\n // creating WebGL contexts is expensive and might fail so we use a dummy\n // object with dummy instance properties for these broken browsers.\n var instanceProperties = /WebKit/.test(navigator.userAgent) ?\n {drawingBufferHeight: null, drawingBufferWidth: null} : {};\n\n registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext,\n instanceProperties);\n\n scope.wrappers.WebGLRenderingContext = WebGLRenderingContext;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var unwrapIfNeeded = scope.unwrapIfNeeded;\n var wrap = scope.wrap;\n\n var OriginalRange = window.Range;\n\n function Range(impl) {\n this.impl = impl;\n }\n Range.prototype = {\n get startContainer() {\n return wrap(this.impl.startContainer);\n },\n get endContainer() {\n return wrap(this.impl.endContainer);\n },\n get commonAncestorContainer() {\n return wrap(this.impl.commonAncestorContainer);\n },\n setStart: function(refNode,offset) {\n this.impl.setStart(unwrapIfNeeded(refNode), offset);\n },\n setEnd: function(refNode,offset) {\n this.impl.setEnd(unwrapIfNeeded(refNode), offset);\n },\n setStartBefore: function(refNode) {\n this.impl.setStartBefore(unwrapIfNeeded(refNode));\n },\n setStartAfter: function(refNode) {\n this.impl.setStartAfter(unwrapIfNeeded(refNode));\n },\n setEndBefore: function(refNode) {\n this.impl.setEndBefore(unwrapIfNeeded(refNode));\n },\n setEndAfter: function(refNode) {\n this.impl.setEndAfter(unwrapIfNeeded(refNode));\n },\n selectNode: function(refNode) {\n this.impl.selectNode(unwrapIfNeeded(refNode));\n },\n selectNodeContents: function(refNode) {\n this.impl.selectNodeContents(unwrapIfNeeded(refNode));\n },\n compareBoundaryPoints: function(how, sourceRange) {\n return this.impl.compareBoundaryPoints(how, unwrap(sourceRange));\n },\n extractContents: function() {\n return wrap(this.impl.extractContents());\n },\n cloneContents: function() {\n return wrap(this.impl.cloneContents());\n },\n insertNode: function(node) {\n this.impl.insertNode(unwrapIfNeeded(node));\n },\n surroundContents: function(newParent) {\n this.impl.surroundContents(unwrapIfNeeded(newParent));\n },\n cloneRange: function() {\n return wrap(this.impl.cloneRange());\n },\n isPointInRange: function(node, offset) {\n return this.impl.isPointInRange(unwrapIfNeeded(node), offset);\n },\n comparePoint: function(node, offset) {\n return this.impl.comparePoint(unwrapIfNeeded(node), offset);\n },\n intersectsNode: function(node) {\n return this.impl.intersectsNode(unwrapIfNeeded(node));\n },\n toString: function() {\n return this.impl.toString();\n }\n };\n\n // IE9 does not have createContextualFragment.\n if (OriginalRange.prototype.createContextualFragment) {\n Range.prototype.createContextualFragment = function(html) {\n return wrap(this.impl.createContextualFragment(html));\n };\n }\n\n registerWrapper(window.Range, Range, document.createRange());\n\n scope.wrappers.Range = Range;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var GetElementsByInterface = scope.GetElementsByInterface;\n var ParentNodeInterface = scope.ParentNodeInterface;\n var SelectorsInterface = scope.SelectorsInterface;\n var mixin = scope.mixin;\n var registerObject = scope.registerObject;\n\n var DocumentFragment = registerObject(document.createDocumentFragment());\n mixin(DocumentFragment.prototype, ParentNodeInterface);\n mixin(DocumentFragment.prototype, SelectorsInterface);\n mixin(DocumentFragment.prototype, GetElementsByInterface);\n\n var Comment = registerObject(document.createComment(''));\n\n scope.wrappers.Comment = Comment;\n scope.wrappers.DocumentFragment = DocumentFragment;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var DocumentFragment = scope.wrappers.DocumentFragment;\n var TreeScope = scope.TreeScope;\n var elementFromPoint = scope.elementFromPoint;\n var getInnerHTML = scope.getInnerHTML;\n var getTreeScope = scope.getTreeScope;\n var mixin = scope.mixin;\n var rewrap = scope.rewrap;\n var setInnerHTML = scope.setInnerHTML;\n var unwrap = scope.unwrap;\n\n var shadowHostTable = new WeakMap();\n var nextOlderShadowTreeTable = new WeakMap();\n\n var spaceCharRe = /[ \\t\\n\\r\\f]/;\n\n function ShadowRoot(hostWrapper) {\n var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment());\n DocumentFragment.call(this, node);\n\n // createDocumentFragment associates the node with a wrapper\n // DocumentFragment instance. Override that.\n rewrap(node, this);\n\n this.treeScope_ = new TreeScope(this, getTreeScope(hostWrapper));\n\n var oldShadowRoot = hostWrapper.shadowRoot;\n nextOlderShadowTreeTable.set(this, oldShadowRoot);\n\n shadowHostTable.set(this, hostWrapper);\n }\n ShadowRoot.prototype = Object.create(DocumentFragment.prototype);\n mixin(ShadowRoot.prototype, {\n get innerHTML() {\n return getInnerHTML(this);\n },\n set innerHTML(value) {\n setInnerHTML(this, value);\n this.invalidateShadowRenderer();\n },\n\n get olderShadowRoot() {\n return nextOlderShadowTreeTable.get(this) || null;\n },\n\n get host() {\n return shadowHostTable.get(this) || null;\n },\n\n invalidateShadowRenderer: function() {\n return shadowHostTable.get(this).invalidateShadowRenderer();\n },\n\n elementFromPoint: function(x, y) {\n return elementFromPoint(this, this.ownerDocument, x, y);\n },\n\n getElementById: function(id) {\n if (spaceCharRe.test(id))\n return null;\n return this.querySelector('[id=\"' + id + '\"]');\n }\n });\n\n scope.wrappers.ShadowRoot = ShadowRoot;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var Element = scope.wrappers.Element;\n var HTMLContentElement = scope.wrappers.HTMLContentElement;\n var HTMLShadowElement = scope.wrappers.HTMLShadowElement;\n var Node = scope.wrappers.Node;\n var ShadowRoot = scope.wrappers.ShadowRoot;\n var assert = scope.assert;\n var getTreeScope = scope.getTreeScope;\n var mixin = scope.mixin;\n var oneOf = scope.oneOf;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n\n /**\n * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.\n * Up means parentNode\n * Sideways means previous and next sibling.\n * @param {!Node} wrapper\n */\n function updateWrapperUpAndSideways(wrapper) {\n wrapper.previousSibling_ = wrapper.previousSibling;\n wrapper.nextSibling_ = wrapper.nextSibling;\n wrapper.parentNode_ = wrapper.parentNode;\n }\n\n /**\n * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.\n * Down means first and last child\n * @param {!Node} wrapper\n */\n function updateWrapperDown(wrapper) {\n wrapper.firstChild_ = wrapper.firstChild;\n wrapper.lastChild_ = wrapper.lastChild;\n }\n\n function updateAllChildNodes(parentNodeWrapper) {\n assert(parentNodeWrapper instanceof Node);\n for (var childWrapper = parentNodeWrapper.firstChild;\n childWrapper;\n childWrapper = childWrapper.nextSibling) {\n updateWrapperUpAndSideways(childWrapper);\n }\n updateWrapperDown(parentNodeWrapper);\n }\n\n function insertBefore(parentNodeWrapper, newChildWrapper, refChildWrapper) {\n var parentNode = unwrap(parentNodeWrapper);\n var newChild = unwrap(newChildWrapper);\n var refChild = refChildWrapper ? unwrap(refChildWrapper) : null;\n\n remove(newChildWrapper);\n updateWrapperUpAndSideways(newChildWrapper);\n\n if (!refChildWrapper) {\n parentNodeWrapper.lastChild_ = parentNodeWrapper.lastChild;\n if (parentNodeWrapper.lastChild === parentNodeWrapper.firstChild)\n parentNodeWrapper.firstChild_ = parentNodeWrapper.firstChild;\n\n var lastChildWrapper = wrap(parentNode.lastChild);\n if (lastChildWrapper)\n lastChildWrapper.nextSibling_ = lastChildWrapper.nextSibling;\n } else {\n if (parentNodeWrapper.firstChild === refChildWrapper)\n parentNodeWrapper.firstChild_ = refChildWrapper;\n\n refChildWrapper.previousSibling_ = refChildWrapper.previousSibling;\n }\n\n parentNode.insertBefore(newChild, refChild);\n }\n\n function remove(nodeWrapper) {\n var node = unwrap(nodeWrapper)\n var parentNode = node.parentNode;\n if (!parentNode)\n return;\n\n var parentNodeWrapper = wrap(parentNode);\n updateWrapperUpAndSideways(nodeWrapper);\n\n if (nodeWrapper.previousSibling)\n nodeWrapper.previousSibling.nextSibling_ = nodeWrapper;\n if (nodeWrapper.nextSibling)\n nodeWrapper.nextSibling.previousSibling_ = nodeWrapper;\n\n if (parentNodeWrapper.lastChild === nodeWrapper)\n parentNodeWrapper.lastChild_ = nodeWrapper;\n if (parentNodeWrapper.firstChild === nodeWrapper)\n parentNodeWrapper.firstChild_ = nodeWrapper;\n\n parentNode.removeChild(node);\n }\n\n var distributedChildNodesTable = new WeakMap();\n var eventParentsTable = new WeakMap();\n var insertionParentTable = new WeakMap();\n var rendererForHostTable = new WeakMap();\n\n function distributeChildToInsertionPoint(child, insertionPoint) {\n getDistributedChildNodes(insertionPoint).push(child);\n assignToInsertionPoint(child, insertionPoint);\n\n var eventParents = eventParentsTable.get(child);\n if (!eventParents)\n eventParentsTable.set(child, eventParents = []);\n eventParents.push(insertionPoint);\n }\n\n function resetDistributedChildNodes(insertionPoint) {\n distributedChildNodesTable.set(insertionPoint, []);\n }\n\n function getDistributedChildNodes(insertionPoint) {\n var rv = distributedChildNodesTable.get(insertionPoint);\n if (!rv)\n distributedChildNodesTable.set(insertionPoint, rv = []);\n return rv;\n }\n\n function getChildNodesSnapshot(node) {\n var result = [], i = 0;\n for (var child = node.firstChild; child; child = child.nextSibling) {\n result[i++] = child;\n }\n return result;\n }\n\n /**\n * Visits all nodes in the tree that fulfils the |predicate|. If the |visitor|\n * function returns |false| the traversal is aborted.\n * @param {!Node} tree\n * @param {function(!Node) : boolean} predicate\n * @param {function(!Node) : *} visitor\n */\n function visit(tree, predicate, visitor) {\n // This operates on logical DOM.\n for (var node = tree.firstChild; node; node = node.nextSibling) {\n if (predicate(node)) {\n if (visitor(node) === false)\n return;\n } else {\n visit(node, predicate, visitor);\n }\n }\n }\n\n // Matching Insertion Points\n // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#matching-insertion-points\n\n // TODO(arv): Verify this... I don't remember why I picked this regexp.\n var selectorMatchRegExp = /^[*.:#[a-zA-Z_|]/;\n\n var allowedPseudoRegExp = new RegExp('^:(' + [\n 'link',\n 'visited',\n 'target',\n 'enabled',\n 'disabled',\n 'checked',\n 'indeterminate',\n 'nth-child',\n 'nth-last-child',\n 'nth-of-type',\n 'nth-last-of-type',\n 'first-child',\n 'last-child',\n 'first-of-type',\n 'last-of-type',\n 'only-of-type',\n ].join('|') + ')');\n\n\n /**\n * @param {Element} node\n * @oaram {Element} point The insertion point element.\n * @return {boolean} Whether the node matches the insertion point.\n */\n function matchesCriteria(node, point) {\n var select = point.getAttribute('select');\n if (!select)\n return true;\n\n // Here we know the select attribute is a non empty string.\n select = select.trim();\n if (!select)\n return true;\n\n if (!(node instanceof Element))\n return false;\n\n // The native matches function in IE9 does not correctly work with elements\n // that are not in the document.\n // TODO(arv): Implement matching in JS.\n // https://github.com/Polymer/ShadowDOM/issues/361\n if (select === '*' || select === node.localName)\n return true;\n\n // TODO(arv): This does not seem right. Need to check for a simple selector.\n if (!selectorMatchRegExp.test(select))\n return false;\n\n // TODO(arv): This no longer matches the spec.\n if (select[0] === ':' && !allowedPseudoRegExp.test(select))\n return false;\n\n try {\n return node.matches(select);\n } catch (ex) {\n // Invalid selector.\n return false;\n }\n }\n\n var request = oneOf(window, [\n 'requestAnimationFrame',\n 'mozRequestAnimationFrame',\n 'webkitRequestAnimationFrame',\n 'setTimeout'\n ]);\n\n var pendingDirtyRenderers = [];\n var renderTimer;\n\n function renderAllPending() {\n // TODO(arv): Order these in document order. That way we do not have to\n // render something twice.\n for (var i = 0; i < pendingDirtyRenderers.length; i++) {\n var renderer = pendingDirtyRenderers[i];\n var parentRenderer = renderer.parentRenderer;\n if (parentRenderer && parentRenderer.dirty)\n continue;\n renderer.render();\n }\n\n pendingDirtyRenderers = [];\n }\n\n function handleRequestAnimationFrame() {\n renderTimer = null;\n renderAllPending();\n }\n\n /**\n * Returns existing shadow renderer for a host or creates it if it is needed.\n * @params {!Element} host\n * @return {!ShadowRenderer}\n */\n function getRendererForHost(host) {\n var renderer = rendererForHostTable.get(host);\n if (!renderer) {\n renderer = new ShadowRenderer(host);\n rendererForHostTable.set(host, renderer);\n }\n return renderer;\n }\n\n function getShadowRootAncestor(node) {\n var root = getTreeScope(node).root;\n if (root instanceof ShadowRoot)\n return root;\n return null;\n }\n\n function getRendererForShadowRoot(shadowRoot) {\n return getRendererForHost(shadowRoot.host);\n }\n\n var spliceDiff = new ArraySplice();\n spliceDiff.equals = function(renderNode, rawNode) {\n return unwrap(renderNode.node) === rawNode;\n };\n\n /**\n * RenderNode is used as an in memory \"render tree\". When we render the\n * composed tree we create a tree of RenderNodes, then we diff this against\n * the real DOM tree and make minimal changes as needed.\n */\n function RenderNode(node) {\n this.skip = false;\n this.node = node;\n this.childNodes = [];\n }\n\n RenderNode.prototype = {\n append: function(node) {\n var rv = new RenderNode(node);\n this.childNodes.push(rv);\n return rv;\n },\n\n sync: function(opt_added) {\n if (this.skip)\n return;\n\n var nodeWrapper = this.node;\n // plain array of RenderNodes\n var newChildren = this.childNodes;\n // plain array of real nodes.\n var oldChildren = getChildNodesSnapshot(unwrap(nodeWrapper));\n var added = opt_added || new WeakMap();\n\n var splices = spliceDiff.calculateSplices(newChildren, oldChildren);\n\n var newIndex = 0, oldIndex = 0;\n var lastIndex = 0;\n for (var i = 0; i < splices.length; i++) {\n var splice = splices[i];\n for (; lastIndex < splice.index; lastIndex++) {\n oldIndex++;\n newChildren[newIndex++].sync(added);\n }\n\n var removedCount = splice.removed.length;\n for (var j = 0; j < removedCount; j++) {\n var wrapper = wrap(oldChildren[oldIndex++]);\n if (!added.get(wrapper))\n remove(wrapper);\n }\n\n var addedCount = splice.addedCount;\n var refNode = oldChildren[oldIndex] && wrap(oldChildren[oldIndex]);\n for (var j = 0; j < addedCount; j++) {\n var newChildRenderNode = newChildren[newIndex++];\n var newChildWrapper = newChildRenderNode.node;\n insertBefore(nodeWrapper, newChildWrapper, refNode);\n\n // Keep track of added so that we do not remove the node after it\n // has been added.\n added.set(newChildWrapper, true);\n\n newChildRenderNode.sync(added);\n }\n\n lastIndex += addedCount;\n }\n\n for (var i = lastIndex; i < newChildren.length; i++) {\n newChildren[i].sync(added);\n }\n }\n };\n\n function ShadowRenderer(host) {\n this.host = host;\n this.dirty = false;\n this.invalidateAttributes();\n this.associateNode(host);\n }\n\n ShadowRenderer.prototype = {\n\n // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees\n render: function(opt_renderNode) {\n if (!this.dirty)\n return;\n\n this.invalidateAttributes();\n this.treeComposition();\n\n var host = this.host;\n var shadowRoot = host.shadowRoot;\n\n this.associateNode(host);\n var topMostRenderer = !renderNode;\n var renderNode = opt_renderNode || new RenderNode(host);\n\n for (var node = shadowRoot.firstChild; node; node = node.nextSibling) {\n this.renderNode(shadowRoot, renderNode, node, false);\n }\n\n if (topMostRenderer)\n renderNode.sync();\n\n this.dirty = false;\n },\n\n get parentRenderer() {\n return getTreeScope(this.host).renderer;\n },\n\n invalidate: function() {\n if (!this.dirty) {\n this.dirty = true;\n pendingDirtyRenderers.push(this);\n if (renderTimer)\n return;\n renderTimer = window[request](handleRequestAnimationFrame, 0);\n }\n },\n\n renderNode: function(shadowRoot, renderNode, node, isNested) {\n if (isShadowHost(node)) {\n renderNode = renderNode.append(node);\n var renderer = getRendererForHost(node);\n renderer.dirty = true; // Need to rerender due to reprojection.\n renderer.render(renderNode);\n } else if (isInsertionPoint(node)) {\n this.renderInsertionPoint(shadowRoot, renderNode, node, isNested);\n } else if (isShadowInsertionPoint(node)) {\n this.renderShadowInsertionPoint(shadowRoot, renderNode, node);\n } else {\n this.renderAsAnyDomTree(shadowRoot, renderNode, node, isNested);\n }\n },\n\n renderAsAnyDomTree: function(shadowRoot, renderNode, node, isNested) {\n renderNode = renderNode.append(node);\n\n if (isShadowHost(node)) {\n var renderer = getRendererForHost(node);\n renderNode.skip = !renderer.dirty;\n renderer.render(renderNode);\n } else {\n for (var child = node.firstChild; child; child = child.nextSibling) {\n this.renderNode(shadowRoot, renderNode, child, isNested);\n }\n }\n },\n\n renderInsertionPoint: function(shadowRoot, renderNode, insertionPoint,\n isNested) {\n var distributedChildNodes = getDistributedChildNodes(insertionPoint);\n if (distributedChildNodes.length) {\n this.associateNode(insertionPoint);\n\n for (var i = 0; i < distributedChildNodes.length; i++) {\n var child = distributedChildNodes[i];\n if (isInsertionPoint(child) && isNested)\n this.renderInsertionPoint(shadowRoot, renderNode, child, isNested);\n else\n this.renderAsAnyDomTree(shadowRoot, renderNode, child, isNested);\n }\n } else {\n this.renderFallbackContent(shadowRoot, renderNode, insertionPoint);\n }\n this.associateNode(insertionPoint.parentNode);\n },\n\n renderShadowInsertionPoint: function(shadowRoot, renderNode,\n shadowInsertionPoint) {\n var nextOlderTree = shadowRoot.olderShadowRoot;\n if (nextOlderTree) {\n assignToInsertionPoint(nextOlderTree, shadowInsertionPoint);\n this.associateNode(shadowInsertionPoint.parentNode);\n for (var node = nextOlderTree.firstChild;\n node;\n node = node.nextSibling) {\n this.renderNode(nextOlderTree, renderNode, node, true);\n }\n } else {\n this.renderFallbackContent(shadowRoot, renderNode,\n shadowInsertionPoint);\n }\n },\n\n renderFallbackContent: function(shadowRoot, renderNode, fallbackHost) {\n this.associateNode(fallbackHost);\n this.associateNode(fallbackHost.parentNode);\n for (var node = fallbackHost.firstChild; node; node = node.nextSibling) {\n this.renderAsAnyDomTree(shadowRoot, renderNode, node, false);\n }\n },\n\n /**\n * Invalidates the attributes used to keep track of which attributes may\n * cause the renderer to be invalidated.\n */\n invalidateAttributes: function() {\n this.attributes = Object.create(null);\n },\n\n /**\n * Parses the selector and makes this renderer dependent on the attribute\n * being used in the selector.\n * @param {string} selector\n */\n updateDependentAttributes: function(selector) {\n if (!selector)\n return;\n\n var attributes = this.attributes;\n\n // .class\n if (/\\.\\w+/.test(selector))\n attributes['class'] = true;\n\n // #id\n if (/#\\w+/.test(selector))\n attributes['id'] = true;\n\n selector.replace(/\\[\\s*([^\\s=\\|~\\]]+)/g, function(_, name) {\n attributes[name] = true;\n });\n\n // Pseudo selectors have been removed from the spec.\n },\n\n dependsOnAttribute: function(name) {\n return this.attributes[name];\n },\n\n // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-distribution-algorithm\n distribute: function(tree, pool) {\n var self = this;\n\n visit(tree, isActiveInsertionPoint,\n function(insertionPoint) {\n resetDistributedChildNodes(insertionPoint);\n self.updateDependentAttributes(\n insertionPoint.getAttribute('select'));\n\n for (var i = 0; i < pool.length; i++) { // 1.2\n var node = pool[i]; // 1.2.1\n if (node === undefined) // removed\n continue;\n if (matchesCriteria(node, insertionPoint)) { // 1.2.2\n distributeChildToInsertionPoint(node, insertionPoint); // 1.2.2.1\n pool[i] = undefined; // 1.2.2.2\n }\n }\n });\n },\n\n // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-tree-composition\n treeComposition: function () {\n var shadowHost = this.host;\n var tree = shadowHost.shadowRoot; // 1.\n var pool = []; // 2.\n\n for (var child = shadowHost.firstChild;\n child;\n child = child.nextSibling) { // 3.\n if (isInsertionPoint(child)) { // 3.2.\n var reprojected = getDistributedChildNodes(child); // 3.2.1.\n // if reprojected is undef... reset it?\n if (!reprojected || !reprojected.length) // 3.2.2.\n reprojected = getChildNodesSnapshot(child);\n pool.push.apply(pool, reprojected); // 3.2.3.\n } else {\n pool.push(child); // 3.3.\n }\n }\n\n var shadowInsertionPoint, point;\n while (tree) { // 4.\n // 4.1.\n shadowInsertionPoint = undefined; // Reset every iteration.\n visit(tree, isActiveShadowInsertionPoint, function(point) {\n shadowInsertionPoint = point;\n return false;\n });\n point = shadowInsertionPoint;\n\n this.distribute(tree, pool); // 4.2.\n if (point) { // 4.3.\n var nextOlderTree = tree.olderShadowRoot; // 4.3.1.\n if (!nextOlderTree) {\n break; // 4.3.1.1.\n } else {\n tree = nextOlderTree; // 4.3.2.2.\n assignToInsertionPoint(tree, point); // 4.3.2.2.\n continue; // 4.3.2.3.\n }\n } else {\n break; // 4.4.\n }\n }\n },\n\n associateNode: function(node) {\n node.impl.polymerShadowRenderer_ = this;\n }\n };\n\n function isInsertionPoint(node) {\n // Should this include ?\n return node instanceof HTMLContentElement;\n }\n\n function isActiveInsertionPoint(node) {\n // inside another or is considered inactive.\n return node instanceof HTMLContentElement;\n }\n\n function isShadowInsertionPoint(node) {\n return node instanceof HTMLShadowElement;\n }\n\n function isActiveShadowInsertionPoint(node) {\n // inside another or is considered inactive.\n return node instanceof HTMLShadowElement;\n }\n\n function isShadowHost(shadowHost) {\n return shadowHost.shadowRoot;\n }\n\n function getShadowTrees(host) {\n var trees = [];\n\n for (var tree = host.shadowRoot; tree; tree = tree.olderShadowRoot) {\n trees.push(tree);\n }\n return trees;\n }\n\n function assignToInsertionPoint(tree, point) {\n insertionParentTable.set(tree, point);\n }\n\n // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees\n function render(host) {\n new ShadowRenderer(host).render();\n };\n\n // Need to rerender shadow host when:\n //\n // - a direct child to the ShadowRoot is added or removed\n // - a direct child to the host is added or removed\n // - a new shadow root is created\n // - a direct child to a content/shadow element is added or removed\n // - a sibling to a content/shadow element is added or removed\n // - content[select] is changed\n // - an attribute in a direct child to a host is modified\n\n /**\n * This gets called when a node was added or removed to it.\n */\n Node.prototype.invalidateShadowRenderer = function(force) {\n var renderer = this.impl.polymerShadowRenderer_;\n if (renderer) {\n renderer.invalidate();\n return true;\n }\n\n return false;\n };\n\n HTMLContentElement.prototype.getDistributedNodes = function() {\n // TODO(arv): We should only rerender the dirty ancestor renderers (from\n // the root and down).\n renderAllPending();\n return getDistributedChildNodes(this);\n };\n\n HTMLShadowElement.prototype.nodeIsInserted_ =\n HTMLContentElement.prototype.nodeIsInserted_ = function() {\n // Invalidate old renderer if any.\n this.invalidateShadowRenderer();\n\n var shadowRoot = getShadowRootAncestor(this);\n var renderer;\n if (shadowRoot)\n renderer = getRendererForShadowRoot(shadowRoot);\n this.impl.polymerShadowRenderer_ = renderer;\n if (renderer)\n renderer.invalidate();\n };\n\n scope.eventParentsTable = eventParentsTable;\n scope.getRendererForHost = getRendererForHost;\n scope.getShadowTrees = getShadowTrees;\n scope.insertionParentTable = insertionParentTable;\n scope.renderAllPending = renderAllPending;\n\n // Exposed for testing\n scope.visual = {\n insertBefore: insertBefore,\n remove: remove,\n };\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var HTMLElement = scope.wrappers.HTMLElement;\n var assert = scope.assert;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n\n var elementsWithFormProperty = [\n 'HTMLButtonElement',\n 'HTMLFieldSetElement',\n 'HTMLInputElement',\n 'HTMLKeygenElement',\n 'HTMLLabelElement',\n 'HTMLLegendElement',\n 'HTMLObjectElement',\n // HTMLOptionElement is handled in HTMLOptionElement.js\n 'HTMLOutputElement',\n // HTMLSelectElement is handled in HTMLSelectElement.js\n 'HTMLTextAreaElement',\n ];\n\n function createWrapperConstructor(name) {\n if (!window[name])\n return;\n\n // Ensure we are not overriding an already existing constructor.\n assert(!scope.wrappers[name]);\n\n var GeneratedWrapper = function(node) {\n // At this point all of them extend HTMLElement.\n HTMLElement.call(this, node);\n }\n GeneratedWrapper.prototype = Object.create(HTMLElement.prototype);\n mixin(GeneratedWrapper.prototype, {\n get form() {\n return wrap(unwrap(this).form);\n },\n });\n\n registerWrapper(window[name], GeneratedWrapper,\n document.createElement(name.slice(4, -7)));\n scope.wrappers[name] = GeneratedWrapper;\n }\n\n elementsWithFormProperty.forEach(createWrapperConstructor);\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var registerWrapper = scope.registerWrapper;\n var unwrap = scope.unwrap;\n var unwrapIfNeeded = scope.unwrapIfNeeded;\n var wrap = scope.wrap;\n\n var OriginalSelection = window.Selection;\n\n function Selection(impl) {\n this.impl = impl;\n }\n Selection.prototype = {\n get anchorNode() {\n return wrap(this.impl.anchorNode);\n },\n get focusNode() {\n return wrap(this.impl.focusNode);\n },\n addRange: function(range) {\n this.impl.addRange(unwrap(range));\n },\n collapse: function(node, index) {\n this.impl.collapse(unwrapIfNeeded(node), index);\n },\n containsNode: function(node, allowPartial) {\n return this.impl.containsNode(unwrapIfNeeded(node), allowPartial);\n },\n extend: function(node, offset) {\n this.impl.extend(unwrapIfNeeded(node), offset);\n },\n getRangeAt: function(index) {\n return wrap(this.impl.getRangeAt(index));\n },\n removeRange: function(range) {\n this.impl.removeRange(unwrap(range));\n },\n selectAllChildren: function(node) {\n this.impl.selectAllChildren(unwrapIfNeeded(node));\n },\n toString: function() {\n return this.impl.toString();\n }\n };\n\n // WebKit extensions. Not implemented.\n // readonly attribute Node baseNode;\n // readonly attribute long baseOffset;\n // readonly attribute Node extentNode;\n // readonly attribute long extentOffset;\n // [RaisesException] void setBaseAndExtent([Default=Undefined] optional Node baseNode,\n // [Default=Undefined] optional long baseOffset,\n // [Default=Undefined] optional Node extentNode,\n // [Default=Undefined] optional long extentOffset);\n // [RaisesException, ImplementedAs=collapse] void setPosition([Default=Undefined] optional Node node,\n // [Default=Undefined] optional long offset);\n\n registerWrapper(window.Selection, Selection, window.getSelection());\n\n scope.wrappers.Selection = Selection;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var GetElementsByInterface = scope.GetElementsByInterface;\n var Node = scope.wrappers.Node;\n var ParentNodeInterface = scope.ParentNodeInterface;\n var Selection = scope.wrappers.Selection;\n var SelectorsInterface = scope.SelectorsInterface;\n var ShadowRoot = scope.wrappers.ShadowRoot;\n var TreeScope = scope.TreeScope;\n var cloneNode = scope.cloneNode;\n var defineWrapGetter = scope.defineWrapGetter;\n var elementFromPoint = scope.elementFromPoint;\n var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;\n var matchesNames = scope.matchesNames;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var renderAllPending = scope.renderAllPending;\n var rewrap = scope.rewrap;\n var unwrap = scope.unwrap;\n var wrap = scope.wrap;\n var wrapEventTargetMethods = scope.wrapEventTargetMethods;\n var wrapNodeList = scope.wrapNodeList;\n\n var implementationTable = new WeakMap();\n\n function Document(node) {\n Node.call(this, node);\n this.treeScope_ = new TreeScope(this, null);\n }\n Document.prototype = Object.create(Node.prototype);\n\n defineWrapGetter(Document, 'documentElement');\n\n // Conceptually both body and head can be in a shadow but suporting that seems\n // overkill at this point.\n defineWrapGetter(Document, 'body');\n defineWrapGetter(Document, 'head');\n\n // document cannot be overridden so we override a bunch of its methods\n // directly on the instance.\n\n function wrapMethod(name) {\n var original = document[name];\n Document.prototype[name] = function() {\n return wrap(original.apply(this.impl, arguments));\n };\n }\n\n [\n 'createComment',\n 'createDocumentFragment',\n 'createElement',\n 'createElementNS',\n 'createEvent',\n 'createEventNS',\n 'createRange',\n 'createTextNode',\n 'getElementById'\n ].forEach(wrapMethod);\n\n var originalAdoptNode = document.adoptNode;\n\n function adoptNodeNoRemove(node, doc) {\n originalAdoptNode.call(doc.impl, unwrap(node));\n adoptSubtree(node, doc);\n }\n\n function adoptSubtree(node, doc) {\n if (node.shadowRoot)\n doc.adoptNode(node.shadowRoot);\n if (node instanceof ShadowRoot)\n adoptOlderShadowRoots(node, doc);\n for (var child = node.firstChild; child; child = child.nextSibling) {\n adoptSubtree(child, doc);\n }\n }\n\n function adoptOlderShadowRoots(shadowRoot, doc) {\n var oldShadowRoot = shadowRoot.olderShadowRoot;\n if (oldShadowRoot)\n doc.adoptNode(oldShadowRoot);\n }\n\n var originalGetSelection = document.getSelection;\n\n mixin(Document.prototype, {\n adoptNode: function(node) {\n if (node.parentNode)\n node.parentNode.removeChild(node);\n adoptNodeNoRemove(node, this);\n return node;\n },\n elementFromPoint: function(x, y) {\n return elementFromPoint(this, this, x, y);\n },\n importNode: function(node, deep) {\n return cloneNode(node, deep, this.impl);\n },\n getSelection: function() {\n renderAllPending();\n return new Selection(originalGetSelection.call(unwrap(this)));\n }\n });\n\n if (document.registerElement) {\n var originalRegisterElement = document.registerElement;\n Document.prototype.registerElement = function(tagName, object) {\n var prototype, extendsOption;\n if (object !== undefined) {\n prototype = object.prototype;\n extendsOption = object.extends;\n }\n\n if (!prototype)\n prototype = Object.create(HTMLElement.prototype);\n\n\n // If we already used the object as a prototype for another custom\n // element.\n if (scope.nativePrototypeTable.get(prototype)) {\n // TODO(arv): DOMException\n throw new Error('NotSupportedError');\n }\n\n // Find first object on the prototype chain that already have a native\n // prototype. Keep track of all the objects before that so we can create\n // a similar structure for the native case.\n var proto = Object.getPrototypeOf(prototype);\n var nativePrototype;\n var prototypes = [];\n while (proto) {\n nativePrototype = scope.nativePrototypeTable.get(proto);\n if (nativePrototype)\n break;\n prototypes.push(proto);\n proto = Object.getPrototypeOf(proto);\n }\n\n if (!nativePrototype) {\n // TODO(arv): DOMException\n throw new Error('NotSupportedError');\n }\n\n // This works by creating a new prototype object that is empty, but has\n // the native prototype as its proto. The original prototype object\n // passed into register is used as the wrapper prototype.\n\n var newPrototype = Object.create(nativePrototype);\n for (var i = prototypes.length - 1; i >= 0; i--) {\n newPrototype = Object.create(newPrototype);\n }\n\n // Add callbacks if present.\n // Names are taken from:\n // https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp&sq=package:chromium&type=cs&l=156\n // and not from the spec since the spec is out of date.\n [\n 'createdCallback',\n 'attachedCallback',\n 'detachedCallback',\n 'attributeChangedCallback',\n ].forEach(function(name) {\n var f = prototype[name];\n if (!f)\n return;\n newPrototype[name] = function() {\n // if this element has been wrapped prior to registration,\n // the wrapper is stale; in this case rewrap\n if (!(wrap(this) instanceof CustomElementConstructor)) {\n rewrap(this);\n }\n f.apply(wrap(this), arguments);\n };\n });\n\n var p = {prototype: newPrototype};\n if (extendsOption)\n p.extends = extendsOption;\n\n function CustomElementConstructor(node) {\n if (!node) {\n if (extendsOption) {\n return document.createElement(extendsOption, tagName);\n } else {\n return document.createElement(tagName);\n }\n }\n this.impl = node;\n }\n CustomElementConstructor.prototype = prototype;\n CustomElementConstructor.prototype.constructor = CustomElementConstructor;\n\n scope.constructorTable.set(newPrototype, CustomElementConstructor);\n scope.nativePrototypeTable.set(prototype, newPrototype);\n\n // registration is synchronous so do it last\n var nativeConstructor = originalRegisterElement.call(unwrap(this),\n tagName, p);\n return CustomElementConstructor;\n };\n\n forwardMethodsToWrapper([\n window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument\n ], [\n 'registerElement',\n ]);\n }\n\n // We also override some of the methods on document.body and document.head\n // for convenience.\n forwardMethodsToWrapper([\n window.HTMLBodyElement,\n window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument\n window.HTMLHeadElement,\n window.HTMLHtmlElement,\n ], [\n 'appendChild',\n 'compareDocumentPosition',\n 'contains',\n 'getElementsByClassName',\n 'getElementsByTagName',\n 'getElementsByTagNameNS',\n 'insertBefore',\n 'querySelector',\n 'querySelectorAll',\n 'removeChild',\n 'replaceChild',\n ].concat(matchesNames));\n\n forwardMethodsToWrapper([\n window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument\n ], [\n 'adoptNode',\n 'importNode',\n 'contains',\n 'createComment',\n 'createDocumentFragment',\n 'createElement',\n 'createElementNS',\n 'createEvent',\n 'createEventNS',\n 'createRange',\n 'createTextNode',\n 'elementFromPoint',\n 'getElementById',\n 'getSelection',\n ]);\n\n mixin(Document.prototype, GetElementsByInterface);\n mixin(Document.prototype, ParentNodeInterface);\n mixin(Document.prototype, SelectorsInterface);\n\n mixin(Document.prototype, {\n get implementation() {\n var implementation = implementationTable.get(this);\n if (implementation)\n return implementation;\n implementation =\n new DOMImplementation(unwrap(this).implementation);\n implementationTable.set(this, implementation);\n return implementation;\n }\n });\n\n registerWrapper(window.Document, Document,\n document.implementation.createHTMLDocument(''));\n\n // Both WebKit and Gecko uses HTMLDocument for document. HTML5/DOM only has\n // one Document interface and IE implements the standard correctly.\n if (window.HTMLDocument)\n registerWrapper(window.HTMLDocument, Document);\n\n wrapEventTargetMethods([\n window.HTMLBodyElement,\n window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument\n window.HTMLHeadElement,\n ]);\n\n function DOMImplementation(impl) {\n this.impl = impl;\n }\n\n function wrapImplMethod(constructor, name) {\n var original = document.implementation[name];\n constructor.prototype[name] = function() {\n return wrap(original.apply(this.impl, arguments));\n };\n }\n\n function forwardImplMethod(constructor, name) {\n var original = document.implementation[name];\n constructor.prototype[name] = function() {\n return original.apply(this.impl, arguments);\n };\n }\n\n wrapImplMethod(DOMImplementation, 'createDocumentType');\n wrapImplMethod(DOMImplementation, 'createDocument');\n wrapImplMethod(DOMImplementation, 'createHTMLDocument');\n forwardImplMethod(DOMImplementation, 'hasFeature');\n\n registerWrapper(window.DOMImplementation, DOMImplementation);\n\n forwardMethodsToWrapper([\n window.DOMImplementation,\n ], [\n 'createDocumentType',\n 'createDocument',\n 'createHTMLDocument',\n 'hasFeature',\n ]);\n\n scope.adoptNodeNoRemove = adoptNodeNoRemove;\n scope.wrappers.DOMImplementation = DOMImplementation;\n scope.wrappers.Document = Document;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var EventTarget = scope.wrappers.EventTarget;\n var Selection = scope.wrappers.Selection;\n var mixin = scope.mixin;\n var registerWrapper = scope.registerWrapper;\n var renderAllPending = scope.renderAllPending;\n var unwrap = scope.unwrap;\n var unwrapIfNeeded = scope.unwrapIfNeeded;\n var wrap = scope.wrap;\n\n var OriginalWindow = window.Window;\n var originalGetComputedStyle = window.getComputedStyle;\n var originalGetSelection = window.getSelection;\n\n function Window(impl) {\n EventTarget.call(this, impl);\n }\n Window.prototype = Object.create(EventTarget.prototype);\n\n OriginalWindow.prototype.getComputedStyle = function(el, pseudo) {\n return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo);\n };\n\n OriginalWindow.prototype.getSelection = function() {\n return wrap(this || window).getSelection();\n };\n\n // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065\n delete window.getComputedStyle;\n delete window.getSelection;\n\n ['addEventListener', 'removeEventListener', 'dispatchEvent'].forEach(\n function(name) {\n OriginalWindow.prototype[name] = function() {\n var w = wrap(this || window);\n return w[name].apply(w, arguments);\n };\n\n // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065\n delete window[name];\n });\n\n mixin(Window.prototype, {\n getComputedStyle: function(el, pseudo) {\n renderAllPending();\n return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el),\n pseudo);\n },\n getSelection: function() {\n renderAllPending();\n return new Selection(originalGetSelection.call(unwrap(this)));\n },\n });\n\n registerWrapper(OriginalWindow, Window);\n\n scope.wrappers.Window = Window;\n\n})(window.ShadowDOMPolyfill);\n","/**\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n 'use strict';\n\n var unwrap = scope.unwrap;\n\n // DataTransfer (Clipboard in old Blink/WebKit) has a single method that\n // requires wrapping. Since it is only a method we do not need a real wrapper,\n // we can just override the method.\n\n var OriginalDataTransfer = window.DataTransfer || window.Clipboard;\n var OriginalDataTransferSetDragImage =\n OriginalDataTransfer.prototype.setDragImage;\n\n OriginalDataTransfer.prototype.setDragImage = function(image, x, y) {\n OriginalDataTransferSetDragImage.call(this, unwrap(image), x, y);\n };\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n 'use strict';\n\n var isWrapperFor = scope.isWrapperFor;\n\n // This is a list of the elements we currently override the global constructor\n // for.\n var elements = {\n 'a': 'HTMLAnchorElement',\n // Do not create an applet element by default since it shows a warning in\n // IE.\n // https://github.com/Polymer/polymer/issues/217\n // 'applet': 'HTMLAppletElement',\n 'area': 'HTMLAreaElement',\n 'audio': 'HTMLAudioElement',\n 'base': 'HTMLBaseElement',\n 'body': 'HTMLBodyElement',\n 'br': 'HTMLBRElement',\n 'button': 'HTMLButtonElement',\n 'canvas': 'HTMLCanvasElement',\n 'caption': 'HTMLTableCaptionElement',\n 'col': 'HTMLTableColElement',\n // 'command': 'HTMLCommandElement', // Not fully implemented in Gecko.\n 'content': 'HTMLContentElement',\n 'data': 'HTMLDataElement',\n 'datalist': 'HTMLDataListElement',\n 'del': 'HTMLModElement',\n 'dir': 'HTMLDirectoryElement',\n 'div': 'HTMLDivElement',\n 'dl': 'HTMLDListElement',\n 'embed': 'HTMLEmbedElement',\n 'fieldset': 'HTMLFieldSetElement',\n 'font': 'HTMLFontElement',\n 'form': 'HTMLFormElement',\n 'frame': 'HTMLFrameElement',\n 'frameset': 'HTMLFrameSetElement',\n 'h1': 'HTMLHeadingElement',\n 'head': 'HTMLHeadElement',\n 'hr': 'HTMLHRElement',\n 'html': 'HTMLHtmlElement',\n 'iframe': 'HTMLIFrameElement',\n 'img': 'HTMLImageElement',\n 'input': 'HTMLInputElement',\n 'keygen': 'HTMLKeygenElement',\n 'label': 'HTMLLabelElement',\n 'legend': 'HTMLLegendElement',\n 'li': 'HTMLLIElement',\n 'link': 'HTMLLinkElement',\n 'map': 'HTMLMapElement',\n 'marquee': 'HTMLMarqueeElement',\n 'menu': 'HTMLMenuElement',\n 'menuitem': 'HTMLMenuItemElement',\n 'meta': 'HTMLMetaElement',\n 'meter': 'HTMLMeterElement',\n 'object': 'HTMLObjectElement',\n 'ol': 'HTMLOListElement',\n 'optgroup': 'HTMLOptGroupElement',\n 'option': 'HTMLOptionElement',\n 'output': 'HTMLOutputElement',\n 'p': 'HTMLParagraphElement',\n 'param': 'HTMLParamElement',\n 'pre': 'HTMLPreElement',\n 'progress': 'HTMLProgressElement',\n 'q': 'HTMLQuoteElement',\n 'script': 'HTMLScriptElement',\n 'select': 'HTMLSelectElement',\n 'shadow': 'HTMLShadowElement',\n 'source': 'HTMLSourceElement',\n 'span': 'HTMLSpanElement',\n 'style': 'HTMLStyleElement',\n 'table': 'HTMLTableElement',\n 'tbody': 'HTMLTableSectionElement',\n // WebKit and Moz are wrong:\n // https://bugs.webkit.org/show_bug.cgi?id=111469\n // https://bugzilla.mozilla.org/show_bug.cgi?id=848096\n // 'td': 'HTMLTableCellElement',\n 'template': 'HTMLTemplateElement',\n 'textarea': 'HTMLTextAreaElement',\n 'thead': 'HTMLTableSectionElement',\n 'time': 'HTMLTimeElement',\n 'title': 'HTMLTitleElement',\n 'tr': 'HTMLTableRowElement',\n 'track': 'HTMLTrackElement',\n 'ul': 'HTMLUListElement',\n 'video': 'HTMLVideoElement',\n };\n\n function overrideConstructor(tagName) {\n var nativeConstructorName = elements[tagName];\n var nativeConstructor = window[nativeConstructorName];\n if (!nativeConstructor)\n return;\n var element = document.createElement(tagName);\n var wrapperConstructor = element.constructor;\n window[nativeConstructorName] = wrapperConstructor;\n }\n\n Object.keys(elements).forEach(overrideConstructor);\n\n Object.getOwnPropertyNames(scope.wrappers).forEach(function(name) {\n window[name] = scope.wrappers[name]\n });\n\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\n // convenient global\n window.wrap = ShadowDOMPolyfill.wrapIfNeeded;\n window.unwrap = ShadowDOMPolyfill.unwrapIfNeeded;\n\n // users may want to customize other types\n // TODO(sjmiles): 'button' is now supported by ShadowDOMPolyfill, but\n // I've left this code here in case we need to temporarily patch another\n // type\n /*\n (function() {\n var elts = {HTMLButtonElement: 'button'};\n for (var c in elts) {\n window[c] = function() { throw 'Patched Constructor'; };\n window[c].prototype = Object.getPrototypeOf(\n document.createElement(elts[c]));\n }\n })();\n */\n\n // patch in prefixed name\n Object.defineProperty(Element.prototype, 'webkitShadowRoot',\n Object.getOwnPropertyDescriptor(Element.prototype, 'shadowRoot'));\n\n var originalCreateShadowRoot = Element.prototype.createShadowRoot;\n Element.prototype.createShadowRoot = function() {\n var root = originalCreateShadowRoot.call(this);\n CustomElements.watchShadow(this);\n return root;\n };\n\n Element.prototype.webkitCreateShadowRoot = Element.prototype.createShadowRoot;\n})();\n","/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/*\n This is a limited shim for ShadowDOM css styling.\n https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles\n \n The intention here is to support only the styling features which can be \n relatively simply implemented. The goal is to allow users to avoid the \n most obvious pitfalls and do so without compromising performance significantly. \n For ShadowDOM styling that's not covered here, a set of best practices\n can be provided that should allow users to accomplish more complex styling.\n\n The following is a list of specific ShadowDOM styling features and a brief\n discussion of the approach used to shim.\n\n Shimmed features:\n\n * :host, :host-context: ShadowDOM allows styling of the shadowRoot's host\n element using the :host rule. To shim this feature, the :host styles are \n reformatted and prefixed with a given scope name and promoted to a \n document level stylesheet.\n For example, given a scope name of .foo, a rule like this:\n \n :host {\n background: red;\n }\n }\n \n becomes:\n \n .foo {\n background: red;\n }\n \n * encapsultion: Styles defined within ShadowDOM, apply only to \n dom inside the ShadowDOM. Polymer uses one of two techniques to imlement\n this feature.\n \n By default, rules are prefixed with the host element tag name \n as a descendant selector. This ensures styling does not leak out of the 'top'\n of the element's ShadowDOM. For example,\n\n div {\n font-weight: bold;\n }\n \n becomes:\n\n x-foo div {\n font-weight: bold;\n }\n \n becomes:\n\n\n Alternatively, if Platform.ShadowCSS.strictStyling is set to true then \n selectors are scoped by adding an attribute selector suffix to each\n simple selector that contains the host element tag name. Each element \n in the element's ShadowDOM template is also given the scope attribute. \n Thus, these rules match only elements that have the scope attribute.\n For example, given a scope name of x-foo, a rule like this:\n \n div {\n font-weight: bold;\n }\n \n becomes:\n \n div[x-foo] {\n font-weight: bold;\n }\n\n Note that elements that are dynamically added to a scope must have the scope\n selector added to them manually.\n\n * upper/lower bound encapsulation: Styles which are defined outside a\n shadowRoot should not cross the ShadowDOM boundary and should not apply\n inside a shadowRoot.\n\n This styling behavior is not emulated. Some possible ways to do this that \n were rejected due to complexity and/or performance concerns include: (1) reset\n every possible property for every possible selector for a given scope name;\n (2) re-implement css in javascript.\n \n As an alternative, users should make sure to use selectors\n specific to the scope in which they are working.\n \n * ::distributed: This behavior is not emulated. It's often not necessary\n to style the contents of a specific insertion point and instead, descendants\n of the host element can be styled selectively. Users can also create an \n extra node around an insertion point and style that node's contents\n via descendent selectors. For example, with a shadowRoot like this:\n \n \n \n \n could become:\n \n \n
          \n \n
          \n \n Note the use of @polyfill in the comment above a ShadowDOM specific style\n declaration. This is a directive to the styling shim to use the selector \n in comments in lieu of the next selector when running under polyfill.\n*/\n(function(scope) {\n\nvar ShadowCSS = {\n strictStyling: false,\n registry: {},\n // Shim styles for a given root associated with a name and extendsName\n // 1. cache root styles by name\n // 2. optionally tag root nodes with scope name\n // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */\n // 4. shim :host and scoping\n shimStyling: function(root, name, extendsName) {\n var scopeStyles = this.prepareRoot(root, name, extendsName);\n var typeExtension = this.isTypeExtension(extendsName);\n var scopeSelector = this.makeScopeSelector(name, typeExtension);\n // use caching to make working with styles nodes easier and to facilitate\n // lookup of extendee\n var cssText = stylesToCssText(scopeStyles, true);\n cssText = this.scopeCssText(cssText, scopeSelector);\n // cache shimmed css on root for user extensibility\n if (root) {\n root.shimmedStyle = cssText;\n }\n // add style to document\n this.addCssToDocument(cssText, name);\n },\n /*\n * Shim a style element with the given selector. Returns cssText that can\n * be included in the document via Platform.ShadowCSS.addCssToDocument(css).\n */\n shimStyle: function(style, selector) {\n return this.shimCssText(style.textContent, selector);\n },\n /*\n * Shim some cssText with the given selector. Returns cssText that can\n * be included in the document via Platform.ShadowCSS.addCssToDocument(css).\n */\n shimCssText: function(cssText, selector) {\n cssText = this.insertDirectives(cssText);\n return this.scopeCssText(cssText, selector);\n },\n makeScopeSelector: function(name, typeExtension) {\n if (name) {\n return typeExtension ? '[is=' + name + ']' : name;\n }\n return '';\n },\n isTypeExtension: function(extendsName) {\n return extendsName && extendsName.indexOf('-') < 0;\n },\n prepareRoot: function(root, name, extendsName) {\n var def = this.registerRoot(root, name, extendsName);\n this.replaceTextInStyles(def.rootStyles, this.insertDirectives);\n // remove existing style elements\n this.removeStyles(root, def.rootStyles);\n // apply strict attr\n if (this.strictStyling) {\n this.applyScopeToContent(root, name);\n }\n return def.scopeStyles;\n },\n removeStyles: function(root, styles) {\n for (var i=0, l=styles.length, s; (i .bar { }\n *\n * to\n *\n * scopeName.foo > .bar\n */\n convertColonHost: function(cssText) {\n return this.convertColonRule(cssText, cssColonHostRe,\n this.colonHostPartReplacer);\n },\n /*\n * convert a rule like :host-context(.foo) > .bar { }\n *\n * to\n *\n * scopeName.foo > .bar, .foo scopeName > .bar { }\n * \n * and\n *\n * :host-context(.foo:host) .bar { ... }\n * \n * to\n * \n * scopeName.foo .bar { ... }\n */\n convertColonHostContext: function(cssText) {\n return this.convertColonRule(cssText, cssColonHostContextRe,\n this.colonHostContextPartReplacer);\n },\n convertColonRule: function(cssText, regExp, partReplacer) {\n // p1 = :host, p2 = contents of (), p3 rest of rule\n return cssText.replace(regExp, function(m, p1, p2, p3) {\n p1 = polyfillHostNoCombinator;\n if (p2) {\n var parts = p2.split(','), r = [];\n for (var i=0, l=parts.length, p; (i .zot becomes .foo[name].bar[name] > .zot[name]\n applyStrictSelectorScope: function(selector, scopeSelector) {\n scopeSelector = scopeSelector.replace(/\\[is=([^\\]]*)\\]/g, '$1');\n var splits = [' ', '>', '+', '~'],\n scoped = selector,\n attrName = '[' + scopeSelector + ']';\n splits.forEach(function(sep) {\n var parts = scoped.split(sep);\n scoped = parts.map(function(p) {\n // remove :host since it should be unnecessary\n var t = p.trim().replace(polyfillHostRe, '');\n if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) {\n p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3')\n }\n return p;\n }).join(sep);\n });\n return scoped;\n },\n insertPolyfillHostInCssText: function(selector) {\n return selector.replace(colonHostContextRe, polyfillHostContext).replace(\n colonHostRe, polyfillHost);\n },\n propertiesFromRule: function(rule) {\n var cssText = rule.style.cssText;\n // TODO(sorvell): Safari cssom incorrectly removes quotes from the content\n // property. (https://bugs.webkit.org/show_bug.cgi?id=118045)\n // don't replace attr rules\n if (rule.style.content && !rule.style.content.match(/['\"]+|attr/)) {\n cssText = cssText.replace(/content:[^;]*;/g, 'content: \\'' + \n rule.style.content + '\\';');\n }\n // TODO(sorvell): we can workaround this issue here, but we need a list\n // of troublesome properties to fix https://github.com/Polymer/platform/issues/53\n //\n // inherit rules can be omitted from cssText\n // TODO(sorvell): remove when Blink bug is fixed:\n // https://code.google.com/p/chromium/issues/detail?id=358273\n var style = rule.style;\n for (var i in style) {\n if (style[i] === 'initial') {\n cssText += i + ': initial; ';\n }\n }\n return cssText;\n },\n replaceTextInStyles: function(styles, action) {\n if (styles && action) {\n if (!(styles instanceof Array)) {\n styles = [styles];\n }\n Array.prototype.forEach.call(styles, function(s) {\n s.textContent = action.call(this, s.textContent);\n }, this);\n }\n },\n addCssToDocument: function(cssText, name) {\n if (cssText.match('@import')) {\n addOwnSheet(cssText, name);\n } else {\n addCssToDocument(cssText);\n }\n }\n};\n\nvar selectorRe = /([^{]*)({[\\s\\S]*?})/gim,\n cssCommentRe = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//gim,\n // TODO(sorvell): remove either content or comment\n cssCommentNextSelectorRe = /\\/\\*\\s*@polyfill ([^*]*\\*+([^/*][^*]*\\*+)*\\/)([^{]*?){/gim,\n cssContentNextSelectorRe = /polyfill-next-selector[^}]*content\\:[\\s]*'([^']*)'[^}]*}([^{]*?){/gim,\n // TODO(sorvell): remove either content or comment\n cssCommentRuleRe = /\\/\\*\\s@polyfill-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n cssContentRuleRe = /(polyfill-rule)[^}]*(content\\:[\\s]*'([^']*)'[^;]*;)[^}]*}/gim,\n // TODO(sorvell): remove either content or comment\n cssCommentUnscopedRuleRe = /\\/\\*\\s@polyfill-unscoped-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content\\:[\\s]*'([^']*)'[^;]*;)[^}]*}/gim,\n cssPseudoRe = /::(x-[^\\s{,(]*)/gim,\n cssPartRe = /::part\\(([^)]*)\\)/gim,\n // note: :host pre-processed to -shadowcsshost.\n polyfillHost = '-shadowcsshost',\n // note: :host-context pre-processed to -shadowcsshostcontext.\n polyfillHostContext = '-shadowcsscontext',\n parenSuffix = ')(?:\\\\((' +\n '(?:\\\\([^)(]*\\\\)|[^)(]*)+?' +\n ')\\\\))?([^,{]*)';\n cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'),\n cssColonHostContextRe = new RegExp('(' + polyfillHostContext + parenSuffix, 'gim'),\n selectorReSuffix = '([>\\\\s~+\\[.,{:][\\\\s\\\\S]*)?$',\n colonHostRe = /\\:host/gim,\n colonHostContextRe = /\\:host-context/gim,\n /* host name without combinator */\n polyfillHostNoCombinator = polyfillHost + '-no-combinator',\n polyfillHostRe = new RegExp(polyfillHost, 'gim'),\n polyfillHostContextRe = new RegExp(polyfillHostContext, 'gim'),\n combinatorsRe = [\n /\\^\\^/g,\n /\\^/g,\n /\\/shadow\\//g,\n /\\/shadow-deep\\//g,\n /::shadow/g,\n /\\/deep\\//g\n ];\n\nfunction stylesToCssText(styles, preserveComments) {\n var cssText = '';\n Array.prototype.forEach.call(styles, function(s) {\n cssText += s.textContent + '\\n\\n';\n });\n // strip comments for easier processing\n if (!preserveComments) {\n cssText = cssText.replace(cssCommentRe, '');\n }\n return cssText;\n}\n\nfunction cssTextToStyle(cssText) {\n var style = document.createElement('style');\n style.textContent = cssText;\n return style;\n}\n\nfunction cssToRules(cssText) {\n var style = cssTextToStyle(cssText);\n document.head.appendChild(style);\n var rules = [];\n if (style.sheet) {\n // TODO(sorvell): Firefox throws when accessing the rules of a stylesheet\n // with an @import\n // https://bugzilla.mozilla.org/show_bug.cgi?id=625013\n try {\n rules = style.sheet.cssRules;\n } catch(e) {\n //\n }\n } else {\n console.warn('sheet not found', style);\n }\n style.parentNode.removeChild(style);\n return rules;\n}\n\nvar frame = document.createElement('iframe');\nframe.style.display = 'none';\n\nfunction initFrame() {\n frame.initialized = true;\n document.body.appendChild(frame);\n var doc = frame.contentDocument;\n var base = doc.createElement('base');\n base.href = document.baseURI;\n doc.head.appendChild(base);\n}\n\nfunction inFrame(fn) {\n if (!frame.initialized) {\n initFrame();\n }\n document.body.appendChild(frame);\n fn(frame.contentDocument);\n document.body.removeChild(frame);\n}\n\n// TODO(sorvell): use an iframe if the cssText contains an @import to workaround\n// https://code.google.com/p/chromium/issues/detail?id=345114\nvar isChrome = navigator.userAgent.match('Chrome');\nfunction withCssRules(cssText, callback) {\n if (!callback) {\n return;\n }\n var rules;\n if (cssText.match('@import') && isChrome) {\n var style = cssTextToStyle(cssText);\n inFrame(function(doc) {\n doc.head.appendChild(style.impl);\n rules = style.sheet.cssRules;\n callback(rules);\n });\n } else {\n rules = cssToRules(cssText);\n callback(rules);\n }\n}\n\nfunction rulesToCss(cssRules) {\n for (var i=0, css=[]; i < cssRules.length; i++) {\n css.push(cssRules[i].cssText);\n }\n return css.join('\\n\\n');\n}\n\nfunction addCssToDocument(cssText) {\n if (cssText) {\n getSheet().appendChild(document.createTextNode(cssText));\n }\n}\n\nfunction addOwnSheet(cssText, name) {\n var style = cssTextToStyle(cssText);\n style.setAttribute(name, '');\n style.setAttribute(SHIMMED_ATTRIBUTE, '');\n document.head.appendChild(style);\n}\n\nvar SHIM_ATTRIBUTE = 'shim-shadowdom';\nvar SHIMMED_ATTRIBUTE = 'shim-shadowdom-css';\nvar NO_SHIM_ATTRIBUTE = 'no-shim';\n\nvar sheet;\nfunction getSheet() {\n if (!sheet) {\n sheet = document.createElement(\"style\");\n sheet.setAttribute(SHIMMED_ATTRIBUTE, '');\n sheet[SHIMMED_ATTRIBUTE] = true;\n }\n return sheet;\n}\n\n// add polyfill stylesheet to document\nif (window.ShadowDOMPolyfill) {\n addCssToDocument('style { display: none !important; }\\n');\n var doc = wrap(document);\n var head = doc.querySelector('head');\n head.insertBefore(getSheet(), head.childNodes[0]);\n\n // TODO(sorvell): monkey-patching HTMLImports is abusive;\n // consider a better solution.\n document.addEventListener('DOMContentLoaded', function() {\n var urlResolver = scope.urlResolver;\n \n if (window.HTMLImports && !HTMLImports.useNative) {\n var SHIM_SHEET_SELECTOR = 'link[rel=stylesheet]' +\n '[' + SHIM_ATTRIBUTE + ']';\n var SHIM_STYLE_SELECTOR = 'style[' + SHIM_ATTRIBUTE + ']';\n HTMLImports.importer.documentPreloadSelectors += ',' + SHIM_SHEET_SELECTOR;\n HTMLImports.importer.importsPreloadSelectors += ',' + SHIM_SHEET_SELECTOR;\n\n HTMLImports.parser.documentSelectors = [\n HTMLImports.parser.documentSelectors,\n SHIM_SHEET_SELECTOR,\n SHIM_STYLE_SELECTOR\n ].join(',');\n \n var originalParseGeneric = HTMLImports.parser.parseGeneric;\n\n HTMLImports.parser.parseGeneric = function(elt) {\n if (elt[SHIMMED_ATTRIBUTE]) {\n return;\n }\n var style = elt.__importElement || elt;\n if (!style.hasAttribute(SHIM_ATTRIBUTE)) {\n originalParseGeneric.call(this, elt);\n return;\n }\n if (elt.__resource) {\n style = elt.ownerDocument.createElement('style');\n style.textContent = urlResolver.resolveCssText(\n elt.__resource, elt.href);\n } else {\n urlResolver.resolveStyle(style); \n }\n style.textContent = ShadowCSS.shimStyle(style);\n style.removeAttribute(SHIM_ATTRIBUTE, '');\n style.setAttribute(SHIMMED_ATTRIBUTE, '');\n style[SHIMMED_ATTRIBUTE] = true;\n // place in document\n if (style.parentNode !== head) {\n // replace links in head\n if (elt.parentNode === head) {\n head.replaceChild(style, elt);\n } else {\n head.appendChild(style);\n }\n }\n style.__importParsed = true;\n this.markParsingComplete(elt);\n }\n\n var hasResource = HTMLImports.parser.hasResource;\n HTMLImports.parser.hasResource = function(node) {\n if (node.localName === 'link' && node.rel === 'stylesheet' &&\n node.hasAttribute(SHIM_ATTRIBUTE)) {\n return (node.__resource);\n } else {\n return hasResource.call(this, node);\n }\n }\n\n }\n });\n}\n\n// exports\nscope.ShadowCSS = ShadowCSS;\n\n})(window.Platform);","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\n // poor man's adapter for template.content on various platform scenarios\n window.templateContent = window.templateContent || function(inTemplate) {\n return inTemplate.content;\n };\n\n // so we can call wrap/unwrap without testing for ShadowDOMPolyfill\n\n window.wrap = window.unwrap = function(n){\n return n;\n }\n \n addEventListener('DOMContentLoaded', function() {\n if (CustomElements.useNative === false) {\n var originalCreateShadowRoot = Element.prototype.createShadowRoot;\n Element.prototype.createShadowRoot = function() {\n var root = originalCreateShadowRoot.call(this);\n CustomElements.watchShadow(this);\n return root;\n };\n }\n });\n \n window.templateContent = function(inTemplate) {\n // if MDV exists, it may need to boostrap this template to reveal content\n if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {\n HTMLTemplateElement.bootstrap(inTemplate);\n }\n // fallback when there is no Shadow DOM polyfill, no MDV polyfill, and no\n // native template support\n if (!inTemplate.content && !inTemplate._content) {\n var frag = document.createDocumentFragment();\n while (inTemplate.firstChild) {\n frag.appendChild(inTemplate.firstChild);\n }\n inTemplate._content = frag;\n }\n return inTemplate.content || inTemplate._content;\n };\n\n})();","/* Any copyright is dedicated to the Public Domain.\n * http://creativecommons.org/publicdomain/zero/1.0/ */\n\n(function(scope) {\n 'use strict';\n\n // feature detect for URL constructor\n var hasWorkingUrl = false;\n if (!scope.forceJURL) {\n try {\n var u = new URL('b', 'http://a');\n hasWorkingUrl = u.href === 'http://a/b';\n } catch(e) {}\n }\n\n if (hasWorkingUrl)\n return;\n\n var relative = Object.create(null);\n relative['ftp'] = 21;\n relative['file'] = 0;\n relative['gopher'] = 70;\n relative['http'] = 80;\n relative['https'] = 443;\n relative['ws'] = 80;\n relative['wss'] = 443;\n\n var relativePathDotMapping = Object.create(null);\n relativePathDotMapping['%2e'] = '.';\n relativePathDotMapping['.%2e'] = '..';\n relativePathDotMapping['%2e.'] = '..';\n relativePathDotMapping['%2e%2e'] = '..';\n\n function isRelativeScheme(scheme) {\n return relative[scheme] !== undefined;\n }\n\n function invalid() {\n clear.call(this);\n this._isInvalid = true;\n }\n\n function IDNAToASCII(h) {\n if ('' == h) {\n invalid.call(this)\n }\n // XXX\n return h.toLowerCase()\n }\n\n function percentEscape(c) {\n var unicode = c.charCodeAt(0);\n if (unicode > 0x20 &&\n unicode < 0x7F &&\n // \" # < > ? `\n [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) == -1\n ) {\n return c;\n }\n return encodeURIComponent(c);\n }\n\n function percentEscapeQuery(c) {\n // XXX This actually needs to encode c using encoding and then\n // convert the bytes one-by-one.\n\n var unicode = c.charCodeAt(0);\n if (unicode > 0x20 &&\n unicode < 0x7F &&\n // \" # < > ` (do not escape '?')\n [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) == -1\n ) {\n return c;\n }\n return encodeURIComponent(c);\n }\n\n var EOF = undefined,\n ALPHA = /[a-zA-Z]/,\n ALPHANUMERIC = /[a-zA-Z0-9\\+\\-\\.]/;\n\n function parse(input, stateOverride, base) {\n function err(message) {\n errors.push(message)\n }\n\n var state = stateOverride || 'scheme start',\n cursor = 0,\n buffer = '',\n seenAt = false,\n seenBracket = false,\n errors = [];\n\n loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) {\n var c = input[cursor];\n switch (state) {\n case 'scheme start':\n if (c && ALPHA.test(c)) {\n buffer += c.toLowerCase(); // ASCII-safe\n state = 'scheme';\n } else if (!stateOverride) {\n buffer = '';\n state = 'no scheme';\n continue;\n } else {\n err('Invalid scheme.');\n break loop;\n }\n break;\n\n case 'scheme':\n if (c && ALPHANUMERIC.test(c)) {\n buffer += c.toLowerCase(); // ASCII-safe\n } else if (':' == c) {\n this._scheme = buffer;\n buffer = '';\n if (stateOverride) {\n break loop;\n }\n if (isRelativeScheme(this._scheme)) {\n this._isRelative = true;\n }\n if ('file' == this._scheme) {\n state = 'relative';\n } else if (this._isRelative && base && base._scheme == this._scheme) {\n state = 'relative or authority';\n } else if (this._isRelative) {\n state = 'authority first slash';\n } else {\n state = 'scheme data';\n }\n } else if (!stateOverride) {\n buffer = '';\n cursor = 0;\n state = 'no scheme';\n continue;\n } else if (EOF == c) {\n break loop;\n } else {\n err('Code point not allowed in scheme: ' + c)\n break loop;\n }\n break;\n\n case 'scheme data':\n if ('?' == c) {\n query = '?';\n state = 'query';\n } else if ('#' == c) {\n this._fragment = '#';\n state = 'fragment';\n } else {\n // XXX error handling\n if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n this._schemeData += percentEscape(c);\n }\n }\n break;\n\n case 'no scheme':\n if (!base || !(isRelativeScheme(base._scheme))) {\n err('Missing scheme.');\n invalid.call(this);\n } else {\n state = 'relative';\n continue;\n }\n break;\n\n case 'relative or authority':\n if ('/' == c && '/' == input[cursor+1]) {\n state = 'authority ignore slashes';\n } else {\n err('Expected /, got: ' + c);\n state = 'relative';\n continue\n }\n break;\n\n case 'relative':\n this._isRelative = true;\n if ('file' != this._scheme)\n this._scheme = base._scheme;\n if (EOF == c) {\n this._host = base._host;\n this._port = base._port;\n this._path = base._path.slice();\n this._query = base._query;\n break loop;\n } else if ('/' == c || '\\\\' == c) {\n if ('\\\\' == c)\n err('\\\\ is an invalid code point.');\n state = 'relative slash';\n } else if ('?' == c) {\n this._host = base._host;\n this._port = base._port;\n this._path = base._path.slice();\n this._query = '?';\n state = 'query';\n } else if ('#' == c) {\n this._host = base._host;\n this._port = base._port;\n this._path = base._path.slice();\n this._query = base._query;\n this._fragment = '#';\n state = 'fragment';\n } else {\n var nextC = input[cursor+1]\n var nextNextC = input[cursor+2]\n if (\n 'file' != this._scheme || !ALPHA.test(c) ||\n (nextC != ':' && nextC != '|') ||\n (EOF != nextNextC && '/' != nextNextC && '\\\\' != nextNextC && '?' != nextNextC && '#' != nextNextC)) {\n this._host = base._host;\n this._port = base._port;\n this._path = base._path.slice();\n this._path.pop();\n }\n state = 'relative path';\n continue;\n }\n break;\n\n case 'relative slash':\n if ('/' == c || '\\\\' == c) {\n if ('\\\\' == c) {\n err('\\\\ is an invalid code point.');\n }\n if ('file' == this._scheme) {\n state = 'file host';\n } else {\n state = 'authority ignore slashes';\n }\n } else {\n if ('file' != this._scheme) {\n this._host = base._host;\n this._port = base._port;\n }\n state = 'relative path';\n continue;\n }\n break;\n\n case 'authority first slash':\n if ('/' == c) {\n state = 'authority second slash';\n } else {\n err(\"Expected '/', got: \" + c);\n state = 'authority ignore slashes';\n continue;\n }\n break;\n\n case 'authority second slash':\n state = 'authority ignore slashes';\n if ('/' != c) {\n err(\"Expected '/', got: \" + c);\n continue;\n }\n break;\n\n case 'authority ignore slashes':\n if ('/' != c && '\\\\' != c) {\n state = 'authority';\n continue;\n } else {\n err('Expected authority, got: ' + c);\n }\n break;\n\n case 'authority':\n if ('@' == c) {\n if (seenAt) {\n err('@ already seen.');\n buffer += '%40';\n }\n seenAt = true;\n for (var i = 0; i < buffer.length; i++) {\n var cp = buffer[i];\n if ('\\t' == cp || '\\n' == cp || '\\r' == cp) {\n err('Invalid whitespace in authority.');\n continue;\n }\n // XXX check URL code points\n if (':' == cp && null === this._password) {\n this._password = '';\n continue;\n }\n var tempC = percentEscape(cp);\n (null !== this._password) ? this._password += tempC : this._username += tempC;\n }\n buffer = '';\n } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n cursor -= buffer.length;\n buffer = '';\n state = 'host';\n continue;\n } else {\n buffer += c;\n }\n break;\n\n case 'file host':\n if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ':' || buffer[1] == '|')) {\n state = 'relative path';\n } else if (buffer.length == 0) {\n state = 'relative path start';\n } else {\n this._host = IDNAToASCII.call(this, buffer);\n buffer = '';\n state = 'relative path start';\n }\n continue;\n } else if ('\\t' == c || '\\n' == c || '\\r' == c) {\n err('Invalid whitespace in file host.');\n } else {\n buffer += c;\n }\n break;\n\n case 'host':\n case 'hostname':\n if (':' == c && !seenBracket) {\n // XXX host parsing\n this._host = IDNAToASCII.call(this, buffer);\n buffer = '';\n state = 'port';\n if ('hostname' == stateOverride) {\n break loop;\n }\n } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n this._host = IDNAToASCII.call(this, buffer);\n buffer = '';\n state = 'relative path start';\n if (stateOverride) {\n break loop;\n }\n continue;\n } else if ('\\t' != c && '\\n' != c && '\\r' != c) {\n if ('[' == c) {\n seenBracket = true;\n } else if (']' == c) {\n seenBracket = false;\n }\n buffer += c;\n } else {\n err('Invalid code point in host/hostname: ' + c);\n }\n break;\n\n case 'port':\n if (/[0-9]/.test(c)) {\n buffer += c;\n } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c || stateOverride) {\n if ('' != buffer) {\n var temp = parseInt(buffer, 10);\n if (temp != relative[this._scheme]) {\n this._port = temp + '';\n }\n buffer = '';\n }\n if (stateOverride) {\n break loop;\n }\n state = 'relative path start';\n continue;\n } else if ('\\t' == c || '\\n' == c || '\\r' == c) {\n err('Invalid code point in port: ' + c);\n } else {\n invalid.call(this);\n }\n break;\n\n case 'relative path start':\n if ('\\\\' == c)\n err(\"'\\\\' not allowed in path.\");\n state = 'relative path';\n if ('/' != c && '\\\\' != c) {\n continue;\n }\n break;\n\n case 'relative path':\n if (EOF == c || '/' == c || '\\\\' == c || (!stateOverride && ('?' == c || '#' == c))) {\n if ('\\\\' == c) {\n err('\\\\ not allowed in relative path.');\n }\n var tmp;\n if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {\n buffer = tmp;\n }\n if ('..' == buffer) {\n this._path.pop();\n if ('/' != c && '\\\\' != c) {\n this._path.push('');\n }\n } else if ('.' == buffer && '/' != c && '\\\\' != c) {\n this._path.push('');\n } else if ('.' != buffer) {\n if ('file' == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == '|') {\n buffer = buffer[0] + ':';\n }\n this._path.push(buffer);\n }\n buffer = '';\n if ('?' == c) {\n this._query = '?';\n state = 'query';\n } else if ('#' == c) {\n this._fragment = '#';\n state = 'fragment';\n }\n } else if ('\\t' != c && '\\n' != c && '\\r' != c) {\n buffer += percentEscape(c);\n }\n break;\n\n case 'query':\n if (!stateOverride && '#' == c) {\n this._fragment = '#';\n state = 'fragment';\n } else if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n this._query += percentEscapeQuery(c);\n }\n break;\n\n case 'fragment':\n if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n this._fragment += c;\n }\n break;\n }\n\n cursor++;\n }\n }\n\n function clear() {\n this._scheme = '';\n this._schemeData = '';\n this._username = '';\n this._password = null;\n this._host = '';\n this._port = '';\n this._path = [];\n this._query = '';\n this._fragment = '';\n this._isInvalid = false;\n this._isRelative = false;\n }\n\n // Does not process domain names or IP addresses.\n // Does not handle encoding for the query parameter.\n function jURL(url, base /* , encoding */) {\n if (base !== undefined && !(base instanceof jURL))\n base = new jURL(String(base));\n\n this._url = url;\n clear.call(this);\n\n var input = url.replace(/^[ \\t\\r\\n\\f]+|[ \\t\\r\\n\\f]+$/g, '');\n // encoding = encoding || 'utf-8'\n\n parse.call(this, input, null, base);\n }\n\n jURL.prototype = {\n get href() {\n if (this._isInvalid)\n return this._url;\n\n var authority = '';\n if ('' != this._username || null != this._password) {\n authority = this._username +\n (null != this._password ? ':' + this._password : '') + '@';\n }\n\n return this.protocol +\n (this._isRelative ? '//' + authority + this.host : '') +\n this.pathname + this._query + this._fragment;\n },\n set href(href) {\n clear.call(this);\n parse.call(this, href);\n },\n\n get protocol() {\n return this._scheme + ':';\n },\n set protocol(protocol) {\n if (this._isInvalid)\n return;\n parse.call(this, protocol + ':', 'scheme start');\n },\n\n get host() {\n return this._isInvalid ? '' : this._port ?\n this._host + ':' + this._port : this._host;\n },\n set host(host) {\n if (this._isInvalid || !this._isRelative)\n return;\n parse.call(this, host, 'host');\n },\n\n get hostname() {\n return this._host;\n },\n set hostname(hostname) {\n if (this._isInvalid || !this._isRelative)\n return;\n parse.call(this, hostname, 'hostname');\n },\n\n get port() {\n return this._port;\n },\n set port(port) {\n if (this._isInvalid || !this._isRelative)\n return;\n parse.call(this, port, 'port');\n },\n\n get pathname() {\n return this._isInvalid ? '' : this._isRelative ?\n '/' + this._path.join('/') : this._schemeData;\n },\n set pathname(pathname) {\n if (this._isInvalid || !this._isRelative)\n return;\n this._path = [];\n parse.call(this, pathname, 'relative path start');\n },\n\n get search() {\n return this._isInvalid || !this._query || '?' == this._query ?\n '' : this._query;\n },\n set search(search) {\n if (this._isInvalid || !this._isRelative)\n return;\n this._query = '?';\n if ('?' == search[0])\n search = search.slice(1);\n parse.call(this, search, 'query');\n },\n\n get hash() {\n return this._isInvalid || !this._fragment || '#' == this._fragment ?\n '' : this._fragment;\n },\n set hash(hash) {\n if (this._isInvalid)\n return;\n this._fragment = '#';\n if ('#' == hash[0])\n hash = hash.slice(1);\n parse.call(this, hash, 'fragment');\n }\n };\n\n scope.URL = jURL;\n\n})(window);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n// Old versions of iOS do not have bind.\n\nif (!Function.prototype.bind) {\n Function.prototype.bind = function(scope) {\n var self = this;\n var args = Array.prototype.slice.call(arguments, 1);\n return function() {\n var args2 = args.slice();\n args2.push.apply(args2, arguments);\n return self.apply(scope, args2);\n };\n };\n}\n\n// mixin\n\n// copy all properties from inProps (et al) to inObj\nfunction mixin(inObj/*, inProps, inMoreProps, ...*/) {\n var obj = inObj || {};\n for (var i = 1; i < arguments.length; i++) {\n var p = arguments[i];\n try {\n for (var n in p) {\n copyProperty(n, p, obj);\n }\n } catch(x) {\n }\n }\n return obj;\n}\n\n// copy property inName from inSource object to inTarget object\nfunction copyProperty(inName, inSource, inTarget) {\n var pd = getPropertyDescriptor(inSource, inName);\n Object.defineProperty(inTarget, inName, pd);\n}\n\n// get property descriptor for inName on inObject, even if\n// inName exists on some link in inObject's prototype chain\nfunction getPropertyDescriptor(inObject, inName) {\n if (inObject) {\n var pd = Object.getOwnPropertyDescriptor(inObject, inName);\n return pd || getPropertyDescriptor(Object.getPrototypeOf(inObject), inName);\n }\n}\n\n// export\n\nscope.mixin = mixin;\n\n})(window.Platform);","// Copyright 2011 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(scope) {\n\n 'use strict';\n\n // polyfill DOMTokenList\n // * add/remove: allow these methods to take multiple classNames\n // * toggle: add a 2nd argument which forces the given state rather\n // than toggling.\n\n var add = DOMTokenList.prototype.add;\n var remove = DOMTokenList.prototype.remove;\n DOMTokenList.prototype.add = function() {\n for (var i = 0; i < arguments.length; i++) {\n add.call(this, arguments[i]);\n }\n };\n DOMTokenList.prototype.remove = function() {\n for (var i = 0; i < arguments.length; i++) {\n remove.call(this, arguments[i]);\n }\n };\n DOMTokenList.prototype.toggle = function(name, bool) {\n if (arguments.length == 1) {\n bool = !this.contains(name);\n }\n bool ? this.add(name) : this.remove(name);\n };\n DOMTokenList.prototype.switch = function(oldName, newName) {\n oldName && this.remove(oldName);\n newName && this.add(newName);\n };\n\n // add array() to NodeList, NamedNodeMap, HTMLCollection\n\n var ArraySlice = function() {\n return Array.prototype.slice.call(this);\n };\n\n var namedNodeMap = (window.NamedNodeMap || window.MozNamedAttrMap || {});\n\n NodeList.prototype.array = ArraySlice;\n namedNodeMap.prototype.array = ArraySlice;\n HTMLCollection.prototype.array = ArraySlice;\n\n // polyfill performance.now\n\n if (!window.performance) {\n var start = Date.now();\n // only at millisecond precision\n window.performance = {now: function(){ return Date.now() - start }};\n }\n\n // polyfill for requestAnimationFrame\n\n if (!window.requestAnimationFrame) {\n window.requestAnimationFrame = (function() {\n var nativeRaf = window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame;\n\n return nativeRaf ?\n function(callback) {\n return nativeRaf(function() {\n callback(performance.now());\n });\n } :\n function( callback ){\n return window.setTimeout(callback, 1000 / 60);\n };\n })();\n }\n\n if (!window.cancelAnimationFrame) {\n window.cancelAnimationFrame = (function() {\n return window.webkitCancelAnimationFrame ||\n window.mozCancelAnimationFrame ||\n function(id) {\n clearTimeout(id);\n };\n })();\n }\n\n // utility\n\n function createDOM(inTagOrNode, inHTML, inAttrs) {\n var dom = typeof inTagOrNode == 'string' ?\n document.createElement(inTagOrNode) : inTagOrNode.cloneNode(true);\n dom.innerHTML = inHTML;\n if (inAttrs) {\n for (var n in inAttrs) {\n dom.setAttribute(n, inAttrs[n]);\n }\n }\n return dom;\n }\n // Make a stub for Polymer() for polyfill purposes; under the HTMLImports\n // polyfill, scripts in the main document run before imports. That means\n // if (1) polymer is imported and (2) Polymer() is called in the main document\n // in a script after the import, 2 occurs before 1. We correct this here\n // by specfiically patching Polymer(); this is not necessary under native\n // HTMLImports.\n var elementDeclarations = [];\n\n var polymerStub = function(name, dictionary) {\n elementDeclarations.push(arguments);\n }\n window.Polymer = polymerStub;\n\n // deliver queued delcarations\n scope.deliverDeclarations = function() {\n scope.deliverDeclarations = function() {\n throw 'Possible attempt to load Polymer twice';\n };\n return elementDeclarations;\n }\n\n // Once DOMContent has loaded, any main document scripts that depend on\n // Polymer() should have run. Calling Polymer() now is an error until\n // polymer is imported.\n window.addEventListener('DOMContentLoaded', function() {\n if (window.Polymer === polymerStub) {\n window.Polymer = function() {\n console.error('You tried to use polymer without loading it first. To ' +\n 'load polymer, ');\n };\n }\n });\n\n // exports\n scope.createDOM = createDOM;\n\n})(window.Platform);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// poor man's adapter for template.content on various platform scenarios\nwindow.templateContent = window.templateContent || function(inTemplate) {\n return inTemplate.content;\n};","(function(scope) {\n \n scope = scope || (window.Inspector = {});\n \n var inspector;\n\n window.sinspect = function(inNode, inProxy) {\n if (!inspector) {\n inspector = window.open('', 'ShadowDOM Inspector', null, true);\n inspector.document.write(inspectorHTML);\n //inspector.document.close();\n inspector.api = {\n shadowize: shadowize\n };\n }\n inspect(inNode || wrap(document.body), inProxy);\n };\n\n var inspectorHTML = [\n '',\n '',\n ' ',\n ' ShadowDOM Inspector',\n ' ',\n ' ',\n ' ',\n '
            ',\n '
          ',\n '
          ',\n ' ',\n ''\n ].join('\\n');\n \n var crumbs = [];\n\n var displayCrumbs = function() {\n // alias our document\n var d = inspector.document;\n // get crumbbar\n var cb = d.querySelector('#crumbs');\n // clear crumbs\n cb.textContent = '';\n // build new crumbs\n for (var i=0, c; c=crumbs[i]; i++) {\n var a = d.createElement('a');\n a.href = '#';\n a.textContent = c.localName;\n a.idx = i;\n a.onclick = function(event) {\n var c;\n while (crumbs.length > this.idx) {\n c = crumbs.pop();\n }\n inspect(c.shadow || c, c);\n event.preventDefault();\n };\n cb.appendChild(d.createElement('li')).appendChild(a);\n }\n };\n\n var inspect = function(inNode, inProxy) {\n // alias our document\n var d = inspector.document;\n // reset list of drillable nodes\n drillable = [];\n // memoize our crumb proxy\n var proxy = inProxy || inNode;\n crumbs.push(proxy);\n // update crumbs\n displayCrumbs();\n // reflect local tree\n d.body.querySelector('#tree').innerHTML =\n '
          ' + output(inNode, inNode.childNodes) + '
          ';\n };\n\n var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n\n var blacklisted = {STYLE:1, SCRIPT:1, \"#comment\": 1, TEMPLATE: 1};\n var blacklist = function(inNode) {\n return blacklisted[inNode.nodeName];\n };\n\n var output = function(inNode, inChildNodes, inIndent) {\n if (blacklist(inNode)) {\n return '';\n }\n var indent = inIndent || '';\n if (inNode.localName || inNode.nodeType == 11) {\n var name = inNode.localName || 'shadow-root';\n //inChildNodes = ShadowDOM.localNodes(inNode);\n var info = indent + describe(inNode);\n // if only textNodes\n // TODO(sjmiles): make correct for ShadowDOM\n /*if (!inNode.children.length && inNode.localName !== 'content' && inNode.localName !== 'shadow') {\n info += catTextContent(inChildNodes);\n } else*/ {\n // TODO(sjmiles): native has no reference to its projection\n if (name == 'content' /*|| name == 'shadow'*/) {\n inChildNodes = inNode.getDistributedNodes();\n }\n info += '
          ';\n var ind = indent + '  ';\n forEach(inChildNodes, function(n) {\n info += output(n, n.childNodes, ind);\n });\n info += indent;\n }\n if (!({br:1}[name])) {\n info += '</' + name + '>';\n info += '
          ';\n }\n } else {\n var text = inNode.textContent.trim();\n info = text ? indent + '\"' + text + '\"' + '
          ' : '';\n }\n return info;\n };\n\n var catTextContent = function(inChildNodes) {\n var info = '';\n forEach(inChildNodes, function(n) {\n info += n.textContent.trim();\n });\n return info;\n };\n\n var drillable = [];\n\n var describe = function(inNode) {\n var tag = '' + '<';\n var name = inNode.localName || 'shadow-root';\n if (inNode.webkitShadowRoot || inNode.shadowRoot) {\n tag += ' ';\n drillable.push(inNode);\n } else {\n tag += name || 'shadow-root';\n }\n if (inNode.attributes) {\n forEach(inNode.attributes, function(a) {\n tag += ' ' + a.name + (a.value ? '=\"' + a.value + '\"' : '');\n });\n }\n tag += '>'+ '';\n return tag;\n };\n\n // remote api\n\n shadowize = function() {\n var idx = Number(this.attributes.idx.value);\n //alert(idx);\n var node = drillable[idx];\n if (node) {\n inspect(node.webkitShadowRoot || node.shadowRoot, node)\n } else {\n console.log(\"bad shadowize node\");\n console.dir(this);\n }\n };\n \n // export\n \n scope.output = output;\n \n})(window.Inspector);\n\n\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\n // TODO(sorvell): It's desireable to provide a default stylesheet \n // that's convenient for styling unresolved elements, but\n // it's cumbersome to have to include this manually in every page.\n // It would make sense to put inside some HTMLImport but \n // the HTMLImports polyfill does not allow loading of stylesheets \n // that block rendering. Therefore this injection is tolerated here.\n\n var style = document.createElement('style');\n style.textContent = ''\n + 'body {'\n + 'transition: opacity ease-in 0.2s;' \n + ' } \\n'\n + 'body[unresolved] {'\n + 'opacity: 0; display: block; overflow: hidden;' \n + ' } \\n'\n ;\n var head = document.querySelector('head');\n head.insertBefore(style, head.firstChild);\n\n})(Platform);\n","(function(scope) {\n\n function withDependencies(task, depends) {\n depends = depends || [];\n if (!depends.map) {\n depends = [depends];\n }\n return task.apply(this, depends.map(marshal));\n }\n\n function module(name, dependsOrFactory, moduleFactory) {\n var module;\n switch (arguments.length) {\n case 0:\n return;\n case 1:\n module = null;\n break;\n case 2:\n module = dependsOrFactory.apply(this);\n break;\n default:\n module = withDependencies(moduleFactory, dependsOrFactory);\n break;\n }\n modules[name] = module;\n };\n\n function marshal(name) {\n return modules[name];\n }\n\n var modules = {};\n\n function using(depends, task) {\n HTMLImports.whenImportsReady(function() {\n withDependencies(task, depends);\n });\n };\n\n // exports\n\n scope.marshal = marshal;\n scope.module = module;\n scope.using = using;\n\n})(window);","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\nvar iterations = 0;\nvar callbacks = [];\nvar twiddle = document.createTextNode('');\n\nfunction endOfMicrotask(callback) {\n twiddle.textContent = iterations++;\n callbacks.push(callback);\n}\n\nfunction atEndOfMicrotask() {\n while (callbacks.length) {\n callbacks.shift()();\n }\n}\n\nnew (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask)\n .observe(twiddle, {characterData: true})\n ;\n\n// exports\n\nscope.endOfMicrotask = endOfMicrotask;\n\n})(Platform);\n\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\nvar urlResolver = {\n resolveDom: function(root, url) {\n url = url || root.ownerDocument.baseURI;\n this.resolveAttributes(root, url);\n this.resolveStyles(root, url);\n // handle template.content\n var templates = root.querySelectorAll('template');\n if (templates) {\n for (var i = 0, l = templates.length, t; (i < l) && (t = templates[i]); i++) {\n if (t.content) {\n this.resolveDom(t.content, url);\n }\n }\n }\n },\n resolveTemplate: function(template) {\n this.resolveDom(template.content, template.ownerDocument.baseURI);\n },\n resolveStyles: function(root, url) {\n var styles = root.querySelectorAll('style');\n if (styles) {\n for (var i = 0, l = styles.length, s; (i < l) && (s = styles[i]); i++) {\n this.resolveStyle(s, url);\n }\n }\n },\n resolveStyle: function(style, url) {\n url = url || style.ownerDocument.baseURI;\n style.textContent = this.resolveCssText(style.textContent, url);\n },\n resolveCssText: function(cssText, baseUrl) {\n cssText = replaceUrlsInCssText(cssText, baseUrl, CSS_URL_REGEXP);\n return replaceUrlsInCssText(cssText, baseUrl, CSS_IMPORT_REGEXP);\n },\n resolveAttributes: function(root, url) {\n if (root.hasAttributes && root.hasAttributes()) {\n this.resolveElementAttributes(root, url);\n }\n // search for attributes that host urls\n var nodes = root && root.querySelectorAll(URL_ATTRS_SELECTOR);\n if (nodes) {\n for (var i = 0, l = nodes.length, n; (i < l) && (n = nodes[i]); i++) {\n this.resolveElementAttributes(n, url);\n }\n }\n },\n resolveElementAttributes: function(node, url) {\n url = url || node.ownerDocument.baseURI;\n URL_ATTRS.forEach(function(v) {\n var attr = node.attributes[v];\n var value = attr && attr.value;\n var replacement;\n if (value && value.search(URL_TEMPLATE_SEARCH) < 0) {\n if (v === 'style') {\n replacement = replaceUrlsInCssText(value, url, CSS_URL_REGEXP);\n } else {\n replacement = resolveRelativeUrl(url, value);\n }\n attr.value = replacement;\n }\n });\n }\n};\n\nvar CSS_URL_REGEXP = /(url\\()([^)]*)(\\))/g;\nvar CSS_IMPORT_REGEXP = /(@import[\\s]+(?!url\\())([^;]*)(;)/g;\nvar URL_ATTRS = ['href', 'src', 'action', 'style'];\nvar URL_ATTRS_SELECTOR = '[' + URL_ATTRS.join('],[') + ']';\nvar URL_TEMPLATE_SEARCH = '{{.*}}';\n\nfunction replaceUrlsInCssText(cssText, baseUrl, regexp) {\n return cssText.replace(regexp, function(m, pre, url, post) {\n var urlPath = url.replace(/[\"']/g, '');\n urlPath = resolveRelativeUrl(baseUrl, urlPath);\n return pre + '\\'' + urlPath + '\\'' + post;\n });\n}\n\nfunction resolveRelativeUrl(baseUrl, url) {\n var u = new URL(url, baseUrl);\n return makeDocumentRelPath(u.href);\n}\n\nfunction makeDocumentRelPath(url) {\n var root = document.location;\n var u = new URL(url, root);\n if (u.host === root.host && u.port === root.port &&\n u.protocol === root.protocol) {\n return makeRelPath(root.pathname, u.pathname);\n } else {\n return url;\n }\n}\n\n// make a relative path from source to target\nfunction makeRelPath(source, target) {\n var s = source.split('/');\n var t = target.split('/');\n while (s.length && s[0] === t[0]){\n s.shift();\n t.shift();\n }\n for (var i = 0, l = s.length - 1; i < l; i++) {\n t.unshift('..');\n }\n return t.join('/');\n}\n\n// exports\nscope.urlResolver = urlResolver;\n\n})(Platform);\n","/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(global) {\n\n var registrationsTable = new WeakMap();\n\n // We use setImmediate or postMessage for our future callback.\n var setImmediate = window.msSetImmediate;\n\n // Use post message to emulate setImmediate.\n if (!setImmediate) {\n var setImmediateQueue = [];\n var sentinel = String(Math.random());\n window.addEventListener('message', function(e) {\n if (e.data === sentinel) {\n var queue = setImmediateQueue;\n setImmediateQueue = [];\n queue.forEach(function(func) {\n func();\n });\n }\n });\n setImmediate = function(func) {\n setImmediateQueue.push(func);\n window.postMessage(sentinel, '*');\n };\n }\n\n // This is used to ensure that we never schedule 2 callas to setImmediate\n var isScheduled = false;\n\n // Keep track of observers that needs to be notified next time.\n var scheduledObservers = [];\n\n /**\n * Schedules |dispatchCallback| to be called in the future.\n * @param {MutationObserver} observer\n */\n function scheduleCallback(observer) {\n scheduledObservers.push(observer);\n if (!isScheduled) {\n isScheduled = true;\n setImmediate(dispatchCallbacks);\n }\n }\n\n function wrapIfNeeded(node) {\n return window.ShadowDOMPolyfill &&\n window.ShadowDOMPolyfill.wrapIfNeeded(node) ||\n node;\n }\n\n function dispatchCallbacks() {\n // http://dom.spec.whatwg.org/#mutation-observers\n\n isScheduled = false; // Used to allow a new setImmediate call above.\n\n var observers = scheduledObservers;\n scheduledObservers = [];\n // Sort observers based on their creation UID (incremental).\n observers.sort(function(o1, o2) {\n return o1.uid_ - o2.uid_;\n });\n\n var anyNonEmpty = false;\n observers.forEach(function(observer) {\n\n // 2.1, 2.2\n var queue = observer.takeRecords();\n // 2.3. Remove all transient registered observers whose observer is mo.\n removeTransientObserversFor(observer);\n\n // 2.4\n if (queue.length) {\n observer.callback_(queue, observer);\n anyNonEmpty = true;\n }\n });\n\n // 3.\n if (anyNonEmpty)\n dispatchCallbacks();\n }\n\n function removeTransientObserversFor(observer) {\n observer.nodes_.forEach(function(node) {\n var registrations = registrationsTable.get(node);\n if (!registrations)\n return;\n registrations.forEach(function(registration) {\n if (registration.observer === observer)\n registration.removeTransientObservers();\n });\n });\n }\n\n /**\n * This function is used for the \"For each registered observer observer (with\n * observer's options as options) in target's list of registered observers,\n * run these substeps:\" and the \"For each ancestor ancestor of target, and for\n * each registered observer observer (with options options) in ancestor's list\n * of registered observers, run these substeps:\" part of the algorithms. The\n * |options.subtree| is checked to ensure that the callback is called\n * correctly.\n *\n * @param {Node} target\n * @param {function(MutationObserverInit):MutationRecord} callback\n */\n function forEachAncestorAndObserverEnqueueRecord(target, callback) {\n for (var node = target; node; node = node.parentNode) {\n var registrations = registrationsTable.get(node);\n\n if (registrations) {\n for (var j = 0; j < registrations.length; j++) {\n var registration = registrations[j];\n var options = registration.options;\n\n // Only target ignores subtree.\n if (node !== target && !options.subtree)\n continue;\n\n var record = callback(options);\n if (record)\n registration.enqueue(record);\n }\n }\n }\n }\n\n var uidCounter = 0;\n\n /**\n * The class that maps to the DOM MutationObserver interface.\n * @param {Function} callback.\n * @constructor\n */\n function JsMutationObserver(callback) {\n this.callback_ = callback;\n this.nodes_ = [];\n this.records_ = [];\n this.uid_ = ++uidCounter;\n }\n\n JsMutationObserver.prototype = {\n observe: function(target, options) {\n target = wrapIfNeeded(target);\n\n // 1.1\n if (!options.childList && !options.attributes && !options.characterData ||\n\n // 1.2\n options.attributeOldValue && !options.attributes ||\n\n // 1.3\n options.attributeFilter && options.attributeFilter.length &&\n !options.attributes ||\n\n // 1.4\n options.characterDataOldValue && !options.characterData) {\n\n throw new SyntaxError();\n }\n\n var registrations = registrationsTable.get(target);\n if (!registrations)\n registrationsTable.set(target, registrations = []);\n\n // 2\n // If target's list of registered observers already includes a registered\n // observer associated with the context object, replace that registered\n // observer's options with options.\n var registration;\n for (var i = 0; i < registrations.length; i++) {\n if (registrations[i].observer === this) {\n registration = registrations[i];\n registration.removeListeners();\n registration.options = options;\n break;\n }\n }\n\n // 3.\n // Otherwise, add a new registered observer to target's list of registered\n // observers with the context object as the observer and options as the\n // options, and add target to context object's list of nodes on which it\n // is registered.\n if (!registration) {\n registration = new Registration(this, target, options);\n registrations.push(registration);\n this.nodes_.push(target);\n }\n\n registration.addListeners();\n },\n\n disconnect: function() {\n this.nodes_.forEach(function(node) {\n var registrations = registrationsTable.get(node);\n for (var i = 0; i < registrations.length; i++) {\n var registration = registrations[i];\n if (registration.observer === this) {\n registration.removeListeners();\n registrations.splice(i, 1);\n // Each node can only have one registered observer associated with\n // this observer.\n break;\n }\n }\n }, this);\n this.records_ = [];\n },\n\n takeRecords: function() {\n var copyOfRecords = this.records_;\n this.records_ = [];\n return copyOfRecords;\n }\n };\n\n /**\n * @param {string} type\n * @param {Node} target\n * @constructor\n */\n function MutationRecord(type, target) {\n this.type = type;\n this.target = target;\n this.addedNodes = [];\n this.removedNodes = [];\n this.previousSibling = null;\n this.nextSibling = null;\n this.attributeName = null;\n this.attributeNamespace = null;\n this.oldValue = null;\n }\n\n function copyMutationRecord(original) {\n var record = new MutationRecord(original.type, original.target);\n record.addedNodes = original.addedNodes.slice();\n record.removedNodes = original.removedNodes.slice();\n record.previousSibling = original.previousSibling;\n record.nextSibling = original.nextSibling;\n record.attributeName = original.attributeName;\n record.attributeNamespace = original.attributeNamespace;\n record.oldValue = original.oldValue;\n return record;\n };\n\n // We keep track of the two (possibly one) records used in a single mutation.\n var currentRecord, recordWithOldValue;\n\n /**\n * Creates a record without |oldValue| and caches it as |currentRecord| for\n * later use.\n * @param {string} oldValue\n * @return {MutationRecord}\n */\n function getRecord(type, target) {\n return currentRecord = new MutationRecord(type, target);\n }\n\n /**\n * Gets or creates a record with |oldValue| based in the |currentRecord|\n * @param {string} oldValue\n * @return {MutationRecord}\n */\n function getRecordWithOldValue(oldValue) {\n if (recordWithOldValue)\n return recordWithOldValue;\n recordWithOldValue = copyMutationRecord(currentRecord);\n recordWithOldValue.oldValue = oldValue;\n return recordWithOldValue;\n }\n\n function clearRecords() {\n currentRecord = recordWithOldValue = undefined;\n }\n\n /**\n * @param {MutationRecord} record\n * @return {boolean} Whether the record represents a record from the current\n * mutation event.\n */\n function recordRepresentsCurrentMutation(record) {\n return record === recordWithOldValue || record === currentRecord;\n }\n\n /**\n * Selects which record, if any, to replace the last record in the queue.\n * This returns |null| if no record should be replaced.\n *\n * @param {MutationRecord} lastRecord\n * @param {MutationRecord} newRecord\n * @param {MutationRecord}\n */\n function selectRecord(lastRecord, newRecord) {\n if (lastRecord === newRecord)\n return lastRecord;\n\n // Check if the the record we are adding represents the same record. If\n // so, we keep the one with the oldValue in it.\n if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord))\n return recordWithOldValue;\n\n return null;\n }\n\n /**\n * Class used to represent a registered observer.\n * @param {MutationObserver} observer\n * @param {Node} target\n * @param {MutationObserverInit} options\n * @constructor\n */\n function Registration(observer, target, options) {\n this.observer = observer;\n this.target = target;\n this.options = options;\n this.transientObservedNodes = [];\n }\n\n Registration.prototype = {\n enqueue: function(record) {\n var records = this.observer.records_;\n var length = records.length;\n\n // There are cases where we replace the last record with the new record.\n // For example if the record represents the same mutation we need to use\n // the one with the oldValue. If we get same record (this can happen as we\n // walk up the tree) we ignore the new record.\n if (records.length > 0) {\n var lastRecord = records[length - 1];\n var recordToReplaceLast = selectRecord(lastRecord, record);\n if (recordToReplaceLast) {\n records[length - 1] = recordToReplaceLast;\n return;\n }\n } else {\n scheduleCallback(this.observer);\n }\n\n records[length] = record;\n },\n\n addListeners: function() {\n this.addListeners_(this.target);\n },\n\n addListeners_: function(node) {\n var options = this.options;\n if (options.attributes)\n node.addEventListener('DOMAttrModified', this, true);\n\n if (options.characterData)\n node.addEventListener('DOMCharacterDataModified', this, true);\n\n if (options.childList)\n node.addEventListener('DOMNodeInserted', this, true);\n\n if (options.childList || options.subtree)\n node.addEventListener('DOMNodeRemoved', this, true);\n },\n\n removeListeners: function() {\n this.removeListeners_(this.target);\n },\n\n removeListeners_: function(node) {\n var options = this.options;\n if (options.attributes)\n node.removeEventListener('DOMAttrModified', this, true);\n\n if (options.characterData)\n node.removeEventListener('DOMCharacterDataModified', this, true);\n\n if (options.childList)\n node.removeEventListener('DOMNodeInserted', this, true);\n\n if (options.childList || options.subtree)\n node.removeEventListener('DOMNodeRemoved', this, true);\n },\n\n /**\n * Adds a transient observer on node. The transient observer gets removed\n * next time we deliver the change records.\n * @param {Node} node\n */\n addTransientObserver: function(node) {\n // Don't add transient observers on the target itself. We already have all\n // the required listeners set up on the target.\n if (node === this.target)\n return;\n\n this.addListeners_(node);\n this.transientObservedNodes.push(node);\n var registrations = registrationsTable.get(node);\n if (!registrations)\n registrationsTable.set(node, registrations = []);\n\n // We know that registrations does not contain this because we already\n // checked if node === this.target.\n registrations.push(this);\n },\n\n removeTransientObservers: function() {\n var transientObservedNodes = this.transientObservedNodes;\n this.transientObservedNodes = [];\n\n transientObservedNodes.forEach(function(node) {\n // Transient observers are never added to the target.\n this.removeListeners_(node);\n\n var registrations = registrationsTable.get(node);\n for (var i = 0; i < registrations.length; i++) {\n if (registrations[i] === this) {\n registrations.splice(i, 1);\n // Each node can only have one registered observer associated with\n // this observer.\n break;\n }\n }\n }, this);\n },\n\n handleEvent: function(e) {\n // Stop propagation since we are managing the propagation manually.\n // This means that other mutation events on the page will not work\n // correctly but that is by design.\n e.stopImmediatePropagation();\n\n switch (e.type) {\n case 'DOMAttrModified':\n // http://dom.spec.whatwg.org/#concept-mo-queue-attributes\n\n var name = e.attrName;\n var namespace = e.relatedNode.namespaceURI;\n var target = e.target;\n\n // 1.\n var record = new getRecord('attributes', target);\n record.attributeName = name;\n record.attributeNamespace = namespace;\n\n // 2.\n var oldValue =\n e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;\n\n forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n // 3.1, 4.2\n if (!options.attributes)\n return;\n\n // 3.2, 4.3\n if (options.attributeFilter && options.attributeFilter.length &&\n options.attributeFilter.indexOf(name) === -1 &&\n options.attributeFilter.indexOf(namespace) === -1) {\n return;\n }\n // 3.3, 4.4\n if (options.attributeOldValue)\n return getRecordWithOldValue(oldValue);\n\n // 3.4, 4.5\n return record;\n });\n\n break;\n\n case 'DOMCharacterDataModified':\n // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata\n var target = e.target;\n\n // 1.\n var record = getRecord('characterData', target);\n\n // 2.\n var oldValue = e.prevValue;\n\n\n forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n // 3.1, 4.2\n if (!options.characterData)\n return;\n\n // 3.2, 4.3\n if (options.characterDataOldValue)\n return getRecordWithOldValue(oldValue);\n\n // 3.3, 4.4\n return record;\n });\n\n break;\n\n case 'DOMNodeRemoved':\n this.addTransientObserver(e.target);\n // Fall through.\n case 'DOMNodeInserted':\n // http://dom.spec.whatwg.org/#concept-mo-queue-childlist\n var target = e.relatedNode;\n var changedNode = e.target;\n var addedNodes, removedNodes;\n if (e.type === 'DOMNodeInserted') {\n addedNodes = [changedNode];\n removedNodes = [];\n } else {\n\n addedNodes = [];\n removedNodes = [changedNode];\n }\n var previousSibling = changedNode.previousSibling;\n var nextSibling = changedNode.nextSibling;\n\n // 1.\n var record = getRecord('childList', target);\n record.addedNodes = addedNodes;\n record.removedNodes = removedNodes;\n record.previousSibling = previousSibling;\n record.nextSibling = nextSibling;\n\n forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n // 2.1, 3.2\n if (!options.childList)\n return;\n\n // 2.2, 3.3\n return record;\n });\n\n }\n\n clearRecords();\n }\n };\n\n global.JsMutationObserver = JsMutationObserver;\n\n if (!global.MutationObserver)\n global.MutationObserver = JsMutationObserver;\n\n\n})(this);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\nwindow.HTMLImports = window.HTMLImports || {flags:{}};","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n // imports\n var path = scope.path;\n var xhr = scope.xhr;\n var flags = scope.flags;\n\n // TODO(sorvell): this loader supports a dynamic list of urls\n // and an oncomplete callback that is called when the loader is done.\n // The polyfill currently does *not* need this dynamism or the onComplete\n // concept. Because of this, the loader could be simplified quite a bit.\n var Loader = function(onLoad, onComplete) {\n this.cache = {};\n this.onload = onLoad;\n this.oncomplete = onComplete;\n this.inflight = 0;\n this.pending = {};\n };\n\n Loader.prototype = {\n addNodes: function(nodes) {\n // number of transactions to complete\n this.inflight += nodes.length;\n // commence transactions\n for (var i=0, l=nodes.length, n; (i -1) {\n body = atob(body);\n } else {\n body = decodeURIComponent(body);\n }\n setTimeout(function() {\n this.receive(url, elt, null, body);\n }.bind(this), 0);\n } else {\n var receiveXhr = function(err, resource) {\n this.receive(url, elt, err, resource);\n }.bind(this);\n xhr.load(url, receiveXhr);\n // TODO(sorvell): blocked on)\n // https://code.google.com/p/chromium/issues/detail?id=257221\n // xhr'ing for a document makes scripts in imports runnable; otherwise\n // they are not; however, it requires that we have doctype=html in\n // the import which is unacceptable. This is only needed on Chrome\n // to avoid the bug above.\n /*\n if (isDocumentLink(elt)) {\n xhr.loadDocument(url, receiveXhr);\n } else {\n xhr.load(url, receiveXhr);\n }\n */\n }\n },\n receive: function(url, elt, err, resource) {\n this.cache[url] = resource;\n var $p = this.pending[url];\n for (var i=0, l=$p.length, p; (i= 200 && request.status < 300)\n || (request.status === 304)\n || (request.status === 0);\n },\n load: function(url, next, nextContext) {\n var request = new XMLHttpRequest();\n if (scope.flags.debug || scope.flags.bust) {\n url += '?' + Math.random();\n }\n request.open('GET', url, xhr.async);\n request.addEventListener('readystatechange', function(e) {\n if (request.readyState === 4) {\n next.call(nextContext, !xhr.ok(request) && request,\n request.response || request.responseText, url);\n }\n });\n request.send();\n return request;\n },\n loadDocument: function(url, next, nextContext) {\n this.load(url, next, nextContext).responseType = 'document';\n }\n };\n\n // exports\n scope.xhr = xhr;\n scope.Loader = Loader;\n\n})(window.HTMLImports);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\nvar IMPORT_LINK_TYPE = 'import';\nvar flags = scope.flags;\nvar isIe = /Trident/.test(navigator.userAgent);\n// TODO(sorvell): SD polyfill intrusion\nvar mainDoc = window.ShadowDOMPolyfill ? \n window.ShadowDOMPolyfill.wrapIfNeeded(document) : document;\n\n// importParser\n// highlander object to manage parsing of imports\n// parses import related elements\n// and ensures proper parse order\n// parse order is enforced by crawling the tree and monitoring which elements\n// have been parsed; async parsing is also supported.\n\n// highlander object for parsing a document tree\nvar importParser = {\n // parse selectors for main document elements\n documentSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',\n // parse selectors for import document elements\n importsSelectors: [\n 'link[rel=' + IMPORT_LINK_TYPE + ']',\n 'link[rel=stylesheet]',\n 'style',\n 'script:not([type])',\n 'script[type=\"text/javascript\"]'\n ].join(','),\n map: {\n link: 'parseLink',\n script: 'parseScript',\n style: 'parseStyle'\n },\n // try to parse the next import in the tree\n parseNext: function() {\n var next = this.nextToParse();\n if (next) {\n this.parse(next);\n }\n },\n parse: function(elt) {\n if (this.isParsed(elt)) {\n flags.parse && console.log('[%s] is already parsed', elt.localName);\n return;\n }\n var fn = this[this.map[elt.localName]];\n if (fn) {\n this.markParsing(elt);\n fn.call(this, elt);\n }\n },\n // only 1 element may be parsed at a time; parsing is async so, each\n // parsing implementation must inform the system that parsing is complete\n // via markParsingComplete.\n markParsing: function(elt) {\n flags.parse && console.log('parsing', elt);\n this.parsingElement = elt;\n },\n markParsingComplete: function(elt) {\n elt.__importParsed = true;\n if (elt.__importElement) {\n elt.__importElement.__importParsed = true;\n }\n this.parsingElement = null;\n flags.parse && console.log('completed', elt);\n this.parseNext();\n },\n parseImport: function(elt) {\n elt.import.__importParsed = true;\n // TODO(sorvell): consider if there's a better way to do this;\n // expose an imports parsing hook; this is needed, for example, by the\n // CustomElements polyfill.\n if (HTMLImports.__importsParsingHook) {\n HTMLImports.__importsParsingHook(elt);\n }\n // fire load event\n if (elt.__resource) {\n elt.dispatchEvent(new CustomEvent('load', {bubbles: false})); \n } else {\n elt.dispatchEvent(new CustomEvent('error', {bubbles: false}));\n }\n // TODO(sorvell): workaround for Safari addEventListener not working\n // for elements not in the main document.\n if (elt.__pending) {\n var fn;\n while (elt.__pending.length) {\n fn = elt.__pending.shift();\n if (fn) {\n fn({target: elt});\n }\n }\n }\n this.markParsingComplete(elt);\n },\n parseLink: function(linkElt) {\n if (nodeIsImport(linkElt)) {\n this.parseImport(linkElt);\n } else {\n // make href absolute\n linkElt.href = linkElt.href;\n this.parseGeneric(linkElt);\n }\n },\n parseStyle: function(elt) {\n // TODO(sorvell): style element load event can just not fire so clone styles\n var src = elt;\n elt = cloneStyle(elt);\n elt.__importElement = src;\n this.parseGeneric(elt);\n },\n parseGeneric: function(elt) {\n this.trackElement(elt);\n document.head.appendChild(elt);\n },\n // tracks when a loadable element has loaded\n trackElement: function(elt, callback) {\n var self = this;\n var done = function(e) {\n if (callback) {\n callback(e);\n }\n self.markParsingComplete(elt);\n };\n elt.addEventListener('load', done);\n elt.addEventListener('error', done);\n\n // NOTE: IE does not fire \"load\" event for styles that have already loaded\n // This is in violation of the spec, so we try our hardest to work around it\n if (isIe && elt.localName === 'style') {\n var fakeLoad = false;\n // If there's not @import in the textContent, assume it has loaded\n if (elt.textContent.indexOf('@import') == -1) {\n fakeLoad = true;\n // if we have a sheet, we have been parsed\n } else if (elt.sheet) {\n fakeLoad = true;\n var csr = elt.sheet.cssRules;\n var len = csr ? csr.length : 0;\n // search the rules for @import's\n for (var i = 0, r; (i < len) && (r = csr[i]); i++) {\n if (r.type === CSSRule.IMPORT_RULE) {\n // if every @import has resolved, fake the load\n fakeLoad = fakeLoad && Boolean(r.styleSheet);\n }\n }\n }\n // dispatch a fake load event and continue parsing\n if (fakeLoad) {\n elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));\n }\n }\n },\n // NOTE: execute scripts by injecting them and watching for the load/error\n // event. Inline scripts are handled via dataURL's because browsers tend to\n // provide correct parsing errors in this case. If this has any compatibility\n // issues, we can switch to injecting the inline script with textContent.\n // Scripts with dataURL's do not appear to generate load events and therefore\n // we assume they execute synchronously.\n parseScript: function(scriptElt) {\n var script = document.createElement('script');\n script.__importElement = scriptElt;\n script.src = scriptElt.src ? scriptElt.src : \n generateScriptDataUrl(scriptElt);\n scope.currentScript = scriptElt;\n this.trackElement(script, function(e) {\n script.parentNode.removeChild(script);\n scope.currentScript = null; \n });\n document.head.appendChild(script);\n },\n // determine the next element in the tree which should be parsed\n nextToParse: function() {\n return !this.parsingElement && this.nextToParseInDoc(mainDoc);\n },\n nextToParseInDoc: function(doc, link) {\n var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));\n for (var i=0, l=nodes.length, p=0, n; (i.content\n // see https://code.google.com/p/chromium/issues/detail?id=249381.\n elt.__resource = resource;\n if (isDocumentLink(elt)) {\n var doc = this.documents[url];\n // if we've never seen a document at this url\n if (!doc) {\n // generate an HTMLDocument from data\n doc = makeDocument(resource, url);\n doc.__importLink = elt;\n // TODO(sorvell): we cannot use MO to detect parsed nodes because\n // SD polyfill does not report these as mutations.\n this.bootDocument(doc);\n // cache document\n this.documents[url] = doc;\n }\n // don't store import record until we're actually loaded\n // store document resource\n elt.import = doc;\n }\n parser.parseNext();\n },\n bootDocument: function(doc) {\n this.loadSubtree(doc);\n this.observe(doc);\n parser.parseNext();\n },\n loadedAll: function() {\n parser.parseNext();\n }\n };\n\n // loader singleton\n var importLoader = new Loader(importer.loaded.bind(importer), \n importer.loadedAll.bind(importer));\n\n function isDocumentLink(elt) {\n return isLinkRel(elt, IMPORT_LINK_TYPE);\n }\n\n function isLinkRel(elt, rel) {\n return elt.localName === 'link' && elt.getAttribute('rel') === rel;\n }\n\n function isScript(elt) {\n return elt.localName === 'script';\n }\n\n function makeDocument(resource, url) {\n // create a new HTML document\n var doc = resource;\n if (!(doc instanceof Document)) {\n doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE);\n }\n // cache the new document's source url\n doc._URL = url;\n // establish a relative path via \n var base = doc.createElement('base');\n base.setAttribute('href', url);\n // add baseURI support to browsers (IE) that lack it.\n if (!doc.baseURI) {\n doc.baseURI = url;\n }\n // ensure UTF-8 charset\n var meta = doc.createElement('meta');\n meta.setAttribute('charset', 'utf-8');\n\n doc.head.appendChild(meta);\n doc.head.appendChild(base);\n // install HTML last as it may trigger CustomElement upgrades\n // TODO(sjmiles): problem wrt to template boostrapping below,\n // template bootstrapping must (?) come before element upgrade\n // but we cannot bootstrap templates until they are in a document\n // which is too late\n if (!(resource instanceof Document)) {\n // install html\n doc.body.innerHTML = resource;\n }\n // TODO(sorvell): ideally this code is not aware of Template polyfill,\n // but for now the polyfill needs help to bootstrap these templates\n if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {\n HTMLTemplateElement.bootstrap(doc);\n }\n return doc;\n }\n} else {\n // do nothing if using native imports\n var importer = {};\n}\n\n// NOTE: We cannot polyfill document.currentScript because it's not possible\n// both to override and maintain the ability to capture the native value;\n// therefore we choose to expose _currentScript both when native imports\n// and the polyfill are in use.\nvar currentScriptDescriptor = {\n get: function() {\n return HTMLImports.currentScript || document.currentScript;\n },\n configurable: true\n};\n\nObject.defineProperty(document, '_currentScript', currentScriptDescriptor);\nObject.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);\n\n// Polyfill document.baseURI for browsers without it.\nif (!document.baseURI) {\n var baseURIDescriptor = {\n get: function() {\n return window.location.href;\n },\n configurable: true\n };\n\n Object.defineProperty(document, 'baseURI', baseURIDescriptor);\n Object.defineProperty(mainDoc, 'baseURI', baseURIDescriptor);\n}\n\n// call a callback when all HTMLImports in the document at call (or at least\n// document ready) time have loaded.\n// 1. ensure the document is in a ready state (has dom), then \n// 2. watch for loading of imports and call callback when done\nfunction whenImportsReady(callback, doc) {\n doc = doc || mainDoc;\n // if document is loading, wait and try again\n whenDocumentReady(function() {\n watchImportsLoad(callback, doc);\n }, doc);\n}\n\n// call the callback when the document is in a ready state (has dom)\nvar requiredReadyState = HTMLImports.isIE ? 'complete' : 'interactive';\nvar READY_EVENT = 'readystatechange';\nfunction isDocumentReady(doc) {\n return (doc.readyState === 'complete' ||\n doc.readyState === requiredReadyState);\n}\n\n// call when we ensure the document is in a ready state\nfunction whenDocumentReady(callback, doc) {\n if (!isDocumentReady(doc)) {\n var checkReady = function() {\n if (doc.readyState === 'complete' || \n doc.readyState === requiredReadyState) {\n doc.removeEventListener(READY_EVENT, checkReady);\n whenDocumentReady(callback, doc);\n }\n }\n doc.addEventListener(READY_EVENT, checkReady);\n } else if (callback) {\n callback();\n }\n}\n\n// call when we ensure all imports have loaded\nfunction watchImportsLoad(callback, doc) {\n var imports = doc.querySelectorAll('link[rel=import]');\n var loaded = 0, l = imports.length;\n function checkDone(d) { \n if (loaded == l) {\n // go async to ensure parser isn't stuck on a script tag\n requestAnimationFrame(callback);\n }\n }\n function loadedImport(e) {\n loaded++;\n checkDone();\n }\n if (l) {\n for (var i=0, imp; (i 1) {\r\n logFlags.dom && console.warn('inserted:', element.localName,\r\n 'insert/remove count:', element.__inserted)\r\n } else if (element.attachedCallback) {\r\n logFlags.dom && console.log('inserted:', element.localName);\r\n element.attachedCallback();\r\n }\r\n }\r\n logFlags.dom && console.groupEnd();\r\n }\r\n}\r\n\r\nfunction removedNode(node) {\r\n removed(node);\r\n forSubtree(node, function(e) {\r\n removed(e);\r\n });\r\n}\r\n\r\nfunction removed(element) {\r\n if (hasPolyfillMutations) {\r\n deferMutation(function() {\r\n _removed(element);\r\n });\r\n } else {\r\n _removed(element);\r\n }\r\n}\r\n\r\nfunction _removed(element) {\r\n // TODO(sjmiles): temporary: do work on all custom elements so we can track\r\n // behavior even when callbacks not defined\r\n if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {\r\n logFlags.dom && console.group('removed:', element.localName);\r\n if (!inDocument(element)) {\r\n element.__inserted = (element.__inserted || 0) - 1;\r\n // if we are in a 'inserted' state, bluntly adjust to an 'removed' state\r\n if (element.__inserted > 0) {\r\n element.__inserted = 0;\r\n }\r\n // if we are 'over removed', squelch the callback\r\n if (element.__inserted < 0) {\r\n logFlags.dom && console.warn('removed:', element.localName,\r\n 'insert/remove count:', element.__inserted)\r\n } else if (element.detachedCallback) {\r\n element.detachedCallback();\r\n }\r\n }\r\n logFlags.dom && console.groupEnd();\r\n }\r\n}\r\n\r\n// SD polyfill intrustion due mainly to the fact that 'document'\r\n// is not entirely wrapped\r\nfunction wrapIfNeeded(node) {\r\n return window.ShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node)\r\n : node;\r\n}\r\n\r\nfunction inDocument(element) {\r\n var p = element;\r\n var doc = wrapIfNeeded(document);\r\n while (p) {\r\n if (p == doc) {\r\n return true;\r\n }\r\n p = p.parentNode || p.host;\r\n }\r\n}\r\n\r\nfunction watchShadow(node) {\r\n if (node.shadowRoot && !node.shadowRoot.__watched) {\r\n logFlags.dom && console.log('watching shadow-root for: ', node.localName);\r\n // watch all unwatched roots...\r\n var root = node.shadowRoot;\r\n while (root) {\r\n watchRoot(root);\r\n root = root.olderShadowRoot;\r\n }\r\n }\r\n}\r\n\r\nfunction watchRoot(root) {\r\n if (!root.__watched) {\r\n observe(root);\r\n root.__watched = true;\r\n }\r\n}\r\n\r\nfunction handler(mutations) {\r\n //\r\n if (logFlags.dom) {\r\n var mx = mutations[0];\r\n if (mx && mx.type === 'childList' && mx.addedNodes) {\r\n if (mx.addedNodes) {\r\n var d = mx.addedNodes[0];\r\n while (d && d !== document && !d.host) {\r\n d = d.parentNode;\r\n }\r\n var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';\r\n u = u.split('/?').shift().split('/').pop();\r\n }\r\n }\r\n console.group('mutations (%d) [%s]', mutations.length, u || '');\r\n }\r\n //\r\n mutations.forEach(function(mx) {\r\n //logFlags.dom && console.group('mutation');\r\n if (mx.type === 'childList') {\r\n forEach(mx.addedNodes, function(n) {\r\n //logFlags.dom && console.log(n.localName);\r\n if (!n.localName) {\r\n return;\r\n }\r\n // nodes added may need lifecycle management\r\n addedNode(n);\r\n });\r\n // removed nodes may need lifecycle management\r\n forEach(mx.removedNodes, function(n) {\r\n //logFlags.dom && console.log(n.localName);\r\n if (!n.localName) {\r\n return;\r\n }\r\n removedNode(n);\r\n });\r\n }\r\n //logFlags.dom && console.groupEnd();\r\n });\r\n logFlags.dom && console.groupEnd();\r\n};\r\n\r\nvar observer = new MutationObserver(handler);\r\n\r\nfunction takeRecords() {\r\n // TODO(sjmiles): ask Raf why we have to call handler ourselves\r\n handler(observer.takeRecords());\r\n takeMutations();\r\n}\r\n\r\nvar forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\r\n\r\nfunction observe(inRoot) {\r\n observer.observe(inRoot, {childList: true, subtree: true});\r\n}\r\n\r\nfunction observeDocument(doc) {\r\n observe(doc);\r\n}\r\n\r\nfunction upgradeDocument(doc) {\r\n logFlags.dom && console.group('upgradeDocument: ', (doc.baseURI).split('/').pop());\r\n addedNode(doc);\r\n logFlags.dom && console.groupEnd();\r\n}\r\n\r\nfunction upgradeDocumentTree(doc) {\r\n doc = wrapIfNeeded(doc);\r\n //console.log('upgradeDocumentTree: ', (doc.baseURI).split('/').pop());\r\n // upgrade contained imported documents\r\n var imports = doc.querySelectorAll('link[rel=' + IMPORT_LINK_TYPE + ']');\r\n for (var i=0, l=imports.length, n; (i= 0) {\n implement(element, HTMLElement);\n }\n return element;\n }\n\n function upgradeElement(element) {\n if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) {\n var is = element.getAttribute('is');\n var definition = getRegisteredDefinition(is || element.localName);\n if (definition) {\n if (is && definition.tag == element.localName) {\n return upgrade(element, definition);\n } else if (!is && !definition.extends) {\n return upgrade(element, definition);\n }\n }\n }\n }\n\n function cloneNode(deep) {\n // call original clone\n var n = domCloneNode.call(this, deep);\n // upgrade the element and subtree\n scope.upgradeAll(n);\n // return the clone\n return n;\n }\n // capture native createElement before we override it\n\n var domCreateElement = document.createElement.bind(document);\n var domCreateElementNS = document.createElementNS.bind(document);\n\n // capture native cloneNode before we override it\n\n var domCloneNode = Node.prototype.cloneNode;\n\n // exports\n\n document.registerElement = register;\n document.createElement = createElement; // override\n document.createElementNS = createElementNS; // override\n Node.prototype.cloneNode = cloneNode; // override\n\n scope.registry = registry;\n\n /**\n * Upgrade an element to a custom element. Upgrading an element\n * causes the custom prototype to be applied, an `is` attribute\n * to be attached (as needed), and invocation of the `readyCallback`.\n * `upgrade` does nothing if the element is already upgraded, or\n * if it matches no registered custom tag name.\n *\n * @method ugprade\n * @param {Element} element The element to upgrade.\n * @return {Element} The upgraded element.\n */\n scope.upgrade = upgradeElement;\n}\n\n// Create a custom 'instanceof'. This is necessary when CustomElements\n// are implemented via a mixin strategy, as for example on IE10.\nvar isInstance;\nif (!Object.__proto__ && !useNative) {\n isInstance = function(obj, ctor) {\n var p = obj;\n while (p) {\n // NOTE: this is not technically correct since we're not checking if\n // an object is an instance of a constructor; however, this should\n // be good enough for the mixin strategy.\n if (p === ctor.prototype) {\n return true;\n }\n p = p.__proto__;\n }\n return false;\n }\n} else {\n isInstance = function(obj, base) {\n return obj instanceof base;\n }\n}\n\n// exports\nscope.instanceof = isInstance;\nscope.reservedTagList = reservedTagList;\n\n// bc\ndocument.register = document.registerElement;\n\nscope.hasNative = hasNative;\nscope.useNative = useNative;\n\n})(window.CustomElements);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n// import\n\nvar IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;\n\n// highlander object for parsing a document tree\n\nvar parser = {\n selectors: [\n 'link[rel=' + IMPORT_LINK_TYPE + ']'\n ],\n map: {\n link: 'parseLink'\n },\n parse: function(inDocument) {\n if (!inDocument.__parsed) {\n // only parse once\n inDocument.__parsed = true;\n // all parsable elements in inDocument (depth-first pre-order traversal)\n var elts = inDocument.querySelectorAll(parser.selectors);\n // for each parsable node type, call the mapped parsing method\n forEach(elts, function(e) {\n parser[parser.map[e.localName]](e);\n });\n // upgrade all upgradeable static elements, anything dynamically\n // created should be caught by observer\n CustomElements.upgradeDocument(inDocument);\n // observe document for dom changes\n CustomElements.observeDocument(inDocument);\n }\n },\n parseLink: function(linkElt) {\n // imports\n if (isDocumentLink(linkElt)) {\n this.parseImport(linkElt);\n }\n },\n parseImport: function(linkElt) {\n if (linkElt.import) {\n parser.parse(linkElt.import);\n }\n }\n};\n\nfunction isDocumentLink(inElt) {\n return (inElt.localName === 'link'\n && inElt.getAttribute('rel') === IMPORT_LINK_TYPE);\n}\n\nvar forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n\n// exports\n\nscope.parser = parser;\nscope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;\n\n})(window.CustomElements);","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope){\n\n// bootstrap parsing\nfunction bootstrap() {\n // parse document\n CustomElements.parser.parse(document);\n // one more pass before register is 'live'\n CustomElements.upgradeDocument(document);\n // choose async\n var async = window.Platform && Platform.endOfMicrotask ? \n Platform.endOfMicrotask :\n setTimeout;\n async(function() {\n // set internal 'ready' flag, now document.registerElement will trigger \n // synchronous upgrades\n CustomElements.ready = true;\n // capture blunt profiling data\n CustomElements.readyTime = Date.now();\n if (window.HTMLImports) {\n CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime;\n }\n // notify the system that we are bootstrapped\n document.dispatchEvent(\n new CustomEvent('WebComponentsReady', {bubbles: true})\n );\n\n // install upgrade hook if HTMLImports are available\n if (window.HTMLImports) {\n HTMLImports.__importsParsingHook = function(elt) {\n CustomElements.parser.parse(elt.import);\n }\n }\n });\n}\n\n// CustomEvent shim for IE\nif (typeof window.CustomEvent !== 'function') {\n window.CustomEvent = function(inType) {\n var e = document.createEvent('HTMLEvents');\n e.initEvent(inType, true, true);\n return e;\n };\n}\n\n// When loading at readyState complete time (or via flag), boot custom elements\n// immediately.\n// If relevant, HTMLImports must already be loaded.\nif (document.readyState === 'complete' || scope.flags.eager) {\n bootstrap();\n// When loading at readyState interactive time, bootstrap only if HTMLImports\n// are not pending. Also avoid IE as the semantics of this state are unreliable.\n} else if (document.readyState === 'interactive' && !window.attachEvent &&\n (!window.HTMLImports || window.HTMLImports.ready)) {\n bootstrap();\n// When loading at other readyStates, wait for the appropriate DOM event to \n// bootstrap.\n} else {\n var loadEvent = window.HTMLImports && !HTMLImports.ready ?\n 'HTMLImportsLoaded' : 'DOMContentLoaded';\n window.addEventListener(loadEvent, bootstrap);\n}\n\n})(window.CustomElements);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\nif (window.ShadowDOMPolyfill) {\n\n // ensure wrapped inputs for these functions\n var fns = ['upgradeAll', 'upgradeSubtree', 'observeDocument',\n 'upgradeDocument'];\n\n // cache originals\n var original = {};\n fns.forEach(function(fn) {\n original[fn] = CustomElements[fn];\n });\n\n // override\n fns.forEach(function(fn) {\n CustomElements[fn] = function(inNode) {\n return original[fn](wrap(inNode));\n };\n });\n\n}\n\n})();\n","/*\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n var endOfMicrotask = scope.endOfMicrotask;\n\n // Generic url loader\n function Loader(regex) {\n this.regex = regex;\n }\n Loader.prototype = {\n // TODO(dfreedm): there may be a better factoring here\n // extract absolute urls from the text (full of relative urls)\n extractUrls: function(text, base) {\n var matches = [];\n var matched, u;\n while ((matched = this.regex.exec(text))) {\n u = new URL(matched[1], base);\n matches.push({matched: matched[0], url: u.href});\n }\n return matches;\n },\n // take a text blob, a root url, and a callback and load all the urls found within the text\n // returns a map of absolute url to text\n process: function(text, root, callback) {\n var matches = this.extractUrls(text, root);\n this.fetch(matches, {}, callback);\n },\n // build a mapping of url -> text from matches\n fetch: function(matches, map, callback) {\n var inflight = matches.length;\n\n // return early if there is no fetching to be done\n if (!inflight) {\n return callback(map);\n }\n\n var done = function() {\n if (--inflight === 0) {\n callback(map);\n }\n };\n\n // map url -> responseText\n var handleXhr = function(err, request) {\n var match = request.match;\n var key = match.url;\n // handle errors with an empty string\n if (err) {\n map[key] = '';\n return done();\n }\n var response = request.response || request.responseText;\n map[key] = response;\n this.fetch(this.extractUrls(response, key), map, done);\n };\n\n var m, req, url;\n for (var i = 0; i < inflight; i++) {\n m = matches[i];\n url = m.url;\n // if this url has already been requested, skip requesting it again\n if (map[url]) {\n // Async call to done to simplify the inflight logic\n endOfMicrotask(done);\n continue;\n }\n req = this.xhr(url, handleXhr, this);\n req.match = m;\n // tag the map with an XHR request to deduplicate at the same level\n map[url] = req;\n }\n },\n xhr: function(url, callback, scope) {\n var request = new XMLHttpRequest();\n request.open('GET', url, true);\n request.send();\n request.onload = function() {\n callback.call(scope, null, request);\n };\n request.onerror = function() {\n callback.call(scope, null, request);\n };\n return request;\n }\n };\n\n scope.Loader = Loader;\n})(window.Platform);\n","/*\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\nvar urlResolver = scope.urlResolver;\nvar Loader = scope.Loader;\n\nfunction StyleResolver() {\n this.loader = new Loader(this.regex);\n}\nStyleResolver.prototype = {\n regex: /@import\\s+(?:url)?[\"'\\(]*([^'\"\\)]*)['\"\\)]*;/g,\n // Recursively replace @imports with the text at that url\n resolve: function(text, url, callback) {\n var done = function(map) {\n callback(this.flatten(text, url, map));\n }.bind(this);\n this.loader.process(text, url, done);\n },\n // resolve the textContent of a style node\n resolveNode: function(style, callback) {\n var text = style.textContent;\n var url = style.ownerDocument.baseURI;\n var done = function(text) {\n style.textContent = text;\n callback(style);\n };\n this.resolve(text, url, done);\n },\n // flatten all the @imports to text\n flatten: function(text, base, map) {\n var matches = this.loader.extractUrls(text, base);\n var match, url, intermediate;\n for (var i = 0; i < matches.length; i++) {\n match = matches[i];\n url = match.url;\n // resolve any css text to be relative to the importer\n intermediate = urlResolver.resolveCssText(map[url], url);\n // flatten intermediate @imports\n intermediate = this.flatten(intermediate, base, map);\n text = text.replace(match.matched, intermediate);\n }\n return text;\n },\n loadStyles: function(styles, callback) {\n var loaded=0, l = styles.length;\n // called in the context of the style\n function loadedStyle(style) {\n loaded++;\n if (loaded === l && callback) {\n callback();\n }\n }\n for (var i=0, s; (i element.\n * @constructor\n * @extends {HTMLElement}\n */\n global.HTMLTemplateElement = function() {\n throw TypeError('Illegal constructor');\n };\n }\n\n var hasProto = '__proto__' in {};\n\n function mixin(to, from) {\n Object.getOwnPropertyNames(from).forEach(function(name) {\n Object.defineProperty(to, name,\n Object.getOwnPropertyDescriptor(from, name));\n });\n }\n\n // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner\n function getOrCreateTemplateContentsOwner(template) {\n var doc = template.ownerDocument\n if (!doc.defaultView)\n return doc;\n var d = doc.templateContentsOwner_;\n if (!d) {\n // TODO(arv): This should either be a Document or HTMLDocument depending\n // on doc.\n d = doc.implementation.createHTMLDocument('');\n while (d.lastChild) {\n d.removeChild(d.lastChild);\n }\n doc.templateContentsOwner_ = d;\n }\n return d;\n }\n\n function getTemplateStagingDocument(template) {\n if (!template.stagingDocument_) {\n var owner = template.ownerDocument;\n if (!owner.stagingDocument_) {\n owner.stagingDocument_ = owner.implementation.createHTMLDocument('');\n owner.stagingDocument_.isStagingDocument = true;\n // TODO(rafaelw): Remove when fix for\n // https://codereview.chromium.org/164803002/\n // makes it to Chrome release.\n var base = owner.stagingDocument_.createElement('base');\n base.href = document.baseURI;\n owner.stagingDocument_.head.appendChild(base);\n\n owner.stagingDocument_.stagingDocument_ = owner.stagingDocument_;\n }\n\n template.stagingDocument_ = owner.stagingDocument_;\n }\n\n return template.stagingDocument_;\n }\n\n // For non-template browsers, the parser will disallow