Big refactoring of widget files + started migration of segmentwidget new-model
authorveltr
Mon, 23 Apr 2012 19:11:08 +0200
branchnew-model
changeset 875 43629caa77bc
parent 874 38b65761a7d5
child 876 03967b6ada7c
Big refactoring of widget files + started migration of segmentwidget
.hgignore
sbin/build/client.xml
src/css/LdtPlayer-base.css
src/css/base.css
src/css/imgs/player-sprites.png
src/css/imgs/player_gradient.png
src/css/imgs/white_arrow_long.png
src/css/widgets/annotationsListWidget.css
src/css/widgets/playerWidget.css
src/css/widgets/sliderWidget.css
src/css/widgets/tooltipWidget.css
src/js/defaults.js
src/js/i18n.js
src/js/init.js
src/js/main.js
src/js/pop.js
src/js/serializers/CinecastSerializer.js
src/js/serializers/PlatformSerializer.js
src/js/utils.js
src/js/widgets.js
src/js/widgets/annotationsListWidget.js
src/js/widgets/helloWorldWidget.js
src/js/widgets/playerWidget.js
src/js/widgets/polemicWidget.js
src/js/widgets/sliderWidget.js
src/js/widgets/sparklineWidget.js
src/js/widgets/tooltipWidget.js
src/templates/annotationsListWidget.html
src/templates/player.html
src/templates/tooltipWidget.html
src/widgets/AnnotationsList.css
src/widgets/AnnotationsList.js
src/widgets/Controller.css
src/widgets/Controller.js
src/widgets/HelloWorld.css
src/widgets/HelloWorld.js
src/widgets/Polemic.css
src/widgets/Polemic.js
src/widgets/Segments.css
src/widgets/Segments.js
src/widgets/Slider.css
src/widgets/Slider.js
src/widgets/Sparkline.css
src/widgets/Sparkline.js
src/widgets/Tooltip.css
src/widgets/Tooltip.js
src/widgets/img/player-sprites.png
src/widgets/img/player_gradient.png
src/widgets/img/white_arrow_long.png
test/integration/polemic.htm
--- a/.hgignore	Fri Apr 20 19:13:11 2012 +0200
+++ b/.hgignore	Mon Apr 23 19:11:08 2012 +0200
@@ -10,4 +10,6 @@
 doc/jsdoc/*
 
 syntax: regexp
-^src/css/LdtPlayer-release\.css$
\ No newline at end of file
+^src/css/LdtPlayer-release\.css$
+syntax: regexp
+^build$
\ No newline at end of file
--- a/sbin/build/client.xml	Fri Apr 20 19:13:11 2012 +0200
+++ b/sbin/build/client.xml	Mon Apr 23 19:11:08 2012 +0200
@@ -37,21 +37,11 @@
             </sequential>
         </for>
     </target>
-    <target name="buildcss" description="Build the CSS Files">
-        <concat encoding="UTF-8" outputencoding="UTF-8" destfile="../../src/css/LdtPlayer-release.css">
-            <!-- Has to be with the images -->
-            <filelist dir="../../src/css/" files="base.css" />
-            <!-- widgets -->
-            <fileset dir="../../src/css/widgets" casesensitive="yes">
-                <include name="**/*.css"/>
-            </fileset>
-        </concat>
-    </target>
-    <target name="concatenate" description="Build the developer release file" depends="make_templates,buildcss">
-        <concat encoding="UTF-8" outputencoding="UTF-8" destfile="../../build/LdtPlayer-release.js">
+    <target name="concatenate" description="Build the developer release file" depends="make_templates">
+        <concat encoding="UTF-8" outputencoding="UTF-8" destfile="../../build/LdtPlayer-core.js">
             <filelist dir="../../src/js/" files="header.js" />
             <filelist dir="../../src/js/libs"
-            files="lab.js mustache.js underscore.js"/>
+            files="lab.js"/>
             <!-- required file before everything else -->
             <filelist dir="../../src/js" files="main.js" />
             <!-- templates -->
@@ -62,14 +52,6 @@
             <fileset dir="../../src/js/players" casesensitive="yes">
                 <include name="**/*.js"/>
             </fileset>
-            <!-- modules -->
-            <fileset dir="../../src/js/modules" casesensitive="yes">
-                <include name="**/*.js"/>
-            </fileset>
-            <!-- widgets -->
-            <fileset dir="../../src/js/widgets" casesensitive="yes">
-                <include name="**/*.js"/>
-            </fileset>
             <!-- serializers -->
             <fileset dir="../../src/js/serializers" casesensitive="yes">
                 <include name="**/*.js"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/css/LdtPlayer-base.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,2 @@
+/* Base classes */
+
--- a/src/css/base.css	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-/* Base classes */
-
Binary file src/css/imgs/player-sprites.png has changed
Binary file src/css/imgs/player_gradient.png has changed
Binary file src/css/imgs/white_arrow_long.png has changed
--- a/src/css/widgets/annotationsListWidget.css	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/* AnnotationsListWidget */
-
-.Ldt-AnnotationsListWidget {
-    font-family: "Open Sans", Helvetica, Arial, sans-serif;
-    border: 1px solid #b6b8b8;
-    overflow: auto;
-    max-height: 480px;
-}
-.Ldt-AnnotationsListWidget a {
-    text-decoration: none;
-}
-ul.Ldt-AnnotationsList-ul {
-    list-style: none;
-    padding: 2px;
-    margin: 0;
-}
-li.Ldt-AnnotationsList-li {
-    width: 100%;
-    clear: both;
-    margin: 2px 0;
-    padding: 2px 0;
-    min-height: 60px;
-}
-.Ldt-AnnotationsList-li:hover {
-    background-color: #e9e9e9;
-}
-.Ldt-AnnotationsList-highlight {
-    background: #F7268E;
-    color: #ffffff;
-}
-.Ldt-AnnotationsList-ThumbContainer {
-    float: left;
-    width: 80px;
-    height: 50px;
-    text-align: center;
-    margin: 2px 0;
-}
-.Ldt-AnnotationsList-Thumbnail {
-    border: none;
-    max-width: 100%;
-    max-height: 100%;
-    margin: 0 auto;
-}
-.Ldt-AnnotationsList-Duration {
-    color: #f7268e;
-    float: right;
-    text-align: right;
-    font-size: 12px;
-    margin: 2px;
-}
-h3.Ldt-AnnotationsList-Title {
-    color: #0068c4;
-    font-size: 13px;
-    margin: 2px 2px 0 82px;
-    font-weight: bold;
-}
-.Ldt-AnnotationsList-Title a {
-    color: #0068c4;
-}
-p.Ldt-AnnotationsList-Description {
-    margin: 2px 0 2px 82px;
-    font-size: 12px;
-    color: #666666;
-}
-ul.Ldt-AnnotationsList-Tags {
-    list-style: none;
-    padding: 0;
-    margin: 2px 0 0 82px;
-}
-li.Ldt-AnnotationsList-Tag-Li {
-    display: inline-block;
-    margin: 2px;
-    background: #0068c4;
-    color: #fff;
-    padding: 2px;
-    font-size: 12px;
-}
-li.Ldt-AnnotationsList-Tag-Li:hover {
-    background: #F7268E;
-}
--- a/src/css/widgets/playerWidget.css	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/* Player Widget */
-
-.Ldt-Ctrl {
-  font-size: 10px;
-  font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-  background:url('imgs/player_gradient.png') repeat-x transparent ;
-  height: 25px;
-  border: 1px solid #b6b8b8;
-  position: relative;
-}
-
-.Ldt-Ctrl-Left {
-  float:left;
-}
-
-.Ldt-Ctrl-Right {
-  float: right;
-}
-
-.Ldt-Ctrl-button {
-  float: left;
-  width: 30px; height: 25px;
-  background: url('imgs/player-sprites.png');
-  cursor: pointer;
-}
-
-.Ldt-Ctrl-spacer {
-    float: left; width: 1px; height: 25px; background: #b6b8b8;
-}
-
-.Ldt-Ctrl-Play {
-  margin: 0 15px;
-}
-
-.Ldt-Ctrl-Play-PlayState {
-  background-position: 0 0;
-}
-
-.Ldt-Ctrl-Play-PlayState:hover {
-  background-position: 0 -25px;
-}
-
-.Ldt-Ctrl-Play-PlayState:active {
-  background-position: 0 -50px;
-}
-
-.Ldt-Ctrl-Play-PauseState {
-  background-position: -30px 0;
-}
-
-.Ldt-Ctrl-Play-PauseState:hover {
-  background-position: -30px -25px;
-}
-
-.Ldt-Ctrl-Play-PauseState:active {
-  background-position: -30px -50px;
-}
-
-.Ldt-Ctrl-Annotate {
-  margin: 0 2px;
-  background-position: -60px 0;
-}
-
-.Ldt-Ctrl-Annotate:hover {
-  background-position: -60px -25px;
-}
-
-.Ldt-Ctrl-Annotate:active {
-  background-position: -60px -50px;
-}
-
-.Ldt-Ctrl-SearchBtn {
-  margin: 0 2px;
-  background-position: -90px 0;
-}
-
-.Ldt-Ctrl-SearchBtn:hover {
-  background-position: -90px -25px;
-}
-
-.Ldt-Ctrl-SearchBtn:active {
-  background-position: -90px -50px;
-}
-
-.Ldt-Ctrl-Search {
-  display: none;
-  width: 165px;
-  height: 25px;
-  border: 1px;
-  border-color: #CFCFCF;
-  float: left;
-  text-align: center;
-}
-
-.Ldt-Ctrl-Time {
-  float: left;
-  margin: 5px;
-  font-size: 12px;
-  font-family: Arial, Verdana, sans-serif;
-}
-
-.Ldt-Ctrl-Time-Elapsed {
-  float: left;
-  color: #4a4a4a;
-}
-
-.Ldt-Ctrl-Time-Separator {
-  margin: 0 4px;      
-  float: left;
-}
-
-.Ldt-Ctrl-Time-Total {
-  float: left;
-  color: #b2b2b2; 
-}
-
-.Ldt-Ctrl-Sound {
-  margin: 0 2px;
-}
-
-.Ldt-Ctrl-Sound-Full {
-  background-position: -120px 0;
-}
-
-.Ldt-Ctrl-Sound-Full:hover {
-  background-position: -120px -25px;
-}
-
-.Ldt-Ctrl-Sound-Full:active {
-  background-position: -120px -50px;
-}
-
-.Ldt-Ctrl-Sound-Mute {
-  background-position: -150px 0;
-}
-
-.Ldt-Ctrl-Sound-Mute:hover {
-  background-position: -150px -25px;
-}
-
-.Ldt-Ctrl-Sound-Mute:active {
-  background-position: -150px -50px;
-}
-
-.Ldt-Ctrl-Sound-Half {
-  background-position: -180px 0;
-}
-
-.Ldt-Ctrl-Sound-Half:hover {
-  background-position: -180px -25px;
-}
-
-.Ldt-Ctrl-Sound-Half:active {
-  background-position: -180px -50px;
-}
-
-.Ldt-Ctrl-Volume-Control {
-    display: none;
-  position: absolute;
-  background:url('imgs/player_gradient.png') repeat-x transparent ;
-  height: 25px;
-  width: 100px; top: 25px; right: -1px; z-index: 100;
-  padding: 0 2px;
-  border: 1px solid #b6b8b8;
-}
-
-.Ldt-Ctrl-Volume-Bar { 
-    height: 5px; margin: 9px 3px 0; background: #cccccc; border: 1px solid #999999; border-radius: 2px;
-}
-
-.Ldt-Ctrl-Volume-Control .ui-slider-handle {
-    width: 6px; height: 19px; background: #a8a8a8; border: 1px solid #999999; border-radius: 2px; top: -8px; margin-left: -4px;
-    cursor: pointer;
-}
-
-.Ldt-Ctrl-Volume-Control:hover .ui-slider-handle {
-     background: #F7268E;
-}
\ No newline at end of file
--- a/src/css/widgets/sliderWidget.css	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/* Slider Widget */
-
-.Ldt-Slider {
-    border: none; border-radius: 0; padding: 0; margin: 0; background: #B6B8B8;
-}
-
-.Ldt-Slider .ui-slider-handle {
-    border-radius: 8px; top: -2px; background: #fc00ff; border: 1px solid #ffffff;
-}
-
-.Ldt-Slider .ui-slider-range {
-    background: #747474;
-}
-
--- a/src/css/widgets/tooltipWidget.css	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/* ToolTip Widget */
-
-.Ldt-Tooltip {
-  position: absolute;
-  padding : 3px;
-  z-index: 10000000000;
-  max-width: 200px;
-  background: transparent url("imgs/white_arrow_long.png");
-  font-size: 12px;
-  height: 115px;
-  width: 180px;
-  padding: 15px 15px 20px;
-  color: black;
-  font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif";
-  overflow:hidden;
-}
-
-.Ldt-Tooltip-Color {
-    float: left; margin: 2px 4px 2px 0; width: 10px; height: 10px;
-}
-
-.Ldt-Tooltip img {
-    max-width: 140px; max-height: 70px; margin: 0 20px;
-}
-
--- a/src/js/defaults.js	Fri Apr 20 19:13:11 2012 +0200
+++ b/src/js/defaults.js	Mon Apr 23 19:11:08 2012 +0200
@@ -3,6 +3,8 @@
 IriSP.libFiles = {
     defaultDir : "js/libs/",
     inDefaultDir : {
+        underscore : "underscore.js",
+        Mustache : "mustache.js",
         jQuery : "jquery.min.js",
         jQueryUI : "jquery-ui.min.js",
         swfObject : "swfobject.js",
@@ -27,6 +29,8 @@
     useCdn : false
 }
 
+IriSP.widgetsDir = 'widgets';
+
 IriSP.guiDefaults = {
     width : 640,            
     container : 'LdtPlayer',
@@ -34,9 +38,6 @@
 }
 
 IriSP.widgetsDefaults = {
-    "PlayerWidget" : {
-        
-    },
     "AnnotationsWidget" : {
         "share_text" : "I'm watching "
     },
@@ -44,11 +45,6 @@
         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" : {
-        minimized_height : 4,
-        maximized_height : 10,
-        minimize_timeout : 1500 // time before minimizing slider after mouseout
-    },
     "SegmentsWidget" : {
         cinecast_version : false
     },
@@ -93,33 +89,6 @@
         api_endpoint_template : "", // platform_url + "/ldtplatform/api/ldt/annotations/{{id}}.json",
         api_method : "PUT"
     },
-    "SparklineWidget" : {
-       lineColor : "#7492b4",
-       fillColor : "#aeaeb8",
-       lineWidth : 2
-    },
-    "AnnotationsListWidget" : {
-        /* 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 : false,
-        /* URL when the annotations are to be reloaded from an LDT-like segment API
-         * e.g. http://ldt.iri.centrepompidou.fr/ldtplatform/api/ldt/segments/{{media}}/{{begin}}/{{end}}?callback=?
-         */
-        ajax_granularity : 300000, /* how much ms should we look before and after the current timecode */
-        default_thumbnail : "http://ldt.iri.centrepompidou.fr/static/site/ldt/css/imgs/video_sequence.png",
-        foreign_url : "",
-        /* URL when the annotation is not in the current project,
-         * e.g. http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/{{media}}/{{project}}/{{annotationType}}#id={{annotation}}
-         */
-        cinecast_version : false,
-        annotation_type : false,
-        refresh_interval : 0,
-        limit_count : 10,
-        newest_first : false
-    },
     "StackGraphWidget" : {
         defaultcolor : "#585858",
         tags : [
@@ -145,39 +114,5 @@
             }
         ],
         streamgraph : false
-    },
-    "PolemicWidget" : {
-        element_width : 5,
-        element_height : 5,
-        annotation_type : "tweet",
-        defaultcolor : "#585858",
-        foundcolor : "#fc00ff",
-        tags : [
-            {
-                "keywords" : [ "++" ],
-                "description" : "positif",
-                "color" : "#1D973D"
-            },
-            {
-                "keywords" : [ "--" ],
-                "description" : "negatif",
-                "color" : "#CE0A15"
-            },
-            {
-                "keywords" : [ "==" ],
-                "description" : "reference",
-                "color" : "#C5A62D"  
-            },
-            {
-                "keywords" : [ "??" ],
-                "description" : "question",
-                "color" : "#036AAE"
-            }
-        ],
-        requires : [
-            {
-                type: "TooltipWidget"
-            }
-        ]
     }
 }
\ No newline at end of file
--- a/src/js/i18n.js	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-IriSP.I18n = function() {
-    this.messages = {};
-    this.base_lang = 'en';
-}
-
-IriSP.I18n.prototype.getLanguage = function(lang) {
-    var _lang = (
-        typeof lang != "undefined"
-        ? lang
-        : (
-            typeof IriSP.language != "undefined"
-            ? IriSP.language
-            : this.base_lang
-        )
-    );
-    return (
-        typeof this.messages[_lang] == "object"
-        ? _lang
-        : (
-            typeof this.messages[this.base_lang] == "object"
-            ? this.base_lang
-            : null
-        )
-    )
-}
-
-IriSP.I18n.prototype.getMessages = function(lang) {
-    var _lang = this.getLanguage(lang);
-    return (
-        _lang != null
-        ? this.messages[_lang]
-        : {}
-    );
-}
-
-IriSP.I18n.prototype.getMessage = function(message, lang) {
-    var _msgs = this.getMessages(lang);
-    return (
-        typeof _msgs[message] != "undefined"
-        ? _msgs[message]
-        : message
-    )
-}
-
-IriSP.I18n.prototype.addMessage = function(lang, messagekey, messagevalue) {
-    if (typeof this.messages[lang] == "undefined") {
-        this.messages[lang] = {};
-    }
-    this.messages[lang][messagekey] = messagevalue;
-}
-
-IriSP.I18n.prototype.addMessages = function(messagesObj) {
-    var _this = this;
-    IriSP.underscore(messagesObj).each(function(_messages, _lang) {
-        IriSP.underscore(_messages).each(function(_value, _key) {
-            _this.addMessage(_lang, _key, _value);
-        })
-    });
-}
-
-IriSP.i18n = new IriSP.I18n();
-
-IriSP.i18n.addMessages({
-    "fr": {
-        "loading_wait": "Chargement en cours, veuillez patienter&hellip;"
-    },
-    "en": {
-        "loading_wait": "Loading, please wait&hellip;"
-    }
-})
--- a/src/js/init.js	Fri Apr 20 19:13:11 2012 +0200
+++ b/src/js/init.js	Mon Apr 23 19:11:08 2012 +0200
@@ -5,9 +5,13 @@
 /* The Metadataplayer Object, single point of entry, replaces IriSP.init_player */
 
 IriSP.Metadataplayer = function(config, video_metadata) {
-    IriSP._.defaults(config.gui, IriSP.guiDefaults);
+    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 = IriSP.templToHTML(IriSP.loading_template, config.gui);
+    _container.innerHTML = '<div class="Ldt-Loader">Loading... Chargement...</div>';
     this.video_metadata = video_metadata;
     this.sourceManager = new IriSP.Model.Directory();
     this.config = config;
@@ -21,7 +25,7 @@
 IriSP.Metadataplayer.prototype.loadLibs = function() {
     // Localize jQuery variable
     IriSP.jQuery = null;
-    var $L = $LAB.script(IriSP.getLib("jQuery")).script(IriSP.getLib("swfObject")).wait().script(IriSP.getLib("jQueryUI"));
+    var $L = $LAB.script(IriSP.getLib("underscore")).script(IriSP.getLib("Mustache")).script(IriSP.getLib("jQuery")).script(IriSP.getLib("swfObject")).wait().script(IriSP.getLib("jQueryUI"));
 
     if(this.config.player.type === "jwplayer" || this.config.player.type === "allocine" || this.config.player.type === "dailymotion") {
         // load our popcorn.js lookalike
@@ -40,7 +44,7 @@
 
     /* widget specific requirements */
     for(var _i = 0; _i < this.config.gui.widgets.length; _i++) {
-        if(this.config.gui.widgets[_i].type === "StackGraphWidget" || this.config.gui.widgets[_i].type === "SparklineWidget") {
+        if(this.config.gui.widgets[_i].type === "Sparkline") {
             $L.script(IriSP.getLib("raphael"));
         }
         if(this.config.gui.widgets[_i].type === "TraceWidget") {
@@ -52,26 +56,34 @@
     
     $L.wait(function() {
         IriSP.jQuery = window.jQuery.noConflict(true);
-
-        var css_link_jquery = IriSP.jQuery("<link>", {
-            rel : "stylesheet",
-            type : "text/css",
-            href : IriSP.getLib("cssjQueryUI")
-        });
-        var css_link_custom = IriSP.jQuery("<link>", {
-            rel : "stylesheet",
-            type : "text/css",
-            href : _this.config.gui.css
-        });
-
-        css_link_jquery.appendTo('head');
-        css_link_custom.appendTo('head');
+        IriSP._ = window._.noConflict();
+        
+        IriSP.loadCss(IriSP.getLib("cssjQueryUI"))
+        IriSP.loadCss(_this.config.gui.css);
         
         _this.onLibsLoaded();
         
     });
 }
 
+IriSP.Metadataplayer.prototype.onLibsLoaded = function() {
+    console.log('OnLibsLoaded');
+    this.videoData = this.loadMetadata(this.video_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);
+    }
+      
+    var _this = this;
+    this.videoData.onLoad(function() {
+        _this.onVideoDataLoaded();
+    });
+}
+
 IriSP.Metadataplayer.prototype.loadMetadata = function(_metadataInfo) {
     if (typeof _metadataInfo.serializer === "undefined" && typeof _metadataInfo.format !== "undefined") {
         _metadataInfo.serializer = IriSP.serializers[_metadataInfo.format];
@@ -86,23 +98,6 @@
     }
 }
 
-IriSP.Metadataplayer.prototype.onLibsLoaded = function() {
-    this.videoData = this.loadMetadata(this.video_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);
-    }
-      
-    var _this = this;
-    this.videoData.onLoad(function() {
-        _this.onVideoDataLoaded();
-    });
-}
-
 IriSP.Metadataplayer.prototype.onVideoDataLoaded = function() {
     if (typeof this.videoData !== "undefined" && typeof this.config.player.video === "undefined") {
         var _media = this.videoData.currentMedia;
@@ -117,15 +112,36 @@
     }
     this.configurePopcorn();
     this.widgets = [];
+    var _this = this;
     for(var i = 0; i < this.config.gui.widgets.length; i++) {
-        var _widget = this.config.gui.widgets[i];
-        if (typeof IriSP[_widget.type] !== "undefined") {
-            this.widgets.push(new IriSP[_widget.type](this, _widget));
-        } else {
-            console.log("Error, Call to Undefined Widget Type : "+_widget.type);
-        }
+        this.loadWidget(this.config.gui.widgets[i], function(_widget) {
+            _this.widgets.push(_widget)
+        });
     };
-    this.$.find('.Ldt-loader').detach();
+    this.$.find('.Ldt-Loader').detach();
+}
+
+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   */
+        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));
+        });
+    }
 }
 
 IriSP.Metadataplayer.prototype.configurePopcorn = function() {
--- a/src/js/main.js	Fri Apr 20 19:13:11 2012 +0200
+++ b/src/js/main.js	Mon Apr 23 19:11:08 2012 +0200
@@ -12,25 +12,3 @@
     __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.getLib = function(lib) {
-    return (
-        IriSP.libFiles.useCdn && typeof IriSP.libFiles.cdn[lib] == "string"
-        ? IriSP.libFiles.cdn[lib]
-        : (
-            typeof IriSP.libFiles.locations[lib] == "string"
-            ? IriSP.libFiles.locations[lib]
-            : (
-                typeof IriSP.libFiles.inDefaultDir[lib] == "string"
-                ? IriSP.libFiles.defaultDir + IriSP.libFiles.inDefaultDir[lib]
-                : null
-            )
-        )
-    )
-}
--- a/src/js/pop.js	Fri Apr 20 19:13:11 2012 +0200
+++ b/src/js/pop.js	Mon Apr 23 19:11:08 2012 +0200
@@ -9,7 +9,9 @@
 IriSP.PopcornReplacement.player = function(container, options) {
   /* the jwplayer calls the callbacks in the global space so we need to 
      preserve them this way */
-    var _this = this;
+  if (typeof IriSP._ === "undefined") {
+      return;
+  }
     
   this.callbacks = {
       onReady:  IriSP._.bind(this.__initApi, this),
--- a/src/js/serializers/CinecastSerializer.js	Fri Apr 20 19:13:11 2012 +0200
+++ b/src/js/serializers/CinecastSerializer.js	Mon Apr 23 19:11:08 2012 +0200
@@ -70,11 +70,6 @@
                 _res.title = _data.meta.creator_name;
                 _res.description = _data.content.data;
                 _res.created = IriSP.Model.isoToDate(_data.meta.created);
-                var _c = parseInt(_data.color).toString(16);
-                while (_c.length < 6) {
-                    _c = '0' + _c;
-                }
-                _res.color = '#' + _c;
                 _res.setMedia(_data.media, _source);
                 _res.setAnnotationType(_data.type);
                 _res.setTags(IriSP._(_data.tags).map(function(_t) {
--- a/src/js/serializers/PlatformSerializer.js	Fri Apr 20 19:13:11 2012 +0200
+++ b/src/js/serializers/PlatformSerializer.js	Mon Apr 23 19:11:08 2012 +0200
@@ -80,11 +80,13 @@
                 _res.title = _data.content.title || "";
                 _res.description = _data.content.description || "";
                 _res.created = IriSP.Model.isoToDate(_data.meta["dc:created"]);
-                var _c = parseInt(_data.color).toString(16);
-                while (_c.length < 6) {
-                    _c = '0' + _c;
+                if (typeof _data.color !== "undefined") {
+                    var _c = parseInt(_data.color).toString(16);
+                    while (_c.length < 6) {
+                        _c = '0' + _c;
+                    }
+                    _res.color = '#' + _c;
                 }
-                _res.color = '#' + _c;
                 _res.setMedia(_data.media, _source);
                 _res.setAnnotationType(_data.meta["id-ref"]);
                 _res.setTags(IriSP._(_data.tags).pluck("id-ref"));
--- a/src/js/utils.js	Fri Apr 20 19:13:11 2012 +0200
+++ b/src/js/utils.js	Mon Apr 23 19:11:08 2012 +0200
@@ -1,5 +1,26 @@
 /* utils.js - various utils that don't belong anywhere else */
 
+IriSP.getLib = function(lib) {
+    if (IriSP.libFiles.useCdn && typeof IriSP.libFiles.cdn[lib] == "string") {
+        return IriSP.libFiles.cdn[lib];
+    }
+    if (typeof IriSP.libFiles.locations[lib] == "string") {
+        return IriSP.libFiles.locations[lib];
+    }
+    if (typeof IriSP.libFiles.inDefaultDir[lib] == "string") {
+        return IriSP.libFiles.defaultDir + IriSP.libFiles.inDefaultDir[lib];
+    }
+}
+
+IriSP.loadCss = function(_cssFile) {
+    IriSP.jQuery("<link>", {
+        rel : "stylesheet",
+        type : "text/css",
+        href : _cssFile
+    }).appendTo('head');
+}
+
+/*
 IriSP.padWithZeros = function(num) {
   if (Math.abs(num) < 10) {
     return "0" + num.toString();
@@ -10,7 +31,7 @@
 
 /* convert a number of milliseconds to a tuple of the form 
    [hours, minutes, seconds]
-*/
+
 IriSP.msToTime = function(ms) {
   return IriSP.secondsToTime(ms / 1000);
 }
@@ -38,7 +59,7 @@
   
   return tweet;
 };
-
+/*
 IriSP.countProperties = function(obj) {
     var count = 0;
 
@@ -62,9 +83,9 @@
   return zeroes + str;
 };
 
-/* shortcut to have global variables in templates */
+/* shortcut to have global variables in templates
 IriSP.templToHTML = function(template, values) {
-  var params = IriSP.underscore.extend(
+  var params = IriSP._.extend(
       {
           "l10n" : IriSP.i18n.getMessages()
       },
--- a/src/js/widgets.js	Fri Apr 20 19:13:11 2012 +0200
+++ b/src/js/widgets.js	Mon Apr 23 19:11:08 2012 +0200
@@ -1,4 +1,8 @@
-/* the widget classes and definitions */
+/* Definition of an ancestor for the Widget classes */
+
+if (typeof IriSP.Widgets === "undefined") {
+    IriSP.Widgets = {}
+}
 
 /**
  * @class IriSP.Widget is an "abstract" class. It's mostly used to define some properties common to every widget.
@@ -10,7 +14,9 @@
  * @param player - a reference to the player widget
  * @param config - configuration options for the widget
  */
-IriSP.Widget = function(player, config) {
+
+
+IriSP.Widgets.Widget = function(player, config) {
 
     if( typeof player === "undefined") {
         /* Probably an abstract call of the class when
@@ -20,16 +26,9 @@
     
     /* Setting all the configuration options */
     var _type = config.type,
-        _config = IriSP._.defaults({}, config, player.config.gui.default_options, IriSP.widgetsDefaults[_type]),
+        _config = IriSP._.defaults({}, config, player.config.gui.default_options, this.defaults),
         _this = this;
     
-    /* Creating containers if needed */
-    if (typeof _config.container === "undefined") {
-        var _divs = player.layoutDivs(_type);
-        _config.container = _divs[0];
-        _config.spacer = _divs[1];
-    }
-    
     IriSP._(_config).forEach(function(_value, _key) {
        _this[_key] = _value;
     });
@@ -52,28 +51,40 @@
     });
    
     /* Adding classes and html attributes */
-    console.log(this.container);
     this.$ = IriSP.jQuery('#' + this.container);
-    this.$.addClass("Ldt-TraceMe").addClass("Ldt-Widget").attr("widget-type", _type);
+    this.$.addClass("Ldt-TraceMe Ldt-Widget").attr("widget-type", _type);
     
     /* Does the widget require other widgets ? */
     if (typeof this.requires !== "undefined") {
         for (var _i = 0; _i < this.requires.length; _i++) {
             var _subconfig = this.requires[_i];
-            if (typeof IriSP[_subconfig.type] !== "undefined") {
-                _subconfig.container = IriSP._.uniqueId(this.container + '_' + _subconfig.type + '_');
-                this.$.append(IriSP.jQuery('<div>').attr("id",_subconfig.container));
-                console.log(this.$.html());
-                this[_subconfig.type] = new IriSP[_subconfig.type](player, _subconfig);
-            } else {
-                console.log("Error, Call to Undefined Widget Type : "+_subconfig.type);
-            }
+            _subconfig.container = IriSP._.uniqueId(this.container + '_' + _subconfig.type + '_');
+            this.$.append(IriSP.jQuery('<div>').attr("id",_subconfig.container));
+            this.player.loadWidget(_subconfig, function(_widget) {
+                _this[_subconfig.type.replace(/^./,function(_s){return _s.toLowerCase();})] = _widget
+            });
         }
     }
     
+    this.l10n = (typeof this.messages[IriSP.language] !== "undefined" ? this.messages[IriSP.language] : this.messages["en"]);
+    
 };
 
-IriSP.Widget.prototype.functionWrapper = function(_name) {
+IriSP.Widgets.Widget.prototype.defaults = {}
+
+IriSP.Widgets.Widget.prototype.template = '';
+
+IriSP.Widgets.Widget.prototype.messages = {"en":{}};
+
+IriSP.Widgets.Widget.prototype.templateToHtml = function(_template) {
+    return Mustache.to_html(_template, this);
+}
+
+IriSP.Widgets.Widget.prototype.renderTemplate = function() {
+    this.$.append(this.templateToHtml(this.template));
+}
+
+IriSP.Widgets.Widget.prototype.functionWrapper = function(_name) {
     var _this = this,
         _function = this[_name];
     if (typeof _function !== "undefined") {
@@ -85,19 +96,19 @@
     }
 }
 
-IriSP.Widget.prototype.bindPopcorn = function(_popcornEvent, _functionName) {
+IriSP.Widgets.Widget.prototype.bindPopcorn = function(_popcornEvent, _functionName) {
     this.player.popcorn.listen(_popcornEvent, this.functionWrapper(_functionName))
 }
 
 /**
  * This method responsible of drawing a widget on screen.
  */
-IriSP.Widget.prototype.draw = function() {
+IriSP.Widgets.Widget.prototype.draw = function() {
     /* implemented by "sub-classes" */
 };
 /**
  * Optional method if you want your widget to support redraws.
  */
-IriSP.Widget.prototype.redraw = function() {
+IriSP.Widgets.Widget.prototype.redraw = function() {
     /* implemented by "sub-classes" */
 };
--- a/src/js/widgets/annotationsListWidget.js	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-IriSP.AnnotationsListWidget = function(player, config) {
-    IriSP.Widget.call(this, player, config);
-    this.bindPopcorn("IriSP.search", "searchHandler");
-    this.bindPopcorn("IriSP.search.closed", "searchHandler");
-    this.bindPopcorn("IriSP.search.cleared", "searchHandler");
-    this.searchString = false;
-    this.lastIds = [];
-    var _this = this;
-    this.throttledRefresh = IriSP._.throttle(function() {
-        _this.refresh(false);
-    }, 1500);
-};
-
-IriSP.AnnotationsListWidget.prototype = new IriSP.Widget();
-
-IriSP.AnnotationsListWidget.prototype.clear = function() {
-};
-
-IriSP.AnnotationsListWidget.prototype.clearWidget = function() {
-};
-
-IriSP.AnnotationsListWidget.prototype.searchHandler = function(searchString) {
-    this.searchString = typeof searchString !== "undefined" ? searchString : '';
-    var _n = this.refresh(true);
-    if (this.searchString) {
-        if (_n) {
-            this.player.popcorn.trigger("IriSP.search.matchFound");
-        } else {
-            this.player.popcorn.trigger("IriSP.search.noMatchFound");
-        }
-    }
-}
-
-//obj.url = this.project_url + "/" + media + "/" + annotations[i].meta.project + "/" + annotations[i].meta["id-ref"] + '#id=' + annotations[i].id;
-
-IriSP.AnnotationsListWidget.prototype.ajaxSource = function() {
-    var _currentTime = this.player.popcorn.currentTime(),
-        _duration = this.source.getDuration();
-    if (typeof _currentTime == "undefined") {
-        _currentTime = 0;
-    }
-    this.lastAjaxQuery = _currentTime;
-    _currentTime = Math.floor(1000 * _currentTime);
-    var _url = Mustache.to_html(this.ajax_url, {
-        media : this.source.currentMedia.namespacedId.name,
-        begin : Math.max(0, _currentTime - this.ajax_granularity),
-        end : Math.min(_duration.milliseconds, _currentTime + this.ajax_granularity)
-    });
-    this.currentSource = this.player.loadMetadata(IriSP._.defaults({
-        "url" : _url
-    }, this.metadata));
-}
-
-IriSP.AnnotationsListWidget.prototype.refresh = function(_forceRedraw) {
-    _forceRedraw = (typeof _forceRedraw !== "undefined" && _forceRedraw);
-    if (this.currentSource.status !== IriSP.Model._SOURCE_STATUS_READY) {
-        return 0;
-    }
-    var _this = this,
-        _currentTime = this.player.popcorn.currentTime();
-    if (typeof _currentTime == "undefined") {
-        _currentTime = 0;
-    }
-    var _list = this.annotation_type ? this.currentSource.getAnnotationsByTypeTitle(this.annotation_type, true) : this.currentSource.getAnnotations();
-    if (this.searchString) {
-        _list = _list.searchByTextFields(this.searchString);
-    }
-    if (this.limit_count) {
-        _list = _list.sortBy(function(_annotation) {
-            return Math.abs(_annotation.begin.getSeconds() - _currentTime);
-        }).slice(0, this.limit_count)
-    }
-    if (this.newest_first) {
-        _list = _list.sortBy(function(_annotation) {
-            return -_annotation.created.valueOf();
-        });
-    } else {
-        _list = _list.sortBy(function(_annotation) {
-            return _annotation.begin;
-        });
-    }
-    
-    var _ids = _list.idIndex;
-    
-    if (_forceRedraw || !IriSP._.isEqual(_ids, this.lastIds)) {
-        /* This part only gets executed if the list needs updating */
-        this.lastIds = _ids;
-       
-        var _html = IriSP.templToHTML(
-            IriSP.annotationsListWidget_template,
-            {
-                annotations : _list.map(function(_annotation) {
-                    var _url = (
-                        ( typeof _annotation.url !== "undefined" )
-                        ? _annotation.url
-                        : (
-                            ( typeof _this.source.projectId !== "undefined" && typeof _annotation.project !== "undefined" && _this.source.projectId !== _annotation.project )
-                            ? Mustache.to_html(
-                                this.foreign_url,
-                                {
-                                    project : _annotation.project,
-                                    media : _annotation.media.id.replace(/^.*:/,''),
-                                    annotation : _annotation.namespacedId.name,
-                                    annotationType : _annotation.annotationType.id.replace(/^.*:/,'')
-                                }
-                            )
-                            : '#id=' + _annotation.namespacedId.name
-                            )
-                    );
-                    var _res = {
-                        id : _annotation.id,
-                        title : _annotation.title.replace(_annotation.description,''),
-                        description : _annotation.description,
-                        begin : _annotation.begin.toString(),
-                        end : _annotation.end.toString(),
-                        thumbnail : typeof _annotation.thumbnail !== "undefined" ? _annotation.thumbnail : _this.default_thumbnail,
-                        url : _url,
-                        tags : _annotation.getTagTexts()
-                    }
-                    return _res;
-                })
-            });
-    
-        this.$.html(_html);
-    
-        this.$.find('.Ldt-AnnotationsList-Tag-Li').click(function() {
-            _this.player.popcorn.trigger("IriSP.search.triggeredSearch", IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,''));
-        })
-        
-        if(this.searchString) {
-            var _searchRe = new RegExp('(' + this.searchString.replace(/(\W)/gm,'\\$1') + ')','gim');
-            this.$.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description").each(function() {
-                var _$ = IriSP.jQuery(this);
-                _$.html(_$.text().replace(/(^\s+|\s+$)/g,'').replace(_searchRe, '<span class="Ldt-AnnotationsList-highlight">$1</span>'))
-            })
-        }
-    }
-    
-    if (this.ajax_url && this.ajax_granularity) {
-        if (Math.abs(_currentTime - this.lastAjaxQuery) > (this.ajax_granularity / 2000)) {
-            this.ajaxSource();
-        }
-    }
-    return _list.length;
-}
-
-IriSP.AnnotationsListWidget.prototype.draw = function() {
-    var _this = this;
-    
-    if (this.ajax_url && this.ajax_granularity) {
-        this.ajaxSource();
-    } else {
-        this.currentSource = this.source;
-    }
-    
-    if (this.refresh_interval) {
-        window.setInterval(function() {
-            _this.currentSource.get()
-        }, this.refresh_interval);
-    }
-    
-    var _events = [
-        "IriSP.createAnnotationWidget.addedAnnotation",
-        "timeupdate",
-        "seeked",
-        "loadedmetadata"
-    ];
-    for (var _i = 0; _i < _events.length; _i++) {
-        this.player.popcorn.listen(_events[_i], this.throttledRefresh);
-    }
-    
-    this.throttledRefresh();
-
-};
--- a/src/js/widgets/helloWorldWidget.js	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-IriSP.i18n.addMessages({
-    "fr": {
-        "Hello" : "Bonjour,"
-    },
-    "en" : {
-        "Hello" : "Hello,"
-    }
-})
-
-IriSP.HelloWorldWidget = function(player, config) {
-    console.log("Calling IriSP.Widget's constructor from IriSP.HelloWorldWidget");
-    IriSP.Widget.call(this, player, config);
-    if (typeof this.text == "undefined") {
-        this.text = 'world'
-    }
-}
-
-IriSP.HelloWorldWidget.prototype = new IriSP.Widget();
-
-IriSP.HelloWorldWidget.prototype.draw = function() {
-    var _tmpl = '<p>{{l10n.Hello}} {{text}}</p><p>Looks like we have {{source.contents.annotation.length}} annotations in this feed</p>'
-        _html = IriSP.templToHTML(_tmpl, this);
-    this.$.append(_html);
-    this.$.find('p').css({
-        "text-align" : "center",
-        "margin": "10px 0",
-        "font-size" : "14px"
-    });
-    console.log("HelloWorldWidget was drawn");
-}
--- a/src/js/widgets/playerWidget.js	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
-/* Internationalization for this widget */
-
-IriSP.i18n.addMessages(
-    {
-        "en": {
-            "play_pause": "Play/Pause",
-            "mute_unmute": "Mute/Unmute",
-            "play": "Play",
-            "pause": "Pause",
-            "mute": "Mute",
-            "unmute": "Unmute",
-            "annotate": "Annotate",
-            "search": "Search",
-            "elapsed_time": "Elapsed time",
-            "total_time": "Total time",
-            "volume": "Volume",
-            "volume_control": "Volume control"
-        },
-        "fr": {
-            "play_pause": "Lecture/Pause",
-            "mute_unmute": "Couper/Activer le son",
-            "play": "Lecture",
-            "pause": "Pause",
-            "mute": "Couper le son",
-            "unmute": "Activer le son",
-            "annotate": "Annoter",
-            "search": "Rechercher",
-            "elapsed_time": "Durée écoulée",
-            "total_time": "Durée totale",
-            "volume": "Niveau sonore",
-            "volume_control": "Réglage du niveau sonore"
-        }
-    }
-);
-
-
-IriSP.PlayerWidget = function(player, config) {
-  IriSP.Widget.call(this, player, config);
-  
-  this._searchLastValue = "";
-};
-
-IriSP.PlayerWidget.prototype = new IriSP.Widget();
-
-IriSP.PlayerWidget.prototype.draw = function() {
-    var _this = this,
-        _html = IriSP.templToHTML(IriSP.player_template, this);
-    
-    this.$.append(_html);
-    
-    // Define blocks
-    this.$playButton = this.$.find(".Ldt-Ctrl-Play");
-    this.$searchBlock = this.$.find(".Ldt-Ctrl-Search");
-    this.$searchInput = this.$.find(".Ldt-Ctrl-SearchInput");
-    this.$volumeBar = this.$.find(".Ldt-Ctrl-Volume-Bar");
-    
-    // handle events
-    this.bindPopcorn("play","playButtonUpdater");
-    this.bindPopcorn("pause","playButtonUpdater");
-    this.bindPopcorn("volumechange","volumeUpdater");
-    this.bindPopcorn("timeupdate","timeDisplayUpdater");
-    this.bindPopcorn("loadedmetadata","timeDisplayUpdater");
-    this.bindPopcorn("IriSP.search.matchFound","searchMatch");
-    this.bindPopcorn("IriSP.search.noMatchFound","searchNoMatch");
-    this.bindPopcorn("IriSP.search.triggeredSearch","triggeredSearch");
-    
-    // handle clicks
-    this.$playButton.click(this.functionWrapper("playHandler"));
-    
-    this.$.find(".Ldt-Ctrl-Annotate").click(function() {
-        _this.player.popcorn.trigger("IriSP.PlayerWidget.AnnotateButton.clicked");
-    });
-    this.$.find(".Ldt-Ctrl-SearchBtn").click(this.functionWrapper("searchButtonHandler"));
-    
-    this.$searchInput.keyup(this.functionWrapper("searchHandler") );
-  
-	var _volctrl = this.$.find(".Ldt-Ctrl-Volume-Control");
-    this.$.find('.Ldt-Ctrl-Sound')
-        .click(this.functionWrapper("muteHandler"))
-        .mouseover(function() {
-            _volctrl.show();
-        })
-        .mouseout(function() {
-            _volctrl.hide();
-        });
-    _volctrl.mouseover(function() {
-        _volctrl.show();
-    }).mouseout(function() {
-        _volctrl.hide();
-    });
-  
-    
-    // Allow Volume Cursor Dragging
-    this.$volumeBar.slider({
-        slide: function(event, ui) {
-            _this.$volumeBar.attr("title",IriSP.i18n.getMessage('volume')+': ' + ui.value + '%');
-            _this.player.popcorn.volume(ui.value / 100);
-        },
-        stop: this.functionWrapper("volumeUpdater")
-    });
-
-    // trigger an IriSP.PlayerWidget.MouseOver to the widgets that are interested (i.e : sliderWidget)
-    this.$.hover(
-        function() {
-            _this.player.popcorn.trigger("IriSP.PlayerWidget.MouseOver");
-        }, 
-        function() {
-            _this.player.popcorn.trigger("IriSP.PlayerWidget.MouseOut");
-        });
-    setTimeout(this.functionWrapper("volumeUpdater"), 1000);
-    /* some players - including jwplayer - save the state of the mute button between sessions */
-};
-
-/* Update the elasped time div */
-IriSP.PlayerWidget.prototype.timeDisplayUpdater = function() {
-    var _curTime = this.player.popcorn.roundTime();
-    if (typeof this._previousSecond !== "undefined" && _curTime === this._previousSecond) {
-        return;
-    }
-  
-    // we get it at each call because it may change.
-    var _totalTime = this.source.getDuration(),
-        _elapsedTime = new IriSP.Model.Time();
-        
-    _elapsedTime.setSeconds(_curTime);
-  
-    this.$.find(".Ldt-Ctrl-Time-Elapsed").html(_elapsedTime.toString());
-    this.$.find(".Ldt-Ctrl-Time-Total").html(_totalTime.toString());
-    this._previousSecond = _curTime;
-};
-
-/* update the icon of the button - separate function from playHandler
-   because in some cases (for instance, when the user directly clicks on
-   the jwplayer window) we have to change the icon without playing/pausing
-*/
-IriSP.PlayerWidget.prototype.playButtonUpdater = function() {
-    
-    var status = this.player.popcorn.media.paused;
-  
-    if (status) {
-    /* the background sprite is changed by adding/removing the correct classes */
-        this.$playButton
-            .attr("title", IriSP.i18n.getMessage('play'))
-            .removeClass("Ldt-Ctrl-Play-PauseState")
-            .addClass("Ldt-Ctrl-Play-PlayState");
-    } else {
-        this.$playButton
-            .attr("title", IriSP.i18n.getMessage('pause'))
-            .removeClass("Ldt-Ctrl-Play-PlayState")
-            .addClass("Ldt-Ctrl-Play-PauseState");
-    }
-};
-
-
-IriSP.PlayerWidget.prototype.playHandler = function() {
-    
-    var status = this.player.popcorn.media.paused;
-  
-    if (status) {        
-        this.player.popcorn.play();   
-    } else {
-        this.player.popcorn.pause();
-    }  
-};
-
-IriSP.PlayerWidget.prototype.muteHandler = function() {
-    this.player.popcorn.mute(!this.player.popcorn.muted());
-};
-
-IriSP.PlayerWidget.prototype.volumeUpdater = function() {
-    var _muted = this.player.popcorn.muted(),
-        _vol = this.player.popcorn.volume();
-    if (_vol === false) {
-        _vol = .5;
-    }
-    var _soundCtl = this.$.find(".Ldt-Ctrl-Sound");
-    _soundCtl.removeClass("Ldt-Ctrl-Sound-Mute Ldt-Ctrl-Sound-Half Ldt-Ctrl-Sound-Full");
-    if (_muted) {        
-        _soundCtl.attr("title", IriSP.i18n.getMessage('unmute'))
-            .addClass("Ldt-Ctrl-Sound-Mute");    
-    } else {
-        _soundCtl.attr("title", IriSP.i18n.getMessage('mute'))
-            .addClass(_vol < .5 ? "Ldt-Ctrl-Sound-Half" : "Ldt-Ctrl-Sound-Full" )
-    }
-    this.$volumeBar.slider("value", _muted ? 0 : 100 * _vol);
-};
-
-IriSP.PlayerWidget.prototype.showSearchBlock = function() {
-    this.$searchBlock.show("blind", { direction: "horizontal"}, 100);
-    this.$searchInput.css('background-color','#fff');
-   
-    this.$searchInput.focus();
-    
-    // we need this variable because some widgets can find a match in
-    // their data while at the same time others 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.player.popcorn.trigger("IriSP.search.open");
-};
-
-IriSP.PlayerWidget.prototype.hideSearchBlock = function() {
-    this._searchLastValue = this.$searchInput.val();
-    this.$searchInput.val('');
-    this.$searchBlock.hide("blind", { direction: "horizontal"}, 75);
-
-    this._positiveMatch = false;
-    
-    this.player.popcorn.trigger("IriSP.search.closed");
-};
-
-/** react to clicks on the search button */
-IriSP.PlayerWidget.prototype.searchButtonHandler = function() {
-    if ( this.$searchBlock.is(":hidden") ) {
-        this.showSearchBlock();
-        this.$searchInput.val(this._searchLastValue);      
-        this.player.popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural.
-	} else {
-        this.hideSearchBlock();
-    }
-};
-
-/** this handler is called whenever the content of the search
-   field changes */
-IriSP.PlayerWidget.prototype.searchHandler = function() {
-    this._searchLastValue = this.$searchInput.val();
-    this._positiveMatch = false;
-  
-    // do nothing if the search field is empty, instead of highlighting everything.
-    if (this._searchLastValue == "") {
-        this.player.popcorn.trigger("IriSP.search.cleared");
-        this.$searchInput.css('background-color','');
-    } else {
-        this.player.popcorn.trigger("IriSP.search", this._searchLastValue);
-    }
-};
-
-/**
-  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.$searchInput.css('background-color','#e1ffe1');
-};
-
-/** the same, except that no value could be found */
-IriSP.PlayerWidget.prototype.searchNoMatch = function() {
-    if (this._positiveMatch !== true) {
-        this.$searchInput.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.$searchInput.attr('value', searchString);      
-    this.player.popcorn.trigger("IriSP.search", searchString); // trigger the search to make it more natural.
-};
-
-
--- a/src/js/widgets/polemicWidget.js	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-IriSP.PolemicWidget = function(player, config) {
-    IriSP.Widget.call(this, player, config);
-    this.bindPopcorn("IriSP.search", "searchHandler");
-    this.bindPopcorn("IriSP.search.closed", "searchHandler");
-    this.bindPopcorn("IriSP.search.cleared", "searchHandler");
-    this.bindPopcorn("timeupdate", "onTimeupdate");
-    this.sliceCount = Math.floor( this.width / this.element_width );
-    this.$zone = IriSP.jQuery('<div>');
-    this.$.append(this.$zone);
-};
-
-IriSP.PolemicWidget.prototype = new IriSP.Widget();
-
-IriSP.PolemicWidget.prototype.searchHandler = function(searchString) {
-    this.searchString = typeof searchString !== "undefined" ? searchString : '';
-    var _found = 0,
-        _re = IriSP.Model.regexpFromTextOrArray(searchString)
-        _this = this;
-    this.$tweets.each(function() {
-        var _el = IriSP.jQuery(this);
-        if (_this.searchString) {
-            if (_re.test(_el.attr("tweet-title"))) {
-                _el.css({
-                    "background" : _this.foundcolor,
-                    "opacity" : 1
-                });
-                _found++;
-            } else {
-                _el.css({
-                    "background" : _el.attr("polemic-color"),
-                    "opacity" : .5
-                });
-            }
-        } else {
-            _el.css({
-                "background" : _el.attr("polemic-color"),
-                "opacity" : 1
-            });
-        }
-    });
-    if (this.searchString) {
-        if (_found) {
-            this.player.popcorn.trigger("IriSP.search.matchFound");
-        } else {
-            this.player.popcorn.trigger("IriSP.search.noMatchFound");
-        }
-    }
-}
-
-IriSP.PolemicWidget.prototype.draw = function() {
-    var _slices = [],
-        _duration = this.source.getDuration(),
-        _max = 0,
-        _list = this.annotation_type ? this.source.getAnnotationsByTypeTitle(this.annotation_type) : this.source.getAnnotations();
-    
-    for (var _i = 0; _i < this.sliceCount; _i++) {
-        var _begin = new IriSP.Model.Time(_i*_duration/this.sliceCount),
-            _end = new IriSP.Model.Time((_i+1)*_duration/this.sliceCount),
-            _count = 0,
-            _res = {
-                annotations : _list.filter(function(_annotation) {
-                    return _annotation.begin >= _begin && _annotation.end < _end;
-                }),
-                polemicStacks : []
-            }
-            
-        for (var _j = 0; _j < this.tags.length; _j++) {
-            var _polemic = _res.annotations.searchByDescription(this.tags[_j].keywords);
-            _count += _polemic.length;
-            _res.polemicStacks.push(_polemic);
-        }
-        for (var _j = 0; _j < this.tags.length; _j++) {
-            _res.annotations.removeElements(_res.polemicStacks[_j]);
-        }
-        _count += _res.annotations.length;
-        _max = Math.max(_max, _count);
-        _slices.push(_res);
-    }
-    this.height = (_max ? (_max + 2) * this.element_height : 0);
-    this.$zone.css({
-        width: this.width + "px",
-        height: this.height + "px",
-        position: "relative"
-    });
-    
-    this.$elapsed = IriSP.jQuery('<div>')
-        .css({
-            background: '#cccccc',
-            position: "absolute",
-            top: 0,
-            left: 0,
-            width: 0,
-            height: "100%"
-        });
-        
-    this.$zone.append(this.$elapsed);
-    
-    var _x = 0,
-        _this = this;
-    
-    function displayElement(_x, _y, _color, _id, _title) {
-        var _el = IriSP.jQuery('<div>')
-            .attr({
-                "tweet-title" : _title,
-                "pos-x" : Math.floor(_x + (_this.element_width - 1) / 2),
-                "pos-y" : _y,
-                "polemic-color" : _color,
-                "annotation-id" : _id
-            })
-            .css({
-                position: "absolute",
-                width: (_this.element_width-1) + "px",
-                height: _this.element_height + "px",
-                left: _x + "px",
-                top: _y + "px",
-                background: _color
-            })
-            .addClass("Ldt-Polemic-TweetDiv");
-        _this.$zone.append(_el);
-        return _el;
-    }
-    
-    IriSP._(_slices).forEach(function(_slice) {
-        var _y = _this.height;
-        _slice.annotations.forEach(function(_annotation) {
-            _y -= _this.element_height;
-            displayElement(_x, _y, _this.defaultcolor, _annotation.namespacedId.name, _annotation.title);
-        });
-        IriSP._(_slice.polemicStacks).forEach(function(_annotations, _j) {
-            var _color = _this.tags[_j].color;
-            _annotations.forEach(function(_annotation) {
-                _y -= _this.element_height;
-                displayElement(_x, _y, _color, _annotation.namespacedId.name, _annotation.title);
-            });
-        });
-        _x += _this.element_width;
-    });
-    
-    this.$tweets = this.$.find(".Ldt-Polemic-TweetDiv");
-    
-    this.$position = IriSP.jQuery('<div>')
-        .css({
-            background: '#fc00ff',
-            position: "absolute",
-            top: 0,
-            left: "-1px",
-            width: "2px",
-            height: "100%"
-        });
-        
-    this.$zone.append(this.$position);
-    
-    this.$tweets
-        .mouseover(function() {
-            var _el = IriSP.jQuery(this);
-            _this.TooltipWidget.show(_el.attr("pos-x"), _el.attr("pos-y"), _el.attr("tweet-title"), _el.attr("polemic-color"));
-        })
-        .mouseout(function() {
-            _this.TooltipWidget.hide();
-        });
-    
-    //TODO: Display Tweet in Tweet Widget on click
-    
-    this.$zone.click(function(_e) {
-        var _x = _e.pageX - _this.$zone.offset().left;
-        _this.player.popcorn.currentTime(_this.source.getDuration().getSeconds() * _x / _this.width);
-    });
-}
-
-IriSP.PolemicWidget.prototype.onTimeupdate = function() {
-    var _x = Math.floor( this.width * this.player.popcorn.currentTime() / this.source.getDuration().getSeconds());
-    this.$elapsed.css({
-        width:  _x + "px"
-    });
-    this.$position.css({
-        left: (_x - 1) + "px"
-    })
-}
--- a/src/js/widgets/sliderWidget.js	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- The Slider Widget fits right under the video
- */
-
-IriSP.SliderWidget = function(player, config) {
-    IriSP.Widget.call(this, player, config);
-    this.bindPopcorn("timeupdate","onTimeupdate");
-    this.bindPopcorn("IriSP.PlayerWidget.MouseOver","onMouseover");
-    this.bindPopcorn("IriSP.PlayerWidget.MouseOut","onMouseout");
-};
-
-IriSP.SliderWidget.prototype = new IriSP.Widget();
-
-IriSP.SliderWidget.prototype.draw = function() {
-    
-    this.$slider = IriSP.jQuery('<div>')
-        .addClass("Ldt-Slider")
-        .css(this.calculateSliderCss(this.minimized_height));
-    
-    this.$.append(this.$slider);
-    
-    var _this = this;
-    
-    this.$slider.slider({
-        range: "min",
-        value: 0,
-        min: 0,
-        max: this.source.getDuration().getSeconds(),
-        slide: function(event, ui) {
-            _this.player.popcorn.currentTime(ui.value);
-        }
-    });
-    
-    this.$handle = this.$slider.find('.ui-slider-handle');
-    
-    this.$handle.css(this.calculateHandleCss(this.minimized_height));
-    
-    this.$
-        .mouseover(this.functionWrapper("onMouseover"))
-        .mouseout(this.functionWrapper("onMouseout"));
-    
-    this.maximized = false;
-    this.timeoutId = false;
-};
-
-IriSP.SliderWidget.prototype.onTimeupdate = function() {
-    this.$slider.slider("value",this.player.popcorn.currentTime());
-}
-
-IriSP.SliderWidget.prototype.onMouseover = function() {
-    if (this.timeoutId) {
-        window.clearTimeout(this.timeoutId);
-        this.timeoutId = false;
-    }
-    if (!this.maximized) {
-       this.animateToHeight(this.maximized_height);
-       this.maximized = true;
-    }
-}
-
-IriSP.SliderWidget.prototype.onMouseout = function() {
-    if (this.timeoutId) {
-        window.clearTimeout(this.timeoutId);
-        this.timeoutId = false;
-    }
-    var _this = this;
-    this.timeoutId = window.setTimeout(function() {
-        if (_this.maximized) {
-            _this.animateToHeight(_this.minimized_height);
-            _this.maximized = false;
-        }
-        _this.timeoutId = false;
-    }, this.minimize_timeout);
-    
-}
-
-IriSP.SliderWidget.prototype.animateToHeight = function(_height) {
-    this.$slider.stop().animate(
-        this.calculateSliderCss(_height),
-        500,
-        function() {
-            IriSP.jQuery(this).css("overflow","visible");
-        });
-    this.$handle.stop().animate(
-        this.calculateHandleCss(_height),
-        500,
-        function() {
-            IriSP.jQuery(this).css("overflow","visible");
-        });
-}
-
-IriSP.SliderWidget.prototype.calculateSliderCss = function(_size) {
-    return {
-        height: _size + "px",
-        "margin-top": (this.minimized_height - _size) + "px"
-    };
-}
-
-IriSP.SliderWidget.prototype.calculateHandleCss = function(_size) {
-    return {
-        height: (2 + _size) + "px",
-        width: (2 + _size) + "px",
-        "margin-left": -Math.ceil(2 + _size / 2) + "px" 
-    }
-}
\ No newline at end of file
--- a/src/js/widgets/sparklineWidget.js	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/** @class The constructor for the sparkline widget */
-IriSP.SparklineWidget = function(Popcorn, config, Serializer) {
-  IriSP.Widget.call(this, Popcorn, config, Serializer);
-
-  this._oldAnnotation = null;
-  this._results = [];
-  
-  this.slices = this._config.slices || Math.floor(this.width/20);
-  if (!this.width) {
-      this.width = this.selector.width();
-  }
-  if (!this.height) {
-      this.height = 40;
-  }
-  this.selector.css("height", this.height + "px");
-  if (this._config.background) {
-      this.selector.css("background", this._config.background);
-  }
-};
-
-
-IriSP.SparklineWidget.prototype = new IriSP.Widget();
-
-IriSP.SparklineWidget.prototype.clear = function() {
-
-};
-
-/** draw the sparkline using jquery sparkline */
-IriSP.SparklineWidget.prototype.draw = function() {
-    this.duration = this.getDuration();
-    this.paper = new Raphael(this.selector[0], this.width, this.height);
-    var _this = this;
-  
-  var views = this._serializer._data.views;
-  var stat_view;
-  if (!IriSP.null_or_undefined(views)) {
-    for (var i = 0; i < views.length; i++) {
-      var view = views[i];
-      if (view.id === "stat") {
-          stat_view = view;
-          break;
-      }
-    }
-  }
-  
-    var _ = IriSP.underscore;
-  // If we've found the correct view, feed the directly the data from the view
-  // to jquery sparkline. Otherwise, compute it ourselves.
-    if (!IriSP.null_or_undefined(stat_view)) {
-        //console.log("sparklinewidget : using stats embedded in the json");
-        var _results = stat_view.meta.stat.split(",");      
-    } else {
-        var _annotations = this._serializer._data.annotations,
-            _sliceDuration = Math.floor( this.duration / this.slices),
-            _results = _(_.range(this.slices)).map(function(_i) {
-                return _(_annotations).filter(function(_a){
-                    return (_a.begin <= (1 + _i) * _sliceDuration) && (_a.end >= _i * _sliceDuration)
-                }).length;
-            });
-    }
-    var _max = Math.max(1, _(_results).max()),
-        _h = this.height,
-        _scale = (_h - this.lineWidth) / _max,
-        _width = this.width / this.slices,
-        _y = _(_results).map(function(_v) {
-            return _h - (_scale * _v);
-        }),
-        _d = _(_y).reduce(function(_memo, _v, _k) {
-               return _memo + ( _k
-                   ? 'C' + (_k * _width) + ' ' + _y[_k - 1] + ' ' + (_k * _width) + ' ' + _v + ' ' + ((_k + .5) * _width) + ' ' + _v
-                   : 'M0 ' + _v + 'L' + (.5*_width) + ' ' + _v )
-            },'') + 'L' + this.width + ' ' + _y[_y.length - 1],
-        _d2 = _d + 'L' + this.width + ' ' + this.height + 'L0 ' + this.height;
-    this.paper.path(_d2).attr({
-        "stroke" : "none",
-        "fill" : this.fillColor
-    });
-         
-    this.paper.path(_d).attr({
-        "fill" : "none",
-        "stroke" : this.lineColor,
-        "stroke-width" : this.lineWidth
-    });
-  
-    this.rectangleProgress = this.paper.rect(0,0,0,this.height)
-        .attr({
-            "stroke" : "none",
-            "fill" : "#808080",
-            "opacity" : .3
-        });
-    this.ligneProgress = this.paper.path("M0 0L0 "+this.height).attr({"stroke":"#ff00ff", "line-width" : 2});
-  // save the results in an array so that we can re-use them when a new annotation
-  // is added.
-  this._results = _results;
-  
-  this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeUpdateHandler));
-//  this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation", IriSP.wrap(this, this.handleNewAnnotation));
-  
-  this.selector.click(IriSP.wrap(this, this.clickHandler));  
-};
-
-/** react to a timeupdate event */
-IriSP.SparklineWidget.prototype.timeUpdateHandler = function() {
-    var _currentTime = this._Popcorn.currentTime(),
-        _x = (1000 * _currentTime / this.duration) * this.width;
-    this.rectangleProgress.attr({
-        "width" : _x
-    });
-    this.ligneProgress.attr({
-        "path" : "M" + _x + " 0L" + _x + " " + this.height
-    });
-                                  
-}
-
-/** handle clicks on the widget */
-IriSP.SparklineWidget.prototype.clickHandler = function(event) {
-  var relX = event.pageX - this.selector.offset().left;
-  var newTime = ((relX / this.width) * this.duration/1000).toFixed(2);
-    
-  this._Popcorn.trigger("IriSP.SparklineWidget.clicked", newTime);
-  this._Popcorn.currentTime(newTime);
-};
-
-/** react when a new annotation is added */
-IriSP.SparklineWidget.prototype.handleNewAnnotation = function(annotation) {
-//  var num_columns = this._results.length;
-//  var duration = this._serializer.getDuration();
-//  var time_step = Math.round(duration / num_columns); /* the time interval between two columns */
-//  var begin = +annotation.begin;
-//  var end = +annotation.end;
-//  
-//  /* increment all the values between the beginning and the end of the annotation */
-//  var index_begin = Math.floor(begin / time_step);
-//  var index_end = Math.floor(end / time_step);
-//  
-//  for (var i = index_begin; i < Math.min(index_end, this._results.length); i++) {
-//    this._results[i]++;
-//  }
-//  
-//  this.selector.find(".Ldt-sparkLine").sparkline(this._results, {lineColor: "#7492b4", fillColor: "#aeaeb8",
-//                                                           spotColor: "#b70056",
-//                                                           width: this.width, height: this.height});
-};
\ No newline at end of file
--- a/src/js/widgets/tooltipWidget.js	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/* this widget displays a small tooltip */
-IriSP.TooltipWidget = function(Popcorn, config, Serializer) {
-    IriSP.Widget.call(this, Popcorn, config, Serializer);
-};
-
-IriSP.TooltipWidget.prototype = new IriSP.Widget();
-
-IriSP.TooltipWidget.prototype.draw = function() {
-    var _html = Mustache.to_html(IriSP.tooltipWidget_template),
-        _this = this;
-    this.$.parent().css({
-        "position" : "relative"
-    });
-    this.$.append(_html);
-    this.$tip = this.$.find(".Ldt-Tooltip");
-    this.$.mouseover(function() {
-        _this.$tip.hide();
-    });
-    this.hide();
-};
-
-IriSP.TooltipWidget.prototype.show = function(x, y, text, color) {
-    
-    if (typeof color !== "undefined") {
-        this.$.find(".Ldt-Tooltip-Color").show().css("background-color", color);
-    } else {
-        this.$.find(".Ldt-Tooltip-Color").hide();
-    }
-    
-    this.$.find(".Ldt-Tooltip-Text").html(text);
-
-    this.$tip.show();
-    this.$tip.css({
-        "left" : Math.floor(x - this.$tip.outerWidth() / 2) + "px",
-        "top" : Math.floor(y - this.$tip.outerHeight() - 5) + "px"
-    });
-};
-
-IriSP.TooltipWidget.prototype.hide = function() {
-    this.$tip.hide();
-};
--- a/src/templates/annotationsListWidget.html	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-{{! template for the annotation list widget }}
-<div class='Ldt-AnnotationsListWidget'>
-    <ul class='Ldt-AnnotationsList-ul'>
-        {{#annotations}}
-        <li id='Ldt-Annotation-li-{{id}}' class='Ldt-AnnotationsList-li Ldt-TraceMe'>
-            <div class='Ldt-AnnotationsList-ThumbContainer'>
-                <a href='{{url}}'>
-                    <img class='Ldt-AnnotationsList-Thumbnail' src='{{thumbnail}}' />
-                </a>
-            </div>
-            <div class='Ldt-AnnotationsList-Duration'>{{begin}} - {{end}}</div>
-            <h3 class='Ldt-AnnotationsList-Title'>
-                <a href='{{url}}'>{{title}}</a>
-            </h3>
-            <p class='Ldt-AnnotationsList-Description'>{{description}}</p>
-            {{#tags.length}}
-            <ul class='Ldt-AnnotationsList-Tags'>
-                {{#tags}}
-                {{#.}}
-                <li class='Ldt-AnnotationsList-Tag-Li'>
-                    <div class='Ldt-AnnotationsList-Tag-Div'>{{.}}</div>
-                </li>
-                {{/.}}
-                {{/tags}}
-            </ul>
-            {{/tags.length}}
-        </li>
-        {{/annotations}}
-    </ul>
-</div>
--- a/src/templates/player.html	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-{{! template for the radio player }}
-<div class='Ldt-Ctrl'>
-	<div class='Ldt-Ctrl-Left'>
-        <div class='Ldt-Ctrl-button Ldt-Ctrl-Play Ldt-Ctrl-Play-PlayState Ldt-TraceMe' title='{{l10n.play_pause}}'></div>
-        <div class='Ldt-Ctrl-spacer'></div>
-        {{^disable_annotate_btn}}
-    	<div class='Ldt-Ctrl-button Ldt-Ctrl-Annotate Ldt-TraceMe' title='{{l10n.annotate}}'></div>
-        <div class='Ldt-Ctrl-spacer'></div>
-        {{/disable_annotate_btn}}
-        {{^disable_search_btn}}
-        <div class='Ldt-Ctrl-button Ldt-Ctrl-SearchBtn Ldt-TraceMe' title='{{l10n.search}}'></div>
-        <div class='Ldt-Ctrl-spacer'></div>
-        {{/disable_search_btn}}
-        <div class='Ldt-Ctrl-Search'>
-          <input class='Ldt-Ctrl-SearchInput Ldt-TraceMe'></input>
-        </div>
-	</div>
-	<div class='Ldt-Ctrl-Right'>
-        <div class='Ldt-Ctrl-spacer'></div>
-        <div class='Ldt-Ctrl-Time'>
-          <div class='Ldt-Ctrl-Time-Elapsed' title='{{l10n.elapsed_time}}'>00:00</div>
-          <div class='Ldt-Ctrl-Time-Separator'>/</div>
-          <div class='Ldt-Ctrl-Time-Total' title='{{l10n.total_time}}'>00:00</div>
-        </div>
-        <div class='Ldt-Ctrl-spacer'></div>
-		<div class='Ldt-Ctrl-button Ldt-Ctrl-Sound Ldt-Ctrl-Sound-Full Ldt-TraceMe' title='{{l10n.mute_unmute}}'></div>
-	</div>
-	<div class='Ldt-Ctrl-Volume-Control' title='{{l10n.volume_control}}'>
-	    <div class='Ldt-Ctrl-Volume-Bar'></div>
-	</div>
-</div>
--- a/src/templates/tooltipWidget.html	Fri Apr 20 19:13:11 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-{{! template for the tooltip widget }}
-
-<div class='Ldt-Tooltip'>
-	<div class='Ldt-Tooltip-Color'></div>
-	<div class='Ldt-Tooltip-Text'></div>
-</div>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/AnnotationsList.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,80 @@
+/* AnnotationsListWidget */
+
+.Ldt-AnnotationsListWidget {
+    font-family: "Open Sans", Helvetica, Arial, sans-serif;
+    border: 1px solid #b6b8b8;
+    overflow: auto;
+    max-height: 480px;
+}
+.Ldt-AnnotationsListWidget a {
+    text-decoration: none;
+}
+ul.Ldt-AnnotationsList-ul {
+    list-style: none;
+    padding: 2px;
+    margin: 0;
+}
+li.Ldt-AnnotationsList-li {
+    width: 100%;
+    clear: both;
+    margin: 2px 0;
+    padding: 2px 0;
+    min-height: 60px;
+}
+.Ldt-AnnotationsList-li:hover {
+    background-color: #e9e9e9;
+}
+.Ldt-AnnotationsList-highlight {
+    background: #F7268E;
+    color: #ffffff;
+}
+.Ldt-AnnotationsList-ThumbContainer {
+    float: left;
+    width: 80px;
+    height: 50px;
+    text-align: center;
+    margin: 2px 0;
+}
+.Ldt-AnnotationsList-Thumbnail {
+    border: none;
+    max-width: 100%;
+    max-height: 100%;
+    margin: 0 auto;
+}
+.Ldt-AnnotationsList-Duration {
+    color: #f7268e;
+    float: right;
+    text-align: right;
+    font-size: 12px;
+    margin: 2px;
+}
+h3.Ldt-AnnotationsList-Title {
+    color: #0068c4;
+    font-size: 13px;
+    margin: 2px 2px 0 82px;
+    font-weight: bold;
+}
+.Ldt-AnnotationsList-Title a {
+    color: #0068c4;
+}
+p.Ldt-AnnotationsList-Description {
+    margin: 2px 0 2px 82px;
+    font-size: 12px;
+    color: #666666;
+}
+ul.Ldt-AnnotationsList-Tags {
+    list-style: none;
+    padding: 0;
+    margin: 2px 0 0 82px;
+}
+li.Ldt-AnnotationsList-Tag-Li {
+    display: inline-block;
+    margin: 2px;
+    background: #0068c4;
+    color: #fff;
+    padding: 2px;
+    font-size: 12px;
+}
+li.Ldt-AnnotationsList-Tag-Li:hover {
+    background: #F7268E;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/AnnotationsList.js	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,225 @@
+IriSP.Widgets.AnnotationsList = function(player, config) {
+    IriSP.Widgets.Widget.call(this, player, config);
+    this.bindPopcorn("IriSP.search", "searchHandler");
+    this.bindPopcorn("IriSP.search.closed", "searchHandler");
+    this.bindPopcorn("IriSP.search.cleared", "searchHandler");
+    this.searchString = false;
+    this.lastIds = [];
+    var _this = this;
+    this.throttledRefresh = IriSP._.throttle(function() {
+        _this.refresh(false);
+    }, 1500);
+};
+
+IriSP.Widgets.AnnotationsList.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.AnnotationsList.prototype.defaults = {
+    /* URL when the annotations are to be reloaded from an LDT-like segment API
+     * e.g. http://ldt.iri.centrepompidou.fr/ldtplatform/api/ldt/segments/{{media}}/{{begin}}/{{end}}?callback=?
+     */
+    ajax_url : false,
+    /* how much ms should we look before and after the current timecode in the segment API
+     */
+    ajax_granularity : 300000, 
+    default_thumbnail : "http://ldt.iri.centrepompidou.fr/static/site/ldt/css/imgs/video_sequence.png",
+    /* URL when the annotation is not in the current project,
+     * e.g. http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/{{media}}/{{project}}/{{annotationType}}#id={{annotation}}
+     */
+    foreign_url : "",
+    cinecast_version : false,
+    annotation_type : false,
+    refresh_interval : 0,
+    limit_count : 10,
+    newest_first : false
+};
+
+IriSP.Widgets.AnnotationsList.prototype.template =
+    '<div class="Ldt-AnnotationsListWidget">'
+    + '<ul class="Ldt-AnnotationsList-ul">'
+    + '{{#annotations}}'
+    + '<li id="Ldt-Annotation-li-{{id}}" class="Ldt-AnnotationsList-li Ldt-TraceMe">'
+    + '<div class="Ldt-AnnotationsList-ThumbContainer">'
+    + '<a href="{{url}}">'
+    + '<img class="Ldt-AnnotationsList-Thumbnail" src="{{thumbnail}}" />'
+    + '</a>'
+    + '</div>'
+    + '<div class="Ldt-AnnotationsList-Duration">{{begin}} - {{end}}</div>'
+    + '<h3 class="Ldt-AnnotationsList-Title">'
+    + '<a href="{{url}}">{{title}}</a>'
+    + '</h3>'
+    + '<p class="Ldt-AnnotationsList-Description">{{description}}</p>'
+    + '{{#tags.length}}'
+    + '<ul class="Ldt-AnnotationsList-Tags">'
+    + '{{#tags}}'
+    + '{{#.}}'
+    + '<li class="Ldt-AnnotationsList-Tag-Li">'
+    + '<div class="Ldt-AnnotationsList-Tag-Div">{{.}}</div>'
+    + '</li>'
+    + '{{/.}}'
+    + '{{/tags}}'
+    + '</ul>'
+    + '{{/tags.length}}'
+    + '</li>'
+    + '{{/annotations}}'
+    + '</ul>'
+    + '</div>';
+
+IriSP.Widgets.AnnotationsList.prototype.clear = function() {
+};
+
+IriSP.Widgets.AnnotationsList.prototype.clearWidget = function() {
+};
+
+IriSP.Widgets.AnnotationsList.prototype.searchHandler = function(searchString) {
+    this.searchString = typeof searchString !== "undefined" ? searchString : '';
+    var _n = this.refresh(true);
+    if (this.searchString) {
+        if (_n) {
+            this.player.popcorn.trigger("IriSP.search.matchFound");
+        } else {
+            this.player.popcorn.trigger("IriSP.search.noMatchFound");
+        }
+    }
+}
+
+//obj.url = this.project_url + "/" + media + "/" + annotations[i].meta.project + "/" + annotations[i].meta["id-ref"] + '#id=' + annotations[i].id;
+
+IriSP.Widgets.AnnotationsList.prototype.ajaxSource = function() {
+    var _currentTime = this.player.popcorn.currentTime(),
+        _duration = this.source.getDuration();
+    if (typeof _currentTime == "undefined") {
+        _currentTime = 0;
+    }
+    this.lastAjaxQuery = _currentTime;
+    _currentTime = Math.floor(1000 * _currentTime);
+    var _url = Mustache.to_html(this.ajax_url, {
+        media : this.source.currentMedia.namespacedId.name,
+        begin : Math.max(0, _currentTime - this.ajax_granularity),
+        end : Math.min(_duration.milliseconds, _currentTime + this.ajax_granularity)
+    });
+    this.currentSource = this.player.loadMetadata(IriSP._.defaults({
+        "url" : _url
+    }, this.metadata));
+}
+
+IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) {
+    _forceRedraw = (typeof _forceRedraw !== "undefined" && _forceRedraw);
+    if (this.currentSource.status !== IriSP.Model._SOURCE_STATUS_READY) {
+        return 0;
+    }
+    var _this = this,
+        _currentTime = this.player.popcorn.currentTime();
+    if (typeof _currentTime == "undefined") {
+        _currentTime = 0;
+    }
+    var _list = this.annotation_type ? this.currentSource.getAnnotationsByTypeTitle(this.annotation_type, true) : this.currentSource.getAnnotations();
+    if (this.searchString) {
+        _list = _list.searchByTextFields(this.searchString);
+    }
+    if (this.limit_count) {
+        _list = _list.sortBy(function(_annotation) {
+            return Math.abs(_annotation.begin.getSeconds() - _currentTime);
+        }).slice(0, this.limit_count)
+    }
+    if (this.newest_first) {
+        _list = _list.sortBy(function(_annotation) {
+            return -_annotation.created.valueOf();
+        });
+    } else {
+        _list = _list.sortBy(function(_annotation) {
+            return _annotation.begin;
+        });
+    }
+    
+    var _ids = _list.idIndex;
+    
+    if (_forceRedraw || !IriSP._.isEqual(_ids, this.lastIds)) {
+        /* This part only gets executed if the list needs updating */
+        this.lastIds = _ids;
+       
+        var _html = Mustache.to_html(
+            this.template,
+            {
+                annotations : _list.map(function(_annotation) {
+                    var _url = (
+                        ( typeof _annotation.url !== "undefined" )
+                        ? _annotation.url
+                        : (
+                            ( typeof _this.source.projectId !== "undefined" && typeof _annotation.project !== "undefined" && _this.source.projectId !== _annotation.project )
+                            ? Mustache.to_html(
+                                this.foreign_url,
+                                {
+                                    project : _annotation.project,
+                                    media : _annotation.media.id.replace(/^.*:/,''),
+                                    annotation : _annotation.namespacedId.name,
+                                    annotationType : _annotation.annotationType.id.replace(/^.*:/,'')
+                                }
+                            )
+                            : '#id=' + _annotation.namespacedId.name
+                            )
+                    );
+                    var _res = {
+                        id : _annotation.id,
+                        title : _annotation.title.replace(_annotation.description,''),
+                        description : _annotation.description,
+                        begin : _annotation.begin.toString(),
+                        end : _annotation.end.toString(),
+                        thumbnail : typeof _annotation.thumbnail !== "undefined" ? _annotation.thumbnail : _this.default_thumbnail,
+                        url : _url,
+                        tags : _annotation.getTagTexts()
+                    }
+                    return _res;
+                })
+            });
+    
+        this.$.html(_html);
+    
+        this.$.find('.Ldt-AnnotationsList-Tag-Li').click(function() {
+            _this.player.popcorn.trigger("IriSP.search.triggeredSearch", IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,''));
+        })
+        
+        if(this.searchString) {
+            var _searchRe = new RegExp('(' + this.searchString.replace(/(\W)/gm,'\\$1') + ')','gim');
+            this.$.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description").each(function() {
+                var _$ = IriSP.jQuery(this);
+                _$.html(_$.text().replace(/(^\s+|\s+$)/g,'').replace(_searchRe, '<span class="Ldt-AnnotationsList-highlight">$1</span>'))
+            })
+        }
+    }
+    
+    if (this.ajax_url && this.ajax_granularity) {
+        if (Math.abs(_currentTime - this.lastAjaxQuery) > (this.ajax_granularity / 2000)) {
+            this.ajaxSource();
+        }
+    }
+    return _list.length;
+}
+
+IriSP.Widgets.AnnotationsList.prototype.draw = function() {
+    var _this = this;
+    
+    if (this.ajax_url && this.ajax_granularity) {
+        this.ajaxSource();
+    } else {
+        this.currentSource = this.source;
+    }
+    
+    if (this.refresh_interval) {
+        window.setInterval(function() {
+            _this.currentSource.get()
+        }, this.refresh_interval);
+    }
+    
+    var _events = [
+        "IriSP.createAnnotationWidget.addedAnnotation",
+        "timeupdate",
+        "seeked",
+        "loadedmetadata"
+    ];
+    for (var _i = 0; _i < _events.length; _i++) {
+        this.player.popcorn.listen(_events[_i], this.throttledRefresh);
+    }
+    
+    this.throttledRefresh();
+
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Controller.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,178 @@
+/* Player Widget */
+
+.Ldt-Ctrl {
+  font-size: 10px;
+  font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+  background:url('img/player_gradient.png') repeat-x transparent ;
+  height: 25px;
+  border: 1px solid #b6b8b8;
+  position: relative;
+}
+
+.Ldt-Ctrl-Left {
+  float:left;
+}
+
+.Ldt-Ctrl-Right {
+  float: right;
+}
+
+.Ldt-Ctrl-button {
+  float: left;
+  width: 30px; height: 25px;
+  background: url('img/player-sprites.png');
+  cursor: pointer;
+}
+
+.Ldt-Ctrl-spacer {
+    float: left; width: 1px; height: 25px; background: #b6b8b8;
+}
+
+.Ldt-Ctrl-Play {
+  margin: 0 15px;
+}
+
+.Ldt-Ctrl-Play-PlayState {
+  background-position: 0 0;
+}
+
+.Ldt-Ctrl-Play-PlayState:hover {
+  background-position: 0 -25px;
+}
+
+.Ldt-Ctrl-Play-PlayState:active {
+  background-position: 0 -50px;
+}
+
+.Ldt-Ctrl-Play-PauseState {
+  background-position: -30px 0;
+}
+
+.Ldt-Ctrl-Play-PauseState:hover {
+  background-position: -30px -25px;
+}
+
+.Ldt-Ctrl-Play-PauseState:active {
+  background-position: -30px -50px;
+}
+
+.Ldt-Ctrl-Annotate {
+  margin: 0 2px;
+  background-position: -60px 0;
+}
+
+.Ldt-Ctrl-Annotate:hover {
+  background-position: -60px -25px;
+}
+
+.Ldt-Ctrl-Annotate:active {
+  background-position: -60px -50px;
+}
+
+.Ldt-Ctrl-SearchBtn {
+  margin: 0 2px;
+  background-position: -90px 0;
+}
+
+.Ldt-Ctrl-SearchBtn:hover {
+  background-position: -90px -25px;
+}
+
+.Ldt-Ctrl-SearchBtn:active {
+  background-position: -90px -50px;
+}
+
+.Ldt-Ctrl-Search {
+  display: none;
+  width: 165px;
+  height: 25px;
+  border: 1px;
+  border-color: #CFCFCF;
+  float: left;
+  text-align: center;
+}
+
+.Ldt-Ctrl-Time {
+  float: left;
+  margin: 5px;
+  font-size: 12px;
+  font-family: Arial, Verdana, sans-serif;
+}
+
+.Ldt-Ctrl-Time-Elapsed {
+  float: left;
+  color: #4a4a4a;
+}
+
+.Ldt-Ctrl-Time-Separator {
+  margin: 0 4px;      
+  float: left;
+}
+
+.Ldt-Ctrl-Time-Total {
+  float: left;
+  color: #b2b2b2; 
+}
+
+.Ldt-Ctrl-Sound {
+  margin: 0 2px;
+}
+
+.Ldt-Ctrl-Sound-Full {
+  background-position: -120px 0;
+}
+
+.Ldt-Ctrl-Sound-Full:hover {
+  background-position: -120px -25px;
+}
+
+.Ldt-Ctrl-Sound-Full:active {
+  background-position: -120px -50px;
+}
+
+.Ldt-Ctrl-Sound-Mute {
+  background-position: -150px 0;
+}
+
+.Ldt-Ctrl-Sound-Mute:hover {
+  background-position: -150px -25px;
+}
+
+.Ldt-Ctrl-Sound-Mute:active {
+  background-position: -150px -50px;
+}
+
+.Ldt-Ctrl-Sound-Half {
+  background-position: -180px 0;
+}
+
+.Ldt-Ctrl-Sound-Half:hover {
+  background-position: -180px -25px;
+}
+
+.Ldt-Ctrl-Sound-Half:active {
+  background-position: -180px -50px;
+}
+
+.Ldt-Ctrl-Volume-Control {
+    display: none;
+  position: absolute;
+  background:url('img/player_gradient.png') repeat-x transparent ;
+  height: 25px;
+  width: 100px; top: 25px; right: -1px; z-index: 100;
+  padding: 0 2px;
+  border: 1px solid #b6b8b8;
+}
+
+.Ldt-Ctrl-Volume-Bar { 
+    height: 5px; margin: 9px 3px 0; background: #cccccc; border: 1px solid #999999; border-radius: 2px;
+}
+
+.Ldt-Ctrl-Volume-Control .ui-slider-handle {
+    width: 6px; height: 19px; background: #a8a8a8; border: 1px solid #999999; border-radius: 2px; top: -8px; margin-left: -4px;
+    cursor: pointer;
+}
+
+.Ldt-Ctrl-Volume-Control:hover .ui-slider-handle {
+     background: #F7268E;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Controller.js	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,293 @@
+/* Displays Play and Pause buttons, Search Button and Form, Volume Control */
+
+IriSP.Widgets.Controller = function(player, config) {
+  IriSP.Widgets.Widget.call(this, player, config);
+  
+  this._searchLastValue = "";
+};
+
+IriSP.Widgets.Controller.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Controller.prototype.defaults = {}
+
+IriSP.Widgets.Controller.prototype.template =
+    '<div class="Ldt-Ctrl">'
+    + '<div class="Ldt-Ctrl-Left">'
+    + '<div class="Ldt-Ctrl-button Ldt-Ctrl-Play Ldt-Ctrl-Play-PlayState Ldt-TraceMe" title="{{l10n.play_pause}}"></div>'
+    + '<div class="Ldt-Ctrl-spacer"></div>'
+    + '{{^disable_annotate_btn}}'
+    + '<div class="Ldt-Ctrl-button Ldt-Ctrl-Annotate Ldt-TraceMe" title="{{l10n.annotate}}"></div>'
+    + '<div class="Ldt-Ctrl-spacer"></div>'
+    + '{{/disable_annotate_btn}}'
+    + '{{^disable_search_btn}}'
+    + '<div class="Ldt-Ctrl-button Ldt-Ctrl-SearchBtn Ldt-TraceMe" title="{{l10n.search}}"></div>'
+    + '<div class="Ldt-Ctrl-spacer"></div>'
+    + '{{/disable_search_btn}}'
+    + '<div class="Ldt-Ctrl-Search">'
+    + '<input class="Ldt-Ctrl-SearchInput Ldt-TraceMe"></input>'
+    + '</div>'
+    + '</div>'
+    + '<div class="Ldt-Ctrl-Right">'
+    + '<div class="Ldt-Ctrl-spacer"></div>'
+    + '<div class="Ldt-Ctrl-Time">'
+    + '<div class="Ldt-Ctrl-Time-Elapsed" title="{{l10n.elapsed_time}}">00:00</div>'
+    + '<div class="Ldt-Ctrl-Time-Separator">/</div>'
+    + '<div class="Ldt-Ctrl-Time-Total" title="{{l10n.total_time}}">00:00</div>'
+    + '</div>'
+    + '<div class="Ldt-Ctrl-spacer"></div>'
+    + '<div class="Ldt-Ctrl-button Ldt-Ctrl-Sound Ldt-Ctrl-Sound-Full Ldt-TraceMe" title="{{l10n.mute_unmute}}"></div>'
+    + '</div>'
+    + '<div class="Ldt-Ctrl-Volume-Control" title="{{l10n.volume_control}}">'
+    + '<div class="Ldt-Ctrl-Volume-Bar"></div>'
+    + '</div>'
+    + '</div>';
+
+IriSP.Widgets.Controller.prototype.messages = {
+    "en": {
+        "play_pause": "Play/Pause",
+        "mute_unmute": "Mute/Unmute",
+        "play": "Play",
+        "pause": "Pause",
+        "mute": "Mute",
+        "unmute": "Unmute",
+        "annotate": "Annotate",
+        "search": "Search",
+        "elapsed_time": "Elapsed time",
+        "total_time": "Total time",
+        "volume": "Volume",
+        "volume_control": "Volume control"
+    },
+    "fr": {
+        "play_pause": "Lecture/Pause",
+        "mute_unmute": "Couper/Activer le son",
+        "play": "Lecture",
+        "pause": "Pause",
+        "mute": "Couper le son",
+        "unmute": "Activer le son",
+        "annotate": "Annoter",
+        "search": "Rechercher",
+        "elapsed_time": "Durée écoulée",
+        "total_time": "Durée totale",
+        "volume": "Niveau sonore",
+        "volume_control": "Réglage du niveau sonore"
+    }
+};
+
+IriSP.Widgets.Controller.prototype.draw = function() {
+    var _this = this;
+    this.renderTemplate();
+    
+    // Define blocks
+    this.$playButton = this.$.find(".Ldt-Ctrl-Play");
+    this.$searchBlock = this.$.find(".Ldt-Ctrl-Search");
+    this.$searchInput = this.$.find(".Ldt-Ctrl-SearchInput");
+    this.$volumeBar = this.$.find(".Ldt-Ctrl-Volume-Bar");
+    
+    // handle events
+    this.bindPopcorn("play","playButtonUpdater");
+    this.bindPopcorn("pause","playButtonUpdater");
+    this.bindPopcorn("volumechange","volumeUpdater");
+    this.bindPopcorn("timeupdate","timeDisplayUpdater");
+    this.bindPopcorn("loadedmetadata","timeDisplayUpdater");
+    this.bindPopcorn("IriSP.search.matchFound","searchMatch");
+    this.bindPopcorn("IriSP.search.noMatchFound","searchNoMatch");
+    this.bindPopcorn("IriSP.search.triggeredSearch","triggeredSearch");
+    
+    // handle clicks
+    this.$playButton.click(this.functionWrapper("playHandler"));
+    
+    this.$.find(".Ldt-Ctrl-Annotate").click(function() {
+        _this.player.popcorn.trigger("IriSP.Player.AnnotateButton.clicked");
+    });
+    this.$.find(".Ldt-Ctrl-SearchBtn").click(this.functionWrapper("searchButtonHandler"));
+    
+    this.$searchInput.keyup(this.functionWrapper("searchHandler") );
+  
+	var _volctrl = this.$.find(".Ldt-Ctrl-Volume-Control");
+    this.$.find('.Ldt-Ctrl-Sound')
+        .click(this.functionWrapper("muteHandler"))
+        .mouseover(function() {
+            _volctrl.show();
+        })
+        .mouseout(function() {
+            _volctrl.hide();
+        });
+    _volctrl.mouseover(function() {
+        _volctrl.show();
+    }).mouseout(function() {
+        _volctrl.hide();
+    });
+  
+    
+    // Allow Volume Cursor Dragging
+    this.$volumeBar.slider({
+        slide: function(event, ui) {
+            _this.$volumeBar.attr("title",this.l10n.volume+': ' + ui.value + '%');
+            _this.player.popcorn.volume(ui.value / 100);
+        },
+        stop: this.functionWrapper("volumeUpdater")
+    });
+
+    // trigger an IriSP.Player.MouseOver to the widgets that are interested (i.e : sliderWidget)
+    this.$.hover(
+        function() {
+            _this.player.popcorn.trigger("IriSP.Player.MouseOver");
+        }, 
+        function() {
+            _this.player.popcorn.trigger("IriSP.Player.MouseOut");
+        });
+    setTimeout(this.functionWrapper("volumeUpdater"), 1000);
+    /* some players - including jwplayer - save the state of the mute button between sessions */
+};
+
+/* Update the elasped time div */
+IriSP.Widgets.Controller.prototype.timeDisplayUpdater = function() {
+    var _curTime = this.player.popcorn.roundTime();
+    if (typeof this._previousSecond !== "undefined" && _curTime === this._previousSecond) {
+        return;
+    }
+  
+    // we get it at each call because it may change.
+    var _totalTime = this.source.getDuration(),
+        _elapsedTime = new IriSP.Model.Time();
+        
+    _elapsedTime.setSeconds(_curTime);
+  
+    this.$.find(".Ldt-Ctrl-Time-Elapsed").html(_elapsedTime.toString());
+    this.$.find(".Ldt-Ctrl-Time-Total").html(_totalTime.toString());
+    this._previousSecond = _curTime;
+};
+
+/* update the icon of the button - separate function from playHandler
+   because in some cases (for instance, when the user directly clicks on
+   the jwplayer window) we have to change the icon without playing/pausing
+*/
+IriSP.Widgets.Controller.prototype.playButtonUpdater = function() {
+    
+    var status = this.player.popcorn.media.paused;
+  
+    if (status) {
+    /* the background sprite is changed by adding/removing the correct classes */
+        this.$playButton
+            .attr("title", this.l10n.play)
+            .removeClass("Ldt-Ctrl-Play-PauseState")
+            .addClass("Ldt-Ctrl-Play-PlayState");
+    } else {
+        this.$playButton
+            .attr("title", this.l10n.pause)
+            .removeClass("Ldt-Ctrl-Play-PlayState")
+            .addClass("Ldt-Ctrl-Play-PauseState");
+    }
+};
+
+
+IriSP.Widgets.Controller.prototype.playHandler = function() {
+    
+    var status = this.player.popcorn.media.paused;
+  
+    if (status) {        
+        this.player.popcorn.play();   
+    } else {
+        this.player.popcorn.pause();
+    }  
+};
+
+IriSP.Widgets.Controller.prototype.muteHandler = function() {
+    this.player.popcorn.mute(!this.player.popcorn.muted());
+};
+
+IriSP.Widgets.Controller.prototype.volumeUpdater = function() {
+    var _muted = this.player.popcorn.muted(),
+        _vol = this.player.popcorn.volume();
+    if (_vol === false) {
+        _vol = .5;
+    }
+    var _soundCtl = this.$.find(".Ldt-Ctrl-Sound");
+    _soundCtl.removeClass("Ldt-Ctrl-Sound-Mute Ldt-Ctrl-Sound-Half Ldt-Ctrl-Sound-Full");
+    if (_muted) {        
+        _soundCtl.attr("title", this.l10n.unmute)
+            .addClass("Ldt-Ctrl-Sound-Mute");    
+    } else {
+        _soundCtl.attr("title", this.l10n.mute)
+            .addClass(_vol < .5 ? "Ldt-Ctrl-Sound-Half" : "Ldt-Ctrl-Sound-Full" )
+    }
+    this.$volumeBar.slider("value", _muted ? 0 : 100 * _vol);
+};
+
+IriSP.Widgets.Controller.prototype.showSearchBlock = function() {
+    this.$searchBlock.show("blind", { direction: "horizontal"}, 100);
+    this.$searchInput.css('background-color','#fff');
+   
+    this.$searchInput.focus();
+    
+    // we need this variable because some widgets can find a match in
+    // their data while at the same time others 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.player.popcorn.trigger("IriSP.search.open");
+};
+
+IriSP.Widgets.Controller.prototype.hideSearchBlock = function() {
+    this._searchLastValue = this.$searchInput.val();
+    this.$searchInput.val('');
+    this.$searchBlock.hide("blind", { direction: "horizontal"}, 75);
+
+    this._positiveMatch = false;
+    
+    this.player.popcorn.trigger("IriSP.search.closed");
+};
+
+/** react to clicks on the search button */
+IriSP.Widgets.Controller.prototype.searchButtonHandler = function() {
+    if ( this.$searchBlock.is(":hidden") ) {
+        this.showSearchBlock();
+        this.$searchInput.val(this._searchLastValue);      
+        this.player.popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural.
+	} else {
+        this.hideSearchBlock();
+    }
+};
+
+/** this handler is called whenever the content of the search
+   field changes */
+IriSP.Widgets.Controller.prototype.searchHandler = function() {
+    this._searchLastValue = this.$searchInput.val();
+    this._positiveMatch = false;
+  
+    // do nothing if the search field is empty, instead of highlighting everything.
+    if (this._searchLastValue == "") {
+        this.player.popcorn.trigger("IriSP.search.cleared");
+        this.$searchInput.css('background-color','');
+    } else {
+        this.player.popcorn.trigger("IriSP.search", this._searchLastValue);
+    }
+};
+
+/**
+  handler for the IriSP.search.found message, which is sent by some views when they
+  highlight a match.
+*/
+IriSP.Widgets.Controller.prototype.searchMatch = function() {
+    this._positiveMatch = true;
+    this.$searchInput.css('background-color','#e1ffe1');
+};
+
+/** the same, except that no value could be found */
+IriSP.Widgets.Controller.prototype.searchNoMatch = function() {
+    if (this._positiveMatch !== true) {
+        this.$searchInput.css('background-color', "#d62e3a");
+    }
+};
+
+/** react to an IriSP.Player.triggeredSearch - that is, when
+    a widget ask the.Player to do a search on his behalf */
+IriSP.Widgets.Controller.prototype.triggeredSearch = function(searchString) {
+    this.showSearchBlock();
+    this.$searchInput.attr('value', searchString);      
+    this.player.popcorn.trigger("IriSP.search", searchString); // trigger the search to make it more natural.
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/HelloWorld.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,3 @@
+.Ldt-HelloWorld p {
+    text-align: center; font-size: 12px; margin: 2px 0; font-family: Helvetica, Arial, sans-serif;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/HelloWorld.js	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,33 @@
+/* Shows an example of a widget, with :
+ * - Use of source data
+ * - Use of templating
+ * - Use of internationalization
+ */
+
+IriSP.Widgets.HelloWorld = function(player, config) {
+    console.log("Calling IriSP.Widget's constructor from IriSP.HelloWorldWidget");
+    IriSP.Widgets.Widget.call(this, player, config);
+}
+
+IriSP.Widgets.HelloWorld.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.HelloWorld.prototype.defaults = {
+    text: "world"
+}
+
+IriSP.Widgets.HelloWorld.prototype.template =
+    '<div class="Ldt-HelloWorld"><p>{{l10n.Hello}} {{text}}</p><p>Looks like we have {{source.contents.annotation.length}} annotations in this feed</p></div>';
+
+IriSP.Widgets.HelloWorld.prototype.messages = {
+    "fr": {
+        "Hello" : "Bonjour,"
+    },
+    "en" : {
+        "Hello" : "Hello,"
+    }
+}
+
+IriSP.Widgets.HelloWorld.prototype.draw = function() {
+    this.renderTemplate();
+    console.log("HelloWorldWidget was drawn");
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Polemic.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,9 @@
+.Ldt-Polemic-Position {
+    background: #fc00ff;
+    position: absolute;
+    top: 0;
+    left: 0;
+    margin-left: -1px;
+    width: 2px;
+    height: 100%;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Polemic.js	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,207 @@
+IriSP.Widgets.Polemic = function(player, config) {
+    IriSP.Widgets.Widget.call(this, player, config);
+};
+
+IriSP.Widgets.Polemic.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Polemic.prototype.defaults = {
+    element_width : 5,
+    element_height : 5,
+    annotation_type : "tweet",
+    defaultcolor : "#585858",
+    foundcolor : "#fc00ff",
+    tags : [
+        {
+            "keywords" : [ "++" ],
+            "description" : "positif",
+            "color" : "#1D973D"
+        },
+        {
+            "keywords" : [ "--" ],
+            "description" : "negatif",
+            "color" : "#CE0A15"
+        },
+        {
+            "keywords" : [ "==" ],
+            "description" : "reference",
+            "color" : "#C5A62D"  
+        },
+        {
+            "keywords" : [ "??" ],
+            "description" : "question",
+            "color" : "#036AAE"
+        }
+    ],
+    requires : [
+        {
+            type: "Tooltip"
+        }
+    ]
+};
+
+IriSP.Widgets.Polemic.prototype.searchHandler = function(searchString) {
+    this.searchString = typeof searchString !== "undefined" ? searchString : '';
+    var _found = 0,
+        _re = IriSP.Model.regexpFromTextOrArray(searchString)
+        _this = this;
+    this.$tweets.each(function() {
+        var _el = IriSP.jQuery(this);
+        if (_this.searchString) {
+            if (_re.test(_el.attr("tweet-title"))) {
+                _el.css({
+                    "background" : _this.foundcolor,
+                    "opacity" : 1
+                });
+                _found++;
+            } else {
+                _el.css({
+                    "background" : _el.attr("polemic-color"),
+                    "opacity" : .5
+                });
+            }
+        } else {
+            _el.css({
+                "background" : _el.attr("polemic-color"),
+                "opacity" : 1
+            });
+        }
+    });
+    if (this.searchString) {
+        if (_found) {
+            this.player.popcorn.trigger("IriSP.search.matchFound");
+        } else {
+            this.player.popcorn.trigger("IriSP.search.noMatchFound");
+        }
+    }
+}
+
+IriSP.Widgets.Polemic.prototype.draw = function() {
+    
+    this.bindPopcorn("IriSP.search", "searchHandler");
+    this.bindPopcorn("IriSP.search.closed", "searchHandler");
+    this.bindPopcorn("IriSP.search.cleared", "searchHandler");
+    this.bindPopcorn("timeupdate", "onTimeupdate");
+    this.$zone = IriSP.jQuery('<div>');
+    this.$.append(this.$zone);
+    
+    var _slices = [],
+        _slice_count = Math.floor( this.width / this.element_width ),
+        _duration = this.source.getDuration(),
+        _max = 0,
+        _list = this.annotation_type ? this.source.getAnnotationsByTypeTitle(this.annotation_type) : this.source.getAnnotations();
+    
+    for (var _i = 0; _i < _slice_count; _i++) {
+        var _begin = new IriSP.Model.Time( _i * _duration / _slice_count ),
+            _end = new IriSP.Model.Time( ( _i + 1 ) * _duration / _slice_count ),
+            _count = 0,
+            _res = {
+                annotations : _list.filter(function(_annotation) {
+                    return _annotation.begin >= _begin && _annotation.end < _end;
+                }),
+                polemicStacks : []
+            }
+            
+        for (var _j = 0; _j < this.tags.length; _j++) {
+            var _polemic = _res.annotations.searchByDescription(this.tags[_j].keywords);
+            _count += _polemic.length;
+            _res.polemicStacks.push(_polemic);
+        }
+        for (var _j = 0; _j < this.tags.length; _j++) {
+            _res.annotations.removeElements(_res.polemicStacks[_j]);
+        }
+        _count += _res.annotations.length;
+        _max = Math.max(_max, _count);
+        _slices.push(_res);
+    }
+    this.height = (_max ? (_max + 2) * this.element_height : 0);
+    this.$zone.css({
+        width: this.width + "px",
+        height: this.height + "px",
+        position: "relative"
+    });
+    
+    this.$elapsed = IriSP.jQuery('<div>')
+        .css({
+            background: '#cccccc',
+            position: "absolute",
+            top: 0,
+            left: 0,
+            width: 0,
+            height: "100%"
+        });
+        
+    this.$zone.append(this.$elapsed);
+    
+    var _x = 0,
+        _this = this;
+    
+    function displayElement(_x, _y, _color, _id, _title) {
+        var _el = IriSP.jQuery('<div>')
+            .attr({
+                "tweet-title" : _title,
+                "pos-x" : Math.floor(_x + (_this.element_width - 1) / 2),
+                "pos-y" : _y,
+                "polemic-color" : _color,
+                "annotation-id" : _id
+            })
+            .css({
+                position: "absolute",
+                width: (_this.element_width-1) + "px",
+                height: _this.element_height + "px",
+                left: _x + "px",
+                top: _y + "px",
+                background: _color
+            })
+            .addClass("Ldt-Polemic-TweetDiv");
+        _this.$zone.append(_el);
+        return _el;
+    }
+    
+    IriSP._(_slices).forEach(function(_slice) {
+        var _y = _this.height;
+        _slice.annotations.forEach(function(_annotation) {
+            _y -= _this.element_height;
+            displayElement(_x, _y, _this.defaultcolor, _annotation.namespacedId.name, _annotation.title);
+        });
+        IriSP._(_slice.polemicStacks).forEach(function(_annotations, _j) {
+            var _color = _this.tags[_j].color;
+            _annotations.forEach(function(_annotation) {
+                _y -= _this.element_height;
+                displayElement(_x, _y, _color, _annotation.namespacedId.name, _annotation.title);
+            });
+        });
+        _x += _this.element_width;
+    });
+    
+    this.$tweets = this.$.find(".Ldt-Polemic-TweetDiv");
+    
+    this.$position = IriSP.jQuery('<div>').addClass("Ldt-Polemic-Position");
+        
+    this.$zone.append(this.$position);
+    
+    this.$tweets
+        .mouseover(function() {
+            var _el = IriSP.jQuery(this);
+            _this.tooltip.show(_el.attr("pos-x"), _el.attr("pos-y"), _el.attr("tweet-title"), _el.attr("polemic-color"));
+        })
+        .mouseout(function() {
+            _this.tooltip.hide();
+        });
+    
+    //TODO: Display Tweet in Tweet Widget on click
+    
+    this.$zone.click(function(_e) {
+        var _x = _e.pageX - _this.$zone.offset().left;
+        _this.player.popcorn.currentTime(_this.source.getDuration().getSeconds() * _x / _this.width);
+    });
+}
+
+IriSP.Widgets.Polemic.prototype.onTimeupdate = function() {
+    var _x = Math.floor( this.width * this.player.popcorn.currentTime() / this.source.getDuration().getSeconds());
+    this.$elapsed.css({
+        width:  _x + "px"
+    });
+    this.$position.css({
+        left: _x + "px"
+    })
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Segments.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,25 @@
+.Ldt-Segments-List {
+    width: 100%; height: 100%;
+}
+
+.Ldt-Segments-Segment {
+    position: absolute; height: 100%; opacity: .7; filter:alpha(opacity=70); margin-left: -1px; border-left: 1px solid #ffffff;
+}
+
+.Ldt-Segments-Segment.active {
+    opacity: 1; filter:alpha(opacity=100);
+}
+
+.Ldt-Segments-Segment.inactive {
+    opacity: .4; filter:alpha(opacity=40);
+}
+
+.Ldt-Segments-Position {
+    background: #fc00ff;
+    position: absolute;
+    top: 0;
+    left: 0;
+    margin-left: -1px;
+    width: 2px;
+    height: 100%;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Segments.js	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,61 @@
+IriSP.Widgets.Segments = function(player, config) {
+    IriSP.Widgets.Widget.call(this, player, config);
+};
+
+IriSP.Widgets.Segments.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Segments.prototype.defaults = {
+    annotation_type : "chap",
+    colors: ["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"],
+    requires : [
+        {
+            type: "Tooltip"
+        }
+    ],
+    height: 10
+};
+
+IriSP.Widgets.Segments.prototype.template =
+    '<div class="Ldt-Segments-List">{{#segments}}'
+    + '<div class="Ldt-Segments-Segment" segment-id="{{id}}" segment-text="{{text}}" segment-color="{{color}}" center-pos="{{center}}" style="left:{{left}}px; width:{{width}}px; background:{{color}}"></div>'
+    + '{{/segments}}</div>'
+    + '<div class="Ldt-Segments-Position"></div>';
+
+IriSP.Widgets.Segments.prototype.draw = function() {
+    var _list = this.annotation_type ? this.source.getAnnotationsByTypeTitle(this.annotation_type) : this.source.getAnnotations(),
+        _this = this,
+        _scale = this.width / this.source.getDuration();
+    this.$.css({
+        width : this.width + "px",
+        height : this.height + "px"
+    });
+    this.$.append(Mustache.to_html(this.template, {
+        segments : _list.map(function(_annotation, _k) {
+            var _left = _annotation.begin * _scale,
+                _width = ( _annotation.end - _annotation.begin ) * _scale,
+                _center = _left + _width / 2;
+            return {
+                text : _annotation.title + ( _annotation.description ? '<br />' + _annotation.description.replace(/(^.{120,140})[\s].+$/,'$1&hellip;') : ''),
+                color : ( typeof _annotation.color !== "undefined" && _annotation.color ? _annotation.color : _this.colors[_k % _this.colors.length] ),
+                left : Math.floor( _left ),
+                width : Math.floor( _width ),
+                center : Math.floor( _center ),
+                id : _annotation.namespacedId.name
+            }
+        })
+    }));
+    var _seglist = this.$.find('.Ldt-Segments-Segment');
+    
+    _seglist.mouseover(function() {
+        var _el = IriSP.jQuery(this);
+        _seglist.removeClass("active").addClass("inactive");
+        _this.tooltip.show( _el.attr("center-pos"), 0, _el.attr("segment-text"), _el.attr("segment-color"));
+        _el.removeClass("inactive").addClass("active");
+    }).mouseout(function() {
+        _seglist.removeClass("inactive active");
+    });
+}
+
+IriSP.Widgets.Segments.prototype.searchHandler = function(searchString) {
+   
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Slider.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,14 @@
+/* Slider Widget */
+
+.Ldt-Slider {
+    border: none; border-radius: 0; padding: 0; margin: 0; background: #B6B8B8;
+}
+
+.Ldt-Slider .ui-slider-handle {
+    border-radius: 8px; top: -2px; background: #fc00ff; border: 1px solid #ffffff;
+}
+
+.Ldt-Slider .ui-slider-range {
+    background: #747474;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Slider.js	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,111 @@
+/*
+ The Slider Widget fits right under the video
+ */
+
+IriSP.Widgets.Slider = function(player, config) {
+    IriSP.Widgets.Widget.call(this, player, config);
+    this.bindPopcorn("timeupdate","onTimeupdate");
+    this.bindPopcorn("IriSP.PlayerWidget.MouseOver","onMouseover");
+    this.bindPopcorn("IriSP.PlayerWidget.MouseOut","onMouseout");
+};
+
+IriSP.Widgets.Slider.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Slider.prototype.defaults = {
+    minimized_height : 4,
+    maximized_height : 10,
+    minimize_timeout : 1500 // time before minimizing slider after mouseout
+};
+
+IriSP.Widgets.Slider.prototype.draw = function() {
+    
+    this.$slider = IriSP.jQuery('<div>')
+        .addClass("Ldt-Slider")
+        .css(this.calculateSliderCss(this.minimized_height));
+    
+    this.$.append(this.$slider);
+    
+    var _this = this;
+    
+    this.$slider.slider({
+        range: "min",
+        value: 0,
+        min: 0,
+        max: this.source.getDuration().getSeconds(),
+        slide: function(event, ui) {
+            _this.player.popcorn.currentTime(ui.value);
+        }
+    });
+    
+    this.$handle = this.$slider.find('.ui-slider-handle');
+    
+    this.$handle.css(this.calculateHandleCss(this.minimized_height));
+    
+    this.$
+        .mouseover(this.functionWrapper("onMouseover"))
+        .mouseout(this.functionWrapper("onMouseout"));
+    
+    this.maximized = false;
+    this.timeoutId = false;
+};
+
+IriSP.Widgets.Slider.prototype.onTimeupdate = function() {
+    this.$slider.slider("value",this.player.popcorn.currentTime());
+}
+
+IriSP.Widgets.Slider.prototype.onMouseover = function() {
+    if (this.timeoutId) {
+        window.clearTimeout(this.timeoutId);
+        this.timeoutId = false;
+    }
+    if (!this.maximized) {
+       this.animateToHeight(this.maximized_height);
+       this.maximized = true;
+    }
+}
+
+IriSP.Widgets.Slider.prototype.onMouseout = function() {
+    if (this.timeoutId) {
+        window.clearTimeout(this.timeoutId);
+        this.timeoutId = false;
+    }
+    var _this = this;
+    this.timeoutId = window.setTimeout(function() {
+        if (_this.maximized) {
+            _this.animateToHeight(_this.minimized_height);
+            _this.maximized = false;
+        }
+        _this.timeoutId = false;
+    }, this.minimize_timeout);
+    
+}
+
+IriSP.Widgets.Slider.prototype.animateToHeight = function(_height) {
+    this.$slider.stop().animate(
+        this.calculateSliderCss(_height),
+        500,
+        function() {
+            IriSP.jQuery(this).css("overflow","visible");
+        });
+    this.$handle.stop().animate(
+        this.calculateHandleCss(_height),
+        500,
+        function() {
+            IriSP.jQuery(this).css("overflow","visible");
+        });
+}
+
+IriSP.Widgets.Slider.prototype.calculateSliderCss = function(_size) {
+    return {
+        height: _size + "px",
+        "margin-top": (this.minimized_height - _size) + "px"
+    };
+}
+
+IriSP.Widgets.Slider.prototype.calculateHandleCss = function(_size) {
+    return {
+        height: (2 + _size) + "px",
+        width: (2 + _size) + "px",
+        "margin-left": -Math.ceil(2 + _size / 2) + "px" 
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Sparkline.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,3 @@
+/*
+ * 
+ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Sparkline.js	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,85 @@
+IriSP.Widgets.Sparkline = function(player, config) {
+    IriSP.Widgets.Widget.call(this, player, config);
+    //this.bindPopcorn("timeupdate", "onTimeupdate");
+};
+
+IriSP.Widgets.Sparkline.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Sparkline.prototype.defaults = {
+   lineColor : "#7492b4",
+   fillColor : "#aeaeb8",
+   lineWidth : 2,
+   slice_count : 20,
+   height : 50,
+   margin : 5
+};
+
+IriSP.Widgets.Sparkline.prototype.draw = function() {
+    var _slices = [],
+        _duration = this.source.getDuration(),
+        _max = 0,
+        _list = this.annotation_type ? this.source.getAnnotationsByTypeTitle(this.annotation_type) : this.source.getAnnotations();
+    
+    for (var _i = 0; _i < this.slice_count; _i++) {
+        var _begin = new IriSP.Model.Time(_i*_duration/this.slice_count),
+            _end = new IriSP.Model.Time((_i+1)*_duration/this.slice_count),
+            _annotations = _list.filter(function(_annotation) {
+                return _annotation.begin >= _begin && _annotation.end < _end;
+            }).length;
+        _max = Math.max(_max, _annotations);
+        _slices.push(_annotations);
+    }
+    if (!_max) {
+        return;
+    }
+    this.paper = new Raphael(this.$[0], this.width, this.height);
+    var _scale = (this.height - this.margin) / _max,
+        _width = this.width / this.slice_count,
+        _this = this,
+        _y = IriSP._(_slices).map(function(_v) {
+            return _this.margin + _this.height - (_scale * _v);
+        }),
+        _d = IriSP._(_y).reduce(function(_memo, _v, _k) {
+               return _memo + ( _k
+                   ? 'C' + (_k * _width) + ' ' + _y[_k - 1] + ' ' + (_k * _width) + ' ' + _v + ' ' + ((_k + .5) * _width) + ' ' + _v
+                   : 'M0 ' + _v + 'L' + (.5*_width) + ' ' + _v )
+            },'') + 'L' + this.width + ' ' + _y[_y.length - 1],
+        _d2 = _d + 'L' + this.width + ' ' + this.height + 'L0 ' + this.height;
+    
+    this.paper.path(_d2).attr({
+        "stroke" : "none",
+        "fill" : this.fillColor
+    });
+         
+    this.paper.path(_d).attr({
+        "fill" : "none",
+        "stroke" : this.lineColor,
+        "stroke-width" : this.lineWidth
+    });
+    
+    this.rectangleProgress = this.paper.rect(0,0,0,this.height)
+        .attr({
+            "stroke" : "none",
+            "fill" : "#808080",
+            "opacity" : .3
+        });
+        
+    this.ligneProgress = this.paper.path("M0 0L0 "+this.height).attr({"stroke":"#ff00ff", "line-width" : 2});
+   
+    this.$.click(function(_e) {
+        var _x = _e.pageX - _this.$.offset().left;
+        _this.player.popcorn.currentTime(_this.source.getDuration().getSeconds() * _x / _this.width);
+    });
+    
+    this.bindPopcorn("timeupdate","onTimeupdate");
+}
+
+IriSP.Widgets.Sparkline.prototype.onTimeupdate = function() {
+    var _x = Math.floor( this.width * this.player.popcorn.currentTime() / this.source.getDuration().getSeconds());
+    this.rectangleProgress.attr({
+        "width" : _x
+    });
+    this.ligneProgress.attr({
+        "path" : "M" + _x + " 0L" + _x + " " + this.height
+    });
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Tooltip.css	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,25 @@
+/* ToolTip Widget */
+
+.Ldt-Tooltip {
+  position: absolute;
+  padding : 3px;
+  z-index: 10000000000;
+  max-width: 200px;
+  background: transparent url("img/white_arrow_long.png");
+  font-size: 12px;
+  height: 115px;
+  width: 180px;
+  padding: 15px 15px 20px;
+  color: black;
+  font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif";
+  overflow:hidden;
+}
+
+.Ldt-Tooltip-Color {
+    float: left; margin: 2px 4px 2px 0; width: 10px; height: 10px;
+}
+
+.Ldt-Tooltip img {
+    max-width: 140px; max-height: 70px; margin: 0 20px;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Tooltip.js	Mon Apr 23 19:11:08 2012 +0200
@@ -0,0 +1,42 @@
+/* this widget displays a small tooltip */
+IriSP.Widgets.Tooltip = function(Popcorn, config, Serializer) {
+    IriSP.Widgets.Widget.call(this, Popcorn, config, Serializer);
+};
+
+IriSP.Widgets.Tooltip.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Tooltip.prototype.template = '<div class="Ldt-Tooltip"><div class="Ldt-Tooltip-Color"></div><div class="Ldt-Tooltip-Text"></div></div>';
+
+IriSP.Widgets.Tooltip.prototype.draw = function() {
+    _this = this;
+    this.$.html(this.template);
+    this.$.parent().css({
+        "position" : "relative"
+    });
+    this.$tip = this.$.find(".Ldt-Tooltip");
+    this.$.mouseover(function() {
+        _this.$tip.hide();
+    });
+    this.hide();
+};
+
+IriSP.Widgets.Tooltip.prototype.show = function(x, y, text, color) {
+    
+    if (typeof color !== "undefined") {
+        this.$.find(".Ldt-Tooltip-Color").show().css("background-color", color);
+    } else {
+        this.$.find(".Ldt-Tooltip-Color").hide();
+    }
+    
+    this.$.find(".Ldt-Tooltip-Text").html(text);
+
+    this.$tip.show();
+    this.$tip.css({
+        "left" : Math.floor(x - this.$tip.outerWidth() / 2) + "px",
+        "top" : Math.floor(y - this.$tip.outerHeight() - 5) + "px"
+    });
+};
+
+IriSP.Widgets.Tooltip.prototype.hide = function() {
+    this.$tip.hide();
+};
Binary file src/widgets/img/player-sprites.png has changed
Binary file src/widgets/img/player_gradient.png has changed
Binary file src/widgets/img/white_arrow_long.png has changed
--- a/test/integration/polemic.htm	Fri Apr 20 19:13:11 2012 +0200
+++ b/test/integration/polemic.htm	Mon Apr 23 19:11:08 2012 +0200
@@ -15,13 +15,14 @@
   
  <!-- START Integration  ###################################### -->
  <!-- SIMPLE PLAYER EXPERIMENTATION -->
-  <script type="text/javascript" src="../../build/LdtPlayer-release.js" type="text/javascript"></script>   
+  <script type="text/javascript" src="../../build/LdtPlayer-core.js" type="text/javascript"></script>   
   
   <div id="video"></div>
   <div id="LdtPlayer"></div>
   
   <script  type="text/javascript">
   IriSP.libFiles.defaultDir = "/metadataplayer/src/js/libs/";
+  IriSP.widgetsDir = "/metadataplayer/src/widgets"
 IriSP.jwplayer_swf_path = "../libs/player.swf";
     var _metadata = {
         url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/13b0aa52-336b-11e0-b233-00145ea49a02?callback=?',
@@ -75,19 +76,25 @@
             excludeWords: ['#museoweb']},, */
 //            {type: "TraceWidget"}
                 {
-                    type: "SliderWidget"
+                    type: "Sparkline"
                 },
                 {
-                    type: "PlayerWidget"
+                    type: "Slider"
+                },
+                {
+                    type: "Controller"
                 },
                 {
-                    type: "PolemicWidget"
+                    type: "Polemic"
                 },
                 {
-                    type: "HelloWorldWidget"
+                    type: "Segments"
                 },
                 {
-                    type: "AnnotationsListWidget",
+                    type: "HelloWorld"
+                },
+                {
+                    type: "AnnotationsList",
                     ajax_url : "http://ldt.iri.centrepompidou.fr/ldtplatform/api/ldt/segments/{{media}}/{{begin}}/{{end}}?callback=?", 
                     foreign_url : "http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/{{media}}/{{project}}/{{annotationType}}#id={{annotation}}",
                     annotation_type : "tweet",