| Index: polymer_1.0.4/bower_components/google-youtube/google-youtube.html
|
| diff --git a/polymer_1.0.4/bower_components/google-youtube/google-youtube.html b/polymer_1.0.4/bower_components/google-youtube/google-youtube.html
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..ae516989dfbe980e26b773f203871d5013849d1c
|
| --- /dev/null
|
| +++ b/polymer_1.0.4/bower_components/google-youtube/google-youtube.html
|
| @@ -0,0 +1,659 @@
|
| +<!--
|
| +Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
|
| +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
|
| +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
|
| +The complete set of contributors may be found at https://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 https://polymer.github.io/PATENTS.txt
|
| +-->
|
| +
|
| +<link rel="import" href="../polymer/polymer.html">
|
| +<link rel="import" href="../iron-localstorage/iron-localstorage.html">
|
| +<link rel="import" href="../google-apis/google-youtube-api.html">
|
| +
|
| +<!--
|
| +`google-youtube` encapsulates the YouTube player into a web component.
|
| +
|
| + <google-youtube
|
| + video-id="..."
|
| + height="270px"
|
| + width="480px"
|
| + rel="0"
|
| + start="5"
|
| + autoplay="1">
|
| + </google-youtube>
|
| +
|
| +`google-youtube` supports all of the [embedded player parameters](https://developers.google.com/youtube/player_parameters). Each can be set as an attribute on `google-youtube`.
|
| +
|
| +The standard set of [YouTube player events](https://developers.google.com/youtube/iframe_api_reference#Events) are exposed, as well as methods for playing, pausing, seeking to a specific time, and loading a new video.
|
| +
|
| +@demo
|
| +-->
|
| +<dom-module id="google-youtube">
|
| + <template>
|
| + <style>
|
| + :host {
|
| + display: block;
|
| + }
|
| +
|
| + :host([fluid]) {
|
| + width: 100%;
|
| + max-width: 100%;
|
| + position: relative;
|
| + }
|
| +
|
| + :host([fluid]) iframe,
|
| + :host([fluid]) #thumbnail {
|
| + vertical-align: bottom;
|
| + position: absolute;
|
| + top: 0px;
|
| + left: 0px;
|
| + width: 100%;
|
| + height: 100%;
|
| + }
|
| +
|
| + #container {
|
| + max-width: 100%;
|
| + max-height: 100%;
|
| + }
|
| +
|
| + #thumbnail {
|
| + width: 100%;
|
| + height: 100%;
|
| + cursor: pointer;
|
| + }
|
| +
|
| + /* Some browsers will refuse to play videos with 'display: none' set, so position the video well offscreen instead. */
|
| + #playtest {
|
| + position: absolute;
|
| + top: -9999px;
|
| + left: -9999px;
|
| + }
|
| + </style>
|
| +
|
| + <div id="container" style$="{{_computeContainerStyle(width, height)}}">
|
| + <template is="dom-if" if="{{thumbnail}}">
|
| + <img id="thumbnail"
|
| + src$="{{thumbnail}}"
|
| + title="YouTube video thumbnail."
|
| + alt="YouTube video thumbnail."
|
| + on-tap="_handleThumbnailTap">
|
| + </template>
|
| +
|
| + <template is="dom-if" if="{{!thumbnail}}">
|
| + <google-youtube-api on-api-load="_apiLoad"></google-youtube-api>
|
| + </template>
|
| +
|
| + <!-- Use this._playsupportedLocalStorage as the value, since this.playsupported is set to
|
| + true as soon as initial playback has started, and we don't want that cached. -->
|
| + <iron-localstorage name="google-youtube-playsupported"
|
| + value="_playsupportedLocalStorage"
|
| + on-iron-localstorage-load="_determinePlaySupported">
|
| + </iron-localstorage>
|
| +
|
| + <div id="player"></div>
|
| + </div>
|
| + </template>
|
| +</dom-module>
|
| +
|
| +<script>
|
| + Polymer({
|
| + is: 'google-youtube',
|
| + /**
|
| + * Fired when the YouTube player is fully initialized and ready for use.
|
| + *
|
| + * @event google-youtube-ready
|
| + */
|
| +
|
| + /**
|
| + * Fired when the state of the player changes. `e.detail.data` is set to one of
|
| + * [the documented](https://developers.google.com/youtube/iframe_api_reference#onStateChange)
|
| + * states.
|
| + *
|
| + * @event google-youtube-state-change
|
| + * @param {Object} e Event parameters.
|
| + */
|
| +
|
| + /**
|
| + * Fired when playback fails due to an error. `e.detail.data` is set to one of
|
| + * [the documented](https://developers.google.com/youtube/iframe_api_reference#onError)
|
| + * error codes.
|
| + *
|
| + * @event google-youtube-error
|
| + * @param {Object} e Event parameters.
|
| + */
|
| +
|
| + properties: {
|
| + /**
|
| + * Sets the id of the video to play. Changing this attribute will trigger a call
|
| + * to load a new video into the player (if `this.autoplay` is set to `1` and `playsupported` is true)
|
| + * or cue a new video otherwise.
|
| + *
|
| + * You can [search for videos programmatically](https://developers.google.com/youtube/v3/docs/search/list)
|
| + * using the YouTube Data API, or just hardcode known video ids to display on your page.
|
| + */
|
| + videoId: {
|
| + type: String,
|
| + value: 'mN7IAaRdi_k',
|
| + observer: '_videoIdChanged'
|
| + },
|
| +
|
| + /**
|
| + * Whether programmatic `<video>.play()` for initial playback is supported in the current browser.
|
| + *
|
| + * Most mobile browsers [do not support](https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW1) autoplaying or scripted playback of videos.
|
| + * If you attempt to automatically initiate playback of a `<google-youtube>`, e.g. by calling the `play()` method before
|
| + * playback has initially begun, the YouTube Player will enter an unrecoverable "stuck" state.
|
| + * To protect against this, check the value of `playsupported` and don't call `play()` if it is set to `false`.
|
| + * (You can hide/disable your custom play button, etc.)
|
| + *
|
| + * The `playsupported` value is determined at runtime, by dynamically creating a `<video>` element with an
|
| + * inlined data source and calling `play()` on it. (Inspired by [Modernizr](https://github.com/Modernizr/Modernizr/blob/master/feature-detects/video/autoplay.js).)
|
| + *
|
| + * If you would rather not incur the minimal overhead involved in going through this process, you can explicitly set
|
| + * `playsupported` to `true` or `false` when initializing `<google-youtube>`. This is only recommended if you know that
|
| + * your web app will never (or only) be used on mobile browsers.
|
| + */
|
| + playsupported: {
|
| + type: Boolean,
|
| + value: null,
|
| + notify: true
|
| + },
|
| +
|
| + /**
|
| + * "1" if video should start automatically
|
| + */
|
| + autoplay: {
|
| + type: Number,
|
| + value: 0
|
| + },
|
| + /**
|
| + * Whether playback has started.
|
| + *
|
| + * This defaults to `false` and is set to `true` once the first 'playing' event is fired by
|
| + * the underlying YouTube Player API.
|
| + *
|
| + * Once set to `true`, it will remain that way indefinitely.
|
| + * Paused/buffering/ended events won't cause `playbackstarted` to reset to `false`.
|
| + * Nor will loading a new video into the player.
|
| + */
|
| + playbackstarted: {
|
| + type: Boolean,
|
| + value: false,
|
| + notify: true
|
| + },
|
| +
|
| + /**
|
| + * Sets the height of the player on the page.
|
| + * Accepts anything valid for a CSS measurement, e.g. '200px' or '50%'.
|
| + * If the unit of measurement is left off, 'px' is assumed.
|
| + */
|
| + height: {
|
| + type: String,
|
| + value: '270px'
|
| + },
|
| +
|
| + /**
|
| + * Sets the width of the player on the page.
|
| + * Accepts anything valid for a CSS measurement, e.g. '200px' or '50%'.
|
| + * If the unit of measurement is left off, 'px' is assumed.
|
| + */
|
| + width: {
|
| + type: String,
|
| + value:'480px'
|
| + },
|
| +
|
| + /**
|
| + * Exposes the current player state.
|
| + * Using this attribute is an alternative to listening to `google-youtube-state-change` events,
|
| + * and can simplify the logic in templates with conditional binding.
|
| + *
|
| + * The [possible values](https://developers.google.com/youtube/iframe_api_reference#onStateChange):
|
| + * - -1 (unstarted)
|
| + * - 0 (ended)
|
| + * - 1 (playing)
|
| + * - 2 (paused)
|
| + * - 3 (buffering)
|
| + * - 5 (video cued)
|
| + */
|
| + state: {
|
| + type: Number,
|
| + value: -1,
|
| + notify: true
|
| + },
|
| +
|
| + /**
|
| + * Exposes the current playback time, in seconds.
|
| + *
|
| + * You can divide this value by the `duration` to determine the playback percentage.
|
| + */
|
| + currenttime: {
|
| + type: Number,
|
| + value: 0,
|
| + notify: true
|
| + },
|
| +
|
| + /**
|
| + * Exposes the video duration, in seconds.
|
| + *
|
| + * You can divide the `currenttime` to determine the playback percentage.
|
| + *
|
| + * @attribute duration
|
| + * @type number
|
| + */
|
| + duration: {
|
| + type: Number,
|
| + value: 1, // To avoid divide-by-zero errors if used before video is cued.
|
| + notify: true
|
| + },
|
| +
|
| + /**
|
| + * Exposes the current playback time, formatted as a (HH:)MM:SS string.
|
| + */
|
| + currenttimeformatted: {
|
| + type: String,
|
| + value: '0:00',
|
| + notify: true
|
| + },
|
| +
|
| + /**
|
| + * Exposes the video duration, formatted as a (HH:)MM:SS string.
|
| + */
|
| + durationformatted: {
|
| + type: String,
|
| + value: '0:00', // To avoid divide-by-zero errors if used before video is cued.
|
| + notify: true
|
| + },
|
| +
|
| + /**
|
| + * The fraction of the bytes that have been loaded for the current video, in the range [0-1].
|
| + */
|
| + fractionloaded: {
|
| + type: Number,
|
| + value: 0,
|
| + notify: true
|
| + },
|
| +
|
| + /**
|
| + * A shorthand to enable a set of player attributes that, used together, simulate a "chromeless" YouTube player.
|
| + *
|
| + * Equivalent to setting the following attributes:
|
| + * - `controls="0"`
|
| + * - `modestbranding="1"`
|
| + * - `showinfo="0"`
|
| + * - `iv_load_policy="3"`
|
| + * - `rel="0"`
|
| + *
|
| + * The "chromeless" player has minimal YouTube branding in cued state, and the native controls
|
| + * will be disabled during playback. Creating your own custom play/pause/etc. controls is recommended.
|
| + */
|
| + chromeless: {
|
| + type: Boolean,
|
| + value: false
|
| + },
|
| + /**
|
| + * The URL of an image to use as a custom thumbnail.
|
| + *
|
| + * This is optional; if not provided, the standard YouTube embed (which uses the thumbnail associated
|
| + * with the video on YouTube) will be used.
|
| + *
|
| + * If `thumbnail` is set, than an `<img>` containing the thumbnail will be used in lieu of the actual
|
| + * YouTube embed. When the thumbnail is clicked, the `<img>` is swapped out for the actual YouTube embed,
|
| + * which will have [`autoplay=1`](https://developers.google.com/youtube/player_parameters#autoplay) set by default (in additional to any other player parameters specified on this element).
|
| + *
|
| + * Please note that `autoplay=1` won't actually autoplay videos on mobile browsers, so two taps will be required
|
| + * to play the video there. Also, on desktop browsers, setting `autoplay=1` will prevent the playback
|
| + * from [incrementing the view count](https://support.google.com/youtube/answer/1714329) for the video.
|
| + */
|
| + thumbnail: {
|
| + type: String,
|
| + value: ''
|
| + },
|
| +
|
| + /**
|
| + * If `fluid` is set, then the player will set its width to 100% to fill
|
| + * the parent container, while adding `padding-top` to preserve the
|
| + * aspect ratio provided by `width` and `height`. If `width` and `height`
|
| + * have not been set, the player will fall back to a 16:9 aspect ratio.
|
| + * This is useful for responsive designs where you don't want to
|
| + * introduce letterboxing on your video.
|
| + */
|
| + fluid: {
|
| + type: Boolean,
|
| + value: false
|
| + }
|
| +
|
| + },
|
| +
|
| + _computeContainerStyle: function(width, height) {
|
| + return 'width:' + width + '; height:' + height;
|
| + },
|
| + /**
|
| + * Detects whether programmatic <video>.play() is supported in the current browser.
|
| + *
|
| + * This is triggered via on-ironlocalstorage-load. The logic is:
|
| + * - If playsupported is explicitly set to true or false on the element, use that.
|
| + * - Otherwise, if there's a cached value in localStorage, use that.
|
| + * - Otherwise, create a hidden <video> element and call play() on it:
|
| + * - If playback starts, playsupported is true.
|
| + * - If playback doesn't start (within 500ms), playsupported is false.
|
| + * - Whatever happens, cache the result in localStorage.
|
| + */
|
| + _determinePlaySupported: function() {
|
| + // If playsupported isn't already being overridden by the page using this component, then attempt
|
| + // to determine if it's supported.
|
| + // This is deliberately checking with ==, to match either undefined or null.
|
| + if (this.playsupported == null) {
|
| + // If we don't have the results of a previous test cached in localStorage, then run a new playback test.
|
| + if (this._playsupportedLocalStorage == null) {
|
| + var timeout;
|
| + var videoElement = document.createElement('video');
|
| +
|
| + if ('play' in videoElement) {
|
| + videoElement.id = 'playtest';
|
| +
|
| + var mp4Source = document.createElement('source');
|
| + mp4Source.src = "data:video/mp4;base64,AAAAFGZ0eXBNU05WAAACAE1TTlYAAAOUbW9vdgAAAGxtdmhkAAAAAM9ghv7PYIb+AAACWAAACu8AAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAnh0cmFrAAAAXHRraGQAAAAHz2CG/s9ghv4AAAABAAAAAAAACu8AAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAFAAAAA4AAAAAAHgbWRpYQAAACBtZGhkAAAAAM9ghv7PYIb+AAALuAAANq8AAAAAAAAAIWhkbHIAAAAAbWhscnZpZGVBVlMgAAAAAAABAB4AAAABl21pbmYAAAAUdm1oZAAAAAAAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAVdzdGJsAAAAp3N0c2QAAAAAAAAAAQAAAJdhdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAFAAOABIAAAASAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGP//AAAAEmNvbHJuY2xjAAEAAQABAAAAL2F2Y0MBTUAz/+EAGGdNQDOadCk/LgIgAAADACAAAAMA0eMGVAEABGjuPIAAAAAYc3R0cwAAAAAAAAABAAAADgAAA+gAAAAUc3RzcwAAAAAAAAABAAAAAQAAABxzdHNjAAAAAAAAAAEAAAABAAAADgAAAAEAAABMc3RzegAAAAAAAAAAAAAADgAAAE8AAAAOAAAADQAAAA0AAAANAAAADQAAAA0AAAANAAAADQAAAA0AAAANAAAADQAAAA4AAAAOAAAAFHN0Y28AAAAAAAAAAQAAA7AAAAA0dXVpZFVTTVQh0k/Ou4hpXPrJx0AAAAAcTVREVAABABIAAAAKVcQAAAAAAAEAAAAAAAAAqHV1aWRVU01UIdJPzruIaVz6ycdAAAAAkE1URFQABAAMAAAAC1XEAAACHAAeAAAABBXHAAEAQQBWAFMAIABNAGUAZABpAGEAAAAqAAAAASoOAAEAZABlAHQAZQBjAHQAXwBhAHUAdABvAHAAbABhAHkAAAAyAAAAA1XEAAEAMgAwADAANQBtAGUALwAwADcALwAwADYAMAA2ACAAMwA6ADUAOgAwAAABA21kYXQAAAAYZ01AM5p0KT8uAiAAAAMAIAAAAwDR4wZUAAAABGjuPIAAAAAnZYiAIAAR//eBLT+oL1eA2Nlb/edvwWZflzEVLlhlXtJvSAEGRA3ZAAAACkGaAQCyJ/8AFBAAAAAJQZoCATP/AOmBAAAACUGaAwGz/wDpgAAAAAlBmgQCM/8A6YEAAAAJQZoFArP/AOmBAAAACUGaBgMz/wDpgQAAAAlBmgcDs/8A6YEAAAAJQZoIBDP/AOmAAAAACUGaCQSz/wDpgAAAAAlBmgoFM/8A6YEAAAAJQZoLBbP/AOmAAAAACkGaDAYyJ/8AFBAAAAAKQZoNBrIv/4cMeQ==";
|
| + videoElement.appendChild(mp4Source);
|
| +
|
| + var webmSource = document.createElement('source');
|
| + webmSource.src = "data:video/webm;base64,GkXfo49CgoR3ZWJtQoeBAUKFgQEYU4BnAQAAAAAAF60RTZt0vE27jFOrhBVJqWZTrIIQA027jFOrhBZUrmtTrIIQbE27jFOrhBFNm3RTrIIXmU27jFOrhBxTu2tTrIIWs+xPvwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUmpZuQq17GDD0JATYCjbGliZWJtbCB2MC43LjcgKyBsaWJtYXRyb3NrYSB2MC44LjFXQY9BVlNNYXRyb3NrYUZpbGVEiYRFnEAARGGIBc2Lz1QNtgBzpJCy3XZ0KNuKNZS4+fDpFxzUFlSua9iu1teBAXPFhL4G+bmDgQG5gQGIgQFVqoEAnIEAbeeBASMxT4Q/gAAAVe6BAIaFVl9WUDiqgQEj44OEE95DVSK1nIN1bmTgkbCBULqBPJqBAFSwgVBUuoE87EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9DtnVB4eeBAKC4obaBAAAAkAMAnQEqUAA8AABHCIWFiIWEiAICAAamYnoOC6cfJa8f5Zvda4D+/7YOf//nNefQYACgnKGWgQFNANEBAAEQEAAYABhYL/QACIhgAPuC/rOgnKGWgQKbANEBAAEQEAAYABhYL/QACIhgAPuC/rKgnKGWgQPoANEBAAEQEAAYABhYL/QACIhgAPuC/rOgnKGWgQU1ANEBAAEQEAAYABhYL/QACIhgAPuC/rOgnKGWgQaDANEBAAEQEAAYABhYL/QACIhgAPuC/rKgnKGWgQfQANEBAAEQEAAYABhYL/QACIhgAPuC/rOgnKGWgQkdANEBAAEQEBRgAGFgv9AAIiGAAPuC/rOgnKGWgQprANEBAAEQEAAYABhYL/QACIhgAPuC/rKgnKGWgQu4ANEBAAEQEAAYABhYL/QACIhgAPuC/rOgnKGWgQ0FANEBAAEQEAAYABhYL/QACIhgAPuC/rOgnKGWgQ5TANEBAAEQEAAYABhYL/QACIhgAPuC/rKgnKGWgQ+gANEBAAEQEAAYABhYL/QACIhgAPuC/rOgnKGWgRDtANEBAAEQEAAYABhYL/QACIhgAPuC/rOgnKGWgRI7ANEBAAEQEAAYABhYL/QACIhgAPuC/rIcU7trQOC7jLOBALeH94EB8YIUzLuNs4IBTbeH94EB8YIUzLuNs4ICm7eH94EB8YIUzLuNs4ID6LeH94EB8YIUzLuNs4IFNbeH94EB8YIUzLuNs4IGg7eH94EB8YIUzLuNs4IH0LeH94EB8YIUzLuNs4IJHbeH94EB8YIUzLuNs4IKa7eH94EB8YIUzLuNs4ILuLeH94EB8YIUzLuNs4INBbeH94EB8YIUzLuNs4IOU7eH94EB8YIUzLuNs4IPoLeH94EB8YIUzLuNs4IQ7beH94EB8YIUzLuNs4ISO7eH94EB8YIUzBFNm3SPTbuMU6uEH0O2dVOsghTM";
|
| + videoElement.appendChild(webmSource);
|
| +
|
| + document.body.appendChild(videoElement);
|
| +
|
| + this.async(function() {
|
| + // Ideally, we'll get a 'playing' event if we're on a browser that supports programmatic play().
|
| + videoElement.onplaying = function(e) {
|
| + clearTimeout(timeout);
|
| +
|
| + this.playsupported = (e && e.type === 'playing') || videoElement.currentTime !== 0;
|
| + this._playsupportedLocalStorage = this.playsupported;
|
| +
|
| + videoElement.onplaying = null;
|
| +
|
| + document.body.removeChild(videoElement);
|
| + }.bind(this);
|
| +
|
| + // If we haven't received a 'playing' event within 500ms, then we're most likely on a browser that doesn't
|
| + // support programmatic plays. Do a final check after 500ms and set this.playsupported at that point.
|
| + timeout = setTimeout(videoElement.onplaying, 500);
|
| +
|
| + // Try to initiate playback...
|
| + videoElement.play();
|
| + });
|
| + } else {
|
| + // If there's no play() method then we know that it's no supported.
|
| + this.playsupported = false;
|
| + this._playsupportedLocalStorage = false;
|
| + }
|
| + } else {
|
| + // If we do have the results of a previous test cached, then just use that.
|
| + // A browser's support for <video>.play() isn't likely to change.
|
| + this.playsupported = this._playsupportedLocalStorage;
|
| + }
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Sets fluid width/height.
|
| + *
|
| + * If the fluid attribute is set, the aspect ratio of the video will
|
| + * be inferred (if set in pixels), or assumed to be 16:9. The element
|
| + * will give itself enough top padding to force the player to use the
|
| + * correct aspect ratio, even as the screen size changes.
|
| + *
|
| + */
|
| + ready: function() {
|
| + if (this.hasAttribute('fluid')) {
|
| + var ratio = parseInt(this.height, 10) / parseInt(this.width, 10);
|
| + if (isNaN(ratio)) {
|
| + ratio = 9/16;
|
| + }
|
| + ratio *= 100;
|
| + this.width = '100%';
|
| + this.height = 'auto';
|
| + this.style['padding-top'] = ratio + '%';
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Clean up the underlying Player `<iframe>` when we're removed from the DOM.
|
| + */
|
| + detached: function() {
|
| + if (this._player) {
|
| + this._player.destroy();
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Plays the current video.
|
| + *
|
| + * Note that on certain mobile browsers, playback
|
| + * [can't be initiated programmatically](https://developers.google.com/youtube/iframe_api_reference#Mobile_considerations).
|
| + *
|
| + * If `this.playsupported` is not `true`, calling `play()` will have no effect.
|
| + *
|
| + * @method play
|
| + */
|
| + play: function() {
|
| + if (this._player && this._player.playVideo && this.playsupported) {
|
| + this._player.playVideo();
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Modifies the volume of the current video.
|
| + *
|
| + * Developers should take care not to break expected user experience by programmatically
|
| + * modifying the volume on mobile browsers.
|
| + * Note that the YouTube player, in addition, does not display volume controls in a
|
| + * mobile environment.
|
| + *
|
| + * @method setVolume
|
| + * @param {number} volume The new volume, an integer between 0 (muted) and 100 (loudest).
|
| + */
|
| + setVolume: function(volume) {
|
| + if (this._player && this._player.setVolume) {
|
| + this._player.setVolume(volume);
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Mutes the current video.
|
| + *
|
| + * Developers should take care not to break expected user experience by programmatically
|
| + * modifying the volume on mobile browsers.
|
| + * Note that the YouTube player, in addition, does not display volume controls in a
|
| + * mobile environment.
|
| + *
|
| + * @method mute
|
| + */
|
| + mute: function() {
|
| + if (this._player && this._player.mute) {
|
| + this._player.mute();
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Unmutes the current video.
|
| + *
|
| + * Developers should take care not to break expected user experience by programmatically
|
| + * modifying the volume on mobile browsers.
|
| + * Note that the YouTube player, in addition, does not display volume controls in a
|
| + * mobile environment.
|
| + *
|
| + * @method unMute
|
| + */
|
| + unMute: function() {
|
| + if (this._player && this._player.unMute) {
|
| + this._player.unMute();
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Pauses the current video.
|
| + *
|
| + * @method pause
|
| + */
|
| + pause: function() {
|
| + if (this._player && this._player.pauseVideo) {
|
| + this._player.pauseVideo();
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Skips ahead (or back) to the specified number of seconds.
|
| + *
|
| + * @method seekTo
|
| + * @param {number} seconds Number of seconds to seek to.
|
| + */
|
| + seekTo: function(seconds) {
|
| + if (this._player && this._player.seekTo) {
|
| + this._player.seekTo(seconds, true);
|
| +
|
| + // Explicitly call _updatePlaybackStats() to ensure that the new playback info is
|
| + // reflected in the bound attributes.
|
| + // The 100ms delay is somewhat arbitrary, but the YouTube player does need time to
|
| + // update its internal state following the call to player.seekTo().
|
| + this.async(function() {
|
| + this._updatePlaybackStats();
|
| + }, null, 100);
|
| + }
|
| + },
|
| +
|
| + _videoIdChanged: function() {
|
| + this.currenttime = 0;
|
| + this.currenttimeformatted = this._toHHMMSS(0);
|
| + this.fractionloaded = 0;
|
| + this.duration = 1;
|
| + this.durationformatted = this._toHHMMSS(0);
|
| +
|
| + if (!this._player || !this._player.cueVideoById) {
|
| + this._pendingVideoId = this.videoId;
|
| + } else {
|
| + // Figure out whether we should cue or load (which will autoplay) the next video.
|
| + if (this.playsupported && this.attributes['autoplay'] && this.attributes['autoplay'].value == '1') {
|
| + this._player.loadVideoById(this.videoId);
|
| + } else {
|
| + this._player.cueVideoById(this.videoId);
|
| + }
|
| + }
|
| + },
|
| +
|
| + _player: null,
|
| + __updatePlaybackStatsInterval: null,
|
| + _pendingVideoId: '',
|
| +
|
| + _apiLoad: function() {
|
| + // Establish some defaults. Attributes set on the google-youtube element
|
| + // can override defaults, or specify additional player parameters. See
|
| + // https://developers.google.com/youtube/player_parameters
|
| + var playerVars = {
|
| + playsinline: 1,
|
| + controls: 2,
|
| + autohide: 1,
|
| + // This will (intentionally) be overwritten if this.attributes['autoplay'] is set.
|
| + autoplay: this.autoplay
|
| + };
|
| +
|
| + if (this.chromeless) {
|
| + playerVars.controls = 0;
|
| + playerVars.modestbranding = 1;
|
| + playerVars.showinfo = 0;
|
| + // Disable annotations.
|
| + playerVars.iv_load_policy = 3;
|
| + // Disable related videos on the end screen.
|
| + playerVars.rel = 0;
|
| + }
|
| +
|
| + for (var i = 0; i < this.attributes.length; i++) {
|
| + var attribute = this.attributes[i];
|
| + playerVars[attribute.nodeName] = attribute.value;
|
| + }
|
| +
|
| + this._player = new YT.Player(this.$.player, {
|
| + videoId: this.videoId,
|
| + width: '100%',
|
| + height: '100%',
|
| + playerVars: playerVars,
|
| + events: {
|
| + onReady: function(e) {
|
| + if (this._pendingVideoId && this._pendingVideoId != this.videoId) {
|
| + this._player.cueVideoById(this._pendingVideoId);
|
| + this._pendingVideoId = '';
|
| + }
|
| +
|
| + this.fire('google-youtube-ready', e);
|
| + }.bind(this),
|
| + onStateChange: function(e) {
|
| + this.state = e.data;
|
| +
|
| + // The YouTube Player API only exposes playback data about a video once
|
| + // playback has begun.
|
| + if (this.state == 1) {
|
| + this.playbackstarted = true;
|
| +
|
| + // After playback has begun, play() can always be used to resume playback if the video is paused.
|
| + this.playsupported = true;
|
| +
|
| + this.duration = this._player.getDuration();
|
| + this.durationformatted = this._toHHMMSS(this.duration);
|
| +
|
| + if (!this.__updatePlaybackStatsInterval) {
|
| + this.__updatePlaybackStatsInterval = setInterval(this._updatePlaybackStats.bind(this), 1000);
|
| + }
|
| + } else {
|
| + // We only need to update the stats if the video is playing.
|
| + if (this.__updatePlaybackStatsInterval) {
|
| + clearInterval(this.__updatePlaybackStatsInterval);
|
| + this.__updatePlaybackStatsInterval = null;
|
| + }
|
| + }
|
| +
|
| + this.fire('google-youtube-state-change', e);
|
| + }.bind(this),
|
| + onError: function(e) {
|
| + // Set the player state to 0 ('ended'), since playback will have stopped.
|
| + this.state = 0;
|
| +
|
| + this.fire('google-youtube-error', e);
|
| + }.bind(this)
|
| + }
|
| + });
|
| + },
|
| +
|
| + _updatePlaybackStats: function() {
|
| + this.currenttime = Math.round(this._player.getCurrentTime());
|
| + this.currenttimeformatted = this._toHHMMSS(this.currenttime);
|
| + this.fractionloaded = this._player.getVideoLoadedFraction();
|
| + },
|
| +
|
| + _toHHMMSS: function(totalSeconds) {
|
| + var hours = Math.floor(totalSeconds / 3600);
|
| + totalSeconds -= hours * 3600;
|
| + var minutes = Math.floor(totalSeconds / 60);
|
| + var seconds = Math.round(totalSeconds - (minutes * 60));
|
| +
|
| + var hourPortion = '';
|
| + if (hours > 0) {
|
| + hourPortion += hours + ':';
|
| +
|
| + if (minutes < 10) {
|
| + minutes = '0' + minutes;
|
| + }
|
| + }
|
| +
|
| + if (seconds < 10) {
|
| + seconds = '0' + seconds;
|
| + }
|
| +
|
| + return hourPortion + minutes + ':' + seconds;
|
| + },
|
| +
|
| + _handleThumbnailTap: function() {
|
| + this.autoplay = 1;
|
| + this.thumbnail = '';
|
| + }
|
| + });
|
| +</script>
|
|
|