All Downloads are FREE. Search and download functionalities are using the official Maven repository.

goog.ui.media.media.js Maven / Gradle / Ivy

// 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:
 *
 * 
 *   var renderer = new goog.ui.media.MediaRenderer();
 *   var control = new goog.ui.media.Media('hello world', renderer);
 *   var control.render(goog.dom.getElement('mediaHolder'));
 * 
* * 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: * *
    *
  • .goog-ui-media *
  • .goog-ui-media-hover *
  • .goog-ui-media-selected *
* * 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: * *
 *   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'));
 * 
* * 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.asserts'); goog.require('goog.dom.TagName'); 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} * @final */ 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) { goog.asserts.assertInstanceof(control, goog.ui.media.Media); var domHelper = control.getDomHelper(); var div = domHelper.createElement(goog.dom.TagName.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(goog.dom.TagName.DIV); caption.className = goog.getCssName(this.getCssClass(), 'caption'); caption.appendChild( domHelper.createDom( goog.dom.TagName.P, goog.getCssName(this.getCssClass(), 'caption-text'), dataModel.getCaption())); domHelper.appendChild(div, caption); } if (dataModel.getDescription()) { var description = domHelper.createElement(goog.dom.TagName.DIV); description.className = goog.getCssName(this.getCssClass(), 'description'); description.appendChild( domHelper.createDom( goog.dom.TagName.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(goog.dom.TagName.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(goog.dom.TagName.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'); } };




© 2015 - 2025 Weber Informatics LLC | Privacy Policy