Some improvements: Hashtags can be used, links are now clickable, ....
authorveltr
Fri, 25 Jan 2013 18:16:29 +0100
changeset 988 eefd336335f9
parent 987 7b65bf78873a
child 989 458e9754d1cf
Some improvements: Hashtags can be used, links are now clickable, ....
assets/psd/tooltip.psd
src/css/LdtPlayer-core.css
src/js/model.js
src/js/utils.js
src/js/widgets.js
src/widgets/Annotation.css
src/widgets/Annotation.js
src/widgets/AnnotationsList.css
src/widgets/AnnotationsList.js
src/widgets/CreateAnnotation.js
src/widgets/HtmlMashupPlayer.js
src/widgets/MultiSegments.js
src/widgets/Slideshare.js
src/widgets/Tagger.css
src/widgets/Tagger.js
src/widgets/Tweet.js
test/jwplayer.htm
test/mashup/moon.htm
test/mp4video.htm
test/test.css
Binary file assets/psd/tooltip.psd has changed
--- a/src/css/LdtPlayer-core.css	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/css/LdtPlayer-core.css	Fri Jan 25 18:16:29 2013 +0100
@@ -12,4 +12,8 @@
 /*    font-family: Arial, Helvetica, sans-serif; */
     color: black;
     font-size: 12px;
-}
\ No newline at end of file
+}
+
+.Ldt-Highlight {
+    background: #ffa0fc;
+}
--- a/src/js/model.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/js/model.js	Fri Jan 25 18:16:29 2013 +0100
@@ -19,11 +19,12 @@
     var uidbase = rand16(8) + "-" + rand16(4) + "-", uidincrement = Math.floor(Math.random()*0x10000);
     
     var charsub = [
-        [ 'a', 'á', 'à', 'â', 'ä' ],
-        [ 'c', 'ç' ],
-        [ 'e', 'é', 'è', 'ê', 'ë' ],
-        [ 'i', 'í', 'ì', 'î', 'ï' ],
-        [ 'o', 'ó', 'ò', 'ô', 'ö' ]
+        '[aáàâä]',
+        '[cç]',
+        '[eéèêë]',
+        '[iíìîï]',
+        '[oóòôö]',
+        '[uùûü]'
     ];
     
     var removeChars = [
@@ -71,10 +72,7 @@
             remrx = new RegExp(remsrc,"gm"),
             txt = _text.toLowerCase().replace(remrx,"")
             res = [],
-            charsrc = ns._(charsub).map(function(c) {
-                return "(" + c.join("|") + ")";
-            }),
-            charsrx = ns._(charsrc).map(function(c) {
+            charsrx = ns._(charsub).map(function(c) {
                 return new RegExp(c);
             }),
             src = "";
@@ -83,7 +81,7 @@
                 src += remsrc + "*";
             }
             var l = txt[j];
-            ns._(charsrc).each(function(v, k) {
+            ns._(charsub).each(function(v, k) {
                 l = l.replace(charsrx[k], v);
             });
             src += l;
@@ -223,7 +221,7 @@
  */
 Model.List.prototype.searchByTitle = function(_text, _iexact) {
     var _iexact = _iexact || false,
-        _rgxp = Model.regexpFromTextOrArray(_text, true);
+        _rgxp = Model.regexpFromTextOrArray(_text, true, _iexact);
     return this.filter(function(_element) {
         return _rgxp.test(_element.title);
     });
@@ -231,7 +229,7 @@
 
 Model.List.prototype.searchByDescription = function(_text, _iexact) {
     var _iexact = _iexact || false,
-        _rgxp = Model.regexpFromTextOrArray(_text, true);
+        _rgxp = Model.regexpFromTextOrArray(_text, true, _iexact);
     return this.filter(function(_element) {
         return _rgxp.test(_element.description);
     });
@@ -239,7 +237,7 @@
 
 Model.List.prototype.searchByTextFields = function(_text, _iexact) {
     var _iexact = _iexact || false,
-        _rgxp =  Model.regexpFromTextOrArray(_text, true);
+        _rgxp =  Model.regexpFromTextOrArray(_text, true, _iexact);
     return this.filter(function(_element) {
         var keywords = (_element.keywords || _element.getTagTexts() || []).join(", ");
         return _rgxp.test(_element.description) || _rgxp.test(_element.title) || _rgxp.test(keywords);
@@ -819,17 +817,6 @@
 
 Model.Mashup.prototype = new Model.Playable();
 
-Model.Mashup.prototype.checkLoaded = function() {
-    var loaded = !!this.segments.length;
-    this.getMedias().forEach(function(_m) {
-        loaded = loaded && _m.loaded;
-    });
-    this.loaded = loaded;
-    if (loaded) {
-        this.trigger("loadedmetadata");
-    }
-}
-
 Model.Mashup.prototype.updateTimes = function() {
     var _time = 0;
     this.segments.forEach(function(_segment) {
@@ -1197,3 +1184,6 @@
 return Model;
 
 })(IriSP);
+
+/* END model.js */
+
--- a/src/js/utils.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/js/utils.js	Fri Jan 25 18:16:29 2013 +0100
@@ -29,6 +29,79 @@
     }
 }
 
+IriSP.textFieldHtml = function(_text, _regexp, _extend) {
+    var list = [],
+        positions = [],
+        text = _text.replace(/(^\s+|\s+$)/g,'');
+    
+    function addToList(_rx, _startHtml, _endHtml) {
+        while(true) {
+            var result = _rx.exec(text);
+            if (!result) {
+                break;
+            }
+            var end = _rx.lastIndex,
+                start = result.index;
+            list.push({
+                start: start,
+                end: end,
+                startHtml: (typeof _startHtml === "function" ? _startHtml(result) : _startHtml),
+                endHtml: (typeof _endHtml === "function" ? _endHtml(result) : _endHtml)
+            });
+            positions.push(start);
+            positions.push(end);
+        }
+    }
+    
+    if (_regexp) {
+        addToList(_regexp, '<span class="Ldt-Highlight">', '</span>');
+    }
+    
+    addToList(/(https?:\/\/)?\w+\.\w+\S+/gm, function(matches) {
+        return '<a href="' + (matches[1] ? '' : 'http://') + matches[0] + '" target="_blank">'
+    }, '</a>');
+    addToList(/@([\d\w]{1,15})/gm, function(matches) {
+        return '<a href="http://twitter.com/' + matches[1] + '" target="_blank">'
+    }, '</a>');
+    addToList(/\*[^*]+\*/gm, '<b>', '</b>');
+    addToList(/[\n\r]+/gm, '', '<br />');
+    
+    IriSP._(_extend).each(function(x) {
+        addToList.apply(null, x);
+    });
+    
+    positions = IriSP._(positions)
+        .chain()
+        .uniq()
+        .sortBy(function(p) { return parseInt(p) })
+        .value();
+    
+    var res = "", lastIndex = 0;
+    
+    for (var i = 0; i < positions.length; i++) {
+        var pos = positions[i];
+        res += text.substring(lastIndex, pos);
+        for (var j = list.length - 1; j >= 0; j--) {
+            var item = list[j];
+            if (item.start < pos && item.end >= pos) {
+                res += item.endHtml;
+            }
+        }
+        for (var j = 0; j < list.length; j++) {
+            var item = list[j];
+            if (item.start <= pos && item.end > pos) {
+                res += item.startHtml;
+            }
+        }
+        lastIndex = pos;
+    }
+    
+    res += text.substring(lastIndex);
+    
+    return res;
+    
+}
+
 IriSP.log = function() {
     if (typeof console !== "undefined" && typeof IriSP.logging !== "undefined" && IriSP.logging) {
         console.log.apply(console, arguments);
--- a/src/js/widgets.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/js/widgets.js	Fri Jan 25 18:16:29 2013 +0100
@@ -35,8 +35,10 @@
        _this[_key] = _value;
     });
     
+    this.$ = IriSP.jQuery('#' + this.container);
+    
     if (typeof this.width === "undefined") {
-        this.width = player.config.width;
+        this.width = this.$.width();
     }
     
     /* Setting this.player at the end in case it's been overriden
@@ -45,7 +47,6 @@
     this.player = player;
     
     /* Adding classes and html attributes */
-    this.$ = IriSP.jQuery('#' + this.container);
     this.$.addClass("Ldt-TraceMe Ldt-Widget").attr("widget-type", _type);
     
     this.l10n = (
--- a/src/widgets/Annotation.css	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/widgets/Annotation.css	Fri Jan 25 18:16:29 2013 +0100
@@ -6,10 +6,6 @@
     margin: 0;
 }
 
-.Ldt-Annotation-Highlight {
-    background: #ffa0fc;
-}
-
 .Ldt-Annotation-Widget.Ldt-Annotation-ShowTop {
     border-top-style: solid;
     padding-top: 1px;
--- a/src/widgets/Annotation.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/widgets/Annotation.js	Fri Jan 25 18:16:29 2013 +0100
@@ -76,17 +76,12 @@
             return;
         }
         var title = currentAnnotation.title,
-            description = currentAnnotation.description.replace(/(^\s+|\s+$)/g,'');
-        if (currentAnnotation.found) {
-            var rgxp = _this.source.getAnnotations().regexp || /^$/,
-                repl = '<span class="Ldt-Annotation-Highlight">$1</span>';
-            title = title.replace(rgxp,repl);
-            description = description.replace(rgxp,repl).replace(/[\n\r]+/gm,'<br />');
-        }
-        _this.$.find(".Ldt-Annotation-Title").html(title || "(" + _this.l10n.untitled + ")");
+            description = currentAnnotation.description.replace(/(^\s+|\s+$)/g,''),
+            rx = (currentAnnotation.found ? (_this.source.getAnnotations().regexp || false) : false);
+        _this.$.find(".Ldt-Annotation-Title").html(IriSP.textFieldHtml(title,rx)  || "(" + _this.l10n.untitled + ")");
         if (description) {
             _this.$.find(".Ldt-Annotation-Description-Block").removeClass("Ldt-Annotation-EmptyBlock");
-            _this.$.find(".Ldt-Annotation-Description").html(description);
+            _this.$.find(".Ldt-Annotation-Description").html(IriSP.textFieldHtml(description,rx));
         } else {
             _this.$.find(".Ldt-Annotation-Description-Block").addClass("Ldt-Annotation-EmptyBlock");
         }
@@ -156,7 +151,7 @@
         this.insertSubwidget(this.$.find(".Ldt-Annotation-Social"), { type: "Social" }, "socialWidget");
     }
     
-    this.insertSubwidget(this.$.find(".Ldt-Annotation-Arrow"), { type: "Arrow" }, "arrow");
+    this.insertSubwidget(this.$.find(".Ldt-Annotation-Arrow"), { type: "Arrow", width: this.width }, "arrow");
     this.onMediaEvent("timeupdate",timeupdate);
     this.onMdpEvent("Annotation.hide","hide");
     this.onMdpEvent("Annotation.show","show");
--- a/src/widgets/AnnotationsList.css	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/widgets/AnnotationsList.css	Fri Jan 25 18:16:29 2013 +0100
@@ -28,9 +28,6 @@
 .Ldt-AnnotationsList-li.selected {
     background-image: url(img/pinstripe-grey.png);
 }
-.Ldt-AnnotationsList-highlight {
-    background: #FFA0FC;
-}
 .Ldt-AnnotationsList-ThumbContainer {
     float: left;
     width: 80px;
@@ -57,14 +54,25 @@
     margin: 2px 2px 0 82px;
     font-weight: bold;
 }
-h3.Ldt-AnnotationsList-Title a {
+
+.Ldt-AnnotationsList-Title a {
     color: #0068c4;
 }
+
 p.Ldt-AnnotationsList-Description {
     margin: 2px 0 2px 82px;
     font-size: 12px;
     color: #333333;
 }
+
+.Ldt-AnnotationsList-Description a {
+    color: #0068c4;
+}
+
+.Ldt-AnnotationsList-Description a:hover {
+    text-decoration: underline; color: #800000;
+}
+
 ul.Ldt-AnnotationsList-Tags {
     list-style: none;
     padding: 0;
--- a/src/widgets/AnnotationsList.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/widgets/AnnotationsList.js	Fri Jan 25 18:16:29 2013 +0100
@@ -71,9 +71,9 @@
     + '</div>'
     + '<div class="Ldt-AnnotationsList-Duration">{{begin}} - {{end}}</div>'
     + '<h3 class="Ldt-AnnotationsList-Title">'
-    + '<a href="{{url}}">{{title}}</a>'
+    + '<a href="{{url}}">{{{title}}}</a>'
     + '</h3>'
-    + '<p class="Ldt-AnnotationsList-Description">{{description}}</p>'
+    + '<p class="Ldt-AnnotationsList-Description">{{{description}}}</p>'
     + '{{#tags.length}}'
     + '<ul class="Ldt-AnnotationsList-Tags">'
     + '{{#tags}}'
@@ -202,8 +202,8 @@
             var _data = {
                 id : _annotation.id,
                 media_id : _annotation.getMedia().id,
-                title : _title,
-                description : _description,
+                title : IriSP.textFieldHtml(_title),
+                description : IriSP.textFieldHtml(_description),
                 begin : _annotation.begin.toString(),
                 end : _annotation.end.toString(),
                 thumbnail : typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail ? _annotation.thumbnail : _this.default_thumbnail,
@@ -265,10 +265,11 @@
         });
         
         if (this.source.getAnnotations().searching) {
+            var rx = _this.source.getAnnotations().regexp || false;
             this.$.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description").each(function() {
                 var _$ = IriSP.jQuery(this);
-                _$.html(_$.text().replace(/(^\s+|\s+$)/g,'').replace(_this.source.getAnnotations().regexp, '<span class="Ldt-AnnotationsList-highlight">$1</span>'))
-            })
+                _$.html(IriSP.textFieldHtml(_$.text(), rx));
+            });
         }
     }
     
--- a/src/widgets/CreateAnnotation.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/widgets/CreateAnnotation.js	Fri Jan 25 18:16:29 2013 +0100
@@ -149,7 +149,7 @@
     if (this.tag_titles && !this.tags) {
         this.tags = IriSP._(this.tag_titles).map(function(_tag_title) {
             var _tag,
-                _tags = _this.source.getTags().searchByTitle(_tag_title);
+                _tags = _this.source.getTags().searchByTitle(_tag_title, true);
             if (_tags.length) {
                 _tag = _tags[0];
             } else {
@@ -370,10 +370,11 @@
         this.recorder.stopRecord();
     }
     
-    var _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* Création d'une liste d'annotations contenant une annotation afin de l'envoyer au serveur */
+    var _this = this,
+        _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* Création d'une liste d'annotations contenant une annotation afin de l'envoyer au serveur */
         _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}), /* Création d'un objet source utilisant un sérialiseur spécifique pour l'export */
         _annotation = new IriSP.Model.Annotation(false, _export), /* Création d'une annotation dans cette source avec un ID généré à la volée (param. false) */
-        _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type), /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */
+        _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */
         _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, _export)), /* Si le Type d'Annotation n'existe pas, il est créé à la volée */
         _url = Mustache.to_html(this.api_endpoint_template, {id: this.source.projectId}); /* Génération de l'URL à laquelle l'annotation doit être envoyée, qui doit inclure l'ID du projet */
     
@@ -400,8 +401,24 @@
     }
     _annotation.created = new Date(); /* Date de création de l'annotation */
     _annotation.description = this.$.find(".Ldt-CreateAnnotation-Description").val(); /* Champ description */
-    _annotation.setTags(this.$.find(".Ldt-CreateAnnotation-TagLi.selected")
-        .map(function() { return IriSP.jQuery(this).attr("tag-id")})); /*Liste des ids de tags */
+   
+    var tagIds = this.$.find(".Ldt-CreateAnnotation-TagLi.selected")
+        .map(function() { return IriSP.jQuery(this).attr("tag-id")});
+    
+    IriSP._(_annotation.description.match(/#[\w\d]+/g)).each(function(_tt) {
+        var _tag,
+            _tag_title = _tt.replace(/^#/,'')
+            _tags = _this.source.getTags().searchByTitle(_tag_title, true);
+        if (_tags.length) {
+            _tag = _tags[0];
+        } else {
+            _tag = new IriSP.Model.Tag(false, _this.source);
+            _tag.title = _tag_title;
+        }
+        tagIds.push(_tag.id);
+    })
+   
+    _annotation.setTags(IriSP._(tagIds).uniq()); /*Liste des ids de tags */
     if (this.audio_url) {
         _annotation.audio = {
             src: "mic",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/HtmlMashupPlayer.js	Fri Jan 25 18:16:29 2013 +0100
@@ -0,0 +1,345 @@
+IriSP.Widgets.HtmlMashupPlayer = function(player, config) {
+    IriSP.Widgets.Widget.call(this, player, config);
+};
+
+IriSP.Widgets.HtmlMashupPlayer.prototype = new IriSP.Widgets.Widget();
+
+
+IriSP.Widgets.HtmlMashupPlayer.prototype.defaults = {
+    aspect_ratio: 14/9,
+    background: "#333333"
+}
+
+IriSP.Widgets.HtmlMashupPlayer.prototype.draw = function() {
+    
+    if (!this.height && this.aspect_ratio) {
+        this.height = this.width / this.aspect_ratio;
+        this.$.css("height", this.height);
+    }
+    
+    if (this.background) {
+        this.$.css("background", this.background);
+    }
+    
+    var mashup = this.media,
+        sel = this.$,
+        width = this.width,
+        height = this.height,
+        url_transform = this.url_transform;
+    
+    mashup.currentMedia = null;
+    mashup.currentAnnotation = null;
+    mashup.seeking = false;
+    var mashupSegmentBegin,
+        mashupSegmentEnd,
+        mashupTimecode = 0,
+ //       seekdiv = $(".video-wait"),
+        mashupTimedelta;
+        
+/*    
+    function showSeek() {
+        if (currentMedia.seeking) {
+            seekdiv.show();
+        }
+    }
+*/
+
+    function changeCurrentAnnotation() {
+        if (mashupTimecode >= mashup.duration) {
+            if (!mashup.paused) {
+                mashup.paused = true;
+                mashup.trigger("pause");
+            }
+            mashupTimecode = 0;
+        }
+        var _annotation = mashup.getAnnotationAtTime( mashupTimecode );
+        if (typeof _annotation === "undefined") {
+            if (mashup.currentMedia) {
+                mashup.currentMedia.pause();
+                if (!mashup.paused) {
+                    mashup.paused = true;
+                    mashup.trigger("pause");
+                }
+            }
+            return;
+        }
+        mashup.currentAnnotation = _annotation;
+        mashupSegmentBegin = mashup.currentAnnotation.annotation.begin.milliseconds;
+        mashupSegmentEnd = mashup.currentAnnotation.annotation.end.milliseconds;
+        mashupTimedelta = mashupSegmentBegin - mashup.currentAnnotation.begin.milliseconds;
+        mashup.currentMedia = mashup.currentAnnotation.getMedia();
+        mashup.getMedias().forEach(function(_media) {
+            if (_media !== mashup.currentMedia) {
+                _media.hide();
+                _media.pause();
+            } else {
+                _media.show();
+            }
+        });
+        
+        mashup.currentMedia.setCurrentTime( mashupTimecode + mashupTimedelta);
+        mashup.currentMedia.seeking = true;
+        
+        if (!mashup.paused) {
+            mashup.currentMedia.play();
+            mashup.seeking = true;
+//            setTimeout(showSeek,200);
+        }
+        mashup.trigger("timeupdate", new IriSP.Model.Time(mashupTimecode));
+
+    }
+    
+    mashup.getMedias().forEach(addMedia);
+    changeCurrentAnnotation();
+    mashup.trigger("loadedmetadata");
+    
+    function addMedia(media) {
+        if (media.has_player) {
+            return;
+        }
+        media.has_player = true;
+        var videourl = media.video;
+        if (typeof url_transform === "function") {
+            videourl = url_transform(media.video);
+        }
+        var videoid = "video_" + media.id,
+            videoElement;
+        
+        media.show = function() {
+            
+            if (document.getElementById(videoid)) {
+                return;
+            }
+            
+            media.loaded = false;
+            media.paused = true;
+            var videoSelector = $('<video>');
+            
+            videoSelector.attr({
+                id : videoid,
+                width : width,
+                height : height
+            }).css({
+                width: width,
+                height: height
+            });
+            
+            if (typeof videourl === "string") {
+                videoSelector.attr( "src", videourl );
+            } else {
+                for (var i = 0; i < videourl.length; i++) {
+                    var _srcNode = IriSP.jQuery('<source>');
+                    _srcNode.attr({
+                        src: videourl[i].src,
+                        type: videourl[i].type
+                    });
+                    videoSelector.append(_srcNode);
+                }
+            }
+            
+            sel.append(videoSelector);
+            
+            videoElement = videoSelector[0];
+            
+            // Binding DOM events to media
+            
+            function getVolume() {
+                media.muted = videoElement.muted;
+                media.volume = videoElement.volume;
+            }
+            
+            videoSelector.on("loadedmetadata", function() {
+                getVolume();
+                media.loaded = true;
+                media.trigger("loadedmetadata");
+                media.trigger("volumechange");
+            })
+            
+            videoSelector.on("timeupdate", function() {
+                media.trigger("timeupdate", new IriSP.Model.Time(1000*videoElement.currentTime));
+            });
+            
+            videoSelector.on("volumechange", function() {
+                getVolume();
+                media.trigger("volumechange");
+            })
+            
+            videoSelector.on("play", function() {
+                media.trigger("play");
+            });
+            
+            videoSelector.on("pause", function() {
+                media.trigger("pause");
+            });
+            
+            videoSelector.on("seeking", function() {
+                media.trigger("seeking");
+            });
+            
+            videoSelector.on("seeked", function() {
+                media.trigger("seeked");
+            });
+        }
+        
+        media.hide = function() {
+            videoElement = undefined;
+            sel.find("#" + videoid).remove();
+        }
+        
+        // Binding functions to Media Element Functions
+        
+        var deferredTime = undefined,
+            deferredPlayPause = undefined;
+        
+        media.on("setcurrenttime", function(_milliseconds) {
+            if (videoElement && videoElement.readyState >= videoElement.HAVE_METADATA) {
+                try {
+                    videoElement.currentTime = (_milliseconds / 1000);
+                    deferredTime = undefined;
+                } catch(err) {
+                    deferredTime = _milliseconds;
+                }
+            } else {
+                deferredTime = _milliseconds;
+            }
+        });
+        
+        media.on("setvolume", function(_vol) {
+            if (videoElement && videoElement.readyState >= videoElement.HAVE_METADATA) {
+                media.volume = _vol;
+                videoElement.volume = _vol;
+            }
+        });
+        
+        media.on("setmuted", function(_muted) {
+            if (videoElement && videoElement.readyState >= videoElement.HAVE_METADATA) {
+                media.muted = _muted;
+                videoElement.muted = _muted;
+            }
+        });
+        
+        media.on("setplay", function() {
+            if (videoElement && videoElement.readyState >= videoElement.HAVE_METADATA) {
+                try {
+                    videoElement.play();
+                    deferredPlayPause = undefined;
+                } catch(err) {
+                    deferredPlayPause = true;
+                }
+            } else {
+                deferredPlayPause = true;
+            }
+        });
+
+        media.on("setpause", function() {
+            if (videoElement && videoElement.readyState >= videoElement.HAVE_METADATA) {
+                try {
+                    videoElement.pause();
+                    deferredPlayPause = undefined;
+                } catch(err) {
+                    deferredPlayPause = false;
+                }
+            } else {
+                deferredPlayPause = false;
+            }
+        });
+        
+        media.on("loadedmetadata", function() {
+            if (typeof deferredTime !== "undefined") {
+                media.setCurrentTime(deferredTime);
+            }
+            if (typeof deferredPlayPause !== "undefined") {
+                if (deferredPlayPause) {
+                    media.play();
+                } else {
+                    media.pause();
+                }
+            }
+        });
+        
+        // Binding UI Events and Mashup Playing to Media
+        
+        media.on("play", function() {
+            if (media === mashup.currentMedia) {
+                mashup.trigger("play");
+            }
+        });
+        
+        media.on("pause", function() {
+            if (media === mashup.currentMedia) {
+                mashup.trigger("pause");
+            }
+        });
+        
+        media.on("timeupdate", function(_time) {
+            if (!mashup.paused && media === mashup.currentMedia && !media.seeking) {
+                if ( _time < mashupSegmentEnd ) {
+                    if ( _time >= mashupSegmentBegin ) {
+                        mashupTimecode = _time - mashupTimedelta;
+                    } else {
+                        mashupTimecode = mashupSegmentBegin - mashupTimedelta;
+                        media.setCurrentTime(mashupSegmentBegin);
+                    }
+                } else {
+                    mashupTimecode = mashupSegmentEnd - mashupTimedelta;
+                    media.pause();
+                    changeCurrentAnnotation();
+                }
+                mashup.trigger("timeupdate", new IriSP.Model.Time(mashupTimecode));
+            }
+        });
+        
+        media.on("seeked", function() {
+            media.seeking = false;
+            if (media === mashup.currentMedia && mashup.seeking) {
+                mashup.seeking = false;
+            }
+//            seekdiv.hide();
+        });
+        
+        media.on("volumechange", function() {
+            mashup.muted = media.muted;
+            mashup.volume = media.volume;
+            mashup.trigger("volumechange");
+        });
+        
+    }
+
+    // Mashup Events
+    
+    mashup.on("setcurrenttime", function(_milliseconds) {
+        mashupTimecode = _milliseconds;
+        changeCurrentAnnotation();
+    });
+    
+    mashup.on("setvolume", function(_vol) {
+        mashup.getMedias().forEach(function(_media) {
+            _media.setVolume(_vol);
+        });
+        mashup.volume = _vol;
+    });
+    
+    mashup.on("setmuted", function(_muted) {
+        mashup.getMedias().forEach(function(_media) {
+            _media.setMuted(_muted);
+        });
+        mashup.muted = _muted;
+    });
+    
+    mashup.on("setplay", function() {
+        mashup.paused = false;
+        changeCurrentAnnotation();
+    });
+    
+    mashup.on("setpause", function() {
+        mashup.paused = true;
+        if (mashup.currentMedia) {
+            mashup.currentMedia.pause();
+        }
+    });
+    
+    mashup.on("loadedmetadata", function() {
+        changeCurrentAnnotation();
+    });
+    
+}
\ No newline at end of file
--- a/src/widgets/MultiSegments.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/widgets/MultiSegments.js	Fri Jan 25 18:16:29 2013 +0100
@@ -79,7 +79,8 @@
                 line.segmentWidget,
                 IriSP._({
                     type: "Segments",
-                    annotation_type: _anntype
+                    annotation_type: _anntype,
+                    width: _this.width
                 }).extend(segmentsopts)
             );
             
@@ -87,7 +88,8 @@
                 line.annotationWidget,
                 IriSP._({
                     type: "Annotation",
-                    annotation_type: _anntype
+                    annotation_type: _anntype,
+                    width: _this.width
                 }).extend(annotationopts)
             );
             
--- a/src/widgets/Slideshare.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/widgets/Slideshare.js	Fri Jan 25 18:16:29 2013 +0100
@@ -9,16 +9,14 @@
 IriSP.Widgets.Slideshare.prototype.defaults = {
     annotation_type: "slide",
     sync: true,
-    embed_width: 400,
-    embed_height: 300
 }
 
 IriSP.Widgets.Slideshare.prototype.messages = {
     fr: {
-        slides_ : "Diapositives&nbsp;:"
+        slides_ : "Diapositives"
     },
     en: {
-        slides_ : "Slides:"
+        slides_ : "Slides"
     }
 }
 
@@ -27,14 +25,9 @@
 
 IriSP.Widgets.Slideshare.prototype.draw = function() {
     
-    var _embedObject = null,
-        $container,
-        _lastEmbedded = "",
-        _this = this;
-    
     function insertSlideshare(_presentation, _slide) {
         if (_lastEmbedded === _presentation) {
-            if (_.embedObject && typeof _embedObject.jumpTo === "function") {
+            if (_embedObject && typeof _embedObject.jumpTo === "function") {
                 _embedObject.jumpTo(parseInt(_slide));
             }
         } else {
@@ -75,8 +68,13 @@
         var _lastPres = "",
             _embedObject = null,
             _oembedCache = {},
-            _this = this;
-        $container = this.$.find(".Ldt-SlideShare-Container");
+            _lastEmbedded = "",
+            _this = this
+            $container = this.$.find(".Ldt-SlideShare-Container");
+            
+        this.embed_width = this.embed_width || $container.innerWidth();
+        this.embed_height = this.embed_height || Math.floor(this.embed_width * 3/4);
+        
         _annotations.forEach(function(_a) {
             _a.on("leave", function() {
                 $container.hide();
--- a/src/widgets/Tagger.css	Thu Jan 17 17:25:46 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-
-.Ldt-Tagger {
-    border-style: solid;
-    border-width: 1px;
-    border-color: #b7b7b7;
-    padding: 1px;
-    margin: 0;
-}
-
-.Ldt-Tagger-Inner {
-    background: url(img/pinstripe.png);
-    padding: 5px;
-    margin: 0;
-}
--- a/src/widgets/Tagger.js	Thu Jan 17 17:25:46 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-IriSP.Widgets.Tagger = function(player, config) {
-    IriSP.Widgets.Widget.call(this, player, config);
-};
-
-IriSP.Widgets.Tagger.prototype = new IriSP.Widgets.Widget();
-
-IriSP.Widgets.Tagger.prototype.defaults = {
-    created_annotation_type: "Contributions",
-    creator_name: 'anonymous',
-    api_endpoint: "",
-    api_method: "PUT",
-    pause_on_write : true,
-    api_serializer: "ldt_annotate",
-    tags: false
-}
-
-IriSP.Widgets.Tagger.prototype.messages = {
-    en: {
-        add_a_tag: "Add a tag",
-        submit: "Submit"
-    },
-    fr: {
-        add_a_tag: "Ajouter un tag",
-        submit: "Envoyer"
-    }
-}
-
-IriSP.Widgets.Tagger.prototype.template =
-    '<div class="Ldt-Tagger"><form class="Ldt-Tagger-Inner"><input class="Ldt-Tagger-Input" placeholder="{{l10n.add_a_tag}}" />'
-    + '<input class="Ldt-Tagger-Submit" type="submit" value="{{l10n.submit}}" /></form></div>';
-
-IriSP.Widgets.Tagger.prototype.draw = function() {
-    this.renderTemplate();
-    var _tags = this.tags || this.source.getTags().getTitles(),
-        _this = this,
-        _input = this.$.find(".Ldt-Tagger-Input");
-    _input.autocomplete({
-        source: _tags
-    });
-    if (this.pause_on_write) {
-        _input.keyup(function() {
-            _this.media.pause();
-        });
-    }
-    this.$.find(".Ldt-Tagger").submit(function() {
-        var _tagvalue = _input.val();
-        if (_tagvalue) {
-            
-            /* Création d'une liste d'annotations contenant une annotation afin de l'envoyer au serveur */
-            var _exportedAnnotations = new IriSP.Model.List(_this.player.sourceManager),
-                /* Création d'un objet source utilisant un sérialiseur spécifique pour l'export */
-                _export = _this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[_this.api_serializer]}),
-                /* Création d'une annotation dans cette source avec un ID généré à la volée (param. false) */
-                _annotation = new IriSP.Model.Annotation(false, _export),
-                /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */
-                _annotationTypes = _this.source.getAnnotationTypes().searchByTitle(_this.created_annotation_type),
-                /* Si le Type d'Annotation n'existe pas, il est créé à la volée */
-                _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, _export)),
-                /* L'objet Tag qui sera envoyé */
-                _tag = new IriSP.Model.Tag(false, _export);
-            /* L'objet Tag doit avoir pour titre le texte du tag envoyé */
-            _tag.title = _tagvalue;
-            /* Si nous avons dû générer un ID d'annotationType à la volée... */
-            if (!_annotationTypes.length) {
-                /* Il ne faudra pas envoyer l'ID généré au serveur */
-                _annotationType.dont_send_id = true;
-                /* Il faut inclure le titre dans le type d'annotation */
-                _annotationType.title = _this.created_annotation_type;
-            }
-            
-            /*
-             * Nous remplissons les données de l'annotation générée à la volée
-             * ATTENTION: Si nous sommes sur un MASHUP, ces éléments doivent se référer AU MEDIA D'ORIGINE
-             * */
-            var _now = _this.media.getCurrentTime(),
-                _pilotAnnotation = null;
-            if (_this.source.currentMedia.elementType == "mashup") {
-                /* Si c'est un mashup, on récupère l'annotation d'origine pour caler le temps */
-                var _pilotAnnotation = _this.source.currentMedia.getAnnotationAtTime(_now).annotation;
-            } else {
-                /* Sinon, on recherche une annotation correspondant au temps */
-                var _annotations = _this.getWidgetAnnotationsAtTime(_now);
-                if (_annotations.length) {
-                    _pilotAnnotation = _annotations[0];
-                }
-            }
-            if (_pilotAnnotation) {
-                _annotation.setBegin(_pilotAnnotation.begin);
-                _annotation.setEnd(_pilotAnnotation.end);
-                /* Id du média annoté */
-                _annotation.setMedia(_pilotAnnotation.getMedia().id);
-            } else {
-                _annotation.setBegin(_now);
-                _annotation.setEnd(_now);
-                /* Id du média annoté */
-                _annotation.setMedia(_this.source.currentMedia.id);
-            }
-            
-            /* Id du type d'annotation */
-            _annotation.setAnnotationType(_annotationType.id); 
-            
-            _annotation.title = _tagvalue;
-            _annotation.created = new Date(); /* Date de création de l'annotation */
-            _annotation.description = _tagvalue;
-            
-            _annotation.setTags([_tag.id]); /*Liste des ids de tags */
-            
-            /* Les données créateur/date de création sont envoyées non pas dans l'annotation, mais dans le projet */
-            _export.creator = _this.creator_name;
-            _export.created = new Date();
-            /* Ajout de l'annotation à la liste à exporter */
-            _exportedAnnotations.push(_annotation);
-            /* Ajout de la liste à exporter à l'objet Source */
-            _export.addList("annotation",_exportedAnnotations);
-            
-            IriSP.jQuery.ajax({
-                url: _this.api_endpoint,
-                type: _this.api_method,
-                contentType: 'application/json',
-                data: _export.serialize(), /* L'objet Source est sérialisé */
-                success: function(_data) {
-                    console.log("success");
-                    /* Pour éviter les doublons, on supprime l'annotation qui a été envoyée */
-                    _export.getAnnotations().removeElement(_annotation, true);
-                    /* On désérialise les données reçues pour les réinjecter */
-                    _export.deSerialize(_data);
-                    /* On récupère les données réimportées dans l'espace global des données */
-                    _this.source.merge(_export);
-                    if (_this.pause_on_write && _this.media.getPaused()) {
-                        _this.media.play();
-                    }
-                    /* On force le rafraîchissement du widget AnnotationsList */
-                    _this.player.trigger("AnnotationsList.refresh");
-                },
-                error: function(_xhr, _error, _thrown) {
-                    console.log("Error when sending annotation", _thrown);
-                    _export.getAnnotations().removeElement(_annotation, true);
-                }
-            });
-            
-            _input.val("");
-        }
-        return false;
-    });
-}
\ No newline at end of file
--- a/src/widgets/Tweet.js	Thu Jan 17 17:25:46 2013 +0100
+++ b/src/widgets/Tweet.js	Fri Jan 25 18:16:29 2013 +0100
@@ -93,83 +93,44 @@
 
 IriSP.Widgets.Tweet.prototype.show = function(_tweet) {
     if (typeof _tweet !== "undefined" && typeof _tweet.source !== "undefined") {
-        var _entities = [];
-        for (var _i = 0; _i < _tweet.source.entities.hashtags.length; _i++) {
-            var _hash = _tweet.source.entities.hashtags[_i];
-            _entities.push({
-                is_link: true,
-                text: '#' + _hash.text,
-                url: 'http://twitter.com/search?q=%23' + encodeURIComponent(_hash.text),
-                indices: _hash.indices
-            });
-        }
-        for (var _i = 0; _i < _tweet.source.entities.urls.length; _i++) {
-            var _url = _tweet.source.entities.urls[_i],
-                _displayurl = (typeof _url.display_url !== "undefined" && _url.display_url !== null ? _url.display_url : _url.url),
-                _linkurl = (typeof _url.expanded_url !== "undefined" && _url.expanded_url !== null ? _url.expanded_url : _url.url);
-            _displayurl = _displayurl.replace(/^\w+:\/\//,'');
-            if (!/^\w+:\/\//.test(_linkurl)) {
-                _linkurl = 'http://' + _linkurl;
-            }
-            _entities.push({
-                is_link: true,
-                text: _displayurl,
-                url: _linkurl,
-                indices: _url.indices
-            });
-        }
-        for (var _i = 0; _i < _tweet.source.entities.user_mentions.length; _i++) {
-            var _user = _tweet.source.entities.user_mentions[_i];
-            _entities.push({
-                is_link: true,
-                text: '@' + _user.screen_name,
-                url: 'http://twitter.com/' + encodeURIComponent(_user.screen_name),
-                indices: _user.indices
-            });
-        }
-        for (var _i = 0; _i < this.polemics.length; _i++) {
-            for (var _j = 0; _j < this.polemics[_i].keywords.length; _j++) {
-                var _p = _tweet.source.text.indexOf(this.polemics[_i].keywords[_j]);
-                while (_p !== -1) {
-                    var _end = (_p + this.polemics[_i].keywords[_j].length);
-                    _entities.push({
-                        is_link: false,
-                        text: this.polemics[_i].keywords[_j],
-                        color: this.polemics[_i].color,
-                        indices: [_p, _end]
-                    });
-                    _p = _tweet.source.text.indexOf(this.polemics[_i].keywords[_j], _end);
-                }
-            }
-        }
-        _entities = IriSP._(_entities).sortBy(function(_entity) {
+        var extend = [
+            [
+                /#(\w+)/gm,
+                function(matches) {
+                    return '<a href="http://twitter.com/search?q=%23' + matches[1] + '" target="_blank">'
+                },
+                '</a>'
+            ]
+        ];
+        var _urls = IriSP._(_tweet.source.entities.urls).sortBy(function(_entity) {
             return _entity.indices[0];
         });
+        
         var _currentPos = 0,
             _txt = '';
-        for (var _i = 0; _i < _entities.length; _i++) {
-            if (_entities[_i].indices[0] >= _currentPos) {
-                _txt += _tweet.source.text.substring(_currentPos, _entities[_i].indices[0]);
-                _currentPos = _entities[_i].indices[1];
-                if (_entities[_i].is_link) {
-                    _txt += '<a href="' + _entities[_i].url + '" target="_blank">';
-                } else {
-                    _txt += '<span style="background:' + _entities[_i].color + '">';
-                }
-                _txt += _entities[_i].text;
-                if (_entities[_i].is_link) {
-                    _txt += '</a>';
-                } else {
-                    _txt += '</span>';
-                }
+        IriSP._(_urls).each(function(_url) {
+            if (_url.indices[0] >= _currentPos) {
+                _txt += _tweet.source.text.substring(_currentPos, _url.indices[0]);
+                _txt += (typeof _url.expanded_url !== "undefined" && _url.expanded_url !== null ? _url.expanded_url : _url.url);
+                _currentPos = _url.indices[1];
             }
+        });
+        _txt += _tweet.source.text.substring(_currentPos);
+        
+        for (var _i = 0; _i < this.polemics.length; _i++) {
+            var rx = IriSP.Model.regexpFromTextOrArray(this.polemics[_i].keywords);
+            extend.push([
+                rx,
+                '<span style="background: ' + this.polemics[_i].color + '">',
+                '</span>'
+            ]);
         }
-        _txt += _tweet.source.text.substring(_currentPos);
+        var rx = (_tweet.found ? (_this.source.getAnnotations().regexp || false) : false);
         this.$.find(".Ldt-Tweet-Avatar").attr("src",_tweet.source.user.profile_image_url);
         this.$.find(".Ldt-Tweet-ScreenName").html('@'+_tweet.source.user.screen_name);
         this.$.find(".Ldt-Tweet-ProfileLink").attr("href", "https://twitter.com/" + _tweet.source.user.screen_name);
         this.$.find(".Ldt-Tweet-FullName").html(_tweet.source.user.name);
-        this.$.find(".Ldt-Tweet-Contents").html(_txt);
+        this.$.find(".Ldt-Tweet-Contents").html(IriSP.textFieldHtml(_txt, rx, extend));
         this.$.find(".Ldt-Tweet-Time").html(this.l10n.original_time + new Date(_tweet.source.created_at).toLocaleTimeString() + " / " + this.l10n.video_time + _tweet.begin.toString());
         this.$.find(".Ldt-Tweet-Retweet").attr("href", "https://twitter.com/intent/retweet?tweet_id=" + _tweet.source.id_str);
         this.$.find(".Ldt-Tweet-Reply").attr("href", "https://twitter.com/intent/tweet?in_reply_to=" + _tweet.source.id_str);
--- a/test/jwplayer.htm	Thu Jan 17 17:25:46 2013 +0100
+++ b/test/jwplayer.htm	Fri Jan 25 18:16:29 2013 +0100
@@ -4,8 +4,8 @@
     <head>
         <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
         <title>Metadataplayer test with JwPlayer</title>
-        <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
-        <link href='test.css' rel='stylesheet' type='text/css'>
+<!--        <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
+-->        <link href='test.css' rel='stylesheet' type='text/css'>
         <script type="text/javascript" src="metadataplayer/LdtPlayer-core.js" type="text/javascript"></script>
     </head>
 
@@ -13,13 +13,16 @@
         <h1>Metadataplayer test with JwPlayer</h1>
         <div id="LdtPlayer"></div>
         <div id="AnnotationsListContainer"></div>
+        <div id="SlideShareContainer"></div>
         <script type="text/javascript">
     IriSP.libFiles.defaultDir = "libs/";
     IriSP.language = 'fr';
     IriSP.widgetsDir = "metadataplayer";
     var _metadata = {
-        url: 'json/ldt-jwplayer.json',
-//        url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/5a893570-ca73-11e1-9443-00145ea4a2be?callback=?',
+//        url: 'json/ldt-jwplayer.json',
+//          url: 'http://capsicum/pf/ldtplatform/ldt/cljson/id/33e49eac-b3b0-11e1-b44d-00145ea4a2be?callback=?',
+//        url: 'http://capsicum/pf/ldtplatform/ldt/cljson/id/f1a17368-2bc8-11e1-b21a-00145ea49a02',
+        url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/fc0a654e-49ea-11e2-b4ad-00145ea4a2be',
         format: 'ldt'
     };
     var _config = {
@@ -32,37 +35,44 @@
         widgets: [
             {
                 type: "AutoPlayer",
-                width: 550,
                 autostart: true
             },
             { type: "Slider" },
             { type: "Controller" },
-            { type: "Polemic" },
-            { type: "Segments" },
-            { type: "Annotation" },
+            {
+                type: "Polemic",
+                max_elements: 20
+            },
+            { type: "Sparkline" },
+            { type: "MultiSegments" },
             {
                 type: "CreateAnnotation",
                 api_endpoint_template: "post-test.php",
                 creator_name: "Metadataplayer",
                 creator_avatar: "https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png",
-                tag_titles: ["#amateur", "#digital-humanities"]
+                tag_titles: ["amateur", "digital-humanities"],
+                //show_title_field: false,
+                //show_creator_field: false,
+                show_slice: false
             },
             { type: "Tweet" },
             {
-                type: "Tagger",
-                api_endpoint: "post-test.php"
-            },
-            {
                 type: "Tagcloud"
             },
             {
                 type: "AnnotationsList",
                 container: "AnnotationsListContainer",
                 default_thumbnail : "http://ldt.iri.centrepompidou.fr/static/site/ldt/css/imgs/video_sequence.png",
-                //ajax_url: "/pf/ldtplatform/api/ldt/segments/{{media}}/{{begin}}/{{end}}",
+                //ajax_url: "/pf/ldtplatform/api/ldt/1.0/segments/bytimecode/{{media}}/{{begin}}/{{end}}",
                 //ajax_granularity : 300000
             },
-            { type: "Mediafragment"}
+            {
+                type: "Slideshare",
+                container: "SlideShareContainer"
+            },
+            { type: "Mediafragment"},
+//            { type: "Trace",
+//            js_console: true }
         ]
     };
     
--- a/test/mashup/moon.htm	Thu Jan 17 17:25:46 2013 +0100
+++ b/test/mashup/moon.htm	Fri Jan 25 18:16:29 2013 +0100
@@ -66,7 +66,7 @@
     css : '../metadataplayer/LdtPlayer-core.css',
     widgets: [
         {
-            type: "MashupPlayer",
+            type: "HtmlMashupPlayer",
 //            split_screen: true,
             url_transform: function(_url) {
                 if (_canPlayMp4 == "maybe" || _canPlayMp4 == "probably") {
--- a/test/mp4video.htm	Thu Jan 17 17:25:46 2013 +0100
+++ b/test/mp4video.htm	Fri Jan 25 18:16:29 2013 +0100
@@ -22,7 +22,7 @@
     format: 'ldt'
 };
 var _config = {
-    width : 620,
+    width : 550,
     container : 'LdtPlayer',
     default_options: {
         metadata: _metadata
@@ -30,8 +30,8 @@
     css : 'metadataplayer/LdtPlayer-core.css',
     widgets: [
         {
-            type: "AutoPlayer",
-            video: "trailer.mp4"
+            type: "AdaptivePlayer",
+            video: "http://media.iri.centrepompidou.fr/video/mashup/texaverybannedcartoonsuncletomscabana1947.mp4"
         },
         { type: "Sparkline" },
         { type: "Slider" },
--- a/test/test.css	Thu Jan 17 17:25:46 2013 +0100
+++ b/test/test.css	Fri Jan 25 18:16:29 2013 +0100
@@ -49,7 +49,7 @@
     margin: 10px;
 }
 
-#AnnotationsListContainer {
+#AnnotationsListContainer, #SlideShareContainer {
     float: left;
     width: 400px;
     margin: 10px 0;