--- a/src/ldt/ldt/static/ldt/js/LdtPlayer-release.js Fri Jan 27 17:21:56 2012 +0100
+++ b/src/ldt/ldt/static/ldt/js/LdtPlayer-release.js Mon Jan 30 16:46:14 2012 +0100
@@ -1009,6 +1009,13 @@
__IriSP = IriSP;
}
+/* underscore comes bundled with the player and we need
+ it ASAP, so load it that way
+*/
+
+IriSP._ = window._.noConflict();
+IriSP.underscore = IriSP._;
+
IriSP.loadLibs = function( libs, config, metadata_url, callback ) {
// Localize jQuery variable
IriSP.jQuery = null;
@@ -1052,8 +1059,6 @@
$L.wait(function() {
IriSP.jQuery = window.jQuery.noConflict( true );
- IriSP._ = window._.noConflict();
- IriSP.underscore = IriSP._;
var css_link_jquery = IriSP.jQuery( "<link>", {
rel: "stylesheet",
@@ -1605,28 +1610,52 @@
};
/* site.js - all our site-dependent config : player chrome, cdn locations, etc...*/
+IriSP.defaults = {};
+
+/* these objects are filled by configureDefaults. The function doesn't overwrite
+ defaults that were originally defined by the user.
+*/
+IriSP.lib = {};
+
+/* We need to define those so that the individual settings can be overwritten */
+IriSP.widgetsDefaults = {};
+
+IriSP.paths = {};
+
IriSP.libdir = "/mdp/src/js/libs/";
IriSP.jwplayer_swf_path = "/mdp/test/libs/player.swf";
IriSP.platform_url = "http://localhost/pf";
-
-IriSP.lib = {
- jQuery : "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js",
- jQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.js",
- jQueryToolTip : "http://cdn.jquerytools.org/1.2.4/all/jquery.tools.min.js",
- swfObject : "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js",
- cssjQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css",
- popcorn : IriSP.libdir + "popcorn.js",
- jwplayer : IriSP.libdir + "jwplayer.js",
- popcornReplacement: IriSP.libdir + "pop.js",
- raphael: IriSP.libdir + "raphael.js",
- jquery_sparkline: IriSP.libdir + "jquery.sparkline.js",
- "popcorn.mediafragment" : IriSP.libdir + "popcorn.mediafragment.js",
- "popcorn.code" : IriSP.libdir + "popcorn.code.js",
- "popcorn.jwplayer": IriSP.libdir + "popcorn.jwplayer.js",
- "popcorn.youtube": IriSP.libdir + "popcorn.youtube.js"
+IriSP.default_templates_vars = { };
+
+/** ugly ugly ugly ugly - returns an object defining
+ the paths to the libs
+ We need it that way cause it's called at runtime by
+ IriSP.configureDefaults.
+*/
+IriSP.defaults.lib = function(libdir) {
+ if (IriSP.null_or_undefined(libdir))
+ libdir = IriSP.libdir;
+
+ return {
+ jQuery : "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js",
+ jQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.js",
+ jQueryToolTip : "http://cdn.jquerytools.org/1.2.4/all/jquery.tools.min.js",
+ swfObject : "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js",
+ cssjQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css",
+ popcorn : libdir + "popcorn.js",
+ jwplayer : libdir + "jwplayer.js",
+ popcornReplacement: libdir + "pop.js",
+ raphael: libdir + "raphael.js",
+ jquery_sparkline: libdir + "jquery.sparkline.js",
+ "popcorn.mediafragment" : libdir + "popcorn.mediafragment.js",
+ "popcorn.code" : libdir + "popcorn.code.js",
+ "popcorn.jwplayer": libdir + "popcorn.jwplayer.js",
+ "popcorn.youtube": libdir + "popcorn.youtube.js"
+ };
};
//Configuration for the player and utility functions.
+// No need to have them configured at runtime
IriSP.config = {};
IriSP.config.shortener = {
@@ -1634,63 +1663,73 @@
//shortening_function : IriSP.platform_shorten_url
};
-IriSP.widgetsDefaults = {
- "LayoutManager" : {spacer_div_height : "0px" },
- "PlayerWidget" : {},
- "AnnotationsWidget": {
- "share_text" : "I'm watching ",
- "fb_link" : "http://www.facebook.com/share.php?u=",
- "tw_link" : "http://twitter.com/home?status=",
- "gplus_link" : ""
+IriSP.defaults.widgetsDefaults = function(platform_url) {
+ if (IriSP.null_or_undefined(platform_url))
+ platform_url = IriSP.platform_url;
+
+ return {
+ "LayoutManager" : {spacer_div_height : "0px" },
+ "PlayerWidget" : {},
+ "AnnotationsWidget": {
+ "share_text" : "I'm watching ",
+ "fb_link" : "http://www.facebook.com/share.php?u=",
+ "tw_link" : "http://twitter.com/home?status=",
+ "gplus_link" : ""
+ },
+
+ "TweetsWidget" : {
+ default_profile_picture : "https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png",
+ tweet_display_period: 10000 // how long do we show a tweet ?
+
+ },
+ "SliderWidget" : {
+ minimize_period: 850 // how long does the slider stays maximized after the user leaves the zone ?
},
- "TweetsWidget" : {
- default_profile_picture : "https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png",
- tweet_display_period: 10000, // how long do we show a tweet ?
-
- },
- "SliderWidget" : {
- minimize_period: 850 // how long does the slider stays maximized after the user leaves the zone ?
- },
- "createAnnotationWidget" : {
- keywords: ["#faux-raccord", "#mot-clef"],
- polemic_mode: true, /* enable polemics ? */
- /* polemics - the corresponding class names defined in the css should be for instance :
- Ldt-createAnnotation-polemic-positive for positive
- Ldt-createAnnotation-polemic-reference for reference, etc.
- */
- polemics: {"++" : "positive", "--" : "negative", "==" : "reference", "??" : "question"},
- cinecast_version: true /* put to false to enable the platform version, true for the festival cinecast one. */
- },
- "SparklineWidget" : {
- column_width: 10 // the width of a column in pixels.
- },
- "Main" : {
- autoplay: true
- },
- "AnnotationsListWidget" : {
- ajax_mode: true, /* use ajax to get information about the annotations.
- if set to false, only search in the annotations for the
- current project. */
- ajax_url: IriSP.platform_url + "/ldtplatform/api/ldt/segments", /* partial
- url of
- where to
- get the
- ajax */
- ajax_granularity: 10000, /* how much ms should we look before and after the
- current timecode */
- project_url: IriSP.platform_url + "/ldtplatform/ldt/front/player/" /* the beginning
- of a link to the
- new front */
- },
+ "createAnnotationWidget" : {
+ keywords: ["#faux-raccord", "#mot-clef"],
+ polemic_mode: true, /* enable polemics ? */
+ /* polemics - the corresponding class names defined in the css should be for instance :
+ Ldt-createAnnotation-polemic-plusplus for plusplus
+ 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. */
+ },
+ "SparklineWidget" : {
+ column_width: 10 // the width of a column in pixels.
+ },
+ "Main" : {
+ autoplay: true
+ },
+ "AnnotationsListWidget" : {
+ ajax_mode: true, /* use ajax to get information about the annotations.
+ if set to false, only search in the annotations for the
+ current project. */
+ ajax_url: platform_url + "/ldtplatform/api/ldt/segments/", /* partial
+ url of
+ where to
+ get the
+ ajax */
+ ajax_granularity: 10000, /* how much ms should we look before and after the
+ current timecode */
+
+ project_url: platform_url + "/ldtplatform/ldt/front/player/" /* the beginning
+ of a link to the
+ new front */
+ }
+ };
};
-IriSP.paths = {
+IriSP.defaults.paths = {
// "imgs": "/tweetlive/res/metadataplayer/src/css/imgs"
"imgs": "/mdp/src/css/imgs"
};
-IriSP.default_templates_vars = {
+
+IriSP.defaults.default_templates_vars = function() {
+ return {
"img_dir" : IriSP.paths.imgs
-};
+ };
+}
/* ui.js - ui related functions */
@@ -2185,6 +2224,51 @@
serializer.sync(IriSP.wrap(widget, function() { this.draw(); }));
return widget;
};
+
+/** Go through the defaults to set a reasonable value */
+IriSP.configureDefaults = function(libdir, platform_url) {
+ /* the defaults configuration is messy and complicated. There are two things to know :
+ - we want to allow overwriting of defaults - that's why we have IriSP.widgetDefaults
+ and IriSP.defaults.widgetDefaults. The first is filled by the embedder and then fleshed out
+ with the contents of the first. We use underscore.defaults for that, but there's one problem with
+ this function : it doesn't work recursively.
+ - we need to compute some values at runtime instead of at compile time
+ */
+
+ IriSP.lib = IriSP.underscore.defaults(IriSP.lib, IriSP.defaults.lib(libdir));
+
+ /* get the factory defaults for the widgets and merge them with the default the user
+ may have defined
+ */
+ var factory_defaults = IriSP.defaults.widgetsDefaults(platform_url);
+ for(var widget in factory_defaults) {
+
+ /* create the object if it doesn't exists */
+ if (IriSP.null_or_undefined(IriSP.widgetsDefaults[widget]))
+ IriSP.widgetsDefaults[widget] = {};
+
+ IriSP.widgetsDefaults[widget] = IriSP.underscore.defaults(IriSP.widgetsDefaults[widget], factory_defaults[widget]);
+ }
+
+ IriSP.paths = IriSP.underscore.defaults(IriSP.paths, IriSP.defaults.paths);
+ IriSP.default_templates_vars = IriSP.underscore.defaults(IriSP.default_templates_vars,
+ IriSP.defaults.default_templates_vars());
+};
+
+/** single point of entry for the metadataplayer */
+IriSP.initPlayer = function(config, metadata_url, libdir, platform_url) {
+ IriSP.configureDefaults(libdir, platform_url);
+ IriSP.loadLibs(IriSP.lib, config, metadata_url,
+ function() {
+
+ var layoutManager = new IriSP.LayoutManager(config.gui);
+
+ var pop = IriSP.configurePopcorn(layoutManager, config.player);
+
+ var widgets = IriSP.configureWidgets(pop, layoutManager, config.gui);
+ var modules = IriSP.configureModules(pop, config.modules);
+ });
+};
/* To wrap a player the develop should create a new class derived from
the IriSP.PopcornReplacement.player and defining the correct functions */
@@ -2492,6 +2576,8 @@
this._Popcorn.listen("seeked", IriSP.wrap(this, this.ajaxRedraw));
this._Popcorn.listen("loadedmetadata", IriSP.wrap(this, this.ajaxRedraw));
this._Popcorn.listen("paused", IriSP.wrap(this, this.ajaxRedraw));
+
+ this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation", IriSP.wrap(this, this.ajaxRedraw));
}
};
@@ -3155,6 +3241,7 @@
this._Popcorn.listen("IriSP.search.matchFound", IriSP.wrap(this, this.searchMatch));
this._Popcorn.listen("IriSP.search.noMatchFound", IriSP.wrap(this, this.searchNoMatch));
+ this._Popcorn.listen("IriSP.search.triggeredSearch", IriSP.wrap(this, this.triggeredSearch));
this.selector.find(".Ldt-CtrlPlay").click(function() { self.playHandler.call(self); });
@@ -3271,47 +3358,59 @@
return;
};
-
+IriSP.PlayerWidget.prototype.showSearchBlock = function() {
+ var self = this;
+
+ if (this._searchBlockOpen == false) {
+ this.selector.find(".LdtSearch").show("blind", { direction: "horizontal"}, 100);
+ this.selector.find(".LdtSearchInput").css('background-color','#fff');
+
+ this._searchBlockOpen = true;
+ this.selector.find(".LdtSearchInput").bind('keyup', null, function() { self.searchHandler.call(self); } );
+ this.selector.find(".LdtSearchInput").focus();
+
+ // we need this variable because some widget can find a match in
+ // their data while at the same time other's don't. As we want the
+ // search field to become green when there's a match, we need a
+ // variable to remember that we had one.
+ this._positiveMatch = false;
+
+ // tell the world the field is open
+ this._Popcorn.trigger("IriSP.search.open");
+ }
+};
+
+IriSP.PlayerWidget.prototype.hideSearchBlock = function() {
+ if (this._searchBlockOpen == true) {
+ this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value');
+ this.selector.find(".LdtSearchInput").attr('value','');
+ this.selector.find(".LdtSearch").hide("blind", { direction: "horizontal"}, 75);
+
+ // unbind the watcher event.
+ this.selector.find(".LdtSearchInput").unbind('keypress set');
+ this._searchBlockOpen = false;
+
+ this._positiveMatch = false;
+
+ this._Popcorn.trigger("IriSP.search.closed");
+ }
+};
+
+/** react to clicks on the search button */
IriSP.PlayerWidget.prototype.searchButtonHandler = function() {
- var self = this;
-
- /* show the search field if it is not shown */
- if ( this._searchBlockOpen == false ) {
- this.selector.find(".LdtSearch").show("blind", { direction: "horizontal"}, 100);
-
- this.selector.find(".LdtSearchInput").css('background-color','#fff');
- this.selector.find(".LdtSearchInput").attr('value', this._searchLastValue);
- this._Popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural.
-
- this._searchBlockOpen = true;
- this.selector.find(".LdtSearchInput").bind('keyup', null, function() { self.searchHandler.call(self); } );
- this.selector.find(".LdtSearchInput").focus();
-
- // we need this variable because some widget can find a match in
- // their data while at the same time other's don't. As we want the
- // search field to become green when there's a match, we need a
- // variable to remember that we had one.
- this._positiveMatch = false;
-
- // tell the world the field is open
- this._Popcorn.trigger("IriSP.search.open");
-
+ var self = this;
+
+ /* show the search field if it is not shown */
+ if ( this._searchBlockOpen == false ) {
+ this.showSearchBlock();
+ this.selector.find(".LdtSearchInput").attr('value', this._searchLastValue);
+ this._Popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural.
} else {
- this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value');
- this.selector.find(".LdtSearchInput").attr('value','');
- this.selector.find(".LdtSearch").hide("blind", { direction: "horizontal"}, 75);
-
- // unbind the watcher event.
- this.selector.find(".LdtSearchInput").unbind('keypress set');
- this._searchBlockOpen = false;
-
- this._positiveMatch = false;
-
- this._Popcorn.trigger("IriSP.search.closed");
+ this.hideSearchBlock();
}
};
-/* this handler is called whenever the content of the search
+/** this handler is called whenever the content of the search
field changes */
IriSP.PlayerWidget.prototype.searchHandler = function() {
this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value');
@@ -3326,20 +3425,29 @@
}
};
-/*
+/**
handler for the IriSP.search.found message, which is sent by some views when they
highlight a match.
*/
IriSP.PlayerWidget.prototype.searchMatch = function() {
this._positiveMatch = true;
this.selector.find(".LdtSearchInput").css('background-color','#e1ffe1');
-}
-
-/* the same, except that no value could be found */
+};
+
+/** the same, except that no value could be found */
IriSP.PlayerWidget.prototype.searchNoMatch = function() {
if (this._positiveMatch !== true)
this.selector.find(".LdtSearchInput").css('background-color', "#d62e3a");
-}
+};
+
+/** react to an IriSP.Player.triggeredSearch - that is, when
+ a widget ask the PlayerWidget to do a search on his behalf */
+IriSP.PlayerWidget.prototype.triggeredSearch = function(searchString) {
+ this.showSearchBlock();
+ this.selector.find(".LdtSearchInput").attr('value', searchString);
+ this._Popcorn.trigger("IriSP.search", searchString); // trigger the search to make it more natural.
+};
+
/*
*
@@ -4177,20 +4285,29 @@
var time = this._Popcorn.currentTime();
var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000;
- var percent = ((time / duration) * 100).toFixed(2);
+ var percents = time / duration;
/* we do these complicated calculations to center exactly
the position Marker */
- var pixels_to_percents = 100 / this.selector.width(); /* how much is a pixel in percents */
+
+ var divWidth = this.selector.width();
+ var pixels = Math.floor(this.selector.width() * percents);
var positionMarker_width = this.positionMarker.width();
- var correction = (pixels_to_percents * positionMarker_width) / 2;
-
- var newPos = percent - correction;
+ var correction = (positionMarker_width / 2);
+
+ /* check that we don't leave the left side */
+ var newPos = pixels - correction;
if (newPos <= 0)
newPos = 0;
- this.sliderForeground.css("width", percent + "%");
- this.positionMarker.css("left", newPos + "%");
+ /* check that we don't leave the right side */
+ var rightEdgePos = pixels + 1 * correction;
+
+ if (rightEdgePos >= divWidth)
+ newPos = divWidth - 1 * correction - 1;
+
+ this.sliderForeground.css("width", pixels + "px");
+ this.positionMarker.css("left", newPos + "px");
};
@@ -4647,7 +4764,7 @@
var _stopwords = [
'aussi', 'and', 'avec', 'aux', 'car', 'cette', 'comme', 'dans', 'donc', 'des', 'elle', 'est',
'être', 'eux', 'fait', 'ici', 'ils', 'les', 'leur', 'leurs', 'mais', 'mes', 'même', 'mon', 'notre',
- 'nos', 'nous', 'ont', 'par', 'pas', 'peu', 'pour', 'que', 'qui', 'ses' ,'son', 'sont', 'sur',
+ 'non', 'nos', 'nous', 'ont', 'par', 'pas', 'peu', 'pour', 'que', 'qui', 'ses' ,'son', 'sont', 'sur',
'tes', 'très', 'the', 'ton', 'tous', 'tout', 'une', 'votre', 'vos', 'vous'
],
_regexpword = /[^\s\.&;,'"!\?\d\(\)\+\[\]\\\…\-«»:\/]{3,}/g,
@@ -4686,6 +4803,7 @@
var _max = _words[0].count,
_min = Math.min(_words[_words.length - 1].count, _max - 1),
_scale = 16 / Math.sqrt(_max - _min),
+ _this = this,
_html = '<ul>'
+ IriSP._(_words)
.chain()
@@ -4704,7 +4822,26 @@
this.selector
.addClass("Ldt-TagCloud")
.html(_html);
-
+ this.selector.find("li").click(function() {
+ var _txt = this.textContent.replace(/(^[\s]+|[\s]+$)/g,'');
+ _this._Popcorn.trigger("IriSP.search.triggeredSearch", _txt);
+ });
+ this._Popcorn.listen("IriSP.search", IriSP.wrap(this, function(searchString) {
+ var _rgxp = new RegExp("(" + searchString.replace(/(\W)/g,'\\$1') + ")","gi");
+ this.selector.find("li").each(function(_i, _e) {
+ _e.innerHTML = searchString.length ?
+ _e.textContent.replace(_rgxp,'<span class="Ldt-TagCloud-actif">$1</span>')
+ : _e.textContent;
+ });
+ }));
+ this._Popcorn.listen("IriSP.search.closed", IriSP.wrap(this, this.endsearch));
+ this._Popcorn.listen("IriSP.search.cleared", IriSP.wrap(this, this.endsearch));
+}
+
+IriSP.TagCloudWidget.prototype.endsearch = function() {
+ this.selector.find("li").each(function(_i, _e) {
+ _e.innerHTML = _e.textContent;
+ });
}
/* this widget displays a small tooltip */
IriSP.TooltipWidget = function(Popcorn, config, Serializer) {