Adding float-no-zero branch hosted build

This commit is contained in:
ahocevar
2014-03-07 10:55:12 +01:00
parent 84cad42f6d
commit bd9092199b
1664 changed files with 731463 additions and 0 deletions
@@ -0,0 +1,631 @@
// Copyright 2009 The Closure Library Authors. 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 Wrapper on a Flash object embedded in the HTML page.
* This class contains routines for writing the HTML to create the Flash object
* using a goog.ui.Component approach. Tested on Firefox 1.5, 2 and 3, IE6, 7,
* Konqueror, Chrome and Safari.
*
* Based on http://go/flashobject.js
*
* Based on the following compatibility test suite:
* http://www.bobbyvandersluis.com/flashembed/testsuite/
*
* TODO(user): take a look at swfobject, and maybe use it instead of the current
* flash embedding method.
*
* Examples of usage:
*
* <pre>
* var flash = new goog.ui.media.FlashObject('http://hostname/flash.swf');
* flash.setFlashVar('myvar', 'foo');
* flash.render(goog.dom.getElement('parent'));
* </pre>
*
* TODO(user, jessan): create a goog.ui.media.BrowserInterfaceFlashObject that
* subclasses goog.ui.media.FlashObject to provide all the goodness of
* http://go/browserinterface.as
*
*/
goog.provide('goog.ui.media.FlashObject');
goog.provide('goog.ui.media.FlashObject.ScriptAccessLevel');
goog.provide('goog.ui.media.FlashObject.Wmodes');
goog.require('goog.asserts');
goog.require('goog.events.Event');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventType');
goog.require('goog.log');
goog.require('goog.object');
goog.require('goog.string');
goog.require('goog.structs.Map');
goog.require('goog.style');
goog.require('goog.ui.Component');
goog.require('goog.userAgent');
goog.require('goog.userAgent.flash');
/**
* A very simple flash wrapper, that allows you to create flash object
* programmatically, instead of embedding your own HTML. It extends
* {@link goog.ui.Component}, which makes it very easy to be embedded on the
* page.
*
* @param {string} flashUrl The flash SWF URL.
* @param {goog.dom.DomHelper=} opt_domHelper An optional DomHelper.
* @extends {goog.ui.Component}
* @constructor
*/
goog.ui.media.FlashObject = function(flashUrl, opt_domHelper) {
goog.ui.Component.call(this, opt_domHelper);
/**
* The URL of the flash movie to be embedded.
*
* @type {string}
* @private
*/
this.flashUrl_ = flashUrl;
/**
* An event handler used to handle events consistently between browsers.
* @type {goog.events.EventHandler}
* @private
*/
this.eventHandler_ = new goog.events.EventHandler(this);
/**
* A map of variables to be passed to the flash movie.
*
* @type {goog.structs.Map}
* @private
*/
this.flashVars_ = new goog.structs.Map();
};
goog.inherits(goog.ui.media.FlashObject, goog.ui.Component);
/**
* Different states of loaded-ness in which the SWF itself can be
*
* Talked about at:
* http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_12059&sliceId=1
*
* @enum {number}
* @private
*/
goog.ui.media.FlashObject.SwfReadyStates_ = {
LOADING: 0,
UNINITIALIZED: 1,
LOADED: 2,
INTERACTIVE: 3,
COMPLETE: 4
};
/**
* The different modes for displaying a SWF. Note that different wmodes
* can result in different bugs in different browsers and also that
* both OPAQUE and TRANSPARENT will result in a performance hit.
*
* @enum {string}
*/
goog.ui.media.FlashObject.Wmodes = {
/**
* Allows for z-ordering of the SWF.
*/
OPAQUE: 'opaque',
/**
* Allows for z-ordering of the SWF and plays the SWF with a transparent BG.
*/
TRANSPARENT: 'transparent',
/**
* The default wmode. Does not allow for z-ordering of the SWF.
*/
WINDOW: 'window'
};
/**
* The different levels of allowScriptAccess.
*
* Talked about at:
* http://kb2.adobe.com/cps/164/tn_16494.html
*
* @enum {string}
*/
goog.ui.media.FlashObject.ScriptAccessLevel = {
/*
* The flash object can always communicate with its container page.
*/
ALWAYS: 'always',
/*
* The flash object can only communicate with its container page if they are
* hosted in the same domain.
*/
SAME_DOMAIN: 'sameDomain',
/*
* The flash can not communicate with its container page.
*/
NEVER: 'never'
};
/**
* The component CSS namespace.
*
* @type {string}
*/
goog.ui.media.FlashObject.CSS_CLASS = goog.getCssName('goog-ui-media-flash');
/**
* The flash object CSS class.
*
* @type {string}
*/
goog.ui.media.FlashObject.FLASH_CSS_CLASS =
goog.getCssName('goog-ui-media-flash-object');
/**
* Template for the object tag for IE.
*
* @type {string}
* @private
*/
goog.ui.media.FlashObject.IE_HTML_ =
'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"' +
' id="%s"' +
' name="%s"' +
' class="%s"' +
'>' +
'<param name="movie" value="%s"/>' +
'<param name="quality" value="high"/>' +
'<param name="FlashVars" value="%s"/>' +
'<param name="bgcolor" value="%s"/>' +
'<param name="AllowScriptAccess" value="%s"/>' +
'<param name="allowFullScreen" value="true"/>' +
'<param name="SeamlessTabbing" value="false"/>' +
'%s' +
'</object>';
/**
* Template for the wmode param for IE.
*
* @type {string}
* @private
*/
goog.ui.media.FlashObject.IE_WMODE_PARAMS_ = '<param name="wmode" value="%s"/>';
/**
* Template for the embed tag for FF.
*
* @type {string}
* @private
*/
goog.ui.media.FlashObject.FF_HTML_ =
'<embed quality="high"' +
' id="%s"' +
' name="%s"' +
' class="%s"' +
' src="%s"' +
' FlashVars="%s"' +
' bgcolor="%s"' +
' AllowScriptAccess="%s"' +
' allowFullScreen="true"' +
' SeamlessTabbing="false"' +
' type="application/x-shockwave-flash"' +
' pluginspage="http://www.macromedia.com/go/getflashplayer"' +
' %s>' +
'</embed>';
/**
* Template for the wmode param for Firefox.
*
* @type {string}
* @private
*/
goog.ui.media.FlashObject.FF_WMODE_PARAMS_ = 'wmode=%s';
/**
* A logger used for debugging.
*
* @type {goog.log.Logger}
* @private
*/
goog.ui.media.FlashObject.prototype.logger_ =
goog.log.getLogger('goog.ui.media.FlashObject');
/**
* The wmode for the SWF.
*
* @type {goog.ui.media.FlashObject.Wmodes}
* @private
*/
goog.ui.media.FlashObject.prototype.wmode_ =
goog.ui.media.FlashObject.Wmodes.WINDOW;
/**
* The minimum required flash version.
*
* @type {?string}
* @private
*/
goog.ui.media.FlashObject.prototype.requiredVersion_;
/**
* The flash movie width.
*
* @type {string}
* @private
*/
goog.ui.media.FlashObject.prototype.width_;
/**
* The flash movie height.
*
* @type {string}
* @private
*/
goog.ui.media.FlashObject.prototype.height_;
/**
* The flash movie background color.
*
* @type {string}
* @private
*/
goog.ui.media.FlashObject.prototype.backgroundColor_ = '#000000';
/**
* The flash movie allowScriptAccess setting.
*
* @type {string}
* @private
*/
goog.ui.media.FlashObject.prototype.allowScriptAccess_ =
goog.ui.media.FlashObject.ScriptAccessLevel.SAME_DOMAIN;
/**
* Sets the flash movie Wmode.
*
* @param {goog.ui.media.FlashObject.Wmodes} wmode the flash movie Wmode.
* @return {goog.ui.media.FlashObject} The flash object instance for chaining.
*/
goog.ui.media.FlashObject.prototype.setWmode = function(wmode) {
this.wmode_ = wmode;
return this;
};
/**
* @return {string} Returns the flash movie wmode.
*/
goog.ui.media.FlashObject.prototype.getWmode = function() {
return this.wmode_;
};
/**
* Adds flash variables.
*
* @param {goog.structs.Map|Object} map A key-value map of variables.
* @return {goog.ui.media.FlashObject} The flash object instance for chaining.
*/
goog.ui.media.FlashObject.prototype.addFlashVars = function(map) {
this.flashVars_.addAll(map);
return this;
};
/**
* Sets a flash variable.
*
* @param {string} key The name of the flash variable.
* @param {string} value The value of the flash variable.
* @return {goog.ui.media.FlashObject} The flash object instance for chaining.
*/
goog.ui.media.FlashObject.prototype.setFlashVar = function(key, value) {
this.flashVars_.set(key, value);
return this;
};
/**
* Sets flash variables. You can either pass a Map of key->value pairs or you
* can pass a key, value pair to set a specific variable.
*
* TODO(user, martino): Get rid of this method.
*
* @deprecated Use {@link #addFlashVars} or {@link #setFlashVar} instead.
* @param {goog.structs.Map|Object|string} flashVar A map of variables (given
* as a goog.structs.Map or an Object literal) or a key to the optional
* {@code opt_value}.
* @param {string=} opt_value The optional value for the flashVar key.
* @return {goog.ui.media.FlashObject} The flash object instance for chaining.
*/
goog.ui.media.FlashObject.prototype.setFlashVars = function(flashVar,
opt_value) {
if (flashVar instanceof goog.structs.Map ||
goog.typeOf(flashVar) == 'object') {
this.addFlashVars(/**@type {!goog.structs.Map|!Object}*/(flashVar));
} else {
goog.asserts.assert(goog.isString(flashVar) && goog.isDef(opt_value),
'Invalid argument(s)');
this.setFlashVar(/**@type {string}*/(flashVar),
/**@type {string}*/(opt_value));
}
return this;
};
/**
* @return {goog.structs.Map} The current flash variables.
*/
goog.ui.media.FlashObject.prototype.getFlashVars = function() {
return this.flashVars_;
};
/**
* Sets the background color of the movie.
*
* @param {string} color The new color to be set.
* @return {goog.ui.media.FlashObject} The flash object instance for chaining.
*/
goog.ui.media.FlashObject.prototype.setBackgroundColor = function(color) {
this.backgroundColor_ = color;
return this;
};
/**
* @return {string} The background color of the movie.
*/
goog.ui.media.FlashObject.prototype.getBackgroundColor = function() {
return this.backgroundColor_;
};
/**
* Sets the allowScriptAccess setting of the movie.
*
* @param {string} value The new value to be set.
* @return {goog.ui.media.FlashObject} The flash object instance for chaining.
*/
goog.ui.media.FlashObject.prototype.setAllowScriptAccess = function(value) {
this.allowScriptAccess_ = value;
return this;
};
/**
* @return {string} The allowScriptAccess setting color of the movie.
*/
goog.ui.media.FlashObject.prototype.getAllowScriptAccess = function() {
return this.allowScriptAccess_;
};
/**
* Sets the width and height of the movie.
*
* @param {number|string} width The width of the movie.
* @param {number|string} height The height of the movie.
* @return {goog.ui.media.FlashObject} The flash object instance for chaining.
*/
goog.ui.media.FlashObject.prototype.setSize = function(width, height) {
this.width_ = goog.isString(width) ? width : Math.round(width) + 'px';
this.height_ = goog.isString(height) ? height : Math.round(height) + 'px';
if (this.getElement()) {
goog.style.setSize(this.getFlashElement(), this.width_, this.height_);
}
return this;
};
/**
* @return {?string} The flash required version.
*/
goog.ui.media.FlashObject.prototype.getRequiredVersion = function() {
return this.requiredVersion_;
};
/**
* Sets the minimum flash required version.
*
* @param {?string} version The minimum required version for this movie to work,
* or null if you want to unset it.
* @return {goog.ui.media.FlashObject} The flash object instance for chaining.
*/
goog.ui.media.FlashObject.prototype.setRequiredVersion = function(version) {
this.requiredVersion_ = version;
return this;
};
/**
* Returns whether this SWF has a minimum required flash version.
*
* @return {boolean} Whether a required version was set or not.
*/
goog.ui.media.FlashObject.prototype.hasRequiredVersion = function() {
return this.requiredVersion_ != null;
};
/**
* Writes the Flash embedding {@code HTMLObjectElement} to this components root
* element and adds listeners for all events to handle them consistently.
* @override
*/
goog.ui.media.FlashObject.prototype.enterDocument = function() {
goog.ui.media.FlashObject.superClass_.enterDocument.call(this);
// The SWF tag must be written after this component's element is appended to
// the DOM. Otherwise Flash's ExternalInterface is broken in IE.
this.getElement().innerHTML = this.generateSwfTag_();
if (this.width_ && this.height_) {
this.setSize(this.width_, this.height_);
}
// Sinks all the events on the bubble phase.
//
// Flash plugins propagates events from/to the plugin to the browser
// inconsistently:
//
// 1) FF2 + linux: the flash plugin will stop the propagation of all events
// from the plugin to the browser.
// 2) FF3 + mac: the flash plugin will propagate events on the <embed> object
// but that will get propagated to its parents.
// 3) Safari 3.1.1 + mac: the flash plugin will propagate the event to the
// <object> tag that event will propagate to its parents.
// 4) IE7 + windows: the flash plugin will eat all events, not propagating
// anything to the javascript.
// 5) Chrome + windows: the flash plugin will eat all events, not propagating
// anything to the javascript.
//
// To overcome this inconsistency, all events from/to the plugin are sinked,
// since you can't assume that the events will be propagated.
//
// NOTE(user): we only sink events on the bubbling phase, since there are no
// inexpensive/scalable way to stop events on the capturing phase unless we
// added an event listener on the document for each flash object.
this.eventHandler_.listen(
this.getElement(),
goog.object.getValues(goog.events.EventType),
goog.events.Event.stopPropagation);
};
/**
* Creates the DOM structure.
*
* @override
*/
goog.ui.media.FlashObject.prototype.createDom = function() {
if (this.hasRequiredVersion() &&
!goog.userAgent.flash.isVersion(
/** @type {string} */ (this.getRequiredVersion()))) {
goog.log.warning(this.logger_, 'Required flash version not found:' +
this.getRequiredVersion());
throw Error(goog.ui.Component.Error.NOT_SUPPORTED);
}
var element = this.getDomHelper().createElement('div');
element.className = goog.ui.media.FlashObject.CSS_CLASS;
this.setElementInternal(element);
};
/**
* Writes the HTML to embed the flash object.
*
* @return {string} Browser appropriate HTML to add the SWF to the DOM.
* @private
*/
goog.ui.media.FlashObject.prototype.generateSwfTag_ = function() {
var template = goog.userAgent.IE ? goog.ui.media.FlashObject.IE_HTML_ :
goog.ui.media.FlashObject.FF_HTML_;
var params = goog.userAgent.IE ? goog.ui.media.FlashObject.IE_WMODE_PARAMS_ :
goog.ui.media.FlashObject.FF_WMODE_PARAMS_;
params = goog.string.subs(params, this.wmode_);
var keys = this.flashVars_.getKeys();
var values = this.flashVars_.getValues();
var flashVars = [];
for (var i = 0; i < keys.length; i++) {
var key = goog.string.urlEncode(keys[i]);
var value = goog.string.urlEncode(values[i]);
flashVars.push(key + '=' + value);
}
// TODO(user): find a more efficient way to build the HTML.
return goog.string.subs(
template,
this.getId(),
this.getId(),
goog.ui.media.FlashObject.FLASH_CSS_CLASS,
goog.string.htmlEscape(this.flashUrl_),
goog.string.htmlEscape(flashVars.join('&')),
this.backgroundColor_,
this.allowScriptAccess_,
params);
};
/**
* @return {HTMLObjectElement} The flash element or null if the element can't
* be found.
*/
goog.ui.media.FlashObject.prototype.getFlashElement = function() {
return /** @type {HTMLObjectElement} */(this.getElement() ?
this.getElement().firstChild : null);
};
/** @override */
goog.ui.media.FlashObject.prototype.disposeInternal = function() {
goog.ui.media.FlashObject.superClass_.disposeInternal.call(this);
this.flashVars_ = null;
this.eventHandler_.dispose();
this.eventHandler_ = null;
};
/**
* @return {boolean} whether the SWF has finished loading or not.
*/
goog.ui.media.FlashObject.prototype.isLoaded = function() {
if (!this.isInDocument() || !this.getElement()) {
return false;
}
if (this.getFlashElement().readyState &&
this.getFlashElement().readyState ==
goog.ui.media.FlashObject.SwfReadyStates_.COMPLETE) {
return true;
}
if (this.getFlashElement().PercentLoaded &&
this.getFlashElement().PercentLoaded() == 100) {
return true;
}
return false;
};
@@ -0,0 +1,308 @@
// Copyright 2009 The Closure Library Authors. 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 provides a reusable FlickrSet photo UI component given a public
* FlickrSetModel.
*
* goog.ui.media.FlickrSet is actually a {@link goog.ui.ControlRenderer}, a
* stateless class - that could/should be used as a Singleton with the static
* method {@code goog.ui.media.FlickrSet.getInstance} -, that knows how to
* render Flickr sets. It is designed to be used with a {@link goog.ui.Control},
* which will actually control the media renderer and provide the
* {@link goog.ui.Component} base. This design guarantees that all different
* types of medias will behave alike but will look different.
*
* goog.ui.media.FlickrSet expects a {@code goog.ui.media.FlickrSetModel} on
* {@code goog.ui.Control.getModel} as data models, and renders a flash object
* that will show the contents of that set.
*
* Example of usage:
*
* <pre>
* var flickrSet = goog.ui.media.FlickrSetModel.newInstance(flickrSetUrl);
* goog.ui.media.FlickrSet.newControl(flickrSet).render();
* </pre>
*
* FlickrSet medias currently support the following states:
*
* <ul>
* <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
* <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
* <li> {@link goog.ui.Component.State.SELECTED}: flash video is shown
* </ul>
*
* Which can be accessed by
* <pre>
* video.setEnabled(true);
* video.setHighlighted(true);
* video.setSelected(true);
* </pre>
*
*
* @supported IE6, FF2+, Safari. Requires flash to actually work.
*
* TODO(user): Support non flash users. Maybe show a link to the Flick set,
* or fetch the data and rendering it using javascript (instead of a broken
* 'You need to install flash' message).
*/
goog.provide('goog.ui.media.FlickrSet');
goog.provide('goog.ui.media.FlickrSetModel');
goog.require('goog.ui.media.FlashObject');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaModel');
goog.require('goog.ui.media.MediaRenderer');
/**
* Subclasses a goog.ui.media.MediaRenderer to provide a FlickrSet specific
* media renderer.
*
* This class knows how to parse FlickrSet URLs, and render the DOM structure
* of flickr set players. This class is meant to be used as a singleton static
* stateless class, that takes {@code goog.ui.media.Media} instances and renders
* it. It expects {@code goog.ui.media.Media.getModel} to return a well formed,
* previously constructed, set id {@see goog.ui.media.FlickrSet.parseUrl},
* which is the data model this renderer will use to construct the DOM
* structure. {@see goog.ui.media.FlickrSet.newControl} for a example of
* constructing a control with this renderer.
*
* This design is patterned after
* http://go/closure_control_subclassing
*
* It uses {@link goog.ui.media.FlashObject} to embed the flash object.
*
* @constructor
* @extends {goog.ui.media.MediaRenderer}
*/
goog.ui.media.FlickrSet = function() {
goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.FlickrSet, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.FlickrSet);
/**
* Default CSS class to be applied to the root element of components rendered
* by this renderer.
*
* @type {string}
*/
goog.ui.media.FlickrSet.CSS_CLASS = goog.getCssName('goog-ui-media-flickrset');
/**
* Flash player URL. Uses Flickr's flash player by default.
*
* @type {string}
* @private
*/
goog.ui.media.FlickrSet.flashUrl_ =
'http://www.flickr.com/apps/slideshow/show.swf?v=63961';
/**
* A static convenient method to construct a goog.ui.media.Media control out of
* a FlickrSet URL. It extracts the set id information on the URL, sets it
* as the data model goog.ui.media.FlickrSet renderer uses, sets the states
* supported by the renderer, and returns a Control that binds everything
* together. This is what you should be using for constructing FlickrSet videos,
* except if you need more fine control over the configuration.
*
* @param {goog.ui.media.FlickrSetModel} dataModel The Flickr Set data model.
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
* document interaction.
* @return {goog.ui.media.Media} A Control binded to the FlickrSet renderer.
* @throws exception in case {@code flickrSetUrl} is an invalid flickr set URL.
* TODO(user): use {@link goog.ui.media.MediaModel} once it is checked in.
*/
goog.ui.media.FlickrSet.newControl = function(dataModel, opt_domHelper) {
var control = new goog.ui.media.Media(
dataModel, goog.ui.media.FlickrSet.getInstance(), opt_domHelper);
control.setSelected(true);
return control;
};
/**
* A static method that sets which flash URL this class should use. Use this if
* you want to host your own flash flickr player.
*
* @param {string} flashUrl The URL of the flash flickr player.
*/
goog.ui.media.FlickrSet.setFlashUrl = function(flashUrl) {
goog.ui.media.FlickrSet.flashUrl_ = flashUrl;
};
/**
* Creates the initial DOM structure of the flickr set, which is basically a
* the flash object pointing to a flickr set player.
*
* @param {goog.ui.Control} c The media control.
* @return {Element} The DOM structure that represents this control.
* @override
*/
goog.ui.media.FlickrSet.prototype.createDom = function(c) {
var control = /** @type {goog.ui.media.Media} */ (c);
var div = goog.ui.media.FlickrSet.superClass_.createDom.call(this, control);
var model =
/** @type {goog.ui.media.FlickrSetModel} */ (control.getDataModel());
// TODO(user): find out what is the policy about hosting this SWF. figure out
// if it works over https.
var flash = new goog.ui.media.FlashObject(
model.getPlayer().getUrl() || '',
control.getDomHelper());
flash.addFlashVars(model.getPlayer().getVars());
flash.render(div);
return div;
};
/**
* Returns the CSS class to be applied to the root element of components
* rendered using this renderer.
* @return {string} Renderer-specific CSS class.
* @override
*/
goog.ui.media.FlickrSet.prototype.getCssClass = function() {
return goog.ui.media.FlickrSet.CSS_CLASS;
};
/**
* The {@code goog.ui.media.FlickrAlbum} media data model. It stores a required
* {@code userId} and {@code setId} fields, sets the flickr Set URL, and
* allows a few optional parameters.
*
* @param {string} userId The flickr userId associated with this set.
* @param {string} setId The flickr setId associated with this set.
* @param {string=} opt_caption An optional caption of the flickr set.
* @param {string=} opt_description An optional description of the flickr set.
* @constructor
* @extends {goog.ui.media.MediaModel}
*/
goog.ui.media.FlickrSetModel = function(userId,
setId,
opt_caption,
opt_description) {
goog.ui.media.MediaModel.call(
this,
goog.ui.media.FlickrSetModel.buildUrl(userId, setId),
opt_caption,
opt_description,
goog.ui.media.MediaModel.MimeType.FLASH);
/**
* The Flickr user id.
* @type {string}
* @private
*/
this.userId_ = userId;
/**
* The Flickr set id.
* @type {string}
* @private
*/
this.setId_ = setId;
var flashVars = {
'offsite': 'true',
'lang': 'en',
'page_show_url': '/photos/' + userId + '/sets/' + setId + '/show/',
'page_show_back_url': '/photos/' + userId + '/sets/' + setId,
'set_id': setId
};
var player = new goog.ui.media.MediaModel.Player(
goog.ui.media.FlickrSet.flashUrl_, flashVars);
this.setPlayer(player);
};
goog.inherits(goog.ui.media.FlickrSetModel, goog.ui.media.MediaModel);
/**
* Regular expression used to extract the username and set id out of the flickr
* URLs.
*
* Copied from http://go/markdownlite.js and {@link FlickrExtractor.xml}.
*
* @type {RegExp}
* @private
* @const
*/
goog.ui.media.FlickrSetModel.MATCHER_ =
/(?:http:\/\/)?(?:www\.)?flickr\.com\/(?:photos\/([\d\w@\-]+)\/sets\/(\d+))\/?/i;
/**
* Takes a {@code flickrSetUrl} and extracts the flickr username and set id.
*
* @param {string} flickrSetUrl A Flickr set URL.
* @param {string=} opt_caption An optional caption of the flickr set.
* @param {string=} opt_description An optional description of the flickr set.
* @return {goog.ui.media.FlickrSetModel} The data model that represents the
* Flickr set.
* @throws exception in case the parsing fails
*/
goog.ui.media.FlickrSetModel.newInstance = function(flickrSetUrl,
opt_caption,
opt_description) {
if (goog.ui.media.FlickrSetModel.MATCHER_.test(flickrSetUrl)) {
var data = goog.ui.media.FlickrSetModel.MATCHER_.exec(flickrSetUrl);
return new goog.ui.media.FlickrSetModel(
data[1], data[2], opt_caption, opt_description);
}
throw Error('failed to parse flickr url: ' + flickrSetUrl);
};
/**
* Takes a flickr username and set id and returns an URL.
*
* @param {string} userId The owner of the set.
* @param {string} setId The set id.
* @return {string} The URL of the set.
*/
goog.ui.media.FlickrSetModel.buildUrl = function(userId, setId) {
return 'http://flickr.com/photos/' + userId + '/sets/' + setId;
};
/**
* Gets the Flickr user id.
* @return {string} The Flickr user id.
*/
goog.ui.media.FlickrSetModel.prototype.getUserId = function() {
return this.userId_;
};
/**
* Gets the Flickr set id.
* @return {string} The Flickr set id.
*/
goog.ui.media.FlickrSetModel.prototype.getSetId = function() {
return this.setId_;
};
@@ -0,0 +1,281 @@
// Copyright 2011 The Closure Library Authors. 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 provides a reusable GoogleVideo UI component given a public
* GoogleVideo video URL.
*
* goog.ui.media.GoogleVideo is actually a {@link goog.ui.ControlRenderer}, a
* stateless class - that could/should be used as a Singleton with the static
* method {@code goog.ui.media.GoogleVideo.getInstance} -, that knows how to
* render GoogleVideo videos. It is designed to be used with a
* {@link goog.ui.Control}, which will actually control the media renderer and
* provide the {@link goog.ui.Component} base. This design guarantees that all
* different types of medias will behave alike but will look different.
*
* goog.ui.media.GoogleVideo expects {@code goog.ui.media.GoogleVideoModel} on
* {@code goog.ui.Control.getModel} as data models, and renders a flash object
* that will show the contents of that video.
*
* Example of usage:
*
* <pre>
* var video = goog.ui.media.GoogleVideoModel.newInstance(
* 'http://video.google.com/videoplay?docid=6698933542780842398');
* goog.ui.media.GoogleVideo.newControl(video).render();
* </pre>
*
* GoogleVideo medias currently support the following states:
*
* <ul>
* <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
* <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
* <li> {@link goog.ui.Component.State.SELECTED}: flash video is shown
* </ul>
*
* Which can be accessed by
* <pre>
* video.setEnabled(true);
* video.setHighlighted(true);
* video.setSelected(true);
* </pre>
*
*
* @supported IE6+, FF2+, Chrome, Safari. Requires flash to actually work.
*/
goog.provide('goog.ui.media.GoogleVideo');
goog.provide('goog.ui.media.GoogleVideoModel');
goog.require('goog.string');
goog.require('goog.ui.media.FlashObject');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaModel');
goog.require('goog.ui.media.MediaRenderer');
/**
* Subclasses a goog.ui.media.MediaRenderer to provide a GoogleVideo specific
* media renderer.
*
* This class knows how to parse GoogleVideo URLs, and render the DOM structure
* of GoogleVideo video players. This class is meant to be used as a singleton
* static stateless class, that takes {@code goog.ui.media.Media} instances and
* renders it. It expects {@code goog.ui.media.Media.getModel} to return a well
* formed, previously constructed, GoogleVideo video id, which is the data model
* this renderer will use to construct the DOM structure.
* {@see goog.ui.media.GoogleVideo.newControl} for a example of constructing a
* control with this renderer.
*
* This design is patterned after http://go/closure_control_subclassing
*
* It uses {@link goog.ui.media.FlashObject} to embed the flash object.
*
* @constructor
* @extends {goog.ui.media.MediaRenderer}
*/
goog.ui.media.GoogleVideo = function() {
goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.GoogleVideo, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.GoogleVideo);
/**
* A static convenient method to construct a goog.ui.media.Media control out of
* a GoogleVideo model. It sets it as the data model goog.ui.media.GoogleVideo
* renderer uses, sets the states supported by the renderer, and returns a
* Control that binds everything together. This is what you should be using for
* constructing GoogleVideo videos, except if you need finer control over the
* configuration.
*
* @param {goog.ui.media.GoogleVideoModel} dataModel The GoogleVideo data model.
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
* document interaction.
* @return {goog.ui.media.Media} A Control binded to the GoogleVideo renderer.
*/
goog.ui.media.GoogleVideo.newControl = function(dataModel, opt_domHelper) {
var control = new goog.ui.media.Media(
dataModel,
goog.ui.media.GoogleVideo.getInstance(),
opt_domHelper);
// GoogleVideo videos don't have any thumbnail for now, so we show the
// "selected" version of the UI at the start, which is the flash player.
control.setSelected(true);
return control;
};
/**
* Default CSS class to be applied to the root element of components rendered
* by this renderer.
*
* @type {string}
*/
goog.ui.media.GoogleVideo.CSS_CLASS =
goog.getCssName('goog-ui-media-googlevideo');
/**
* Creates the initial DOM structure of the GoogleVideo video, which is
* basically a the flash object pointing to a GoogleVideo video player.
*
* @param {goog.ui.Control} c The media control.
* @return {Element} The DOM structure that represents this control.
* @override
*/
goog.ui.media.GoogleVideo.prototype.createDom = function(c) {
var control = /** @type {goog.ui.media.Media} */ (c);
var div = goog.base(this, 'createDom', control);
var dataModel =
/** @type {goog.ui.media.GoogleVideoModel} */ (control.getDataModel());
var flash = new goog.ui.media.FlashObject(
dataModel.getPlayer().getUrl() || '',
control.getDomHelper());
flash.render(div);
return div;
};
/**
* Returns the CSS class to be applied to the root element of components
* rendered using this renderer.
*
* @return {string} Renderer-specific CSS class.
* @override
*/
goog.ui.media.GoogleVideo.prototype.getCssClass = function() {
return goog.ui.media.GoogleVideo.CSS_CLASS;
};
/**
* The {@code goog.ui.media.GoogleVideo} media data model. It stores a required
* {@code videoId} field, sets the GoogleVideo URL, and allows a few optional
* parameters.
*
* @param {string} videoId The GoogleVideo video id.
* @param {string=} opt_caption An optional caption of the GoogleVideo video.
* @param {string=} opt_description An optional description of the GoogleVideo
* video.
* @param {boolean=} opt_autoplay Whether to autoplay video.
* @constructor
* @extends {goog.ui.media.MediaModel}
*/
goog.ui.media.GoogleVideoModel = function(videoId, opt_caption, opt_description,
opt_autoplay) {
goog.ui.media.MediaModel.call(
this,
goog.ui.media.GoogleVideoModel.buildUrl(videoId),
opt_caption,
opt_description,
goog.ui.media.MediaModel.MimeType.FLASH);
/**
* The GoogleVideo video id.
* @type {string}
* @private
*/
this.videoId_ = videoId;
this.setPlayer(new goog.ui.media.MediaModel.Player(
goog.ui.media.GoogleVideoModel.buildFlashUrl(videoId, opt_autoplay)));
};
goog.inherits(goog.ui.media.GoogleVideoModel, goog.ui.media.MediaModel);
/**
* Regular expression used to extract the GoogleVideo video id (docid) out of
* GoogleVideo URLs.
*
* @type {RegExp}
* @private
* @const
*/
goog.ui.media.GoogleVideoModel.MATCHER_ =
/^http:\/\/(?:www\.)?video\.google\.com\/videoplay.*[\?#]docid=(-?[0-9]+)#?$/i;
/**
* A auxiliary static method that parses a GoogleVideo URL, extracting the ID of
* the video, and builds a GoogleVideoModel.
*
* @param {string} googleVideoUrl A GoogleVideo video URL.
* @param {string=} opt_caption An optional caption of the GoogleVideo video.
* @param {string=} opt_description An optional description of the GoogleVideo
* video.
* @param {boolean=} opt_autoplay Whether to autoplay video.
* @return {goog.ui.media.GoogleVideoModel} The data model that represents the
* GoogleVideo URL.
* @see goog.ui.media.GoogleVideoModel.getVideoId()
* @throws Error in case the parsing fails.
*/
goog.ui.media.GoogleVideoModel.newInstance = function(googleVideoUrl,
opt_caption,
opt_description,
opt_autoplay) {
if (goog.ui.media.GoogleVideoModel.MATCHER_.test(googleVideoUrl)) {
var data = goog.ui.media.GoogleVideoModel.MATCHER_.exec(googleVideoUrl);
return new goog.ui.media.GoogleVideoModel(
data[1], opt_caption, opt_description, opt_autoplay);
}
throw Error('failed to parse video id from GoogleVideo url: ' +
googleVideoUrl);
};
/**
* The opposite of {@code goog.ui.media.GoogleVideo.newInstance}: it takes a
* videoId and returns a GoogleVideo URL.
*
* @param {string} videoId The GoogleVideo video ID.
* @return {string} The GoogleVideo URL.
*/
goog.ui.media.GoogleVideoModel.buildUrl = function(videoId) {
return 'http://video.google.com/videoplay?docid=' +
goog.string.urlEncode(videoId);
};
/**
* An auxiliary method that builds URL of the flash movie to be embedded,
* out of the GoogleVideo video id.
*
* @param {string} videoId The GoogleVideo video ID.
* @param {boolean=} opt_autoplay Whether the flash movie should start playing
* as soon as it is shown, or if it should show a 'play' button.
* @return {string} The flash URL to be embedded on the page.
*/
goog.ui.media.GoogleVideoModel.buildFlashUrl = function(videoId, opt_autoplay) {
var autoplay = opt_autoplay ? '&autoplay=1' : '';
return 'http://video.google.com/googleplayer.swf?docid=' +
goog.string.urlEncode(videoId) +
'&hl=en&fs=true' + autoplay;
};
/**
* Gets the GoogleVideo video id.
* @return {string} The GoogleVideo video id.
*/
goog.ui.media.GoogleVideoModel.prototype.getVideoId = function() {
return this.videoId_;
};
@@ -0,0 +1,285 @@
// Copyright 2009 The Closure Library Authors. 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 Provides the base goog.ui.Control and goog.ui.ControlRenderer
* for media types, as well as a media model consistent with the Yahoo Media RSS
* specification {@link http://search.yahoo.com/mrss/}.
*
* The goog.ui.media.* package is basically a set of goog.ui.ControlRenderers
* subclasses (such as goog.ui.media.Youtube, goog.ui.media.Picasa, etc) that
* should all work with the same goog.ui.Control (goog.ui.media.Media) logic.
*
* This design guarantees that all different types of medias will behave alike
* (in a base level) but will look different.
*
* In MVC terms, {@link goog.ui.media.Media} is the Controller,
* {@link goog.ui.media.MediaRenderer} + CSS definitions are the View and
* {@code goog.ui.media.MediaModel} is the data Model. Typically,
* MediaRenderer will be subclassed to provide media specific renderers.
* MediaRenderer subclasses are also responsible for defining the data model.
*
* This design is strongly patterned after:
* http://go/closure_control_subclassing
*
* goog.ui.media.MediaRenderer handles the basic common ways to display media,
* such as displaying tooltips, frames, minimize/maximize buttons, play buttons,
* etc. Its subclasses are responsible for rendering media specific DOM
* structures, like youtube flash players, picasa albums, etc.
*
* goog.ui.media.Media handles the Control of Medias, by listening to events
* and firing the appropriate actions. It knows about the existence of captions,
* minimize/maximize buttons, and takes all the actions needed to change states,
* including delegating the UI actions to MediaRenderers.
*
* Although MediaRenderer is a base class designed to be subclassed, it can
* be used by itself:
*
* <pre>
* var renderer = new goog.ui.media.MediaRenderer();
* var control = new goog.ui.media.Media('hello world', renderer);
* var control.render(goog.dom.getElement('mediaHolder'));
* </pre>
*
* It requires a few CSS rules to be defined, which you should use to control
* how the component is displayed. {@link goog.ui.ControlRenderer}s is very CSS
* intensive, which separates the UI structure (the HTML DOM elements, which is
* created by the {@code goog.ui.media.MediaRenderer}) from the UI view (which
* nodes are visible, which aren't, where they are positioned. These are defined
* on the CSS rules for each state). A few examples of CSS selectors that needs
* to be defined are:
*
* <ul>
* <li>.goog-ui-media
* <li>.goog-ui-media-hover
* <li>.goog-ui-media-selected
* </ul>
*
* If you want to have different custom renderers CSS namespaces (eg. you may
* want to show a small thumbnail, or you may want to hide the caption, etc),
* you can do so by using:
*
* <pre>
* var renderer = goog.ui.ControlRenderer.getCustomRenderer(
* goog.ui.media.MediaRenderer, 'my-custom-namespace');
* var media = new goog.ui.media.Media('', renderer);
* media.render(goog.dom.getElement('parent'));
* </pre>
*
* Which will allow you to set your own .my-custom-namespace-hover,
* .my-custom-namespace-selected CSS selectors.
*
* NOTE(user): it seems like an overkill to subclass goog.ui.Control instead of
* using a factory, but we wanted to make sure we had more control over the
* events for future media implementations. Since we intent to use it in many
* different places, it makes sense to have a more flexible design that lets us
* control the inner workings of goog.ui.Control.
*
* TODO(user): implement, as needed, the Media specific state changes UI, such
* as minimize/maximize buttons, expand/close buttons, etc.
*
*/
goog.provide('goog.ui.media.Media');
goog.provide('goog.ui.media.MediaRenderer');
goog.require('goog.style');
goog.require('goog.ui.Component');
goog.require('goog.ui.Control');
goog.require('goog.ui.ControlRenderer');
/**
* Provides the control mechanism of media types.
*
* @param {goog.ui.media.MediaModel} dataModel The data model to be used by the
* renderer.
* @param {goog.ui.ControlRenderer=} opt_renderer Renderer used to render or
* decorate the component; defaults to {@link goog.ui.ControlRenderer}.
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
* document interaction.
* @constructor
* @extends {goog.ui.Control}
*/
goog.ui.media.Media = function(dataModel, opt_renderer, opt_domHelper) {
goog.ui.Control.call(this, null, opt_renderer, opt_domHelper);
// Sets up the data model.
this.setDataModel(dataModel);
this.setSupportedState(goog.ui.Component.State.OPENED, true);
this.setSupportedState(goog.ui.Component.State.SELECTED, true);
// TODO(user): had to do this to for mouseDownHandler not to
// e.preventDefault(), because it was not allowing the event to reach the
// flash player. figure out a better way to not e.preventDefault().
this.setAllowTextSelection(true);
// Media items don't use RTL styles, so avoid accessing computed styles to
// figure out if the control is RTL.
this.setRightToLeft(false);
};
goog.inherits(goog.ui.media.Media, goog.ui.Control);
/**
* The media data model used on the renderer.
*
* @type {goog.ui.media.MediaModel}
* @private
*/
goog.ui.media.Media.prototype.dataModel_;
/**
* Sets the media model to be used on the renderer.
* @param {goog.ui.media.MediaModel} dataModel The media model the renderer
* should use.
*/
goog.ui.media.Media.prototype.setDataModel = function(dataModel) {
this.dataModel_ = dataModel;
};
/**
* Gets the media model renderer is using.
* @return {goog.ui.media.MediaModel} The media model being used.
*/
goog.ui.media.Media.prototype.getDataModel = function() {
return this.dataModel_;
};
/**
* Base class of all media renderers. Provides the common renderer functionality
* of medias.
*
* The current common functionality shared by Medias is to have an outer frame
* that gets highlighted on mouse hover.
*
* TODO(user): implement more common UI behavior, as needed.
*
* NOTE(user): I am not enjoying how the subclasses are changing their state
* through setState() ... maybe provide abstract methods like
* goog.ui.media.MediaRenderer.prototype.preview = goog.abstractMethod;
* goog.ui.media.MediaRenderer.prototype.play = goog.abstractMethod;
* goog.ui.media.MediaRenderer.prototype.minimize = goog.abstractMethod;
* goog.ui.media.MediaRenderer.prototype.maximize = goog.abstractMethod;
* and call them on this parent class setState ?
*
* @constructor
* @extends {goog.ui.ControlRenderer}
*/
goog.ui.media.MediaRenderer = function() {
goog.ui.ControlRenderer.call(this);
};
goog.inherits(goog.ui.media.MediaRenderer, goog.ui.ControlRenderer);
/**
* Builds the common DOM structure of medias. Builds an outer div, and appends
* a child div with the {@code goog.ui.Control.getContent} content. Marks the
* caption with a {@code this.getClassClass()} + '-caption' css flag, so that
* specific renderers can hide/show the caption as desired.
*
* @param {goog.ui.Control} control The control instance.
* @return {Element} The DOM structure that represents control.
* @override
*/
goog.ui.media.MediaRenderer.prototype.createDom = function(control) {
var domHelper = control.getDomHelper();
var div = domHelper.createElement('div');
div.className = this.getClassNames(control).join(' ');
var dataModel = control.getDataModel();
// Only creates DOMs if the data is available.
if (dataModel.getCaption()) {
var caption = domHelper.createElement('div');
caption.className = goog.getCssName(this.getCssClass(), 'caption');
caption.appendChild(domHelper.createDom(
'p', goog.getCssName(this.getCssClass(), 'caption-text'),
dataModel.getCaption()));
domHelper.appendChild(div, caption);
}
if (dataModel.getDescription()) {
var description = domHelper.createElement('div');
description.className = goog.getCssName(this.getCssClass(), 'description');
description.appendChild(domHelper.createDom(
'p', goog.getCssName(this.getCssClass(), 'description-text'),
dataModel.getDescription()));
domHelper.appendChild(div, description);
}
// Creates thumbnails of the media.
var thumbnails = dataModel.getThumbnails() || [];
for (var index = 0; index < thumbnails.length; index++) {
var thumbnail = thumbnails[index];
var thumbnailElement = domHelper.createElement('img');
thumbnailElement.src = thumbnail.getUrl();
thumbnailElement.className = this.getThumbnailCssName(index);
// Check that the size is defined and that the size's height and width
// are defined. Undefined height and width is deprecated but still
// seems to exist in some cases.
var size = thumbnail.getSize();
if (size && goog.isDefAndNotNull(size.height) &&
goog.isDefAndNotNull(size.width)) {
goog.style.setSize(thumbnailElement, size);
}
domHelper.appendChild(div, thumbnailElement);
}
if (dataModel.getPlayer()) {
// if medias have players, allow UI for a play button.
var playButton = domHelper.createElement('div');
playButton.className = goog.getCssName(this.getCssClass(), 'playbutton');
domHelper.appendChild(div, playButton);
}
control.setElementInternal(div);
this.setState(
control,
/** @type {goog.ui.Component.State} */ (control.getState()),
true);
return div;
};
/**
* Returns a renamable CSS class name for a numbered thumbnail. The default
* implementation generates the class names goog-ui-media-thumbnail0,
* goog-ui-media-thumbnail1, and the generic goog-ui-media-thumbnailn.
* Subclasses can override this method when their media requires additional
* specific class names (Applications are supposed to know how many thumbnails
* media will have).
*
* @param {number} index The thumbnail index.
* @return {string} CSS class name.
* @protected
*/
goog.ui.media.MediaRenderer.prototype.getThumbnailCssName = function(index) {
switch (index) {
case 0: return goog.getCssName(this.getCssClass(), 'thumbnail0');
case 1: return goog.getCssName(this.getCssClass(), 'thumbnail1');
case 2: return goog.getCssName(this.getCssClass(), 'thumbnail2');
case 3: return goog.getCssName(this.getCssClass(), 'thumbnail3');
case 4: return goog.getCssName(this.getCssClass(), 'thumbnail4');
default: return goog.getCssName(this.getCssClass(), 'thumbnailn');
}
};
@@ -0,0 +1,960 @@
// Copyright 2009 The Closure Library Authors. 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 Provides the base media model consistent with the Yahoo Media
* RSS specification {@link http://search.yahoo.com/mrss/}.
*/
goog.provide('goog.ui.media.MediaModel');
goog.provide('goog.ui.media.MediaModel.Category');
goog.provide('goog.ui.media.MediaModel.Credit');
goog.provide('goog.ui.media.MediaModel.Credit.Role');
goog.provide('goog.ui.media.MediaModel.Credit.Scheme');
goog.provide('goog.ui.media.MediaModel.Medium');
goog.provide('goog.ui.media.MediaModel.MimeType');
goog.provide('goog.ui.media.MediaModel.Player');
goog.provide('goog.ui.media.MediaModel.SubTitle');
goog.provide('goog.ui.media.MediaModel.Thumbnail');
goog.require('goog.array');
/**
* An base data value class for all media data models.
*
* MediaModels are exact matches to the fields defined in the Yahoo RSS media
* specification {@link http://search.yahoo.com/mrss/}.
*
* The current common data shared by medias is to have URLs, mime types,
* captions, descriptions, thumbnails and players. Some of these may not be
* available, or applications may not want to render them, so {@code null}
* values are allowed. {@code goog.ui.media.MediaRenderer} checks whether the
* values are available before creating DOMs for them.
*
* TODO(user): support asynchronous data models by subclassing
* {@link goog.events.EventTarget} or {@link goog.ds.DataNode}. Understand why
* {@link http://goto/datanode} is not available in closure. Add setters to
* MediaModel once this is supported.
*
* @param {string=} opt_url An optional URL of the media.
* @param {string=} opt_caption An optional caption of the media.
* @param {string=} opt_description An optional description of the media.
* @param {goog.ui.media.MediaModel.MimeType=} opt_type The type of the media.
* @param {goog.ui.media.MediaModel.Medium=} opt_medium The medium of the media.
* @param {number=} opt_duration The duration of the media in seconds.
* @param {number=} opt_width The width of the media in pixels.
* @param {number=} opt_height The height of the media in pixels.
* @constructor
*/
goog.ui.media.MediaModel = function(opt_url,
opt_caption,
opt_description,
opt_type,
opt_medium,
opt_duration,
opt_width,
opt_height) {
/**
* The URL of the media.
* @type {string|undefined}
* @private
*/
this.url_ = opt_url;
/**
* The caption of the media.
* @type {string|undefined}
* @private
*/
this.caption_ = opt_caption;
/**
* A description of the media, typically user generated comments about it.
* @type {string|undefined}
* @private
*/
this.description_ = opt_description;
/**
* The mime type of the media.
* @type {goog.ui.media.MediaModel.MimeType|undefined}
* @private
*/
this.type_ = opt_type;
/**
* The medium of the media.
* @type {goog.ui.media.MediaModel.Medium|undefined}
* @private
*/
this.medium_ = opt_medium;
/**
* The duration of the media in seconds.
* @type {number|undefined}
* @private
*/
this.duration_ = opt_duration;
/**
* The width of the media in pixels.
* @type {number|undefined}
* @private
*/
this.width_ = opt_width;
/**
* The height of the media in pixels.
* @type {number|undefined}
* @private
*/
this.height_ = opt_height;
/**
* A list of thumbnails representations of the media (eg different sizes of
* the same photo, etc).
* @type {Array.<goog.ui.media.MediaModel.Thumbnail>}
* @private
*/
this.thumbnails_ = [];
/**
* The list of categories that are applied to this media.
* @type {Array.<goog.ui.media.MediaModel.Category>}
* @private
*/
this.categories_ = [];
/**
* The list of credits that pertain to this media object.
* @type {!Array.<goog.ui.media.MediaModel.Credit>}
* @private
*/
this.credits_ = [];
/**
* The list of subtitles for the media object.
* @type {Array.<goog.ui.media.MediaModel.SubTitle>}
* @private
*/
this.subTitles_ = [];
};
/**
* The supported media mime types, a subset of the media types found here:
* {@link http://www.iana.org/assignments/media-types/} and here
* {@link http://en.wikipedia.org/wiki/Internet_media_type}
* @enum {string}
*/
goog.ui.media.MediaModel.MimeType = {
HTML: 'text/html',
PLAIN: 'text/plain',
FLASH: 'application/x-shockwave-flash',
JPEG: 'image/jpeg',
GIF: 'image/gif',
PNG: 'image/png'
};
/**
* Supported mediums, found here:
* {@link http://video.search.yahoo.com/mrss}
* @enum {string}
*/
goog.ui.media.MediaModel.Medium = {
IMAGE: 'image',
AUDIO: 'audio',
VIDEO: 'video',
DOCUMENT: 'document',
EXECUTABLE: 'executable'
};
/**
* The media player.
* @type {goog.ui.media.MediaModel.Player}
* @private
*/
goog.ui.media.MediaModel.prototype.player_;
/**
* Gets the URL of this media.
* @return {string|undefined} The URL of the media.
*/
goog.ui.media.MediaModel.prototype.getUrl = function() {
return this.url_;
};
/**
* Sets the URL of this media.
* @param {string} url The URL of the media.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setUrl = function(url) {
this.url_ = url;
return this;
};
/**
* Gets the caption of this media.
* @return {string|undefined} The caption of the media.
*/
goog.ui.media.MediaModel.prototype.getCaption = function() {
return this.caption_;
};
/**
* Sets the caption of this media.
* @param {string} caption The caption of the media.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setCaption = function(caption) {
this.caption_ = caption;
return this;
};
/**
* Gets the media mime type.
* @return {goog.ui.media.MediaModel.MimeType|undefined} The media mime type.
*/
goog.ui.media.MediaModel.prototype.getType = function() {
return this.type_;
};
/**
* Sets the media mime type.
* @param {goog.ui.media.MediaModel.MimeType} type The media mime type.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setType = function(type) {
this.type_ = type;
return this;
};
/**
* Gets the media medium.
* @return {goog.ui.media.MediaModel.Medium|undefined} The media medium.
*/
goog.ui.media.MediaModel.prototype.getMedium = function() {
return this.medium_;
};
/**
* Sets the media medium.
* @param {goog.ui.media.MediaModel.Medium} medium The media medium.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setMedium = function(medium) {
this.medium_ = medium;
return this;
};
/**
* Gets the description of this media.
* @return {string|undefined} The description of the media.
*/
goog.ui.media.MediaModel.prototype.getDescription = function() {
return this.description_;
};
/**
* Sets the description of this media.
* @param {string} description The description of the media.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setDescription = function(description) {
this.description_ = description;
return this;
};
/**
* Gets the thumbnail urls.
* @return {Array.<goog.ui.media.MediaModel.Thumbnail>} The list of thumbnails.
*/
goog.ui.media.MediaModel.prototype.getThumbnails = function() {
return this.thumbnails_;
};
/**
* Sets the thumbnail list.
* @param {Array.<goog.ui.media.MediaModel.Thumbnail>} thumbnails The list of
* thumbnail.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setThumbnails = function(thumbnails) {
this.thumbnails_ = thumbnails;
return this;
};
/**
* Gets the duration of the media.
* @return {number|undefined} The duration in seconds.
*/
goog.ui.media.MediaModel.prototype.getDuration = function() {
return this.duration_;
};
/**
* Sets duration of the media.
* @param {number} duration The duration of the media, in seconds.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setDuration = function(duration) {
this.duration_ = duration;
return this;
};
/**
* Gets the width of the media in pixels.
* @return {number|undefined} The width in pixels.
*/
goog.ui.media.MediaModel.prototype.getWidth = function() {
return this.width_;
};
/**
* Sets the width of the media.
* @param {number} width The width of the media, in pixels.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setWidth = function(width) {
this.width_ = width;
return this;
};
/**
* Gets the height of the media in pixels.
* @return {number|undefined} The height in pixels.
*/
goog.ui.media.MediaModel.prototype.getHeight = function() {
return this.height_;
};
/**
* Sets the height of the media.
* @param {number} height The height of the media, in pixels.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setHeight = function(height) {
this.height_ = height;
return this;
};
/**
* Gets the player data.
* @return {goog.ui.media.MediaModel.Player|undefined} The media player data.
*/
goog.ui.media.MediaModel.prototype.getPlayer = function() {
return this.player_;
};
/**
* Sets the player data.
* @param {goog.ui.media.MediaModel.Player} player The media player data.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setPlayer = function(player) {
this.player_ = player;
return this;
};
/**
* Gets the categories of the media.
* @return {Array.<goog.ui.media.MediaModel.Category>} The categories of the
* media.
*/
goog.ui.media.MediaModel.prototype.getCategories = function() {
return this.categories_;
};
/**
* Sets the categories of the media
* @param {Array.<goog.ui.media.MediaModel.Category>} categories The categories
* of the media.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setCategories = function(categories) {
this.categories_ = categories;
return this;
};
/**
* Finds the first category with the given scheme.
* @param {string} scheme The scheme to search for.
* @return {goog.ui.media.MediaModel.Category} The category that has the
* given scheme. May be null.
*/
goog.ui.media.MediaModel.prototype.findCategoryWithScheme = function(scheme) {
if (!this.categories_) {
return null;
}
var category = goog.array.find(this.categories_, function(category) {
return category ? (scheme == category.getScheme()) : false;
});
return /** @type {goog.ui.media.MediaModel.Category} */ (category);
};
/**
* Gets the credits of the media.
* @return {!Array.<goog.ui.media.MediaModel.Credit>} The credits of the media.
*/
goog.ui.media.MediaModel.prototype.getCredits = function() {
return this.credits_;
};
/**
* Sets the credits of the media
* @param {!Array.<goog.ui.media.MediaModel.Credit>} credits The credits of the
* media.
* @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
*/
goog.ui.media.MediaModel.prototype.setCredits = function(credits) {
this.credits_ = credits;
return this;
};
/**
* Finds all credits with the given role.
* @param {string} role The role to search for.
* @return {!Array.<!goog.ui.media.MediaModel.Credit>} An array of credits
* with the given role. May be empty.
*/
goog.ui.media.MediaModel.prototype.findCreditsWithRole = function(role) {
var credits = goog.array.filter(this.credits_, function(credit) {
return role == credit.getRole();
});
return /** @type {!Array.<!goog.ui.media.MediaModel.Credit>} */ (credits);
};
/**
* Gets the subtitles for the media.
* @return {Array.<goog.ui.media.MediaModel.SubTitle>} The subtitles.
*/
goog.ui.media.MediaModel.prototype.getSubTitles = function() {
return this.subTitles_;
};
/**
* Sets the subtitles for the media
* @param {Array.<goog.ui.media.MediaModel.SubTitle>} subtitles The subtitles.
* @return {!goog.ui.media.MediaModel} The object itself.
*/
goog.ui.media.MediaModel.prototype.setSubTitles = function(subtitles) {
this.subTitles_ = subtitles;
return this;
};
/**
* Constructs a thumbnail containing details of the thumbnail's image URL and
* optionally its size.
* @param {string} url The URL of the thumbnail's image.
* @param {goog.math.Size=} opt_size The size of the thumbnail's image if known.
* @constructor
*/
goog.ui.media.MediaModel.Thumbnail = function(url, opt_size) {
/**
* The thumbnail's image URL.
* @type {string}
* @private
*/
this.url_ = url;
/**
* The size of the thumbnail's image if known.
* @type {goog.math.Size}
* @private
*/
this.size_ = opt_size || null;
};
/**
* Gets the thumbnail URL.
* @return {string} The thumbnail's image URL.
*/
goog.ui.media.MediaModel.Thumbnail.prototype.getUrl = function() {
return this.url_;
};
/**
* Sets the thumbnail URL.
* @param {string} url The thumbnail's image URL.
* @return {goog.ui.media.MediaModel.Thumbnail} The object itself, used for
* chaining.
*/
goog.ui.media.MediaModel.Thumbnail.prototype.setUrl = function(url) {
this.url_ = url;
return this;
};
/**
* Gets the thumbnail size.
* @return {goog.math.Size} The size of the thumbnail's image if known.
*/
goog.ui.media.MediaModel.Thumbnail.prototype.getSize = function() {
return this.size_;
};
/**
* Sets the thumbnail size.
* @param {goog.math.Size} size The size of the thumbnail's image.
* @return {goog.ui.media.MediaModel.Thumbnail} The object itself, used for
* chaining.
*/
goog.ui.media.MediaModel.Thumbnail.prototype.setSize = function(size) {
this.size_ = size;
return this;
};
/**
* Constructs a player containing details of the player's URL and
* optionally its size.
* @param {string} url The URL of the player.
* @param {Object=} opt_vars Optional map of arguments to the player.
* @param {goog.math.Size=} opt_size The size of the player if known.
* @constructor
*/
goog.ui.media.MediaModel.Player = function(url, opt_vars, opt_size) {
/**
* The player's URL.
* @type {string}
* @private
*/
this.url_ = url;
/**
* Player arguments, typically flash arguments.
* @type {Object}
* @private
*/
this.vars_ = opt_vars || null;
/**
* The size of the player if known.
* @type {goog.math.Size}
* @private
*/
this.size_ = opt_size || null;
};
/**
* Gets the player url.
* @return {string} The thumbnail's image URL.
*/
goog.ui.media.MediaModel.Player.prototype.getUrl = function() {
return this.url_;
};
/**
* Sets the player url.
* @param {string} url The thumbnail's image URL.
* @return {goog.ui.media.MediaModel.Player} The object itself, used for
* chaining.
*/
goog.ui.media.MediaModel.Player.prototype.setUrl = function(url) {
this.url_ = url;
return this;
};
/**
* Gets the player arguments.
* @return {Object} The media player arguments.
*/
goog.ui.media.MediaModel.Player.prototype.getVars = function() {
return this.vars_;
};
/**
* Sets the player arguments.
* @param {Object} vars The media player arguments.
* @return {goog.ui.media.MediaModel.Player} The object itself, used for
* chaining.
*/
goog.ui.media.MediaModel.Player.prototype.setVars = function(vars) {
this.vars_ = vars;
return this;
};
/**
* Gets the size of the player.
* @return {goog.math.Size} The size of the player if known.
*/
goog.ui.media.MediaModel.Player.prototype.getSize = function() {
return this.size_;
};
/**
* Sets the size of the player.
* @param {goog.math.Size} size The size of the player.
* @return {goog.ui.media.MediaModel.Player} The object itself, used for
* chaining.
*/
goog.ui.media.MediaModel.Player.prototype.setSize = function(size) {
this.size_ = size;
return this;
};
/**
* A taxonomy to be set that gives an indication of the type of media content,
* and its particular contents.
* @param {string} scheme The URI that identifies the categorization scheme.
* @param {string} value The value of the category.
* @param {string=} opt_label The human readable label that can be displayed in
* end user applications.
* @constructor
*/
goog.ui.media.MediaModel.Category = function(scheme, value, opt_label) {
/**
* The URI that identifies the categorization scheme.
* @type {string}
* @private
*/
this.scheme_ = scheme;
/**
* The value of the category.
* @type {string}
* @private
*/
this.value_ = value;
/**
* The human readable label that can be displayed in end user applications.
* @type {string}
* @private
*/
this.label_ = opt_label || '';
};
/**
* Gets the category scheme.
* @return {string} The category scheme URI.
*/
goog.ui.media.MediaModel.Category.prototype.getScheme = function() {
return this.scheme_;
};
/**
* Sets the category scheme.
* @param {string} scheme The category's scheme.
* @return {goog.ui.media.MediaModel.Category} The object itself, used for
* chaining.
*/
goog.ui.media.MediaModel.Category.prototype.setScheme = function(scheme) {
this.scheme_ = scheme;
return this;
};
/**
* Gets the categor's value.
* @return {string} The category's value.
*/
goog.ui.media.MediaModel.Category.prototype.getValue = function() {
return this.value_;
};
/**
* Sets the category value.
* @param {string} value The category value to be set.
* @return {goog.ui.media.MediaModel.Category} The object itself, used for
* chaining.
*/
goog.ui.media.MediaModel.Category.prototype.setValue = function(value) {
this.value_ = value;
return this;
};
/**
* Gets the label of the category.
* @return {string} The label of the category.
*/
goog.ui.media.MediaModel.Category.prototype.getLabel = function() {
return this.label_;
};
/**
* Sets the label of the category.
* @param {string} label The label of the category.
* @return {goog.ui.media.MediaModel.Category} The object itself, used for
* chaining.
*/
goog.ui.media.MediaModel.Category.prototype.setLabel = function(label) {
this.label_ = label;
return this;
};
/**
* Indicates an entity that has contributed to a media object. Based on
* 'media.credit' in the rss spec.
* @param {string} value The name of the entity being credited.
* @param {goog.ui.media.MediaModel.Credit.Role=} opt_role The role the entity
* played.
* @param {goog.ui.media.MediaModel.Credit.Scheme=} opt_scheme The URI that
* identifies the role scheme.
* @constructor
*/
goog.ui.media.MediaModel.Credit = function(value, opt_role, opt_scheme) {
/**
* The name of entity being credited.
* @type {string}
* @private
*/
this.value_ = value;
/**
* The role the entity played.
* @type {goog.ui.media.MediaModel.Credit.Role|undefined}
* @private
*/
this.role_ = opt_role;
/**
* The URI that identifies the role scheme
* @type {goog.ui.media.MediaModel.Credit.Scheme|undefined}
* @private
*/
this.scheme_ = opt_scheme;
};
/**
* The types of known roles.
* @enum {string}
*/
goog.ui.media.MediaModel.Credit.Role = {
UPLOADER: 'uploader',
OWNER: 'owner'
};
/**
* The types of known schemes.
* @enum {string}
*/
goog.ui.media.MediaModel.Credit.Scheme = {
EUROPEAN_BROADCASTING: 'urn:ebu',
YAHOO: 'urn:yvs',
YOUTUBE: 'urn:youtube'
};
/**
* Gets the name of the entity being credited.
* @return {string} The name of the entity.
*/
goog.ui.media.MediaModel.Credit.prototype.getValue = function() {
return this.value_;
};
/**
* Sets the value of the credit object.
* @param {string} value The value.
* @return {goog.ui.media.MediaModel.Credit} The object itself.
*/
goog.ui.media.MediaModel.Credit.prototype.setValue = function(value) {
this.value_ = value;
return this;
};
/**
* Gets the role of the entity being credited.
* @return {goog.ui.media.MediaModel.Credit.Role|undefined} The role of the
* entity.
*/
goog.ui.media.MediaModel.Credit.prototype.getRole = function() {
return this.role_;
};
/**
* Sets the role of the credit object.
* @param {goog.ui.media.MediaModel.Credit.Role} role The role.
* @return {goog.ui.media.MediaModel.Credit} The object itself.
*/
goog.ui.media.MediaModel.Credit.prototype.setRole = function(role) {
this.role_ = role;
return this;
};
/**
* Gets the scheme of the credit object.
* @return {goog.ui.media.MediaModel.Credit.Scheme|undefined} The URI that
* identifies the role scheme.
*/
goog.ui.media.MediaModel.Credit.prototype.getScheme = function() {
return this.scheme_;
};
/**
* Sets the scheme of the credit object.
* @param {goog.ui.media.MediaModel.Credit.Scheme} scheme The scheme.
* @return {goog.ui.media.MediaModel.Credit} The object itself.
*/
goog.ui.media.MediaModel.Credit.prototype.setScheme = function(scheme) {
this.scheme_ = scheme;
return this;
};
/**
* A reference to the subtitle URI for a media object.
* Implements the 'media.subTitle' in the rss spec.
*
* @param {string} href The subtitle's URI.
* to fetch the subtitle file.
* @param {string} lang An RFC 3066 language.
* @param {string} type The MIME type of the URI.
* @constructor
*/
goog.ui.media.MediaModel.SubTitle = function(href, lang, type) {
/**
* The subtitle href.
* @type {string}
* @private
*/
this.href_ = href;
/**
* The RFC 3066 language.
* @type {string}
* @private
*/
this.lang_ = lang;
/**
* The MIME type of the resource.
* @type {string}
* @private
*/
this.type_ = type;
};
/**
* Sets the href for the subtitle object.
* @param {string} href The subtitle's URI.
* @return {goog.ui.media.MediaModel.SubTitle} The object itself.
*/
goog.ui.media.MediaModel.SubTitle.prototype.setHref = function(href) {
this.href_ = href;
return this;
};
/**
* Get the href for the subtitle object.
* @return {string} href The subtitle's URI.
*/
goog.ui.media.MediaModel.SubTitle.prototype.getHref = function() {
return this.href_;
};
/**
* Sets the language for the subtitle object.
* @param {string} lang The RFC 3066 language.
* @return {goog.ui.media.MediaModel.SubTitle} The object itself.
*/
goog.ui.media.MediaModel.SubTitle.prototype.setLang = function(lang) {
this.lang_ = lang;
return this;
};
/**
* Get the lang for the subtitle object.
* @return {string} lang The RFC 3066 language.
*/
goog.ui.media.MediaModel.SubTitle.prototype.getLang = function() {
return this.lang_;
};
/**
* Sets the type for the subtitle object.
* @param {string} type The MIME type.
* @return {goog.ui.media.MediaModel.SubTitle} The object itself.
*/
goog.ui.media.MediaModel.SubTitle.prototype.setType = function(type) {
this.type_ = type;
return this;
};
/**
* Get the type for the subtitle object.
* @return {string} type The MIME type.
*/
goog.ui.media.MediaModel.SubTitle.prototype.getType = function() {
return this.type_;
};
@@ -0,0 +1,228 @@
// Copyright 2009 The Closure Library Authors. 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 provides a reusable mp3 UI component given a mp3 URL.
*
* goog.ui.media.Mp3 is actually a {@link goog.ui.ControlRenderer}, a stateless
* class - that could/should be used as a Singleton with the static method
* {@code goog.ui.media.Mp3.getInstance} -, that knows how to render Mp3s. It is
* designed to be used with a {@link goog.ui.Control}, which will actually
* control the media renderer and provide the {@link goog.ui.Component} base.
* This design guarantees that all different types of medias will behave alike
* but will look different.
*
* goog.ui.media.Mp3 expects mp3 urls on {@code goog.ui.Control.getModel} as
* data models, and render a flash object that will play that URL.
*
* Example of usage:
*
* <pre>
* goog.ui.media.Mp3.newControl('http://hostname/file.mp3').render();
* </pre>
*
* Mp3 medias currently support the following states:
*
* <ul>
* <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
* <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the mp3
* <li> {@link goog.ui.Component.State.SELECTED}: mp3 is playing
* </ul>
*
* Which can be accessed by
*
* <pre>
* mp3.setEnabled(true);
* mp3.setHighlighted(true);
* mp3.setSelected(true);
* </pre>
*
*
* @supported IE6, FF2+, Safari. Requires flash to actually work.
*
* TODO(user): test on other browsers
*/
goog.provide('goog.ui.media.Mp3');
goog.require('goog.string');
goog.require('goog.ui.media.FlashObject');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaRenderer');
/**
* Subclasses a goog.ui.media.MediaRenderer to provide a Mp3 specific media
* renderer.
*
* This class knows how to parse mp3 URLs, and render the DOM structure
* of mp3 flash players. This class is meant to be used as a singleton static
* stateless class, that takes {@code goog.ui.media.Media} instances and renders
* it. It expects {@code goog.ui.media.Media.getModel} to return a well formed,
* previously checked, mp3 URL {@see goog.ui.media.PicasaAlbum.parseUrl},
* which is the data model this renderer will use to construct the DOM
* structure. {@see goog.ui.media.PicasaAlbum.newControl} for an example of
* constructing a control with this renderer.
*
* This design is patterned after http://go/closure_control_subclassing
*
* It uses {@link goog.ui.media.FlashObject} to embed the flash object.
*
* @constructor
* @extends {goog.ui.media.MediaRenderer}
*/
goog.ui.media.Mp3 = function() {
goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.Mp3, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.Mp3);
/**
* Flash player arguments. We expect that {@code flashUrl_} will contain a flash
* movie that takes an audioUrl parameter on its URL, containing the URL of the
* mp3 to be played.
*
* @type {string}
* @private
*/
goog.ui.media.Mp3.PLAYER_ARGUMENTS_ = 'audioUrl=%s';
/**
* Default CSS class to be applied to the root element of components rendered
* by this renderer.
*
* @type {string}
*/
goog.ui.media.Mp3.CSS_CLASS = goog.getCssName('goog-ui-media-mp3');
/**
* Flash player URL. Uses Google Reader's mp3 flash player by default.
*
* @type {string}
* @private
*/
goog.ui.media.Mp3.flashUrl_ =
'http://www.google.com/reader/ui/3523697345-audio-player.swf';
/**
* Regular expression to check if a given URL is a valid mp3 URL.
*
* Copied from http://go/markdownlite.js.
*
* NOTE(user): although it would be easier to use goog.string.endsWith('.mp3'),
* in the future, we want to provide media inlining, which is basically getting
* a text and replacing all mp3 references with an mp3 player, so it makes sense
* to share the same regular expression to match everything.
*
* @type {RegExp}
*/
goog.ui.media.Mp3.MATCHER =
/(https?:\/\/[\w-%&\/.=:#\+~\(\)]+\.(mp3)+(\?[\w-%&\/.=:#\+~\(\)]+)?)/i;
/**
* A static convenient method to construct a goog.ui.media.Media control out of
* a mp3 URL. It checks the mp3 URL, sets it as the data model
* goog.ui.media.Mp3 renderer uses, sets the states supported by the renderer,
* and returns a Control that binds everything together. This is what you
* should be using for constructing Mp3 videos, except if you need more fine
* control over the configuration.
*
* @param {goog.ui.media.MediaModel} dataModel A media model that must contain
* an mp3 url on {@code dataModel.getUrl}.
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
* document interaction.
* @return {goog.ui.media.Media} A goog.ui.Control subclass with the mp3
* renderer.
*/
goog.ui.media.Mp3.newControl = function(dataModel, opt_domHelper) {
var control = new goog.ui.media.Media(
dataModel,
goog.ui.media.Mp3.getInstance(),
opt_domHelper);
// mp3 ui doesn't have a non selected view: it shows the mp3 player by
// default.
control.setSelected(true);
return control;
};
/**
* A static method that sets which flash URL this class should use. Use this if
* you want to host your own flash mp3 player.
*
* @param {string} flashUrl The URL of the flash mp3 player.
*/
goog.ui.media.Mp3.setFlashUrl = function(flashUrl) {
goog.ui.media.Mp3.flashUrl_ = flashUrl;
};
/**
* A static method that builds a URL that will contain the flash player that
* will play the {@code mp3Url}.
*
* @param {string} mp3Url The URL of the mp3 music.
* @return {string} An URL of a flash player that will know how to play the
* given {@code mp3Url}.
*/
goog.ui.media.Mp3.buildFlashUrl = function(mp3Url) {
var flashUrl = goog.ui.media.Mp3.flashUrl_ + '?' + goog.string.subs(
goog.ui.media.Mp3.PLAYER_ARGUMENTS_,
goog.string.urlEncode(mp3Url));
return flashUrl;
};
/**
* Creates the initial DOM structure of a mp3 video, which is basically a
* the flash object pointing to a flash mp3 player.
*
* @param {goog.ui.Control} c The media control.
* @return {Element} A DOM structure that represents the control.
* @override
*/
goog.ui.media.Mp3.prototype.createDom = function(c) {
var control = /** @type {goog.ui.media.Media} */ (c);
var div = goog.ui.media.Mp3.superClass_.createDom.call(this, control);
var dataModel =
/** @type {goog.ui.media.MediaModel} */ (control.getDataModel());
var flashUrl = goog.ui.media.Mp3.flashUrl_ + '?' + goog.string.subs(
goog.ui.media.Mp3.PLAYER_ARGUMENTS_,
goog.string.urlEncode(dataModel.getUrl()));
var flash = new goog.ui.media.FlashObject(
dataModel.getPlayer().getUrl(), control.getDomHelper());
flash.setFlashVar('playerMode', 'embedded');
flash.render(div);
return div;
};
/**
* Returns the CSS class to be applied to the root element of components
* rendered using this renderer.
* @return {string} Renderer-specific CSS class.
* @override
*/
goog.ui.media.Mp3.prototype.getCssClass = function() {
return goog.ui.media.Mp3.CSS_CLASS;
};
@@ -0,0 +1,142 @@
// Copyright 2009 The Closure Library Authors. 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 provides a reusable photo UI component that renders photos that
* contains metadata (such as captions, description, thumbnail/high resolution
* versions, etc).
*
* goog.ui.media.Photo is actually a {@link goog.ui.ControlRenderer},
* a stateless class - that could/should be used as a Singleton with the static
* method {@code goog.ui.media.Photo.getInstance} -, that knows how to render
* Photos. It is designed to be used with a {@link goog.ui.Control}, which will
* actually control the media renderer and provide the {@link goog.ui.Component}
* base. This design guarantees that all different types of medias will behave
* alike but will look different.
*
* goog.ui.media.Photo expects {@code goog.ui.media.MediaModel} on
* {@code goog.ui.Control.getModel} as data models.
*
* Example of usage:
*
* <pre>
* var photo = goog.ui.media.Photo.newControl(
* new goog.ui.media.MediaModel('http://hostname/file.jpg'));
* photo.render(goog.dom.getElement('parent'));
* </pre>
*
* Photo medias currently support the following states:
*
* <ul>
* <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the photo.
* <li> {@link goog.ui.Component.State.SELECTED}: photo is being displayed.
* </ul>
*
* Which can be accessed by
*
* <pre>
* photo.setHighlighted(true);
* photo.setSelected(true);
* </pre>
*
*/
goog.provide('goog.ui.media.Photo');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaRenderer');
/**
* Subclasses a goog.ui.media.MediaRenderer to provide a Photo specific media
* renderer. Provides a base class for any other renderer that wants to display
* photos.
*
* This class is meant to be used as a singleton static stateless class, that
* takes {@code goog.ui.media.Media} instances and renders it.
*
* This design is patterned after
* http://go/closure_control_subclassing
*
* @constructor
* @extends {goog.ui.media.MediaRenderer}
*/
goog.ui.media.Photo = function() {
goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.Photo, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.Photo);
/**
* Default CSS class to be applied to the root element of components rendered
* by this renderer.
*
* @type {string}
*/
goog.ui.media.Photo.CSS_CLASS = goog.getCssName('goog-ui-media-photo');
/**
* A static convenient method to construct a goog.ui.media.Media control out of
* a photo {@code goog.ui.media.MediaModel}. It sets it as the data model
* goog.ui.media.Photo renderer uses, sets the states supported by the renderer,
* and returns a Control that binds everything together. This is what you
* should be using for constructing Photos, except if you need finer control
* over the configuration.
*
* @param {goog.ui.media.MediaModel} dataModel The photo data model.
* @return {goog.ui.media.Media} A goog.ui.Control subclass with the photo
* renderer.
*/
goog.ui.media.Photo.newControl = function(dataModel) {
var control = new goog.ui.media.Media(
dataModel,
goog.ui.media.Photo.getInstance());
return control;
};
/**
* Creates the initial DOM structure of a photo.
*
* @param {goog.ui.Control} c The media control.
* @return {Element} A DOM structure that represents the control.
* @override
*/
goog.ui.media.Photo.prototype.createDom = function(c) {
var control = /** @type {goog.ui.media.Media} */ (c);
var div = goog.ui.media.Photo.superClass_.createDom.call(this, control);
var img = control.getDomHelper().createDom('img', {
src: control.getDataModel().getPlayer().getUrl(),
className: goog.getCssName(this.getCssClass(), 'image')
});
div.appendChild(img);
return div;
};
/**
* Returns the CSS class to be applied to the root element of components
* rendered using this renderer.
* @return {string} Renderer-specific CSS class.
* @override
*/
goog.ui.media.Photo.prototype.getCssClass = function() {
return goog.ui.media.Photo.CSS_CLASS;
};
@@ -0,0 +1,321 @@
// Copyright 2009 The Closure Library Authors. 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 provides a reusable picasa album UI component given a public
* picasa album URL.
*
* TODO(user): implement the javascript viewer, for users without flash. Get it
* from the Gmail Picasa gadget.
*
* goog.ui.media.PicasaAlbum is actually a {@link goog.ui.ControlRenderer}, a
* stateless class - that could/should be used as a Singleton with the static
* method {@code goog.ui.media.PicasaAlbum.getInstance} -, that knows how to
* render picasa albums. It is designed to be used with a
* {@link goog.ui.Control}, which will actually control the media renderer and
* provide the {@link goog.ui.Component} base. This design guarantees that all
* different types of medias will behave alike but will look different.
*
* goog.ui.media.PicasaAlbum expects {@code goog.ui.media.PicasaAlbumModel}s on
* {@code goog.ui.Control.getModel} as data models, and render a flash object
* that will show a slideshow with the contents of that album URL.
*
* Example of usage:
*
* <pre>
* var album = goog.ui.media.PicasaAlbumModel.newInstance(
* 'http://picasaweb.google.com/username/SanFranciscoCalifornia');
* goog.ui.media.PicasaAlbum.newControl(album).render();
* </pre>
*
* picasa medias currently support the following states:
*
* <ul>
* <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
* <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the album
* <li> {@link goog.ui.Component.State.SELECTED}: flash album is shown
* </ul>
*
* Which can be accessed by
*
* <pre>
* picasa.setEnabled(true);
* picasa.setHighlighted(true);
* picasa.setSelected(true);
* </pre>
*
*
* @supported IE6, FF2+, Safari. Requires flash to actually work.
*
* TODO(user): test on other browsers
*/
goog.provide('goog.ui.media.PicasaAlbum');
goog.provide('goog.ui.media.PicasaAlbumModel');
goog.require('goog.ui.media.FlashObject');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaModel');
goog.require('goog.ui.media.MediaRenderer');
/**
* Subclasses a goog.ui.media.MediaRenderer to provide a Picasa specific media
* renderer.
*
* This class knows how to parse picasa URLs, and render the DOM structure
* of picasa album players and previews. This class is meant to be used as a
* singleton static stateless class, that takes {@code goog.ui.media.Media}
* instances and renders it. It expects {@code goog.ui.media.Media.getModel} to
* return a well formed, previously constructed, object with a user and album
* fields {@see goog.ui.media.PicasaAlbum.parseUrl}, which is the data model
* this renderer will use to construct the DOM structure.
* {@see goog.ui.media.PicasaAlbum.newControl} for a example of constructing a
* control with this renderer.
*
* goog.ui.media.PicasaAlbum currently displays a picasa-made flash slideshow
* with the photos, but could possibly display a handwritten js photo viewer,
* in case flash is not available.
*
* This design is patterned after http://go/closure_control_subclassing
*
* It uses {@link goog.ui.media.FlashObject} to embed the flash object.
*
* @constructor
* @extends {goog.ui.media.MediaRenderer}
*/
goog.ui.media.PicasaAlbum = function() {
goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.PicasaAlbum, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.PicasaAlbum);
/**
* Default CSS class to be applied to the root element of components rendered
* by this renderer.
*
* @type {string}
*/
goog.ui.media.PicasaAlbum.CSS_CLASS = goog.getCssName('goog-ui-media-picasa');
/**
* A static convenient method to construct a goog.ui.media.Media control out of
* a picasa data model. It sets it as the data model goog.ui.media.PicasaAlbum
* renderer uses, sets the states supported by the renderer, and returns a
* Control that binds everything together. This is what you should be using for
* constructing Picasa albums, except if you need finer control over the
* configuration.
*
* @param {goog.ui.media.PicasaAlbumModel} dataModel A picasa album data model.
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
* document interaction.
* @return {goog.ui.media.Media} A Control instance binded to the Picasa
* renderer.
*/
goog.ui.media.PicasaAlbum.newControl = function(dataModel, opt_domHelper) {
var control = new goog.ui.media.Media(
dataModel,
goog.ui.media.PicasaAlbum.getInstance(),
opt_domHelper);
control.setSelected(true);
return control;
};
/**
* Creates the initial DOM structure of the picasa album, which is basically a
* the flash object pointing to a flash picasa album player.
*
* @param {goog.ui.Control} c The media control.
* @return {Element} The DOM structure that represents the control.
* @override
*/
goog.ui.media.PicasaAlbum.prototype.createDom = function(c) {
var control = /** @type {goog.ui.media.Media} */ (c);
var div = goog.ui.media.PicasaAlbum.superClass_.createDom.call(this, control);
var picasaAlbum =
/** @type {goog.ui.media.PicasaAlbumModel} */ (control.getDataModel());
var authParam =
picasaAlbum.getAuthKey() ? ('&authkey=' + picasaAlbum.getAuthKey()) : '';
var flash = new goog.ui.media.FlashObject(
picasaAlbum.getPlayer().getUrl() || '',
control.getDomHelper());
flash.addFlashVars(picasaAlbum.getPlayer().getVars());
flash.render(div);
return div;
};
/**
* Returns the CSS class to be applied to the root element of components
* rendered using this renderer.
* @return {string} Renderer-specific CSS class.
* @override
*/
goog.ui.media.PicasaAlbum.prototype.getCssClass = function() {
return goog.ui.media.PicasaAlbum.CSS_CLASS;
};
/**
* The {@code goog.ui.media.PicasaAlbum} media data model. It stores a required
* {@code userId} and {@code albumId} fields, sets the picasa album URL, and
* allows a few optional parameters.
*
* @param {string} userId The picasa userId associated with this album.
* @param {string} albumId The picasa albumId associated with this album.
* @param {string=} opt_authKey An optional authentication key, used on private
* albums.
* @param {string=} opt_caption An optional caption of the picasa album.
* @param {string=} opt_description An optional description of the picasa album.
* @param {boolean=} opt_autoplay Whether to autoplay the slideshow.
* @constructor
* @extends {goog.ui.media.MediaModel}
*/
goog.ui.media.PicasaAlbumModel = function(userId,
albumId,
opt_authKey,
opt_caption,
opt_description,
opt_autoplay) {
goog.ui.media.MediaModel.call(
this,
goog.ui.media.PicasaAlbumModel.buildUrl(userId, albumId),
opt_caption,
opt_description,
goog.ui.media.MediaModel.MimeType.FLASH);
/**
* The Picasa user id.
* @type {string}
* @private
*/
this.userId_ = userId;
/**
* The Picasa album id.
* @type {string}
* @private
*/
this.albumId_ = albumId;
/**
* The Picasa authentication key, used on private albums.
* @type {?string}
* @private
*/
this.authKey_ = opt_authKey || null;
var authParam = opt_authKey ? ('&authkey=' + opt_authKey) : '';
var flashVars = {
'host': 'picasaweb.google.com',
'RGB': '0x000000',
'feed': 'http://picasaweb.google.com/data/feed/api/user/' +
userId + '/album/' + albumId + '?kind=photo&alt=rss' + authParam
};
flashVars[opt_autoplay ? 'autoplay' : 'noautoplay'] = '1';
var player = new goog.ui.media.MediaModel.Player(
'http://picasaweb.google.com/s/c/bin/slideshow.swf', flashVars);
this.setPlayer(player);
};
goog.inherits(goog.ui.media.PicasaAlbumModel, goog.ui.media.MediaModel);
/**
* Regular expression used to extract the picasa username and albumid out of
* picasa URLs.
*
* Copied from http://go/markdownlite.js,
* and {@link PicasaWebExtractor.xml}.
*
* @type {RegExp}
* @private
* @const
*/
goog.ui.media.PicasaAlbumModel.MATCHER_ =
/https?:\/\/(?:www\.)?picasaweb\.(?:google\.)?com\/([\d\w\.]+)\/([\d\w_\-\.]+)(?:\?[\w\d\-_=&amp;;\.]*&?authKey=([\w\d\-_=;\.]+))?(?:#([\d]+)?)?/im;
/**
* Gets a {@code picasaUrl} and extracts the user and album id.
*
* @param {string} picasaUrl A picasa album URL.
* @param {string=} opt_caption An optional caption of the picasa album.
* @param {string=} opt_description An optional description of the picasa album.
* @param {boolean=} opt_autoplay Whether to autoplay the slideshow.
* @return {goog.ui.media.PicasaAlbumModel} The picasa album data model that
* represents the picasa URL.
* @throws exception in case the parsing fails
*/
goog.ui.media.PicasaAlbumModel.newInstance = function(picasaUrl,
opt_caption,
opt_description,
opt_autoplay) {
if (goog.ui.media.PicasaAlbumModel.MATCHER_.test(picasaUrl)) {
var data = goog.ui.media.PicasaAlbumModel.MATCHER_.exec(picasaUrl);
return new goog.ui.media.PicasaAlbumModel(
data[1], data[2], data[3], opt_caption, opt_description, opt_autoplay);
}
throw Error('failed to parse user and album from picasa url: ' + picasaUrl);
};
/**
* The opposite of {@code newInstance}: takes an {@code userId} and an
* {@code albumId} and builds a URL.
*
* @param {string} userId The user that owns the album.
* @param {string} albumId The album id.
* @return {string} The URL of the album.
*/
goog.ui.media.PicasaAlbumModel.buildUrl = function(userId, albumId) {
return 'http://picasaweb.google.com/' + userId + '/' + albumId;
};
/**
* Gets the Picasa user id.
* @return {string} The Picasa user id.
*/
goog.ui.media.PicasaAlbumModel.prototype.getUserId = function() {
return this.userId_;
};
/**
* Gets the Picasa album id.
* @return {string} The Picasa album id.
*/
goog.ui.media.PicasaAlbumModel.prototype.getAlbumId = function() {
return this.albumId_;
};
/**
* Gets the Picasa album authentication key.
* @return {?string} The Picasa album authentication key.
*/
goog.ui.media.PicasaAlbumModel.prototype.getAuthKey = function() {
return this.authKey_;
};
@@ -0,0 +1,276 @@
// Copyright 2009 The Closure Library Authors. 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 provides a reusable Vimeo video UI component given a public
* Vimeo video URL.
*
* goog.ui.media.Vimeo is actually a {@link goog.ui.ControlRenderer}, a
* stateless class - that could/should be used as a Singleton with the static
* method {@code goog.ui.media.Vimeo.getInstance} -, that knows how to render
* video videos. It is designed to be used with a {@link goog.ui.Control},
* which will actually control the media renderer and provide the
* {@link goog.ui.Component} base. This design guarantees that all different
* types of medias will behave alike but will look different.
*
* goog.ui.media.Vimeo expects vimeo video IDs on
* {@code goog.ui.Control.getModel} as data models, and renders a flash object
* that will show the contents of that video.
*
* Example of usage:
*
* <pre>
* var video = goog.ui.media.VimeoModel.newInstance('http://vimeo.com/30012');
* goog.ui.media.Vimeo.newControl(video).render();
* </pre>
*
* Vimeo medias currently support the following states:
*
* <ul>
* <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
* <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
* <li> {@link goog.ui.Component.State.SELECTED}: flash video is shown
* </ul>
*
* Which can be accessed by
* <pre>
* video.setEnabled(true);
* video.setHighlighted(true);
* video.setSelected(true);
* </pre>
*
*
* @supported IE6, FF2+, Safari. Requires flash to actually work.
*
* TODO(user): test on other browsers
*/
goog.provide('goog.ui.media.Vimeo');
goog.provide('goog.ui.media.VimeoModel');
goog.require('goog.string');
goog.require('goog.ui.media.FlashObject');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaModel');
goog.require('goog.ui.media.MediaRenderer');
/**
* Subclasses a goog.ui.media.MediaRenderer to provide a Vimeo specific media
* renderer.
*
* This class knows how to parse Vimeo URLs, and render the DOM structure
* of vimeo video players. This class is meant to be used as a singleton static
* stateless class, that takes {@code goog.ui.media.Media} instances and renders
* it. It expects {@code goog.ui.media.Media.getModel} to return a well formed,
* previously constructed, vimeoId {@see goog.ui.media.Vimeo.parseUrl}, which is
* the data model this renderer will use to construct the DOM structure.
* {@see goog.ui.media.Vimeo.newControl} for a example of constructing a control
* with this renderer.
*
* This design is patterned after http://go/closure_control_subclassing
*
* It uses {@link goog.ui.media.FlashObject} to embed the flash object.
*
* @constructor
* @extends {goog.ui.media.MediaRenderer}
*/
goog.ui.media.Vimeo = function() {
goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.Vimeo, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.Vimeo);
/**
* Default CSS class to be applied to the root element of components rendered
* by this renderer.
*
* @type {string}
*/
goog.ui.media.Vimeo.CSS_CLASS = goog.getCssName('goog-ui-media-vimeo');
/**
* A static convenient method to construct a goog.ui.media.Media control out of
* a Vimeo URL. It extracts the videoId information on the URL, sets it
* as the data model goog.ui.media.Vimeo renderer uses, sets the states
* supported by the renderer, and returns a Control that binds everything
* together. This is what you should be using for constructing Vimeo videos,
* except if you need more fine control over the configuration.
*
* @param {goog.ui.media.VimeoModel} dataModel A vimeo video URL.
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
* document interaction.
* @return {goog.ui.media.Media} A Control binded to the Vimeo renderer.
*/
goog.ui.media.Vimeo.newControl = function(dataModel, opt_domHelper) {
var control = new goog.ui.media.Media(
dataModel, goog.ui.media.Vimeo.getInstance(), opt_domHelper);
// vimeo videos don't have any thumbnail for now, so we show the
// "selected" version of the UI at the start, which is the
// flash player.
control.setSelected(true);
return control;
};
/**
* Creates the initial DOM structure of the vimeo video, which is basically a
* the flash object pointing to a vimeo video player.
*
* @param {goog.ui.Control} c The media control.
* @return {Element} The DOM structure that represents this control.
* @override
*/
goog.ui.media.Vimeo.prototype.createDom = function(c) {
var control = /** @type {goog.ui.media.Media} */ (c);
var div = goog.ui.media.Vimeo.superClass_.createDom.call(this, control);
var dataModel =
/** @type {goog.ui.media.VimeoModel} */ (control.getDataModel());
var flash = new goog.ui.media.FlashObject(
dataModel.getPlayer().getUrl() || '',
control.getDomHelper());
flash.render(div);
return div;
};
/**
* Returns the CSS class to be applied to the root element of components
* rendered using this renderer.
* @return {string} Renderer-specific CSS class.
* @override
*/
goog.ui.media.Vimeo.prototype.getCssClass = function() {
return goog.ui.media.Vimeo.CSS_CLASS;
};
/**
* The {@code goog.ui.media.Vimeo} media data model. It stores a required
* {@code videoId} field, sets the vimeo URL, and allows a few optional
* parameters.
*
* @param {string} videoId The vimeo video id.
* @param {string=} opt_caption An optional caption of the vimeo video.
* @param {string=} opt_description An optional description of the vimeo video.
* @param {boolean=} opt_autoplay Whether to autoplay video.
* @constructor
* @extends {goog.ui.media.MediaModel}
*/
goog.ui.media.VimeoModel = function(videoId, opt_caption, opt_description,
opt_autoplay) {
goog.ui.media.MediaModel.call(
this,
goog.ui.media.VimeoModel.buildUrl(videoId),
opt_caption,
opt_description,
goog.ui.media.MediaModel.MimeType.FLASH);
/**
* The Vimeo video id.
* @type {string}
* @private
*/
this.videoId_ = videoId;
this.setPlayer(new goog.ui.media.MediaModel.Player(
goog.ui.media.VimeoModel.buildFlashUrl(videoId, opt_autoplay)));
};
goog.inherits(goog.ui.media.VimeoModel, goog.ui.media.MediaModel);
/**
* Regular expression used to extract the vimeo video id out of vimeo URLs.
*
* Copied from http://go/markdownlite.js
*
* TODO(user): add support to https.
*
* @type {RegExp}
* @private
* @const
*/
goog.ui.media.VimeoModel.MATCHER_ =
/https?:\/\/(?:www\.)?vimeo\.com\/(?:hd#)?([0-9]+)/i;
/**
* Takes a {@code vimeoUrl} and extracts the video id.
*
* @param {string} vimeoUrl A vimeo video URL.
* @param {string=} opt_caption An optional caption of the vimeo video.
* @param {string=} opt_description An optional description of the vimeo video.
* @param {boolean=} opt_autoplay Whether to autoplay video.
* @return {goog.ui.media.VimeoModel} The vimeo data model that represents this
* URL.
* @throws exception in case the parsing fails
*/
goog.ui.media.VimeoModel.newInstance = function(vimeoUrl,
opt_caption,
opt_description,
opt_autoplay) {
if (goog.ui.media.VimeoModel.MATCHER_.test(vimeoUrl)) {
var data = goog.ui.media.VimeoModel.MATCHER_.exec(vimeoUrl);
return new goog.ui.media.VimeoModel(
data[1], opt_caption, opt_description, opt_autoplay);
}
throw Error('failed to parse vimeo url: ' + vimeoUrl);
};
/**
* The opposite of {@code goog.ui.media.Vimeo.parseUrl}: it takes a videoId
* and returns a vimeo URL.
*
* @param {string} videoId The vimeo video ID.
* @return {string} The vimeo URL.
*/
goog.ui.media.VimeoModel.buildUrl = function(videoId) {
return 'http://vimeo.com/' + goog.string.urlEncode(videoId);
};
/**
* Builds a flash url from the vimeo {@code videoId}.
*
* @param {string} videoId The vimeo video ID.
* @param {boolean=} opt_autoplay Whether the flash movie should start playing
* as soon as it is shown, or if it should show a 'play' button.
* @return {string} The vimeo flash URL.
*/
goog.ui.media.VimeoModel.buildFlashUrl = function(videoId, opt_autoplay) {
var autoplay = opt_autoplay ? '&autoplay=1' : '';
return 'http://vimeo.com/moogaloop.swf?clip_id=' +
goog.string.urlEncode(videoId) +
'&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0color=&' +
'fullscreen=1' + autoplay;
};
/**
* Gets the Vimeo video id.
* @return {string} The Vimeo video id.
*/
goog.ui.media.VimeoModel.prototype.getVideoId = function() {
return this.videoId_;
};
@@ -0,0 +1,357 @@
// Copyright 2009 The Closure Library Authors. 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 provides a reusable youtube UI component given a youtube data
* model.
*
* goog.ui.media.Youtube is actually a {@link goog.ui.ControlRenderer}, a
* stateless class - that could/should be used as a Singleton with the static
* method {@code goog.ui.media.Youtube.getInstance} -, that knows how to render
* youtube videos. It is designed to be used with a {@link goog.ui.Control},
* which will actually control the media renderer and provide the
* {@link goog.ui.Component} base. This design guarantees that all different
* types of medias will behave alike but will look different.
*
* goog.ui.media.Youtube expects {@code goog.ui.media.YoutubeModel} on
* {@code goog.ui.Control.getModel} as data models, and render a flash object
* that will play that URL.
*
* Example of usage:
*
* <pre>
* var video = goog.ui.media.YoutubeModel.newInstance(
* 'http://www.youtube.com/watch?v=ddl5f44spwQ');
* goog.ui.media.Youtube.newControl(video).render();
* </pre>
*
* youtube medias currently support the following states:
*
* <ul>
* <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
* <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
* <li> {@link !goog.ui.Component.State.SELECTED}: a static thumbnail is shown
* <li> {@link goog.ui.Component.State.SELECTED}: video is playing
* </ul>
*
* Which can be accessed by
* <pre>
* youtube.setEnabled(true);
* youtube.setHighlighted(true);
* youtube.setSelected(true);
* </pre>
*
* This package also provides a few static auxiliary methods, such as:
*
* <pre>
* var videoId = goog.ui.media.Youtube.parseUrl(
* 'http://www.youtube.com/watch?v=ddl5f44spwQ');
* </pre>
*
*
* @supported IE6, FF2+, Safari. Requires flash to actually work.
*
* TODO(user): test on other browsers
*/
goog.provide('goog.ui.media.Youtube');
goog.provide('goog.ui.media.YoutubeModel');
goog.require('goog.string');
goog.require('goog.ui.Component');
goog.require('goog.ui.media.FlashObject');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaModel');
goog.require('goog.ui.media.MediaRenderer');
/**
* Subclasses a goog.ui.media.MediaRenderer to provide a Youtube specific media
* renderer.
*
* This class knows how to parse youtube urls, and render the DOM structure
* of youtube video players and previews. This class is meant to be used as a
* singleton static stateless class, that takes {@code goog.ui.media.Media}
* instances and renders it. It expects {@code goog.ui.media.Media.getModel} to
* return a well formed, previously constructed, youtube video id, which is the
* data model this renderer will use to construct the DOM structure.
* {@see goog.ui.media.Youtube.newControl} for a example of constructing a
* control with this renderer.
*
* goog.ui.media.Youtube currently supports all {@link goog.ui.Component.State}.
* It will change its DOM structure between SELECTED and !SELECTED, and rely on
* CSS definitions on the others. On !SELECTED, the renderer will render a
* youtube static <img>, with a thumbnail of the video. On SELECTED, the
* renderer will append to the DOM a flash object, that contains the youtube
* video.
*
* This design is patterned after http://go/closure_control_subclassing
*
* It uses {@link goog.ui.media.FlashObject} to embed the flash object.
*
* @constructor
* @extends {goog.ui.media.MediaRenderer}
*/
goog.ui.media.Youtube = function() {
goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.Youtube, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.Youtube);
/**
* A static convenient method to construct a goog.ui.media.Media control out of
* a youtube model. It sets it as the data model goog.ui.media.Youtube renderer
* uses, sets the states supported by the renderer, and returns a Control that
* binds everything together. This is what you should be using for constructing
* Youtube videos, except if you need finer control over the configuration.
*
* @param {goog.ui.media.YoutubeModel} youtubeModel The youtube data model.
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
* document interaction.
* @return {goog.ui.media.Media} A Control binded to the youtube renderer.
*/
goog.ui.media.Youtube.newControl = function(youtubeModel, opt_domHelper) {
var control = new goog.ui.media.Media(
youtubeModel,
goog.ui.media.Youtube.getInstance(),
opt_domHelper);
control.setStateInternal(goog.ui.Component.State.ACTIVE);
return control;
};
/**
* Default CSS class to be applied to the root element of components rendered
* by this renderer.
* @type {string}
*/
goog.ui.media.Youtube.CSS_CLASS = goog.getCssName('goog-ui-media-youtube');
/**
* Changes the state of a {@code control}. Currently only changes the DOM
* structure when the youtube movie is SELECTED (by default fired by a MOUSEUP
* on the thumbnail), which means we have to embed the youtube flash video and
* play it.
*
* @param {goog.ui.Control} c The media control.
* @param {goog.ui.Component.State} state The state to be set or cleared.
* @param {boolean} enable Whether the state is enabled or disabled.
* @override
*/
goog.ui.media.Youtube.prototype.setState = function(c, state, enable) {
var control = /** @type {goog.ui.media.Media} */ (c);
goog.ui.media.Youtube.superClass_.setState.call(this, control, state, enable);
// control.createDom has to be called before any state is set.
// Use control.setStateInternal if you need to set states
if (!control.getElement()) {
throw Error(goog.ui.Component.Error.STATE_INVALID);
}
var domHelper = control.getDomHelper();
var dataModel =
/** @type {goog.ui.media.YoutubeModel} */ (control.getDataModel());
if (!!(state & goog.ui.Component.State.SELECTED) && enable) {
var flashEls = domHelper.getElementsByTagNameAndClass(
'div',
goog.ui.media.FlashObject.CSS_CLASS,
control.getElement());
if (flashEls.length > 0) {
return;
}
var youtubeFlash = new goog.ui.media.FlashObject(
dataModel.getPlayer().getUrl() || '',
domHelper);
control.addChild(youtubeFlash, true);
}
};
/**
* Returns the CSS class to be applied to the root element of components
* rendered using this renderer.
*
* @return {string} Renderer-specific CSS class.
* @override
*/
goog.ui.media.Youtube.prototype.getCssClass = function() {
return goog.ui.media.Youtube.CSS_CLASS;
};
/**
* The {@code goog.ui.media.Youtube} media data model. It stores a required
* {@code videoId} field, sets the youtube URL, and allows a few optional
* parameters.
*
* @param {string} videoId The youtube video id.
* @param {string=} opt_caption An optional caption of the youtube video.
* @param {string=} opt_description An optional description of the youtube
* video.
* @constructor
* @extends {goog.ui.media.MediaModel}
*/
goog.ui.media.YoutubeModel = function(videoId, opt_caption, opt_description) {
goog.ui.media.MediaModel.call(
this,
goog.ui.media.YoutubeModel.buildUrl(videoId),
opt_caption,
opt_description,
goog.ui.media.MediaModel.MimeType.FLASH);
/**
* The Youtube video id.
* @type {string}
* @private
*/
this.videoId_ = videoId;
this.setThumbnails([new goog.ui.media.MediaModel.Thumbnail(
goog.ui.media.YoutubeModel.getThumbnailUrl(videoId))]);
this.setPlayer(new goog.ui.media.MediaModel.Player(
this.getFlashUrl(videoId, true)));
};
goog.inherits(goog.ui.media.YoutubeModel, goog.ui.media.MediaModel);
/**
* A youtube regular expression matcher. It matches the VIDEOID of URLs like
* http://www.youtube.com/watch?v=VIDEOID. Based on:
* googledata/contentonebox/opencob/specs/common/YTPublicExtractorCard.xml
* @type {RegExp}
* @private
* @const
*/
// Be careful about the placement of the dashes in the character classes. Eg,
// use "[\\w=-]" instead of "[\\w-=]" if you mean to include the dash as a
// character and not create a character range like "[a-f]".
goog.ui.media.YoutubeModel.MATCHER_ = new RegExp(
// Lead in.
'http://(?:[a-zA-Z]{2,3}\\.)?' +
// Watch URL prefix. This should handle new URLs of the form:
// http://www.youtube.com/watch#!v=jqxENMKaeCU&feature=related
// where the parameters appear after "#!" instead of "?".
'(?:youtube\\.com/watch)' +
// Get the video id:
// The video ID is a parameter v=[videoid] either right after the "?"
// or after some other parameters.
'(?:\\?(?:[\\w=-]+&(?:amp;)?)*v=([\\w-]+)' +
'(?:&(?:amp;)?[\\w=-]+)*)?' +
// Get any extra arguments in the URL's hash part.
'(?:#[!]?(?:' +
// Video ID from the v=[videoid] parameter, optionally surrounded by other
// & separated parameters.
'(?:(?:[\\w=-]+&(?:amp;)?)*(?:v=([\\w-]+))' +
'(?:&(?:amp;)?[\\w=-]+)*)' +
'|' +
// Continue supporting "?" for the video ID
// and "#" for other hash parameters.
'(?:[\\w=&-]+)' +
'))?' +
// Should terminate with a non-word, non-dash (-) character.
'[^\\w-]?', 'i');
/**
* A auxiliary static method that parses a youtube URL, extracting the ID of the
* video, and builds a YoutubeModel.
*
* @param {string} youtubeUrl A youtube URL.
* @param {string=} opt_caption An optional caption of the youtube video.
* @param {string=} opt_description An optional description of the youtube
* video.
* @return {goog.ui.media.YoutubeModel} The data model that represents the
* youtube URL.
* @see goog.ui.media.YoutubeModel.getVideoId()
* @throws Error in case the parsing fails.
*/
goog.ui.media.YoutubeModel.newInstance = function(youtubeUrl,
opt_caption,
opt_description) {
var extract = goog.ui.media.YoutubeModel.MATCHER_.exec(youtubeUrl);
if (extract) {
var videoId = extract[1] || extract[2];
return new goog.ui.media.YoutubeModel(
videoId, opt_caption, opt_description);
}
throw Error('failed to parse video id from youtube url: ' + youtubeUrl);
};
/**
* The opposite of {@code goog.ui.media.Youtube.newInstance}: it takes a videoId
* and returns a youtube URL.
*
* @param {string} videoId The youtube video ID.
* @return {string} The youtube URL.
*/
goog.ui.media.YoutubeModel.buildUrl = function(videoId) {
return 'http://www.youtube.com/watch?v=' + goog.string.urlEncode(videoId);
};
/**
* A static auxiliary method that builds a static image URL with a preview of
* the youtube video.
*
* NOTE(user): patterned after Gmail's gadgets/youtube,
*
* TODO(user): how do I specify the width/height of the resulting image on the
* url ? is there an official API for http://ytimg.com ?
*
* @param {string} youtubeId The youtube video ID.
* @return {string} An URL that contains an image with a preview of the youtube
* movie.
*/
goog.ui.media.YoutubeModel.getThumbnailUrl = function(youtubeId) {
return 'http://i.ytimg.com/vi/' + youtubeId + '/default.jpg';
};
/**
* An auxiliary method that builds URL of the flash movie to be embedded,
* out of the youtube video id.
*
* @param {string} videoId The youtube video ID.
* @param {boolean=} opt_autoplay Whether the flash movie should start playing
* as soon as it is shown, or if it should show a 'play' button.
* @return {string} The flash URL to be embedded on the page.
*/
goog.ui.media.YoutubeModel.prototype.getFlashUrl = function(videoId,
opt_autoplay) {
var autoplay = opt_autoplay ? '&autoplay=1' : '';
// YouTube video ids are extracted from youtube URLs, which are user
// generated input. the video id is later used to embed a flash object,
// which is generated through HTML construction. We goog.string.urlEncode
// the video id to make sure the URL is safe to be embedded.
return 'http://www.youtube.com/v/' + goog.string.urlEncode(videoId) +
'&hl=en&fs=1' + autoplay;
};
/**
* Gets the Youtube video id.
* @return {string} The Youtube video id.
*/
goog.ui.media.YoutubeModel.prototype.getVideoId = function() {
return this.videoId_;
};