# HG changeset patch # User hamidouk # Date 1329476364 -3600 # Node ID 8be7c3e9aae3a6e0e74502f3fa2e81c7bab529ed # Parent 1ed2c41e3aaead421e264dad09b4cc359771d336# Parent 7525046c6e7ae8856ffd8c4aa63e9ef1f007e094 Merge with upstream diff -r 7525046c6e7a -r 8be7c3e9aae3 src/ldt/ldt/static/ldt/css/LdtPlayer.css --- a/src/ldt/ldt/static/ldt/css/LdtPlayer.css Fri Feb 17 11:49:29 2012 +0100 +++ b/src/ldt/ldt/static/ldt/css/LdtPlayer.css Fri Feb 17 11:59:24 2012 +0100 @@ -164,12 +164,20 @@ } .Ldt-CtrlPlay { - background:url('imgs/play_sprite.png') no-repeat transparent ; + background-position: 0 0; width: 59px; height: 25px; } +.Ldt-CtrlPlay-PlayState { + background:url('imgs/play_sprite.png') no-repeat transparent ; +} + +.Ldt-CtrlPlay-PauseState { + background:url('imgs/pause_sprite.png') no-repeat transparent ; +} + .Ldt-CtrlPlay:hover { background-position: 0 -25px; } @@ -253,7 +261,6 @@ } .Ldt-CtrlSound { - background:url('imgs/sound_sprite.png') no-repeat scroll 0 0 transparent ; width: 33px; height: 25px; border-right: 1px solid #b6b8b8; @@ -261,6 +268,14 @@ border-left: none; } +.Ldt-CtrlSound-SoundState { + background:url('imgs/sound_sprite.png') no-repeat scroll 0 0 transparent ; +} + +.Ldt-CtrlSound-MuteState { + background:url('imgs/mute_sprite.png') no-repeat scroll 0 0 transparent ; +} + .Ldt-CtrlSound:hover { background-position: 0 -25px; } @@ -284,7 +299,7 @@ /* Arrow Widget */ .Ldt-arrowWidget { position: relative; - background:url('imgs/arrow.png') no-repeat scroll 0 0 transparent ; + height:16px; width:27px; margin-bottom: -3px; @@ -292,6 +307,18 @@ left: 0%; } +.Ldt-arrowLeftEdge { + background:url('imgs/left_edge_arrow.png') no-repeat scroll 0 0 transparent ; +} + +.Ldt-arrowCenter { + background:url('imgs/arrow.png') no-repeat scroll 0 0 transparent ; +} + +.Ldt-arrowRightEdge { + background:url('imgs/right_edge_arrow.png') no-repeat scroll 0 0 transparent ; +} + .cleaner { clear:both; } @@ -774,6 +801,31 @@ .Ldt-createAnnotation-polemic-question.Ldt-createAnnotation-polemic-active { background-position: -114px -52px; } + +.Ldt-createAnnotation-spinner { + display: inline; + width: 16px; + height: 16px; + background-image('imgs/spinner.gif'); +} + +.Ldt-createAnnotation-endScreen-TweetLink { + width: 54px; + height: 20px; + background-image('imgs/tweet_button.png'); +} + +.Ldt-createAnnotation-endScreen-FbLink { + width: 55px; + height: 20px; + background-image('imgs/facebook_button.png'); +} + +.Ldt-createAnnotation-endScreen-GplusLink { + width: 50px; + height: 20px; + background-image('imgs/gplus_button.png'); +} /* AnnotationsListWidget */ .Ldt-AnnotationsListWidget { @@ -807,7 +859,10 @@ .Ldt-AnnotationsList-Caption { float: left; display: table-cell; - vertical-align: middle; + vertical-align: middle; + height: 64px; + width: 64px; + background-image: url('imgs/video_sequence.png'); } .Ldt-AnnotationsList-Duration { diff -r 7525046c6e7a -r 8be7c3e9aae3 src/ldt/ldt/static/ldt/js/LdtPlayer-release.js --- a/src/ldt/ldt/static/ldt/js/LdtPlayer-release.js Fri Feb 17 11:49:29 2012 +0100 +++ b/src/ldt/ldt/static/ldt/js/LdtPlayer-release.js Fri Feb 17 11:59:24 2012 +0100 @@ -1085,24 +1085,23 @@ IriSP.__jsonMetadata = data; callback.call(window) }); }); -}; -IriSP.SparklineWidget_template = "
Loading
"; -IriSP.annotation_template = "{{! template for an annotation displayed in a segmentWidget }}
"; -IriSP.annotationWidget_template = "{{! template for the annotation widget }}
"; -IriSP.annotation_loading_template = "{{! template shown while the annotation widget is loading }}
 
Chargement...
"; -IriSP.annotationsListWidget_template = "{{! template for the annotation list widget }}
"; -IriSP.arrowWidget_template = "
"; -IriSP.createAnnotationWidget_template = "{{! template for the annotation creation widget }}
{{^cinecast_version}}
{{/cinecast_version}}
{{^user_avatar}} {{/user_avatar}} {{#user_avatar}} {{/user_avatar}}
Submit
Add keywords :
{{#polemic_mode}}
Add polemic keywords
{{/polemic_mode}}
"; -IriSP.createAnnotationWidget_festivalCinecast_template = "{{! template for the annotation creation widget specific for the cinecast festival}}
Add keywords :
Submit
"; -IriSP.createAnnotation_errorMessage_template = "

You must enter text to submit an annotation

"; -IriSP.overlay_marker_template = "{{! the template for the small bars which is z-indexed over our segment widget }}
"; -IriSP.player_template = "{{! template for the radio player }}
00:00
/
00:00
"; -IriSP.search_template = "{{! template for the search container }}
"; -IriSP.share_template = "{{! social network sharing template }}       "; -IriSP.sliceWidget_template = "{{! template for the slice widget }}
{{! the whole bar }}
{{! the zone which represents our slice }}
"; -IriSP.sliderWidget_template = "{{! template for the slider widget - it's composed of two divs we one overlayed on top of the other }}
"; -IriSP.tooltip_template = "{{! template used by the jquery ui tooltip }}
{{title}}
{{begin}} : {{end}}
{{description}}
"; -IriSP.tooltipWidget_template = "{{! template for the tooltip widget }}
"; +}; +IriSP.SparklineWidget_template = "
Loading
"; +IriSP.annotation_template = "{{! template for an annotation displayed in a segmentWidget }}
"; +IriSP.annotationWidget_template = "{{! template for the annotation widget }}
"; +IriSP.annotation_loading_template = "{{! template shown while the annotation widget is loading }}
 
Chargement...
"; +IriSP.annotationsListWidget_template = "{{! template for the annotation list widget }}
"; +IriSP.arrowWidget_template = "
"; +IriSP.createAnnotationWidget_template = "{{! template for the annotation creation widget }}
{{^cinecast_version}}
{{/cinecast_version}}
{{^user_avatar}} {{/user_avatar}} {{#user_avatar}} {{/user_avatar}}
Submit
Add keywords :
{{#polemic_mode}}
Add polemic keywords
{{/polemic_mode}}
"; +IriSP.createAnnotation_errorMessage_template = "

You must enter text to submit an annotation

"; +IriSP.overlay_marker_template = "{{! the template for the small bars which is z-indexed over our segment widget }}
"; +IriSP.player_template = "{{! template for the radio player }}
00:00
/
00:00
"; +IriSP.search_template = "{{! template for the search container }}
"; +IriSP.share_template = "{{! social network sharing template }} "; +IriSP.sliceWidget_template = "{{! template for the slice widget }}
{{! the whole bar }}
{{! the zone which represents our slice }}
"; +IriSP.sliderWidget_template = "{{! template for the slider widget - it's composed of two divs we one overlayed on top of the other }}
"; +IriSP.tooltip_template = "{{! template used by the jquery ui tooltip }}
{{title}}
{{begin}} : {{end}}
{{description}}
"; +IriSP.tooltipWidget_template = "{{! template for the tooltip widget }}
"; IriSP.tweetWidget_template = "{{! template for the tweet widget }}";/* utils.js - various utils that don't belong anywhere else */ /* trace function, for debugging */ @@ -1626,9 +1625,9 @@ IriSP.paths = {}; -IriSP.libdir = ""; -IriSP.jwplayer_swf_path = ""; -IriSP.platform_url = ""; +IriSP.libdir = "/mdp/src/js/libs/"; +IriSP.jwplayer_swf_path = "/mdp/test/libs/player.swf"; +IriSP.platform_url = "http://localhost/pf"; IriSP.default_templates_vars = { }; /** ugly ugly ugly ugly - returns an object defining @@ -1697,7 +1696,11 @@ Ldt-createAnnotation-polemic-equalequal for equalequal, etc. */ polemics: {"++" : "positive", "--" : "negative", "==" : "reference", "??" : "question"}, - cinecast_version: true /* put to false to enable the platform version, true for the festival cinecast one. */ + cinecast_version: true, /* put to false to enable the platform version, true for the festival cinecast one. */ + /* where does the widget PUT the annotations - this is a mustache template. id refers to the id of the media ans is filled + by the widget. + */ + api_endpoint_template: platform_url + "/ldtplatform/api/ldt/annotations/{{id}}.json" }, "SparklineWidget" : { column_width: 10 // the width of a column in pixels. @@ -1709,13 +1712,13 @@ ajax_mode: true, /* use ajax to get information about the annotations. if set to false, only search in the annotations for the current project. */ + /* the platform generates some funky urls. We replace them afterwards to point to the correct place - this setting will probably be overwritten by the platform implementers. Note that the player has to replace the variables between {{ and }} by its own values. */ ajax_url: platform_url + "/ldtplatform/api/ldt/segments/{media}/{begin}/{end}", - ajax_granularity: 10000, /* how much ms should we look before and after the current timecode */ @@ -1726,28 +1729,27 @@ }; }; +IriSP.defaults.paths = { +// "imgs": "/tweetlive/res/metadataplayer/src/css/imgs" + "imgs": "/mdp/src/css/imgs" +}; + +IriSP.defaults.default_templates_vars = function() { + return { + //"img_dir" : IriSP.paths.imgs + }; +} + /* Override this if you want to change the info the player receives about the user. It's typically overrided in server-side templates with user-specific data. */ -IriSP.defaults.user = function() { return { +IriSP.defaults.user = function() { + return { "name" : "Anonymous user", "avatar" : IriSP.paths.imgs + "/user_default_icon.png" - } -}; - - -IriSP.defaults.paths = { -// "imgs": "/tweetlive/res/metadataplayer/src/css/imgs" - "imgs": "" -}; - -IriSP.defaults.default_templates_vars = function() { - return { - "img_dir" : IriSP.paths.imgs - }; -} - + } +}; /* the widget classes and definitions */ /** @@ -1982,6 +1984,16 @@ opts.file = ""; opts.streamer = ""; var fullPath = IriSP.__jsonMetadata["medias"][0]["href"]; + + /* files can either use href or url to refer to the stream */ + if (IriSP.null_or_undefined(fullPath)) { + fullPath = IriSP.__jsonMetadata["medias"][0]["url"]; + } + + if (IriSP.null_or_undefined(fullPath)) { + console.log("no url or href field defined in the metadata."); + } + var pathSplit = fullPath.split('/'); for (var i = 0; i < pathSplit.length; i++) { @@ -2047,13 +2059,16 @@ 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 widgetConfig = guiOptions.widgets[index]; - var widget = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, widgetConfig); - + var widget = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, guiOptions.widgets[index], default_options); + ret_widgets.push(widget); }; @@ -2086,8 +2101,14 @@ @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) { +IriSP.instantiateWidget = function(popcornInstance, serialFactory, layoutManager, widgetConfig, defaultOptions) { + + if (IriSP.null_or_undefined(defaultOptions)) + defaultOptions = {}; + + widgetConfig = IriSP.underscore.defaults(widgetConfig, defaultOptions); var arr = IriSP.jQuery.extend({}, widgetConfig); @@ -2117,7 +2138,7 @@ var i = 0; for(i = 0; i < widgetConfig.requires.length; i++) { var widgetName = widgetConfig.requires[i]["type"]; - widget[widgetName] = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, widgetConfig.requires[i]); + widget[widgetName] = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, widgetConfig.requires[i], defaultOptions); } } @@ -2317,7 +2338,27 @@ }; IriSP.PopcornReplacement.jwplayer.prototype = new IriSP.PopcornReplacement.player("", {}); -/* mediafragment module */ +/* embed module - listens and relay hash changes to a parent window. */ + +IriSP.EmbedModule = function(Popcorn, config, Serializer) { + IriSP.Module.call(this, Popcorn, config, Serializer); + + window.addEventListener('message', IriSP.wrap(this, this.handleMessages), false); + this._Popcorn.listen("IriSP.Mediafragment.hashchange", IriSP.wrap(this, this.relayChanges)); +}; + +IriSP.EmbedModule.prototype = new IriSP.Module(); + +IriSP.EmbedModule.prototype.handleMessages = function(e) { + if (e.data.type === "hashchange") { + window.location.hash = e.data.value; + } +}; + +IriSP.EmbedModule.prototype.relayChanges = function(newHash) { + window.parent.postMessage({type: "hashchange", value: newHash}, "*"); + return; +};/* mediafragment module */ IriSP.MediaFragment = function(Popcorn, config, Serializer) { IriSP.Module.call(this, Popcorn, config, Serializer); @@ -2359,7 +2400,7 @@ this._serializer.sync(IriSP.wrap(this, function() { this.lookupAnnotation.call(this, annotationId); })); - } + } } }; @@ -2381,6 +2422,9 @@ } else { var ntime = time.toFixed(2); } + + // used to relay the new hash to the embedder + this._Popcorn.trigger("IriSP.Mediafragment.hashchange", "#t=" + ntime); splitArr = window.location.href.split( "#" ) history.replaceState( {}, "", splitArr[0] + "#t=" + ntime ); @@ -2395,10 +2439,15 @@ if ( !history.pushState ) { return false; } + + + // used to relay the new hash to the embedder + this._Popcorn.trigger("IriSP.Mediafragment.hashchange", "#id=" + annotationId); splitArr = window.location.href.split( "#" ) history.replaceState( {}, "", splitArr[0] + "#id=" + annotationId); - + + // reset the mutex afterwards to prevent the module from reacting to his own changes. window.setTimeout(function() { _this.mutex = false }, 50); }; @@ -2660,7 +2709,7 @@ IriSP.AnnotationsWidget.prototype.displayAnnotation = function(annotation) { var title = annotation.content.title; var description = annotation.content.description; - var keywords = "" // FIXME; + var keywords = ""; var begin = +annotation.begin / 1000; var end = +annotation.end / 1000; var duration = +this._serializer.currentMedia().meta["dc:duration"]; @@ -2838,15 +2887,15 @@ if (corrected_pixels <= 0) corrected_pixels = 0; - if (corrected_pixels <= 15) { - var left_edge_img_templ = IriSP.templToHTML("url('{{img_dir}}/left_edge_arrow.png')"); - this.selector.children(".Ldt-arrowWidget").css("background-image", left_edge_img_templ); + if (corrected_pixels <= 15) { + this.selector.children(".Ldt-arrowWidget").removeClass("Ldt-arrowLeftEdge Ldt-arrowCenter Ldt-arrowRightEdge") + .addClass("Ldt-arrowLeftEdge"); } else if (corrected_pixels >= totalWidth - 25) { - var right_edge_img_templ = IriSP.templToHTML("url('{{img_dir}}/right_edge_arrow.png')"); - this.selector.children(".Ldt-arrowWidget").css("background-image", right_edge_img_templ); + this.selector.children(".Ldt-arrowWidget").removeClass("Ldt-arrowLeftEdge Ldt-arrowCenter Ldt-arrowRightEdge") + .addClass("Ldt-arrowRightEdge"); } else { - var img_templ = IriSP.templToHTML("url('{{img_dir}}/arrow.png')"); - this.selector.children(".Ldt-arrowWidget").css("background-image", img_templ); + this.selector.children(".Ldt-arrowWidget").removeClass("Ldt-arrowLeftEdge Ldt-arrowCenter Ldt-arrowRightEdge") + .addClass("Ldt-arrowCenter"); } this.selector.children(".Ldt-arrowWidget").animate({"left" : corrected_pixels + "px"}); @@ -2872,6 +2921,8 @@ this.polemics = IriSP.widgetsDefaults["createAnnotationWidget"].polemics; this.cinecast_version = IriSP.widgetsDefaults["createAnnotationWidget"].cinecast_version; + this.api_endpoint_template = IriSP.widgetsDefaults["createAnnotationWidget"].api_endpoint_template; + this.ids = {}; /* a dictionnary linking buttons ids to keywords */ /* variables to save the current position of the slicer */ @@ -2905,6 +2956,9 @@ if (!this.cinecast_version) this.selector.hide(); + else { + this.showStartScreen(); + } // add the keywords. for (var i = 0; i < this.keywords.length; i++) { @@ -2963,17 +3017,17 @@ } _this.selector.find(".Ldt-createAnnotation-Description").val(newVal); - // we use a custom event because there's no simple way to test for a js - // change in a textfield. - _this.selector.find(".Ldt-createAnnotation-Description").trigger("js_mod"); + // also call our update function. _this.handleTextChanges(); } }(polemic)); } + // js_mod is a custom event because there's no simple way to test for a js + // change in a textfield. this.selector.find(".Ldt-createAnnotation-Description") - .bind("propertychange keyup input paste", IriSP.wrap(this, this.handleTextChanges)); + .bind("propertychange keyup input paste js_mod", IriSP.wrap(this, this.handleTextChanges)); /* the cinecast version of the player is supposed to pause when the user clicks on the button */ if (this.cinecast_version) { @@ -3052,7 +3106,7 @@ } else { this._Popcorn.trigger("IriSP.AnnotationsWidget.hide"); - this.showStartScreen(); + this.showStartScreen(); this.selector.show(); this._hidden = false; var currentTime = this._Popcorn.currentTime(); @@ -3133,8 +3187,19 @@ IriSP.createAnnotationWidget.prototype.showStartScreen = function() { this.selector.find(".Ldt-createAnnotation-DoubleBorder").children().hide(); this.selector.find(".Ldt-createAnnotation-startScreen").show(); - this.selector.find(".Ldt-createAnnotation-Description").val("Type your annotation here."); - + + var jqTextfield = this.selector.find(".Ldt-createAnnotation-Description"); // handle on the textfield. used for the closure + + /* test if the browser supports the placeholder attribute */ + if (!IriSP.null_or_undefined(jqTextfield.get(0).placeholder)) { + jqTextfield.attr("placeholder", "Type your annotation here."); + } else { + jqTextfield.val("Type your annotation here."); + jqTextfield.one("click", IriSP.wrap(this, function() { jqTextfield.val(""); })); + } + + + this._state = "startScreen"; }; @@ -3275,8 +3340,8 @@ var project_id = this._serializer._data.meta.id; //TODO: extract magic url - var url = Mustache.to_html("{{platf_url}}/ldtplatform/api/ldt/annotations/{{id}}.json", - {platf_url: IriSP.platform_url, id: project_id}); + var url = Mustache.to_html(this.api_endpoint_template, + {id: project_id}); IriSP.jQuery.ajax({ url: url, @@ -3420,21 +3485,13 @@ IriSP.PlayerWidget.prototype.playButtonUpdater = function() { var status = this._Popcorn.media.paused; - if ( status == true ){ + if ( status == true ){ + /* the background sprite is changed by adding/removing the correct classes */ this.selector.find(".Ldt-CtrlPlay").attr("title", "Play"); - - // we use templToHTML because it has some predefined - // vars like where to get the images - var templ = IriSP.templToHTML("url({{img_dir}}/play_sprite.png)"); - this.selector.find(".Ldt-CtrlPlay").css("background-image", templ); - + this.selector.find(".Ldt-CtrlPlay").removeClass("Ldt-CtrlPlay-PauseState").addClass("Ldt-CtrlPlay-PlayState"); } else { this.selector.find(".Ldt-CtrlPlay").attr("title", "Pause"); - - // we use templToHTML because it has some predefined - // vars like where to get the images - var templ = IriSP.templToHTML("url({{img_dir}}/pause_sprite.png)"); - this.selector.find(".Ldt-CtrlPlay").css("background-image", templ); + this.selector.find(".Ldt-CtrlPlay").removeClass("Ldt-CtrlPlay-PlayState").addClass("Ldt-CtrlPlay-PauseState"); } return; @@ -3464,19 +3521,10 @@ if ( status == true ){ this.selector.find(".Ldt-CtrlSound").attr("title", "Unmute"); - - // we use templToHTML because it has some predefined - // vars like where to get the images - var templ = IriSP.templToHTML("url({{img_dir}}/sound_sprite.png)"); - this.selector.find(".Ldt-CtrlSound").css("background-image", templ); - + this.selector.find(".Ldt-CtrlSound").removeClass("Ldt-CtrlSound-MuteState").addClass("Ldt-CtrlSound-SoundState"); } else { this.selector.find(".Ldt-CtrlSound").attr("title", "Mute"); - - // we use templToHTML because it has some predefined - // vars like where to get the images - var templ = IriSP.templToHTML("url({{img_dir}}/mute_sprite.png)"); - this.selector.find(".Ldt-CtrlSound").css("background-image", templ); + this.selector.find(".Ldt-CtrlSound").removeClass("Ldt-CtrlSound-SoundState").addClass("Ldt-CtrlSound-MuteState"); } return;