From 3070d7b2a3b96609eace60825c721951c85405cc Mon Sep 17 00:00:00 2001
From: François Frisch
Date: Sat, 17 Mar 2012 18:05:23 -0700
Subject: Adding the youtube player
---
.../examples/youtube-channel-example/index.html | 44 +++
.../examples/youtube-channel-example/package.json | 7 +
.../examples/youtube-channel-example/style.css | 47 +++
.../youtube-channel-example.js | 8 +
.../youtube-channel.reel/youtube-channel.html | 34 ++
.../youtube-channel.reel/youtube-channel.js | 101 ++++++
.../montage/test/ui/youtube-player-spec.js | 363 +++++++++++++++++++++
.../youtube-player-test/youtube-player-test.html | 47 +++
.../ui/youtube-player-test/youtube-player-test.js | 9 +
.../ui/youtube-player.reel/youtube-player.html | 29 ++
.../ui/youtube-player.reel/youtube-player.js | 179 ++++++++++
11 files changed, 868 insertions(+)
create mode 100755 node_modules/montage/examples/youtube-channel-example/index.html
create mode 100755 node_modules/montage/examples/youtube-channel-example/package.json
create mode 100755 node_modules/montage/examples/youtube-channel-example/style.css
create mode 100755 node_modules/montage/examples/youtube-channel-example/youtube-channel-example.js
create mode 100644 node_modules/montage/examples/youtube-channel-example/youtube-channel.reel/youtube-channel.html
create mode 100644 node_modules/montage/examples/youtube-channel-example/youtube-channel.reel/youtube-channel.js
create mode 100755 node_modules/montage/test/ui/youtube-player-spec.js
create mode 100644 node_modules/montage/test/ui/youtube-player-test/youtube-player-test.html
create mode 100755 node_modules/montage/test/ui/youtube-player-test/youtube-player-test.js
create mode 100644 node_modules/montage/ui/youtube-player.reel/youtube-player.html
create mode 100644 node_modules/montage/ui/youtube-player.reel/youtube-player.js
(limited to 'node_modules')
diff --git a/node_modules/montage/examples/youtube-channel-example/index.html b/node_modules/montage/examples/youtube-channel-example/index.html
new file mode 100755
index 00000000..71baba29
--- /dev/null
+++ b/node_modules/montage/examples/youtube-channel-example/index.html
@@ -0,0 +1,44 @@
+
+
+
+
+ Youtube Channel
+
+
+
+
+
+
+
+
diff --git a/node_modules/montage/examples/youtube-channel-example/package.json b/node_modules/montage/examples/youtube-channel-example/package.json
new file mode 100755
index 00000000..ecfbdd8a
--- /dev/null
+++ b/node_modules/montage/examples/youtube-channel-example/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "youtube-channel-example",
+ "version": "0.0.0",
+ "mappings": {
+ "montage": "../../"
+ }
+}
\ No newline at end of file
diff --git a/node_modules/montage/examples/youtube-channel-example/style.css b/node_modules/montage/examples/youtube-channel-example/style.css
new file mode 100755
index 00000000..c281cd65
--- /dev/null
+++ b/node_modules/montage/examples/youtube-channel-example/style.css
@@ -0,0 +1,47 @@
+/*
+ This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
+ */
+
+
+/* Base ----------------------------- */
+
+html {
+ background-color: hsl(0,0%,85%);
+ height: 100%;
+}
+
+body {
+ margin: 0;
+ width: 100%;
+ height: 100%;
+ display: -webkit-box;
+ -webkit-box-align: center;
+ -webkit-box-pack: center;
+
+ display: -moz-box;
+ -moz-box-align: center;
+ -moz-box-pack: center;
+}
+
+
+/* Converter ----------------------------- */
+
+.youtube-channel-example {
+ padding: 10px;
+ text-shadow: #fff 0 1px 0;
+ border-radius: 8px;
+ background-color: hsl(0,0%,95%);
+ box-shadow: inset 0px 1px 2px 1px hsla(0,0%,100%,1), 0px 2px 5px hsla(0,0%,0%,.1);
+}
+
+.youtube-channel-example #title {
+ margin: 0 0 5px 0;
+ text-align: center;
+ font: 24px/40px "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
+}
+
+.youtube-channel-example-url {
+ width: 100%;
+}
diff --git a/node_modules/montage/examples/youtube-channel-example/youtube-channel-example.js b/node_modules/montage/examples/youtube-channel-example/youtube-channel-example.js
new file mode 100755
index 00000000..4ca12757
--- /dev/null
+++ b/node_modules/montage/examples/youtube-channel-example/youtube-channel-example.js
@@ -0,0 +1,8 @@
+/*
+ This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
+ */
+var Montage = require("montage").Montage;
+
+exports.YoutubeChannelExample = Montage.create(Converter, {});
diff --git a/node_modules/montage/examples/youtube-channel-example/youtube-channel.reel/youtube-channel.html b/node_modules/montage/examples/youtube-channel-example/youtube-channel.reel/youtube-channel.html
new file mode 100644
index 00000000..8514f5ce
--- /dev/null
+++ b/node_modules/montage/examples/youtube-channel-example/youtube-channel.reel/youtube-channel.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/node_modules/montage/examples/youtube-channel-example/youtube-channel.reel/youtube-channel.js b/node_modules/montage/examples/youtube-channel-example/youtube-channel.reel/youtube-channel.js
new file mode 100644
index 00000000..1f5aa2d1
--- /dev/null
+++ b/node_modules/montage/examples/youtube-channel-example/youtube-channel.reel/youtube-channel.js
@@ -0,0 +1,101 @@
+/*
+ This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
+ */
+/*global require,exports*/
+var Montage = require("montage").Montage,
+ Component = require("montage/ui/component").Component,
+ Uuid = require("montage/core/uuid").Uuid;
+
+
+var YoutubeChannel = exports.YoutubeChannel = Montage.create(Component, {
+
+ _userRe: {
+ enumerable: false,
+ value: /youtube.com\/(user\/)?([a-z0-9]+)/i
+ },
+
+ _channelUrl: {
+ enumerable: false,
+ value: null
+ },
+ channelUrl: {
+ depends: ["channel"],
+ get: function() {
+ return this._channelUrl;
+ },
+ set: function(value, fromChannel) {
+ if (this._channelUrl !== value) {
+ this._channelUrl = value;
+
+ // prevent infinite loop
+ if (!fromChannel) {
+ var match = this._userRe.exec(value);
+ if (match && match[2]) {
+ Object.getPropertyDescriptor(this, "channel").set.call(this, match[2], true);
+ }
+ }
+ }
+ }
+ },
+
+ _channel: {
+ enumerable: false,
+ value: null
+ },
+ channel: {
+ get: function() {
+ return this._channel;
+ },
+ set: function(value, fromUrl) {
+ if (this._channel !== value) {
+ this._channel = value;
+
+ // prevent infinite loop
+ if (!fromUrl) {
+ Object.getPropertyDescriptor(this, "channelUrl").set.call(this, "http://www.youtube.com/user/" + value, true);
+ }
+
+ this._loadChannel();
+ }
+ }
+ },
+
+ _loadChannel: {
+ enumerable: false,
+ value: function() {
+ var self = this;
+
+ var callbackName = "scriptCallback" + Uuid.generate().replace(/-/g, "_");
+
+ window[callbackName] = function(data) {
+ self.handleData(data);
+ delete window[callbackName];
+ };
+
+ // create url
+ var url = "http://gdata.youtube.com/feeds/api/users/" + this._channel + "/uploads?v=2&alt=json-in-script&callback=" + callbackName;
+
+ var script = document.createElement("script");
+ script.src = url;
+ this._element.appendChild(script);
+ }
+ },
+
+ handleData: {
+ value: function(data) {
+ var entries = data.feed.entry || [];
+
+ var playlist = [];
+
+ for (var i = 0, len = entries.length; i < len; i++) {
+ var id = entries[i]["media$group"]["yt$videoid"]["$t"];
+ playlist.push(id);
+ }
+
+ this.player.playlist = playlist;
+ }
+ }
+
+});
\ No newline at end of file
diff --git a/node_modules/montage/test/ui/youtube-player-spec.js b/node_modules/montage/test/ui/youtube-player-spec.js
new file mode 100755
index 00000000..dc57e3ec
--- /dev/null
+++ b/node_modules/montage/test/ui/youtube-player-spec.js
@@ -0,0 +1,363 @@
+/*
+ This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
+ */
+var Montage = require("montage").Montage,
+ TestPageLoader = require("support/testpageloader").TestPageLoader;
+
+var testPage = TestPageLoader.queueTest("buttontest", function() {
+ var test = testPage.test;
+
+ var click = function(component, el, fn) {
+ el = el || component.element;
+
+ var listener = testPage.addListener(component, fn);
+
+ testPage.mouseEvent({target: el}, "mousedown");
+ testPage.mouseEvent({target: el}, "mouseup");
+ testPage.mouseEvent({target: el}, "click");
+
+ // Return this so that it can be checked in tha calling function.
+ return listener;
+ };
+ var testButton = function(component, value) {
+ expect(component).toBeDefined();
+ expect(click(component)).toHaveBeenCalled();
+ expect(component.label).toBe(value);
+ };
+
+ describe("ui/button-spec", function() {
+ it("should load", function() {
+ expect(testPage.loaded).toBe(true);
+ });
+
+ describe("button", function(){
+
+ it("can be created from a div element", function(){
+ testButton(test.divbutton, "div button");
+ });
+ it("can be created from an input element", function(){
+ testButton(test.inputbutton, "input button");
+ });
+ it("can be created from a button element", function(){
+ testButton(test.buttonbutton, "button button");
+ });
+
+ describe("disabled property", function(){
+ it("is taken from the element's disabled attribute", function() {
+ expect(test.disabledbutton.disabled).toBe(true);
+ expect(click(test.disabledbutton)).not.toHaveBeenCalled();
+ expect(test.disabledinput.disabled).toBe(true);
+ expect(click(test.disabledinput)).not.toHaveBeenCalled();
+ expect(test.inputbutton.disabled).toBe(false);
+ });
+ it("can be set", function(){
+ expect(test.disabledbutton.disabled).toBe(true);
+ test.disabledbutton.disabled = false;
+ expect(test.disabledbutton.disabled).toBe(false);
+ // TODO click the button and check that it wasn't pressed
+
+ expect(test.disabledinput.disabled).toBe(true);
+ test.disabledinput.disabled = false;
+ expect(test.disabledinput.disabled).toBe(false);
+ // TODO click the button and check that it wasn't pressed
+ });
+ it("can can be set in the serialization", function(){
+ expect(test.disabledinputszn.disabled).toBe(true);
+ // TODO check button pressibility
+ });
+ it("is the inverse of the enabled property", function(){
+ expect(test.enabledinputszn.disabled).toBe(false);
+ expect(test.enabledinputszn.enabled).toBe(true);
+ test.enabledinputszn.enabled = false;
+ expect(test.enabledinputszn.disabled).toBe(true);
+ expect(test.enabledinputszn.enabled).toBe(false);
+ // TODO click the button and check that it wasn't pressed
+ });
+ });
+
+ describe("label property", function() {
+ it("is set from the serialization on a button", function() {
+ expect(test.buttonlabelszn.label).toBe("pass");
+ testPage.waitForDraw();
+ runs(function(){
+ expect(test.buttonlabelszn.element.firstChild.data).toBe("pass");
+ });
+ });
+ it("is set from the serialization on an input", function() {
+ expect(test.inputlabelszn.label).toBe("pass");
+ expect(test.inputlabelszn.element.value).toBe("pass");
+ });
+ it("sets the value on an input", function() {
+ expect(test.inputbutton.label).toBe("input button");
+ test.inputbutton.label = "label pass";
+ expect(test.inputbutton.label).toBe("label pass");
+ expect(test.inputbutton.value).toBe("label pass");
+ test.inputbutton.label = "input button";
+ });
+ it("sets the first child on a non-input element", function() {
+ expect(test.buttonbutton.label).toBe("button button");
+ test.buttonbutton.label = "label pass";
+ expect(test.buttonbutton.label).toBe("label pass");
+
+ testPage.waitForDraw();
+ runs(function(){
+ expect(test.buttonbutton.element.firstChild.data).toBe("label pass");
+ test.buttonbutton.label = "button button";
+ });
+ });
+ });
+
+ describe("value property", function() {
+ it("is set from the value on an input", function() {
+ expect(test.inputbutton.element.value).toBe("input button");
+ expect(test.inputbutton.value).toBe("input button");
+ });
+ it("is set by the label property in the serialization", function() {
+ expect(test.inputlabelszn.label).toBe("pass");
+ //expect(test.inputlabelszn.value).toBe("pass");
+ });
+ it("sets the label property when using an input element", function() {
+ expect(test.inputbutton.label).toBe("input button");
+ test.inputbutton.value = "value pass";
+ expect(test.inputbutton.value).toBe("value pass");
+ expect(test.inputbutton.label).toBe("value pass");
+ test.inputbutton.value = "input button";
+ });
+ it("doesn't set the label property when using a non-input element", function() {
+ expect(test.buttonbutton.label).toBe("button button");
+ test.buttonbutton.value = "value fail";
+ expect(test.buttonbutton.label).toBe("button button");
+ testPage.waitForDraw();
+ runs(function(){
+ expect(test.buttonbutton.element.firstChild.data).toBe("button button");
+ test.buttonbutton.value = "button button";
+ });
+ });
+
+ });
+
+
+ it("responds when child elements are clicked on", function(){
+ expect(click(test.buttonnested, test.buttonnested.element.firstChild)).toHaveBeenCalled();
+ });
+
+ it("supports converters for label", function(){
+ expect(test.converterbutton.label).toBe("PASS");
+ expect(test.converterbutton.element.value).toBe("PASS");
+ });
+
+ // TODO should be transplanted to the press-composer-spec
+ // it("correctly releases the pointer", function() {
+ // var l = testPage.addListener(test.scroll_button);
+
+ // testpage.mouseEvent({target: test.scroll_button.element}, "mousedown");;
+ // expect(test.scroll_button.active).toBe(true);
+ // test.scroll_button.surrenderPointer(test.scroll_button._observedPointer, null);
+ // expect(test.scroll_button.active).toBe(false);
+ // testPage.mouseEvent({target: test.scroll_button.element}, "mouseup");;
+
+ // expect(l).not.toHaveBeenCalled();
+
+ // });
+
+ if (window.Touch) {
+
+ describe("when supporting touch events", function() {
+
+ it("should dispatch an action event when a touchend follows a touchstart on a button", function() {
+
+ });
+
+ });
+
+ } else {
+
+ describe("when supporting mouse events", function() {
+ it("dispatches an action event when a mouseup follows a mousedown", function() {
+ expect(click(test.inputbutton)).toHaveBeenCalled();
+ });
+
+ it("does not dispatch an action event when a mouseup occurs after not previously receiving a mousedown", function() {
+ // reset interaction
+ // test.inputbutton._endInteraction();
+ var l = testPage.addListener(test.inputbutton);
+ testPage.mouseEvent({target: test.inputbutton.element}, "mouseup");;
+ expect(l).not.toHaveBeenCalled();
+ });
+
+ it("does not dispatch an action event when a mouseup occurs away from the button after a mousedown on a button", function() {
+ var l = testPage.addListener(test.inputbutton);
+
+ testpage.mouseEvent({target: test.inputbutton.element}, "mousedown");;
+ // Mouse up somewhere else
+ testPage.mouseEvent({target: test.divbutton.element}, "mouseup");;
+
+ expect(l).not.toHaveBeenCalled();
+ });
+ });
+ }
+
+ describe("inside a scroll view", function() {
+ it("fires an action event when clicked", function() {
+ testButton(test.scroll_button, "scroll button");
+ });
+ it("doesn't fire an action event when scroller is dragged", function() {
+ var el = test.scroll_button.element;
+ var scroll_el = test.scroll.element;
+
+ var listener = testPage.addListener(test.scroll_button);
+
+ var press_composer = test.scroll_button.composerList[0];
+
+ // mousedown
+ testPage.mouseEvent({target: el}, "mousedown");
+
+ expect(test.scroll_button.active).toBe(true);
+ expect(test.scroll_button.eventManager.isPointerClaimedByComponent(press_composer._observedPointer, press_composer)).toBe(true);
+
+ // Mouse move doesn't happen instantly
+ waits(10);
+ runs(function() {
+ // mouse move up
+ var moveEvent = document.createEvent("MouseEvent");
+ // Dispatch to scroll view, but use the coordinates from the
+ // button
+ moveEvent.initMouseEvent("mousemove", true, true, scroll_el.view, null,
+ el.offsetLeft, el.offsetTop - 100,
+ el.offsetLeft, el.offsetTop - 100,
+ false, false, false, false,
+ 0, null);
+ scroll_el.dispatchEvent(moveEvent);
+
+ expect(test.scroll_button.active).toBe(false);
+ expect(test.scroll_button.eventManager.isPointerClaimedByComponent(press_composer._observedPointer, press_composer)).toBe(false);
+
+ // mouse up
+ testPage.mouseEvent({target: el}, "mouseup");;
+
+ expect(listener).not.toHaveBeenCalled();
+ });
+
+ });
+ });
+ });
+
+ describe("toggle button", function() {
+ it("alternates between unpressed and pressed", function() {
+ expect(test.toggleinput.pressed).toBe(false);
+ expect(test.toggleinput.label).toBe("off");
+
+ click(test.toggleinput);
+ expect(test.toggleinput.pressed).toBe(true);
+ expect(test.toggleinput.label).toBe("on");
+
+ click(test.toggleinput);
+ expect(test.toggleinput.pressed).toBe(false);
+ expect(test.toggleinput.label).toBe("off");
+ });
+
+ describe("toggle()", function() {
+ it("swaps the state", function() {
+ test.toggleinput.pressed = false;
+ test.toggleinput.toggle();
+ expect(test.toggleinput.pressed).toBe(true);
+ test.toggleinput.toggle();
+ expect(test.toggleinput.pressed).toBe(false);
+ test.toggleinput.toggle();
+ expect(test.toggleinput.pressed).toBe(true);
+ });
+ });
+
+ describe("label property", function() {
+ it("alternates between unpressed and pressed", function() {
+ test.toggleinput.pressed = false;
+
+ // The expectations are in a closure because the draw can
+ // happen at any point after we click on the button
+ var checker = function(e) {
+ return function(){
+ expect(test.toggleinput.pressed).toBe(e);
+ expect(test.toggleinput.element.value).toBe((e)?"on":"off");
+ };
+ };
+
+ runs(checker(false));
+
+ runs(function(){ click(test.toggleinput); });
+ testPage.waitForDraw();
+ runs(checker(true));
+ });
+ it("changes pressed state when set to unpressedLabel or pressedLabel", function(){
+ test.toggleinput.pressed = false;
+ test.toggleinput.label = "on";
+ expect(test.toggleinput.pressed).toBe(true);
+ test.toggleinput.label = "off";
+ expect(test.toggleinput.pressed).toBe(false);
+ });
+ it("doesn't change pressed state when set to a non-matching string", function(){
+ expect(test.toggleinput.pressed).toBe(false);
+ test.toggleinput.label = "random";
+ expect(test.toggleinput.pressed).toBe(false);
+ expect(test.toggleinput.label).toBe("random");
+
+ test.toggleinput.pressed = true;
+ expect(test.toggleinput.label).toBe("on");
+ });
+ });
+ describe("unpressedLabel", function() {
+ it("is set as the value when the button is unpressed", function() {
+ test.toggleinput.pressed = false;
+ expect(test.toggleinput.label).toBe("off");
+ test.toggleinput.unpressedLabel = "unpressed";
+ expect(test.toggleinput.label).toBe("unpressed");
+
+ testPage.waitForDraw();
+ runs(function(){
+ expect(test.toggleinput.element.value).toBe("unpressed");
+ });
+ });
+ it("is taken from `value` on init if the button is unpressed and unpressedLabel isn't set", function() {
+ expect(test.toggleinput2.unpressedLabel).toBe(test.toggleinput2.label);
+ });
+ });
+
+ describe("pressedLabel", function() {
+ it("is set as the value when the button is pressed", function() {
+ test.toggleinput.pressed = true;
+ expect(test.toggleinput.label).toBe("on");
+ test.toggleinput.pressedLabel = "pressed";
+ expect(test.toggleinput.label).toBe("pressed");
+
+ testPage.waitForDraw();
+ runs(function(){
+ expect(test.toggleinput.element.value).toBe("pressed");
+ });
+ });
+ it("is taken from `value` on init if the button is pressed and pressedLabel isn't set", function() {
+ expect(test.toggleinput3.pressedLabel).toBe(test.toggleinput3.label);
+ });
+ });
+
+ describe("pressedClass", function() {
+ it("is not in the classList when the button is unpressed", function() {
+ test.toggleinput.pressed = false;
+
+ testPage.waitForDraw();
+ runs(function(){
+ expect(test.toggleinput.element.className).not.toContain("pressed");
+ });
+ });
+ it("is added to the classList when the button is pressed", function() {
+ test.toggleinput.pressed = true;
+
+ testPage.waitForDraw();
+ runs(function(){
+ expect(test.toggleinput.element.className).toContain("pressed");
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/node_modules/montage/test/ui/youtube-player-test/youtube-player-test.html b/node_modules/montage/test/ui/youtube-player-test/youtube-player-test.html
new file mode 100644
index 00000000..a82f50e9
--- /dev/null
+++ b/node_modules/montage/test/ui/youtube-player-test/youtube-player-test.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+ Youtube player test
+
+
+
+
+
+ Youtube Player test
+
+ Basic
+
+
+
+
diff --git a/node_modules/montage/test/ui/youtube-player-test/youtube-player-test.js b/node_modules/montage/test/ui/youtube-player-test/youtube-player-test.js
new file mode 100755
index 00000000..8319fc93
--- /dev/null
+++ b/node_modules/montage/test/ui/youtube-player-test/youtube-player-test.js
@@ -0,0 +1,9 @@
+/*
+ This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
+ */
+var Montage = require("montage").Montage,
+ YoutubePlayer = require("montage/ui/youtube-player").YoutubePlayer;
+
+var YoutubePlayerTest = exports.YoutubePlayerTest = Montage.create(Montage, {});
diff --git a/node_modules/montage/ui/youtube-player.reel/youtube-player.html b/node_modules/montage/ui/youtube-player.reel/youtube-player.html
new file mode 100644
index 00000000..ae757626
--- /dev/null
+++ b/node_modules/montage/ui/youtube-player.reel/youtube-player.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/node_modules/montage/ui/youtube-player.reel/youtube-player.js b/node_modules/montage/ui/youtube-player.reel/youtube-player.js
new file mode 100644
index 00000000..2f7709d7
--- /dev/null
+++ b/node_modules/montage/ui/youtube-player.reel/youtube-player.js
@@ -0,0 +1,179 @@
+//data="https://www.youtube.com/v/u1zgFlCw8Aw?version=3&enablejsapi=1&playerapiid=ytplayer"
+/*
+ This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
+ */
+/*global require,exports*/
+var Montage = require("montage").Montage,
+ Component = require("ui/component").Component;
+
+var YoutubePlayer = exports.YoutubePlayer = Montage.create(Component, {
+
+ // Stores a queue of function calls to make on the player in the draw
+ // function
+ _playerQueue: {
+ enumerable: false,
+ value: []
+ },
+
+ _ready: {
+ enumerable: false,
+ value: false
+ },
+
+ _player: {
+ enumerable: false,
+ value: null
+ },
+ player: {
+ get: function() {
+ return this._player;
+ },
+ set: function(value) {
+ // TODO don't allow this to be changed
+ if (this._player !== value) {
+ this._player = value;
+ }
+ }
+ },
+
+ _autoplay: {
+ enumerable: false,
+ value: false
+ },
+ autoplay: {
+ get: function() {
+ return this._autoplay;
+ },
+ set: function(value) {
+ if (this._autoplay !== value) {
+ this._autoplay = value;
+ }
+ }
+ },
+
+ _videoId: {
+ enumerable: false,
+ value: null
+ },
+ videoId: {
+ get: function() {
+ return this._videoId;
+ },
+ set: function(value) {
+ if (this._videoId !== value) {
+ // TODO handle URLs as well
+ this._videoId = value;
+
+ // If the video isn't in the playlist, clear the playlist,
+ if (this._playlist && this._playlist.indexOf(value) === -1) {
+ this._playlist = null;
+ }
+ // TODO if the video is in the playlist use playVideoAt
+
+ if (this._autoplay) {
+ this._playerQueue.push(["loadVideoById", value]);
+ } else {
+ this._playerQueue.push(["cueVideoById", value]);
+ }
+ this.needsDraw = true;
+ }
+ }
+ },
+
+ _playlist: {
+ enumerable: false,
+ value: null
+ },
+ playlist: {
+ get: function() {
+ return this._playlist;
+ },
+ set: function(value) {
+ if (this._playlist !== value) {
+ this._playlist = value;
+
+ if (this._autoplay) {
+ this._playerQueue.push(["loadPlaylist", value]);
+ } else {
+ this._playerQueue.push(["cuePlaylist", value]);
+ }
+ this.needsDraw = true;
+ }
+ }
+ },
+
+ play: {
+ value: function() {
+ this._playerQueue.push("playVideo");
+ this.needsDraw = true;
+ }
+ },
+ pause: {
+ value: function() {
+ this._playerQueue.push("pauseVideo");
+ this.needsDraw = true;
+ }
+ },
+ stop: {
+ value: function() {
+ this._playerQueue.push("stopVideo");
+ this.needsDraw = true;
+ }
+ },
+
+ prepareForDraw: {
+ value: function() {
+ // Create the callback if it doesn't exist, and make it dispatch
+ // an event on the document instead
+ if (!window.onYouTubePlayerReady) {
+ window.onYouTubePlayerReady = function(playerId) {
+ var event = document.createEvent("CustomEvent");
+ event.initEvent("youtubePlayerReady", true, true);
+ event.playerId = playerId;
+ document.dispatchEvent(event);
+ };
+ }
+
+ document.addEventListener("youtubePlayerReady", this, false);
+
+ // If there's no videoId set one the doesn't exist
+ this._player.data = "https://www.youtube.com/v/" + (this._videoId || "xxxxxxxxxxx") + "?version=3&enablejsapi=1&playerapiid=" + this.uuid;
+ }
+ },
+
+ handleYoutubePlayerReady: {
+ value: function(event) {
+ if (event.playerId !== this.uuid) {
+ return;
+ }
+
+ this._ready = true;
+ this.needsDraw = true;
+ }
+ },
+
+ draw: {
+ value: function() {
+ if (!this._ready) {
+ return;
+ }
+
+ for (var i = 0, len = this._playerQueue.length; i < len; i++) {
+ var fnName, args;
+ if (typeof this._playerQueue[i] === "string") {
+ fnName = this._playerQueue[i];
+ args = [];
+ } else {
+ fnName = this._playerQueue[i].shift();
+ args = this._playerQueue[i];
+ }
+
+ this._player[fnName].apply(this._player, args);
+ }
+
+ this._playerQueue.length = 0;
+ }
+ }
+});
\ No newline at end of file
--
cgit v1.2.3