src/js/init.js
changeset 944 8a6c9e3d0158
parent 863 dc5e0ea0093c
parent 941 1e64e46a954f
child 945 7d9f6fd6f904
--- a/src/js/init.js	Thu May 24 15:05:47 2012 +0200
+++ b/src/js/init.js	Thu Aug 30 13:16:33 2012 +0200
@@ -1,260 +1,382 @@
 /* init.js - initialization and configuration of Popcorn and the widgets
-exemple json configuration:
- 
- */
+*/
 
-/**
-    set up the IriSP.__dataloader instance - 
-    we need it because we have to get the metadata
-    about the video before that the widget have even
-    loaded.
-*/
-IriSP.setupDataLoader = function() {
-  /* we set it up separately because we need to
-     get data at the very beginning, for instance when
-     setting up the video */
-  IriSP.__dataloader = new IriSP.DataLoader();
-};
+if (typeof window.IriSP === "undefined") {
+    IriSP = {};
+}
+
+/* The Metadataplayer Object, single point of entry, replaces IriSP.init_player */
 
-/** do some magic to configure popcorn according to the options object passed.
-    Works for html5, jwplayer and youtube videos 
-*/
-IriSP.configurePopcorn = function (layoutManager, options) {
-    var pop;
-    var ret = layoutManager.createDiv(); 
-    var containerDiv = ret[0];
-    var spacerDiv = ret[1];
-    
-    /* insert one pixel of margin between the video and the first widget, using the 
-       spacer.
-    */
-    IriSP.jQuery("#" + spacerDiv).css("height", "1px");
-    
-    switch(options.type) {
-      /*
-        todo : dynamically create the div/video tag which
-        will contain the video.
-      */
-      case "html5":
-           var tmpId = Popcorn.guid("video"); 
-           IriSP.jQuery("#" + containerDiv).append("<video src='" + options.file + "' id='" + tmpId + "'></video>");
+IriSP.Metadataplayer = function(config) {
+    IriSP.log("IriSP.Metadataplayer constructor");
+    for (var key in IriSP.guiDefaults) {
+        if (IriSP.guiDefaults.hasOwnProperty(key) && !config.gui.hasOwnProperty(key)) {
+            config.gui[key] = IriSP.guiDefaults[key]
+        }
+    }
+    var _container = document.getElementById(config.gui.container);
+    _container.innerHTML = '<h3 class="Ldt-Loader">Loading... Chargement...</h3>';
+    this.sourceManager = new IriSP.Model.Directory();
+    this.config = config;
+    this.callbackQueue = [];
+    this.isLoaded = false;
+    this.loadLibs();
+}
+
+IriSP.Metadataplayer.prototype.toString = function() {
+    return 'Metadataplayer in #' + this.config.gui.container;
+}
+
+IriSP.Metadataplayer.prototype.deferCallback = function(_callback) {
+    var _this = this;
+    IriSP._.defer(function() {
+        _callback.call(_this);
+    });
+}
 
-           if (options.hasOwnProperty("width"))
-             IriSP.jQuery("#" + containerDiv).css("width", options.width);
-           
-           if (options.hasOwnProperty("height"))
-             IriSP.jQuery("#" + containerDiv).css("height", options.height);
+IriSP.Metadataplayer.prototype.handleCallbacks = function() {
+    this.isLoaded = true;
+    while (this.callbackQueue.length) {
+        this.deferCallback(this.callbackQueue.splice(0,1)[0]);
+    }
+}
 
-           pop = Popcorn("#" + tmpId);
-        break;
-        
-      case "jwplayer":
-          var opts = IriSP.jQuery.extend({}, options);
-          delete opts.container;
-          delete opts.type;
+IriSP.Metadataplayer.prototype.onLoad = function(_callback) {
+    if (this.isLoaded) {
+        this.deferCallback(_callback);
+    } else {
+        this.callbackQueue.push(_callback);
+    }
+}
 
-          
-          /* Try to guess options.file and options.streamer only if file and streamer
-             are not already defined in the configuration */
-          if (options.provider === "rtmp" && !opts.hasOwnProperty("file") && !opts.hasOwnProperty("streamer")) {
-            /* exit if we can't access the metadata */
-            if (typeof(IriSP.__jsonMetadata) === "undefined") {
-                break;
-            };
-
-            // the json format is totally illogical
-            //opts.streamer = IriSP.__jsonMetadata["medias"][0]["meta"]["item"]["value"];
-            //var source = IriSP.__jsonMetadata["medias"][0]["href"];
+IriSP.Metadataplayer.prototype.loadLibs = function() {
+    IriSP.log("IriSP.Metadataplayer.prototype.loadLibs");
+    var $L = $LAB
+        .script(IriSP.getLib("underscore"))
+        .script(IriSP.getLib("Mustache"))
+        .script(IriSP.getLib("jQuery"))
+        .script(IriSP.getLib("swfObject"));
+    
+    if (typeof JSON == "undefined") {
+        $L.script(IriSP.getLib("json"));
+    }
+    
+    $L.wait()
+        .script(IriSP.getLib("jQueryUI"));
 
-            // the source if a full url but jwplayer wants an url relative to the
-            // streamer url, so we've got to remove the common part.
-            //opts.file = source.slice(opts.streamer.length);
-            
-            /* sometimes we get served a file with a wrong path and streamer.
-               as a streamer is of the form rtmp://domain/path/ and the media is
-               the rest, we uglily do this :
-            */
-            opts.file = "";
-            opts.streamer = "";
-            var fullPath = IriSP.get_aliased(IriSP.__jsonMetadata["medias"][0], ["href","url"]);
-            
-            if (fullPath === null) {
-              console.log("no url or href field defined in the metadata.");
+    if (this.config.player.type === "jwplayer" || this.config.player.type === "auto") {
+        $L.script(IriSP.getLib("jwplayer"));
+    }
+    
+    if (this.config.player.type !== "jwplayer" && this.config.player.type !== "allocine" && this.config.player.type !== "dailymotion") {
+        $L.script(IriSP.getLib("popcorn"));
+    }
+
+    /* widget specific requirements */
+    for(var _i = 0; _i < this.config.gui.widgets.length; _i++) {
+        var _t = this.config.gui.widgets[_i].type;
+        if (typeof IriSP.widgetsRequirements[_t] !== "undefined" && typeof IriSP.widgetsRequirements[_t].requires !== "undefined" ) {
+            for (var _j = 0; _j < IriSP.widgetsRequirements[_t].requires.length; _j++) {
+                $L.script(IriSP.getLib(IriSP.widgetsRequirements[_t].requires[_j]));
             }
-            
-            var pathSplit = fullPath.split('/');
-            
-            for (var i = 0; i < pathSplit.length; i++) {
-              if (i < 4) {
-                 opts.streamer += pathSplit[i] + "/";
-              } else {
-                 opts.file += pathSplit[i];
-                 /* omit the last slash if we're on the last element */
-                 if (i < pathSplit.length - 1)
-                  opts.file += "/";
-              }
-            }            
-          } else {
-            /* other providers type, video for instance -
-               pass everything as is */
-          }
+        }
+    }
+    
+    var _this = this;
+    
+    $L.wait(function() {
+        _this.onLibsLoaded();
+    });
+}
 
-          if (!options.hasOwnProperty("flashplayer")) {
-            opts.flashplayer = IriSP.jwplayer_swf_path;
-          }
-
-          if (!options.hasOwnProperty("controlbar.position")) {
-            opts["controlbar.position"] = "none";
-          }
-
-          pop = new IriSP.PopcornReplacement.jwplayer("#" + containerDiv, opts);
-        break;
+IriSP.Metadataplayer.prototype.onLibsLoaded = function() {
+    IriSP.log("IriSP.Metadataplayer.prototype.onLibsLoaded");
+    if (typeof IriSP.jQuery === "undefined" && typeof window.jQuery !== "undefined") {
+        IriSP.jQuery = window.jQuery.noConflict();
+    }
+    if (typeof IriSP._ === "undefined" && typeof window._ !== "undefined") {
+        IriSP._ = window._;
+    }
+    IriSP.loadCss(IriSP.getLib("cssjQueryUI"));
+    IriSP.loadCss(this.config.gui.css);
+    
+    this.videoData = this.loadMetadata(this.config.player.metadata);
+    this.$ = IriSP.jQuery('#' + this.config.gui.container);
+    this.$.css({
+        "width": this.config.gui.width,
+        "clear": "both"
+    });
+    if (typeof this.config.gui.height !== "undefined") {
+        this.$.css("height", this.config.gui.height);
+    }
       
-      case "youtube":
-          var opts = IriSP.jQuery.extend({}, options);
-          delete opts.container;
-          opts.controls = 0;
-          opts.autostart = false;
-          templ = "width: {{width}}px; height: {{height}}px;";
-          var str = Mustache.to_html(templ, {width: opts.width, height: opts.height});    
-          // Popcorn.youtube wants us to specify the size of the player in the style attribute of its container div.
-          IriSP.jQuery("#" + containerDiv).attr("style", str);
-          
-          pop = Popcorn.youtube("#" + containerDiv, opts.video, opts);
-        break;
-      
-    case "dailymotion":
-        pop = new IriSP.PopcornReplacement.dailymotion("#" + containerDiv, options);
-        break;
-             
-      case "allocine":
-          /* pass the options as-is to the allocine player and let it handle everything */
-          pop = new IriSP.PopcornReplacement.allocine("#" + containerDiv, options);
-          break;
-          
-      default:
-        pop = undefined;
-    };
-    
-    return pop;
-};
+    var _this = this;
+    this.videoData.onLoad(function() {
+        _this.onVideoDataLoaded();
+    });
+}
 
-/** Configure the gui and instantiate the widgets passed as parameters
-    @param guiOptions the gui object as seen in the examples.
- */
-IriSP.configureWidgets = function (popcornInstance, layoutManager, guiOptions) {
- 
-  var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader);
-  var params = {width: guiOptions.width, height: guiOptions.height};
-
-  var default_options = guiOptions.default_options;
-  if (IriSP.null_or_undefined(default_options))
-    default_options = {};
-  
-  var ret_widgets = [];
-  var index;
-  for (index = 0; index < guiOptions.widgets.length; index++) {
-    var widget = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, guiOptions.widgets[index], default_options);
-   
-    ret_widgets.push(widget);
-  };
-
-  return ret_widgets;
-};
+IriSP.Metadataplayer.prototype.loadMetadata = function(_metadataInfo) {
+    if (typeof _metadataInfo.serializer === "undefined" && typeof _metadataInfo.format !== "undefined") {
+        _metadataInfo.serializer = IriSP.serializers[_metadataInfo.format];
+    }
+    if (typeof _metadataInfo.url === "undefined" && typeof _metadataInfo.src !== "undefined") {
+        _metadataInfo.url = _metadataInfo.src;
+    }
+    if (typeof _metadataInfo.url !== "undefined" && typeof _metadataInfo.serializer !== "undefined") {
+        return this.sourceManager.remoteSource(_metadataInfo);
+    } else {
+        return this.sourceManager.newLocalSource(_metadataInfo);
+    }
+}
 
-/** configure modules. @see configureWidgets */
-IriSP.configureModules = function (popcornInstance, modulesList) {
-  if (IriSP.null_or_undefined(modulesList))
-    return;
-  
-  var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader);
-  var ret_modules = [];
-  var index;
-  
-  for (index = 0; index < modulesList.length; index++) {    
-    var moduleConfig = modulesList[index];
+IriSP.Metadataplayer.prototype.onVideoDataLoaded = function() {
     
-    var serializer = serialFactory.getSerializer(moduleConfig.metadata);
-    var module = new IriSP[moduleConfig.type](popcornInstance, moduleConfig, serializer);    
-    ret_modules.push(module);
-  };
-
-  return ret_modules;
-};
-
-/** instantiate a widget - only called by configureWidgets, never by the user. Handles widget 
-    dependencies.
-    @param popcornInstance popcorn instance the widget will user
-    @param serialFactory serializer factory to instantiate the widget with
-    @param layoutManager layout manager
-    @param widgetConfig configuration options for the widget
-    @param defaultOptions a dictionnary with some options defined for every widget.
- */
-IriSP.instantiateWidget = function(popcornInstance, serialFactory, layoutManager, widgetConfig, defaultOptions) {
-
-    if (IriSP.null_or_undefined(defaultOptions)) {
-      defaultOptions = {};
+    /* Setting default media from metadata */
+   
+    if (typeof this.videoData !== "undefined") {
+        
+        var _media;
+        
+        if (typeof this.videoData.mainMedia !== "undefined") {
+            _media = this.videoData.getElement(this.videoData.mainMedia);
+        }
+        
+        if (this.config.player.type === "mashup" || this.config.player.type === "mashup-html") {
+            if (typeof _media === "undefined" || _media.elementType !== "mashup") {
+                var _mashups = this.videoData.getMashups();
+                if (_mashups.length) {
+                    _media = _mashups[0];
+                }
+            }
+        } else {
+            if (typeof _media === "undefined" || _media.elementType !== "media") {
+                var _medias = this.videoData.getMedias();
+                if (_medias.length) {
+                    _media = _medias[0];
+                }
+            }
+        }
+        
+        this.videoData.currentMedia = _media;
+        
+        /* Getting video URL from metadata if it's not in the player config options */
+        
+        if (typeof _media !== "undefined" && typeof _media.video !== "undefined" && typeof this.config.player.video === "undefined") {
+            this.config.player.video = _media.video;
+            if (typeof this.config.player.streamer == "undefined" && typeof _media.streamer !== "undefined") {
+                this.config.player.streamer = _media.streamer;
+            }
+        }
+        
     }
-    if (IriSP.null_or_undefined(widgetConfig)) {
-      return;
+    
+    if (typeof this.config.player.video === "string" && this.config.player.url_transform === "function") {
+        this.config.player.video = this.config.player.url_transform(this.config.player.video);
     }
     
-    widgetConfig = IriSP.underscore.defaults(widgetConfig, defaultOptions);
-
-    var arr = IriSP.jQuery.extend({}, widgetConfig);
-    
-    /* create a div for those widgets who didn't already specify a container; */
-    if (!arr.hasOwnProperty("container")) {
-      /* create div returns us a container for the widget and a spacer */    
-      var ret = layoutManager.createDiv(widgetConfig.type);        
-      var container = ret[0];
-      var spacer = ret[1];           
-      arr.container = container;
-      arr.spacer = spacer;
-      arr.layoutManager = layoutManager;
-    }
-    var serializer = serialFactory.getSerializer(widgetConfig.metadata);    
-    
-    if (typeof serializer == "undefined")   
-      debugger;
-    
-    // instantiate the object passed as a string
-    var widget = new IriSP[widgetConfig.type](popcornInstance, arr, serializer);    
+    var _pop,
+        _divs = this.layoutDivs("video",this.config.player.height || undefined),
+        containerDiv = _divs[0],
+        spacerDiv = _divs[1],
+        _this = this,
+        _types = {
+            "html5" : /\.(ogg|ogv|webm)$/,
+            "youtube" : /^(https?:\/\/)?(www\.)?youtube\.com/,
+            "vimeo" : /^(https?:\/\/)?(www\.)?vimeo\.com/,
+            "dailymotion" : /^(https?:\/\/)?(www\.)?dailymotion\.com/
+        };
     
-    if (widgetConfig.hasOwnProperty("requires")) {
-      // also create the widgets this one depends on.
-      // the dependency widget is available in the parent widget context as
-      // this.WidgetName (for instance, this.TipWidget);
-      
-      var i = 0;
-      for(i = 0; i < widgetConfig.requires.length; i++) {
-        var widgetName = widgetConfig.requires[i]["type"],
-            _configobj = IriSP.jQuery.extend({}, widgetConfig.requires[i]),
-            _div = document.createElement('div'),
-            _container = IriSP.guid(arr.container + '_' + widgetName + '_');
-        _configobj.container = _container;
-        _div.id = _container;
-        widget.selector.append(_div);
-        widget[widgetName] = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, _configobj, defaultOptions);
-      }
-    }       
-     
-    serializer.sync(IriSP.wrap(widget, function() { this.draw(); }));
-    return widget;
+    if (this.config.player.type === "auto") {
+        this.config.player.type = "jwplayer";
+        IriSP._(_types).each(function(_v, _k) {
+            if (_v.test(_this.config.player.video)) {
+                _this.config.player.type = _k
+            }
+        });
+    }
+
+    switch(this.config.player.type) {
+        case "html5":
+            var _tmpId = Popcorn.guid("video"),
+                _videoEl = IriSP.jQuery('<video>');
+            
+            _videoEl.attr({
+                "src" : this.config.player.video,
+                "id" : _tmpId
+            })
+
+            if(this.config.player.hasOwnProperty("width")) {
+                _videoEl.attr("width", this.config.player.width);
+            }
+            if(this.config.player.hasOwnProperty("height")) {
+                _videoEl.attr("height", this.config.player.height);
+            }
+            IriSP.jQuery("#" + containerDiv).append(_videoEl);
+            _pop = Popcorn("#" + _tmpId);
+            break;
+
+        case "html5-audio":
+            var _tmpId = Popcorn.guid("audio"),
+                _videoEl = IriSP.jQuery('<audio>');
+            
+            _videoEl.attr({
+                "src" : this.config.player.video,
+                "id" : _tmpId
+            })
+
+            if(this.config.player.hasOwnProperty("width")) {
+                _videoEl.attr("width", this.config.player.width);
+            }
+            if(this.config.player.hasOwnProperty("height")) {
+                _videoEl.attr("height", this.config.player.height);
+            }
+            IriSP.jQuery("#" + containerDiv).append(_videoEl);
+            _pop = Popcorn("#" + _tmpId);
+            break;
+
+        case "jwplayer":
+            var opts = IriSP.jQuery.extend({}, this.config.player);
+            delete opts.container;
+            delete opts.type;
+            if (typeof opts.streamer === "function") {
+                opts.streamer = opts.streamer(opts.video);
+            }
+            if (typeof opts.streamer === "string") {
+                opts.video = opts.video.replace(opts.streamer,"");
+            }
+            opts.file = opts.video;
+            delete opts.video;
+            delete opts.metadata;
+
+            if(!opts.hasOwnProperty("flashplayer")) {
+                opts.flashplayer = IriSP.getLib("jwPlayerSWF");
+            }
+
+            if(!opts.hasOwnProperty("controlbar.position")) {
+                opts["controlbar.position"] = "none";
+            }
+            _pop = new IriSP.PopcornReplacement.jwplayer("#" + containerDiv, opts);
+            break;
+
+        case "youtube":
+            // Popcorn.youtube wants us to specify the size of the player in the style attribute of its container div.
+            IriSP.jQuery("#" + containerDiv).css({
+                width : this.config.player.width + "px",
+                height : this.config.player.height + "px"
+            });
+            var _urlparts = this.config.player.video.split(/[?&]/),
+                _params = {};
+            for (var _j = 1; _j < _urlparts.length; _j++) {
+                var _ppart = _urlparts[_j].split('=');
+                _params[_ppart[0]] = decodeURIComponent(_ppart[1]);
+            }
+            _params.controls = 0;
+            _params.modestbranding = 1;
+            _url = _urlparts[0] + '?' + IriSP.jQuery.param(_params);
+            _pop = Popcorn.youtube("#" + containerDiv, _url);
+            break;
+
+        case "vimeo":
+            // Popcorn.vimeo wants us to specify the size of the player in the style attribute of its container div.
+            IriSP.jQuery("#" + containerDiv).css({
+                width : this.config.player.width + "px",
+                height : this.config.player.height + "px"
+            });
+            _pop = Popcorn.vimeo("#" + containerDiv, this.config.player.video);
+            break;
+            
+        case "dailymotion":
+            _pop = new IriSP.PopcornReplacement.dailymotion("#" + containerDiv, this.config.player);
+            break;
+
+        case "mashup":
+            _pop = new IriSP.PopcornReplacement.mashup("#" + containerDiv, this.config.player);
+            break;
+            
+        case "allocine":
+            _pop = new IriSP.PopcornReplacement.allocine("#" + containerDiv, this.config.player);
+            break;
+        
+        case "mashup-html":
+            _pop = new IriSP.PopcornReplacement.htmlMashup("#" + containerDiv, this.config.player, this.videoData);
+            break;
+        
+        default:
+            _pop = undefined;
+    };
+
+    this.popcorn = _pop;
+    
+    /* Now Loading Widgets */
+    
+    this.widgets = [];
+    var _this = this;
+    for(var i = 0; i < this.config.gui.widgets.length; i++) {
+        this.loadWidget(this.config.gui.widgets[i], function(_widget) {
+            _this.widgets.push(_widget)
+        });
+    };
+    this.$.find('.Ldt-Loader').detach();
+    this.handleCallbacks();
+}
+
+IriSP.Metadataplayer.prototype.loadWidget = function(_widgetConfig, _callback) {
+    /* Creating containers if needed */
+    if (typeof _widgetConfig.container === "undefined") {
+        var _divs = this.layoutDivs(_widgetConfig.type);
+        _widgetConfig.container = _divs[0];
+    }
+    
+    var _this = this;
+    
+    if (typeof IriSP.Widgets[_widgetConfig.type] !== "undefined") {
+        IriSP._.defer(function() {
+            _callback(new IriSP.Widgets[_widgetConfig.type](_this, _widgetConfig));
+        });
+    } else {
+        /* Loading Widget CSS */
+        if (typeof IriSP.widgetsRequirements[_widgetConfig.type] === "undefined" || typeof IriSP.widgetsRequirements[_widgetConfig.type].noCss === "undefined" || !IriSP.widgetsRequirements[_widgetConfig.type].noCss) {
+            IriSP.loadCss(IriSP.widgetsDir + '/' + _widgetConfig.type + '.css');
+        }
+        /* Loading Widget JS    */
+        $LAB.script(IriSP.widgetsDir + '/' + _widgetConfig.type + '.js').wait(function() {
+            _callback(new IriSP.Widgets[_widgetConfig.type](_this, _widgetConfig));
+        });
+    }
+}
+
+/** create a subdiv with an unique id, and a spacer div as well.
+    @param widgetName the name of the widget.
+    @return an array of the form [createdivId, spacerdivId].
+*/
+IriSP.Metadataplayer.prototype.layoutDivs = function(_name, _height) {
+    if (typeof(_name) === "undefined") {
+       _name = "";
+    }
+    var newDiv = IriSP._.uniqueId(this.config.gui.container + "_widget_" + _name + "_"),
+        spacerDiv = IriSP._.uniqueId("LdtPlayer_spacer_"),
+        divHtml = IriSP.jQuery('<div>')
+            .attr("id",newDiv)
+            .css({
+                width: this.config.gui.width + "px",
+                position: "relative",
+                clear: "both"
+            }),
+        spacerHtml = IriSP.jQuery('<div>')
+            .attr("id",spacerDiv)
+            .css({
+                width: this.config.gui.width + "px",
+                height: this.config.gui.spacer_div_height + "px",
+                position: "relative",
+                clear: "both"
+            });
+    if (typeof _height !== "undefined") {
+        divHtml.css("height", _height);
+    }
+            
+    this.$.append(divHtml);
+    this.$.append(spacerHtml);
+
+    return [newDiv, spacerDiv];
 };
-
-/** single point of entry for the metadataplayer */
-IriSP.initPlayer = function(config, metadata_url) {
-    document.getElementById(config.gui.container).innerHTML = IriSP.templToHTML(IriSP.loading_template, config.gui);
-    IriSP.loadLibs(config, metadata_url,
-      function() {   
-              
-              var layoutManager = new IriSP.LayoutManager(config.gui);
-
-              var pop = IriSP.configurePopcorn(layoutManager, config.player);
-              
-              IriSP._widgets = IriSP.configureWidgets(pop, layoutManager, config.gui); 
-              IriSP._modules = IriSP.configureModules(pop, config.modules); 
-              IriSP.jQuery('#Ldt-loader').detach();
-      });
-};
\ No newline at end of file