Modifications for LDT-Platform new-model
authorveltr
Thu, 05 Jul 2012 19:08:13 +0200
branchnew-model
changeset 924 64c2eaafe5e2
parent 923 b3ee7d1b472a
child 925 28efc97b5d78
Modifications for LDT-Platform
assets/psd/socialbuttons.psd
sbin/build/compil.sh
src/css/LdtPlayer-core.css
src/js/init.js
src/js/players/player.jwplayer.js
src/js/serializers/ldt_annotate.js
src/js/widgets.js
src/widgets/Annotation.css
src/widgets/Annotation.js
src/widgets/AnnotationsList.css
src/widgets/AnnotationsList.js
src/widgets/CreateAnnotation.css
src/widgets/CreateAnnotation.js
src/widgets/Polemic.js
src/widgets/Segments.js
src/widgets/Slice.css
src/widgets/Slice.js
src/widgets/Social.css
src/widgets/Social.js
src/widgets/Trace.js
src/widgets/img/socialbuttons.png
test/dailymotion.htm
test/jwplayer.htm
unittests/README.txt
unittests/index.html
unittests/jquery.simulate.js
unittests/mockSerializer.js
unittests/mockTweetSerializer.js
unittests/qunit.css
unittests/qunit.js
unittests/sinon-ie.js
unittests/sinon-qunit.js
unittests/sinon.js
unittests/tests/dataloader.js
unittests/tests/init.js
unittests/tests/layout.js
unittests/tests/module.js
unittests/tests/serializer.js
unittests/tests/serializerFactory.js
unittests/tests/serializers/JSONSerializer.js
unittests/tests/serializers/mockSerializer.js
unittests/tests/serializers/mockTweetSerializer.js
unittests/tests/utils.js
unittests/tests/widget.js
unittests/tests/widgets/annotationsWidget.js
unittests/tests/widgets/arrowWidget.js
unittests/tests/widgets/playerWidget.js
unittests/tests/widgets/polemicWidget.js
unittests/tests/widgets/segmentsWidget.js
unittests/tests/widgets/sliderWidget.js
unittests/tests/widgets/sparklineWidget.js
unittests/tests/widgets/tooltipWidget.js
unittests/tests/widgets/tweetsWidget.js
Binary file assets/psd/socialbuttons.psd has changed
--- a/sbin/build/compil.sh	Fri Jun 29 16:22:52 2012 +0200
+++ b/sbin/build/compil.sh	Thu Jul 05 19:08:13 2012 +0200
@@ -1,4 +1,5 @@
 #!/bin/sh
 sh ../res/ant/bin/ant -f client.xml
-cp ../../build/LdtPlayer-core.js ../../test/metadataplayer/LdtPlayer-core.js
+cp ../../build/LdtPlayer-core.js ../../test/metadataplayer
+cp -R ../../src/css/* ../../test/metadataplayer
 cp -R ../../src/widgets/* ../../test/metadataplayer
\ No newline at end of file
--- a/src/css/LdtPlayer-core.css	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/css/LdtPlayer-core.css	Thu Jul 05 19:08:13 2012 +0200
@@ -12,4 +12,4 @@
 /*    font-family: Arial, Helvetica, sans-serif; */
     color: black;
     font-size: 12px;
-}
+}
\ No newline at end of file
--- a/src/js/init.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/js/init.js	Thu Jul 05 19:08:13 2012 +0200
@@ -130,9 +130,9 @@
 
 IriSP.Metadataplayer.prototype.onVideoDataLoaded = function() {
     
-    /* Getting video URL from metadata if it's not in the player config options */
+    /* Setting default media from metadata */
    
-    if (typeof this.videoData !== "undefined" && typeof this.config.player.video === "undefined") {
+    if (typeof this.videoData !== "undefined") {
         
         var _media;
         
@@ -158,11 +158,12 @@
         
         this.videoData.currentMedia = _media;
         
-        if (typeof _media !== "undefined" && typeof _media.video !== "undefined") {
+        /* Getting video URL from metadata if it's not in the player config options */
+        
+        if (typeof _media !== "undefined" && typeof _media.video !== "undefined" && typeof this.config.player.video === "undefined") {
             this.config.player.video = _media.video;
-            if (typeof _media.streamer !== "undefined") {
+            if (typeof this.config.player.streamer == "undefined" && typeof _media.streamer !== "undefined") {
                 this.config.player.streamer = _media.streamer;
-                this.config.player.video = _media.video.replace(_media.streamer,'');
             }
         }
         
@@ -235,8 +236,12 @@
             var opts = IriSP.jQuery.extend({}, this.config.player);
             delete opts.container;
             delete opts.type;
+            if (typeof opts.streamer !== "undefined") {
+                opts.video = opts.video.replace(opts.streamer,"");
+            }
             opts.file = opts.video;
             delete opts.video;
+            delete opts.metadata;
 
             if(!opts.hasOwnProperty("flashplayer")) {
                 opts.flashplayer = IriSP.getLib("jwPlayerSWF");
--- a/src/js/players/player.jwplayer.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/js/players/player.jwplayer.js	Thu Jul 05 19:08:13 2012 +0200
@@ -5,18 +5,25 @@
 IriSP.PopcornReplacement.jwplayer = function(container, options) {
     /* appel du parent pour initialiser les structures communes à tous les players */
     IriSP.PopcornReplacement.player.call(this, container, options);
-  
-    this.media.duration = options.duration; /* optional */
+    
+    if (options.autostart) {
+        this.media.paused = false;
+        this.trigger("play");
+    }
  
     var _player = jwplayer(this.container),
-        _this = this;
+        _this = this,
+        _seekPause = false;
   
   /* Définition des fonctions de l'API -  */
     this.playerFns = {
         play: function() { return _player.play(true); },
         pause: function() { return _player.pause(true); },
         getPosition: function() { return _player.getPosition(); },
-        seek: function(pos) { return _player.seek(pos); },
+        seek: function(pos) {
+            _seekPause = _this.media.paused;
+            return _player.seek(pos);
+        },
         getMute: function() { return _player.getMute() },
         setMute: function(p) { return _player.setMute(p); },
         getVolume: function() { return _player.getVolume() / 100; },
@@ -28,15 +35,22 @@
             _this.trigger("loadedmetadata");
         },
         onTime:   function() {
-            if (_this.media.paused && _player.getState() === "PLAYING") {
-                _this.media.paused = false;
-                _this.trigger("play");
+            if (_seekPause) {
+                _player.pause(true);
+                _seekPause = false;
+            } else {
+                if (_this.media.paused && _player.getState() === "PLAYING") {
+                    _this.media.paused = false;
+                    _this.trigger("play");
+                }
             }
             _this.trigger("timeupdate");
         },
         onPlay:   function() {
-            _this.media.paused = false;
-            _this.trigger("play");
+            if (!_seekPause) {
+                _this.media.paused = false;
+                _this.trigger("play");
+            }
         },
         onPause:  function() {
             _this.media.paused = true;
--- a/src/js/serializers/ldt_annotate.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/js/serializers/ldt_annotate.js	Thu Jul 05 19:08:13 2012 +0200
@@ -52,7 +52,7 @@
             var _anndata = _data.annotations[0],
                 _ann = new IriSP.Model.Annotation(_anndata.id, _source);
             _ann.description = _anndata.content.data || "";
-            _ann.title = _data.creator;
+            _ann.title = _data.creator || "";
             _ann.created = new Date(_data.meta.created);
             _ann.setMedia(_anndata.media, _source);
             var _anntypes = _source.getAnnotationTypes(true).searchByTitle(_anndata.type_title);
--- a/src/js/widgets.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/js/widgets.js	Thu Jul 05 19:08:13 2012 +0200
@@ -54,18 +54,6 @@
     this.$ = IriSP.jQuery('#' + this.container);
     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];
-            _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]
@@ -120,6 +108,19 @@
     });
 }
 
+IriSP.Widgets.Widget.prototype.insertSubwidget = function(_selector, _propname, _widgetoptions) {
+    var _id = _selector.attr("id"),
+        _this = this;
+    if (typeof _id == "undefined") {
+        _id = IriSP._.uniqueId(this.container + '_sub_widget_' + _widgetoptions.type);
+        _selector.attr("id", _id);
+    }
+    _widgetoptions.container = _id;
+    _this.player.loadWidget(_widgetoptions, function(_widget) {
+        _this[_propname] = _widget;
+    });
+}
+
 /**
  * This method responsible of drawing a widget on screen.
  */
--- a/src/widgets/Annotation.css	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/Annotation.css	Thu Jul 05 19:08:13 2012 +0200
@@ -28,7 +28,12 @@
 }
 
 .Ldt-Annotation-MaxMinButton {
-    float: right; margin: 5px 5px 0; width: 17px; height: 17px; background: url(img/widget-control.png); background-position: 0 -51px; cursor: hand;
+    float: right; margin: 5px 5px 0; width: 17px; height: 17px;
+    background: url(img/widget-control.png); background-position: 0 -51px; cursor: pointer;
+}
+
+.Ldt-Annotation-Social {
+    float: right;
 }
 
 .Ldt-Annotation-MaxMinButton:hover {
@@ -67,34 +72,6 @@
     margin: 5px 0 0 90px; clear: right;
 }
 
-.Ldt-Annotation-Share {
-    display: inline-block; width: 24px; height: 24px; margin: 2px 0 0 2px; background: url(img/socialbuttons.png);
-}
-
-.Ldt-Annotation-Twitter {
-    background-position: 0 0;
-}
-
-.Ldt-Annotation-Twitter:hover {
-    background-position: 0 -24px;
-}
-
-.Ldt-Annotation-Fb {
-    background-position: -24px 0;
-}
-
-.Ldt-Annotation-Fb:hover {
-    background-position: -24px -24px;
-}
-
-.Ldt-Annotation-Gplus {
-    background-position: -48px 0;
-}
-
-.Ldt-Annotation-Gplus:hover {
-    background-position: -48px -24px;
-}
-
 .Ldt-Annotation-Tags-Block {
     font-size: 12px;
 }
@@ -138,3 +115,7 @@
     display: none;
 }
 
+.Ldt-Annotation-EmptyBlock {
+    display: none;
+}
+
--- a/src/widgets/Annotation.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/Annotation.js	Thu Jul 05 19:08:13 2012 +0200
@@ -1,4 +1,4 @@
-// TODO: Open share links in a small window - Migrate Timeupdate functions to Extract
+// TODO: Migrate Timeupdate functions to Extract
 
 IriSP.Widgets.Annotation = function(player, config) {
     IriSP.Widgets.Widget.call(this, player, config);
@@ -11,8 +11,6 @@
 
 IriSP.Widgets.Annotation.prototype.messages = {
     fr: {
-        share_: "Partager&nbsp;:",
-        share_on: "Partager sur",
         watching: "Je regarde ",
         on_site: " sur ",
         tags_: "Mots-clés&nbsp;:",
@@ -20,8 +18,6 @@
         excerpt_from: "Extrait de&nbsp;:"
     },
     en: {
-        share_: "Share:",
-        share_on: "Share on",
         watching: "I'm watching ",
         on_site: " on ",
         tags_: "Keywords:",
@@ -34,6 +30,7 @@
     '<div class="Ldt-Annotation-Widget {{#show_top_border}}Ldt-Annotation-ShowTop{{/show_top_border}}">'
     + '<div class="Ldt-Annotation-Inner Ldt-Annotation-Empty{{#start_minimized}} Ldt-Annotation-Minimized{{/start_minimized}}">'
     + '<div class="Ldt-Annotation-HiddenWhenEmpty Ldt-Annotation-MaxMinButton"></div>'
+    + '<div class="Ldt-Annotation-Social Ldt-Annotation-HiddenWhenMinimized"></div>'
     + '<h3 class="Ldt-Annotation-HiddenWhenEmpty"><span class="Ldt-Annotation-Title"></span> <span class="Ldt-Annotation-Time">'
     + '( <span class="Ldt-Annotation-Begin"></span> - <span class="Ldt-Annotation-End"></span> )</span></h3>'
     + '<h3 class="Ldt-Annotation-MashupOrigin Ldt-Annotation-HiddenWhenEmpty">{{l10n.excerpt_from}} <span class="Ldt-Annotation-MashupMedia"></span> <span class="Ldt-Annotation-Time">'
@@ -42,21 +39,18 @@
     + '<p class="Ldt-Annotation-Labelled Ldt-Annotation-Description"></p></div>'
     + '<div class="Ldt-Annotation-Tags-Block Ldt-Annotation-HiddenWhenMinimized Ldt-Annotation-HiddenWhenEmpty Ldt-Annotation-Cleared">'
     + '<div class="Ldt-Annotation-Label">{{l10n.tags_}}</div><ul class="Ldt-Annotation-Labelled Ldt-Annotation-Tags"></ul>'
-    + '</div><div class="Ldt-Annotation-Cleared Ldt-Annotation-HiddenWhenMinimized Ldt-Annotation-HiddenWhenEmpty"><div class="Ldt-Annotation-Label">{{l10n.share_}}</div><p class="Ldt-Annotation-Labelled">'
-    + '<a href="#" target="_blank" class="Ldt-Annotation-Share Ldt-Annotation-Fb Ldt-TraceMe" title="{{l10n.share_on}} Facebook"></a>'
-    + '<a href="#" target="_blank" class="Ldt-Annotation-Share Ldt-Annotation-Twitter Ldt-TraceMe" title="{{l10n.share_on}} Twitter"></a>'
-    + '<a href="#" target="_blank" class="Ldt-Annotation-Share Ldt-Annotation-Gplus Ldt-TraceMe" title="{{l10n.share_on}} Google+"></a>'
-    + '</p></div></div></div></div>';
+    + '</div></div></div></div>';
 
 IriSP.Widgets.Annotation.prototype.defaults = {
     annotation_type : "chap",
-    start_minimized: false,
+    start_minimized: true,
     show_top_border : false,
     site_name : "Lignes de Temps"
 }
 
 IriSP.Widgets.Annotation.prototype.draw = function() {
     this.renderTemplate();
+    this.insertSubwidget(this.$.find(".Ldt-Annotation-Social"), "socialWidget", { type: "Social" });
     this.bindPopcorn("timeupdate","onTimeupdate");
     this.bindPopcorn("IriSP.Annotation.hide","hide");
     this.bindPopcorn("IriSP.Annotation.show","show");
@@ -102,7 +96,7 @@
             return '<li class="Ldt-Annotation-TagLabel"><span>' + _tag + '</span></li>';
         }).join("");
         this.$.find(".Ldt-Annotation-Tags").html(_html);
-        this.$.find(".Ldt-Annotation-Tags-Block").removeClass("Ldt-Annotation-NoTags");
+        this.$.find(".Ldt-Annotation-Tags-Block").removeClass("Ldt-Annotation-EmptyBlock");
         
         /* Correct the empty tag bug */
         this.$.find('.Ldt-Annotation-TagLabel').each(function() {
@@ -116,15 +110,15 @@
             _this.player.popcorn.trigger("IriSP.search.triggeredSearch", IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,''));
         });
     } else {
-        this.$.find(".Ldt-Annotation-Tags-Block").hide();
+        this.$.find(".Ldt-Annotation-Tags-Block").addClass("Ldt-Annotation-EmptyBlock");
     }
     this.$.find(".Ldt-Annotation-Title").html(_annotation.title);
     var _desc = _annotation.description.replace(/(^\s+|\s+$)/g,'');
     if (_desc) {
-        this.$.find(".Ldt-Annotation-Description-Block").show();
+        this.$.find(".Ldt-Annotation-Description-Block").removeClass("Ldt-Annotation-EmptyBlock");
         this.$.find(".Ldt-Annotation-Description").html(_desc);
     } else {
-        this.$.find(".Ldt-Annotation-Description-Block").hide();
+        this.$.find(".Ldt-Annotation-Description-Block").addClass("Ldt-Annotation-EmptyBlock");
     }
     this.$.find(".Ldt-Annotation-Begin").html(_annotation.begin.toString());
     this.$.find(".Ldt-Annotation-End").html(_annotation.end.toString());
@@ -136,9 +130,9 @@
     } else {
         this.$.find('.Ldt-Annotation-Inner').removeClass("Ldt-Annotation-isMashup");
     }
-    this.$.find(".Ldt-Annotation-Fb").attr("href", "http://www.facebook.com/share.php?" + IriSP.jQuery.param({ u: _url, t: _text }));
-    this.$.find(".Ldt-Annotation-Twitter").attr("href", "https://twitter.com/intent/tweet?" + IriSP.jQuery.param({ url: _url, text: _text }));
-    this.$.find(".Ldt-Annotation-Gplus").attr("href", "https://plusone.google.com/_/+1/confirm?" + IriSP.jQuery.param({ url: _url, title: _text }));
+    if (typeof this.socialWidget !== "undefined") {
+        this.socialWidget.updateUrls(_url, _text);
+    }
     this.$.find(".Ldt-Annotation-Inner").removeClass("Ldt-Annotation-Empty");
 }
 
--- a/src/widgets/AnnotationsList.css	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/AnnotationsList.css	Thu Jul 05 19:08:13 2012 +0200
@@ -21,7 +21,7 @@
     min-height: 60px;
 }
 .Ldt-AnnotationsList-li:hover {
-    background: url(img/pinstripe-grey.png);
+    background: url(img/pinstripe-grey.png) !important;
 }
 .Ldt-AnnotationsList-highlight {
     background: #F7268E;
@@ -59,7 +59,7 @@
 p.Ldt-AnnotationsList-Description {
     margin: 2px 0 2px 82px;
     font-size: 12px;
-    color: #666666;
+    color: #333333;
 }
 ul.Ldt-AnnotationsList-Tags {
     list-style: none;
--- a/src/widgets/AnnotationsList.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/AnnotationsList.js	Thu Jul 05 19:08:13 2012 +0200
@@ -27,14 +27,27 @@
     annotation_type : false,
     refresh_interval : 0,
     limit_count : 10,
-    newest_first : false
+    newest_first : false,
+    polemics : [{
+        keyword: "++",
+        background_color: "#c9ecc6"
+    },{
+        keyword: "--",
+        background_color: "#f9c5c6"
+    },{
+        keyword: "??",
+        background_color: "#cec5f9"
+    },{
+        keyword: "==",
+        background_color: "#f9f4c6"
+    }]
 };
 
 IriSP.Widgets.AnnotationsList.prototype.template =
     '<div class="Ldt-AnnotationsListWidget">'
     + '<ul class="Ldt-AnnotationsList-ul">'
     + '{{#annotations}}'
-    + '<li class="Ldt-AnnotationsList-li Ldt-TraceMe" trace-info="annotation-id:{{id}}">'
+    + '<li class="Ldt-AnnotationsList-li Ldt-TraceMe" trace-info="annotation-id:{{id}}" style="{{specific_style}}">'
     + '<div class="Ldt-AnnotationsList-ThumbContainer">'
     + '<a href="{{url}}">'
     + '<img class="Ldt-AnnotationsList-Thumbnail" src="{{thumbnail}}" />'
@@ -175,7 +188,7 @@
                             : '#id=' + _annotation.id
                             )
                     );
-                    var _title = _annotation.title.replace(_annotation.description,''),
+                    var _title = (_annotation.title || "").replace(_annotation.description,''),
                         _description = _annotation.description;
                     if (!_annotation.title) {
                         _title = _annotation.creator;
@@ -184,6 +197,13 @@
                         _description = _annotation.title;
                         _title = _annotation.creator;
                     }
+                    var _bgcolor;
+                    IriSP._(_this.polemics).each(function(_polemic) {
+                        var _rgxp = IriSP.Model.regexpFromTextOrArray(_polemic.keyword);
+                        if (_rgxp.test(_title + " " + _description)) {
+                            _bgcolor = _polemic.background_color;
+                        }
+                    });
                     var _res = {
                         id : _annotation.id,
                         title : _title,
@@ -192,7 +212,8 @@
                         end : _annotation.end.toString(),
                         thumbnail : typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail ? _annotation.thumbnail : _this.default_thumbnail,
                         url : _url,
-                        tags : _annotation.getTagTexts()
+                        tags : _annotation.getTagTexts(),
+                        specific_style : (typeof _bgcolor !== "undefined" ? "background: " + _bgcolor : "")
                     }
                     return _res;
             }),
--- a/src/widgets/CreateAnnotation.css	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/CreateAnnotation.css	Thu Jul 05 19:08:13 2012 +0200
@@ -17,9 +17,11 @@
 }
 
 .Ldt-CreateAnnotation-Inner h3 {
-    margin: 5px 0;
-    font-size: 14px;
-    font-weight: bold;
+    margin: 5px 0; font-size: 14px; font-weight: bold; text-align: right;
+}
+
+.Ldt-CreateAnnotation-h3Left {
+    float: left;
 }
 
 .Ldt-CreateAnnotation-Main {
@@ -27,7 +29,6 @@
 }
 
 .Ldt-CreateAnnotation-Title, .Ldt-CreateAnnotation-Creator {
-    margin-right: 2px;
     font-size: 14px;
     font-weight: bold;
     color: #0068c4;
@@ -63,7 +64,7 @@
     height: 56px;
     padding: 2px;
     resize: none;
-    width: 520px;
+    width: 460px;
     border: 1px solid #666666;
     border-radius: 2px;
 }
--- a/src/widgets/CreateAnnotation.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/CreateAnnotation.js	Thu Jul 05 19:08:13 2012 +0200
@@ -10,13 +10,14 @@
     show_title_field : false, /* For the moment, titles can't be sent to ldtplatform */
     show_creator_field : true,
     start_visible : true,
-    always_visible : true,
+    always_visible : false,
     sync_on_slice_widget : true, /* If false, syncs on current timecode */
     takeover_arrow : false,
-    minimize_annotation_widget : false,
+    minimize_annotation_widget : true,
     creator_name : "",
-    creator_avatar : "https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png",
+    creator_avatar : "",
     tags : false,
+    tag_titles : false,
     pause_on_write : true,
     max_tags : 8,
     polemics : [{
@@ -91,11 +92,11 @@
 IriSP.Widgets.CreateAnnotation.prototype.template =
     '<div class="Ldt-CreateAnnotation"><div class="Ldt-CreateAnnotation-Inner">'
     + '<form class="Ldt-CreateAnnotation-Screen Ldt-CreateAnnotation-Main">'
-    + '<h3>{{#show_title_field}}<input class="Ldt-CreateAnnotation-Title" placeholder="{{l10n.type_title}}" />{{/show_title_field}}'
+    + '<h3><span class="Ldt-CreateAnnotation-h3Left">{{#show_title_field}}<input class="Ldt-CreateAnnotation-Title" placeholder="{{l10n.type_title}}" />{{/show_title_field}}'
     + '{{^show_title_field}}<span class="Ldt-CreateAnnotation-NoTitle">{{l10n.no_title}} </span>{{/show_title_field}}'
     + ' <span class="Ldt-CreateAnnotation-Times">{{#sync_on_slice_widget}}{{l10n.from_time}} {{/sync_on_slice_widget}}{{^sync_on_slice_widget}}{{l10n.at_time}} {{/sync_on_slice_widget}} <span class="Ldt-CreateAnnotation-Begin">00:00</span>'
-    + '{{#sync_on_slice_widget}} {{l10n.to_time}} <span class="Ldt-CreateAnnotation-End">00:00</span>{{/sync_on_slice_widget}}</span></h3>'
-    + '{{#show_creator_field}}<h3>{{l10n.your_name_}} <input class="Ldt-CreateAnnotation-Creator" value="{{creator_name}}" /></h3>{{/show_creator_field}}'
+    + '{{#sync_on_slice_widget}} {{l10n.to_time}} <span class="Ldt-CreateAnnotation-End">00:00</span>{{/sync_on_slice_widget}}</span></span>'
+    + '{{#show_creator_field}}{{l10n.your_name_}} <input class="Ldt-CreateAnnotation-Creator" value="{{creator_name}}" /></h3>{{/show_creator_field}}'
     + '<textarea class="Ldt-CreateAnnotation-Description" placeholder="{{l10n.type_description}}"></textarea>'
     + '<div class="Ldt-CreateAnnotation-Avatar"><img src="{{creator_avatar}}" title="{{creator_name}}"></img></div>'
     + '<input type="submit" class="Ldt-CreateAnnotation-Submit" value="{{l10n.submit}}" />'
@@ -110,6 +111,20 @@
     + '</div></div>';
     
 IriSP.Widgets.CreateAnnotation.prototype.draw = function() {
+    var _this = this;
+    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);
+            if (_tags.length) {
+                _tag = _tags[0];
+            } else {
+                _tag = new IriSP.Model.Tag(false, _this.source);
+                _tag.title = _tag_title;
+            }
+            return _tag;
+        });
+    }
     if (!this.tags) {
         this.tags = this.source.getTags()
             .sortBy(function (_tag) {
@@ -121,7 +136,6 @@
             });
         // We have to use the map function because Mustache doesn't like our tags object
     }
-    var _this = this;
     this.renderTemplate();
     this.$.find(".Ldt-CreateAnnotation-Close").click(function() {
         _this.hide();
--- a/src/widgets/Polemic.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/Polemic.js	Thu Jul 05 19:08:13 2012 +0200
@@ -40,11 +40,6 @@
             "keywords" : [ "?" ],
             "color" : "#036AAE"
         }
-    ],
-    requires : [
-        {
-            type: "Tooltip"
-        }
     ]
 };
 
@@ -287,6 +282,10 @@
         var _x = _e.pageX - _this.$zone.offset().left;
         _this.player.popcorn.currentTime(_this.source.getDuration().getSeconds() * _x / _this.width);
     });
+    
+    this.$.append('<div class="Ldt-Polemic-Tooltip"></div>');
+    
+    this.insertSubwidget(this.$.find(".Ldt-Polemic-Tooltip"), "tooltip", { type: "Tooltip" });
 }
 
 IriSP.Widgets.Polemic.prototype.onTimeupdate = function() {
--- a/src/widgets/Segments.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/Segments.js	Thu Jul 05 19:08:13 2012 +0200
@@ -9,11 +9,6 @@
 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
 };
 
@@ -22,7 +17,8 @@
     + '<div class="Ldt-Segments-Segment Ldt-TraceMe" trace-info="segment-id:{{id}}" segment-id="{{id}}" segment-text="{{text}}" segment-color="{{color}}" center-pos="{{center}}" begin-seconds="{{beginseconds}}"'
     + 'style="left:{{left}}px; width:{{width}}px; background:{{color}}"></div>'
     + '{{/segments}}</div>'
-    + '<div class="Ldt-Segments-Position"></div>';
+    + '<div class="Ldt-Segments-Position"></div>'
+    + '<div class="Ldt-Segments-Tooltip"></div>';
 
 IriSP.Widgets.Segments.prototype.draw = function() {
     this.bindPopcorn("IriSP.search", "onSearch");
@@ -55,6 +51,7 @@
             }
         })
     }));
+    this.insertSubwidget(this.$.find(".Ldt-Segments-Tooltip"), "tooltip", { type: "Tooltip" });
     this.$segments = this.$.find('.Ldt-Segments-Segment');
     
     this.$segments.mouseover(function() {
--- a/src/widgets/Slice.css	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/Slice.css	Thu Jul 05 19:08:13 2012 +0200
@@ -5,7 +5,8 @@
 }
 
 .Ldt-Slice .ui-slider-handle {
-    width: 7px; height: 20px; top: 0; border: none; margin: 0; padding: 0; background: url(img/slice-handles.png); border-radius: 0;
+    width: 7px; height: 20px; top: 0; border: none; margin: 0; padding: 0;
+    background: url(img/slice-handles.png); border-radius: 0; cursor: pointer;
 }
 
 .ui-slider-handle.Ldt-Slice-left-handle {
--- a/src/widgets/Slice.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/Slice.js	Thu Jul 05 19:08:13 2012 +0200
@@ -4,13 +4,13 @@
 
 IriSP.Widgets.Slice = function(player, config) {
     IriSP.Widgets.Widget.call(this, player, config);
+    this.sliding = false;
 };
 
 IriSP.Widgets.Slice.prototype = new IriSP.Widgets.Widget();
 
 IriSP.Widgets.Slice.prototype.defaults = {
     start_visible : false,
-    pause_on_change : true,
     live_update : true
         /* Shall the bounds change each time
         the Annotation Widget sends an update (true)
@@ -29,7 +29,8 @@
     this.min = 0;
     this.max = this.source.getDuration().valueOf();
     
-    var _this = this;
+    var _this = this,
+        _currentTime;
     
     this.$slider.slider({
         range: true,
@@ -44,9 +45,18 @@
             _this.player.popcorn.trigger("IriSP.Slice.boundsChanged",[ui.values[0], ui.values[1]]);
         },
         start: function() {
-            if (_this.pause_on_change && !_this.player.popcorn.media.paused) {
+            _this.sliding = true;
+            if (!_this.player.popcorn.media.paused) {
                 _this.player.popcorn.pause();
             }
+            _currentTime = _this.player.popcorn.currentTime();
+        },
+        slide: function(event, ui) {
+            _this.player.popcorn.currentTime(ui.value / 1000);
+        },
+        stop: function() {
+            _this.sliding = false;
+            _this.player.popcorn.currentTime(_currentTime);
         }
     });
     this.$slider.find(".ui-slider-handle:first").addClass("Ldt-Slice-left-handle");
@@ -74,9 +84,11 @@
 }
 
 IriSP.Widgets.Slice.prototype.storeBounds = function(_values) {
-    this.min = _values[0];
-    this.max = _values[1];
-    if (this.live_update) {
-        this.$slider.slider("values", [this.min, this.max]);
+    if (!this.sliding && !this.player.popcorn.media.paused && (this.min != _values[0] || this.max != _values[1])) {
+        this.min = _values[0];
+        this.max = _values[1];
+        if (this.live_update) {
+            this.$slider.slider("values", [this.min, this.max]);
+        }
     }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Social.css	Thu Jul 05 19:08:13 2012 +0200
@@ -0,0 +1,35 @@
+.Ldt-Social a {
+    display: inline-block; width: 24px; height: 24px; margin: 2px 0 0 2px; background: url(img/socialbuttons.png);
+}
+
+a.Ldt-Social-Twitter {
+    background-position: 0 0;
+}
+
+a.Ldt-Social-Twitter:hover {
+    background-position: 0 -24px;
+}
+
+a.Ldt-Social-Fb {
+    background-position: -24px 0;
+}
+
+a.Ldt-Social-Fb:hover {
+    background-position: -24px -24px;
+}
+
+a.Ldt-Social-Gplus {
+    background-position: -48px 0;
+}
+
+a.Ldt-Social-Gplus:hover {
+    background-position: -48px -24px;
+}
+
+a.Ldt-Social-Mail {
+    background-position: -72px 0;
+}
+
+a.Ldt-Social-Mail:hover {
+    background-position: -72px -24px;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/Social.js	Thu Jul 05 19:08:13 2012 +0200
@@ -0,0 +1,45 @@
+// TODO: Open share links in a small window
+
+IriSP.Widgets.Social = function(player, config) {
+    IriSP.Widgets.Widget.call(this, player, config);
+}
+
+IriSP.Widgets.Social.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Social.prototype.defaults = {
+    text: "",
+    url: "",
+    show_twitter: true,
+    show_fb: true,
+    show_gplus: true,
+    show_mail: true
+}
+
+IriSP.Widgets.Social.prototype.template =
+    '<span class="Ldt-Social">{{#show_fb}}<a href="#" target="_blank" class="Ldt-Social-Fb Ldt-TraceMe" title="{{l10n.share_on}} Facebook"></a>{{/show_fb}}'
+    + '{{#show_twitter}}<a href="#" target="_blank" class="Ldt-Social-Twitter Ldt-TraceMe" title="{{l10n.share_on}} Twitter"></a>{{/show_twitter}}'
+    + '{{#show_gplus}}<a href="#" target="_blank" class="Ldt-Social-Gplus Ldt-TraceMe" title="{{l10n.share_on}} Google+"></a>{{/show_gplus}}'
+    + '{{#show_mail}}<a href="#" target="_blank" class="Ldt-Social-Mail Ldt-TraceMe" title="{{l10n.share_mail}}"></a>{{/show_mail}}</span>';
+
+IriSP.Widgets.Social.prototype.messages = {
+    "fr": {
+        share_on: "Partager sur",
+        share_mail: "Envoyer par courriel"
+    },
+    "en" : {
+        share_on: "Share on",
+        share_mail: "Share by e-mail"
+    }
+}
+
+IriSP.Widgets.Social.prototype.draw = function() {
+    this.renderTemplate();
+    this.updateUrls(this.url, this.text);
+}
+
+IriSP.Widgets.Social.prototype.updateUrls = function(_url, _text) {
+    this.$.find(".Ldt-Social-Fb").attr("href", "http://www.facebook.com/share.php?" + IriSP.jQuery.param({ u: _url, t: _text }));
+    this.$.find(".Ldt-Social-Twitter").attr("href", "https://twitter.com/intent/tweet?" + IriSP.jQuery.param({ url: _url, text: _text }));
+    this.$.find(".Ldt-Social-Gplus").attr("href", "https://plusone.google.com/_/+1/confirm?" + IriSP.jQuery.param({ url: _url, title: _text }));
+    this.$.find(".Ldt-Social-Mail").attr("href", "mailto:?" + IriSP.jQuery.param({ subject: _text, body: _text + ": " + _url }));
+}
--- a/src/widgets/Trace.js	Fri Jun 29 16:22:52 2012 +0200
+++ b/src/widgets/Trace.js	Thu Jul 05 19:08:13 2012 +0200
@@ -9,7 +9,8 @@
     js_console : false,
     url: "http://traces.advene.org:5000/",
     requestmode: 'GET',
-    syncmode: "sync"
+    syncmode: "sync",
+    default_subject: "IRI"
 }
 
 IriSP.Widgets.Trace.prototype.draw = function() {
@@ -49,7 +50,8 @@
     this.tracer = window.tracemanager.init_trace("test", {
         url: this.url,
         requestmode: this.requestmode,
-        syncmode: this.syncmode
+        syncmode: this.syncmode,
+        default_subject: this.default_subject
     });
     this.tracer.trace("StartTracing", {});
     
Binary file src/widgets/img/socialbuttons.png has changed
--- a/test/dailymotion.htm	Fri Jun 29 16:22:52 2012 +0200
+++ b/test/dailymotion.htm	Thu Jul 05 19:08:13 2012 +0200
@@ -15,7 +15,7 @@
         <div id="LdtPlayer"></div>
         <div id="AnnotationsListContainer"></div>
         <script type="text/javascript">
-            testConfig('json/ldt-dailymotion.json', true);
+            testConfig('json/ldt-dailymotion.json', true, 'http://www.dailymotion.com/video/xodjrx_data-expression_creation');
         </script>
     </body>
 </html>
--- a/test/jwplayer.htm	Fri Jun 29 16:22:52 2012 +0200
+++ b/test/jwplayer.htm	Thu Jul 05 19:08:13 2012 +0200
@@ -25,7 +25,7 @@
     };
     var _config = {            
         gui: {
-            width : 620,
+            width : 550,
             container : 'LdtPlayer',
             default_options: {
                 metadata: _metadata
@@ -37,12 +37,17 @@
                 { type: "Polemic" },
                 { type: "Segments" },
                 { type: "Slice" },
-                { type: "Arrow" },
+                {
+                    type: "Arrow",
+                    base_height: 4
+                },
                 { type: "Annotation" },
                 {
                     type: "CreateAnnotation",
                     api_endpoint_template: "http://192.168.56.101/pf/ldtplatform/api/ldt/annotations/{{id}}.json",
-                    creator_name: "Metadataplayer"
+                    creator_name: "Metadataplayer",
+                    creator_avatar: "https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png",
+                    tag_titles: ["#amateur", "#digital-humanities"]
                 },
                 { type: "Tweet" },
                 {
@@ -59,7 +64,7 @@
             type:'auto',
             live: true, 
             height: 350, 
-            width: 620, 
+            width: 550, 
             provider: "rtmp",
             autostart: true,
             metadata: _metadata
--- a/unittests/README.txt	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-Layout of the unittests directory
-==================================
-
-We've got a directory for tests - unittests/tests. Add your tests there. There should be only one file per functionality area tested (i.e - all the
-tests about JSONSerializer should be in jsonserializer.js). Your tests should be wrapped in a function named "test_$filename$" where $filename$ is the
-name of your file. Don't forget to define a module for your tests and to add a reference to your file in index.html
--- a/unittests/index.html	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-<html>
-<head>
-	<title>Unit Tests</title>
-	<!-- the following libs are included only for unit testing -->
-	<script src="../res/js/jquery.min.js"></script>
-	<script src="../res/js/jquery.tools.min.js"></script>
-	<script src="../res/js/jquery-ui.min.js"></script>
-  
-  <!-- used by the jquery team to simulate events -->
-	<script src="jquery.simulate.js"></script>
-  
-	<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css" type="text/css" media="screen" />
-	<!-- -->	
-	
-	<script src="../build/LdtPlayer-release.js" type="text/javascript"></script>
-	<script src="../src/js/libs/popcorn.js" type="text/javascript"></script>
-	<script src="../src/js/libs/popcorn.code.js" type="text/javascript"></script>
-	<script src="../src/js/libs/popcorn.youtube.js" type="text/javascript"></script>
-	<script src="../src/js/libs/raphael.js" type="text/javascript"></script>
-	<script src="../src/js/libs/jquery.sparkline.js" type="text/javascript"></script>
-	<script src="../src/js/libs/underscore.js" type="text/javascript"></script>
-	<link rel="stylesheet" href="../src/css/LdtPlayer.css"  type="text/css" media="screen" />
-  
-	<script src="mockSerializer.js" type="text/javascript"></script>
-	<script src="mockTweetSerializer.js" type="text/javascript"></script>
-	<script src="qunit.js" type="text/javascript"></script>
-	<script src="sinon.js" type="text/javascript"></script>
-	<script src="sinon-ie.js" type="text/javascript"></script>
-	<script src="sinon-qunit.js" type="text/javascript"></script>
-	<link rel="stylesheet" href="qunit.css" type="text/css" media="screen" />
-	
-	<!-- tests -->
-	<script src="tests/dataloader.js" type="text/javascript"></script>
-	<script src="tests/serializer.js" type="text/javascript"></script>
-	<script src="tests/serializers/mockSerializer.js" type="text/javascript"></script>
-	<script src="tests/serializers/mockTweetSerializer.js" type="text/javascript"></script>
-	<script src="tests/serializers/JSONSerializer.js" type="text/javascript"></script>
-	<script src="tests/serializerFactory.js" type="text/javascript"></script>
-	<script src="tests/widget.js" type="text/javascript"></script>
-	<script src="tests/module.js" type="text/javascript"></script>
-	<script src="tests/utils.js" type="text/javascript"></script>	
-	<script src="tests/layout.js" type="text/javascript"></script>
-	<script src="tests/init.js" type="text/javascript"></script>
-  <script src="tests/widgets/playerWidget.js" type="text/javascript"></script>
-	<script src="tests/widgets/annotationsWidget.js" type="text/javascript"></script>
-  <script src="tests/widgets/segmentsWidget.js" type="text/javascript"></script> 
-  <script src="tests/widgets/tooltipWidget.js" type="text/javascript"></script>
-  <script src="tests/widgets/polemicWidget.js" type="text/javascript"></script>
-  <script src="tests/widgets/sliderWidget.js" type="text/javascript"></script>
-  <script src="tests/widgets/tweetsWidget.js" type="text/javascript"></script>
-	<script src="tests/widgets/arrowWidget.js" type="text/javascript"></script>
-	<script src="tests/widgets/sparklineWidget.js" type="text/javascript"></script>
-  
-</head>
-<script>
- $(document).ready(function(){ 
-		/* only for unit-testing ! */
-    IriSP.underscore = _;
-		IriSP.jQuery = jQuery;    
-		jQuery.fx.off = true;
-    
-		test_dataloader();
-		test_serializer();    
-		test_mockSerializer();
-		test_mockTweetSerializer();
-		test_JSONSerializer();
-		test_serializerFactory();
-    test_utils();
-		test_widget();
-		test_module();
-		test_player_widget();
-		test_annotations_widget();
-//		test_segments_widget();
-		test_layout();
-		test_init();
-		test_tooltip_widget();
-		test_polemic_widget();
-    test_slider_widget();
-//    test_tweets_widget();
-    test_arrow_widget();
-    test_sparkline_widget();
-});
-</script>	
-<body>
- <h1 id="qunit-header">Metadataplayer Unit Tests</h1>
- <h2 id="qunit-banner"></h2>
- <div id="qunit-testrunner-toolbar"></div>
- <h2 id="qunit-userAgent"></h2>
- <ol id="qunit-tests"></ol>
- <div id="qunit-fixture" style="position: float;">
-      <video id='popcorn-div' style="display:;width:300px" controls preload="auto">
-        <source id='mp4' src="../test/trailer.mp4" type='video/mp4; codecs="avc1, mp4a"'>
-        <source id='ogv' src="../test/trailer.ogv" type='video/ogg; codecs="theora, vorbis"'>      
-        <source id='webm' src="../test/trailer.webm" type='video/webm; codecs="vp8, vorbis"'>
-        <p>Your user agent does not support the HTML5 Video element.</p>
-      </video>
-        
-      <div id='widget-div'></div>
- </div>
-</body>
-</html>
--- a/unittests/jquery.simulate.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * jquery.simulate - simulate browser mouse and keyboard events
- *
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- */
-
-;(function($) {
-
-$.fn.extend({
-	simulate: function(type, options) {
-		return this.each(function() {
-			var opt = $.extend({}, $.simulate.defaults, options || {});
-			new $.simulate(this, type, opt);
-		});
-	}
-});
-
-$.simulate = function(el, type, options) {
-	this.target = el;
-	this.options = options;
-
-	if (/^drag$/.test(type)) {
-		this[type].apply(this, [this.target, options]);
-	} else {
-		this.simulateEvent(el, type, options);
-	}
-}
-
-$.extend($.simulate.prototype, {
-	simulateEvent: function(el, type, options) {
-		var evt = this.createEvent(type, options);
-		this.dispatchEvent(el, type, evt, options);
-		return evt;
-	},
-	createEvent: function(type, options) {
-		if (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {
-			return this.mouseEvent(type, options);
-		} else if (/^key(up|down|press)$/.test(type)) {
-			return this.keyboardEvent(type, options);
-		}
-	},
-	mouseEvent: function(type, options) {
-		var evt;
-		var e = $.extend({
-			bubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,
-			screenX: 0, screenY: 0, clientX: 0, clientY: 0,
-			ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
-			button: 0, relatedTarget: undefined
-		}, options);
-
-		var relatedTarget = $(e.relatedTarget)[0];
-
-		if ($.isFunction(document.createEvent)) {
-			evt = document.createEvent("MouseEvents");
-			evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
-				e.screenX, e.screenY, e.clientX, e.clientY,
-				e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
-				e.button, e.relatedTarget || document.body.parentNode);
-		} else if (document.createEventObject) {
-			evt = document.createEventObject();
-			$.extend(evt, e);
-			evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
-		}
-		return evt;
-	},
-	keyboardEvent: function(type, options) {
-		var evt;
-
-		var e = $.extend({ bubbles: true, cancelable: true, view: window,
-			ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
-			keyCode: 0, charCode: 0
-		}, options);
-
-		if ($.isFunction(document.createEvent)) {
-			try {
-				evt = document.createEvent("KeyEvents");
-				evt.initKeyEvent(type, e.bubbles, e.cancelable, e.view,
-					e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
-					e.keyCode, e.charCode);
-			} catch(err) {
-				evt = document.createEvent("Events");
-				evt.initEvent(type, e.bubbles, e.cancelable);
-				$.extend(evt, { view: e.view,
-					ctrlKey: e.ctrlKey, altKey: e.altKey, shiftKey: e.shiftKey, metaKey: e.metaKey,
-					keyCode: e.keyCode, charCode: e.charCode
-				});
-			}
-		} else if (document.createEventObject) {
-			evt = document.createEventObject();
-			$.extend(evt, e);
-		}
-		if ($.browser.msie || $.browser.opera) {
-			evt.keyCode = (e.charCode > 0) ? e.charCode : e.keyCode;
-			evt.charCode = undefined;
-		}
-		return evt;
-	},
-
-	dispatchEvent: function(el, type, evt) {
-		if (el.dispatchEvent) {
-			el.dispatchEvent(evt);
-		} else if (el.fireEvent) {
-			el.fireEvent('on' + type, evt);
-		}
-		return evt;
-	},
-
-	drag: function(el) {
-		var self = this, center = this.findCenter(this.target), 
-			options = this.options,	x = Math.floor(center.x), y = Math.floor(center.y), 
-			dx = options.dx || 0, dy = options.dy || 0, target = this.target;
-		var coord = { clientX: x, clientY: y };
-		this.simulateEvent(target, "mousedown", coord);
-		coord = { clientX: x + 1, clientY: y + 1 };
-		this.simulateEvent(document, "mousemove", coord);
-		coord = { clientX: x + dx, clientY: y + dy };
-		this.simulateEvent(document, "mousemove", coord);
-		this.simulateEvent(document, "mousemove", coord);
-		this.simulateEvent(target, "mouseup", coord);
-	},
-	findCenter: function(el) {
-		var el = $(this.target), o = el.offset();
-		return {
-			x: o.left + el.outerWidth() / 2,
-			y: o.top + el.outerHeight() / 2
-		};
-	}
-});
-
-$.extend($.simulate, {
-	defaults: {
-		speed: 'sync'
-	},
-	VK_TAB: 9,
-	VK_ENTER: 13,
-	VK_ESC: 27,
-	VK_PGUP: 33,
-	VK_PGDN: 34,
-	VK_END: 35,
-	VK_HOME: 36,
-	VK_LEFT: 37,
-	VK_UP: 38,
-	VK_RIGHT: 39,
-	VK_DOWN: 40
-});
-
-})(jQuery);
--- a/unittests/mockSerializer.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1471 +0,0 @@
-/* mock serializer, for unit testing. This file is separated from data.js
-   because the stub data is huge an we don't want to ship it with the rest
-   of the app */
-
-IriSP.MockSerializer = function(DataLoader, url) {
-  IriSP.Serializer.call(this, DataLoader, url);
-  this._data = IriSP.MockSerializer.prototype._data;
-};
-
-IriSP.MockSerializer.prototype = new IriSP.JSONSerializer();   
-
-IriSP.MockSerializer.prototype.currentMedia = function() {
-  return this._data.medias[0];
-};
-
-IriSP.MockSerializer.prototype.sync = IriSP.Serializer.prototype.sync;
-
-IriSP.MockSerializer.prototype._data = { "tags": [
-      {
-          "meta": {
-            "dc:contributor": "IRI ", 
-            "dc:created": "2010-09-06T15:53:44.618963", 
-            "dc:title": "suffrage universel", 
-            "dc:modified": "2010-09-06T15:53:44.618963", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaabd04-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.621828", 
-            "dc:title": "Patrick Rogiers", 
-            "dc:modified": "2010-09-06T15:53:44.621828", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edab1fec-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.575615", 
-            "dc:title": "Kirgistan", 
-            "dc:modified": "2010-09-06T15:53:44.575615", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "eda50fb2-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.600158", 
-            "dc:title": "Alphonse Baudin", 
-            "dc:modified": "2010-09-06T15:53:44.600158", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "eda8ba7c-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.618963", 
-            "dc:title": "mandats rétribués", 
-            "dc:modified": "2010-09-06T15:53:44.618963", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaab0b6-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.621828", 
-            "dc:title": "Belgique", 
-            "dc:modified": "2010-09-06T15:53:44.621828", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edab1808-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.609400", 
-            "dc:title": "18juin", 
-            "dc:modified": "2010-09-06T15:53:44.609400", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaa23f8-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.621828", 
-            "dc:title": "Wallons", 
-            "dc:modified": "2010-09-06T15:53:44.621828", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edab2730-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.626707", 
-            "dc:title": "theatre.doc", 
-            "dc:modified": "2010-09-06T15:53:44.626707", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edabd6b2-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.609400", 
-            "dc:title": "marée noire", 
-            "dc:modified": "2010-09-06T15:53:44.609400", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaa3aaa-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.621828", 
-            "dc:title": "Flamands", 
-            "dc:modified": "2010-09-06T15:53:44.621828", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edab1c36-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.618963", 
-            "dc:title": "Auguste Baudin", 
-            "dc:modified": "2010-09-06T15:53:44.618963", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaaa8dc-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.575615", 
-            "dc:title": "retraite", 
-            "dc:modified": "2010-09-06T15:53:44.575615", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "eda7047a-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.618963", 
-            "dc:title": "financement politique", 
-            "dc:modified": "2010-09-06T15:53:44.618963", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaaad00-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.609400", 
-            "dc:title": "Bloody Sunday", 
-            "dc:modified": "2010-09-06T15:53:44.609400", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaa329e-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.621828", 
-            "dc:title": "éléction", 
-            "dc:modified": "2010-09-06T15:53:44.621828", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edab2b68-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.618963", 
-            "dc:title": "suffrage directs", 
-            "dc:modified": "2010-09-06T15:53:44.618963", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaab962-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.621828", 
-            "dc:title": "vuvuzela", 
-            "dc:modified": "2010-09-06T15:53:44.621828", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edab238e-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.609400", 
-            "dc:title": "Domenech", 
-            "dc:modified": "2010-09-06T15:53:44.609400", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaa36ea-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.624524", 
-            "dc:title": "sociologie du sport", 
-            "dc:modified": "2010-09-06T15:53:44.624524", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edab8162-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.575615", 
-            "dc:title": "Mondiale", 
-            "dc:modified": "2010-09-06T15:53:44.575615", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "eda60c8c-b9ce-11df-9e63-00145ea4a2be"
-        }, 
-        {
-          "meta": {
-            "dc:contributor": "IRI", 
-            "dc:created": "2010-09-06T15:53:44.618963", 
-            "dc:title": "professionalisation de la politique", 
-            "dc:modified": "2010-09-06T15:53:44.618963", 
-            "dc:creator": "IRI"
-          }, 
-          "id": "edaab5c0-b9ce-11df-9e63-00145ea4a2be"
-        }
-      ], 
-      "views": null, 
-      "lists": [
-        {
-          "items": [
-            {
-              "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560"
-            }, 
-            {
-              "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795"
-            }, 
-            {
-              "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831"
-            }, 
-            {
-              "id-ref": "c_DE60F95E-73B8-922D-3AC7-6FB197A1BF16"
-            }
-          ], 
-          "meta": {
-            "dc:contributor": "undefined", 
-            "dc:created": "2010-09-06T15:53:44.572185", 
-            "dc:creator": "perso", 
-            "id-ref": "franceculture_retourdudimanche20100620", 
-            "dc:title": "Découpages personnels", 
-            "editable": "false", 
-            "dc:modified": "2010-09-06T15:53:44.572185", 
-            "dc:description": ""
-          }, 
-          "id": "ens_perso"
-        }
-      ], 
-      "medias": [
-        {
-          "origin": "0", 
-          "http://advene.liris.cnrs.fr/ns/frame_of_reference/ms": "o=0", 
-          "href": "rtmp://media.iri.centrepompidou.fr/ddc_player/video/franceculture/franceculture_retourdudimanche20100620.flv", 
-          "meta": {
-            "dc:contributor": "IRI", 
-            "item": {
-              "name": "streamer", 
-              "value": "rtmp://media.iri.centrepompidou.fr/ddc_player/"
-            }, 
-            "dc:created": "2010-06-25T16:58:36.186952", 
-            "dc:duration": 3016000, 
-            "dc:creator": "IRI", 
-            "dc:created.contents": "2010-06-25", 
-            "dc:title": "FC Retour du dimanche 2010-06-20", 
-            "dc:creator.contents": "IRI", 
-            "dc:modified": "2010-06-25T16:58:36.187009", 
-            "dc:description": "France Culture. Retour du dimanche 2010-06-20"
-          }, 
-          "id": "franceculture_retourdudimanche20100620", 
-          "unit": "ms"
-        }
-      ], 
-      "meta": {
-        "dc:contributor": "admin", 
-        "dc:created": "2010-07-12T00:30:40.272719", 
-        "dc:creator": "admin", 
-        "main_media": {
-          "id-ref": "franceculture_retourdudimanche20100620"
-        }, 
-        "dc:description": "", 
-        "dc:title": "RetourDimanche20juin_decoupageChronique", 
-        "id": "ef4dcc2e-8d3b-11df-8a24-00145ea4a2be", 
-        "dc:modified": "2010-08-25T11:39:25.507013"
-      }, 
-      "annotations": [
-        {
-          "begin": "0", 
-          "end": 88414, 
-          "tags": [
-            {
-              "id-ref": "eda50fb2-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "eda60c8c-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "eda7047a-b9ce-11df-9e63-00145ea4a2be"
-            }
-          ], 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "16776960", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": "Générique"
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-            "dc:created": "2010-09-06T15:53:44.572226", 
-            "dc:modified": "2010-09-06T15:53:44.572226", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_32C565F4-15F4-E7CB-EBC5-6FB51DAC635C"
-        }, 
-        {
-          "begin": "88422", 
-          "end": 169831, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "6684774", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": "Sommaire"
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-            "dc:created": "2010-09-06T15:53:44.572226", 
-            "dc:modified": "2010-09-06T15:53:44.572226", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_8F385150-64B3-7539-AB94-6FB51DAC40B4"
-        }, 
-        {
-          "begin": "170235", 
-          "end": 316123, 
-          "tags": [
-            {
-              "id-ref": "eda8ba7c-b9ce-11df-9e63-00145ea4a2be"
-            }
-          ], 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "10027008", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "L'invité : Alain Guarrigue, sur Alphonse Baudin", 
-            "title": "Présentation de l'invité - Alain Garrigou"
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-            "dc:created": "2010-09-06T15:53:44.572226", 
-            "dc:modified": "2010-09-06T15:53:44.572226", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_948A7C82-DD23-8CAC-27D4-6FB51DAC7D41"
-        }, 
-        {
-          "begin": "316720", 
-          "end": 694781, 
-          "tags": [
-            {
-              "id-ref": "edaa23f8-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaa329e-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaa36ea-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaa36ea-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaa3aaa-b9ce-11df-9e63-00145ea4a2be"
-            }
-          ], 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "6736896", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": "Revue d'actualité - Hervé Gardette"
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-            "dc:created": "2010-09-06T15:53:44.572226", 
-            "dc:modified": "2010-09-06T15:53:44.572226", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_54DB840E-01AC-D042-37E2-B2BA1E18B47C"
-        }, 
-        {
-          "begin": "695261", 
-          "end": 1772062, 
-          "tags": [
-            {
-              "id-ref": "edaaa8dc-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaaad00-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaab0b6-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaab5c0-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaab962-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edaabd04-b9ce-11df-9e63-00145ea4a2be"
-            }
-          ], 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "10027008", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": "Invité spécial - Alain Garrigou"
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-            "dc:created": "2010-09-06T15:53:44.572226", 
-            "dc:modified": "2010-09-06T15:53:44.572226", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_BDB0677D-DBF9-D198-896B-B2BDB9012D54"
-        }, 
-        {
-          "begin": "1772707", 
-          "end": 2515173, 
-          "tags": [
-            {
-              "id-ref": "edab1808-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edab1c36-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edab1fec-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edab238e-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edab2730-b9ce-11df-9e63-00145ea4a2be"
-            }, 
-            {
-              "id-ref": "edab2b68-b9ce-11df-9e63-00145ea4a2be"
-            }
-          ], 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "6749952", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": "Revue de presse - Hervé Gardette"
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-            "dc:created": "2010-09-06T15:53:44.572226", 
-            "dc:modified": "2010-09-06T15:53:44.572226", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_3FC1D037-34A3-FEF7-541C-B2C31ED973A8"
-        }, 
-        {
-          "begin": "2516091", 
-          "end": 2646767, 
-          "tags": [
-            {
-              "id-ref": "edab8162-b9ce-11df-9e63-00145ea4a2be"
-            }
-          ], 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "10027008", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": "Le sujet de l'invité : la sociologie du sport - Alain Garrigou"
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-            "dc:created": "2010-09-06T15:53:44.572226", 
-            "dc:modified": "2010-09-06T15:53:44.572226", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_82613B88-9578-DC2C-D7D0-B2C5BE0B7BDA"
-        }, 
-        {
-          "begin": "2647012", 
-          "end": 3012503, 
-          "tags": [
-            {
-              "id-ref": "edabd6b2-b9ce-11df-9e63-00145ea4a2be"
-            }
-          ], 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "16776960", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": "Chronique du Courrier International - Antony Bélanger"
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-            "dc:created": "2010-09-06T15:53:44.572226", 
-            "dc:modified": "2010-09-06T15:53:44.572226", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_24324ACF-E8D0-46FE-E977-B2C7D1A1FBAA"
-        }, 
-        {
-          "begin": "902235", 
-          "end": 1022560, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Garrigou : financement politique, suffrage universel et direct et mandats rétribués,", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_C5118055-7575-43BD-05BA-B2B91B977B61"
-        }, 
-        {
-          "begin": "1022560", 
-          "end": 1029340, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Caroline Broué", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_224FA6AF-AC6B-5412-C882-B2B91B97A0BC"
-        }, 
-        {
-          "begin": "1029340", 
-          "end": 1123892, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Garrigou : professionalisation de la politique, promotion sociale et financière", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_99950FC3-A79B-9A08-5E90-B2B91B97C844"
-        }, 
-        {
-          "begin": "1123892", 
-          "end": 1135827, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "CBroué : mourir pour des idées", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_7DE30BA7-4E61-F41D-9EB8-B2B91B97C4C1"
-        }, 
-        {
-          "begin": "1135827", 
-          "end": 1195874, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Archives Radio : Auguste Bodin, mourrir pour 25 francs", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_C588B92E-EB4F-B383-4D50-B2B91B97B4C2"
-        }, 
-        {
-          "begin": "1195874", 
-          "end": 1215565, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "C.Broué : geste et figure du député. Emblématique.", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_87A5F46B-9588-4C02-24B6-B2B91B97037A"
-        }, 
-        {
-          "begin": "1215565", 
-          "end": 1391433, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Garrigou : mourrir pour des idées est valorisé, grandeur humaine au 19è siècle\nVictor Hugo esthétise Bodin\nSouscription de bodin ou se révèle Gambetta", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_1CF29EC2-1109-25FF-F8D7-B2B91B97944A"
-        }, 
-        {
-          "begin": "1391433", 
-          "end": 1451340, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "C.Broué : héros civique, figure disparue,\ndéfense de l'indémnité parlementaire\nl'intérete a repris le dessus sur la politique", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_B3A6C0FE-10B0-91D2-BC98-B2B91B97EC15"
-        }, 
-        {
-          "begin": "1451340", 
-          "end": 1539483, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Garrigou : humour de Bodin, \non ne meurt pas pour de l'argent, \nl'argent n'est pas une conviction,\nHéros : héros guerrier, le Saint ou martyr,", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_FE44EC82-002E-3A78-B712-B2B91B975C76"
-        }, 
-        {
-          "begin": "1539483", 
-          "end": 1547610, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "C.Broué : Degaulle figure de héros civique ?", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_943F5904-D438-F263-C8B4-B2B91B97608C"
-        }, 
-        {
-          "begin": "1547610", 
-          "end": 1659484, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Garrigou : appel à la désobéissance, résistance de Bodin et Résistance de J.Moulin\nhéros civique : personnage anonyme\nca n'est pas le soldat, ni le saint, ni le Grand Homme", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_FBB30EA9-8699-E909-62BA-B2B91B9792C6"
-        }, 
-        {
-          "begin": "1659484", 
-          "end": 1720413, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "C.Broué : autonomisation du champs politique par rapport à l'intéret économique.\nperspective contemporaine : tenter de rétablir une certaine morale publique.", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_8F2D73FD-4C22-DE0A-E22A-B2B91B97CA92"
-        }, 
-        {
-          "begin": "1720413", 
-          "end": 1773308, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Garrigou : société post-héroique : la politique est une question économique\nsociété d'irresponsabilité,", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_716B6123-2040-71A2-3B8F-B2B91B978EF1"
-        }, 
-        {
-          "begin": "1773308", 
-          "end": 1846311, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Gardette : transition\nBelgique a voté. Flamand fait une percée historique. Tsunami politique ?\ninstabilité politique", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_1D64F959-8A86-FD3E-3FD1-B2B91B972648"
-        }, 
-        {
-          "begin": "1846311", 
-          "end": 2176406, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Patrick Rogiers : sur les résutats des élections belges", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_D7398F00-E4F5-9692-88D0-B2B91B976204"
-        }, 
-        {
-          "begin": "2176406", 
-          "end": 2207985, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Gardette : transition\nC. Broué : montée des nationalismes et séparatismes", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_21BCA9F6-A71C-C601-1247-B2B91B97A664"
-        }, 
-        {
-          "begin": "2207985", 
-          "end": 2248713, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Garrigou : sur les séparatismes, narcissisme des petites différences", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_45E25D8E-416B-8158-23DD-B2B91B9745CE"
-        }, 
-        {
-          "begin": "2248713", 
-          "end": 2519086, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "H. Gardette : Vuvuzela : tradition et calvaire", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_88FBDAB0-64C7-74B9-7C5A-B2B91B977EC3"
-        }, 
-        {
-          "begin": "2519086", 
-          "end": 2540542, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "C.Broué : question à Garrigou : sociologie du sport", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_6506C8B0-AAB0-3678-31FD-B2B91B978702"
-        }, 
-        {
-          "begin": "2540542", 
-          "end": 2647121, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Elimination de l'équipe de France\nArgent, politique du foot", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_CB104420-63C8-F957-78CF-B2B91B97D0B0"
-        }, 
-        {
-          "begin": "2647121", 
-          "end": 2657384, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "intermède musical", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_1947C9C6-B47F-1544-AD5E-B2B91B97A552"
-        }, 
-        {
-          "begin": "2657384", 
-          "end": 3012515, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Antony Bélanger (Courrier International) : Moscou, pièce de théatre à guichet fermé\nTheatre.doc : agonie de l'avocat en prison", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_874A4942-9AA9-CA9A-F595-B2B91B97210A"
-        }, 
-        {
-          "begin": "3012515", 
-          "end": 3013515, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-            "dc:created": "2010-09-06T15:53:44.626882", 
-            "dc:modified": "2010-09-06T15:53:44.626882", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_1F7790E7-BC3F-6C87-9B4F-B2B91B9769B6"
-        }, 
-        {
-          "begin": "206240", 
-          "end": 316720, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Interview : Alphonse Baudin\n\"comment meurt vos 25 francs\"\nabolitionniste, barricade,Victor Hugo, Victor", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_9CA4F1C6-6FA0-7070-EBCA-B293F1474ECC"
-        }, 
-        {
-          "begin": "316720", 
-          "end": 546458, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "actualité de Gardette : \n- Domenech et défaite francaise contre le Mexique\n- La France aura eu besoin de De Gaulle\n- 18 juin : 1815, défaite de waterloo\ndéfaite de Dien Bien \n- Belgique: éléctions et divorce Wallon et Flamands\n- Kirgistan : Pogrom contre les Ouzbeks, 200 morts.\n- Conflits Israélo-palestinien : enquete indépendante\n- Bloody Sunday, London dairy, répression sanglante. Rapport conclut à la seule culpabilité de l'armée britannique", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_F1A706C3-8CFD-8479-FE1A-B293F147FB10"
-        }, 
-        {
-          "begin": "546458", 
-          "end": 552728, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "intermède musicale", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_D87336F4-AF1E-1192-AD6F-B293F14750F6"
-        }, 
-        {
-          "begin": "552728", 
-          "end": 694963, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Retraite, travail allongé : méthode douce du gouvernement\nTony Eward communicant BP\nCatastrophe dans le Var\nApéro saucisson et pinard interdit\nécrivain portugais Saramago : l'évangile selon Jésus Christ", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_EA074915-79A3-E8C3-A7BD-B293F1472B4A"
-        }, 
-        {
-          "begin": "695261", 
-          "end": 725426, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "commentaire Alain Guarigou", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_20B4A5D9-D87C-329A-8D6E-B293F147D954"
-        }, 
-        {
-          "begin": "725716", 
-          "end": 784695, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Fond public - fond privé", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_F0A40BE7-0DE5-F4AE-00E7-B293F147C76E"
-        }, 
-        {
-          "begin": "784695", 
-          "end": 802807, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Gardette : Francois Fillon veut montrer l'exemple", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_801AE38E-9E88-347D-365A-B293F147FA32"
-        }, 
-        {
-          "begin": "802807", 
-          "end": 853566, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Reportage : Fillon et les privilèges des politiques", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_F5F3F6C7-2152-6FCA-3838-B293F147F4A6"
-        }, 
-        {
-          "begin": "853566", 
-          "end": 870284, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Caroline Broué à Garrigou : les privilèges ?", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_F01AD8C9-6F7F-0ED8-FCB8-B293F147EAE0"
-        }, 
-        {
-          "begin": "870284", 
-          "end": 899309, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "Réponse : privilège du cumul.", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_306A6A5E-BB28-DBB3-1B2C-B293F147B879"
-        }, 
-        {
-          "begin": "899309", 
-          "end": 900309, 
-          "tags": null, 
-          "media": "franceculture_retourdudimanche20100620", 
-          "content": {
-            "mimetype": "application/x-ldt-structured", 
-            "color": "255", 
-            "audio": {
-              "mimetype": "audio/mp3", 
-              "src": "", 
-              "href": ""
-            }, 
-            "description": "", 
-            "title": ""
-          }, 
-          "meta": {
-            "dc:contributor": "perso", 
-            "id-ref": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-            "dc:created": "2010-09-06T15:53:44.675786", 
-            "dc:modified": "2010-09-06T15:53:44.675786", 
-            "dc:creator": "perso"
-          }, 
-          "id": "s_40445FD2-80E5-F9C9-57B8-B293F1472D60"
-        }
-      ], 
-      "annotation-types": [
-        {
-          "dc:contributor": "perso", 
-          "dc:creator": "perso", 
-          "dc:title": "Chapitrage Notes", 
-          "id": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-          "dc:created": "2010-09-06T15:53:44.572226", 
-          "dc:description": "", 
-          "dc:modified": "2010-09-06T15:53:44.572226"
-        }, 
-        {
-          "dc:contributor": "perso", 
-          "dc:creator": "perso", 
-          "dc:title": "Mes notes", 
-          "id": "c_F6BB72C6-686E-1E8A-D775-B2B91B97C795", 
-          "dc:created": "2010-09-06T15:53:44.626882", 
-          "dc:description": "", 
-          "dc:modified": "2010-09-06T15:53:44.626882"
-        }, 
-        {
-          "dc:contributor": "perso", 
-          "dc:creator": "perso", 
-          "dc:title": "Mes notes", 
-          "id": "c_393E05F0-80CC-9D29-A42B-B293F1478831", 
-          "dc:created": "2010-09-06T15:53:44.675786", 
-          "dc:description": "", 
-          "dc:modified": "2010-09-06T15:53:44.675786"
-        }, 
-        {
-          "dc:contributor": "perso", 
-          "dc:creator": "perso", 
-          "dc:title": "Chapitrage", 
-          "id": "c_DE60F95E-73B8-922D-3AC7-6FB197A1BF16", 
-          "dc:created": "2010-09-06T15:53:44.699595", 
-          "dc:description": "", 
-          "dc:modified": "2010-09-06T15:53:44.699595"
-        }
-      ]};
--- a/unittests/mockTweetSerializer.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1389 +0,0 @@
-/* mock serializer, for unit testing. This file is separated from data.js
-   because the stub data is huge an we don't want to ship it with the rest
-   of the app */
-
-IriSP.MockTweetSerializer = function(DataLoader, url) {
-  IriSP.Serializer.call(this, DataLoader, url);
-  this._data = IriSP.MockTweetSerializer.prototype._data;
-};
-
-IriSP.MockTweetSerializer.prototype = new IriSP.Serializer();   
-
-IriSP.MockTweetSerializer.prototype.currentMedia = function() {
-  return this._data.medias[0];
-};
-
-// Copy some methods from JSONSerializer because we need them in
-// some tests.
-
-IriSP.MockTweetSerializer.prototype.searchAnnotations = IriSP.JSONSerializer.prototype.searchAnnotations;
-IriSP.MockTweetSerializer.prototype.searchOccurences = IriSP.JSONSerializer.prototype.searchOccurences;
-
-IriSP.MockTweetSerializer.prototype._data = {
-"views": [
-{
-"id": "0", 
-"contents": [
-"914e1bcc-b6e0-11e0-a965-00145ea49a02"
-], 
-"annotation_types": [
-"c_5AEE45AE-F0E5-2921-31CB-2683540AA7A4", 
-"61bcaa2e-9963-4df2-a987-34c08e184fb6"
-]
-}
-], 
-"tags": [
-{
-"meta": {
-"dc:contributor": "IRI", 
-"dc:created": "2011-11-03T14:57:21.009848", 
-"dc:title": "libidinal", 
-"dc:modified": "2011-11-03T14:57:21.009848", 
-"dc:creator": "IRI"
-}, 
-"id": "219d25fc-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"meta": {
-"dc:contributor": "IRI", 
-"dc:created": "2011-11-03T14:57:20.999902", 
-"dc:title": "eg8", 
-"dc:modified": "2011-11-03T14:57:20.999902", 
-"dc:creator": "IRI"
-}, 
-"id": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"meta": {
-"dc:contributor": "IRI", 
-"dc:created": "2011-11-03T14:57:20.993496", 
-"dc:title": "enmi", 
-"dc:modified": "2011-11-03T14:57:20.993496", 
-"dc:creator": "IRI"
-}, 
-"id": "219aa55c-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"meta": {
-"dc:contributor": "IRI", 
-"dc:created": "2011-11-03T14:57:20.995151", 
-"dc:title": "Hadopi", 
-"dc:modified": "2011-11-03T14:57:20.995151", 
-"dc:creator": "IRI"
-}, 
-"id": "219ae77e-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"meta": {
-"dc:contributor": "IRI", 
-"dc:created": "2011-11-03T14:57:20.995151", 
-"dc:title": "eG8", 
-"dc:modified": "2011-11-03T14:57:20.995151", 
-"dc:creator": "IRI"
-}, 
-"id": "219ae30a-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"meta": {
-"dc:contributor": "IRI", 
-"dc:created": "2011-11-03T14:57:21.009848", 
-"dc:title": "contribution", 
-"dc:modified": "2011-11-03T14:57:21.009848", 
-"dc:creator": "IRI"
-}, 
-"id": "219d2156-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"meta": {
-"dc:contributor": "IRI", 
-"dc:created": "2011-11-03T14:57:20.993496", 
-"dc:title": "trust", 
-"dc:modified": "2011-11-03T14:57:20.993496", 
-"dc:creator": "IRI"
-}, 
-"id": "219aaab6-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"meta": {
-"dc:contributor": "IRI", 
-"dc:created": "2011-11-03T14:57:20.999902", 
-"dc:title": "barlow", 
-"dc:modified": "2011-11-03T14:57:20.999902", 
-"dc:creator": "IRI"
-}, 
-"id": "219b9c96-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"lists": [
-{
-"items": [
-{
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6"
-}
-], 
-"meta": {
-"dc:contributor": "undefined", 
-"dc:created": "2011-11-03T14:57:20.992502", 
-"dc:creator": "undefined", 
-"id-ref": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"dc:title": "Découpages personnels", 
-"editable": "false", 
-"dc:modified": "2011-11-03T14:57:20.992502", 
-"dc:description": ""
-}, 
-"id": "tweet_CB21314C-490A-91C7-ADAF-6212DFCF4E23"
-}, 
-{
-"items": [
-{
-"id-ref": "c_5AEE45AE-F0E5-2921-31CB-2683540AA7A4"
-}
-], 
-"meta": {
-"dc:contributor": "undefined", 
-"dc:created": "2011-11-03T14:57:21.010261", 
-"dc:creator": "undefined", 
-"id-ref": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"dc:title": "Découpages personnels", 
-"editable": "false", 
-"dc:modified": "2011-11-03T14:57:21.010261", 
-"dc:description": ""
-}, 
-"id": "g_CB21314C-490A-91C7-ADAF-6212DFCF4E23"
-}
-], 
-"medias": [
-{
-"origin": "0", 
-"http://advene.liris.cnrs.fr/ns/frame_of_reference/ms": "o=0", 
-"href": "rtmp://media.iri.centrepompidou.fr/ddc_player/video/enmi/iri_enmiprepa2011_1bs.flv", 
-"meta": {
-"dc:contributor": "IRI", 
-"item": {
-"name": "streamer", 
-"value": "rtmp://media.iri.centrepompidou.fr/ddc_player/"
-}, 
-"dc:created": "2011-07-25T19:08:41.797402", 
-"dc:duration": 1699997, 
-"dc:creator": "IRI", 
-"dc:created.contents": "2011-07-25", 
-"dc:title": "Bernard Stiegler - Introduction ENMI préparatoires 2011", 
-"dc:creator.contents": "IRI", 
-"dc:modified": "2011-07-25T19:08:41.862348", 
-"dc:description": ""
-}, 
-"id": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"unit": "ms"
-}
-], 
-"meta": {
-"dc:contributor": "admin", 
-"dc:created": "2011-07-25T19:08:53.255900", 
-"dc:creator": "admin", 
-"main_media": {
-"id-ref": "914e1bcc-b6e0-11e0-a965-00145ea49a02"
-}, 
-"dc:description": "", 
-"dc:title": " \tBernard Stiegler - Introduction ENMI préparatoires 2011", 
-"id": "c609832e-b6e0-11e0-9f0f-00145ea49a02", 
-"dc:modified": "2011-07-25T20:01:12.072312"
-}, 
-"annotations": [
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "Bernard Stiegler : Introduction. Nouvel espace public - Wikileaks\nToute publication implique une dissimulation. Estia : le privé c'est le domestique. Le rapport public - privé est profondement bouleversé. Privé = privatisation (des données privées commercialisées). Nous sommes motivés par le désir de publication dont les industries culturelles nous ont privé. Ethique à Nicomaque (Aristote): il n'y a pas de confirance sans filia (amitié).", 
-"img": {
-"src": ""
-}, 
-"title": "Introduction", 
-"color": "16711680", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "undefined", 
-"href": null
-}
-}, 
-"begin": 4364, 
-"meta": {
-"dc:contributor": "perso", 
-"id-ref": "c_5AEE45AE-F0E5-2921-31CB-2683540AA7A4", 
-"dc:created": "2011-11-03T14:57:21.010291", 
-"dc:modified": "2011-11-03T14:57:21.010291", 
-"dc:creator": "perso"
-}, 
-"end": 445403, 
-"tags": null, 
-"color": "16711680", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "s_41FCF75C-4DBC-E109-57A2-2683540BC343"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "Première considération. Antigone : Le choeur dit ce qu'est l'Homme : inquiétant est l'homme. Hegel ajoute : la sagesse procède de l'inquiétude. Freud : l'inquiétante étrangeté, fin de la quiétude.", 
-"img": {
-"src": ""
-}, 
-"title": "Première considération", 
-"color": "16737792", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "undefined", 
-"href": null
-}
-}, 
-"begin": 446166, 
-"meta": {
-"dc:contributor": "perso", 
-"id-ref": "c_5AEE45AE-F0E5-2921-31CB-2683540AA7A4", 
-"dc:created": "2011-11-03T14:57:21.010291", 
-"dc:modified": "2011-11-03T14:57:21.010291", 
-"dc:creator": "perso"
-}, 
-"end": 683750, 
-"tags": null, 
-"color": "16737792", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "s_ABD0E503-B166-8AAD-7109-2683540BA6C9"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "Le double redoublement époqual (Epoké: suspension du rapport au monde)\nHusserl : nous sommes dans une époké technologique. La confiance passe par un système technique (imprimerie puis Luther) selon B. Gilles. Ces espaces de confiance sont repris par Max Weber (la foi est la conception monothéiste de la confiance) et doivent être calculables.", 
-"img": {
-"src": ""
-}, 
-"title": "Le double redoublement époqual", 
-"color": "16750848", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "undefined", 
-"href": null
-}
-}, 
-"begin": 683750, 
-"meta": {
-"dc:contributor": "perso", 
-"id-ref": "c_5AEE45AE-F0E5-2921-31CB-2683540AA7A4", 
-"dc:created": "2011-11-03T14:57:21.010291", 
-"dc:modified": "2011-11-03T14:57:21.010291", 
-"dc:creator": "perso"
-}, 
-"end": 1132168, 
-"tags": null, 
-"color": "16750848", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "s_A677A43D-BD3A-E2EB-46F5-2683540B5B5E"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "La confiance, la foi, la croyance, la filia, tous ces contextes repassent par le concept de l'économie libidinale introduit par Freud. Ethique Hacker (Himanen) : réaction au désinvestissement libidinal. Nous sommes dans un processus de défiance et d'infantilisation de régression (catastrophé). Rôle grandissant des tiers de confiance.", 
-"img": {
-"src": ""
-}, 
-"title": "Économie libidinale - tiers de confiance", 
-"color": "13369344", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "undefined", 
-"href": null
-}
-}, 
-"begin": 1132168, 
-"meta": {
-"dc:contributor": "perso", 
-"id-ref": "c_5AEE45AE-F0E5-2921-31CB-2683540AA7A4", 
-"dc:created": "2011-11-03T14:57:21.010291", 
-"dc:modified": "2011-11-03T14:57:21.010291", 
-"dc:creator": "perso"
-}, 
-"end": 1694349, 
-"tags": null, 
-"color": "13369344", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "s_D68D6DC7-756D-0A6C-80C8-2683540B8F72"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "", 
-"img": {
-"src": ""
-}, 
-"title": "", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "undefined", 
-"href": null
-}
-}, 
-"begin": 1694349, 
-"meta": {
-"dc:contributor": "perso", 
-"id-ref": "c_5AEE45AE-F0E5-2921-31CB-2683540AA7A4", 
-"dc:created": "2011-11-03T14:57:21.010291", 
-"dc:modified": "2011-11-03T14:57:21.010291", 
-"dc:creator": "perso"
-}, 
-"end": 1696543, 
-"tags": null, 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "s_C6A7D84F-B50D-F756-2CAE-2683540B2F12"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "RT @amil310: #enmi RT @amil310: #trust Waiting for Bernard Stiegler Can we trust in SNCF, really? Follow the seminar at http://bit.ly/l4ZbO4", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg"
-}, 
-"title": "Alexandre Monnin: RT @amil310: #enmi RT @amil310: #trust Waiting for Bernard Stiegler Can we trust in SNCF, really? Follow the seminar at http://bit.ly/l4ZbO4", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 15000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 7409472, \"verified\": false, \"profile_sidebar_fill_color\": \"E3E2DE\", \"profile_text_color\": \"634047\", \"followers_count\": 371, \"protected\": false, \"location\": \"Paris\", \"default_profile_image\": false, \"listed_count\": 68, \"utc_offset\": -10800, \"statuses_count\": 2825, \"description\": \"PhD student in Philosophy working on ontologies (computer & philo ones), tagging, Semantic Web, DigitalH, but mostly advocate for the Philosophy of the Web.\", \"friends_count\": 457, \"profile_link_color\": \"088253\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"EDECE9\", \"id_str\": \"7409472\", \"profile_background_image_url\": \"http://a1.twimg.com/images/themes/theme3/bg.gif\", \"name\": \"Alexandre Monnin\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 6, \"screen_name\": \"aamonnz\", \"url\": \"http://execo.univ-paris1.fr/spip.php?article67\", \"created_at\": \"Wed Jul 11 18:52:41 +0000 2007\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"D3D2CF\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"retweeted_status\": {\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 137694060, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 60, \"protected\": false, \"location\": \"Lyon, France\", \"default_profile_image\": false, \"listed_count\": 9, \"utc_offset\": null, \"statuses_count\": 138, \"description\": \"Prof, University Lyon1, France. Computer Science, Dynamic Knowledge Management and Engineering, Chair www2012\", \"friends_count\": 33, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a0.twimg.com/profile_images/855353678/alain_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"137694060\", \"profile_background_image_url\": \"http://a0.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Alain Mille\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 1, \"screen_name\": \"amil310\", \"url\": \"http://liris.cnrs.fr/alain.mille\", \"created_at\": \"Tue Apr 27 13:25:54 +0000 2010\", \"contributors_enabled\": false, \"time_zone\": null, \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [{\"indices\": [9, 17], \"id\": 137694060, \"id_str\": \"137694060\", \"name\": \"Alain Mille\", \"screen_name\": \"amil310\"}], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}, {\"indices\": [19, 25], \"text\": \"trust\"}], \"urls\": [{\"indices\": [107, 127], \"url\": \"http://bit.ly/l4ZbO4\", \"expanded_url\": null}]}, \"text\": \"#enmi RT @amil310: #trust Waiting for Bernard Stiegler Can we trust in SNCF, really? Follow the seminar at http://bit.ly/l4ZbO4\", \"created_at\": \"Wed May 25 09:00:33 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73312486249611265, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73312486249611265\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}, \"contributors\": null, \"entities\": {\"user_mentions\": [{\"indices\": [3, 11], \"id\": 137694060, \"id_str\": \"137694060\", \"name\": \"Alain Mille\", \"screen_name\": \"amil310\"}, {\"indices\": [22, 30], \"id\": 137694060, \"id_str\": \"137694060\", \"name\": \"Alain Mille\", \"screen_name\": \"amil310\"}], \"hashtags\": [{\"indices\": [13, 18], \"text\": \"enmi\"}, {\"indices\": [32, 38], \"text\": \"trust\"}], \"urls\": [{\"indices\": [120, 140], \"url\": \"http://bit.ly/l4ZbO4\", \"expanded_url\": null}]}, \"text\": \"RT @amil310: #enmi RT @amil310: #trust Waiting for Bernard Stiegler Can we trust in SNCF, really? Follow the seminar at http://bit.ly/l4ZbO4\", \"created_at\": \"Wed May 25 09:02:03 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73312863908925440, \"source\": \"<a href=\\\"http://twitter.com/tweetbutton\\\" rel=\\\"nofollow\\\">Tweet Button</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73312863908925440\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 15000, 
-"tags": [
-{
-"id-ref": "219aa55c-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"id-ref": "219aaab6-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "ada27eb6-1145-4b77-b7d5-dac5c65654e0-73312863908925440"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Souci de live ???", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg"
-}, 
-"title": "Alexandre Monnin: #enmi Souci de live ???", 
-"color": "16763904", 
-"polemics": [
-"Q"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 50000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 7409472, \"verified\": false, \"profile_sidebar_fill_color\": \"E3E2DE\", \"profile_text_color\": \"634047\", \"followers_count\": 370, \"protected\": false, \"location\": \"Paris\", \"default_profile_image\": false, \"listed_count\": 68, \"utc_offset\": -10800, \"statuses_count\": 2826, \"description\": \"PhD student in Philosophy working on ontologies (computer & philo ones), tagging, Semantic Web, DigitalH, but mostly advocate for the Philosophy of the Web.\", \"friends_count\": 457, \"profile_link_color\": \"088253\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"EDECE9\", \"id_str\": \"7409472\", \"profile_background_image_url\": \"http://a1.twimg.com/images/themes/theme3/bg.gif\", \"name\": \"Alexandre Monnin\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 6, \"screen_name\": \"aamonnz\", \"url\": \"http://execo.univ-paris1.fr/spip.php?article67\", \"created_at\": \"Wed Jul 11 18:52:41 +0000 2007\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"D3D2CF\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Souci de live ???\", \"created_at\": \"Wed May 25 09:02:38 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73313011430993920, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73313011430993920\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 50000, 
-"tags": [
-{
-"id-ref": "219aaab6-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "2ac976de-899e-4a08-8513-e4ea7bc8b92e-73313011430993920"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "RT @borisarfi: Xavier Niel sur #Hadopi \"Je pense que nous avons une mauvaise loi en France, une loi folle\" #eG8  #enmi", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/309624209/Cy2_normal.png"
-}, 
-"title": "Samuel Huron: RT @borisarfi: Xavier Niel sur #Hadopi \"Je pense que nous avons une mauvaise loi en France, une loi folle\" #eG8  #enmi", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 80000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 14905766, \"verified\": false, \"profile_sidebar_fill_color\": \"ffffff\", \"profile_text_color\": \"4c9c8f\", \"followers_count\": 414, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 46, \"utc_offset\": -10800, \"statuses_count\": 1929, \"description\": \"Designer @ IRI Centre Pompidou / PhD student in Computer Human interface @ Paris11 : #ui #infoviz #Webdesign, #WebScience, #philosophy, #open #innovation\", \"friends_count\": 542, \"profile_link_color\": \"b3009b\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/309624209/Cy2_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"000000\", \"id_str\": \"14905766\", \"profile_background_image_url\": \"http://a2.twimg.com/profile_background_images/51130859/3577914799_1350cff02e.jpg\", \"name\": \"Samuel Huron\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 268, \"screen_name\": \"cybunk\", \"url\": \"http://www.cybunk.com\", \"created_at\": \"Mon May 26 06:02:18 +0000 2008\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"b3009b\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [{\"indices\": [3, 13], \"id\": 26981417, \"id_str\": \"26981417\", \"name\": \"Boris Arfi\", \"screen_name\": \"borisarfi\"}], \"hashtags\": [{\"indices\": [31, 38], \"text\": \"Hadopi\"}, {\"indices\": [107, 111], \"text\": \"eG8\"}, {\"indices\": [113, 118], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"RT @borisarfi: Xavier Niel sur #Hadopi \\\"Je pense que nous avons une mauvaise loi en France, une loi folle\\\" #eG8  #enmi\", \"created_at\": \"Wed May 25 09:03:08 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73313137151057920, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73313137151057920\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 80000, 
-"tags": [
-{
-"id-ref": "219ae30a-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"id-ref": "219ae30a-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"id-ref": "219ae77e-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "9b766956-6bb2-4720-a7b5-d150a41ab202-73313137151057920"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi La défiance ne serait seulement la perte de confiance, mais son retournement agressif, son inversion perverse, au sens etymologique", 
-"img": {
-"src": "http://a3.twimg.com/sticky/default_profile_images/default_profile_6_normal.png"
-}, 
-"title": "Etienne Armand AMATO: #enmi La défiance ne serait seulement la perte de confiance, mais son retournement agressif, son inversion perverse, au sens etymologique", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 99000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 223600369, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 7, \"protected\": false, \"location\": null, \"default_profile_image\": true, \"listed_count\": 0, \"utc_offset\": null, \"statuses_count\": 1, \"description\": null, \"friends_count\": 1, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/sticky/default_profile_images/default_profile_6_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"223600369\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Etienne Armand AMATO\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"EA_Amato\", \"url\": null, \"created_at\": \"Mon Dec 06 20:51:31 +0000 2010\", \"contributors_enabled\": false, \"time_zone\": null, \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi La d\\u00e9fiance ne serait seulement la perte de confiance, mais son retournement agressif, son inversion perverse, au sens etymologique\", \"created_at\": \"Wed May 25 09:03:27 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73313214305280000, \"source\": \"web\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73313214305280000\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 99000, 
-"tags": [
-{
-"id-ref": "219ae77e-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "b99854e0-29ad-4bc5-b38b-4aaa2b39f33d-73313214305280000"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi mise en place d'un nouvel espace publique depuis 9/11. Espace public = dispositif de publication.", 
-"img": {
-"src": "http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg"
-}, 
-"title": "nicolasauret: #enmi mise en place d'un nouvel espace publique depuis 9/11. Espace public = dispositif de publication.", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 188000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 293395401, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 3, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 0, \"utc_offset\": 3600, \"statuses_count\": 3, \"description\": \"Founder of Inflammable Productions, producer of new media content + project manager @IRI Centre Pompidou\", \"friends_count\": 10, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": true, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"293395401\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"nicolasauret\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"nicolasauret\", \"url\": null, \"created_at\": \"Thu May 05 08:31:25 +0000 2011\", \"contributors_enabled\": false, \"time_zone\": \"Paris\", \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi mise en place d'un nouvel espace publique depuis 9/11. Espace public = dispositif de publication.\", \"created_at\": \"Wed May 25 09:04:56 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73313588592386048, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73313588592386048\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 188000, 
-"tags": [
-{
-"id-ref": "219ae77e-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "9e283e03-9d4d-4e7f-98f7-c3ea1e4fdabc-73313588592386048"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Catastrophe et Confiance == http://bit.ly/jh2dTK ??", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/309624209/Cy2_normal.png"
-}, 
-"title": "Samuel Huron: #enmi Catastrophe et Confiance == http://bit.ly/jh2dTK ??", 
-"color": "16763904", 
-"polemics": [
-"Q", 
-"REF"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 209000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 14905766, \"verified\": false, \"profile_sidebar_fill_color\": \"ffffff\", \"profile_text_color\": \"4c9c8f\", \"followers_count\": 414, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 46, \"utc_offset\": -10800, \"statuses_count\": 1929, \"description\": \"Designer @ IRI Centre Pompidou / PhD student in Computer Human interface @ Paris11 : #ui #infoviz #Webdesign, #WebScience, #philosophy, #open #innovation\", \"friends_count\": 542, \"profile_link_color\": \"b3009b\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/309624209/Cy2_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"000000\", \"id_str\": \"14905766\", \"profile_background_image_url\": \"http://a2.twimg.com/profile_background_images/51130859/3577914799_1350cff02e.jpg\", \"name\": \"Samuel Huron\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 268, \"screen_name\": \"cybunk\", \"url\": \"http://www.cybunk.com\", \"created_at\": \"Mon May 26 06:02:18 +0000 2008\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"b3009b\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": [{\"indices\": [34, 54], \"url\": \"http://bit.ly/jh2dTK\", \"expanded_url\": null}]}, \"text\": \"#enmi Catastrophe et Confiance == http://bit.ly/jh2dTK ??\", \"created_at\": \"Wed May 25 09:05:17 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73313679264854016, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73313679264854016\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 209000, 
-"tags": [
-{
-"id-ref": "219ae77e-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "b0b5c6f0-5ce3-4292-af28-11ddf80653b6-73313679264854016"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Plus de live -- :(", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg"
-}, 
-"title": "Alexandre Monnin: #enmi Plus de live -- :(", 
-"color": "16763904", 
-"polemics": [
-"KO"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 287000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 7409472, \"verified\": false, \"profile_sidebar_fill_color\": \"E3E2DE\", \"profile_text_color\": \"634047\", \"followers_count\": 370, \"protected\": false, \"location\": \"Paris\", \"default_profile_image\": false, \"listed_count\": 68, \"utc_offset\": -10800, \"statuses_count\": 2827, \"description\": \"PhD student in Philosophy working on ontologies (computer & philo ones), tagging, Semantic Web, DigitalH, but mostly advocate for the Philosophy of the Web.\", \"friends_count\": 457, \"profile_link_color\": \"088253\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"EDECE9\", \"id_str\": \"7409472\", \"profile_background_image_url\": \"http://a1.twimg.com/images/themes/theme3/bg.gif\", \"name\": \"Alexandre Monnin\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 6, \"screen_name\": \"aamonnz\", \"url\": \"http://execo.univ-paris1.fr/spip.php?article67\", \"created_at\": \"Wed Jul 11 18:52:41 +0000 2007\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"D3D2CF\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Plus de live -- :(\", \"created_at\": \"Wed May 25 09:06:35 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73314003862044672, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73314003862044672\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 287000, 
-"tags": [
-{
-"id-ref": "219ae77e-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "cbcdc041-a215-4f67-baa9-86f818392ac9-73314003862044672"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Dispositif de publication et d'occultation, qui compense la souffrance du peuple qui n'avait plus accès aux moyens de diffusion", 
-"img": {
-"src": "http://a3.twimg.com/sticky/default_profile_images/default_profile_6_normal.png"
-}, 
-"title": "Etienne Armand AMATO: #enmi Dispositif de publication et d'occultation, qui compense la souffrance du peuple qui n'avait plus accès aux moyens de diffusion", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 325000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 223600369, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 7, \"protected\": false, \"location\": null, \"default_profile_image\": true, \"listed_count\": 0, \"utc_offset\": null, \"statuses_count\": 2, \"description\": null, \"friends_count\": 1, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/sticky/default_profile_images/default_profile_6_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"223600369\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Etienne Armand AMATO\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"EA_Amato\", \"url\": null, \"created_at\": \"Mon Dec 06 20:51:31 +0000 2010\", \"contributors_enabled\": false, \"time_zone\": null, \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Dispositif de publication et d'occultation, qui compense la souffrance du peuple qui n'avait plus acc\\u00e8s aux moyens de diffusion\", \"created_at\": \"Wed May 25 09:07:13 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73314163715358720, \"source\": \"web\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73314163715358720\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 325000, 
-"tags": [
-{
-"id-ref": "219ae77e-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "9d2af859-5765-4013-9d81-edfdb44c0b49-73314163715358720"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "== #enmi \"le peuple souffre depuis un siecle de ne plus avoir accés a la publication\"  B. Stiegler", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/309624209/Cy2_normal.png"
-}, 
-"title": "Samuel Huron: == #enmi \"le peuple souffre depuis un siecle de ne plus avoir accés a la publication\"  B. Stiegler", 
-"color": "16763904", 
-"polemics": [
-"REF"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 340000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 14905766, \"verified\": false, \"profile_sidebar_fill_color\": \"ffffff\", \"profile_text_color\": \"4c9c8f\", \"followers_count\": 414, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 46, \"utc_offset\": -10800, \"statuses_count\": 1930, \"description\": \"Designer @ IRI Centre Pompidou / PhD student in Computer Human interface @ Paris11 : #ui #infoviz #Webdesign, #WebScience, #philosophy, #open #innovation\", \"friends_count\": 542, \"profile_link_color\": \"b3009b\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/309624209/Cy2_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"000000\", \"id_str\": \"14905766\", \"profile_background_image_url\": \"http://a2.twimg.com/profile_background_images/51130859/3577914799_1350cff02e.jpg\", \"name\": \"Samuel Huron\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 268, \"screen_name\": \"cybunk\", \"url\": \"http://www.cybunk.com\", \"created_at\": \"Mon May 26 06:02:18 +0000 2008\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"b3009b\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [3, 8], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"== #enmi \\\"le peuple souffre depuis un siecle de ne plus avoir acc\\u00e9s a la publication\\\"  B. Stiegler\", \"created_at\": \"Wed May 25 09:07:28 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73314228785790976, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73314228785790976\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 340000, 
-"tags": [
-{
-"id-ref": "219ae77e-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "4310875e-202f-4704-87e4-bd456f2a615f-73314228785790976"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi B.Stiegler \"Montée en puissance du web numérique : nouvel espace de publication. Investit par un désir de publication.\" #eg8 #barlow", 
-"img": {
-"src": "http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg"
-}, 
-"title": "nicolasauret: #enmi B.Stiegler \"Montée en puissance du web numérique : nouvel espace de publication. Investit par un désir de publication.\" #eg8 #barlow", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 401000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 293395401, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 3, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 0, \"utc_offset\": 3600, \"statuses_count\": 4, \"description\": \"Founder of Inflammable Productions, producer of new media content + project manager @IRI Centre Pompidou\", \"friends_count\": 10, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": true, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"293395401\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"nicolasauret\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"nicolasauret\", \"url\": null, \"created_at\": \"Thu May 05 08:31:25 +0000 2011\", \"contributors_enabled\": false, \"time_zone\": \"Paris\", \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}, {\"indices\": [126, 130], \"text\": \"eg8\"}, {\"indices\": [131, 138], \"text\": \"barlow\"}], \"urls\": []}, \"text\": \"#enmi B.Stiegler \\\"Mont\\u00e9e en puissance du web num\\u00e9rique : nouvel espace de publication. Investit par un d\\u00e9sir de publication.\\\" #eg8 #barlow\", \"created_at\": \"Wed May 25 09:08:29 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73314481106714624, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73314481106714624\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 401000, 
-"tags": [
-{
-"id-ref": "219b9c96-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "807eec28-0165-4fee-8f1e-0facab6d5bb7-73314481106714624"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Problème de réseau, le live est tombé. On essayera à la pause", 
-"img": {
-"src": "http://a3.twimg.com/sticky/default_profile_images/default_profile_0_normal.png"
-}, 
-"title": "Yves-Marie Haussonne: #enmi Problème de réseau, le live est tombé. On essayera à la pause", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 572000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 47312923, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 4, \"protected\": false, \"location\": null, \"default_profile_image\": true, \"listed_count\": 0, \"utc_offset\": null, \"statuses_count\": 124, \"description\": null, \"friends_count\": 0, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/sticky/default_profile_images/default_profile_0_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"47312923\", \"profile_background_image_url\": \"http://a0.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Yves-Marie Haussonne\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"ymh_work\", \"url\": null, \"created_at\": \"Mon Jun 15 11:25:05 +0000 2009\", \"contributors_enabled\": false, \"time_zone\": null, \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Probl\\u00e8me de r\\u00e9seau, le live est tomb\\u00e9. On essayera \\u00e0 la pause\", \"created_at\": \"Wed May 25 09:11:20 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73315198567579649, \"source\": \"web\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73315198567579649\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 572000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "e0511a28-c123-4af0-859d-dfaa52ee74b3-73315198567579649"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi \"inquiétant est l'homme\" sophocle  \"l'inquiétude est la source de la philo \" Hegel \"inquietante étrangeté\" Freud http://bit.ly/l0fanQ", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/309624209/Cy2_normal.png"
-}, 
-"title": "Samuel Huron: #enmi \"inquiétant est l'homme\" sophocle  \"l'inquiétude est la source de la philo \" Hegel \"inquietante étrangeté\" Freud http://bit.ly/l0fanQ", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 628000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 14905766, \"verified\": false, \"profile_sidebar_fill_color\": \"ffffff\", \"profile_text_color\": \"4c9c8f\", \"followers_count\": 414, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 46, \"utc_offset\": -10800, \"statuses_count\": 1931, \"description\": \"Designer @ IRI Centre Pompidou / PhD student in Computer Human interface @ Paris11 : #ui #infoviz #Webdesign, #WebScience, #philosophy, #open #innovation\", \"friends_count\": 542, \"profile_link_color\": \"b3009b\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/309624209/Cy2_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"000000\", \"id_str\": \"14905766\", \"profile_background_image_url\": \"http://a2.twimg.com/profile_background_images/51130859/3577914799_1350cff02e.jpg\", \"name\": \"Samuel Huron\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 268, \"screen_name\": \"cybunk\", \"url\": \"http://www.cybunk.com\", \"created_at\": \"Mon May 26 06:02:18 +0000 2008\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"b3009b\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": [{\"indices\": [119, 139], \"url\": \"http://bit.ly/l0fanQ\", \"expanded_url\": null}]}, \"text\": \"#enmi \\\"inqui\\u00e9tant est l'homme\\\" sophocle  \\\"l'inqui\\u00e9tude est la source de la philo \\\" Hegel \\\"inquietante \\u00e9tranget\\u00e9\\\" Freud http://bit.ly/l0fanQ\", \"created_at\": \"Wed May 25 09:12:16 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73315436367855616, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73315436367855616\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 628000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "61a45d63-7352-4611-9b09-bd37077987fe-73315436367855616"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Cable débranché. Le live est de retour", 
-"img": {
-"src": "http://a3.twimg.com/sticky/default_profile_images/default_profile_0_normal.png"
-}, 
-"title": "Yves-Marie Haussonne: #enmi Cable débranché. Le live est de retour", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 735000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 47312923, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 4, \"protected\": false, \"location\": null, \"default_profile_image\": true, \"listed_count\": 0, \"utc_offset\": null, \"statuses_count\": 125, \"description\": null, \"friends_count\": 0, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/sticky/default_profile_images/default_profile_0_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"47312923\", \"profile_background_image_url\": \"http://a0.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Yves-Marie Haussonne\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"ymh_work\", \"url\": null, \"created_at\": \"Mon Jun 15 11:25:05 +0000 2009\", \"contributors_enabled\": false, \"time_zone\": null, \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Cable d\\u00e9branch\\u00e9. Le live est de retour\", \"created_at\": \"Wed May 25 09:14:03 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73315883203833856, \"source\": \"web\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73315883203833856\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 735000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "21693b30-7ded-4dbc-9827-136b15cfa5ec-73315883203833856"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi ça remarche :) ++", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg"
-}, 
-"title": "Alexandre Monnin: #enmi ça remarche :) ++", 
-"color": "16763904", 
-"polemics": [
-"OK"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 799000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 7409472, \"verified\": false, \"profile_sidebar_fill_color\": \"E3E2DE\", \"profile_text_color\": \"634047\", \"followers_count\": 370, \"protected\": false, \"location\": \"Paris\", \"default_profile_image\": false, \"listed_count\": 68, \"utc_offset\": -10800, \"statuses_count\": 2828, \"description\": \"PhD student in Philosophy working on ontologies (computer & philo ones), tagging, Semantic Web, DigitalH, but mostly advocate for the Philosophy of the Web.\", \"friends_count\": 457, \"profile_link_color\": \"088253\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"EDECE9\", \"id_str\": \"7409472\", \"profile_background_image_url\": \"http://a1.twimg.com/images/themes/theme3/bg.gif\", \"name\": \"Alexandre Monnin\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 6, \"screen_name\": \"aamonnz\", \"url\": \"http://execo.univ-paris1.fr/spip.php?article67\", \"created_at\": \"Wed Jul 11 18:52:41 +0000 2007\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"D3D2CF\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi \\u00e7a remarche :) ++\", \"created_at\": \"Wed May 25 09:15:07 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73316151018524672, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73316151018524672\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 799000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "d09bcacb-90e4-4a55-91d7-088125d9acfb-73316151018524672"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Descartes: interruption de ma volonté par rapport à mon entendement==", 
-"img": {
-"src": "http://a3.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg"
-}, 
-"title": "Vincent Puig: #enmi Descartes: interruption de ma volonté par rapport à mon entendement==", 
-"color": "16763904", 
-"polemics": [
-"REF"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 856000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 68424173, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 93, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 5, \"utc_offset\": 3600, \"statuses_count\": 169, \"description\": \"Co-founder of IRI/Centre Pompidou, Research Institute on cultural technologies (annotation tools, collaborative Web and social networks, multimodal interfaces)\", \"friends_count\": 5, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"68424173\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Vincent Puig\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"vincentpuig\", \"url\": \"http://www.iri.centrepompidou.fr\", \"created_at\": \"Mon Aug 24 14:49:27 +0000 2009\", \"contributors_enabled\": false, \"time_zone\": \"Paris\", \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Descartes: interruption de ma volont\\u00e9 par rapport \\u00e0 mon entendement==\", \"created_at\": \"Wed May 25 09:16:04 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73316389389217792, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73316389389217792\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 856000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "09b576b3-36c7-4775-91f0-41e38fe73ccd-73316389389217792"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi le Web est aussi une technique de publication ++", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg"
-}, 
-"title": "Alexandre Monnin: #enmi le Web est aussi une technique de publication ++", 
-"color": "16763904", 
-"polemics": [
-"OK"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 912000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 7409472, \"verified\": false, \"profile_sidebar_fill_color\": \"E3E2DE\", \"profile_text_color\": \"634047\", \"followers_count\": 370, \"protected\": false, \"location\": \"Paris\", \"default_profile_image\": false, \"listed_count\": 68, \"utc_offset\": -10800, \"statuses_count\": 2829, \"description\": \"PhD student in Philosophy working on ontologies (computer & philo ones), tagging, Semantic Web, DigitalH, but mostly advocate for the Philosophy of the Web.\", \"friends_count\": 457, \"profile_link_color\": \"088253\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"EDECE9\", \"id_str\": \"7409472\", \"profile_background_image_url\": \"http://a1.twimg.com/images/themes/theme3/bg.gif\", \"name\": \"Alexandre Monnin\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 6, \"screen_name\": \"aamonnz\", \"url\": \"http://execo.univ-paris1.fr/spip.php?article67\", \"created_at\": \"Wed Jul 11 18:52:41 +0000 2007\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"D3D2CF\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi le Web est aussi une technique de publication ++\", \"created_at\": \"Wed May 25 09:17:00 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73316627998982144, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73316627998982144\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 912000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "429dd17e-568f-453b-b821-56cb419ba9d3-73316627998982144"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Donc d'écriture ++", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg"
-}, 
-"title": "Alexandre Monnin: #enmi Donc d'écriture ++", 
-"color": "16763904", 
-"polemics": [
-"OK"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 923000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 7409472, \"verified\": false, \"profile_sidebar_fill_color\": \"E3E2DE\", \"profile_text_color\": \"634047\", \"followers_count\": 370, \"protected\": false, \"location\": \"Paris\", \"default_profile_image\": false, \"listed_count\": 68, \"utc_offset\": -10800, \"statuses_count\": 2830, \"description\": \"PhD student in Philosophy working on ontologies (computer & philo ones), tagging, Semantic Web, DigitalH, but mostly advocate for the Philosophy of the Web.\", \"friends_count\": 457, \"profile_link_color\": \"088253\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/513016932/twitterProfilePhoto_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"EDECE9\", \"id_str\": \"7409472\", \"profile_background_image_url\": \"http://a1.twimg.com/images/themes/theme3/bg.gif\", \"name\": \"Alexandre Monnin\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 6, \"screen_name\": \"aamonnz\", \"url\": \"http://execo.univ-paris1.fr/spip.php?article67\", \"created_at\": \"Wed Jul 11 18:52:41 +0000 2007\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"D3D2CF\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Donc d'\\u00e9criture ++\", \"created_at\": \"Wed May 25 09:17:11 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73316673108717568, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73316673108717568\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 923000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "8b191a27-5c94-46c7-8d3e-1f0a3476f2cf-73316673108717568"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Stiegler :Ce qui constitue l'humain depuis l'hominisation, c'est qu'il est régulièrement confronté à des suspensions technologiques.++", 
-"img": {
-"src": "http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg"
-}, 
-"title": "nicolasauret: #enmi Stiegler :Ce qui constitue l'humain depuis l'hominisation, c'est qu'il est régulièrement confronté à des suspensions technologiques.++", 
-"color": "16763904", 
-"polemics": [
-"OK"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 1015000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 293395401, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 3, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 0, \"utc_offset\": 3600, \"statuses_count\": 7, \"description\": \"Founder of Inflammable Productions, producer of new media content + project manager @IRI Centre Pompidou\", \"friends_count\": 10, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": true, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"293395401\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"nicolasauret\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"nicolasauret\", \"url\": null, \"created_at\": \"Thu May 05 08:31:25 +0000 2011\", \"contributors_enabled\": false, \"time_zone\": \"Paris\", \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Stiegler :Ce qui constitue l'humain depuis l'hominisation, c'est qu'il est r\\u00e9guli\\u00e8rement confront\\u00e9 \\u00e0 des suspensions technologiques.++\", \"created_at\": \"Wed May 25 09:18:43 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73317056312909824, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73317056312909824\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 1015000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "0f98001e-3c41-4b9c-921d-e369cfbdef7f-73317056312909824"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Stiegler pense un rapport de l'Homme au monde par la technologie++", 
-"img": {
-"src": "http://a3.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg"
-}, 
-"title": "Vincent Puig: #enmi Stiegler pense un rapport de l'Homme au monde par la technologie++", 
-"color": "16763904", 
-"polemics": [
-"OK"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 1025000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 68424173, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 93, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 5, \"utc_offset\": 3600, \"statuses_count\": 170, \"description\": \"Co-founder of IRI/Centre Pompidou, Research Institute on cultural technologies (annotation tools, collaborative Web and social networks, multimodal interfaces)\", \"friends_count\": 5, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"68424173\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Vincent Puig\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"vincentpuig\", \"url\": \"http://www.iri.centrepompidou.fr\", \"created_at\": \"Mon Aug 24 14:49:27 +0000 2009\", \"contributors_enabled\": false, \"time_zone\": \"Paris\", \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Stiegler pense un rapport de l'Homme au monde par la technologie++\", \"created_at\": \"Wed May 25 09:18:53 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73317100810276864, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73317100810276864\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 1025000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "b72f2732-73d9-4425-8e62-9d32b31a51fd-73317100810276864"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi la foi conception monotheist de lq confiance et calculabilite ==", 
-"img": {
-"src": "http://a3.twimg.com/sticky/default_profile_images/default_profile_0_normal.png"
-}, 
-"title": "Yves-Marie Haussonne: #enmi la foi conception monotheist de lq confiance et calculabilite ==", 
-"color": "16763904", 
-"polemics": [
-"REF"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 1155000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 47312923, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 4, \"protected\": false, \"location\": null, \"default_profile_image\": true, \"listed_count\": 0, \"utc_offset\": null, \"statuses_count\": 126, \"description\": null, \"friends_count\": 0, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/sticky/default_profile_images/default_profile_0_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"47312923\", \"profile_background_image_url\": \"http://a0.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Yves-Marie Haussonne\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"ymh_work\", \"url\": null, \"created_at\": \"Mon Jun 15 11:25:05 +0000 2009\", \"contributors_enabled\": false, \"time_zone\": null, \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi la foi conception monotheist de lq confiance et calculabilite ==\", \"created_at\": \"Wed May 25 09:21:03 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73317644270444546, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73317644270444546\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 1155000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "875ca945-960a-4346-9149-692ba6575f2d-73317644270444546"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "RT @nicolasauret: #enmi Stiegler :Ce qui constitue l'humain depuis l'hominisation, c'est qu'il est régulièrement confronté à des suspens ...", 
-"img": {
-"src": "http://a2.twimg.com/profile_images/1367788685/021EB7A5-E5A2-4837-9E76-4A6019F6E1EE_normal"
-}, 
-"title": "Fabian Gental: RT @nicolasauret: #enmi Stiegler :Ce qui constitue l'humain depuis l'hominisation, c'est qu'il est régulièrement confronté à des suspens ...", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 1174000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 115128839, \"verified\": false, \"profile_sidebar_fill_color\": \"d6fffc\", \"profile_text_color\": \"04838f\", \"followers_count\": 10, \"protected\": false, \"location\": \"Paris / Limoges / Berlin\", \"default_profile_image\": false, \"listed_count\": 0, \"utc_offset\": 3600, \"statuses_count\": 14, \"description\": \"\\u00c9tudiant en design @ENSCI les Ateliers\\n@ENSA Limoges\", \"friends_count\": 29, \"profile_link_color\": \"05d5ff\", \"profile_image_url\": \"http://a2.twimg.com/profile_images/1367788685/021EB7A5-E5A2-4837-9E76-4A6019F6E1EE_normal\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"bf9dc9\", \"id_str\": \"115128839\", \"profile_background_image_url\": \"http://a3.twimg.com/profile_background_images/76127896/test.png\", \"name\": \"Fabian Gental\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": true, \"favourites_count\": 1, \"screen_name\": \"3615fabe\", \"url\": null, \"created_at\": \"Wed Feb 17 18:08:52 +0000 2010\", \"contributors_enabled\": false, \"time_zone\": \"Berlin\", \"profile_sidebar_border_color\": \"ffffff\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"retweeted_status\": {\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 293395401, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 3, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 0, \"utc_offset\": 3600, \"statuses_count\": 7, \"description\": \"Founder of Inflammable Productions, producer of new media content + project manager @IRI Centre Pompidou\", \"friends_count\": 10, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": true, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"293395401\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"nicolasauret\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"nicolasauret\", \"url\": null, \"created_at\": \"Thu May 05 08:31:25 +0000 2011\", \"contributors_enabled\": false, \"time_zone\": \"Paris\", \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Stiegler :Ce qui constitue l'humain depuis l'hominisation, c'est qu'il est r\\u00e9guli\\u00e8rement confront\\u00e9 \\u00e0 des suspensions technologiques.++\", \"created_at\": \"Wed May 25 09:18:43 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73317056312909824, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73317056312909824\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}, \"contributors\": null, \"entities\": {\"user_mentions\": [{\"indices\": [3, 16], \"id\": 293395401, \"id_str\": \"293395401\", \"name\": \"nicolasauret\", \"screen_name\": \"nicolasauret\"}], \"hashtags\": [{\"indices\": [18, 23], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"RT @nicolasauret: #enmi Stiegler :Ce qui constitue l'humain depuis l'hominisation, c'est qu'il est r\\u00e9guli\\u00e8rement confront\\u00e9 \\u00e0 des suspens ...\", \"created_at\": \"Wed May 25 09:21:22 +0000 2011\", \"truncated\": true, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73317726894030848, \"source\": \"<a href=\\\"http://tapbots.com/tweetbot\\\" rel=\\\"nofollow\\\">Tweetbot for iPhone</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73317726894030848\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 1174000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "1adb2d5a-71d6-4704-acc1-71f7b2fe0130-73317726894030848"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi B stiegler :  Crise de confiance, car le nouveau systeme techno fait exploser les cadres sociaux http://bit.ly/l4ZbO4", 
-"img": {
-"src": "http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg"
-}, 
-"title": "nicolasauret: #enmi B stiegler :  Crise de confiance, car le nouveau systeme techno fait exploser les cadres sociaux http://bit.ly/l4ZbO4", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 1181000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 293395401, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 3, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 0, \"utc_offset\": 3600, \"statuses_count\": 8, \"description\": \"Founder of Inflammable Productions, producer of new media content + project manager @IRI Centre Pompidou\", \"friends_count\": 10, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/profile_images/1339638568/photoNicoS_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": true, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"293395401\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"nicolasauret\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"nicolasauret\", \"url\": null, \"created_at\": \"Thu May 05 08:31:25 +0000 2011\", \"contributors_enabled\": false, \"time_zone\": \"Paris\", \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": [{\"indices\": [103, 123], \"url\": \"http://bit.ly/l4ZbO4\", \"expanded_url\": null}]}, \"text\": \"#enmi B stiegler :  Crise de confiance, car le nouveau systeme techno fait exploser les cadres sociaux http://bit.ly/l4ZbO4\", \"created_at\": \"Wed May 25 09:21:29 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73317753603358720, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73317753603358720\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 1181000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "52afd104-e38f-4bf6-a23d-a6b5d6379da8-73317753603358720"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi Confiance calculable (raison) et foi (non calculable mais motivée par le desir) ne s'opposent pas.--", 
-"img": {
-"src": "http://a3.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg"
-}, 
-"title": "Vincent Puig: #enmi Confiance calculable (raison) et foi (non calculable mais motivée par le desir) ne s'opposent pas.--", 
-"color": "16763904", 
-"polemics": [
-"KO"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 1438000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 68424173, \"verified\": false, \"profile_sidebar_fill_color\": \"DDEEF6\", \"profile_text_color\": \"333333\", \"followers_count\": 93, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 5, \"utc_offset\": 3600, \"statuses_count\": 171, \"description\": \"Co-founder of IRI/Centre Pompidou, Research Institute on cultural technologies (annotation tools, collaborative Web and social networks, multimodal interfaces)\", \"friends_count\": 5, \"profile_link_color\": \"0084B4\", \"profile_image_url\": \"http://a3.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": false, \"profile_background_color\": \"C0DEED\", \"id_str\": \"68424173\", \"profile_background_image_url\": \"http://a3.twimg.com/images/themes/theme1/bg.png\", \"name\": \"Vincent Puig\", \"lang\": \"en\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 0, \"screen_name\": \"vincentpuig\", \"url\": \"http://www.iri.centrepompidou.fr\", \"created_at\": \"Mon Aug 24 14:49:27 +0000 2009\", \"contributors_enabled\": false, \"time_zone\": \"Paris\", \"profile_sidebar_border_color\": \"C0DEED\", \"default_profile\": true, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#enmi Confiance calculable (raison) et foi (non calculable mais motiv\\u00e9e par le desir) ne s'opposent pas.--\", \"created_at\": \"Wed May 25 09:25:46 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73318830763552769, \"source\": \"<a href=\\\"http://amateur.iri.centrepompidou.fr/\\\" rel=\\\"nofollow\\\">Annotation pol\\u00e9mique par tweeter</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73318830763552769\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 1438000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "6d1660e1-a012-484b-99f8-e6cc49ccf39c-73318830763552769"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#eg8 #enmi :: le language, interface entre l'homme et le monde.   technologie de confiance ?? Qu'elles liberté ?", 
-"img": {
-"src": "http://a1.twimg.com/profile_images/309624209/Cy2_normal.png"
-}, 
-"title": "Samuel Huron: #eg8 #enmi :: le language, interface entre l'homme et le monde.   technologie de confiance ?? Qu'elles liberté ?", 
-"color": "16763904", 
-"polemics": [
-"Q"
-], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 1454000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 14905766, \"verified\": false, \"profile_sidebar_fill_color\": \"ffffff\", \"profile_text_color\": \"4c9c8f\", \"followers_count\": 414, \"protected\": false, \"location\": \"Paris, France\", \"default_profile_image\": false, \"listed_count\": 46, \"utc_offset\": -10800, \"statuses_count\": 1934, \"description\": \"Designer @ IRI Centre Pompidou / PhD student in Computer Human interface @ Paris11 : #ui #infoviz #Webdesign, #WebScience, #philosophy, #open #innovation\", \"friends_count\": 542, \"profile_link_color\": \"b3009b\", \"profile_image_url\": \"http://a1.twimg.com/profile_images/309624209/Cy2_normal.png\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"000000\", \"id_str\": \"14905766\", \"profile_background_image_url\": \"http://a2.twimg.com/profile_background_images/51130859/3577914799_1350cff02e.jpg\", \"name\": \"Samuel Huron\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": false, \"favourites_count\": 268, \"screen_name\": \"cybunk\", \"url\": \"http://www.cybunk.com\", \"created_at\": \"Mon May 26 06:02:18 +0000 2008\", \"contributors_enabled\": false, \"time_zone\": \"Greenland\", \"profile_sidebar_border_color\": \"b3009b\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 4], \"text\": \"eg8\"}, {\"indices\": [5, 10], \"text\": \"enmi\"}], \"urls\": []}, \"text\": \"#eg8 #enmi :: le language, interface entre l'homme et le monde.   technologie de confiance ?? Qu'elles libert\\u00e9 ?\", \"created_at\": \"Wed May 25 09:26:02 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": null, \"id\": 73318901475328000, \"source\": \"<a href=\\\"http://www.tweetdeck.com\\\" rel=\\\"nofollow\\\">TweetDeck</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73318901475328000\", \"place\": null, \"retweet_count\": 0, \"geo\": null, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 1454000, 
-"tags": [
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"id-ref": "219ba10a-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "0a85f156-f4b1-49f1-ac00-51b0ea070134-73318901475328000"
-}, 
-{
-"content": {
-"mimetype": "application/x-ldt-structured", 
-"description": "#enmi  edward bernays /VS/ pekka himanen ? #libidinal vers #contribution ?", 
-"img": {
-"src": "http://a2.twimg.com/profile_images/1367788685/021EB7A5-E5A2-4837-9E76-4A6019F6E1EE_normal"
-}, 
-"title": "Fabian Gental: #enmi  edward bernays /VS/ pekka himanen ? #libidinal vers #contribution ?", 
-"color": "16763904", 
-"polemics": [], 
-"audio": {
-"mimetype": "audio/mp3", 
-"src": "", 
-"href": null
-}
-}, 
-"begin": 1538000, 
-"meta": {
-"dc:contributor": "perso", 
-"dc:source": {
-"mimetype": "application/json", 
-"url": "http://dev.twitter.com", 
-"content": "{\"user\": {\"follow_request_sent\": null, \"profile_use_background_image\": true, \"id\": 115128839, \"verified\": false, \"profile_sidebar_fill_color\": \"d6fffc\", \"profile_text_color\": \"04838f\", \"followers_count\": 10, \"protected\": false, \"location\": \"Paris / Limoges / Berlin\", \"default_profile_image\": false, \"listed_count\": 0, \"utc_offset\": 3600, \"statuses_count\": 16, \"description\": \"\\u00c9tudiant en design @ENSCI les Ateliers\\n@ENSA Limoges\", \"friends_count\": 29, \"profile_link_color\": \"05d5ff\", \"profile_image_url\": \"http://a2.twimg.com/profile_images/1367788685/021EB7A5-E5A2-4837-9E76-4A6019F6E1EE_normal\", \"notifications\": null, \"show_all_inline_media\": false, \"geo_enabled\": true, \"profile_background_color\": \"bf9dc9\", \"id_str\": \"115128839\", \"profile_background_image_url\": \"http://a3.twimg.com/profile_background_images/76127896/test.png\", \"name\": \"Fabian Gental\", \"lang\": \"fr\", \"following\": null, \"profile_background_tile\": true, \"favourites_count\": 1, \"screen_name\": \"3615fabe\", \"url\": null, \"created_at\": \"Wed Feb 17 18:08:52 +0000 2010\", \"contributors_enabled\": false, \"time_zone\": \"Berlin\", \"profile_sidebar_border_color\": \"ffffff\", \"default_profile\": false, \"is_translator\": false}, \"favorited\": false, \"contributors\": null, \"entities\": {\"user_mentions\": [], \"hashtags\": [{\"indices\": [0, 5], \"text\": \"enmi\"}, {\"indices\": [43, 53], \"text\": \"libidinal\"}, {\"indices\": [59, 72], \"text\": \"contribution\"}], \"urls\": []}, \"text\": \"#enmi  edward bernays /VS/ pekka himanen ? #libidinal vers #contribution ?\", \"created_at\": \"Wed May 25 09:27:26 +0000 2011\", \"truncated\": false, \"retweeted\": false, \"in_reply_to_status_id\": null, \"coordinates\": {\"type\": \"Point\", \"coordinates\": [2.3704253400000002, 48.858806250000001]}, \"id\": 73319252060405760, \"source\": \"<a href=\\\"http://tapbots.com/tweetbot\\\" rel=\\\"nofollow\\\">Tweetbot for iPhone</a>\", \"in_reply_to_status_id_str\": null, \"in_reply_to_screen_name\": null, \"id_str\": \"73319252060405760\", \"place\": {\"country_code\": \"FR\", \"url\": \"http://api.twitter.com/1/geo/id/7238f93a3e899af6.json\", \"country\": \"France\", \"place_type\": \"city\", \"bounding_box\": {\"type\": \"Polygon\", \"coordinates\": [[[2.2241005999999999, 48.815541400000001], [2.4697521, 48.815541400000001], [2.4697521, 48.902146100000003], [2.2241005999999999, 48.902146100000003]]]}, \"full_name\": \"Paris, Paris\", \"attributes\": {}, \"id\": \"7238f93a3e899af6\", \"name\": \"Paris\"}, \"retweet_count\": 0, \"geo\": {\"type\": \"Point\", \"coordinates\": [48.858806250000001, 2.3704253400000002]}, \"in_reply_to_user_id_str\": null, \"in_reply_to_user_id\": null}"
-}, 
-"dc:creator": "perso", 
-"id-ref": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}, 
-"end": 1538000, 
-"tags": [
-{
-"id-ref": "219d2156-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"id-ref": "219d2156-062c-11e1-93a3-00145ea49a02"
-}, 
-{
-"id-ref": "219d25fc-062c-11e1-93a3-00145ea49a02"
-}
-], 
-"color": "16763904", 
-"media": "914e1bcc-b6e0-11e0-a965-00145ea49a02", 
-"id": "9862e2d4-ef66-4368-98e2-562a61232a5a-73319252060405760"
-}
-], 
-"annotation-types": [
-{
-"dc:contributor": "perso", 
-"dc:creator": "perso", 
-"dc:title": "Bernard Stiegler", 
-"id": "c_5AEE45AE-F0E5-2921-31CB-2683540AA7A4", 
-"dc:created": "2011-11-03T14:57:21.010291", 
-"dc:description": "", 
-"dc:modified": "2011-11-03T14:57:21.010291"
-}, 
-{
-"dc:contributor": "perso", 
-"dc:creator": "perso", 
-"dc:title": "Tweets", 
-"id": "61bcaa2e-9963-4df2-a987-34c08e184fb6", 
-"dc:created": "2011-11-03T14:57:20.992536", 
-"dc:description": "Tweets", 
-"dc:modified": "2011-11-03T14:57:20.992536"
-}
-]
-}
\ No newline at end of file
--- a/unittests/qunit.css	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +0,0 @@
-/**
- * QUnit - A JavaScript Unit Testing Framework
- *
- * http://docs.jquery.com/QUnit
- *
- * Copyright (c) 2011 John Resig, Jörn Zaefferer
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * or GPL (GPL-LICENSE.txt) licenses.
- * Pulled Live from Git Thu Oct  6 09:15:01 UTC 2011
- * Last Commit: 3006fa77db4625c4293c368a8999ddb1abba7f48
- */
-
-/** Font Family and Sizes */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
-	font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
-}
-
-#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
-#qunit-tests { font-size: smaller; }
-
-
-/** Resets */
-
-#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
-	margin: 0;
-	padding: 0;
-}
-
-
-/** Header */
-
-#qunit-header {
-	padding: 0.5em 0 0.5em 1em;
-
-	color: #8699a4;
-	background-color: #0d3349;
-
-	font-size: 1.5em;
-	line-height: 1em;
-	font-weight: normal;
-
-	border-radius: 15px 15px 0 0;
-	-moz-border-radius: 15px 15px 0 0;
-	-webkit-border-top-right-radius: 15px;
-	-webkit-border-top-left-radius: 15px;
-}
-
-#qunit-header a {
-	text-decoration: none;
-	color: #c2ccd1;
-}
-
-#qunit-header a:hover,
-#qunit-header a:focus {
-	color: #fff;
-}
-
-#qunit-banner {
-	height: 5px;
-}
-
-#qunit-testrunner-toolbar {
-	padding: 0.5em 0 0.5em 2em;
-	color: #5E740B;
-	background-color: #eee;
-}
-
-#qunit-userAgent {
-	padding: 0.5em 0 0.5em 2.5em;
-	background-color: #2b81af;
-	color: #fff;
-	text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
-}
-
-
-/** Tests: Pass/Fail */
-
-#qunit-tests {
-	list-style-position: inside;
-}
-
-#qunit-tests li {
-	padding: 0.4em 0.5em 0.4em 2.5em;
-	border-bottom: 1px solid #fff;
-	list-style-position: inside;
-}
-
-#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {
-	display: none;
-}
-
-#qunit-tests li strong {
-	cursor: pointer;
-}
-
-#qunit-tests li a {
-	padding: 0.5em;
-	color: #c2ccd1;
-	text-decoration: none;
-}
-#qunit-tests li a:hover,
-#qunit-tests li a:focus {
-	color: #000;
-}
-
-#qunit-tests ol {
-	margin-top: 0.5em;
-	padding: 0.5em;
-
-	background-color: #fff;
-
-	border-radius: 15px;
-	-moz-border-radius: 15px;
-	-webkit-border-radius: 15px;
-
-	box-shadow: inset 0px 2px 13px #999;
-	-moz-box-shadow: inset 0px 2px 13px #999;
-	-webkit-box-shadow: inset 0px 2px 13px #999;
-}
-
-#qunit-tests table {
-	border-collapse: collapse;
-	margin-top: .2em;
-}
-
-#qunit-tests th {
-	text-align: right;
-	vertical-align: top;
-	padding: 0 .5em 0 0;
-}
-
-#qunit-tests td {
-	vertical-align: top;
-}
-
-#qunit-tests pre {
-	margin: 0;
-	white-space: pre-wrap;
-	word-wrap: break-word;
-}
-
-#qunit-tests del {
-	background-color: #e0f2be;
-	color: #374e0c;
-	text-decoration: none;
-}
-
-#qunit-tests ins {
-	background-color: #ffcaca;
-	color: #500;
-	text-decoration: none;
-}
-
-/*** Test Counts */
-
-#qunit-tests b.counts                       { color: black; }
-#qunit-tests b.passed                       { color: #5E740B; }
-#qunit-tests b.failed                       { color: #710909; }
-
-#qunit-tests li li {
-	margin: 0.5em;
-	padding: 0.4em 0.5em 0.4em 0.5em;
-	background-color: #fff;
-	border-bottom: none;
-	list-style-position: inside;
-}
-
-/*** Passing Styles */
-
-#qunit-tests li li.pass {
-	color: #5E740B;
-	background-color: #fff;
-	border-left: 26px solid #C6E746;
-}
-
-#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
-#qunit-tests .pass .test-name               { color: #366097; }
-
-#qunit-tests .pass .test-actual,
-#qunit-tests .pass .test-expected           { color: #999999; }
-
-#qunit-banner.qunit-pass                    { background-color: #C6E746; }
-
-/*** Failing Styles */
-
-#qunit-tests li li.fail {
-	color: #710909;
-	background-color: #fff;
-	border-left: 26px solid #EE5757;
-	white-space: pre;
-}
-
-#qunit-tests > li:last-child {
-	border-radius: 0 0 15px 15px;
-	-moz-border-radius: 0 0 15px 15px;
-	-webkit-border-bottom-right-radius: 15px;
-	-webkit-border-bottom-left-radius: 15px;
-}
-
-#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }
-#qunit-tests .fail .test-name,
-#qunit-tests .fail .module-name             { color: #000000; }
-
-#qunit-tests .fail .test-actual             { color: #EE5757; }
-#qunit-tests .fail .test-expected           { color: green;   }
-
-#qunit-banner.qunit-fail                    { background-color: #EE5757; }
-
-
-/** Result */
-
-#qunit-testresult {
-	padding: 0.5em 0.5em 0.5em 2.5em;
-
-	color: #2b81af;
-	background-color: #D2E0E6;
-
-	border-bottom: 1px solid white;
-}
-
-/** Fixture */
-
-#qunit-fixture {
-	position: absolute;
-	top: -10000px;
-	left: -10000px;
-}
--- a/unittests/qunit.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1554 +0,0 @@
-/**
- * QUnit - A JavaScript Unit Testing Framework
- *
- * http://docs.jquery.com/QUnit
- *
- * Copyright (c) 2011 John Resig, Jörn Zaefferer
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * or GPL (GPL-LICENSE.txt) licenses.
- * Pulled Live from Git Thu Oct  6 09:15:01 UTC 2011
- * Last Commit: 3006fa77db4625c4293c368a8999ddb1abba7f48
- */
-
-(function(window) {
-
-var defined = {
-	setTimeout: typeof window.setTimeout !== "undefined",
-	sessionStorage: (function() {
-		try {
-			return !!sessionStorage.getItem;
-		} catch(e) {
-			return false;
-		}
-	})()
-};
-
-var testId = 0;
-
-var Test = function(name, testName, expected, testEnvironmentArg, async, callback) {
-	this.name = name;
-	this.testName = testName;
-	this.expected = expected;
-	this.testEnvironmentArg = testEnvironmentArg;
-	this.async = async;
-	this.callback = callback;
-	this.assertions = [];
-};
-Test.prototype = {
-	init: function() {
-		var tests = id("qunit-tests");
-		if (tests) {
-			var b = document.createElement("strong");
-				b.innerHTML = "Running " + this.name;
-			var li = document.createElement("li");
-				li.appendChild( b );
-				li.className = "running";
-				li.id = this.id = "test-output" + testId++;
-			tests.appendChild( li );
-		}
-	},
-	setup: function() {
-		if (this.module != config.previousModule) {
-			if ( config.previousModule ) {
-				runLoggingCallbacks('moduleDone', QUnit, {
-					name: config.previousModule,
-					failed: config.moduleStats.bad,
-					passed: config.moduleStats.all - config.moduleStats.bad,
-					total: config.moduleStats.all
-				} );
-			}
-			config.previousModule = this.module;
-			config.moduleStats = { all: 0, bad: 0 };
-			runLoggingCallbacks( 'moduleStart', QUnit, {
-				name: this.module
-			} );
-		}
-
-		config.current = this;
-		this.testEnvironment = extend({
-			setup: function() {},
-			teardown: function() {}
-		}, this.moduleTestEnvironment);
-		if (this.testEnvironmentArg) {
-			extend(this.testEnvironment, this.testEnvironmentArg);
-		}
-
-		runLoggingCallbacks( 'testStart', QUnit, {
-			name: this.testName,
-			module: this.module
-		});
-
-		// allow utility functions to access the current test environment
-		// TODO why??
-		QUnit.current_testEnvironment = this.testEnvironment;
-
-		try {
-			if ( !config.pollution ) {
-				saveGlobal();
-			}
-
-			this.testEnvironment.setup.call(this.testEnvironment);
-		} catch(e) {
-			QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message );
-		}
-	},
-	run: function() {
-		if ( this.async ) {
-			QUnit.stop();
-		}
-
-		if ( config.notrycatch ) {
-			this.callback.call(this.testEnvironment);
-			return;
-		}
-		try {
-			this.callback.call(this.testEnvironment);
-		} catch(e) {
-			fail("Test " + this.testName + " died, exception and test follows", e, this.callback);
-			QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) );
-			// else next test will carry the responsibility
-			saveGlobal();
-
-			// Restart the tests if they're blocking
-			if ( config.blocking ) {
-				start();
-			}
-		}
-	},
-	teardown: function() {
-		try {
-			this.testEnvironment.teardown.call(this.testEnvironment);
-			checkPollution();
-		} catch(e) {
-			QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message );
-		}
-	},
-	finish: function() {
-		if ( this.expected && this.expected != this.assertions.length ) {
-			QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
-		}
-
-		var good = 0, bad = 0,
-			tests = id("qunit-tests");
-
-		config.stats.all += this.assertions.length;
-		config.moduleStats.all += this.assertions.length;
-
-		if ( tests ) {
-			var ol = document.createElement("ol");
-
-			for ( var i = 0; i < this.assertions.length; i++ ) {
-				var assertion = this.assertions[i];
-
-				var li = document.createElement("li");
-				li.className = assertion.result ? "pass" : "fail";
-				li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed");
-				ol.appendChild( li );
-
-				if ( assertion.result ) {
-					good++;
-				} else {
-					bad++;
-					config.stats.bad++;
-					config.moduleStats.bad++;
-				}
-			}
-
-			// store result when possible
-			if ( QUnit.config.reorder && defined.sessionStorage ) {
-				if (bad) {
-					sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad);
-				} else {
-					sessionStorage.removeItem("qunit-" + this.module + "-" + this.testName);
-				}
-			}
-
-			if (bad == 0) {
-				ol.style.display = "none";
-			}
-
-			var b = document.createElement("strong");
-			b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
-
-			var a = document.createElement("a");
-			a.innerHTML = "Rerun";
-			a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
-
-			addEvent(b, "click", function() {
-				var next = b.nextSibling.nextSibling,
-					display = next.style.display;
-				next.style.display = display === "none" ? "block" : "none";
-			});
-
-			addEvent(b, "dblclick", function(e) {
-				var target = e && e.target ? e.target : window.event.srcElement;
-				if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
-					target = target.parentNode;
-				}
-				if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
-					window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
-				}
-			});
-
-			var li = id(this.id);
-			li.className = bad ? "fail" : "pass";
-			li.removeChild( li.firstChild );
-			li.appendChild( b );
-			li.appendChild( a );
-			li.appendChild( ol );
-
-		} else {
-			for ( var i = 0; i < this.assertions.length; i++ ) {
-				if ( !this.assertions[i].result ) {
-					bad++;
-					config.stats.bad++;
-					config.moduleStats.bad++;
-				}
-			}
-		}
-
-		try {
-			QUnit.reset();
-		} catch(e) {
-			fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset);
-		}
-
-		runLoggingCallbacks( 'testDone', QUnit, {
-			name: this.testName,
-			module: this.module,
-			failed: bad,
-			passed: this.assertions.length - bad,
-			total: this.assertions.length
-		} );
-	},
-
-	queue: function() {
-		var test = this;
-		synchronize(function() {
-			test.init();
-		});
-		function run() {
-			// each of these can by async
-			synchronize(function() {
-				test.setup();
-			});
-			synchronize(function() {
-				test.run();
-			});
-			synchronize(function() {
-				test.teardown();
-			});
-			synchronize(function() {
-				test.finish();
-			});
-		}
-		// defer when previous test run passed, if storage is available
-		var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.module + "-" + this.testName);
-		if (bad) {
-			run();
-		} else {
-			synchronize(run);
-		};
-	}
-
-};
-
-var QUnit = {
-
-	// call on start of module test to prepend name to all tests
-	module: function(name, testEnvironment) {
-		config.currentModule = name;
-		config.currentModuleTestEnviroment = testEnvironment;
-	},
-
-	asyncTest: function(testName, expected, callback) {
-		if ( arguments.length === 2 ) {
-			callback = expected;
-			expected = 0;
-		}
-
-		QUnit.test(testName, expected, callback, true);
-	},
-
-	test: function(testName, expected, callback, async) {
-		var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg;
-
-		if ( arguments.length === 2 ) {
-			callback = expected;
-			expected = null;
-		}
-		// is 2nd argument a testEnvironment?
-		if ( expected && typeof expected === 'object') {
-			testEnvironmentArg = expected;
-			expected = null;
-		}
-
-		if ( config.currentModule ) {
-			name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
-		}
-
-		if ( !validTest(config.currentModule + ": " + testName) ) {
-			return;
-		}
-
-		var test = new Test(name, testName, expected, testEnvironmentArg, async, callback);
-		test.module = config.currentModule;
-		test.moduleTestEnvironment = config.currentModuleTestEnviroment;
-		test.queue();
-	},
-
-	/**
-	 * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
-	 */
-	expect: function(asserts) {
-		config.current.expected = asserts;
-	},
-
-	/**
-	 * Asserts true.
-	 * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
-	 */
-	ok: function(a, msg) {
-		a = !!a;
-		var details = {
-			result: a,
-			message: msg
-		};
-		msg = escapeInnerText(msg);
-		runLoggingCallbacks( 'log', QUnit, details );
-		config.current.assertions.push({
-			result: a,
-			message: msg
-		});
-	},
-
-	/**
-	 * Checks that the first two arguments are equal, with an optional message.
-	 * Prints out both actual and expected values.
-	 *
-	 * Prefered to ok( actual == expected, message )
-	 *
-	 * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
-	 *
-	 * @param Object actual
-	 * @param Object expected
-	 * @param String message (optional)
-	 */
-	equal: function(actual, expected, message) {
-		QUnit.push(expected == actual, actual, expected, message);
-	},
-
-	notEqual: function(actual, expected, message) {
-		QUnit.push(expected != actual, actual, expected, message);
-	},
-
-	deepEqual: function(actual, expected, message) {
-		QUnit.push(QUnit.equiv(actual, expected), actual, expected, message);
-	},
-
-	notDeepEqual: function(actual, expected, message) {
-		QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);
-	},
-
-	strictEqual: function(actual, expected, message) {
-		QUnit.push(expected === actual, actual, expected, message);
-	},
-
-	notStrictEqual: function(actual, expected, message) {
-		QUnit.push(expected !== actual, actual, expected, message);
-	},
-
-	raises: function(block, expected, message) {
-		var actual, ok = false;
-
-		if (typeof expected === 'string') {
-			message = expected;
-			expected = null;
-		}
-
-		try {
-			block();
-		} catch (e) {
-			actual = e;
-		}
-
-		if (actual) {
-			// we don't want to validate thrown error
-			if (!expected) {
-				ok = true;
-			// expected is a regexp
-			} else if (QUnit.objectType(expected) === "regexp") {
-				ok = expected.test(actual);
-			// expected is a constructor
-			} else if (actual instanceof expected) {
-				ok = true;
-			// expected is a validation function which returns true is validation passed
-			} else if (expected.call({}, actual) === true) {
-				ok = true;
-			}
-		}
-
-		QUnit.ok(ok, message);
-	},
-
-	start: function(count) {
-		config.semaphore -= count || 1;
-		if (config.semaphore > 0) {
-			// don't start until equal number of stop-calls
-			return;
-		}
-		if (config.semaphore < 0) {
-			// ignore if start is called more often then stop
-			config.semaphore = 0;
-		}
-		// A slight delay, to avoid any current callbacks
-		if ( defined.setTimeout ) {
-			window.setTimeout(function() {
-				if (config.semaphore > 0) {
-					return;
-				}
-				if ( config.timeout ) {
-					clearTimeout(config.timeout);
-				}
-
-				config.blocking = false;
-				process();
-			}, 13);
-		} else {
-			config.blocking = false;
-			process();
-		}
-	},
-
-	stop: function(count) {
-		config.semaphore += count || 1;
-		config.blocking = true;
-
-		if ( config.testTimeout && defined.setTimeout ) {
-			clearTimeout(config.timeout);
-			config.timeout = window.setTimeout(function() {
-				QUnit.ok( false, "Test timed out" );
-				config.semaphore = 1;
-				QUnit.start();
-			}, config.testTimeout);
-		}
-	}
-};
-
-//We want access to the constructor's prototype
-(function() {
-	function F(){};
-	F.prototype = QUnit;
-	QUnit = new F();
-	//Make F QUnit's constructor so that we can add to the prototype later
-	QUnit.constructor = F;
-})();
-
-// Backwards compatibility, deprecated
-QUnit.equals = QUnit.equal;
-QUnit.same = QUnit.deepEqual;
-
-// Maintain internal state
-var config = {
-	// The queue of tests to run
-	queue: [],
-
-	// block until document ready
-	blocking: true,
-
-	// when enabled, show only failing tests
-	// gets persisted through sessionStorage and can be changed in UI via checkbox
-	hidepassed: false,
-
-	// by default, run previously failed tests first
-	// very useful in combination with "Hide passed tests" checked
-	reorder: true,
-
-	// by default, modify document.title when suite is done
-	altertitle: true,
-
-	urlConfig: ['noglobals', 'notrycatch'],
-
-	//logging callback queues
-	begin: [],
-	done: [],
-	log: [],
-	testStart: [],
-	testDone: [],
-	moduleStart: [],
-	moduleDone: []
-};
-
-// Load paramaters
-(function() {
-	var location = window.location || { search: "", protocol: "file:" },
-		params = location.search.slice( 1 ).split( "&" ),
-		length = params.length,
-		urlParams = {},
-		current;
-
-	if ( params[ 0 ] ) {
-		for ( var i = 0; i < length; i++ ) {
-			current = params[ i ].split( "=" );
-			current[ 0 ] = decodeURIComponent( current[ 0 ] );
-			// allow just a key to turn on a flag, e.g., test.html?noglobals
-			current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
-			urlParams[ current[ 0 ] ] = current[ 1 ];
-		}
-	}
-
-	QUnit.urlParams = urlParams;
-	config.filter = urlParams.filter;
-
-	// Figure out if we're running the tests from a server or not
-	QUnit.isLocal = !!(location.protocol === 'file:');
-})();
-
-// Expose the API as global variables, unless an 'exports'
-// object exists, in that case we assume we're in CommonJS
-if ( typeof exports === "undefined" || typeof require === "undefined" ) {
-	extend(window, QUnit);
-	window.QUnit = QUnit;
-} else {
-	extend(exports, QUnit);
-	exports.QUnit = QUnit;
-}
-
-// define these after exposing globals to keep them in these QUnit namespace only
-extend(QUnit, {
-	config: config,
-
-	// Initialize the configuration options
-	init: function() {
-		extend(config, {
-			stats: { all: 0, bad: 0 },
-			moduleStats: { all: 0, bad: 0 },
-			started: +new Date,
-			updateRate: 1000,
-			blocking: false,
-			autostart: true,
-			autorun: false,
-			filter: "",
-			queue: [],
-			semaphore: 0
-		});
-
-		var tests = id( "qunit-tests" ),
-			banner = id( "qunit-banner" ),
-			result = id( "qunit-testresult" );
-
-		if ( tests ) {
-			tests.innerHTML = "";
-		}
-
-		if ( banner ) {
-			banner.className = "";
-		}
-
-		if ( result ) {
-			result.parentNode.removeChild( result );
-		}
-
-		if ( tests ) {
-			result = document.createElement( "p" );
-			result.id = "qunit-testresult";
-			result.className = "result";
-			tests.parentNode.insertBefore( result, tests );
-			result.innerHTML = 'Running...<br/>&nbsp;';
-		}
-	},
-
-	/**
-	 * Resets the test setup. Useful for tests that modify the DOM.
-	 *
-	 * If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
-	 */
-	reset: function() {
-		if ( window.jQuery ) {
-			jQuery( "#qunit-fixture" ).html( config.fixture );
-		} else {
-			var main = id( 'qunit-fixture' );
-			if ( main ) {
-				main.innerHTML = config.fixture;
-			}
-		}
-	},
-
-	/**
-	 * Trigger an event on an element.
-	 *
-	 * @example triggerEvent( document.body, "click" );
-	 *
-	 * @param DOMElement elem
-	 * @param String type
-	 */
-	triggerEvent: function( elem, type, event ) {
-		if ( document.createEvent ) {
-			event = document.createEvent("MouseEvents");
-			event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
-				0, 0, 0, 0, 0, false, false, false, false, 0, null);
-			elem.dispatchEvent( event );
-
-		} else if ( elem.fireEvent ) {
-			elem.fireEvent("on"+type);
-		}
-	},
-
-	// Safe object type checking
-	is: function( type, obj ) {
-		return QUnit.objectType( obj ) == type;
-	},
-
-	objectType: function( obj ) {
-		if (typeof obj === "undefined") {
-				return "undefined";
-
-		// consider: typeof null === object
-		}
-		if (obj === null) {
-				return "null";
-		}
-
-		var type = Object.prototype.toString.call( obj )
-			.match(/^\[object\s(.*)\]$/)[1] || '';
-
-		switch (type) {
-				case 'Number':
-						if (isNaN(obj)) {
-								return "nan";
-						} else {
-								return "number";
-						}
-				case 'String':
-				case 'Boolean':
-				case 'Array':
-				case 'Date':
-				case 'RegExp':
-				case 'Function':
-						return type.toLowerCase();
-		}
-		if (typeof obj === "object") {
-				return "object";
-		}
-		return undefined;
-	},
-
-	push: function(result, actual, expected, message) {
-		var details = {
-			result: result,
-			message: message,
-			actual: actual,
-			expected: expected
-		};
-
-		message = escapeInnerText(message) || (result ? "okay" : "failed");
-		message = '<span class="test-message">' + message + "</span>";
-		expected = escapeInnerText(QUnit.jsDump.parse(expected));
-		actual = escapeInnerText(QUnit.jsDump.parse(actual));
-		var output = message + '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';
-		if (actual != expected) {
-			output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';
-			output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';
-		}
-		if (!result) {
-			var source = sourceFromStacktrace();
-			if (source) {
-				details.source = source;
-				output += '<tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr>';
-			}
-		}
-		output += "</table>";
-
-		runLoggingCallbacks( 'log', QUnit, details );
-
-		config.current.assertions.push({
-			result: !!result,
-			message: output
-		});
-	},
-
-	url: function( params ) {
-		params = extend( extend( {}, QUnit.urlParams ), params );
-		var querystring = "?",
-			key;
-		for ( key in params ) {
-			querystring += encodeURIComponent( key ) + "=" +
-				encodeURIComponent( params[ key ] ) + "&";
-		}
-		return window.location.pathname + querystring.slice( 0, -1 );
-	},
-
-	extend: extend,
-	id: id,
-	addEvent: addEvent
-});
-
-//QUnit.constructor is set to the empty F() above so that we can add to it's prototype later
-//Doing this allows us to tell if the following methods have been overwritten on the actual
-//QUnit object, which is a deprecated way of using the callbacks.
-extend(QUnit.constructor.prototype, {
-	// Logging callbacks; all receive a single argument with the listed properties
-	// run test/logs.html for any related changes
-	begin: registerLoggingCallback('begin'),
-	// done: { failed, passed, total, runtime }
-	done: registerLoggingCallback('done'),
-	// log: { result, actual, expected, message }
-	log: registerLoggingCallback('log'),
-	// testStart: { name }
-	testStart: registerLoggingCallback('testStart'),
-	// testDone: { name, failed, passed, total }
-	testDone: registerLoggingCallback('testDone'),
-	// moduleStart: { name }
-	moduleStart: registerLoggingCallback('moduleStart'),
-	// moduleDone: { name, failed, passed, total }
-	moduleDone: registerLoggingCallback('moduleDone')
-});
-
-if ( typeof document === "undefined" || document.readyState === "complete" ) {
-	config.autorun = true;
-}
-
-QUnit.load = function() {
-	runLoggingCallbacks( 'begin', QUnit, {} );
-
-	// Initialize the config, saving the execution queue
-	var oldconfig = extend({}, config);
-	QUnit.init();
-	extend(config, oldconfig);
-
-	config.blocking = false;
-
-	var urlConfigHtml = '', len = config.urlConfig.length;
-	for ( var i = 0, val; i < len, val = config.urlConfig[i]; i++ ) {
-		config[val] = QUnit.urlParams[val];
-		urlConfigHtml += '<label><input name="' + val + '" type="checkbox"' + ( config[val] ? ' checked="checked"' : '' ) + '>' + val + '</label>';
-	}
-
-	var userAgent = id("qunit-userAgent");
-	if ( userAgent ) {
-		userAgent.innerHTML = navigator.userAgent;
-	}
-	var banner = id("qunit-header");
-	if ( banner ) {
-		banner.innerHTML = '<a href="' + QUnit.url({ filter: undefined }) + '"> ' + banner.innerHTML + '</a> ' + urlConfigHtml;
-		addEvent( banner, "change", function( event ) {
-			var params = {};
-			params[ event.target.name ] = event.target.checked ? true : undefined;
-			window.location = QUnit.url( params );
-		});
-	}
-
-	var toolbar = id("qunit-testrunner-toolbar");
-	if ( toolbar ) {
-		var filter = document.createElement("input");
-		filter.type = "checkbox";
-		filter.id = "qunit-filter-pass";
-		addEvent( filter, "click", function() {
-			var ol = document.getElementById("qunit-tests");
-			if ( filter.checked ) {
-				ol.className = ol.className + " hidepass";
-			} else {
-				var tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
-				ol.className = tmp.replace(/ hidepass /, " ");
-			}
-			if ( defined.sessionStorage ) {
-				if (filter.checked) {
-					sessionStorage.setItem("qunit-filter-passed-tests", "true");
-				} else {
-					sessionStorage.removeItem("qunit-filter-passed-tests");
-				}
-			}
-		});
-		if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) {
-			filter.checked = true;
-			var ol = document.getElementById("qunit-tests");
-			ol.className = ol.className + " hidepass";
-		}
-		toolbar.appendChild( filter );
-
-		var label = document.createElement("label");
-		label.setAttribute("for", "qunit-filter-pass");
-		label.innerHTML = "Hide passed tests";
-		toolbar.appendChild( label );
-	}
-
-	var main = id('qunit-fixture');
-	if ( main ) {
-		config.fixture = main.innerHTML;
-	}
-
-	if (config.autostart) {
-		QUnit.start();
-	}
-};
-
-addEvent(window, "load", QUnit.load);
-
-function done() {
-	config.autorun = true;
-
-	// Log the last module results
-	if ( config.currentModule ) {
-		runLoggingCallbacks( 'moduleDone', QUnit, {
-			name: config.currentModule,
-			failed: config.moduleStats.bad,
-			passed: config.moduleStats.all - config.moduleStats.bad,
-			total: config.moduleStats.all
-		} );
-	}
-
-	var banner = id("qunit-banner"),
-		tests = id("qunit-tests"),
-		runtime = +new Date - config.started,
-		passed = config.stats.all - config.stats.bad,
-		html = [
-			'Tests completed in ',
-			runtime,
-			' milliseconds.<br/>',
-			'<span class="passed">',
-			passed,
-			'</span> tests of <span class="total">',
-			config.stats.all,
-			'</span> passed, <span class="failed">',
-			config.stats.bad,
-			'</span> failed.'
-		].join('');
-
-	if ( banner ) {
-		banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
-	}
-
-	if ( tests ) {
-		id( "qunit-testresult" ).innerHTML = html;
-	}
-
-	if ( config.altertitle && typeof document !== "undefined" && document.title ) {
-		// show ✖ for good, ✔ for bad suite result in title
-		// use escape sequences in case file gets loaded with non-utf-8-charset
-		document.title = [
-			(config.stats.bad ? "\u2716" : "\u2714"),
-			document.title.replace(/^[\u2714\u2716] /i, "")
-		].join(" ");
-	}
-
-	runLoggingCallbacks( 'done', QUnit, {
-		failed: config.stats.bad,
-		passed: passed,
-		total: config.stats.all,
-		runtime: runtime
-	} );
-}
-
-function validTest( name ) {
-	var filter = config.filter,
-		run = false;
-
-	if ( !filter ) {
-		return true;
-	}
-
-	var not = filter.charAt( 0 ) === "!";
-	if ( not ) {
-		filter = filter.slice( 1 );
-	}
-
-	if ( name.indexOf( filter ) !== -1 ) {
-		return !not;
-	}
-
-	if ( not ) {
-		run = true;
-	}
-
-	return run;
-}
-
-// so far supports only Firefox, Chrome and Opera (buggy)
-// could be extended in the future to use something like https://github.com/csnover/TraceKit
-function sourceFromStacktrace() {
-	try {
-		throw new Error();
-	} catch ( e ) {
-		if (e.stacktrace) {
-			// Opera
-			return e.stacktrace.split("\n")[6];
-		} else if (e.stack) {
-			// Firefox, Chrome
-			return e.stack.split("\n")[4];
-		} else if (e.sourceURL) {
-			// Safari, PhantomJS
-			// TODO sourceURL points at the 'throw new Error' line above, useless
-			//return e.sourceURL + ":" + e.line;
-		}
-	}
-}
-
-function escapeInnerText(s) {
-	if (!s) {
-		return "";
-	}
-	s = s + "";
-	return s.replace(/[\&<>]/g, function(s) {
-		switch(s) {
-			case "&": return "&amp;";
-			case "<": return "&lt;";
-			case ">": return "&gt;";
-			default: return s;
-		}
-	});
-}
-
-function synchronize( callback ) {
-	config.queue.push( callback );
-
-	if ( config.autorun && !config.blocking ) {
-		process();
-	}
-}
-
-function process() {
-	var start = (new Date()).getTime();
-
-	while ( config.queue.length && !config.blocking ) {
-		if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
-			config.queue.shift()();
-		} else {
-			window.setTimeout( process, 13 );
-			break;
-		}
-	}
-	if (!config.blocking && !config.queue.length) {
-		done();
-	}
-}
-
-function saveGlobal() {
-	config.pollution = [];
-
-	if ( config.noglobals ) {
-		for ( var key in window ) {
-			config.pollution.push( key );
-		}
-	}
-}
-
-function checkPollution( name ) {
-	var old = config.pollution;
-	saveGlobal();
-
-	var newGlobals = diff( config.pollution, old );
-	if ( newGlobals.length > 0 ) {
-		ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
-	}
-
-	var deletedGlobals = diff( old, config.pollution );
-	if ( deletedGlobals.length > 0 ) {
-		ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
-	}
-}
-
-// returns a new Array with the elements that are in a but not in b
-function diff( a, b ) {
-	var result = a.slice();
-	for ( var i = 0; i < result.length; i++ ) {
-		for ( var j = 0; j < b.length; j++ ) {
-			if ( result[i] === b[j] ) {
-				result.splice(i, 1);
-				i--;
-				break;
-			}
-		}
-	}
-	return result;
-}
-
-function fail(message, exception, callback) {
-	if ( typeof console !== "undefined" && console.error && console.warn ) {
-		console.error(message);
-		console.error(exception);
-		console.warn(callback.toString());
-
-	} else if ( window.opera && opera.postError ) {
-		opera.postError(message, exception, callback.toString);
-	}
-}
-
-function extend(a, b) {
-	for ( var prop in b ) {
-		if ( b[prop] === undefined ) {
-			delete a[prop];
-		} else {
-			a[prop] = b[prop];
-		}
-	}
-
-	return a;
-}
-
-function addEvent(elem, type, fn) {
-	if ( elem.addEventListener ) {
-		elem.addEventListener( type, fn, false );
-	} else if ( elem.attachEvent ) {
-		elem.attachEvent( "on" + type, fn );
-	} else {
-		fn();
-	}
-}
-
-function id(name) {
-	return !!(typeof document !== "undefined" && document && document.getElementById) &&
-		document.getElementById( name );
-}
-
-function registerLoggingCallback(key){
-	return function(callback){
-		config[key].push( callback );
-	};
-}
-
-// Supports deprecated method of completely overwriting logging callbacks
-function runLoggingCallbacks(key, scope, args) {
-	//debugger;
-	var callbacks;
-	if ( QUnit.hasOwnProperty(key) ) {
-		QUnit[key].call(scope, args);
-	} else {
-		callbacks = config[key];
-		for( var i = 0; i < callbacks.length; i++ ) {
-			callbacks[i].call( scope, args );
-		}
-	}
-}
-
-// Test for equality any JavaScript type.
-// Author: Philippe Rathé <prathe@gmail.com>
-QUnit.equiv = function () {
-
-	var innerEquiv; // the real equiv function
-	var callers = []; // stack to decide between skip/abort functions
-	var parents = []; // stack to avoiding loops from circular referencing
-
-	// Call the o related callback with the given arguments.
-	function bindCallbacks(o, callbacks, args) {
-		var prop = QUnit.objectType(o);
-		if (prop) {
-			if (QUnit.objectType(callbacks[prop]) === "function") {
-				return callbacks[prop].apply(callbacks, args);
-			} else {
-				return callbacks[prop]; // or undefined
-			}
-		}
-	}
-
-	var callbacks = function () {
-
-		// for string, boolean, number and null
-		function useStrictEquality(b, a) {
-			if (b instanceof a.constructor || a instanceof b.constructor) {
-				// to catch short annotaion VS 'new' annotation of a
-				// declaration
-				// e.g. var i = 1;
-				// var j = new Number(1);
-				return a == b;
-			} else {
-				return a === b;
-			}
-		}
-
-		return {
-			"string" : useStrictEquality,
-			"boolean" : useStrictEquality,
-			"number" : useStrictEquality,
-			"null" : useStrictEquality,
-			"undefined" : useStrictEquality,
-
-			"nan" : function(b) {
-				return isNaN(b);
-			},
-
-			"date" : function(b, a) {
-				return QUnit.objectType(b) === "date"
-						&& a.valueOf() === b.valueOf();
-			},
-
-			"regexp" : function(b, a) {
-				return QUnit.objectType(b) === "regexp"
-						&& a.source === b.source && // the regex itself
-						a.global === b.global && // and its modifers
-													// (gmi) ...
-						a.ignoreCase === b.ignoreCase
-						&& a.multiline === b.multiline;
-			},
-
-			// - skip when the property is a method of an instance (OOP)
-			// - abort otherwise,
-			// initial === would have catch identical references anyway
-			"function" : function() {
-				var caller = callers[callers.length - 1];
-				return caller !== Object && typeof caller !== "undefined";
-			},
-
-			"array" : function(b, a) {
-				var i, j, loop;
-				var len;
-
-				// b could be an object literal here
-				if (!(QUnit.objectType(b) === "array")) {
-					return false;
-				}
-
-				len = a.length;
-				if (len !== b.length) { // safe and faster
-					return false;
-				}
-
-				// track reference to avoid circular references
-				parents.push(a);
-				for (i = 0; i < len; i++) {
-					loop = false;
-					for (j = 0; j < parents.length; j++) {
-						if (parents[j] === a[i]) {
-							loop = true;// dont rewalk array
-						}
-					}
-					if (!loop && !innerEquiv(a[i], b[i])) {
-						parents.pop();
-						return false;
-					}
-				}
-				parents.pop();
-				return true;
-			},
-
-			"object" : function(b, a) {
-				var i, j, loop;
-				var eq = true; // unless we can proove it
-				var aProperties = [], bProperties = []; // collection of
-														// strings
-
-				// comparing constructors is more strict than using
-				// instanceof
-				if (a.constructor !== b.constructor) {
-					return false;
-				}
-
-				// stack constructor before traversing properties
-				callers.push(a.constructor);
-				// track reference to avoid circular references
-				parents.push(a);
-
-				for (i in a) { // be strict: don't ensures hasOwnProperty
-								// and go deep
-					loop = false;
-					for (j = 0; j < parents.length; j++) {
-						if (parents[j] === a[i])
-							loop = true; // don't go down the same path
-											// twice
-					}
-					aProperties.push(i); // collect a's properties
-
-					if (!loop && !innerEquiv(a[i], b[i])) {
-						eq = false;
-						break;
-					}
-				}
-
-				callers.pop(); // unstack, we are done
-				parents.pop();
-
-				for (i in b) {
-					bProperties.push(i); // collect b's properties
-				}
-
-				// Ensures identical properties name
-				return eq
-						&& innerEquiv(aProperties.sort(), bProperties
-								.sort());
-			}
-		};
-	}();
-
-	innerEquiv = function() { // can take multiple arguments
-		var args = Array.prototype.slice.apply(arguments);
-		if (args.length < 2) {
-			return true; // end transition
-		}
-
-		return (function(a, b) {
-			if (a === b) {
-				return true; // catch the most you can
-			} else if (a === null || b === null || typeof a === "undefined"
-					|| typeof b === "undefined"
-					|| QUnit.objectType(a) !== QUnit.objectType(b)) {
-				return false; // don't lose time with error prone cases
-			} else {
-				return bindCallbacks(a, callbacks, [ b, a ]);
-			}
-
-			// apply transition with (1..n) arguments
-		})(args[0], args[1])
-				&& arguments.callee.apply(this, args.splice(1,
-						args.length - 1));
-	};
-
-	return innerEquiv;
-
-}();
-
-/**
- * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
- * http://flesler.blogspot.com Licensed under BSD
- * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
- *
- * @projectDescription Advanced and extensible data dumping for Javascript.
- * @version 1.0.0
- * @author Ariel Flesler
- * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
- */
-QUnit.jsDump = (function() {
-	function quote( str ) {
-		return '"' + str.toString().replace(/"/g, '\\"') + '"';
-	};
-	function literal( o ) {
-		return o + '';
-	};
-	function join( pre, arr, post ) {
-		var s = jsDump.separator(),
-			base = jsDump.indent(),
-			inner = jsDump.indent(1);
-		if ( arr.join )
-			arr = arr.join( ',' + s + inner );
-		if ( !arr )
-			return pre + post;
-		return [ pre, inner + arr, base + post ].join(s);
-	};
-	function array( arr, stack ) {
-		var i = arr.length, ret = Array(i);
-		this.up();
-		while ( i-- )
-			ret[i] = this.parse( arr[i] , undefined , stack);
-		this.down();
-		return join( '[', ret, ']' );
-	};
-
-	var reName = /^function (\w+)/;
-
-	var jsDump = {
-		parse:function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance
-			stack = stack || [ ];
-			var parser = this.parsers[ type || this.typeOf(obj) ];
-			type = typeof parser;
-			var inStack = inArray(obj, stack);
-			if (inStack != -1) {
-				return 'recursion('+(inStack - stack.length)+')';
-			}
-			//else
-			if (type == 'function')  {
-					stack.push(obj);
-					var res = parser.call( this, obj, stack );
-					stack.pop();
-					return res;
-			}
-			// else
-			return (type == 'string') ? parser : this.parsers.error;
-		},
-		typeOf:function( obj ) {
-			var type;
-			if ( obj === null ) {
-				type = "null";
-			} else if (typeof obj === "undefined") {
-				type = "undefined";
-			} else if (QUnit.is("RegExp", obj)) {
-				type = "regexp";
-			} else if (QUnit.is("Date", obj)) {
-				type = "date";
-			} else if (QUnit.is("Function", obj)) {
-				type = "function";
-			} else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") {
-				type = "window";
-			} else if (obj.nodeType === 9) {
-				type = "document";
-			} else if (obj.nodeType) {
-				type = "node";
-			} else if (typeof obj === "object" && typeof obj.length === "number" && obj.length >= 0) {
-				type = "array";
-			} else {
-				type = typeof obj;
-			}
-			return type;
-		},
-		separator:function() {
-			return this.multiline ?	this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
-		},
-		indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
-			if ( !this.multiline )
-				return '';
-			var chr = this.indentChar;
-			if ( this.HTML )
-				chr = chr.replace(/\t/g,'   ').replace(/ /g,'&nbsp;');
-			return Array( this._depth_ + (extra||0) ).join(chr);
-		},
-		up:function( a ) {
-			this._depth_ += a || 1;
-		},
-		down:function( a ) {
-			this._depth_ -= a || 1;
-		},
-		setParser:function( name, parser ) {
-			this.parsers[name] = parser;
-		},
-		// The next 3 are exposed so you can use them
-		quote:quote,
-		literal:literal,
-		join:join,
-		//
-		_depth_: 1,
-		// This is the list of parsers, to modify them, use jsDump.setParser
-		parsers:{
-			window: '[Window]',
-			document: '[Document]',
-			error:'[ERROR]', //when no parser is found, shouldn't happen
-			unknown: '[Unknown]',
-			'null':'null',
-			'undefined':'undefined',
-			'function':function( fn ) {
-				var ret = 'function',
-					name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
-				if ( name )
-					ret += ' ' + name;
-				ret += '(';
-
-				ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');
-				return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );
-			},
-			array: array,
-			nodelist: array,
-			arguments: array,
-			object:function( map, stack ) {
-				var ret = [ ];
-				QUnit.jsDump.up();
-				for ( var key in map ) {
-				    var val = map[key];
-					ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(val, undefined, stack));
-                }
-				QUnit.jsDump.down();
-				return join( '{', ret, '}' );
-			},
-			node:function( node ) {
-				var open = QUnit.jsDump.HTML ? '&lt;' : '<',
-					close = QUnit.jsDump.HTML ? '&gt;' : '>';
-
-				var tag = node.nodeName.toLowerCase(),
-					ret = open + tag;
-
-				for ( var a in QUnit.jsDump.DOMAttrs ) {
-					var val = node[QUnit.jsDump.DOMAttrs[a]];
-					if ( val )
-						ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );
-				}
-				return ret + close + open + '/' + tag + close;
-			},
-			functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function
-				var l = fn.length;
-				if ( !l ) return '';
-
-				var args = Array(l);
-				while ( l-- )
-					args[l] = String.fromCharCode(97+l);//97 is 'a'
-				return ' ' + args.join(', ') + ' ';
-			},
-			key:quote, //object calls it internally, the key part of an item in a map
-			functionCode:'[code]', //function calls it internally, it's the content of the function
-			attribute:quote, //node calls it internally, it's an html attribute value
-			string:quote,
-			date:quote,
-			regexp:literal, //regex
-			number:literal,
-			'boolean':literal
-		},
-		DOMAttrs:{//attributes to dump from nodes, name=>realName
-			id:'id',
-			name:'name',
-			'class':'className'
-		},
-		HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
-		indentChar:'  ',//indentation unit
-		multiline:true //if true, items in a collection, are separated by a \n, else just a space.
-	};
-
-	return jsDump;
-})();
-
-// from Sizzle.js
-function getText( elems ) {
-	var ret = "", elem;
-
-	for ( var i = 0; elems[i]; i++ ) {
-		elem = elems[i];
-
-		// Get the text from text nodes and CDATA nodes
-		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
-			ret += elem.nodeValue;
-
-		// Traverse everything else, except comment nodes
-		} else if ( elem.nodeType !== 8 ) {
-			ret += getText( elem.childNodes );
-		}
-	}
-
-	return ret;
-};
-
-//from jquery.js
-function inArray( elem, array ) {
-	if ( array.indexOf ) {
-		return array.indexOf( elem );
-	}
-
-	for ( var i = 0, length = array.length; i < length; i++ ) {
-		if ( array[ i ] === elem ) {
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-/*
- * Javascript Diff Algorithm
- *  By John Resig (http://ejohn.org/)
- *  Modified by Chu Alan "sprite"
- *
- * Released under the MIT license.
- *
- * More Info:
- *  http://ejohn.org/projects/javascript-diff-algorithm/
- *
- * Usage: QUnit.diff(expected, actual)
- *
- * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
- */
-QUnit.diff = (function() {
-	function diff(o, n) {
-		var ns = {};
-		var os = {};
-
-		for (var i = 0; i < n.length; i++) {
-			if (ns[n[i]] == null)
-				ns[n[i]] = {
-					rows: [],
-					o: null
-				};
-			ns[n[i]].rows.push(i);
-		}
-
-		for (var i = 0; i < o.length; i++) {
-			if (os[o[i]] == null)
-				os[o[i]] = {
-					rows: [],
-					n: null
-				};
-			os[o[i]].rows.push(i);
-		}
-
-		for (var i in ns) {
-			if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
-				n[ns[i].rows[0]] = {
-					text: n[ns[i].rows[0]],
-					row: os[i].rows[0]
-				};
-				o[os[i].rows[0]] = {
-					text: o[os[i].rows[0]],
-					row: ns[i].rows[0]
-				};
-			}
-		}
-
-		for (var i = 0; i < n.length - 1; i++) {
-			if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&
-			n[i + 1] == o[n[i].row + 1]) {
-				n[i + 1] = {
-					text: n[i + 1],
-					row: n[i].row + 1
-				};
-				o[n[i].row + 1] = {
-					text: o[n[i].row + 1],
-					row: i + 1
-				};
-			}
-		}
-
-		for (var i = n.length - 1; i > 0; i--) {
-			if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
-			n[i - 1] == o[n[i].row - 1]) {
-				n[i - 1] = {
-					text: n[i - 1],
-					row: n[i].row - 1
-				};
-				o[n[i].row - 1] = {
-					text: o[n[i].row - 1],
-					row: i - 1
-				};
-			}
-		}
-
-		return {
-			o: o,
-			n: n
-		};
-	}
-
-	return function(o, n) {
-		o = o.replace(/\s+$/, '');
-		n = n.replace(/\s+$/, '');
-		var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/));
-
-		var str = "";
-
-		var oSpace = o.match(/\s+/g);
-		if (oSpace == null) {
-			oSpace = [" "];
-		}
-		else {
-			oSpace.push(" ");
-		}
-		var nSpace = n.match(/\s+/g);
-		if (nSpace == null) {
-			nSpace = [" "];
-		}
-		else {
-			nSpace.push(" ");
-		}
-
-		if (out.n.length == 0) {
-			for (var i = 0; i < out.o.length; i++) {
-				str += '<del>' + out.o[i] + oSpace[i] + "</del>";
-			}
-		}
-		else {
-			if (out.n[0].text == null) {
-				for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
-					str += '<del>' + out.o[n] + oSpace[n] + "</del>";
-				}
-			}
-
-			for (var i = 0; i < out.n.length; i++) {
-				if (out.n[i].text == null) {
-					str += '<ins>' + out.n[i] + nSpace[i] + "</ins>";
-				}
-				else {
-					var pre = "";
-
-					for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {
-						pre += '<del>' + out.o[n] + oSpace[n] + "</del>";
-					}
-					str += " " + out.n[i].text + nSpace[i] + pre;
-				}
-			}
-		}
-
-		return str;
-	};
-})();
-
-})(this);
--- a/unittests/sinon-ie.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/**
- * Sinon.JS 1.2.0, 2011/09/27
- *
- * @author Christian Johansen (christian@cjohansen.no)
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2011, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-"use strict";
-/*global sinon, setTimeout, setInterval, clearTimeout, clearInterval, Date*/
-/**
- * Helps IE run the fake timers. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake timers to work in IE, don't include this file.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-function setTimeout() {}
-function clearTimeout() {}
-function setInterval() {}
-function clearInterval() {}
-function Date() {}
-
-// Reassign the original functions. Now their writable attribute
-// should be true. Hackish, I know, but it works.
-setTimeout = sinon.timers.setTimeout;
-clearTimeout = sinon.timers.clearTimeout;
-setInterval = sinon.timers.setInterval;
-clearInterval = sinon.timers.clearInterval;
-Date = sinon.timers.Date;
-
-/*global sinon*/
-/**
- * Helps IE run the fake XMLHttpRequest. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake XHR to work in IE, don't include this file.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-function XMLHttpRequest() {}
-
-// Reassign the original function. Now its writable attribute
-// should be true. Hackish, I know, but it works.
-XMLHttpRequest = sinon.xhr.XMLHttpRequest || undefined;
--- a/unittests/sinon-qunit.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/**
- * sinon-qunit 1.0.0, 2010/12/09
- *
- * @author Christian Johansen (christian@cjohansen.no)
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2011, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*global sinon, QUnit, test*/
-sinon.assert.fail = function (msg) {
-    QUnit.ok(false, msg);
-};
-
-sinon.assert.pass = function (assertion) {
-    QUnit.ok(true, assertion);
-};
-
-sinon.config = {
-    injectIntoThis: true,
-    injectInto: null,
-    properties: ["spy", "stub", "mock", "clock", "sandbox"],
-    useFakeTimers: true,
-    useFakeServer: false
-};
-
-(function (global) {
-    var qTest = QUnit.test;
-    
-    QUnit.test = global.test = function (testName, expected, callback, async) {
-        if (arguments.length === 2) {
-            callback = expected;
-            expected = null;
-        }
-
-        return qTest(testName, expected, sinon.test(callback), async);
-    };
-}(this));
--- a/unittests/sinon.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2916 +0,0 @@
-/**
- * Sinon.JS 1.2.0, 2011/09/27
- *
- * @author Christian Johansen (christian@cjohansen.no)
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2011, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-"use strict";
-/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
-/*global module, require, __dirname, document*/
-/**
- * Sinon core utilities. For internal use only.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-var sinon = (function () {
-    var div = typeof document != "undefined" && document.createElement("div");
-
-    function isNode(obj) {
-        var success = false;
-
-        try {
-            obj.appendChild(div);
-            success = div.parentNode == obj;
-        } catch (e) {
-            return false;
-        } finally {
-            try {
-                obj.removeChild(div);
-            } catch (e) {}
-        }
-
-        return success;
-    }
-
-    function isElement(obj) {
-        return div && obj && obj.nodeType === 1 && isNode(obj);
-    }
-
-    return {
-        wrapMethod: function wrapMethod(object, property, method) {
-            if (!object) {
-                throw new TypeError("Should wrap property of object");
-            }
-
-            if (typeof method != "function") {
-                throw new TypeError("Method wrapper should be function");
-            }
-
-            var wrappedMethod = object[property];
-            var type = typeof wrappedMethod;
-
-            if (type != "function") {
-                throw new TypeError("Attempted to wrap " + type + " property " + property +
-                                    " as function");
-            }
-
-            if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
-                throw new TypeError("Attempted to wrap " + property + " which is already wrapped");
-            }
-
-            if (wrappedMethod.calledBefore) {
-                var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
-                throw new TypeError("Attempted to wrap " + property + " which is already " + verb);
-            }
-
-            var owned = object.hasOwnProperty(property);
-            object[property] = method;
-            method.displayName = property;
-
-            method.restore = function () {
-                if(owned) {
-                    object[property] = wrappedMethod;
-                } else {
-                    delete object[property];
-                }
-            };
-
-            method.restore.sinon = true;
-
-            return method;
-        },
-
-        extend: function extend(target) {
-            for (var i = 1, l = arguments.length; i < l; i += 1) {
-                for (var prop in arguments[i]) {
-                    if (arguments[i].hasOwnProperty(prop)) {
-                        target[prop] = arguments[i][prop];
-                    }
-
-                    // DONT ENUM bug, only care about toString
-                    if (arguments[i].hasOwnProperty("toString") &&
-                        arguments[i].toString != target.toString) {
-                        target.toString = arguments[i].toString;
-                    }
-                }
-            }
-
-            return target;
-        },
-
-        create: function create(proto) {
-            var F = function () {};
-            F.prototype = proto;
-            return new F();
-        },
-
-        deepEqual: function deepEqual(a, b) {
-            if (typeof a != "object" || typeof b != "object") {
-                return a === b;
-            }
-
-            if (isElement(a) || isElement(b)) {
-                return a === b;
-            }
-
-            if (a === b) {
-                return true;
-            }
-
-            if (Object.prototype.toString.call(a) == "[object Array]") {
-                if (a.length !== b.length) {
-                    return false;
-                }
-
-                for (var i = 0, l = a.length; i < l; i += 1) {
-                    if (!deepEqual(a[i], b[i])) {
-                        return false;
-                    }
-                }
-
-                return true;
-            }
-
-            var prop, aLength = 0, bLength = 0;
-
-            for (prop in a) {
-                aLength += 1;
-
-                if (!deepEqual(a[prop], b[prop])) {
-                    return false;
-                }
-            }
-
-            for (prop in b) {
-                bLength += 1;
-            }
-
-            if (aLength != bLength) {
-                return false;
-            }
-
-            return true;
-        },
-
-        functionName: function functionName(func) {
-            var name = func.displayName || func.name;
-
-            // Use function decomposition as a last resort to get function
-            // name. Does not rely on function decomposition to work - if it
-            // doesn't debugging will be slightly less informative
-            // (i.e. toString will say 'spy' rather than 'myFunc').
-            if (!name) {
-                var matches = func.toString().match(/function ([^\s\(]+)/);
-                name = matches && matches[1];
-            }
-
-            return name;
-        },
-
-        functionToString: function toString() {
-            if (this.getCall && this.callCount) {
-                var thisValue, prop, i = this.callCount;
-
-                while (i--) {
-                    thisValue = this.getCall(i).thisValue;
-
-                    for (prop in thisValue) {
-                        if (thisValue[prop] === this) {
-                            return prop;
-                        }
-                    }
-                }
-            }
-
-            return this.displayName || "sinon fake";
-        },
-
-        getConfig: function (custom) {
-            var config = {};
-            custom = custom || {};
-            var defaults = sinon.defaultConfig;
-
-            for (var prop in defaults) {
-                if (defaults.hasOwnProperty(prop)) {
-                    config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
-                }
-            }
-
-            return config;
-        },
-
-        format: function (val) {
-            return "" + val;
-        },
-
-        defaultConfig: {
-            injectIntoThis: true,
-            injectInto: null,
-            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-            useFakeTimers: true,
-            useFakeServer: true
-        },
-
-        timesInWords: function timesInWords(count) {
-            return count == 1 && "once" ||
-                count == 2 && "twice" ||
-                count == 3 && "thrice" ||
-                (count || 0) + " times";
-        },
-
-        calledInOrder: function (spies) {
-            for (var i = 1, l = spies.length; i < l; i++) {
-                if (!spies[i - 1].calledBefore(spies[i])) {
-                    return false;
-                }
-            }
-
-            return true;
-        },
-
-        orderByFirstCall: function (spies) {
-            return spies.sort(function (a, b) {
-                // uuid, won't ever be equal
-                return a.getCall(0).callId < b.getCall(0).callId ? -1 : 1;
-            });
-        }
-    };
-}());
-
-if (typeof module == "object" && typeof require == "function") {
-    module.exports = sinon;
-    module.exports.spy = require("./sinon/spy");
-    module.exports.stub = require("./sinon/stub");
-    module.exports.mock = require("./sinon/mock");
-    module.exports.collection = require("./sinon/collection");
-    module.exports.assert = require("./sinon/assert");
-    module.exports.sandbox = require("./sinon/sandbox");
-    module.exports.test = require("./sinon/test");
-    module.exports.testCase = require("./sinon/test_case");
-    module.exports.assert = require("./sinon/assert");
-}
-
-/* @depend ../sinon.js */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Spy functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module == "object" && typeof require == "function";
-    var spyCall;
-    var callId = 0;
-    var push = [].push;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function spy(object, property) {
-        if (!property && typeof object == "function") {
-            return spy.create(object);
-        }
-
-        if (!object || !property) {
-            return spy.create(function () {});
-        }
-
-        var method = object[property];
-        return sinon.wrapMethod(object, property, spy.create(method));
-    }
-
-    sinon.extend(spy, (function () {
-        var slice = Array.prototype.slice;
-
-        function delegateToCalls(api, method, matchAny, actual, notCalled) {
-            api[method] = function () {
-                if (!this.called) {
-                    return !!notCalled;
-                }
-
-                var currentCall;
-                var matches = 0;
-
-                for (var i = 0, l = this.callCount; i < l; i += 1) {
-                    currentCall = this.getCall(i);
-
-                    if (currentCall[actual || method].apply(currentCall, arguments)) {
-                        matches += 1;
-
-                        if (matchAny) {
-                            return true;
-                        }
-                    }
-                }
-
-                return matches === this.callCount;
-            };
-        }
-
-        function matchingFake(fakes, args, strict) {
-            if (!fakes) {
-                return;
-            }
-
-            var alen = args.length;
-
-            for (var i = 0, l = fakes.length; i < l; i++) {
-                if (fakes[i].matches(args, strict)) {
-                    return fakes[i];
-                }
-            }
-        }
-
-        var uuid = 0;
-
-        // Public API
-        var spyApi = {
-            reset: function () {
-                this.called = false;
-                this.calledOnce = false;
-                this.calledTwice = false;
-                this.calledThrice = false;
-                this.callCount = 0;
-                this.args = [];
-                this.returnValues = [];
-                this.thisValues = [];
-                this.exceptions = [];
-                this.callIds = [];
-            },
-
-            create: function create(func) {
-                var name;
-
-                if (typeof func != "function") {
-                    func = function () {};
-                } else {
-                    name = sinon.functionName(func);
-                }
-
-                function proxy() {
-                    return proxy.invoke(func, this, slice.call(arguments));
-                }
-
-                sinon.extend(proxy, spy);
-                delete proxy.create;
-                sinon.extend(proxy, func);
-
-                proxy.reset();
-                proxy.prototype = func.prototype;
-                proxy.displayName = name || "spy";
-                proxy.toString = sinon.functionToString;
-                proxy._create = sinon.spy.create;
-                proxy.id = "spy#" + uuid++;
-
-                return proxy;
-            },
-
-            invoke: function invoke(func, thisValue, args) {
-                var matching = matchingFake(this.fakes, args);
-                var exception, returnValue;
-                this.called = true;
-                this.callCount += 1;
-                this.calledOnce = this.callCount == 1;
-                this.calledTwice = this.callCount == 2;
-                this.calledThrice = this.callCount == 3;
-                push.call(this.thisValues, thisValue);
-                push.call(this.args, args);
-                push.call(this.callIds, callId++);
-
-                try {
-                    if (matching) {
-                        returnValue = matching.invoke(func, thisValue, args);
-                    } else {
-                        returnValue = (this.func || func).apply(thisValue, args);
-                    }
-                } catch (e) {
-                    push.call(this.returnValues, undefined);
-                    exception = e;
-                    throw e;
-                } finally {
-                    push.call(this.exceptions, exception);
-                }
-
-                push.call(this.returnValues, returnValue);
-
-                return returnValue;
-            },
-
-            getCall: function getCall(i) {
-                if (i < 0 || i >= this.callCount) {
-                    return null;
-                }
-
-                return spyCall.create(this, this.thisValues[i], this.args[i],
-                                      this.returnValues[i], this.exceptions[i],
-                                      this.callIds[i]);
-            },
-
-            calledBefore: function calledBefore(spyFn) {
-                if (!this.called) {
-                    return false;
-                }
-
-                if (!spyFn.called) {
-                    return true;
-                }
-
-                return this.callIds[0] < spyFn.callIds[0];
-            },
-
-            calledAfter: function calledAfter(spyFn) {
-                if (!this.called || !spyFn.called) {
-                    return false;
-                }
-
-                return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
-            },
-
-            withArgs: function () {
-                var args = slice.call(arguments);
-
-                if (this.fakes) {
-                    var match = matchingFake(this.fakes, args, true);
-
-                    if (match) {
-                        return match;
-                    }
-                } else {
-                    this.fakes = [];
-                }
-
-                var original = this;
-                var fake = this._create();
-                fake.matchingAguments = args;
-                push.call(this.fakes, fake);
-
-                fake.withArgs = function () {
-                    return original.withArgs.apply(original, arguments);
-                };
-
-                return fake;
-            },
-
-            matches: function (args, strict) {
-                var margs = this.matchingAguments;
-
-                if (margs.length <= args.length &&
-                    sinon.deepEqual(margs, args.slice(0, margs.length))) {
-                    return !strict || margs.length == args.length;
-                }
-            },
-
-            printf: function (format) {
-                var spy = this;
-                var args = [].slice.call(arguments, 1);
-                var formatter;
-
-                return (format || "").replace(/%(.)/g, function (match, specifyer) {
-                    formatter = spyApi.formatters[specifyer];
-
-                    if (typeof formatter == "function") {
-                        return formatter.call(null, spy, args);
-                    } else if (!isNaN(parseInt(specifyer), 10)) {
-                        return sinon.format(args[specifyer - 1]);
-                    }
-
-                    return "%" + specifyer;
-                });
-            }
-        };
-
-        delegateToCalls(spyApi, "calledOn", true);
-        delegateToCalls(spyApi, "alwaysCalledOn", false, "calledOn");
-        delegateToCalls(spyApi, "calledWith", true);
-        delegateToCalls(spyApi, "alwaysCalledWith", false, "calledWith");
-        delegateToCalls(spyApi, "calledWithExactly", true);
-        delegateToCalls(spyApi, "alwaysCalledWithExactly", false, "calledWithExactly");
-        delegateToCalls(spyApi, "neverCalledWith", false, "notCalledWith", true);
-        delegateToCalls(spyApi, "threw", true);
-        delegateToCalls(spyApi, "alwaysThrew", false, "threw");
-        delegateToCalls(spyApi, "returned", true);
-        delegateToCalls(spyApi, "alwaysReturned", false, "returned");
-        delegateToCalls(spyApi, "calledWithNew", true);
-        delegateToCalls(spyApi, "alwaysCalledWithNew", false, "calledWithNew");
-
-        spyApi.formatters = {
-            "c": function (spy) {
-                return sinon.timesInWords(spy.callCount);
-            },
-
-            "n": function (spy) {
-                return spy.toString();
-            },
-
-            "C": function (spy) {
-                var calls = [];
-
-                for (var i = 0, l = spy.callCount; i < l; ++i) {
-                    push.call(calls, "    " + spy.getCall(i).toString());
-                }
-
-                return calls.length > 0 ? "\n" + calls.join("\n") : "";
-            },
-
-            "t": function (spy) {
-                var objects = [];
-
-                for (var i = 0, l = spy.callCount; i < l; ++i) {
-                    push.call(objects, sinon.format(spy.thisValues[i]));
-                }
-
-                return objects.join(", ");
-            },
-
-            "*": function (spy, args) {
-                return args.join(", ");
-            }
-        };
-
-        return spyApi;
-    }()));
-
-    spyCall = (function () {
-        return {
-            create: function create(spy, thisValue, args, returnValue, exception, id) {
-                var proxyCall = sinon.create(spyCall);
-                delete proxyCall.create;
-                proxyCall.proxy = spy;
-                proxyCall.thisValue = thisValue;
-                proxyCall.args = args;
-                proxyCall.returnValue = returnValue;
-                proxyCall.exception = exception;
-                proxyCall.callId = typeof id == "number" && id || callId++;
-
-                return proxyCall;
-            },
-
-            calledOn: function calledOn(thisValue) {
-                return this.thisValue === thisValue;
-            },
-
-            calledWith: function calledWith() {
-                for (var i = 0, l = arguments.length; i < l; i += 1) {
-                    if (!sinon.deepEqual(arguments[i], this.args[i])) {
-                        return false;
-                    }
-                }
-
-                return true;
-            },
-
-            calledWithExactly: function calledWithExactly() {
-                return arguments.length == this.args.length &&
-                    this.calledWith.apply(this, arguments);
-            },
-
-            notCalledWith: function notCalledWith() {
-                for (var i = 0, l = arguments.length; i < l; i += 1) {
-                    if (!sinon.deepEqual(arguments[i], this.args[i])) {
-                        return true;
-                    }
-                }
-                return false;
-            },
-
-            returned: function returned(value) {
-                return this.returnValue === value;
-            },
-
-            threw: function threw(error) {
-                if (typeof error == "undefined" || !this.exception) {
-                    return !!this.exception;
-                }
-
-                if (typeof error == "string") {
-                    return this.exception.name == error;
-                }
-
-                return this.exception === error;
-            },
-
-            calledWithNew: function calledWithNew(thisValue) {
-                return this.thisValue instanceof this.proxy;
-            },
-
-            calledBefore: function (other) {
-                return this.callId < other.callId;
-            },
-
-            calledAfter: function (other) {
-                return this.callId > other.callId;
-            },
-
-            toString: function () {
-                var callStr = this.proxy.toString() + "(";
-                var args = [];
-
-                for (var i = 0, l = this.args.length; i < l; ++i) {
-                    push.call(args, sinon.format(this.args[i]));
-                }
-
-                callStr = callStr + args.join(", ") + ")";
-
-                if (typeof this.returnValue != "undefined") {
-                    callStr += " => " + sinon.format(this.returnValue);
-                }
-
-                if (this.exception) {
-                    callStr += " !" + this.exception.name;
-
-                    if (this.exception.message) {
-                        callStr += "(" + this.exception.message + ")";
-                    }
-                }
-
-                return callStr;
-            }
-        };
-    }());
-
-    spy.spyCall = spyCall;
-
-    // This steps outside the module sandbox and will be removed
-    sinon.spyCall = spyCall;
-
-    if (commonJSModule) {
-        module.exports = spy;
-    } else {
-        sinon.spy = spy;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend spy.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon*/
-/**
- * Stub functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module == "object" && typeof require == "function";
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function stub(object, property, func) {
-        if (!!func && typeof func != "function") {
-            throw new TypeError("Custom stub should be function");
-        }
-
-        var wrapper;
-
-        if (func) {
-            wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
-        } else {
-            wrapper = stub.create();
-        }
-
-        if (!object && !property) {
-            return sinon.stub.create();
-        }
-
-        if (!property && !!object && typeof object == "object") {
-            for (var prop in object) {
-                if (object.hasOwnProperty(prop) && typeof object[prop] == "function") {
-                    stub(object, prop);
-                }
-            }
-
-            return object;
-        }
-
-        return sinon.wrapMethod(object, property, wrapper);
-    }
-
-    function getCallback(stub, args) {
-        if (stub.callArgAt < 0) {
-            for (var i = 0, l = args.length; i < l; ++i) {
-                if (!stub.callArgProp && typeof args[i] == "function") {
-                    return args[i];
-                }
-
-                if (stub.callArgProp && args[i] &&
-                    typeof args[i][stub.callArgProp] == "function") {
-                    return args[i][stub.callArgProp];
-                }
-            }
-
-            return null;
-        }
-
-        return args[stub.callArgAt];
-    }
-
-    var join = Array.prototype.join;
-
-    function getCallbackError(stub, func, args) {
-        if (stub.callArgAt < 0) {
-            var msg;
-
-            if (stub.callArgProp) {
-                msg = sinon.functionName(stub) +
-                    " expected to yield to '" + stub.callArgProp +
-                    "', but no object with such a property was passed."
-            } else {
-                msg = sinon.functionName(stub) +
-                            " expected to yield, but no callback was passed."
-            }
-
-            if (args.length > 0) {
-                msg += " Received [" + join.call(args, ", ") + "]";
-            }
-
-            return msg;
-        }
-
-        return "argument at index " + stub.callArgAt + " is not a function: " + func;
-    }
-
-    function callCallback(stub, args) {
-        if (typeof stub.callArgAt == "number") {
-            var func = getCallback(stub, args);
-
-            if (typeof func != "function") {
-                throw new TypeError(getCallbackError(stub, func, args));
-            }
-
-            func.apply(null, stub.callbackArguments);
-        }
-    }
-
-    var uuid = 0;
-
-    sinon.extend(stub, (function () {
-        var slice = Array.prototype.slice;
-
-        function throwsException(error, message) {
-            if (typeof error == "string") {
-                this.exception = new Error(message || "");
-                this.exception.name = error;
-            } else if (!error) {
-                this.exception = new Error("Error");
-            } else {
-                this.exception = error;
-            }
-            
-            return this;
-        }
-
-        return {
-            create: function create() {
-                var functionStub = function () {
-                    if (functionStub.exception) {
-                        throw functionStub.exception;
-                    }
-
-                    callCallback(functionStub, arguments);
-
-                    return functionStub.returnValue;
-                };
-
-                functionStub.id = "stub#" + uuid++;
-                var orig = functionStub;
-                functionStub = sinon.spy.create(functionStub);
-                functionStub.func = orig;
-
-                sinon.extend(functionStub, stub);
-                functionStub._create = sinon.stub.create;
-                functionStub.displayName = "stub";
-                functionStub.toString = sinon.functionToString;
-
-                return functionStub;
-            },
-
-            returns: function returns(value) {
-                this.returnValue = value;
-
-                return this;
-            },
-
-            "throws": throwsException,
-            throwsException: throwsException,
-
-            callsArg: function callsArg(pos) {
-                if (typeof pos != "number") {
-                    throw new TypeError("argument index is not number");
-                }
-
-                this.callArgAt = pos;
-                this.callbackArguments = [];
-
-                return this;
-            },
-
-            callsArgWith: function callsArgWith(pos) {
-                if (typeof pos != "number") {
-                    throw new TypeError("argument index is not number");
-                }
-
-                this.callArgAt = pos;
-                this.callbackArguments = slice.call(arguments, 1);
-
-                return this;
-            },
-
-            yields: function () {
-                this.callArgAt = -1;
-                this.callbackArguments = slice.call(arguments, 0);
-
-                return this;
-            },
-
-            yieldsTo: function (prop) {
-                this.callArgAt = -1;
-                this.callArgProp = prop;
-                this.callbackArguments = slice.call(arguments, 1);
-
-                return this;
-            }
-        };
-    }()));
-
-    if (commonJSModule) {
-        module.exports = stub;
-    } else {
-        sinon.stub = stub;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false*/
-/*global module, require, sinon*/
-/**
- * Mock functions.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module == "object" && typeof require == "function";
-    var push = [].push;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function mock(object) {
-        if (!object) {
-            return sinon.expectation.create("Anonymous mock");
-        }
-
-        return mock.create(object);
-    }
-
-    sinon.mock = mock;
-
-    sinon.extend(mock, (function () {
-        function each(collection, callback) {
-            if (!collection) {
-                return;
-            }
-
-            for (var i = 0, l = collection.length; i < l; i += 1) {
-                callback(collection[i]);
-            }
-        }
-
-        return {
-            create: function create(object) {
-                if (!object) {
-                    throw new TypeError("object is null");
-                }
-
-                var mockObject = sinon.extend({}, mock);
-                mockObject.object = object;
-                delete mockObject.create;
-
-                return mockObject;
-            },
-
-            expects: function expects(method) {
-                if (!method) {
-                    throw new TypeError("method is falsy");
-                }
-
-                if (!this.expectations) {
-                    this.expectations = {};
-                    this.proxies = [];
-                }
-
-                if (!this.expectations[method]) {
-                    this.expectations[method] = [];
-                    var mockObject = this;
-
-                    sinon.wrapMethod(this.object, method, function () {
-                        return mockObject.invokeMethod(method, this, arguments);
-                    });
-
-                    push.call(this.proxies, method);
-                }
-
-                var expectation = sinon.expectation.create(method);
-                push.call(this.expectations[method], expectation);
-
-                return expectation;
-            },
-
-            restore: function restore() {
-                var object = this.object;
-
-                each(this.proxies, function (proxy) {
-                    if (typeof object[proxy].restore == "function") {
-                        object[proxy].restore();
-                    }
-                });
-            },
-
-            verify: function verify() {
-                var expectations = this.expectations || {};
-                var messages = [], met = [];
-
-                each(this.proxies, function (proxy) {
-                    each(expectations[proxy], function (expectation) {
-                        if (!expectation.met()) {
-                            push.call(messages, expectation.toString());
-                        } else {
-                            push.call(met, expectation.toString());
-                        }
-                    });
-                });
-
-                this.restore();
-
-                if (messages.length > 0) {
-                    sinon.expectation.fail(messages.concat(met).join("\n"));
-                }
-
-                return true;
-            },
-
-            invokeMethod: function invokeMethod(method, thisValue, args) {
-                var expectations = this.expectations && this.expectations[method];
-                var length = expectations && expectations.length || 0;
-
-                for (var i = 0; i < length; i += 1) {
-                    if (!expectations[i].met() &&
-                        expectations[i].allowsCall(thisValue, args)) {
-                        return expectations[i].apply(thisValue, args);
-                    }
-                }
-
-                var messages = [];
-
-                for (i = 0; i < length; i += 1) {
-                    push.call(messages, "    " + expectations[i].toString());
-                }
-
-                messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
-                    proxy: method,
-                    args: args
-                }));
-
-                sinon.expectation.fail(messages.join("\n"));
-            }
-        };
-    }()));
-
-    var times = sinon.timesInWords;
-
-    sinon.expectation = (function () {
-        var slice = Array.prototype.slice;
-        var _invoke = sinon.spy.invoke;
-
-        function callCountInWords(callCount) {
-            if (callCount == 0) {
-                return "never called";
-            } else {
-                return "called " + times(callCount);
-            }
-        }
-
-        function expectedCallCountInWords(expectation) {
-            var min = expectation.minCalls;
-            var max = expectation.maxCalls;
-
-            if (typeof min == "number" && typeof max == "number") {
-                var str = times(min);
-
-                if (min != max) {
-                    str = "at least " + str + " and at most " + times(max);
-                }
-
-                return str;
-            }
-
-            if (typeof min == "number") {
-                return "at least " + times(min);
-            }
-
-            return "at most " + times(max);
-        }
-
-        function receivedMinCalls(expectation) {
-            var hasMinLimit = typeof expectation.minCalls == "number";
-            return !hasMinLimit || expectation.callCount >= expectation.minCalls;
-        }
-
-        function receivedMaxCalls(expectation) {
-            if (typeof expectation.maxCalls != "number") {
-                return false;
-            }
-
-            return expectation.callCount == expectation.maxCalls;
-        }
-
-        return {
-            minCalls: 1,
-            maxCalls: 1,
-
-            create: function create(methodName) {
-                var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
-                delete expectation.create;
-                expectation.method = methodName;
-
-                return expectation;
-            },
-
-            invoke: function invoke(func, thisValue, args) {
-                this.verifyCallAllowed(thisValue, args);
-
-                return _invoke.apply(this, arguments);
-            },
-
-            atLeast: function atLeast(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not number");
-                }
-
-                if (!this.limitsSet) {
-                    this.maxCalls = null;
-                    this.limitsSet = true;
-                }
-
-                this.minCalls = num;
-
-                return this;
-            },
-
-            atMost: function atMost(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not number");
-                }
-
-                if (!this.limitsSet) {
-                    this.minCalls = null;
-                    this.limitsSet = true;
-                }
-
-                this.maxCalls = num;
-
-                return this;
-            },
-
-            never: function never() {
-                return this.exactly(0);
-            },
-
-            once: function once() {
-                return this.exactly(1);
-            },
-
-            twice: function twice() {
-                return this.exactly(2);
-            },
-
-            thrice: function thrice() {
-                return this.exactly(3);
-            },
-
-            exactly: function exactly(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not a number");
-                }
-
-                this.atLeast(num);
-                return this.atMost(num);
-            },
-
-            met: function met() {
-                return !this.failed && receivedMinCalls(this);
-            },
-
-            verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
-                if (receivedMaxCalls(this)) {
-                    this.failed = true;
-                    sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
-                }
-
-                if ("expectedThis" in this && this.expectedThis !== thisValue) {
-                    sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
-                        this.expectedThis);
-                }
-
-                if (!("expectedArguments" in this)) {
-                    return;
-                }
-
-                if (!args || args.length === 0) {
-                    sinon.expectation.fail(this.method + " received no arguments, expected " +
-                        this.expectedArguments.join());
-                }
-
-                if (args.length < this.expectedArguments.length) {
-                    sinon.expectation.fail(this.method + " received too few arguments (" + args.join() +
-                        "), expected " + this.expectedArguments.join());
-                }
-
-                if (this.expectsExactArgCount &&
-                    args.length != this.expectedArguments.length) {
-                    sinon.expectation.fail(this.method + " received too many arguments (" + args.join() +
-                        "), expected " + this.expectedArguments.join());
-                }
-
-                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
-                        sinon.expectation.fail(this.method + " received wrong arguments (" + args.join() +
-                            "), expected " + this.expectedArguments.join());
-                    }
-                }
-            },
-
-            allowsCall: function allowsCall(thisValue, args) {
-                if (this.met()) {
-                    return false;
-                }
-
-                if ("expectedThis" in this && this.expectedThis !== thisValue) {
-                    return false;
-                }
-
-                if (!("expectedArguments" in this)) {
-                    return true;
-                }
-
-                args = args || [];
-
-                if (args.length < this.expectedArguments.length) {
-                    return false;
-                }
-
-                if (this.expectsExactArgCount &&
-                    args.length != this.expectedArguments.length) {
-                    return false;
-                }
-
-                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
-                        return false;
-                    }
-                }
-
-                return true;
-            },
-
-            withArgs: function withArgs() {
-                this.expectedArguments = slice.call(arguments);
-                return this;
-            },
-
-            withExactArgs: function withExactArgs() {
-                this.withArgs.apply(this, arguments);
-                this.expectsExactArgCount = true;
-                return this;
-            },
-
-            on: function on(thisValue) {
-                this.expectedThis = thisValue;
-                return this;
-            },
-
-            toString: function () {
-                var args = (this.expectedArguments || []).slice();
-
-                if (!this.expectsExactArgCount) {
-                    push.call(args, "[...]");
-                }
-
-                var callStr = sinon.spyCall.toString.call({
-                    proxy: this.method, args: args
-                });
-
-                var message = callStr.replace(", [...", "[, ...") + " " +
-                    expectedCallCountInWords(this);
-
-                if (this.met()) {
-                    return "Expectation met: " + message;
-                }
-
-                return "Expected " + message + " (" +
-                    callCountInWords(this.callCount) + ")";
-            },
-
-            verify: function verify() {
-                if (!this.met()) {
-                    sinon.expectation.fail(this.toString());
-                }
-
-                return true;
-            },
-
-            fail: function (message) {
-                var exception = new Error(message);
-                exception.name = "ExpectationError";
-
-                throw exception;
-            }
-        };
-    }());
-
-    if (commonJSModule) {
-        module.exports = mock;
-    } else {
-        sinon.mock = mock;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true*/
-/*global module, require, sinon*/
-/**
- * Collections of stubs, spies and mocks.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module == "object" && typeof require == "function";
-    var push = [].push;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function getFakes(fakeCollection) {
-        if (!fakeCollection.fakes) {
-            fakeCollection.fakes = [];
-        }
-
-        return fakeCollection.fakes;
-    }
-
-    function each(fakeCollection, method) {
-        var fakes = getFakes(fakeCollection);
-
-        for (var i = 0, l = fakes.length; i < l; i += 1) {
-            if (typeof fakes[i][method] == "function") {
-                fakes[i][method]();
-            }
-        }
-    }
-
-    function compact(fakeCollection) {
-        var fakes = getFakes(fakeCollection);
-        var i = 0;
-        while (i < fakes.length) {
-          fakes.splice(i, 1);
-        }
-    }
-
-    var collection = {
-        verify: function resolve() {
-            each(this, "verify");
-        },
-
-        restore: function restore() {
-            each(this, "restore");
-            compact(this);
-        },
-
-        verifyAndRestore: function verifyAndRestore() {
-            var exception;
-
-            try {
-                this.verify();
-            } catch (e) {
-                exception = e;
-            }
-
-            this.restore();
-
-            if (exception) {
-                throw exception;
-            }
-        },
-
-        add: function add(fake) {
-            push.call(getFakes(this), fake);
-            return fake;
-        },
-
-        spy: function spy() {
-            return this.add(sinon.spy.apply(sinon, arguments));
-        },
-
-        stub: function stub(object, property, value) {
-            if (property) {
-                var original = object[property];
-
-                if (typeof original != "function") {
-                    if (!object.hasOwnProperty(property)) {
-                        throw new TypeError("Cannot stub non-existent own property " + property);
-                    }
-
-                    object[property] = value;
-
-                    return this.add({
-                        restore: function () {
-                            object[property] = original;
-                        }
-                    });
-                }
-            }
-
-            return this.add(sinon.stub.apply(sinon, arguments));
-        },
-
-        mock: function mock() {
-            return this.add(sinon.mock.apply(sinon, arguments));
-        },
-
-        inject: function inject(obj) {
-            var col = this;
-
-            obj.spy = function () {
-                return col.spy.apply(col, arguments);
-            };
-
-            obj.stub = function () {
-                return col.stub.apply(col, arguments);
-            };
-
-            obj.mock = function () {
-                return col.mock.apply(col, arguments);
-            };
-
-            return obj;
-        }
-    };
-
-    if (commonJSModule) {
-        module.exports = collection;
-    } else {
-        sinon.collection = collection;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
-/*global module, require, window*/
-/**
- * Fake timer API
- * setTimeout
- * setInterval
- * clearTimeout
- * clearInterval
- * tick
- * reset
- * Date
- *
- * Inspired by jsUnitMockTimeOut from JsUnit
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    var sinon = {};
-}
-
-sinon.clock = (function () {
-    var id = 0;
-
-    function addTimer(args, recurring) {
-        if (args.length === 0) {
-            throw new Error("Function requires at least 1 parameter");
-        }
-
-        var toId = id++;
-        var delay = args[1] || 0;
-
-        if (!this.timeouts) {
-            this.timeouts = {};
-        }
-
-        this.timeouts[toId] = {
-            id: toId,
-            func: args[0],
-            callAt: this.now + delay
-        };
-
-        if (recurring === true) {
-            this.timeouts[toId].interval = delay;
-        }
-
-        return toId;
-    }
-
-    function parseTime(str) {
-        if (!str) {
-            return 0;
-        }
-
-        var strings = str.split(":");
-        var l = strings.length, i = l;
-        var ms = 0, parsed;
-
-        if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
-            throw new Error("tick only understands numbers and 'h:m:s'");
-        }
-
-        while (i--) {
-            parsed = parseInt(strings[i], 10);
-
-            if (parsed >= 60) {
-                throw new Error("Invalid time " + str);
-            }
-
-            ms += parsed * Math.pow(60, (l - i - 1));
-        }
-
-        return ms * 1000;
-    }
-
-    function createObject(object) {
-        var newObject;
-
-        if (Object.create) {
-            newObject = Object.create(object);
-        } else {
-            var F = function () {};
-            F.prototype = object;
-            newObject = new F();
-        }
-
-        newObject.Date.clock = newObject;
-        return newObject;
-    }
-
-    return {
-        now: 0,
-
-        create: function create(now) {
-            var clock = createObject(this);
-
-            if (typeof now == "number") {
-                this.now = now;
-            }
-
-            return clock;
-        },
-
-        setTimeout: function setTimeout(callback, timeout) {
-            return addTimer.call(this, arguments, false);
-        },
-
-        clearTimeout: function clearTimeout(timerId) {
-            if (!this.timeouts) {
-                this.timeouts = [];
-            }
-
-            delete this.timeouts[timerId];
-        },
-
-        setInterval: function setInterval(callback, timeout) {
-            return addTimer.call(this, arguments, true);
-        },
-
-        clearInterval: function clearInterval(timerId) {
-            this.clearTimeout(timerId);
-        },
-
-        tick: function tick(ms) {
-            ms = typeof ms == "number" ? ms : parseTime(ms);
-            var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
-            var timer = this.firstTimerInRange(tickFrom, tickTo);
-
-            while (timer && tickFrom <= tickTo) {
-                if (this.timeouts[timer.id]) {
-                    tickFrom = this.now = timer.callAt;
-                    this.callTimer(timer);
-                }
-
-                timer = this.firstTimerInRange(previous, tickTo);
-                previous = tickFrom;
-            }
-
-            this.now = tickTo;
-        },
-
-        firstTimerInRange: function (from, to) {
-            var timer, smallest, originalTimer;
-
-            for (var id in this.timeouts) {
-                if (this.timeouts.hasOwnProperty(id)) {
-                    if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
-                        continue;
-                    }
-
-                    if (!smallest || this.timeouts[id].callAt < smallest) {
-                        originalTimer = this.timeouts[id];
-                        smallest = this.timeouts[id].callAt;
-                        
-                        timer = {
-                            func: this.timeouts[id].func,
-                            callAt: this.timeouts[id].callAt,
-                            interval: this.timeouts[id].interval,
-                            id: this.timeouts[id].id
-                        };
-                    }
-                }
-            }
-            
-            return timer || null;
-        },
-
-        callTimer: function (timer) {
-            try {
-                if (typeof timer.func == "function") {
-                    timer.func.call(null);
-                } else {
-                    eval(timer.func);
-                }
-            } catch (e) {}
-
-            if (!this.timeouts[timer.id]) {
-                return;
-            }
-
-            if (typeof timer.interval == "number") {
-                this.timeouts[timer.id].callAt += timer.interval;
-            } else {
-                delete this.timeouts[timer.id];
-            }
-        },
-
-        reset: function reset() {
-            this.timeouts = {};
-        },
-
-        Date: (function () {
-            var NativeDate = Date;
-
-            function ClockDate(year, month, date, hour, minute, second, ms) {
-                // Defensive and verbose to avoid potential harm in passing
-                // explicit undefined when user does not pass argument
-                switch (arguments.length) {
-                case 0:
-                    return new NativeDate(ClockDate.clock.now);
-                case 1:
-                    return new NativeDate(year);
-                case 2:
-                    return new NativeDate(year, month);
-                case 3:
-                    return new NativeDate(year, month, date);
-                case 4:
-                    return new NativeDate(year, month, date, hour);
-                case 5:
-                    return new NativeDate(year, month, date, hour, minute);
-                case 6:
-                    return new NativeDate(year, month, date, hour, minute, second);
-                default:
-                    return new NativeDate(year, month, date, hour, minute, second, ms);
-                }
-            }
-
-            if (NativeDate.now) {
-                ClockDate.now = function now() {
-                    return ClockDate.clock.now;
-                };
-            }
-
-            if (NativeDate.toSource) {
-                ClockDate.toSource = function toSource() {
-                    return NativeDate.toSource();
-                };
-            }
-
-            ClockDate.toString = function toString() {
-                return NativeDate.toString();
-            };
-
-            ClockDate.prototype = NativeDate.prototype;
-            ClockDate.parse = NativeDate.parse;
-            ClockDate.UTC = NativeDate.UTC;
-
-            return ClockDate;
-        }())
-    };
-}());
-
-sinon.timers = {
-    setTimeout: setTimeout,
-    clearTimeout: clearTimeout,
-    setInterval: setInterval,
-    clearInterval: clearInterval,
-    Date: Date
-};
-
-sinon.useFakeTimers = (function (global) {
-    var methods = ["Date", "setTimeout", "setInterval", "clearTimeout", "clearInterval"];
-
-    function restore() {
-        var method;
-
-        for (var i = 0, l = this.methods.length; i < l; i++) {
-            method = this.methods[i];
-            global[method] = this["_" + method];
-        }
-    }
-
-    function stubGlobal(method, clock) {
-        clock["_" + method] = global[method];
-
-        global[method] = function () {
-            return clock[method].apply(clock, arguments);
-        };
-
-        for (var prop in clock[method]) {
-            if (clock[method].hasOwnProperty(prop)) {
-                global[method][prop] = clock[method][prop];
-            }
-        }
-
-        global[method].clock = clock;
-    }
-
-    return function useFakeTimers(now) {
-        var clock = sinon.clock.create(now);
-        clock.restore = restore;
-        clock.methods = Array.prototype.slice.call(arguments,
-                                                   typeof now == "number" ? 1 : 0);
-
-        if (clock.methods.length === 0) {
-            clock.methods = methods;
-        }
-
-        for (var i = 0, l = clock.methods.length; i < l; i++) {
-            stubGlobal(clock.methods[i], clock);
-        }
-
-        return clock;
-    };
-}(typeof global != "undefined" ? global : this));
-
-if (typeof module == "object" && typeof require == "function") {
-    module.exports = sinon;
-}
-
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Minimal Event interface implementation
- *
- * Original implementation by Sven Fuchs: https://gist.github.com/995028
- * Modifications and tests by Christian Johansen.
- *
- * @author Sven Fuchs (svenfuchs@artweb-design.de)
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2011 Sven Fuchs, Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    this.sinon = {};
-}
-
-(function () {
-    var push = [].push;
-
-    sinon.Event = function Event(type, bubbles, cancelable) {
-        this.initEvent(type, bubbles, cancelable);
-    };
-
-    sinon.Event.prototype = {
-        initEvent: function(type, bubbles, cancelable) {
-            this.type = type;
-            this.bubbles = bubbles;
-            this.cancelable = cancelable;
-        },
-
-        stopPropagation: function () {},
-
-        preventDefault: function () {
-            this.defaultPrevented = true;
-        }
-    };
-
-    sinon.EventTarget = {
-        addEventListener: function addEventListener(event, listener, useCapture) {
-            this.eventListeners = this.eventListeners || {};
-            this.eventListeners[event] = this.eventListeners[event] || [];
-            push.call(this.eventListeners[event], listener);
-        },
-
-        removeEventListener: function removeEventListener(event, listener, useCapture) {
-            var listeners = this.eventListeners && this.eventListeners[event] || [];
-
-            for (var i = 0, l = listeners.length; i < l; ++i) {
-                if (listeners[i] == listener) {
-                    return listeners.splice(i, 1);
-                }
-            }
-        },
-
-        dispatchEvent: function dispatchEvent(event) {
-            var type = event.type;
-            var listeners = this.eventListeners && this.eventListeners[type] || [];
-
-            for (var i = 0; i < listeners.length; i++) {
-                if (typeof listeners[i] == "function") {
-                    listeners[i].call(this, event);
-                } else {
-                    listeners[i].handleEvent(event);
-                }
-            }
-
-            return !!event.defaultPrevented;
-        }
-    };
-}());
-
-/**
- * @depend event.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Fake XMLHttpRequest object
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    this.sinon = {};
-}
-
-sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
-
-sinon.FakeXMLHttpRequest = (function () {
-    /*jsl:ignore*/
-    var unsafeHeaders = {
-        "Accept-Charset": true,
-        "Accept-Encoding": true,
-        "Connection": true,
-        "Content-Length": true,
-        "Cookie": true,
-        "Cookie2": true,
-        "Content-Transfer-Encoding": true,
-        "Date": true,
-        "Expect": true,
-        "Host": true,
-        "Keep-Alive": true,
-        "Referer": true,
-        "TE": true,
-        "Trailer": true,
-        "Transfer-Encoding": true,
-        "Upgrade": true,
-        "User-Agent": true,
-        "Via": true
-    };
-    /*jsl:end*/
-
-    function FakeXMLHttpRequest() {
-        this.readyState = FakeXMLHttpRequest.UNSENT;
-        this.requestHeaders = {};
-        this.requestBody = null;
-        this.status = 0;
-        this.statusText = "";
-
-        if (typeof FakeXMLHttpRequest.onCreate == "function") {
-            FakeXMLHttpRequest.onCreate(this);
-        }
-    }
-
-    function verifyState(xhr) {
-        if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
-            throw new Error("INVALID_STATE_ERR");
-        }
-
-        if (xhr.sendFlag) {
-            throw new Error("INVALID_STATE_ERR");
-        }
-    }
-
-    sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
-        async: true,
-
-        open: function open(method, url, async, username, password) {
-            this.method = method;
-            this.url = url;
-            this.async = typeof async == "boolean" ? async : true;
-            this.username = username;
-            this.password = password;
-            this.responseText = null;
-            this.responseXML = null;
-            this.requestHeaders = {};
-            this.sendFlag = false;
-            this.readyStateChange(FakeXMLHttpRequest.OPENED);
-        },
-
-        readyStateChange: function readyStateChange(state) {
-            this.readyState = state;
-
-            if (typeof this.onreadystatechange == "function") {
-                this.onreadystatechange();
-            }
-
-            this.dispatchEvent(new sinon.Event("readystatechange"));
-        },
-
-        setRequestHeader: function setRequestHeader(header, value) {
-            verifyState(this);
-
-            if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
-                throw new Error("Refused to set unsafe header \"" + header + "\"");
-            }
-
-            if (this.requestHeaders[header]) {
-                this.requestHeaders[header] += "," + value; 
-            } else {
-                this.requestHeaders[header] = value;
-            }
-        },
-
-        // Helps testing
-        setResponseHeaders: function setResponseHeaders(headers) {
-            this.responseHeaders = {};
-
-            for (var header in headers) {
-                if (headers.hasOwnProperty(header)) {
-                    this.responseHeaders[header] = headers[header];
-                }
-            }
-
-            if (this.async) {
-                this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
-            }
-        },
-
-        // Currently treats ALL data as a DOMString (i.e. no Document)
-        send: function send(data) {
-            verifyState(this);
-
-            if (!/^(get|head)$/i.test(this.method)) {
-                if (this.requestHeaders["Content-Type"]) {
-                    var value = this.requestHeaders["Content-Type"].split(";");
-                    this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
-                } else {
-                    this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
-                }
-
-                this.requestBody = data;
-            }
-
-            this.errorFlag = false;
-            this.sendFlag = this.async;
-            this.readyStateChange(FakeXMLHttpRequest.OPENED);
-
-            if (typeof this.onSend == "function") {
-                this.onSend(this);
-            }
-        },
-
-        abort: function abort() {
-            this.aborted = true;
-            this.responseText = null;
-            this.errorFlag = true;
-            this.requestHeaders = {};
-
-            if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
-                this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
-                this.sendFlag = false;
-            }
-
-            this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
-        },
-
-        getResponseHeader: function getResponseHeader(header) {
-            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                return null;
-            }
-
-            if (/^Set-Cookie2?$/i.test(header)) {
-                return null;
-            }
-
-            header = header.toLowerCase();
-
-            for (var h in this.responseHeaders) {
-                if (h.toLowerCase() == header) {
-                    return this.responseHeaders[h];
-                }
-            }
-
-            return null;
-        },
-
-        getAllResponseHeaders: function getAllResponseHeaders() {
-            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                return "";
-            }
-
-            var headers = "";
-
-            for (var header in this.responseHeaders) {
-                if (this.responseHeaders.hasOwnProperty(header) &&
-                    !/^Set-Cookie2?$/i.test(header)) {
-                    headers += header + ": " + this.responseHeaders[header] + "\r\n";
-                }
-            }
-
-            return headers;
-        },
-
-        setResponseBody: function setResponseBody(body) {
-            if (this.readyState == FakeXMLHttpRequest.DONE) {
-                throw new Error("Request done");
-            }
-
-            if (this.async && this.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                throw new Error("No headers received");
-            }
-
-            var chunkSize = this.chunkSize || 10;
-            var index = 0;
-            this.responseText = "";
-
-            do {
-                if (this.async) {
-                    this.readyStateChange(FakeXMLHttpRequest.LOADING);
-                }
-
-                this.responseText += body.substring(index, index + chunkSize);
-                index += chunkSize;
-            } while (index < body.length);
-
-            var type = this.getResponseHeader("Content-Type");
-
-            if (this.responseText &&
-                (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
-                try {
-                    this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
-                } catch (e) {}
-            }
-
-            if (this.async) {
-                this.readyStateChange(FakeXMLHttpRequest.DONE);
-            } else {
-                this.readyState = FakeXMLHttpRequest.DONE;
-            }
-        },
-
-        respond: function respond(status, headers, body) {
-            this.setResponseHeaders(headers || {});
-            this.status = typeof status == "number" ? status : 200;
-            this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
-            this.setResponseBody(body || "");
-        }
-    });
-
-    sinon.extend(FakeXMLHttpRequest, {
-        UNSENT: 0,
-        OPENED: 1,
-        HEADERS_RECEIVED: 2,
-        LOADING: 3,
-        DONE: 4
-    });
-
-    // Borrowed from JSpec
-    FakeXMLHttpRequest.parseXML = function parseXML(text) {
-        var xmlDoc;
-
-        if (typeof DOMParser != "undefined") {
-            var parser = new DOMParser();
-            xmlDoc = parser.parseFromString(text, "text/xml");
-        } else {
-            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
-            xmlDoc.async = "false";
-            xmlDoc.loadXML(text);
-        }
-
-        return xmlDoc;
-    };
-
-    FakeXMLHttpRequest.statusCodes = {
-        100: "Continue",
-        101: "Switching Protocols",
-        200: "OK",
-        201: "Created",
-        202: "Accepted",
-        203: "Non-Authoritative Information",
-        204: "No Content",
-        205: "Reset Content",
-        206: "Partial Content",
-        300: "Multiple Choice",
-        301: "Moved Permanently",
-        302: "Found",
-        303: "See Other",
-        304: "Not Modified",
-        305: "Use Proxy",
-        307: "Temporary Redirect",
-        400: "Bad Request",
-        401: "Unauthorized",
-        402: "Payment Required",
-        403: "Forbidden",
-        404: "Not Found",
-        405: "Method Not Allowed",
-        406: "Not Acceptable",
-        407: "Proxy Authentication Required",
-        408: "Request Timeout",
-        409: "Conflict",
-        410: "Gone",
-        411: "Length Required",
-        412: "Precondition Failed",
-        413: "Request Entity Too Large",
-        414: "Request-URI Too Long",
-        415: "Unsupported Media Type",
-        416: "Requested Range Not Satisfiable",
-        417: "Expectation Failed",
-        422: "Unprocessable Entity",
-        500: "Internal Server Error",
-        501: "Not Implemented",
-        502: "Bad Gateway",
-        503: "Service Unavailable",
-        504: "Gateway Timeout",
-        505: "HTTP Version Not Supported"
-    };
-
-    return FakeXMLHttpRequest;
-}());
-
-(function (global) {
-    var GlobalXMLHttpRequest = global.XMLHttpRequest;
-    var GlobalActiveXObject = global.ActiveXObject;
-    var supportsActiveX = typeof ActiveXObject != "undefined";
-    var supportsXHR = typeof XMLHttpRequest != "undefined";
-
-    sinon.useFakeXMLHttpRequest = function () {
-        sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
-            if (supportsXHR) {
-                global.XMLHttpRequest = GlobalXMLHttpRequest;
-            }
-
-            if (supportsActiveX) {
-                global.ActiveXObject = GlobalActiveXObject;
-            }
-
-            delete sinon.FakeXMLHttpRequest.restore;
-
-            if (keepOnCreate !== true) {
-                delete sinon.FakeXMLHttpRequest.onCreate;
-            }
-        };
-
-        if (supportsXHR) {
-            global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
-        }
-
-        if (supportsActiveX) {
-            global.ActiveXObject = function ActiveXObject(objId) {
-                if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
-                    return new sinon.FakeXMLHttpRequest();
-                }
-
-                return new GlobalActiveXObject(objId);
-            };
-        }
-
-        return sinon.FakeXMLHttpRequest;
-    };
-}(this));
-
-if (typeof module == "object" && typeof require == "function") {
-    module.exports = sinon;
-}
-
-/**
- * @depend fake_xml_http_request.js
- */
-/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
-/*global module, require, window*/
-/**
- * The Sinon "server" mimics a web server that receives requests from
- * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
- * both synchronously and asynchronously. To respond synchronuously, canned
- * answers have to be provided upfront.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    var sinon = {};
-}
-
-sinon.fakeServer = (function () {
-    var push = [].push;
-    function F() {}
-
-    function create(proto) {
-        F.prototype = proto;
-        return new F();
-    }
-
-    function responseArray(handler) {
-        var response = handler;
-
-        if (Object.prototype.toString.call(handler) != "[object Array]") {
-            response = [200, {}, handler];
-        }
-
-        if (typeof response[2] != "string") {
-            throw new TypeError("Fake server response body should be string, but was " +
-                                typeof response[2]);
-        }
-
-        return response;
-    }
-
-    var wloc = window.location;
-    var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
-
-    function matchOne(response, reqMethod, reqUrl) {
-        var rmeth = response.method;
-        var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
-        var url = response.url;
-        var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
-
-        return matchMethod && matchUrl;
-    }
-
-    function match(response, request) {
-        var requestMethod = this.getHTTPMethod(request);
-        var requestUrl = request.url;
-
-        if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
-            requestUrl = requestUrl.replace(rCurrLoc, "");
-        }
-
-        if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
-            if (typeof response.response == "function") {
-                var args = [request].concat(requestUrl.match(response.url).slice(1));
-                return response.response.apply(response, args);
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    return {
-        create: function () {
-            var server = create(this);
-            this.xhr = sinon.useFakeXMLHttpRequest();
-            server.requests = [];
-
-            this.xhr.onCreate = function (xhrObj) {
-                server.addRequest(xhrObj);
-            };
-
-            return server;
-        },
-
-        addRequest: function addRequest(xhrObj) {
-            var server = this;
-            push.call(this.requests, xhrObj);
-
-            xhrObj.onSend = function () {
-                server.handleRequest(this);
-            };
-
-            if (this.autoRespond && !this.responding) {
-                setTimeout(function () {
-                    server.responding = false;
-                    server.respond();
-                }, this.autoRespondAfter || 10);
-
-                this.responding = true;
-            }
-        },
-
-        getHTTPMethod: function getHTTPMethod(request) {
-            if (this.fakeHTTPMethods && /post/i.test(request.method)) {
-                var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
-                return !!matches ? matches[1] : request.method;
-            }
-
-            return request.method;
-        },
-
-        handleRequest: function handleRequest(xhr) {
-            if (xhr.async) {
-                if (!this.queue) {
-                    this.queue = [];
-                }
-
-                push.call(this.queue, xhr);
-            } else {
-                this.processRequest(xhr);
-            }
-        },
-
-        respondWith: function respondWith(method, url, body) {
-            if (arguments.length == 1) {
-                this.response = responseArray(method);
-            } else {
-                if (!this.responses) {
-                    this.responses = [];
-                }
-
-                if (arguments.length == 2) {
-                    body = url;
-                    url = method;
-                    method = null;
-                }
-
-                push.call(this.responses, {
-                    method: method,
-                    url: url,
-                    response: typeof body == "function" ? body : responseArray(body)
-                });
-            }
-        },
-
-        respond: function respond() {
-            var queue = this.queue || [];
-            var request;
-
-            while(request = queue.shift()) {
-                this.processRequest(request);
-            }
-        },
-
-        processRequest: function processRequest(request) {
-            try {
-                if (request.aborted) {
-                    return;
-                }
-
-                var response = this.response || [404, {}, ""];
-
-                if (this.responses) {
-                    for (var i = 0, l = this.responses.length; i < l; i++) {
-                        if (match.call(this, this.responses[i], request)) {
-                            response = this.responses[i].response;
-                            break;
-                        }
-                    }
-                }
-
-                if (request.readyState != 4) {
-                    request.respond(response[0], response[1], response[2]);
-                }
-            } catch (e) {}
-        },
-
-        restore: function restore() {
-            return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
-        }
-    };
-}());
-
-if (typeof module == "object" && typeof require == "function") {
-    module.exports = sinon;
-}
-
-/**
- * @depend fake_server.js
- * @depend fake_timers.js
- */
-/*jslint browser: true, eqeqeq: false, onevar: false*/
-/*global sinon*/
-/**
- * Add-on for sinon.fakeServer that automatically handles a fake timer along with
- * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
- * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
- * it polls the object for completion with setInterval. Dispite the direct
- * motivation, there is nothing jQuery-specific in this file, so it can be used
- * in any environment where the ajax implementation depends on setInterval or
- * setTimeout.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-(function () {
-    function Server() {}
-    Server.prototype = sinon.fakeServer;
-
-    sinon.fakeServerWithClock = new Server();
-
-    sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
-        if (xhr.async) {
-            if (typeof setTimeout.clock == "object") {
-                this.clock = setTimeout.clock;
-            } else {
-                this.clock = sinon.useFakeTimers();
-                this.resetClock = true;
-            }
-
-            if (!this.longestTimeout) {
-                var clockSetTimeout = this.clock.setTimeout;
-                var clockSetInterval = this.clock.setInterval;
-                var server = this;
-
-                this.clock.setTimeout = function (fn, timeout) {
-                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
-                    return clockSetTimeout.apply(this, arguments);
-                };
-
-                this.clock.setInterval = function (fn, timeout) {
-                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
-                    return clockSetInterval.apply(this, arguments);
-                };
-            }
-        }
-
-        return sinon.fakeServer.addRequest.call(this, xhr);
-    };
-
-    sinon.fakeServerWithClock.respond = function respond() {
-        var returnVal = sinon.fakeServer.respond.apply(this, arguments);
-
-        if (this.clock) {
-            this.clock.tick(this.longestTimeout || 0);
-            this.longestTimeout = 0;
-
-            if (this.resetClock) {
-                this.clock.restore();
-                this.resetClock = false;
-            }
-        }
-
-        return returnVal;
-    };
-
-    sinon.fakeServerWithClock.restore = function restore() {
-        if (this.clock) {
-            this.clock.restore();
-        }
-
-        return sinon.fakeServer.restore.apply(this, arguments);
-    };
-}());
-
-/**
- * @depend ../sinon.js
- * @depend collection.js
- * @depend util/fake_timers.js
- * @depend util/fake_server_with_clock.js
- */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global require, module*/
-/**
- * Manages fake collections as well as fake utilities such as Sinon's
- * timers and fake XHR implementation in one convenient object.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-if (typeof module == "object" && typeof require == "function") {
-    var sinon = require("../sinon");
-    sinon.extend(sinon, require("./util/fake_timers"));
-}
-
-(function () {
-    var push = [].push;
-
-    function exposeValue(sandbox, config, key, value) {
-        if (!value) {
-            return;
-        }
-
-        if (config.injectInto) {
-            config.injectInto[key] = value;
-        } else {
-            push.call(sandbox.args, value);
-        }
-    }
-
-    function prepareSandboxFromConfig(config) {
-        var sandbox = sinon.create(sinon.sandbox);
-
-        if (config.useFakeServer) {
-            if (typeof config.useFakeServer == "object") {
-                sandbox.serverPrototype = config.useFakeServer;
-            }
-
-            sandbox.useFakeServer();
-        }
-
-        if (config.useFakeTimers) {
-            if (typeof config.useFakeTimers == "object") {
-                sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
-            } else {
-                sandbox.useFakeTimers();
-            }
-        }
-
-        return sandbox;
-    }
-
-    sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
-        useFakeTimers: function useFakeTimers() {
-            this.clock = sinon.useFakeTimers.apply(sinon, arguments);
-
-            return this.add(this.clock);
-        },
-
-        serverPrototype: sinon.fakeServer,
-
-        useFakeServer: function useFakeServer() {
-            var proto = this.serverPrototype || sinon.fakeServer;
-
-            if (!proto || !proto.create) {
-                return null;
-            }
-
-            this.server = proto.create();
-            return this.add(this.server);
-        },
-
-        inject: function (obj) {
-            sinon.collection.inject.call(this, obj);
-
-            if (this.clock) {
-                obj.clock = this.clock;
-            }
-
-            if (this.server) {
-                obj.server = this.server;
-                obj.requests = this.server.requests;
-            }
-
-            return obj;
-        },
-
-        create: function (config) {
-            if (!config) {
-                return sinon.create(sinon.sandbox);
-            }
-
-            var sandbox = prepareSandboxFromConfig(config);
-            sandbox.args = sandbox.args || [];
-            var prop, value, exposed = sandbox.inject({});
-
-            if (config.properties) {
-                for (var i = 0, l = config.properties.length; i < l; i++) {
-                    prop = config.properties[i];
-                    value = exposed[prop] || prop == "sandbox" && sandbox;
-                    exposeValue(sandbox, config, prop, value);
-                }
-            } else {
-                exposeValue(sandbox, config, "sandbox", value);
-            }
-
-            return sandbox;
-        }
-    });
-
-    sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
-
-    if (typeof module != "undefined") {
-        module.exports = sinon.sandbox;
-    }
-}());
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- * @depend sandbox.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Test function, sandboxes fakes
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module == "object" && typeof require == "function";
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function test(callback) {
-        var type = typeof callback;
-
-        if (type != "function") {
-            throw new TypeError("sinon.test needs to wrap a test function, got " + type);
-        }
-
-        return function () {
-            var config = sinon.getConfig(sinon.config);
-            config.injectInto = config.injectIntoThis && this || config.injectInto;
-            var sandbox = sinon.sandbox.create(config);
-            var exception, result;
-            var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
-
-            try {
-                result = callback.apply(this, args);
-            } catch (e) {
-                exception = e;
-            }
-
-            sandbox.verifyAndRestore();
-
-            if (exception) {
-                throw exception;
-            }
-
-            return result;
-        };
-    }
-
-    test.config = {
-        injectIntoThis: true,
-        injectInto: null,
-        properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-        useFakeTimers: true,
-        useFakeServer: true
-    };
-
-    if (commonJSModule) {
-        module.exports = test;
-    } else {
-        sinon.test = test;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend test.js
- */
-/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
-/*global module, require, sinon*/
-/**
- * Test case, sandboxes all test functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module == "object" && typeof require == "function";
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon || !Object.prototype.hasOwnProperty) {
-        return;
-    }
-
-    function createTest(property, setUp, tearDown) {
-        return function () {
-            if (setUp) {
-                setUp.apply(this, arguments);
-            }
-
-            var exception, result;
-
-            try {
-                result = property.apply(this, arguments);
-            } catch (e) {
-                exception = e;
-            }
-
-            if (tearDown) {
-                tearDown.apply(this, arguments);
-            }
-
-            if (exception) {
-                throw exception;
-            }
-
-            return result;
-        };
-    }
-
-    function testCase(tests, prefix) {
-        /*jsl:ignore*/
-        if (!tests || typeof tests != "object") {
-            throw new TypeError("sinon.testCase needs an object with test functions");
-        }
-        /*jsl:end*/
-
-        prefix = prefix || "test";
-        var rPrefix = new RegExp("^" + prefix);
-        var methods = {}, testName, property, method;
-        var setUp = tests.setUp;
-        var tearDown = tests.tearDown;
-
-        for (testName in tests) {
-            if (tests.hasOwnProperty(testName)) {
-                property = tests[testName];
-
-                if (/^(setUp|tearDown)$/.test(testName)) {
-                    continue;
-                }
-
-                if (typeof property == "function" && rPrefix.test(testName)) {
-                    method = property;
-
-                    if (setUp || tearDown) {
-                        method = createTest(property, setUp, tearDown);
-                    }
-
-                    methods[testName] = sinon.test(method);
-                } else {
-                    methods[testName] = tests[testName];
-                }
-            }
-        }
-
-        return methods;
-    }
-
-    if (commonJSModule) {
-        module.exports = testCase;
-    } else {
-        sinon.testCase = testCase;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Assertions matching the test spy retrieval interface.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2011 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module == "object" && typeof require == "function";
-    var slice = Array.prototype.slice;
-    var assert;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function verifyIsStub() {
-        var method;
-
-        for (var i = 0, l = arguments.length; i < l; ++i) {
-            method = arguments[i];
-
-            if (!method) {
-                assert.fail("fake is not a spy");
-            }
-
-            if (typeof method != "function") {
-                assert.fail(method + " is not a function");
-            }
-
-            if (typeof method.getCall != "function") {
-                assert.fail(method + " is not stubbed");
-            }
-        }
-    }
-
-    function failAssertion(object, msg) {
-        var failMethod = object.fail || assert.fail;
-        failMethod.call(object, msg);
-    }
-
-    function mirrorPropAsAssertion(name, method, message) {
-        if (arguments.length == 2) {
-            message = method;
-            method = name;
-        }
-
-        assert[name] = function (fake) {
-            verifyIsStub(fake);
-
-            var args = slice.call(arguments, 1);
-            var failed = false;
-
-            if (typeof method == "function") {
-                failed = !method(fake);
-            } else {
-                failed = typeof fake[method] == "function" ?
-                    !fake[method].apply(fake, args) : !fake[method];
-            }
-
-            if (failed) {
-                failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
-            } else {
-                assert.pass(name);
-            }
-        };
-    }
-
-    function exposedName(prefix, prop) {
-        return !prefix || /^fail/.test(prop) ? prop :
-            prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
-    };
-
-    assert = {
-        failException: "AssertError",
-
-        fail: function fail(message) {
-            var error = new Error(message);
-            error.name = this.failException || assert.failException;
-
-            throw error;
-        },
-
-        pass: function pass(assertion) {},
-
-        callOrder: function assertCallOrder() {
-            verifyIsStub.apply(null, arguments);
-            var expected = "", actual = "";
-
-            if (!sinon.calledInOrder(arguments)) {
-                try {
-                    expected = [].join.call(arguments, ", ");
-                    actual = sinon.orderByFirstCall(slice.call(arguments)).join(", ");
-                } catch (e) {}
-
-                failAssertion(this, "expected " + expected + " to be " +
-                              "called in order but were called as " + actual);
-            } else {
-                assert.pass("callOrder");
-            }
-        },
-
-        callCount: function assertCallCount(method, count) {
-            verifyIsStub(method);
-
-            if (method.callCount != count) {
-                var msg = "expected %n to be called " + sinon.timesInWords(count) +
-                    " but was called %c%C";
-                failAssertion(this, method.printf(msg));
-            } else {
-                assert.pass("callCount");
-            }
-        },
-
-        expose: function expose(target, options) {
-            if (!target) {
-                throw new TypeError("target is null or undefined");
-            }
-
-            var o = options || {};
-            var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
-            var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
-
-            for (var method in this) {
-                if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
-                    target[exposedName(prefix, method)] = this[method];
-                }
-            }
-
-            return target;
-        }
-    };
-
-    mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
-    mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
-                          "expected %n to not have been called but was called %c%C");
-    mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
-    mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
-    mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
-    mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
-    mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
-    mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
-    mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
-    mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
-    mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
-    mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
-    mirrorPropAsAssertion("threw", "%n did not throw exception%C");
-    mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
-
-    if (commonJSModule) {
-        module.exports = assert;
-    } else {
-        sinon.assert = assert;
-    }
-}(typeof sinon == "object" && sinon || null));
-
--- a/unittests/tests/dataloader.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-function test_dataloader() {
-  module("Dataloader", { setup: function() {                                     
-                                      IriSP.jQuery = jQuery;
-                                }
-    });  
-  
-  test("should initialize dataloader", function() {
-    var dt = new IriSP.DataLoader();    
-    deepEqual(dt._cache, {}, "_cache empty");
-  });
-               
-  test("should get an outside ressource", function() {
-   
-    var response_array = [{ id: 12, text: "Hey there" }];
-    var response_string = JSON.stringify(response_array);
-    
-    var xhr = this.sandbox.useFakeXMLHttpRequest();
-    var requests = this.requests = [];
-    
-    xhr.onCreate = function (request) {
-        requests.push(request);
-    };
-
-    var spy_callback = this.spy();
-    var dt = new IriSP.DataLoader();
-    
-    var resp = dt.get("/url&a=1", spy_callback);
-
-    equals(xhr.requests.length, 1, "the mock ajax object should have received the request");
-    
-    xhr.requests[0].respond(200, { "Content-Type": "application/json" },
-                             response_string);
-    
-    
-    ok(spy_callback.calledOnce, "callback called");
-    ok(spy_callback.calledWith(response_array), "callback called with correct string");
-    
-    deepEqual(dt._cache["/url"], response_array, "the response should be stored in the cache");
-    
-    var resp2 = dt.get("/url&a=2", spy_callback);
-    ok(spy_callback.calledTwice && xhr.requests.length === 1, "callback called twice but request made only once.");
-    
-  });
- 
-  test("should default to JSONP for foreign domains", function() {
-    /* we can't simulate jsonp so we just verify that the function is called */
-    var stub = this.stub(IriSP.jQuery, "ajax");
-    var dt = new IriSP.DataLoader();
-    
-    var resp = dt.get("http://example.com/url&a=1", stub);
-
-    ok(stub.calledOnce, "ajax request actually made");
-  });
-   
-}
--- a/unittests/tests/init.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-function test_init() {
-	module("test initialization routines",
-  {
-    setup: function() {
-      IriSP.jQuery("#widget-div").append("<div id='LdtPlayer'></div>");
-      this.popcornOptions = {
-          container: "LdtPlayer",
-          type: "html5", 
-          file : "trailer.mp4",
-        };
-
-        this.widgetOptions = {
-						width:650,
-						height:480,
-						container:'LdtPlayer',
-						css:'../../src/css/LdtPlayer.css',
-            widgets: [
-              {type: "PlayerWidget",
-               mode: "radio",
-               metadata:{
-                format:'cinelab',
-                src:'test.json',
-                type:'dummy'}
-              },
-             {type: "SegmentsWidget",
-               metadata:{
-                format:'cinelab',
-                src:'test.json',
-                type:'dummy'}
-              },
-             {type: "AnnotationsWidget",
-               metadata:{
-                format:'cinelab',
-                src:'test.json',
-                type:'dummy'}
-              },
-            ]};
-
-        this.modulesOptions = [ 
-            {type: "Module", a : 36},
-            {type: "Module", b : 54}
-        ];
-    }
-  });
-
-  test("test the creation of a correct popcorn object", function() {
-
-    var layoutManager = new IriSP.LayoutManager({container: "LdtPlayer", width: 327, height: 542});
-    var pop = IriSP.configurePopcorn(layoutManager, this.popcornOptions);
-    notDeepEqual(pop, undefined, "returned object is not undefined");
-  });
-
-  test("test the creation of a video tag", function() {
-
-    var popcornOptions = {
-            type: "html5",
-            file: "demo.mp4"
-          };
-
-    var layoutManager = new IriSP.LayoutManager({container: "LdtPlayer", width: 327, height: 542});
-    var pop = IriSP.configurePopcorn(layoutManager, popcornOptions);
-
-    var elem = IriSP.jQuery("#LdtPlayer").find("video");
-    notDeepEqual(elem, [], "the element is not null");
-    equal(elem.attr("src"), popcornOptions.file, "the src attribute is set correctly");
-  });
-
-  test("test the instantiation of a single widget without dependencies", function() {
-
-    var dt = new IriSP.DataLoader();
-    var serialFactory = new IriSP.SerializerFactory(dt);
-
-    var layoutManager = new IriSP.LayoutManager({container: "LdtPlayer", width: 327, height: 542});
-    var pop = IriSP.configurePopcorn(layoutManager, this.popcornOptions);
-    var conf = {type: "PlayerWidget",
-               mode: "radio",
-               metadata:{
-                format:'cinelab',
-                src:'test.json',
-                type:'dummy'}
-              };
-
-    var res = IriSP.instantiateWidget(pop, serialFactory, layoutManager, conf);
-    ok(res instanceof IriSP.PlayerWidget, "the returned widget is of the correct instance");
-    equal(res._config.mode, "radio", "the parameters not interpreted by the config are copied into the object");
-  });
-
-  test("test the instantiation of a single widget with one dependency", function() {
-    var dt = new IriSP.DataLoader();
-    var serialFactory = new IriSP.SerializerFactory(dt);
-
-    var layoutManager = new IriSP.LayoutManager({container: "LdtPlayer", width: 327, height: 542});
-
-    var pop = IriSP.configurePopcorn(layoutManager, this.popcornOptions);
-    var conf = {type: "PlayerWidget",
-               mode: "radio",
-               metadata:{
-                format:'cinelab',
-                src:'../test/test.json',
-                type:'dummy'},
-                requires: [
-                {type: "PlayerWidget",
-                  mode: "radio",
-                  metadata:{
-                    format:'cinelab',
-                    src:'../test/test.json',
-                    type:'dummy'
-                } }]
-              };
-
-
-    var res = IriSP.instantiateWidget(pop, serialFactory, layoutManager, conf);
-
-    ok(res instanceof IriSP.PlayerWidget, "the returned widget is of the correct instance");
-    ok(res.PlayerWidget instanceof IriSP.PlayerWidget, "the dependency widget is accessible from the parent");
-  });
-
-  test("test the instantiation of a bunch of widgets", function() {
-
-    var layoutManager = new IriSP.LayoutManager({container: "LdtPlayer", width: 327, height: 542});
-    var pop = IriSP.configurePopcorn(layoutManager, this.popcornOptions);
-    var widgets = IriSP.configureWidgets(pop, layoutManager, this.widgetOptions);
-
-    ok(widgets[0] instanceof IriSP.PlayerWidget, "first widget is a player widget");
-    ok(widgets[1] instanceof IriSP.SegmentsWidget, "second widget is a segments widget");
-    ok(widgets[2] instanceof IriSP.AnnotationsWidget, "third widget is an annotation widget");
-    equal(IriSP.jQuery("#" + this.widgetOptions.container).length, 1, "a new dom element has been created");
-  });
-
-  test("test the instantiation of a couple modules", function() {
-      
-    var layoutManager = new IriSP.LayoutManager({container: "LdtPlayer", width: 327, height: 542});
-    var pop = IriSP.configurePopcorn(layoutManager, this.popcornOptions);
-
-    var modules = IriSP.configureModules(pop, this.modulesOptions);
-
-    ok(modules[0] instanceof IriSP.Module && modules[0]._config.a === 36);
-    ok(modules[1] instanceof IriSP.Module && modules[1]._config.b === 54);
-  });
-
-
-}
--- a/unittests/tests/layout.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/* tests for layout.js */
-function test_layout() {
-  module("layout manager", {setup: 
-    function() { 
-    IriSP.jQuery("#widget-div").append("<div id='LdtPlayer'></div>"); 
-    IriSP.jQuery("#widget-div").append("<div id='myDiv'></div>"); 
-    }});
-  
-  test("test the default initialization of layout manager", function() {
-      var lay = new IriSP.LayoutManager();
-      equal(lay._div, "LdtPlayer", "the default div is set correctly");
-      equal(lay._width, 640, "the default width is set correctly");
-      equal(lay._height, undefined, "the default height is set correctly");
-      
-      equal(IriSP.jQuery("#" + lay._div).css("width"), lay._width + "px", "div width is set correctly");      
-  });
-  
-  test("test custom init of layout manager", function() {
-    var lay = new IriSP.LayoutManager({container: "myDiv", width: 327, height: 542});
-    equal(lay._div, "myDiv", "the default div is set correctly");
-    equal(lay._width, 327, "the default width is set correctly");
-    equal(lay._height, 542, "the default height is set correctly");
-    
-    equal(IriSP.jQuery("#" + lay._div).css("width"), lay._width + "px", "div width is set correctly");
-    equal(IriSP.jQuery("#" + lay._div).css("height"), lay._height + "px", "div height is set correctly");
-  });
-  
-  test("test widget div creation", function() {
-    var lay = new IriSP.LayoutManager({});
-    var ret = lay.createDiv(); 
-    var divId = ret[0];
-    var spacerId = ret[1];
-    
-    equal(lay.selector.children("#" + divId).length, 1, "check that a subdiv container is created");
-    equal(lay.selector.children("#" + spacerId).length, 1, "check that a spacer subdiv is created");
-    equal(lay.selector.children("#" + spacerId).height() + "px", IriSP.widgetsDefaults.LayoutManager.spacer_div_height, "check that spacer height is set");
-    
-  });
-  
-};
--- a/unittests/tests/module.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-/* test module for base widgets */
-function test_module() {
-  module("Base module testing", 
-  {setup : function() {
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.JSONSerializer(this.dt, "/url");
-  } }
-  );
-  
-  test("test initialisation", function() {
-    var config = { a : 540};
-    var mod = new IriSP.Module(this.Popcorn, config, this.ser);
-    deepEqual(mod._config, config, "Check that config is copied correctly");
-  });
-};
--- a/unittests/tests/serializer.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-function test_serializer() {
-  module("Serializer basic tests", {setup: function() {
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.Serializer(this.dt, "http://google.com");
-  }});
-  
-  test("init the serializer with a DataLoader and an url", function() {
-      
-      equal( this.ser._DataLoader, this.dt, "The dataloader reference is copied to the object." );
-      equal( this.ser._url, "http://google.com", "The url has been copied as well." );      
-      deepEqual( this.ser._data, [], "The serializer data is not defined." );
-  });
-  
-  test("check that the serialize and deserialize abstract functions are defined", function() {
-      notEqual(this.ser.serialize, undefined, ".serialize is defined");
-      notEqual(this.ser.deserialize, undefined, ".deserialize is defined");
-  });
-  
-  test("check if currentMedia() is defined", function() {
-  
-  });
-
-};
\ No newline at end of file
--- a/unittests/tests/serializerFactory.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/* tests for the serializer factory */
-function test_serializerFactory() {
-  module("SerializerFactory tests", 
-    { setup: function() {
-              this.dt = new IriSP.DataLoader();
-  }}); 
-  
-  test("test instantiation of a json serializer", function() {
-    var factory = new IriSP.SerializerFactory(this.dt);    
-    var config = { type: "json", src : "/url" };
-    var ser = factory.getSerializer(config);
-    
-    ok(ser instanceof IriSP.JSONSerializer, "returned object is instance of json serializer");    
-  });
-
-  test("test instantiation of a dummy serializer", function() {
-    var factory = new IriSP.SerializerFactory(this.dt);    
-    var config = { type: "dummy", src : "/url" };
-    var ser = factory.getSerializer(config);
-    
-    ok(ser instanceof IriSP.MockSerializer, "returned object is instance of json serializer");    
-  });
-  
-  test("test instantiation of a garbage serializer", function() {
-    var factory = new IriSP.SerializerFactory(this.dt);    
-    var config = {type: "garbage", src : "/url" };
-    var ser = factory.getSerializer(config);
-    
-    equal(ser, undefined, "returned object is undefined");    
-  });
-};
\ No newline at end of file
--- a/unittests/tests/serializers/JSONSerializer.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-function test_JSONSerializer() {
-  module("JSON Serializer tests", 
-    { setup: function() {      
-      this.dt = new IriSP.DataLoader();
-      }
-    }
-    );    
-    
-    test("should return the correct JSON", function() {
-      var arr = ["ab", {"de" : "fg"}, "lp"];
-      var serializer = new IriSP.JSONSerializer(this.dt);
-
-      equal(serializer.serialize(arr), JSON.stringify(arr), "assert that the outputted json is correct");
-    });
-    
-    test("sync()", function() {
-      this.xhr = this.sandbox.useFakeXMLHttpRequest();
-      this.requests = [];
-      this.xhr.onCreate = function (request) {
-        this.requests.push(request);
-      };
-      
-      var response_array = { media: 12, content: "Hey there", 
-                             annotations: [{"begin": "32", "end" : 64}, {"begin": "08", "end" : 27},{"begin": "02", "end" : 61}]  };
-
-      /* sorted array is our comparision array */
-      var sorted_array = IriSP.jQuery.extend({}, response_array);
-      sorted_array.annotations.sort(function(a, b) 
-          { var a_begin = +a.begin;
-            var b_begin = +b.begin;
-            return a_begin - b_begin;
-          });
-          
-      var response_string = JSON.stringify(response_array);
-  
-      var spy_callback = this.spy();
-      var ser = new IriSP.JSONSerializer(this.dt, "/url");
-      
-      ser.sync(spy_callback);
-      
-      equals(this.xhr.requests.length, 1, "the mock ajax object should have received the request");
-      equals(this.xhr.requests[0].url, "/url", "the requested url is correct");
-
-      this.xhr.requests[0].respond(200, { "Content-Type": "application/json" },
-                             response_string);
-        
-      ok(spy_callback.calledOnce, "callback called");
-      ok(spy_callback.calledWith(response_array), "callback called with correct value");
-      deepEqual(ser._data, response_array, "the internal variable is initialized to the correct value");
-      
-      var order_preserved = true;
-      
-      var i = 0;
-      for(i = 0; i < ser._data.length - 1; i++) {
-        if (ser._data.annotations[i].begin > ser._data.annotations[i+1].begin) {
-            order_preserved = false;
-            break;
-        }
-      }
-      
-      ok(order_preserved, "the annotation sub-array is sorted by begin time");
-    });
-
-    test("currentMedia should return the current media", function() {
-      var ser = new IriSP.JSONSerializer(this.dt, "/url");
-
-      ser._data = {}
-      ser._data.medias = [0];
-      equal(ser.currentMedia(), 0, "currentMedia() returns the correct value");
-    });
-
-    test("test annotation search", function() {
-      var ser = new IriSP.JSONSerializer(this.dt, "../test/test.json");
-            
-      ser._data = { annotations : [
-      {"content": {        
-        "description": "professeur", 
-        "title": "garrigou"
-        }},
-      { "content": {        
-        "description": "interview", 
-        "title": "Revue de presse - Hervé Gardette"
-      }},
-      {"content": {        
-        "description": "concept", 
-        "title": "idée"
-      }},
-      { "content": {        
-        "description": "", 
-        "title": "sans titre"
-      }}
-      ]};
-      
-      equal(ser.searchAnnotations("GarriGOU", "", "").length, 1, "requesting on title works");
-      equal(ser.searchAnnotations("", "IntErView", "").length, 1, "requesting on description works");      
-      equal(ser.searchAnnotations("", "", "").length, 4, "empty request works");
-      equal(ser.searchAnnotations("idée", "concept", "").length, 1, "specific request works");
-      
-      
-    });
-    
-    test("test occurence count", function() {
-    var ser = new IriSP.JSONSerializer(this.dt, "../test/test.json");
-            
-      ser._data = { annotations : [
-      {"content": {        
-        "description": "professeur", 
-        "title": "garrigou"
-        }, "id" : 1 },
-      { "content": {        
-        "description": "interview", 
-        "title": "Revue de presse - Hervé Gardette"
-      }, "id" : 2},
-      {"content": {        
-        "description": "concept", 
-        "title": "idée"
-      }, "id" : 3},
-      { "content": {        
-        "description": "", 
-        "title": "sans titre"
-      }, "id" : 4}
-      ]};
-      
-      // a function to get the number of fields in a dict.
-      function countOccurences(queryString) {
-        var count = 0;
-        for (var i in ser.searchOccurences(queryString)) {
-          count++;
-        };
-        
-        return count;
-      };
-      
-      equal(countOccurences("garrigou"), 1, "first request works");
-      deepEqual(ser.searchOccurences("garrigou"), {1 : 1}, "returned object is correctly defined");
-          
-      equal(countOccurences("garrigou interview"), 2, "second request works");
-      equal(countOccurences("garrigou idée interview"), 3, "third request works");
-    });
-    
-    test("test current annotation search", function() {
-      var ser = new IriSP.JSONSerializer(this.dt, "../test/test.json");      
-
-      ser._data = { 
-      "views": [
-          {
-            "id": "0", 
-            "contents": [
-              "franceculture_retourdudimanche20100620"
-            ], 
-            "annotation_types": [
-              "c_1F07824B-F512-78A9-49DB-6FB51DAB9560"
-            ]
-          }
-        ], 
-          annotations : [
-      {"begin": 1234, "end" : 578900,
-       "content": {        
-        "description": "professeur", 
-        "title": "garrigou"
-        }, 
-      "id" : 1,
-      "meta": {
-        "dc:contributor": "perso", 
-        "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-        "dc:created": "2011-10-20T13:36:18.286693", 
-        "dc:modified": "2011-10-20T13:36:18.286693", 
-        "dc:creator": "perso"
-        } 
-      }, 
-      {"begin": 1234, "end" : 578900,
-       "content": {        
-        "description": "interview", 
-        "title": "Revue de presse - Hervé Gardette"
-        }, 
-       "id" : 2, 
-       "meta": {
-        "dc:contributor": "perso", 
-        "id-ref": "c_1F07824B-F512-78A9-49DB-6FB51DAB9560", 
-        "dc:created": "2011-10-20T13:36:18.286693", 
-        "dc:modified": "2011-10-20T13:36:18.286693", 
-        "dc:creator": "perso"
-        } 
-      },
-      {"begin": 1234, "end" : 578900,
-       "content": {        
-        "description": "interview", 
-        "title": "lolol"
-        }, 
-       "id" : 2, 
-       "meta": {
-        "dc:contributor": "perso", 
-        "id-ref": "c_dfdfdfdf", 
-        "dc:created": "2011-10-20T13:36:18.286693", 
-        "dc:modified": "2011-10-20T13:36:18.286693", 
-        "dc:creator": "perso"
-        } 
-      }
- 
-      ]};
-
-      var ret = ser.currentAnnotations(234);  
-      equal(ret.length, 2, "the correct number of elements is returned");
-      ok(ret[0].begin < 234 * 1000 && ret[0].end > 234 * 1000 && 
-         ret[0].meta["id-ref"] == "c_1F07824B-F512-78A9-49DB-6FB51DAB9560",
-         "the first element is correctly configured");
-
-    });
- 
-};
--- a/unittests/tests/serializers/mockSerializer.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-function test_mockSerializer() {
-  module("Mock Serializer basic tests");
-  
-  test("init the serializer with a DataLoader and an url", function() {
-      var dt = new IriSP.DataLoader();
-      var ser = new IriSP.MockSerializer(dt, "http://google.com");
-      equal( ser._DataLoader, dt, "The dataloader reference is copied to the object." );
-      equal( ser._url, "http://google.com", "The url has been copied as well." );
-      ok(ser._data, "the mock data is defined");
-  });
-  
-  test("check that the serialize and deserialize abstract functions are defined", function() {
-      var dt = new IriSP.DataLoader();
-      var ser = new IriSP.MockSerializer(dt);
-      notEqual(ser.serialize, undefined, ".serialize is defined");
-      notEqual(ser.deserialize, undefined, ".deserialize is defined");
-  });
-  
-  test("check that the callback is called", function() {
-      var dt = new IriSP.DataLoader();
-      var ser = new IriSP.MockSerializer(dt);
-      var spy = this.spy();
-      ser.sync(spy);
-      ok(spy.called, "the callback has been called");
-  });
-
-};
\ No newline at end of file
--- a/unittests/tests/serializers/mockTweetSerializer.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-function test_mockTweetSerializer() {
-  module("Mock Tweet Serializer basic tests");
-  
-  test("init the serializer with a DataLoader and an url", function() {
-      var dt = new IriSP.DataLoader();
-      var ser = new IriSP.MockTweetSerializer(dt, "http://google.com");
-      equal( ser._DataLoader, dt, "The dataloader reference is copied to the object." );
-      equal( ser._url, "http://google.com", "The url has been copied as well." );
-      ok(ser._data, "the mock data is defined");
-  });
-  
-  test("check that the serialize and deserialize abstract functions are defined", function() {
-      var dt = new IriSP.DataLoader();
-      var ser = new IriSP.MockTweetSerializer(dt);
-      notEqual(ser.serialize, undefined, ".serialize is defined");
-      notEqual(ser.deserialize, undefined, ".deserialize is defined");
-  });
-  
-  test("check that the callback is called", function() {
-      var dt = new IriSP.DataLoader();
-      var ser = new IriSP.MockTweetSerializer(dt);
-      var spy = this.spy();
-      ser.sync(spy);
-      ok(spy.called, "the callback has been called");
-  });
-
-};
\ No newline at end of file
--- a/unittests/tests/utils.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-function test_utils() {
-  module("Utility function tests");
-  
-  test("test a function to preserve the scope of a method in a callback", function() {
-    var obj = { a : 2};
-    obj.b = function(e, f) { 
-      equal(this.a, 2, "the scope is preserved");
-      equal(e, 1, "arg 1 passed correctly");
-      equal(f, 2, "arg 2 passed correctly");
-    };
-    
-    (IriSP.wrap(obj, obj.b))(1, 2);
-  
-  });
-  
-  test("test function to convert a ratio to a percentage", function() {
-    var time = 2;
-    var total = 3;
-    
-    equal(IriSP.timeToPourcent(2, 3), 66, "the function returns the correct result");    
-    
-    var total = -total;    
-    
-    equal(IriSP.timeToPourcent(2, 3), 66, "the function is immune to negative numbers");            
-  });
-  
-  test("test padding function", function() {
-    equal(IriSP.padWithZeros(3), "03", "function works correctly");
-  });
-  
-  test("test function to convert from seconds to a time", function() {
-    var h = 13, m = 7, s = 41;
-    var t = 13 * 3600 + 7* 60 + 41;
-    
-    var r = IriSP.secondsToTime(t);
-    ok(r.hours === h && r.minutes === m && r.seconds === s, "the converted time is correct");
-    
-    t = -t;
-    var r = IriSP.secondsToTime(t);
-    ok(r.hours === h && r.minutes === m && r.seconds === s, "the function is immune to negative numbers.");
-    equal(IriSP.secondsToTime(t), "13:07:41");
-  });
-  
-  test("test function to format a tweet", function() {
-    var inputs = ["@handle", "@bundle", "#hashtag", "http://t.co/11111", "++", "--"];
-    var outputs = ["<a href='http://twitter.com/handle'>@handle</a>", 
-                   "<a href='http://twitter.com/bundle'>@bundle</a>",
-                   "<a href='http://twitter.com/search?q=%23hashtag'>#hashtag</a>",
-                   "<a href='http://t.co/11111'>http://t.co/11111</a>",
-                   "<span class='Ldt-PolemicPlusPlus'>++</span>",
-                   "<span class='Ldt-PolemicMinusMinus'>--</span>"];
-
-    var i = 0;
-    for(i = 0; i < inputs.length; i++) {
-      equal(IriSP.formatTweet(inputs[i]), outputs[i], "the correct output is given");
-    }
-  });
-
-  test("test function to convert decimal color to hexadecimal", function() {
-    equal(IriSP.DEC_HEXA_COLOR(125), "7D", "first test passes");
-    equal(IriSP.DEC_HEXA_COLOR(24345), "5F19", "second test passes");
-
-  });
-
-  test("test template function", function() {
-    IriSP.default_templates_vars["test_fixture"] = "FIXTURE";
-    equal(IriSP.templToHTML("{{test_fixture}} {{foo}}", {foo: 2}), "FIXTURE 2", "correct template returned"); 
-  });
-
-  test("test url encoding function", function() {
-    equal(IriSP.encodeURI("!'()*"), "%21%27%28%29%2A", "the returned string is correct");
-  });
-}
--- a/unittests/tests/widget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/* test module for base widgets */
-function test_widget() {
-  module("Base widget testing", 
-  {setup : function() {
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.JSONSerializer(this.dt, "/url");
-  } }
-  );
-  
-  test("test initialisation", function() {
-    var config = { container: "mydiv", width: 640, height: 480};
-    var wid = new IriSP.Widget(this.Popcorn, config, this.ser);
-    deepEqual(wid._config, config, "Check if the parent div is set correctly");
-    ok(wid.selector, "Check if the jquery selector is set");
-    
-  });
-  
-  test("test initialisation with more values", function() {
-    var config = { container: "mydiv", widthmax: 640, heightmax: 480};
-    var wid = new IriSP.Widget(this.Popcorn, config, this.ser);
-    deepEqual(wid._config, config, "Check if the parent div is set correctly");
-    ok(wid.selector, "Check if the jquery selector is set");
-    
-  });
-  
-  
-};
--- a/unittests/tests/widgets/annotationsWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/* annotationsWidget.js */
-
-function test_annotations_widget() {
-  module("annotations widget testing", 
-  {setup : function() {    
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockSerializer(this.dt, "/url"); /* dummy serializer */
-        
-    IriSP.jQuery("#widget-div").append("<div id='Ldt-Ligne'></div>");
-    
-    this.config = {
-							width:650,
-							height:1,
-							mode:'radio',
-							container:'widget-div',
-							debug:true,
-							css:'../src/css/LdtPlayer.css'};
-    },
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }
-  });
-  
-  test("test widget initialization", function() {  
-    var widget = new IriSP.AnnotationsWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-
-    equal(widget.selector.children(".Ldt-AnnotationsWidget").length, 1, "test if the div has been added correctly");
-  });
-  
-  test("test annotation display function", function() {
-    var widget = new IriSP.AnnotationsWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-    var annotation = {content: {"title": "title", "description": "description", "keywords": "keywords"}};
-    widget.displayAnnotation(annotation);
-    equal(widget.selector.find(".Ldt-SaTitle").text(), "title - ( NaN:NaN - NaN:NaN )", "title set correctly");
-    equal(widget.selector.find(".Ldt-SaDescription").text(), "description", "description set correctly");
-    equal(widget.selector.find(".Ldt-SaKeywordText").text(), "", "keywords field set correctly");
-  });
-}; 
--- a/unittests/tests/widgets/arrowWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/* arrowWidget.js */
-
-function test_arrow_widget() {
-  module("arrow widget testing", 
-  {setup : function() {    
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockSerializer(this.dt, "/url"); /* dummy serializer */
-        
-    
-    this.config = {
-							width:650,
-							height:1,
-							mode:'radio',
-							container:'widget-div',
-							debug:true,
-							css:'../src/css/LdtPlayer.css'};
-    },
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }
-  });
-  
-  test("test widget initialization", function() {  
-  
-    var widget = new IriSP.ArrowWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-
-    equal(widget.selector.children(".Ldt-arrowWidget").length, 1, "test if the div has been added correctly");
-
-    /*
-    widget._Popcorn.media.currentTime = 400;
-    widget._Popcorn.trigger("timeupdate");
-    equal(widget.selector.children(".Ldt-arrowWidget").css("left"), "22%", "test if the widget responds correctly to messages.");
-  */
-  });
- }; 
--- a/unittests/tests/widgets/playerWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/* test module for the player widget */
-
-function test_player_widget() {
-  module("player widget testing", 
-  {setup : function() {    
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockSerializer(this.dt, "/url"); /* dummy serializer */
-    this.lay = new IriSP.LayoutManager('widget-div');
-    
-    this.config = {
-							width:650,
-							height:1,
-							mode:'radio',
-							container:'widget-div',
-							debug:true,
-							css:'../src/css/LdtPlayer.css'}					
-    },
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }
-
-  });
-  
-  test("test player initialisation", function() {  
-    var player = new IriSP.PlayerWidget(this.Popcorn, this.config, this.ser);    
-    player.draw();
-    
-    equal(IriSP.jQuery("#widget-div").length, 1, "test if the div has been added correctly");     
-  });
- 
-  test("test play button event handler", function() {
-    var player = new IriSP.PlayerWidget(this.Popcorn, this.config, this.ser);
-
-    var spy_callback = this.spy();
-    var spy_callback2 = this.spy();
-    this.Popcorn.listen("play", spy_callback);
-    this.Popcorn.listen("pause", spy_callback2);
-    sinon.spy(player, "playHandler");
-    
-    player.draw();        
-
-    player.selector.find(".ldt-CtrlPlay").trigger("click");    
-    player.selector.find(".ldt-CtrlPlay").trigger("click");
-    ok(player.playHandler.calledTwice, "play handler called");
-  });
-  
-  test("test mute button event handler", function() {
-    var player = new IriSP.PlayerWidget(this.Popcorn, this.config, this.ser);
-
-    var spy_callback = this.spy();
-    var spy_handler = sinon.spy(player, "muteHandler");
-    this.Popcorn.listen("volumechange", spy_callback);    
-    
-    player.draw();
-         
-    player.selector.find(".ldt-CtrlSound").trigger("click");    
-    ok(this.Popcorn.muted(), "the player is muted");
-    
-    player.selector.find(".ldt-CtrlSound").trigger("click");
-    ok(!this.Popcorn.muted(), "the player is un muted");         
-    ok(spy_handler.called, "handling function has been called");                                                                                                                                        
-  });
-  
-  test("test search button event handler", function() {
-  var player = new IriSP.PlayerWidget(this.Popcorn, this.config, this.ser);
-  
-  var searchTerm = "blah";
-  
-  var spy_callback = this.spy();
-  var spy_open = this.spy();
-  var spy_closed = this.spy();
-  var spy_cleared = this.spy();
-  var spy_handler = sinon.spy(player, "searchButtonHandler");
-  
-  player._Popcorn.listen("IriSP.search", spy_callback);    
-  player._Popcorn.listen("IriSP.search.open", spy_open);    
-  player._Popcorn.listen("IriSP.search.closed", spy_closed);    
-  player._Popcorn.listen("IriSP.search.cleared", spy_cleared);    
-  
-  player.draw();
-     
-  player.selector.find(".ldt-CtrlSearch").trigger("click");
-  player.selector.find(".LdtSearchInput").attr('value', searchTerm); 
-  player.selector.find(".LdtSearchInput").trigger('keyup');
-  
-  ok(spy_handler.called, "search button handling function has been called");  
-  ok(spy_open.called, "open signal has been sent");  
-  ok(spy_callback.called, "search typeahead function has been called");  
-  ok(spy_callback.calledWith(searchTerm), "popcorn message sent with the right parameters");
-
-  player.selector.find(".LdtSearchInput").attr('value', ""); 
-  player.selector.find(".LdtSearchInput").trigger('keyup');
-  ok(spy_cleared.called, "clear message has been sent");
-  
-  player.selector.find(".ldt-CtrlSearch").trigger("click");
-  ok(spy_closed.called, "closed signal has been sent");  
-  
-  });
- 
-  test("test mouseover handler", function() {
-    var player = new IriSP.PlayerWidget(this.Popcorn, this.config, this.ser);
-
-    var spy_callback = this.spy();
-    this.Popcorn.listen("IriSP.PlayerWidget.MouseOver", spy_callback);    
-    this.Popcorn.listen("IriSP.PlayerWidget.MouseOut", spy_callback);    
-    
-    player.draw();
-    var elem = player.selector.get(0);
-
-    if( document.createEvent ) {
-      var evObj = document.createEvent('MouseEvents');
-        evObj.initEvent( 'mouseover', true, false );
-        elem.dispatchEvent(evObj);
-    } else if( document.createEventObject ) {
-        elem.fireEvent('onmouseover');
-    }
-
-     ok(spy_callback.called, "the MouseOver event has been fired");
-
-     if( document.createEvent ) {
-      var evObj = document.createEvent('MouseEvents');
-        evObj.initEvent( 'mouseout', true, false );
-        elem.dispatchEvent(evObj);
-     } else if( document.createEventObject ) {
-        elem.fireEvent('onmouseout');
-     }
-
-     ok(spy_callback.calledTwice, "the MouseOver event has been fired");
-  });
-
-};
--- a/unittests/tests/widgets/polemicWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/* polemicWidget.js */
-
-function test_polemic_widget() {
-  module("polemic widget testing", 
-  {setup : function() {    
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockTweetSerializer(this.dt, "/url"); /* dummy serializer */
-
-    IriSP.jQuery("#widget-div").append("<div id='TooltipDiv'></div>");
-    IriSP.jQuery("#widget-div").append("<div id='PolemicDiv'></div>");
-    this.config = {
-						metadata:{
-							format:'cinelab',
-							src:'test.json',
-							load:'json'},
-							width:650,
-							height:120,
-							mode:'radio',
-							container:'PolemicDiv',
-							debug:true,
-							css:'../src/css/LdtPlayer.css',
-            requires: [{
-							type: "TooltipWidget",
-              container: "TooltipDiv",
-							width: 180,
-							heigh: 160,
-							metadata : {
-								format:'cinelab',
-								type:'empty'
-							}
-						 }]
-    }
-    },  
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }});
-  
-  test("test widget initialization", function() {
-
-    var tooltip = new IriSP.TooltipWidget(this.Popcorn, this.config.requires[0], this.ser);
-    var widget = new IriSP.PolemicWidget(this.Popcorn, this.config, this.ser);
-    widget.TooltipWidget = tooltip;
-    
-    widget.draw();    
-    equal(IriSP.jQuery("#widget-div").length, 1, "test if the div has been added correctly");        
-    equal(IriSP.jQuery("#PolemicDiv svg").length, 1, "test if svg div has been added correctly");
-    
-    // select the second element of the svg. the second because the first is a rect which serves
-    // as a background.
-    var paperSlider = IriSP.jQuery("#PolemicDiv svg :nth-child(2)");
-    // querying svg with jquery is quite the piece of cake.
-    equal(paperSlider.attr("x").baseVal.value, 0, "test if the slider has been created correctly");            
-  });
-  
-  test("test widget interactions", function() {
-  
-    /* We can't test interactions because of raphael */
-    // var tooltip = new IriSP.TooltipWidget(this.Popcorn, this.config.requires[0], this.ser);
-    // var widget = new IriSP.PolemicWidget(this.Popcorn, this.config, this.ser);
-    
-    // widget.TooltipWidget = tooltip;
-    // widget.draw();
-    
-    // var spy_callback = this.spy();    
-    // this.Popcorn.listen("timeupdate", spy_callback);
-    
-    // var random = Math.round(Math.random() * widget.svgElements.length) + 1;
-    // var e = widget.svgElements[random].node;
-    // IriSP.jQuery(e).click();
-    
-    // ok(spy_callback.called, "the currenttime was changed");  
-    
-  });
-  
-  
-}; 
--- a/unittests/tests/widgets/segmentsWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* segmentsWidget.js */
-
-function test_segments_widget() {
-  module("segments widget testing", 
-  {setup : function() {    
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockSerializer(this.dt, "/url"); /* dummy serializer */
-            
-    this.config = {
-						metadata:{
-							format:'cinelab',
-							src:'test.json',
-							load:'json'},
-							width:650,
-							height:1,
-							mode:'radio',
-							container:'widget-div',
-							debug:true,
-							css:'../src/css/LdtPlayer.css'}
-    },  
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }});
-  
-  test("test widget initialization", function() {  
-    var widget = new IriSP.SegmentsWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-  
-    equal(IriSP.jQuery("#widget-div").length, 1, "test if the div has been added correctly");
-    // the + 1 is because we have a z-index div to indicate progress in the video.
-    equal(IriSP.jQuery("#widget-div").children().length, this.ser._data.annotations.length + 1, "test if children have been added correctly");
-    equal(IriSP.jQuery("#widget-div").children(":first").css("z-index"), 100, "test if slider div is created correctly.");
-    equal(IriSP.jQuery("#widget-div").css("overflow"), "auto", "test if the divs are floated correctly.");
-  });
-  
-  test("test click on a random segment", function() {
-    var widget = new IriSP.SegmentsWidget(this.Popcorn, this.config, this.ser);
-    widget.draw();
-
-    var spy_timeupdate = this.spy();
-    var spy_segmentClick = this.spy();
-    var spy_handler = sinon.spy(widget, "clickHandler");
-    this.Popcorn.listen("timeupdate", spy_timeupdate);    
-    
-    var selector = IriSP.jQuery("#widget-div :not(first-child)");
-    var random = Math.round(Math.random() * selector.length) + 1;
-    selector.eq(12).click();
-        
-    ok(spy_timeupdate.called, "the timeupdate signal has been sent");         
-    ok(spy_handler.called, "handling function has been called");           
-  });
-
-  test("test search highlight features", function() {
-  
-    var tag_id = "#s_" + "82613B88-9578-DC2C-D7D0-B2C5BE0B7BDA".toUpperCase();
-    
-    var widget = new IriSP.SegmentsWidget(this.Popcorn, this.config, this.ser);
-    widget.draw();    
-
-    var oldStyle = IriSP.jQuery("#widget-div").children(tag_id).attr("style");
-    widget._Popcorn.trigger("IriSP.search", "sociologie");
-    var newStyle = IriSP.jQuery("#widget-div").children(tag_id).attr("style");
-    notEqual(oldStyle, newStyle, "the segment style has been modified");
-  });
-}; 
--- a/unittests/tests/widgets/sliderWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-function test_slider_widget() {
- module("slider widget testing",
-  {setup : function() {
-    this.Popcorn = Popcorn("#popcorn-div");
-
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockSerializer(this.dt, "/url"); /* dummy serializer */
-
-    this.config = {
-						metadata:{
-							format:'cinelab',
-							src:'test.json',
-							load:'json'},
-							width:650,
-							height:1,
-							mode:'radio',
-							container:'widget-div',
-							debug:true,
-							css:'../src/css/LdtPlayer.css'};
-    IriSP.jQuery("#widget-div").html("");
-    },
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }});
-
-  test("test widget initialization", function() {
-    var widget = new IriSP.SliderWidget(this.Popcorn, this.config, this.ser);
-    widget.draw();
-
-    ok(IriSP.jQuery("#widget-div").children().hasClass("Ldt-sliderBackground"), "test if the div has been set-up");
-    ok(IriSP.jQuery("#widget-div").children().hasClass("Ldt-sliderForeground"), "test if the div has been set-up");
-
-  });
-
-  test("test slider seeking", function() {
-    /*
-    var widget = new IriSP.SliderWidget(this.Popcorn, this.config, this.ser);
-    widget.draw();
-
-    var spy_callback = this.spy();
-    widget._Popcorn.listen("timeupdate", spy_callback);
-    IriSP.jQuery("#widget-div").children().click();
-    ok(spy_callback.called, "handling function has been called");
-    */
-  });
-
-  test("test slider dragging", function() {
-
-    /* comes from the jquery unit tests */
-    var drag = function(handle, dx, dy) {
-      var element = el.data("draggable").element;
-      $(handle).simulate("drag", {
-        dx: dx || 0,
-        dy: dy || 0
-      });
-      dragged = { dx: dx, dy: dy };
-    }
-
-    var widget = new IriSP.SliderWidget(this.Popcorn, this.config, this.ser);
-    widget.draw();
-
-    var spy_callback = this.spy();
-    widget._Popcorn.listen("timeupdate", spy_callback);
-
-    /*
-    IriSP.jQuery("#widget-div").children(".Ldt-sliderPositionMarker").simulate("drag", 70, 50);
-    ok(spy_callback.called, "handling function has been called");
-    */
-  });
-}
--- a/unittests/tests/widgets/sparklineWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/* sparklineWidget.js */
-
-function test_sparkline_widget() {
-  module("Sparkline widget testing", 
-  {setup : function() {    
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockSerializer(this.dt, "/url"); /* dummy serializer */
-        
-    
-    this.config = {
-							width:650,
-							height:1,
-							mode:'radio',
-							container:'widget-div',
-							debug:true,
-							css:'../src/css/LdtPlayer.css'};
-    },
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }
-  });
-  
-  test("test widget initialization", function() {  
-  
-    var widget = new IriSP.SparklineWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-
-    equal(widget.selector.children(".Ldt-SparklineWidget").length, 1, "test if the div has been added correctly");
-
-    /*
-    widget._Popcorn.currentTime(400);
-    widget._Popcorn.trigger("timeupdate");
-    equal(widget.selector.children(".Ldt-SparklineWidget").css("left"), "22%", "test if the widget responds correctly to messages.");
-  */
-  });
- }; 
--- a/unittests/tests/widgets/tooltipWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/* tooltipWidget.js */
-
-function test_tooltip_widget() {
-  module("tooltip widget testing", 
-  {setup : function() {    
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockSerializer(this.dt, "/url"); /* dummy serializer */
-            
-    this.config = {
-							width: 160,
-							height:120,
-              container: "widget-div"
-						};
-    },
-    
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }
-  });
-  
-  test("test tooltip widget initialization", function() {  
-    var widget = new IriSP.TooltipWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-
-    equal(widget.selector.children(".tip").length, 1, "test if the div has been added correctly");
-    equal(widget.selector.children(".tip").css("position"), "fixed", "test if the widget has the correct position attr");    
-    equal(widget.selector.children(".tip").css("display"), "none", "test if tooltip is hidden");    
-  });
-  
-  test("test widget display function", function() {
-    var widget = new IriSP.TooltipWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-    
-    widget.show("ceci est un texte", "#fefefe", 105, 240);
-    equal(widget.selector.children(".tip").css("left"), "105px", "test if div has been positionned correctly");
-    equal(widget.selector.children(".tip").css("top"), "240px", "test if div has been positionned correctly");    
-    equal(widget.selector.find(".tiptext").text(), "ceci est un texte", "test if text has been set correctly");
-    notEqual(widget.selector.children(".tip").css("display"), "none", "test if tooltip is hidden"); 
-    
-    widget.hide();
-    equal(widget.selector.children(".tip").css("display"), "none", "test if tooltip is hidden"); 
-  });
-}; 
--- a/unittests/tests/widgets/tweetsWidget.js	Fri Jun 29 16:22:52 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/* tweetsWidget.js */
-
-function test_tweets_widget() {
-  module("tweet widget testing", 
-  {setup : function() {    
-    this.Popcorn = Popcorn("#popcorn-div");
-    
-    this.dt = new IriSP.DataLoader();
-    this.ser = new IriSP.MockTweetSerializer(this.dt, "/url"); /* dummy serializer */
-
-    this.config = {
-							width:650,
-							height:1,
-							mode:'radio',
-							container:'widget-div',
-							debug:true,
-							css:'../src/css/LdtPlayer.css'};
-    },
-  teardown: function() {
-    /* free the popcorn object because it has signal handlers attached to it */
-    this.Popcorn = Popcorn("#popcorn-div");
-  }
-  });
-  
-  test("test widget initialization", function() {  
-    var widget = new IriSP.TweetsWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-
-    equal(widget.selector.find(".Ldt-tweetAvatar").length, 1, "test if the div has been added correctly");
-    equal(widget.selector.find(".Ldt-tweetContents").length, 1, "test if sub-div has been added correctly");
-  });
-  
-  test("test tweet display function", function() {    
-    // tweak the display period so that our tests don't timeout
-    IriSP.widgetsDefaults.TweetsWidget.tweet_display_period = 10;
-    
-    var widget = new IriSP.TweetsWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-    var annotation = {content: 
-                        {"title": "title", "description": "description", "keywords": "keywords", "img": {"src" : "http://yop.com"}},
-                      meta: {"dc:source" : {}}
-                     };
-    widget.displayTweet(annotation);
-    
-    equal(widget.selector.find(".Ldt-tweetContents").text(), "title", "title set correctly");    
-    equal(widget.selector.find(".Ldt-tweetAvatar").children().attr("src"), "http://yop.com", "user avatar set correctly");
-    
-    var annotation2 = {content: {"title": "title", "description": "description", "keywords": "keywords", "img" : {}}, meta: {"dc:source" : {}}};
-    widget.displayTweet(annotation2);
-    equal(widget.selector.find(".Ldt-tweetAvatar").children().attr("src"), 
-                               IriSP.widgetsDefaults.TweetsWidget.default_profile_picture, "default avatar set correctly");
-    
-    widget.selector.find(".Ldt-tweetWidgetKeepOpen").click();
-    ok(widget._timeoutId === null, "the timeout is cancelled");
-    widget.selector.find(".Ldt-tweetWidgetMinimize").click();
-    
-    widget.displayTweet(annotation2);
-    
-    ok(!widget.selector.is(":visible"), "the widget is hidden after a click");    
-  });
-  
-  test("test async clear", function() {
-  /*
-    expect(1);
-    
-    // tweak the display period so that our tests don't timeout
-    IriSP.widgetsDefaults.TweetsWidget.tweet_display_period = 10;
-    stop();
-    
-    var widget = new IriSP.TweetsWidget(this.Popcorn, this.config, this.ser);    
-    widget.draw();
-    var annotation = {content: {"title": "title", "description": "description", "keywords": "keywords", "img": {"src" : "http://yop.com"}}};
-    widget.displayTweet(annotation);
-  
-
-    window.setTimeout(function() { console.log("called!"); 
-      ok(!widget.selector.is(":visible"), "the widget is hidden after the timeout has passed."); 
-      start(); 
-      }, 100);
-  */
-  });
-};