Merge with the latest changes from jverrier
authorhamidouk
Thu, 12 Jan 2012 10:19:47 +0100
changeset 357 7e234ffc2a23
parent 356 5a89838f79d4 (diff)
parent 352 6fa2e1f8ddaa (current diff)
child 358 27be3fb68776
Merge with the latest changes from jverrier
--- a/src/ldt/ldt/ldt_utils/templates/front/front_player.html	Thu Jan 12 10:13:00 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_player.html	Thu Jan 12 10:19:47 2012 +0100
@@ -17,7 +17,7 @@
 <script type="text/javascript">
     var $j = jQuery.noConflict();
 </script>
-<script type="text/javascript" src="{{LDT_MEDIA_PREFIX}}js/LdtPlayer.min.js"></script>
+<script type="text/javascript" src="{{LDT_MEDIA_PREFIX}}js/LdtPlayer-release.js"></script>
 <script type="text/javascript">
     __IriSP.lib = {
         jQuery:"{{LDT_MEDIA_PREFIX}}js/jquery.min.js",
@@ -85,112 +85,8 @@
     <div class="li_h2">
         <h2>{% trans 'All annotations on the media' %}</h2>
     </div>
-    <ul class="floatlist" id="annot_media">
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li class="selected">
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-        <li>
-            <img class="fl img_media" src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" />
-            <div class="fl une_annot">
-                <h5><a class="blue">Lorem Ipsum Dolor</a></h5>
-                <p class="fr pink font_11">00:12:12 - 00:15:13</p>
-                <p class="clear font_11">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque</p>
-            </div>
-        </li>
-    </ul>
+    <div id="annot_media">       
+    </div>
 </div>
 {% endblock %}
 
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html	Thu Jan 12 10:13:00 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html	Thu Jan 12 10:19:47 2012 +0100
@@ -5,23 +5,127 @@
 <div id="{{ player_id }}_embed" class="iri_player_embed">
 </div>
 <script type="text/javascript">
-	var config = {
-			metadata:{
-				format:'cinelab',
-				src:'{{ json_url }}',
-				load:'jsonp'},
-			gui:{
-				width:{{ player_width }},
-				height:{{ player_height }},
-				mode:'{{ stream_mode }}',
-				container:'{{ player_id }}_embed',
-				debug:false,
-				css:'{{WEB_URL}}{{LDT_MEDIA_PREFIX}}css/LdtPlayer.css'},
-			player:{
-				type:'jwplayer',
-				src:'{{WEB_URL}}{{LDT_MEDIA_PREFIX}}swf/player.swf'}
-		};
-	__IriSP.init(config);     
+  /* Redefine a few variables */  
+  IriSP.jwplayer_swf_path = "{{WEB_URL}}{{LDT_MEDIA_PREFIX}}swf/player.swf";
+  IriSP.libdir = "{{WEB_URL}}{{LDT_MEDIA_PREFIX}}js/";
+  
+  IriSP.lib = { 
+    jQuery : IriSP.libdir + "jquery.min.js",
+    jQueryUI : IriSP.libdir + "jquery-ui.min.js",
+    jQueryToolTip : IriSP.libdir + "jquery.tools.min.js",
+    swfObject : IriSP.libdir + "swfobject.js",
+    cssjQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css",
+    popcorn : IriSP.libdir + "popcorn.js",
+    jwplayer : IriSP.libdir + "jwplayer.js",
+    popcornReplacement: IriSP.libdir + "pop.js",
+    raphael: IriSP.libdir + "raphael.js",
+    jquery_sparkline: IriSP.libdir + "jquery.sparkline.js",
+    "popcorn.mediafragment" : IriSP.libdir + "popcorn.mediafragment.js",
+    "popcorn.code" : IriSP.libdir + "popcorn.code.js",
+    "popcorn.jwplayer": IriSP.libdir + "popcorn.jwplayer.js",
+    "popcorn.youtube": IriSP.libdir + "popcorn.youtube.js",    
+  };
+    var config = {            
+        gui:{
+            width:{{ player_width }},             
+            container:'{{ player_id }}_embed',
+            css:'{{WEB_URL}}{{LDT_MEDIA_PREFIX}}css/LdtPlayer.css',
+            widgets: [
+            {type: "SparklineWidget",
+             width: {{ player_width }}, /* required for this widget */
+             height: 50,
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'}
+            },
+            {type: "SliderWidget",
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'}
+            },
+            {type: "AnnotationsListWidget",
+             container: "annot_media",             
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'}
+            },
+            {type: "PlayerWidget", // please note that type refers directly to the constructor of the widget.
+             mode: "radio",
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'}
+            },
+            {type: "SegmentsWidget",
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'},
+             requires: [{
+              type: "TooltipWidget",
+              width: 180,
+              heigh: 160,
+              metadata : {
+                type:'empty'
+              }
+             }],
+            },           
+            {type: "ArrowWidget",
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'}
+            },
+
+
+            {type: "AnnotationsWidget",
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'}
+            },
+            {type: "TweetsWidget",
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'}
+            },
+            {type: "createAnnotationWidget",
+             metadata:{
+              format:'cinelab',
+              src:'{{ json_url }}',
+              type:'json'}
+            }      
+            ]
+        },
+      player:{
+      type:'jwplayer', // player type
+              live: true, 
+              height: 300, 
+              width: {{ player_width }}, 
+              provider: "rtmp" 
+      },
+      modules: [
+               { type: "MediaFragment",
+                  metadata:{
+                 format:'cinelab',
+                 src:'{{ json_url }}',
+                 type:'json'}
+            }]
+
+    };
+    
+    IriSP.loadLibs(IriSP.lib, config, "{{ json_url }}",
+      function() {   
+              var layoutManager = new IriSP.LayoutManager(config.gui);
+              var pop = IriSP.configurePopcorn(layoutManager, config.player);
+              
+              var widgets = IriSP.configureWidgets(pop, layoutManager, config.gui); 
+              var modules = IriSP.configureModules(pop, config.modules); 
+      });    
 </script>
 </div>
 {% endspaceless %}
--- a/src/ldt/ldt/static/ldt/css/LdtPlayer.css	Thu Jan 12 10:13:00 2012 +0100
+++ b/src/ldt/ldt/static/ldt/css/LdtPlayer.css	Thu Jan 12 10:19:47 2012 +0100
@@ -1,165 +1,736 @@
-		#demo-frame > div.demo { padding: 5px !important; };
-		
-		button.ui-button-icon-only  {
-			height:1.5em;
-			width:1.5em;
-		}
-		
-		#Ldt-loader {
-			background:url(imgs/loader.gif) no-repeat;
-			width:20px;
-			height:16px;
-			float:left;
-		}
-		
-		#Ldt-controler {
-			font-size: 62.5%;
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-			background-color:#eeeeee;
-			height:35px;
-			padding:5px;
-		}
-		
-		.Ldt-iri-chapter{
-			padding-top:10px;
-			padding-bottom:5px;
-			border-left:solid 1px #000;
-			border-right:solid 1px #000;
-		}
-		
-		.tooltip {
-			display:none;
-			background:transparent url(imgs/white_arrow_mini.png);
-			font-size:12px;
-			height:55px;
-			width:180px;
-			padding:10px;
-			padding-left:15px;
-			padding-top:15px;
-			padding-right:15px;
-			color:#000;	
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-		}
-		#Ldt-Root{
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-		}
-		#Ldt-Hat{
-			height:3px;
-		}
-		#Ldt-Annotations{
-			padding-left:5px;
-			width:470px;
-			float:left;
-			font-size: 62.5%;
-		}
-		#Ldt-SaTitle{
-			padding-top:2px;
-			padding-bottom:5px;
-			font-size:18px;
-			height:22p;
-		}
-		#Ldt-SaDescription{
-			font-size:12px;	
-		}
-		#Ldt-Show-Arrow-container{
-			margin-left:60px;
-		}
-		#Ldt-Show-Arrow{
-			position:relative;
-			background:url(imgs/grey_arrow_Show.png);
-			width:27px;
-			height:13px;
-			margin-top:12px;
-			margin-left:-10px;
-		}
+#demo-frame > div.demo { padding: 5px !important; };
+
+button.ui-button-icon-only  {
+  height:1.5em;
+  width:1.5em;
+}
+
+#Ldt-loader {
+  background:url(imgs/loader.gif) no-repeat;
+  width:20px;
+  height:16px;
+  float:left;
+}
+
+/* general class for all buttons */
+.Ldt-button {
+
+}
+
+.Ldt-SegmentsWidget {
+ /* overflow: auto; /* clear the floats */
+  margin-top: 1px;
+  padding-bottom: 8px; /* FIXME: only a temporary fix. This should be put into the layout manager. */
+}
+
+.Ldt-iri-chapter {
+  position: absolute;
+  height: 10px;
+  border-right: 1px solid white;
+}
+
+.Ldt-SegmentPositionMarker {
+  position: absolute;
+  z-index: 100;
+  width: 1px;
+  height: 10px;
+  background-color: white;
+}
+.tooltip {
+  display:none;
+  background:transparent url(imgs/white_arrow_mini.png);
+  font-size:12px;
+  height:55px;
+  width:180px;
+  padding:10px;
+  padding-left:15px;
+  padding-top:15px;
+  padding-right:15px;
+  color:#000;
+  font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+}
+#Ldt-Root{
+  font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+}
+#Ldt-Hat{
+  height:3px;
+}
+
+.Ldt-AnnotationsWidget {
+  font-size: 12px;
+  font-family: "Arial",  "Verdana", "sans-serif";
+  background-color:#eeeeee;
+  background:url('imgs/wire_pattern.png') repeat scroll transparent ;
+  border: 1px solid #b6b8b8;
+}
+
+.Ldt-Annotation-DoubleBorder {
+  border: 1px solid white;
+  overflow: auto;
+}
+
+.Ldt-AnnotationContent {
+  padding:5px;
+  padding-left: 12px;
+
+}
+
+.Ldt-SaTitle{
+  padding-top:2px;
+  padding-bottom:3px;
+  font-size: 12pt;
+  color : #0068c4;
+}
+
+.Ldt-SaDescription{
+  font-size:12px;
+}
+
+.Ldt-SaKeyword{
+  background-color:#b9b9b9;
+  color:#4D4D4D;
+  padding:5px;
+  font-weight:bold;
+  text-align:left;
+  float:left;
+  font-size:10px;
+}
+
+.Ldt-AnnotationShareIcons {
+  float:right;
+  position: relative;
+}
+
+
+#Ldt-PlaceHolder{
+  position:absolue;
+  float:none;
+}
+
+.Ldt-Segments{
+  float:left;
+  font-size: 62.5%;
+}
+
+.Ldt-mode-radio{
+  visibility:hidden;
+  height:0px;
+  display:none
+}
+
+/* player */
+.Ldt-controler {
+  font-size: 62.5%;
+  font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+  background:url('imgs/player_gradient.png') repeat-x transparent ;
+  height: 25px;
+  border-top: 1px solid #b6b8b8;
+  border-bottom: 1px solid #b6b8b8;
+}
+
+
+.Ldt-LeftPlayerControls {
+  float:left;
+}
+
+.Ldt-RightPlayerControls {
+  float: right;
+}
+
+.Ldt-button {
+  border-left: 1px solid #b6b8b8;
+  float: left;
+  cursor: pointer;
+ 
+}
+
+.Ldt-CtrlPlay {
+  background:url('imgs/play_sprite.png') no-repeat transparent ;
+  background-position: 0 0;
+  width: 59px;
+  height: 25px;
+}
+
+.Ldt-CtrlPlay:hover {
+  background-position: 0 -25px;
+}
+
+.Ldt-CtrlPlay:active {
+  background-position: 0 -50px;
+}
+
+.Ldt-CtrlAnnotate {
+  background:url('imgs/annotate_sprite.png') no-repeat scroll 0 0 transparent ;
+  width: 33px;
+  height: 25px;
+  border-right: 1px solid #b6b8b8;
+  float: left;
+}
+
+.Ldt-CtrlAnnotate:hover {
+  background-position: 0 -25px;
+}
+
+.Ldt-CtrlAnnotate:active {
+  background-position: 0 -50px;
+}
+
+.Ldt-CtrlSearch {
+  background:url('imgs/search_sprite.png') no-repeat scroll 0 0 transparent ;
+  width: 33px;
+  height: 25px;
+  border-right: 1px solid #b6b8b8;
+  float: left;
+  border-left: none;
+}
+
+.Ldt-CtrlSearch:hover {
+  background-position: 0 -25px;
+}
+
+.Ldt-CtrlSearch:active {
+  background-position: 0 -50px;
+}
+
+.LdtSearch {
+  display: none;
+  width: 165px;
+  height: 25px;
+  border: 1px;
+  border-color: #CFCFCF;
+  float: left;
+  text-align: center;
+}
+
+.Ldt-Time {
+  position: inherit;
+  float: left;
+  border-right: 1px solid #b6b8b8;
+  height: 25px;
+  padding-right: 2px;
+  font-size: 12px;
+  font-family: Arial, Verdana, sans-serif;
+}
+
+.Ldt-ElapsedTime {
+  margin-top: 4px;
+  margin-right: 2px;
+  float: left;
+  color: #4a4a4a;
+}
+
+.Ldt-TimeSeparator {
+  margin-top: 4px;      
+  float: left;
+  padding-left: 1px;
+  padding-right: 1px;
+}
+
+.Ldt-TotalTime {
+  margin-top: 4px;
+  margin-left: 2px;
+  float: left;
+  color: #b2b2b2; 
+}
+
+.Ldt-CtrlSound {
+  background:url('imgs/sound_sprite.png') no-repeat scroll 0 0 transparent ;
+  width: 33px;
+  height: 25px;
+  border-right: 1px solid #b6b8b8;
+  float: right;
+  border-left: none;
+}
+
+.Ldt-CtrlSound:hover {
+  background-position: 0 -25px;
+}
+
+.Ldt-CtrlSound:active {
+  background-position: 0 -50px;
+}
+/*
+.Ldt-CtrlSound {
+  float: right;
+  border-left: none;
+  height: 25px;
+  top: 7px;
+  position: inherit;
+}
+*/    
+.Ldt-cleaner {
+  clear:both;
+}
+
+/* Arrow Widget */
+.Ldt-arrowWidget {
+  position: relative;
+  background:url('imgs/arrow.png') no-repeat scroll 0 0 transparent ;
+  height:16px;
+  width:27px;
+  margin-bottom: -3px;
+  z-index: 4;
+  left: 0%;
+}
+
+.cleaner {
+  clear:both;
+}
+
+.share {
+  background:url('imgs/widget20.png') no-repeat scroll 0 0 transparent ;
+  display:block;
+  height:16px;
+  line-height:16px !important;
+  overflow:hidden;
+  width:16px;
+  float:left;
+  cursor:pointer;
+  margin:2px;
+}
+.shareFacebook{
+  background-position:0 -704px;
+}
+.shareMySpace{
+  background-position:0 -736px;
+}
+.shareTwitter{
+  background-position:0 -1072px;
+}
+.shareGoogle{
+  background-position:0 -752px;
+}
+.shareDelicious{
+  background-position:0 -672px;
+}
+.shareJamesPot{
+  background-position:0 -1808px;
+}
+
+.tip{
+  position: absolute;
+  padding : 3px;
+  z-index: 10000000000;
+  max-width: 200px;
+  background: transparent url("imgs/white_arrow_long.png");
+  font-size: 12px;
+  height: 125px;
+  width: 180px;
+  padding: 10px;
+  padding-left: 15px;
+  padding-top: 15px;
+  padding-right: 15px;
+  color: black;
+  font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif";
+  overflow:hidden;
+}
+
+/* slider */
+.Ldt-SliderMinimized {
+  height: 6px;
+}
+
+.Ldt-SliderMaximized {
+  height: 11px;
+}
+
+.Ldt-sliderElementMinimized {
+  width: 100%;
+  height: 5px;
+}
+
+.Ldt-sliderElementMaximized {
+  width: 100%;
+  height: 10px;
+}
+
+.Ldt-sliderBackground  {
+  background-color: #B6B8B8;
+  position: absolute;
+  z-index: 2;
+  bottom: 1px;
+  width: 100%;
+  height: 5px;
+
+}
+
+.Ldt-sliderForeground  {
+  background-color: #747474;
+  z-index: 2;
+  width: 0px;
+  position: absolute;
+  bottom: 1px;
+  height: 5px;
+}
 
-		#Ldt-Show-Tags{
-			position:relative;
-			height:13px;
-			margin-top:-10px;
-			border: solid 1px #000;
-		}
-		#Ldt-ShowAnnotation-video{
-			position:absolute;
-			z-index: 999;
-			padding:5px;
-			background:url(imgs/transBlack.png);
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-			color:#FFF;	
-		}
-		#Ldt-ShowAnnotation-audio{
-			position:relative;
-			padding:5px;
-			background-color:#cfcfcf;
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-			color:#4D4D4D;	
-		}
-		#Ldt-SaKeyword{
-			background-color:#b9b9b9;
-			color:#4D4D4D;
-			padding:5px;
-			font-weight:bold;
-			text-align:left;
-			float:left;
-			font-size:10px;
-		}
-		#Ldt-SaShareTools{
-			text-align:right;
-			float:right;
-		}
-		
-		
-		#Ldt-PlaceHolder{
-			position:absolue;
-			float:none;
-		}
-		
-		.Ldt-mode-radio{
-			visibility:hidden;
-			height:0px;
-			display:none
-		}
-		
-		.Ldt-Control1{
-			width:60px;
-			float:left;
-		}
-		.Ldt-Control2{
-			padding-left:10px;
-			width:60px;
-			float:left;
-		}
-		.Ldt-cleaner {
-			clear:both;
-		} 
-		.share {
-			background:url('imgs/widget20.png') no-repeat scroll 0 0 transparent ;
-			display:block;
-			height:16px;
-			line-height:16px !important;
-			overflow:hidden;
-			width:16px;
-			float:left;
-			cursor:pointer;
-			margin:2px;
-		}
-		.shareFacebook{
-			background-position:0 -704px;
-		}
-		.shareMySpace{
-			background-position:0 -736px;
-		}
-		.shareTwitter{
-			background-position:0 -1072px;
-		}
-		.shareGoogle{
-			background-position:0 -752px;
-		}
-		.shareDelicious{
-			background-position:0 -672px;
-		}
-		.shareJamesPot{
-			background-position:0 -1808px;
-		}
-		
-		
\ No newline at end of file
+.Ldt-sliderPositionMarker {
+  position: absolute;
+  z-index: 100;
+  background-color: #f7268e;
+  height: 5px;
+  width: 5px;
+  bottom: 1px;
+  border-left: 1px solid white;
+  border-right: 1px solid white;
+}
+
+/* tweet Widget */
+.Ldt-tweetWidget {
+  font-size: 12px;
+  font-family: "Arial",  "Verdana", "sans-serif";
+  background:url('imgs/wire_pattern.png') repeat scroll transparent ;
+  border: 1px solid #b6b8b8;
+  border-top: none;
+  overflow: auto;
+}
+
+.Ldt-tweet-DoubleBorder {
+  border: 1px solid white;
+  padding: 5px;
+  overflow: auto;
+}
+
+.Ldt-tweetAvatar {
+  float: left;
+}
+
+.Ldt-tweetAvatar-profileArrow {
+  float: left;
+  height: 48px;
+  margin-left: 5px;
+  margin-right: 5px;
+}
+
+.Ldt-tweet_userHandle {
+   float: left;
+   color: #5c8df1;
+}
+
+.Ldt-tweet_realName {
+  float: left;
+  margin-left: 3px;
+}
+
+.Ldt-tweetContents {
+}
+
+.Ldt-tweet_date {
+  float: left;
+}
+
+.Ldt-tweetWidgetKeepOpen {
+  position: relative;
+  float: right;
+  height: 17px;
+  width: 17px;
+  margin-right: 1px;
+}
+
+.Ldt-tweetWidgetMinimize {
+  position: relative;
+  float: right;
+  height: 17px;
+  width: 17px;
+  right: 9px;
+}
+
+.Ldt-tweetWidget * a:link {
+  color: #729efa;
+
+}
+
+.Ldt-TweetReply {
+  float: left;
+  margin-left: 16px;
+}
+
+.Ldt-TweetReplyIcon {
+  background:url('imgs/reply_sprite.png') no-repeat scroll 0 0 transparent ;
+  width: 14px;
+  height: 11px;
+  float: left;
+  margin-top: 2px;
+}
+
+.Ldt-TweetReplyIcon:hover {
+  background-position: 0 -11px;
+}
+
+.Ldt-TweetReplyIcon:active {
+  background-position: 0 -22px;
+}
+
+.Ldt-Retweet {
+  float: left;
+  margin-left: 16px;
+}
+
+.Ldt-RetweetIcon {
+  background:url('imgs/retweet_sprite.png') no-repeat scroll 0 0 transparent ;
+  width: 14px;
+  height: 8px;
+  float: left;
+  margin-top: 3px;
+}
+
+.Ldt-RetweetIcon:hover {
+  background-position: 0 -8px;
+}
+
+.Ldt-RetweetIcon:active {
+  background-position: 0 -16px;
+}
+
+/* styling of a "++" in a tweet */
+.Ldt-PolemicPlusPlus {
+  background-color: #1d973d;
+}
+
+/* styling of a "==" in a tweet */
+.Ldt-PolemicEqualEqual {
+  background-color: #5c8df1
+}
+
+/* styling of a "--" in a tweet */
+.Ldt-PolemicMinusMinus {
+  background-color: #ce0a15;
+}
+
+/* styling of a "??" in a tweet */
+.Ldt-PolemicQuestion {
+  background-color: #c5a62d;
+}
+
+/* the styling of a spacer div */
+.Ldt-spacer {
+  background-color:#eeeeee;
+}
+
+/* sparkline widget */
+.Ldt-sparklineWidget {
+  position: relative;
+  margin-bottom: 5px;
+}
+
+.Ldt-sparkLinePositionMarker {
+  position: absolute;
+  top: 0px;
+  width: 0px;
+  background-color: #333333;
+  border-right: solid 1px pink;
+  z-index: 3;
+  opacity: 0.2;
+}
+
+.Ldt-sparkLine {
+  position: absolute;
+  top: 0px;
+}
+
+.Ldt-sparkLineClickOverlay {
+  position: absolute;
+  width: 640px;
+  height: 60px;
+  z-index: 4;
+  top: 0px;
+  opacity: 0.3;
+}
+
+.Ldt-sliceWidget {
+  position: relative;
+  width: 100%;
+  height: 25px;
+  margin-top: 3px;
+}
+
+.Ldt-sliceBackground {
+  width: 100%;
+  background-color: #b6b8b8;
+  height: 12px;
+}
+
+.Ldt-sliceZone {
+  position: absolute;
+  top: 0px;
+  background:url('imgs/wire_pattern.png') repeat scroll transparent;
+  height: 12px;
+  z-index: 2;
+}
+
+.Ldt-sliceLeftHandle {
+  position: absolute;
+  top: 0px;
+  height: 25px;
+  width: 7px;
+  background:url('imgs/left_handle.gif') no-repeat scroll transparent;
+  z-index: 2;
+}
+
+.Ldt-sliceRightHandle {
+  position: absolute;
+  top: 0px;
+  height: 25px;
+  width: 7px;
+  background:url('imgs/right_handle.gif') no-repeat scroll transparent;
+  z-index: 2;
+}
+
+.Ldt-createAnnotationWidget {
+  font-size: 12px;
+  font-family: "Arial",  "Verdana", "sans-serif";
+  background-color:#eeeeee;
+  background:url('imgs/wire_pattern.png') repeat scroll transparent ;
+  border: 1px solid #b6b8b8;  
+}
+
+.Ldt-createAnnotation-DoubleBorder {
+  border: 1px solid white;
+  overflow: auto;
+  padding: 7px;
+}
+
+.Ldt-createAnnotation-Title {
+  font-size: 12pt;
+  color : #0068c4;  
+  float: left;
+  margin-right: 5px;
+}
+
+.Ldt-createAnnotation-TimeFrame {
+  font-size: 12pt;
+  color : #ff5589;  
+  float: left;
+}
+
+.Ldt-createAnnotation-Container {  
+  display: table;
+  border-collapse: collapse;
+  width: 100%;
+}
+
+.Ldt-createAnnotation-userAvatar {  
+  width: 48px;
+  display: table-cell;
+  vertical-align: top;
+}
+
+.Ldt-createAnnotation-userAvatar img {  
+  display: block;
+  border: 1px solid #babcbc;
+}
+.Ldt-createAnnotation-profileArrow {
+  display: table-cell;
+  vertical-align: top;
+  height: 48px;
+  width: 15px;
+  padding-right: 5px;
+  padding-left: 3px;
+}
+
+.Ldt-createAnnotation-profileArrow img {
+  display: block;
+  margin-left: 4px;
+}
+
+.Ldt-createAnnotation-Description {
+  display: table-cell;   
+  width: 100%;
+  height: 48px;  
+  vertical-align: top;
+  -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+  -moz-box-sizing: border-box;    /* Firefox, other Gecko */
+  box-sizing: border-box;         /* Opera/IE 8+ */
+}
+
+.Ldt-createAnnotation-present-keyword {
+  border: 1px solid #ffffff;
+  background-color: #217bcb;
+  color: #ffffff;
+  padding: 3px;
+  padding-left: 4px;
+  padding-right: 4px;
+  cursor: pointer;
+}
+
+.Ldt-createAnnotation-absent-keyword {
+  border: 1px solid #ffffff;
+  background-color: #d93c71;
+  color: #ffffff;
+  padding: 3px;
+  padding-left: 4px;
+  padding-right: 4px;
+  cursor: pointer;
+}
+
+.Ldt-createAnnotation-submitButton {
+  float: right;
+  background-color: #d93c71;
+  color: #ffffff;
+  cursor: pointer;
+  background-image: url('imgs/submit_annotation.png');
+  background-repeat: no-repeat;
+  height: 48px;
+  width: 48px;
+}
+
+.Ldt-createAnnotation-endScreen {
+  background-color: #ffffff;
+  margin-left: 5px;
+  margin-right: 5px;
+  border: 1px solid #d6d6d6;
+  padding: 10px;
+  font-size: 13px;
+  font-weight: bold;
+  color : #f7268e;
+  text-align: center;
+}
+
+.Ldt-createAnnotation-errorMessage {
+  color: #D93C71;
+}
+
+/* AnnotationsListWidget */
+
+.Ldt-AnnotationsListWidget {
+  font-size: 12px;
+  font-family: "Arial",  "Verdana", "sans-serif";
+  border: 1px solid #b6b8b8;
+  overflow: auto;
+  max-height: 480px;
+}
+
+.Ldt-AnnotationsListWidget ul {
+  padding: 5px;
+}
+
+.Ldt-AnnotationsListWidget li {
+  list-style-type: none;
+  cursor: pointer;
+  display: table-row;
+  padding-top: 2px;
+  height: 64px;
+}
+
+.Ldt-AnnotationsListWidget li:hover {
+  background-color: #e9e9e9;
+}
+
+.Ldt-AnnotationsList-Caption {
+  float: left;
+  display: table-cell;
+  vertical-align: middle;  
+}
+
+.Ldt-AnnotationsList-Duration {  
+  color : #f7268e;  
+  float: right;
+  text-align: left;
+  width: 120px;
+}
+
+.Ldt-AnnotationsList-Title {
+  color: #0068c4;
+  font-size: 13px;
+  display: table-cell;
+  width: 80%;
+}
Binary file src/ldt/ldt/static/ldt/css/imgs/annotate_arrow.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/annotate_sprite.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/arrow.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/facebook_button.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/google.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/gplus_button.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/left_edge_arrow.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/left_handle.gif has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/loader_fc2.gif has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/minimize.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/mute_sprite.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/pause_sprite.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/play_sprite.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/player_gradient.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/profile_arrow.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/purple_arrow_Show.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/reply_sprite.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/retweet_sprite.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/right_edge_arrow.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/right_handle.gif has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/search_sprite.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/sound_sprite.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/submit_annotation.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/tweet_button.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/white_arrow_long.png has changed
Binary file src/ldt/ldt/static/ldt/css/imgs/wire_pattern.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/LdtPlayer-release.js	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,4446 @@
+/* 
+ * 	
+ *	Copyright 2010 Institut de recherche et d'innovation 
+ *	contributor(s) : Samuel Huron 
+ *	 
+ *	contact@iri.centrepompidou.fr
+ *	http://www.iri.centrepompidou.fr 
+ *	 
+ *	This software is a computer program whose purpose is to show and add annotations on a video .
+ *	This software is governed by the CeCILL-C license under French law and
+ *	abiding by the rules of distribution of free software. You can  use, 
+ *	modify and/ or redistribute the software under the terms of the CeCILL-C
+ *	license as circulated by CEA, CNRS and INRIA at the following URL
+ *	"http://www.cecill.info". 
+ *	
+ *	The fact that you are presently reading this means that you have had
+ *	knowledge of the CeCILL-C license and that you accept its terms.
+*/
+/*! LAB.js (LABjs :: Loading And Blocking JavaScript)
+    v2.0.3 (c) Kyle Simpson
+    MIT License
+*/
+
+(function(global){
+	var _$LAB = global.$LAB,
+	
+		// constants for the valid keys of the options object
+		_UseLocalXHR = "UseLocalXHR",
+		_AlwaysPreserveOrder = "AlwaysPreserveOrder",
+		_AllowDuplicates = "AllowDuplicates",
+		_CacheBust = "CacheBust",
+		/*!START_DEBUG*/_Debug = "Debug",/*!END_DEBUG*/
+		_BasePath = "BasePath",
+		
+		// stateless variables used across all $LAB instances
+		root_page = /^[^?#]*\//.exec(location.href)[0],
+		root_domain = /^\w+\:\/\/\/?[^\/]+/.exec(root_page)[0],
+		append_to = document.head || document.getElementsByTagName("head"),
+		
+		// inferences... ick, but still necessary
+		opera_or_gecko = (global.opera && Object.prototype.toString.call(global.opera) == "[object Opera]") || ("MozAppearance" in document.documentElement.style),
+
+/*!START_DEBUG*/
+		// console.log() and console.error() wrappers
+		log_msg = function(){}, 
+		log_error = log_msg,
+/*!END_DEBUG*/
+		
+		// feature sniffs (yay!)
+		test_script_elem = document.createElement("script"),
+		explicit_preloading = typeof test_script_elem.preload == "boolean", // http://wiki.whatwg.org/wiki/Script_Execution_Control#Proposal_1_.28Nicholas_Zakas.29
+		real_preloading = explicit_preloading || (test_script_elem.readyState && test_script_elem.readyState == "uninitialized"), // will a script preload with `src` set before DOM append?
+		script_ordered_async = !real_preloading && test_script_elem.async === true, // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
+		
+		// XHR preloading (same-domain) and cache-preloading (remote-domain) are the fallbacks (for some browsers)
+		xhr_or_cache_preloading = !real_preloading && !script_ordered_async && !opera_or_gecko
+	;
+
+/*!START_DEBUG*/
+	// define console wrapper functions if applicable
+	if (global.console && global.console.log) {
+		if (!global.console.error) global.console.error = global.console.log;
+		log_msg = function(msg) { global.console.log(msg); };
+		log_error = function(msg,err) { global.console.error(msg,err); };
+	}
+/*!END_DEBUG*/
+
+	// test for function
+	function is_func(func) { return Object.prototype.toString.call(func) == "[object Function]"; }
+
+	// test for array
+	function is_array(arr) { return Object.prototype.toString.call(arr) == "[object Array]"; }
+
+	// make script URL absolute/canonical
+	function canonical_uri(src,base_path) {
+		var absolute_regex = /^\w+\:\/\//;
+		
+		// is `src` is protocol-relative (begins with // or ///), prepend protocol
+		if (/^\/\/\/?/.test(src)) {
+			src = location.protocol + src;
+		}
+		// is `src` page-relative? (not an absolute URL, and not a domain-relative path, beginning with /)
+		else if (!absolute_regex.test(src) && src.charAt(0) != "/") {
+			// prepend `base_path`, if any
+			src = (base_path || "") + src;
+		}
+		// make sure to return `src` as absolute
+		return absolute_regex.test(src) ? src : ((src.charAt(0) == "/" ? root_domain : root_page) + src);
+	}
+
+	// merge `source` into `target`
+	function merge_objs(source,target) {
+		for (var k in source) { if (source.hasOwnProperty(k)) {
+			target[k] = source[k]; // TODO: does this need to be recursive for our purposes?
+		}}
+		return target;
+	}
+
+	// does the chain group have any ready-to-execute scripts?
+	function check_chain_group_scripts_ready(chain_group) {
+		var any_scripts_ready = false;
+		for (var i=0; i<chain_group.scripts.length; i++) {
+			if (chain_group.scripts[i].ready && chain_group.scripts[i].exec_trigger) {
+				any_scripts_ready = true;
+				chain_group.scripts[i].exec_trigger();
+				chain_group.scripts[i].exec_trigger = null;
+			}
+		}
+		return any_scripts_ready;
+	}
+
+	// creates a script load listener
+	function create_script_load_listener(elem,registry_item,flag,onload) {
+		elem.onload = elem.onreadystatechange = function() {
+			if ((elem.readyState && elem.readyState != "complete" && elem.readyState != "loaded") || registry_item[flag]) return;
+			elem.onload = elem.onreadystatechange = null;
+			onload();
+		};
+	}
+
+	// script executed handler
+	function script_executed(registry_item) {
+		registry_item.ready = registry_item.finished = true;
+		for (var i=0; i<registry_item.finished_listeners.length; i++) {
+			registry_item.finished_listeners[i]();
+		}
+		registry_item.ready_listeners = [];
+		registry_item.finished_listeners = [];
+	}
+
+	// make the request for a scriptha
+	function request_script(chain_opts,script_obj,registry_item,onload,preload_this_script) {
+		// setTimeout() "yielding" prevents some weird race/crash conditions in older browsers
+		setTimeout(function(){
+			var script, src = script_obj.real_src, xhr;
+			
+			// don't proceed until `append_to` is ready to append to
+			if ("item" in append_to) { // check if `append_to` ref is still a live node list
+				if (!append_to[0]) { // `append_to` node not yet ready
+					// try again in a little bit -- note: will re-call the anonymous function in the outer setTimeout, not the parent `request_script()`
+					setTimeout(arguments.callee,25);
+					return;
+				}
+				// reassign from live node list ref to pure node ref -- avoids nasty IE bug where changes to DOM invalidate live node lists
+				append_to = append_to[0];
+			}
+			script = document.createElement("script");
+			if (script_obj.type) script.type = script_obj.type;
+			if (script_obj.charset) script.charset = script_obj.charset;
+			
+			// should preloading be used for this script?
+			if (preload_this_script) {
+				// real script preloading?
+				if (real_preloading) {
+					/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload: "+src);/*!END_DEBUG*/
+					registry_item.elem = script;
+					if (explicit_preloading) { // explicit preloading (aka, Zakas' proposal)
+						script.preload = true;
+						script.onpreload = onload;
+					}
+					else {
+						script.onreadystatechange = function(){
+							if (script.readyState == "loaded") onload();
+						};
+					}
+					script.src = src;
+					// NOTE: no append to DOM yet, appending will happen when ready to execute
+				}
+				// same-domain and XHR allowed? use XHR preloading
+				else if (preload_this_script && src.indexOf(root_domain) == 0 && chain_opts[_UseLocalXHR]) {
+					xhr = new XMLHttpRequest(); // note: IE never uses XHR (it supports true preloading), so no more need for ActiveXObject fallback for IE <= 7
+					/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload (xhr): "+src);/*!END_DEBUG*/
+					xhr.onreadystatechange = function() {
+						if (xhr.readyState == 4) {
+							xhr.onreadystatechange = function(){}; // fix a memory leak in IE
+							registry_item.text = xhr.responseText + "\n//@ sourceURL=" + src; // http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/
+							onload();
+						}
+					};
+					xhr.open("GET",src);
+					xhr.send();
+				}
+				// as a last resort, use cache-preloading
+				else {
+					/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload (cache): "+src);/*!END_DEBUG*/
+					script.type = "text/cache-script";
+					create_script_load_listener(script,registry_item,"ready",function() {
+						append_to.removeChild(script);
+						onload();
+					});
+					script.src = src;
+					append_to.insertBefore(script,append_to.firstChild);
+				}
+			}
+			// use async=false for ordered async? parallel-load-serial-execute http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
+			else if (script_ordered_async) {
+				/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script load (ordered async): "+src);/*!END_DEBUG*/
+				script.async = false;
+				create_script_load_listener(script,registry_item,"finished",onload);
+				script.src = src;
+				append_to.insertBefore(script,append_to.firstChild);
+			}
+			// otherwise, just a normal script element
+			else {
+				/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script load: "+src);/*!END_DEBUG*/
+				create_script_load_listener(script,registry_item,"finished",onload);
+				script.src = src;
+				append_to.insertBefore(script,append_to.firstChild);
+			}
+		},0);
+	}
+		
+	// create a clean instance of $LAB
+	function create_sandbox() {
+		var global_defaults = {},
+			can_use_preloading = real_preloading || xhr_or_cache_preloading,
+			queue = [],
+			registry = {},
+			instanceAPI
+		;
+		
+		// global defaults
+		global_defaults[_UseLocalXHR] = true;
+		global_defaults[_AlwaysPreserveOrder] = false;
+		global_defaults[_AllowDuplicates] = false;
+		global_defaults[_CacheBust] = false;
+		/*!START_DEBUG*/global_defaults[_Debug] = false;/*!END_DEBUG*/
+		global_defaults[_BasePath] = "";
+
+		// execute a script that has been preloaded already
+		function execute_preloaded_script(chain_opts,script_obj,registry_item) {
+			var script;
+			
+			function preload_execute_finished() {
+				if (script != null) { // make sure this only ever fires once
+					script = null;
+					script_executed(registry_item);
+				}
+			}
+			
+			if (registry[script_obj.src].finished) return;
+			if (!chain_opts[_AllowDuplicates]) registry[script_obj.src].finished = true;
+			
+			script = registry_item.elem || document.createElement("script");
+			if (script_obj.type) script.type = script_obj.type;
+			if (script_obj.charset) script.charset = script_obj.charset;
+			create_script_load_listener(script,registry_item,"finished",preload_execute_finished);
+			
+			// script elem was real-preloaded
+			if (registry_item.elem) {
+				registry_item.elem = null;
+			}
+			// script was XHR preloaded
+			else if (registry_item.text) {
+				script.onload = script.onreadystatechange = null;	// script injection doesn't fire these events
+				script.text = registry_item.text;
+			}
+			// script was cache-preloaded
+			else {
+				script.src = script_obj.real_src;
+			}
+			append_to.insertBefore(script,append_to.firstChild);
+
+			// manually fire execution callback for injected scripts, since events don't fire
+			if (registry_item.text) {
+				preload_execute_finished();
+			}
+		}
+	
+		// process the script request setup
+		function do_script(chain_opts,script_obj,chain_group,preload_this_script) {
+			var registry_item,
+				registry_items,
+				ready_cb = function(){ script_obj.ready_cb(script_obj,function(){ execute_preloaded_script(chain_opts,script_obj,registry_item); }); },
+				finished_cb = function(){ script_obj.finished_cb(script_obj,chain_group); }
+			;
+			
+			script_obj.src = canonical_uri(script_obj.src,chain_opts[_BasePath]);
+			script_obj.real_src = script_obj.src + 
+				// append cache-bust param to URL?
+				(chain_opts[_CacheBust] ? ((/\?.*$/.test(script_obj.src) ? "&_" : "?_") + ~~(Math.random()*1E9) + "=") : "")
+			;
+			
+			if (!registry[script_obj.src]) registry[script_obj.src] = {items:[],finished:false};
+			registry_items = registry[script_obj.src].items;
+
+			// allowing duplicates, or is this the first recorded load of this script?
+			if (chain_opts[_AllowDuplicates] || registry_items.length == 0) {
+				registry_item = registry_items[registry_items.length] = {
+					ready:false,
+					finished:false,
+					ready_listeners:[ready_cb],
+					finished_listeners:[finished_cb]
+				};
+
+				request_script(chain_opts,script_obj,registry_item,
+					// which callback type to pass?
+					(
+					 	(preload_this_script) ? // depends on script-preloading
+						function(){
+							registry_item.ready = true;
+							for (var i=0; i<registry_item.ready_listeners.length; i++) {
+								registry_item.ready_listeners[i]();
+							}
+							registry_item.ready_listeners = [];
+						} :
+						function(){ script_executed(registry_item); }
+					),
+					// signal if script-preloading should be used or not
+					preload_this_script
+				);
+			}
+			else {
+				registry_item = registry_items[0];
+				if (registry_item.finished) {
+					finished_cb();
+				}
+				else {
+					registry_item.finished_listeners.push(finished_cb);
+				}
+			}
+		}
+
+		// creates a closure for each separate chain spawned from this $LAB instance, to keep state cleanly separated between chains
+		function create_chain() {
+			var chainedAPI,
+				chain_opts = merge_objs(global_defaults,{}),
+				chain = [],
+				exec_cursor = 0,
+				scripts_currently_loading = false,
+				group
+			;
+			
+			// called when a script has finished preloading
+			function chain_script_ready(script_obj,exec_trigger) {
+				/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("script preload finished: "+script_obj.real_src);/*!END_DEBUG*/
+				script_obj.ready = true;
+				script_obj.exec_trigger = exec_trigger;
+				advance_exec_cursor(); // will only check for 'ready' scripts to be executed
+			}
+
+			// called when a script has finished executing
+			function chain_script_executed(script_obj,chain_group) {
+				/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("script execution finished: "+script_obj.real_src);/*!END_DEBUG*/
+				script_obj.ready = script_obj.finished = true;
+				script_obj.exec_trigger = null;
+				// check if chain group is all finished
+				for (var i=0; i<chain_group.scripts.length; i++) {
+					if (!chain_group.scripts[i].finished) return;
+				}
+				// chain_group is all finished if we get this far
+				chain_group.finished = true;
+				advance_exec_cursor();
+			}
+
+			// main driver for executing each part of the chain
+			function advance_exec_cursor() {
+				while (exec_cursor < chain.length) {
+					if (is_func(chain[exec_cursor])) {
+						/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("$LAB.wait() executing: "+chain[exec_cursor]);/*!END_DEBUG*/
+						try { chain[exec_cursor++](); } catch (err) {
+							/*!START_DEBUG*/if (chain_opts[_Debug]) log_error("$LAB.wait() error caught: ",err);/*!END_DEBUG*/
+						}
+						continue;
+					}
+					else if (!chain[exec_cursor].finished) {
+						if (check_chain_group_scripts_ready(chain[exec_cursor])) continue;
+						break;
+					}
+					exec_cursor++;
+				}
+				// we've reached the end of the chain (so far)
+				if (exec_cursor == chain.length) {
+					scripts_currently_loading = false;
+					group = false;
+				}
+			}
+			
+			// setup next chain script group
+			function init_script_chain_group() {
+				if (!group || !group.scripts) {
+					chain.push(group = {scripts:[],finished:true});
+				}
+			}
+
+			// API for $LAB chains
+			chainedAPI = {
+				// start loading one or more scripts
+				script:function(){
+					for (var i=0; i<arguments.length; i++) {
+						(function(script_obj,script_list){
+							var splice_args;
+							
+							if (!is_array(script_obj)) {
+								script_list = [script_obj];
+							}
+							for (var j=0; j<script_list.length; j++) {
+								init_script_chain_group();
+								script_obj = script_list[j];
+								
+								if (is_func(script_obj)) script_obj = script_obj();
+								if (!script_obj) continue;
+								if (is_array(script_obj)) {
+									// set up an array of arguments to pass to splice()
+									splice_args = [].slice.call(script_obj); // first include the actual array elements we want to splice in
+									splice_args.unshift(j,1); // next, put the `index` and `howMany` parameters onto the beginning of the splice-arguments array
+									[].splice.apply(script_list,splice_args); // use the splice-arguments array as arguments for splice()
+									j--; // adjust `j` to account for the loop's subsequent `j++`, so that the next loop iteration uses the same `j` index value
+									continue;
+								}
+								if (typeof script_obj == "string") script_obj = {src:script_obj};
+								script_obj = merge_objs(script_obj,{
+									ready:false,
+									ready_cb:chain_script_ready,
+									finished:false,
+									finished_cb:chain_script_executed
+								});
+								group.finished = false;
+								group.scripts.push(script_obj);
+								
+								do_script(chain_opts,script_obj,group,(can_use_preloading && scripts_currently_loading));
+								scripts_currently_loading = true;
+								
+								if (chain_opts[_AlwaysPreserveOrder]) chainedAPI.wait();
+							}
+						})(arguments[i],arguments[i]);
+					}
+					return chainedAPI;
+				},
+				// force LABjs to pause in execution at this point in the chain, until the execution thus far finishes, before proceeding
+				wait:function(){
+					if (arguments.length > 0) {
+						for (var i=0; i<arguments.length; i++) {
+							chain.push(arguments[i]);
+						}
+						group = chain[chain.length-1];
+					}
+					else group = false;
+					
+					advance_exec_cursor();
+					
+					return chainedAPI;
+				}
+			};
+
+			// the first chain link API (includes `setOptions` only this first time)
+			return {
+				script:chainedAPI.script, 
+				wait:chainedAPI.wait, 
+				setOptions:function(opts){
+					merge_objs(opts,chain_opts);
+					return chainedAPI;
+				}
+			};
+		}
+
+		// API for each initial $LAB instance (before chaining starts)
+		instanceAPI = {
+			// main API functions
+			setGlobalDefaults:function(opts){
+				merge_objs(opts,global_defaults);
+				return instanceAPI;
+			},
+			setOptions:function(){
+				return create_chain().setOptions.apply(null,arguments);
+			},
+			script:function(){
+				return create_chain().script.apply(null,arguments);
+			},
+			wait:function(){
+				return create_chain().wait.apply(null,arguments);
+			},
+
+			// built-in queuing for $LAB `script()` and `wait()` calls
+			// useful for building up a chain programmatically across various script locations, and simulating
+			// execution of the chain
+			queueScript:function(){
+				queue[queue.length] = {type:"script", args:[].slice.call(arguments)};
+				return instanceAPI;
+			},
+			queueWait:function(){
+				queue[queue.length] = {type:"wait", args:[].slice.call(arguments)};
+				return instanceAPI;
+			},
+			runQueue:function(){
+				var $L = instanceAPI, len=queue.length, i=len, val;
+				for (;--i>=0;) {
+					val = queue.shift();
+					$L = $L[val.type].apply(null,val.args);
+				}
+				return $L;
+			},
+
+			// rollback `[global].$LAB` to what it was before this file was loaded, the return this current instance of $LAB
+			noConflict:function(){
+				global.$LAB = _$LAB;
+				return instanceAPI;
+			},
+
+			// create another clean instance of $LAB
+			sandbox:function(){
+				return create_sandbox();
+			}
+		};
+
+		return instanceAPI;
+	}
+
+	// create the main instance of $LAB
+	global.$LAB = create_sandbox();
+
+
+	/* The following "hack" was suggested by Andrea Giammarchi and adapted from: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
+	   NOTE: this hack only operates in FF and then only in versions where document.readyState is not present (FF < 3.6?).
+	   
+	   The hack essentially "patches" the **page** that LABjs is loaded onto so that it has a proper conforming document.readyState, so that if a script which does 
+	   proper and safe dom-ready detection is loaded onto a page, after dom-ready has passed, it will still be able to detect this state, by inspecting the now hacked 
+	   document.readyState property. The loaded script in question can then immediately trigger any queued code executions that were waiting for the DOM to be ready. 
+	   For instance, jQuery 1.4+ has been patched to take advantage of document.readyState, which is enabled by this hack. But 1.3.2 and before are **not** safe or 
+	   fixed by this hack, and should therefore **not** be lazy-loaded by script loader tools such as LABjs.
+	*/ 
+	(function(addEvent,domLoaded,handler){
+		if (document.readyState == null && document[addEvent]){
+			document.readyState = "loading";
+			document[addEvent](domLoaded,handler = function(){
+				document.removeEventListener(domLoaded,handler,false);
+				document.readyState = "complete";
+			},false);
+		}
+	})("addEventListener","DOMContentLoaded");
+
+})(this);/*
+  mustache.js — Logic-less templates in JavaScript
+
+  See http://mustache.github.com/ for more info.
+*/
+
+var Mustache = function () {
+  var _toString = Object.prototype.toString;
+
+  Array.isArray = Array.isArray || function (obj) {
+    return _toString.call(obj) == "[object Array]";
+  }
+
+  var _trim = String.prototype.trim, trim;
+
+  if (_trim) {
+    trim = function (text) {
+      return text == null ? "" : _trim.call(text);
+    }
+  } else {
+    var trimLeft, trimRight;
+
+    // IE doesn't match non-breaking spaces with \s.
+    if ((/\S/).test("\xA0")) {
+      trimLeft = /^[\s\xA0]+/;
+      trimRight = /[\s\xA0]+$/;
+    } else {
+      trimLeft = /^\s+/;
+      trimRight = /\s+$/;
+    }
+
+    trim = function (text) {
+      return text == null ? "" :
+        text.toString().replace(trimLeft, "").replace(trimRight, "");
+    }
+  }
+
+  var escapeMap = {
+    "&": "&amp;",
+    "<": "&lt;",
+    ">": "&gt;",
+    '"': '&quot;',
+    "'": '&#39;'
+  };
+
+  function escapeHTML(string) {
+    return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) {
+      return escapeMap[s] || s;
+    });
+  }
+
+  var regexCache = {};
+  var Renderer = function () {};
+
+  Renderer.prototype = {
+    otag: "{{",
+    ctag: "}}",
+    pragmas: {},
+    buffer: [],
+    pragmas_implemented: {
+      "IMPLICIT-ITERATOR": true
+    },
+    context: {},
+
+    render: function (template, context, partials, in_recursion) {
+      // reset buffer & set context
+      if (!in_recursion) {
+        this.context = context;
+        this.buffer = []; // TODO: make this non-lazy
+      }
+
+      // fail fast
+      if (!this.includes("", template)) {
+        if (in_recursion) {
+          return template;
+        } else {
+          this.send(template);
+          return;
+        }
+      }
+
+      // get the pragmas together
+      template = this.render_pragmas(template);
+
+      // render the template
+      var html = this.render_section(template, context, partials);
+
+      // render_section did not find any sections, we still need to render the tags
+      if (html === false) {
+        html = this.render_tags(template, context, partials, in_recursion);
+      }
+
+      if (in_recursion) {
+        return html;
+      } else {
+        this.sendLines(html);
+      }
+    },
+
+    /*
+      Sends parsed lines
+    */
+    send: function (line) {
+      if (line !== "") {
+        this.buffer.push(line);
+      }
+    },
+
+    sendLines: function (text) {
+      if (text) {
+        var lines = text.split("\n");
+        for (var i = 0; i < lines.length; i++) {
+          this.send(lines[i]);
+        }
+      }
+    },
+
+    /*
+      Looks for %PRAGMAS
+    */
+    render_pragmas: function (template) {
+      // no pragmas
+      if (!this.includes("%", template)) {
+        return template;
+      }
+
+      var that = this;
+      var regex = this.getCachedRegex("render_pragmas", function (otag, ctag) {
+        return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
+      });
+
+      return template.replace(regex, function (match, pragma, options) {
+        if (!that.pragmas_implemented[pragma]) {
+          throw({message:
+            "This implementation of mustache doesn't understand the '" +
+            pragma + "' pragma"});
+        }
+        that.pragmas[pragma] = {};
+        if (options) {
+          var opts = options.split("=");
+          that.pragmas[pragma][opts[0]] = opts[1];
+        }
+        return "";
+        // ignore unknown pragmas silently
+      });
+    },
+
+    /*
+      Tries to find a partial in the curent scope and render it
+    */
+    render_partial: function (name, context, partials) {
+      name = trim(name);
+      if (!partials || partials[name] === undefined) {
+        throw({message: "unknown_partial '" + name + "'"});
+      }
+      if (!context || typeof context[name] != "object") {
+        return this.render(partials[name], context, partials, true);
+      }
+      return this.render(partials[name], context[name], partials, true);
+    },
+
+    /*
+      Renders inverted (^) and normal (#) sections
+    */
+    render_section: function (template, context, partials) {
+      if (!this.includes("#", template) && !this.includes("^", template)) {
+        // did not render anything, there were no sections
+        return false;
+      }
+
+      var that = this;
+
+      var regex = this.getCachedRegex("render_section", function (otag, ctag) {
+        // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
+        return new RegExp(
+          "^([\\s\\S]*?)" +         // all the crap at the beginning that is not {{*}} ($1)
+
+          otag +                    // {{
+          "(\\^|\\#)\\s*(.+)\\s*" + //  #foo (# == $2, foo == $3)
+          ctag +                    // }}
+
+          "\n*([\\s\\S]*?)" +       // between the tag ($2). leading newlines are dropped
+
+          otag +                    // {{
+          "\\/\\s*\\3\\s*" +        //  /foo (backreference to the opening tag).
+          ctag +                    // }}
+
+          "\\s*([\\s\\S]*)$",       // everything else in the string ($4). leading whitespace is dropped.
+
+        "g");
+      });
+
+
+      // for each {{#foo}}{{/foo}} section do...
+      return template.replace(regex, function (match, before, type, name, content, after) {
+        // before contains only tags, no sections
+        var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",
+
+        // after may contain both sections and tags, so use full rendering function
+            renderedAfter = after ? that.render(after, context, partials, true) : "",
+
+        // will be computed below
+            renderedContent,
+
+            value = that.find(name, context);
+
+        if (type === "^") { // inverted section
+          if (!value || Array.isArray(value) && value.length === 0) {
+            // false or empty list, render it
+            renderedContent = that.render(content, context, partials, true);
+          } else {
+            renderedContent = "";
+          }
+        } else if (type === "#") { // normal section
+          if (Array.isArray(value)) { // Enumerable, Let's loop!
+            renderedContent = that.map(value, function (row) {
+              return that.render(content, that.create_context(row), partials, true);
+            }).join("");
+          } else if (that.is_object(value)) { // Object, Use it as subcontext!
+            renderedContent = that.render(content, that.create_context(value),
+              partials, true);
+          } else if (typeof value == "function") {
+            // higher order section
+            renderedContent = value.call(context, content, function (text) {
+              return that.render(text, context, partials, true);
+            });
+          } else if (value) { // boolean section
+            renderedContent = that.render(content, context, partials, true);
+          } else {
+            renderedContent = "";
+          }
+        }
+
+        return renderedBefore + renderedContent + renderedAfter;
+      });
+    },
+
+    /*
+      Replace {{foo}} and friends with values from our view
+    */
+    render_tags: function (template, context, partials, in_recursion) {
+      // tit for tat
+      var that = this;
+
+      var new_regex = function () {
+        return that.getCachedRegex("render_tags", function (otag, ctag) {
+          return new RegExp(otag + "(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?" + ctag + "+", "g");
+        });
+      };
+
+      var regex = new_regex();
+      var tag_replace_callback = function (match, operator, name) {
+        switch(operator) {
+        case "!": // ignore comments
+          return "";
+        case "=": // set new delimiters, rebuild the replace regexp
+          that.set_delimiters(name);
+          regex = new_regex();
+          return "";
+        case ">": // render partial
+          return that.render_partial(name, context, partials);
+        case "{": // the triple mustache is unescaped
+        case "&": // & operator is an alternative unescape method
+          return that.find(name, context);
+        default: // escape the value
+          return escapeHTML(that.find(name, context));
+        }
+      };
+      var lines = template.split("\n");
+      for(var i = 0; i < lines.length; i++) {
+        lines[i] = lines[i].replace(regex, tag_replace_callback, this);
+        if (!in_recursion) {
+          this.send(lines[i]);
+        }
+      }
+
+      if (in_recursion) {
+        return lines.join("\n");
+      }
+    },
+
+    set_delimiters: function (delimiters) {
+      var dels = delimiters.split(" ");
+      this.otag = this.escape_regex(dels[0]);
+      this.ctag = this.escape_regex(dels[1]);
+    },
+
+    escape_regex: function (text) {
+      // thank you Simon Willison
+      if (!arguments.callee.sRE) {
+        var specials = [
+          '/', '.', '*', '+', '?', '|',
+          '(', ')', '[', ']', '{', '}', '\\'
+        ];
+        arguments.callee.sRE = new RegExp(
+          '(\\' + specials.join('|\\') + ')', 'g'
+        );
+      }
+      return text.replace(arguments.callee.sRE, '\\$1');
+    },
+
+    /*
+      find `name` in current `context`. That is find me a value
+      from the view object
+    */
+    find: function (name, context) {
+      name = trim(name);
+
+      // Checks whether a value is thruthy or false or 0
+      function is_kinda_truthy(bool) {
+        return bool === false || bool === 0 || bool;
+      }
+
+      var value;
+
+      // check for dot notation eg. foo.bar
+      if (name.match(/([a-z_]+)\./ig)) {
+        var childValue = this.walk_context(name, context);
+        if (is_kinda_truthy(childValue)) {
+          value = childValue;
+        }
+      } else {
+        if (is_kinda_truthy(context[name])) {
+          value = context[name];
+        } else if (is_kinda_truthy(this.context[name])) {
+          value = this.context[name];
+        }
+      }
+
+      if (typeof value == "function") {
+        return value.apply(context);
+      }
+      if (value !== undefined) {
+        return value;
+      }
+      // silently ignore unkown variables
+      return "";
+    },
+
+    walk_context: function (name, context) {
+      var path = name.split('.');
+      // if the var doesn't exist in current context, check the top level context
+      var value_context = (context[path[0]] != undefined) ? context : this.context;
+      var value = value_context[path.shift()];
+      while (value != undefined && path.length > 0) {
+        value_context = value;
+        value = value[path.shift()];
+      }
+      // if the value is a function, call it, binding the correct context
+      if (typeof value == "function") {
+        return value.apply(value_context);
+      }
+      return value;
+    },
+
+    // Utility methods
+
+    /* includes tag */
+    includes: function (needle, haystack) {
+      return haystack.indexOf(this.otag + needle) != -1;
+    },
+
+    // by @langalex, support for arrays of strings
+    create_context: function (_context) {
+      if (this.is_object(_context)) {
+        return _context;
+      } else {
+        var iterator = ".";
+        if (this.pragmas["IMPLICIT-ITERATOR"]) {
+          iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
+        }
+        var ctx = {};
+        ctx[iterator] = _context;
+        return ctx;
+      }
+    },
+
+    is_object: function (a) {
+      return a && typeof a == "object";
+    },
+
+    /*
+      Why, why, why? Because IE. Cry, cry cry.
+    */
+    map: function (array, fn) {
+      if (typeof array.map == "function") {
+        return array.map(fn);
+      } else {
+        var r = [];
+        var l = array.length;
+        for(var i = 0; i < l; i++) {
+          r.push(fn(array[i]));
+        }
+        return r;
+      }
+    },
+
+    getCachedRegex: function (name, generator) {
+      var byOtag = regexCache[this.otag];
+      if (!byOtag) {
+        byOtag = regexCache[this.otag] = {};
+      }
+
+      var byCtag = byOtag[this.ctag];
+      if (!byCtag) {
+        byCtag = byOtag[this.ctag] = {};
+      }
+
+      var regex = byCtag[name];
+      if (!regex) {
+        regex = byCtag[name] = generator(this.otag, this.ctag);
+      }
+
+      return regex;
+    }
+  };
+
+  return({
+    name: "mustache.js",
+    version: "0.5.0-dev",
+
+    /*
+      Turns a template and view into HTML
+    */
+    to_html: function (template, view, partials, send_fun) {
+      var renderer = new Renderer();
+      if (send_fun) {
+        renderer.send = send_fun;
+      }
+      renderer.render(template, view || {}, partials);
+      if (!send_fun) {
+        return renderer.buffer.join("\n");
+      }
+    }
+  });
+}();
+// Underscore.js 1.2.3
+// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+(function(){function r(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
+c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&r(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(m.call(a,h)&&(f++,!(g=m.call(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(m.call(c,
+h)&&!f--)break;g=!f}}d.pop();return g}var s=this,F=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,G=k.concat,H=k.unshift,l=p.toString,m=p.hasOwnProperty,v=k.forEach,w=k.map,x=k.reduce,y=k.reduceRight,z=k.filter,A=k.every,B=k.some,q=k.indexOf,C=k.lastIndexOf,p=Array.isArray,I=Object.keys,t=Function.prototype.bind,b=function(a){return new n(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&&
+define.amd?define("underscore",function(){return b}):s._=b;b.VERSION="1.2.3";var j=b.each=b.forEach=function(a,c,b){if(a!=null)if(v&&a.forEach===v)a.forEach(c,b);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(b,a[e],e,a)===o)break}else for(e in a)if(m.call(a,e)&&c.call(b,a[e],e,a)===o)break};b.map=function(a,c,b){var e=[];if(a==null)return e;if(w&&a.map===w)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});return e};b.reduce=b.foldl=b.inject=function(a,
+c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(x&&a.reduce===x)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(y&&a.reduceRight===y)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,
+c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;D(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.filter===z)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(A&&a.every===A)return a.every(c,
+b);j(a,function(a,g,h){if(!(e=e&&c.call(b,a,g,h)))return o});return e};var D=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(B&&a.some===B)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return q&&a.indexOf===q?a.indexOf(c)!=-1:b=D(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(c.call?c||a:a[c]).apply(a,
+d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&(e={value:a,
+computed:b})});return e.value};b.shuffle=function(a){var c=[],b;j(a,function(a,f){f==0?c[0]=a:(b=Math.floor(Math.random()*(f+1)),c[f]=c[b],c[b]=a)});return c};b.sortBy=function(a,c,d){return b.pluck(b.map(a,function(a,b,g){return{value:a,criteria:c.call(d,a,b,g)}}).sort(function(a,c){var b=a.criteria,d=c.criteria;return b<d?-1:b>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=
+function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:a.toArray?a.toArray():b.isArray(a)?i.call(a):b.isArguments(a)?i.call(a):b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=b.head=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-
+1]};b.rest=b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,h){if(0==h||(c===true?b.last(d)!=g:!b.include(d,g)))d[d.length]=g,e[e.length]=a[h];return d},
+[]);return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,
+c,d){if(a==null)return-1;var e;if(d)return d=b.sortedIndex(a,c),a[d]===c?d:-1;if(q&&a.indexOf===q)return a.indexOf(c);for(d=0,e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(C&&a.lastIndexOf===C)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){arguments.length<=1&&(b=a||0,a=0);for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;)g[f++]=a,a+=d;return g};
+var E=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));E.prototype=a.prototype;var b=new E,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,
+c){var d={};c||(c=b.identity);return function(){var b=c.apply(this,arguments);return m.call(d,b)?d[b]:d[b]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i=b.debounce(function(){h=g=false},c);return function(){d=this;e=arguments;var b;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);i()},c));g?h=true:
+a.apply(d,e);i();g=true}};b.debounce=function(a,b){var d;return function(){var e=this,f=arguments;clearTimeout(d);d=setTimeout(function(){d=null;a.apply(e,f)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=G.apply([a],arguments);return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=
+function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=I||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)m.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){j(i.call(arguments,
+1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(m.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===
+Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!m.call(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)==
+"[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){s._=F;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")};b.mixin=function(a){j(b.functions(a),function(c){J(c,
+b[c]=a[c])})};var K=0;b.uniqueId=function(a){var b=K++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape,function(a,b){return"',_.escape("+b.replace(/\\'/g,"'")+"),'"}).replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g,
+"'")+",'"}).replace(d.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};var n=function(a){this._wrapped=a};b.prototype=n.prototype;var u=function(a,c){return c?b(a).chain():a},J=function(a,c){n.prototype[a]=function(){var a=i.call(arguments);H.call(a,this._wrapped);return u(c.apply(b,
+a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];n.prototype[a]=function(){b.apply(this._wrapped,arguments);return u(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];n.prototype[a]=function(){return u(b.apply(this._wrapped,arguments),this._chain)}});n.prototype.chain=function(){this._chain=true;return this};n.prototype.value=function(){return this._wrapped}}).call(this);
+/* main file */
+
+
+if ( window.IriSP === undefined && window.__IriSP === undefined ) { 
+  /**
+    @class
+    the object under which everything goes.        
+  */
+	IriSP = {}; 
+  
+  /** Alias to IriSP for backward compatibility */
+	__IriSP = IriSP;
+}
+
+IriSP.loadLibs = function( libs, config, metadata_url, callback ) {
+    // Localize jQuery variable
+		IriSP.jQuery = null;
+    var $L = $LAB.script(libs.jQuery).script(libs.swfObject).wait()
+                .script(libs.jQueryUI);
+                                   
+    if (config.player.type === "jwplayer") {
+      // load our popcorn.js lookalike
+      $L = $L.script(libs.jwplayer);
+    } else {
+      // load the real popcorn
+      $L = $L.script(libs.popcorn).script(libs["popcorn.code"]);
+      if (config.player.type === "youtube") {
+        $L = $L.script(libs["popcorn.youtube"]);
+      } 
+      if (config.player.type === "vimeo")
+        $L = $L.script(libs["popcorn.vimeo"]);
+      
+      /* do nothing for html5 */
+    }       
+    
+    /* widget specific requirements */
+    for (var idx in config.gui.widgets) {
+      if (config.gui.widgets[idx].type === "PolemicWidget") {        
+        $L.script(libs.raphael);
+      }
+
+      if (config.gui.widgets[idx].type === "SparklineWidget") {
+        $L.script(libs.jquery_sparkline);
+      }
+    }
+    
+    // same for modules
+    /*
+    for (var idx in config.modules) {
+      if (config.modules[idx].type === "PolemicWidget")
+        $L.script(libs.raphaelJs);
+    }
+    */
+
+    $L.wait(function() {
+      IriSP.jQuery = window.jQuery.noConflict( true );
+      IriSP._ = window._.noConflict();
+      IriSP.underscore = IriSP._;
+      
+      var css_link_jquery = IriSP.jQuery( "<link>", { 
+        rel: "stylesheet", 
+        type: "text/css", 
+        href: libs.cssjQueryUI,
+        'class': "dynamic_css"
+      } );
+      var css_link_custom = IriSP.jQuery( "<link>", { 
+        rel: "stylesheet", 
+        type: "text/css", 
+        href: config.gui.css,
+        'class': "dynamic_css"
+      } );
+      
+      css_link_jquery.appendTo('head');
+      css_link_custom.appendTo('head');
+          
+      IriSP.setupDataLoader();
+      IriSP.__dataloader.get(metadata_url, 
+          function(data) {
+            /* save the data so that we could re-use it to
+               configure the video
+            */
+            IriSP.__jsonMetadata = data;
+            callback.call(window) });
+    });
+};
+IriSP.SparklineWidget_template = "<div class='Ldt-sparklineWidget' style='width: {{width}}px; height: {{height}}px'>    <div class='Ldt-sparkLinePositionMarker' style='width: 0px; height: {{height}}px'></div>    <div class='Ldt-sparkLineClickOverlay' style='width: {{width}}px; height: {{height}}px'></div>    <div class='Ldt-sparkLine' style='width: {{width}}px; height: {{height}}px'>Loading</div></div>";
+IriSP.annotation_template = "{{! template for an annotation displayed in a segmentWidget }}<div title='{{divTitle}}' id='{{id}}'	class='Ldt-iri-chapter' 	style='left: {{startPixel}}px;          width: {{pxWidth}}px;          background-color:#{{hexa_color}};' 	></div>";
+IriSP.annotationWidget_template = "{{! template for the annotation widget }}<div class='Ldt-AnnotationsWidget'>  <!-- ugly div because we want to have a double border -->  <div class='Ldt-Annotation-DoubleBorder'>      <div class='Ldt-AnnotationContent'>        <div class='Ldt-AnnotationShareIcons'>         <a target='_blank' class='Ldt-fbShare' href=''><img src='{{img_dir}}/facebook.png' alt='share on facebook'></img></a>         <a target='_blank' class='Ldt-TwShare' href=''><img src='{{img_dir}}/twitter.png' alt='share on twitter'></img></a>         <a target='_blank'  class='Ldt-GplusShare' href=''><img src='{{img_dir}}/google.png' alt='share on google+'></img></a>      </div>		  <div class='Ldt-SaTitle'></div>	  	<div class='Ldt-SaDescription'></div>    </div>  </div></div>";
+IriSP.annotation_loading_template = "{{! template shown while the annotation widget is loading }}<div id='Ldt-load-container'><div id='Ldt-loader'>&nbsp;</div> Chargement... </div>";
+IriSP.annotationsListWidget_template = "{{! template for the annotation list widget }}<div class='Ldt-AnnotationsListWidget'>  <!-- ugly div because we want to have a double border -->  <div class='Ldt-Annotation-DoubleBorder'>    <ul>    {{#annotations}}      <li>        <a href='#a={{id}}'>          <div style='overflow: auto; margin-top: 5px; margin-bottom: 5px;'>            <div class='Ldt-AnnotationsList-Caption'>              <img src='http://i.imgur.com/aoUlC.jpg'></img>            </div>            <div class='Ldt-AnnotationsList-Duration'>{{begin}} - {{end}}</div>            <div class='Ldt-AnnotationsList-Title'>{{title}}</div>            <div class='Ldt-AnnotationsList-Description'>{{desc}}</div>          </div>        </a>      </li>    {{/annotations}}    </ul>  </div></div>";
+IriSP.arrowWidget_template = "<div class='Ldt-arrowWidget'></div>";
+IriSP.createAnnotationWidget_template = "{{! template for the annotation creation widget }}<div class='Ldt-createAnnotationWidget'>  <!-- ugly div because we want to have a double border -->  <div class='Ldt-createAnnotation-DoubleBorder'>    <div style='margin-bottom: 7px; overflow: auto;'>      <div class='Ldt-createAnnotation-Title'></div>      <div class='Ldt-createAnnotation-TimeFrame'></div>    </div>        <div class='Ldt-createAnnotation-Container'>      <textarea class='Ldt-createAnnotation-Description'></textarea>      <div class='Ldt-createAnnotation-profileArrow'>        <img src='{{img_dir}}/annotate_arrow.png'></img>      </div>      <div class='Ldt-createAnnotation-userAvatar'>                <img src='https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png'></img>      </div>    </div>        <div class='Ldt-createAnnotation-keywords'>      Add keywords :           </div>              <div class='Ldt-createAnnotation-submitButton'>      <div style='position: absolute; bottom: 10pt; right: 11pt;'>Submit</div>    </div>        <div class='Ldt-createAnnotation-endScreen' style='display: none'>      Thank you, your annotation has been saved.<br>      Would you like to share it on social networks ?      <div style='margin-top: 12px; text-align: center;'>          <a target='_blank' class='Ldt-createAnnotation-endScreen-TweetLink'><img src='{{img_dir}}/tweet_button.png' style='margin-right: 20px;'></img></a>          <a target='_blank' class='Ldt-createAnnotation-endScreen-FbLink'><img src='{{img_dir}}/facebook_button.png' style='margin-right: 20px;'></img></a>          <a target='_blank' class='Ldt-createAnnotation-endScreen-GplusLink'><img src='{{img_dir}}/gplus_button.png' style='margin-right: 20px;'></img></a>                          </div>    </div>  </div></div>";
+IriSP.createAnnotationWidget_festivalCinecast_template = "{{! template for the annotation creation widget specific for the cinecast festival}}<div class='Ldt-createAnnotationWidget'>  <!-- ugly div because we want to have a double border -->  <div class='Ldt-createAnnotation-DoubleBorder'>    <div style='margin-bottom: 7px; overflow: auto;'>      <div class='Ldt-createAnnotation-Title'></div>      <div class='Ldt-createAnnotation-TimeFrame'></div>    </div>        <div class='Ldt-createAnnotation-Container'>      <textarea class='Ldt-createAnnotation-Description'></textarea>      <div class='Ldt-createAnnotation-profileArrow'>        <img src='{{img_dir}}/annotate_arrow.png'></img>      </div>      <div class='Ldt-createAnnotation-userAvatar'>                <img src='https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png'></img>      </div>    </div>        <div class='Ldt-createAnnotation-keywords'>      Add keywords :           </div>              <div class='Ldt-createAnnotation-submitButton'>      <div style='position: absolute; bottom: 10pt; right: 11pt;'>Submit</div>    </div>        <div class='Ldt-createAnnotation-endScreen' style='display: none'>      Thank you, your annotation has been saved.<br>      Would you like to share it on social networks ?      <div style='margin-top: 12px; text-align: center;'>          <a target='_blank' class='Ldt-createAnnotation-endScreen-TweetLink'><img src='{{img_dir}}/tweet_button.png' style='margin-right: 20px;'></img></a>          <a target='_blank' class='Ldt-createAnnotation-endScreen-FbLink'><img src='{{img_dir}}/facebook_button.png' style='margin-right: 20px;'></img></a>          <a target='_blank' class='Ldt-createAnnotation-endScreen-GplusLink'><img src='{{img_dir}}/gplus_button.png' style='margin-right: 20px;'></img></a>                          </div>    </div>  </div></div>";
+IriSP.createAnnotation_errorMessage_template = "<p class='Ldt-createAnnotation-errorMessage'>  You must enter text to submit an annotation</p>";
+IriSP.overlay_marker_template = "{{! the template for the small bars which is z-indexed over our segment widget }}<div class='Ldt-SegmentPositionMarker' style='background-color: #F7268E;'></div>";
+IriSP.player_template = "{{! template for the radio player }}<div class='Ldt-controler demo'>	<div class='Ldt-LeftPlayerControls'>    <div class='Ldt-button Ldt-CtrlPlay' title='Play/Pause'></div>		<div class='Ldt-button Ldt-CtrlAnnotate' title='Annotate'></div>    <div class='Ldt-button Ldt-CtrlSearch' title='Search'></div>    <div class='LdtSearch'>      <input class='LdtSearchInput' style='margin-top: 2px; margin-bottom: 2px;'></input>    </div>    	</div>	<div class='Ldt-RightPlayerControls'>    <div class='Ldt-Time'>      <div class='Ldt-ElapsedTime' title='Elapsed time'>00:00</div>      <div class='Ldt-TimeSeparator'>/</div>      <div class='Ldt-TotalTime' title='Total time'>00:00</div>    </div>		<div class='Ldt-button Ldt-CtrlSound' title='Mute/Unmute'></div>	</div></div>";
+IriSP.search_template = "{{! template for the search container }}<div class='LdtSearchContainer'	style='margin-left: {{margin_left}}; position: absolute; margin-top: -60px;'>	<div class='LdtSearch'		style='display: none; background-color: #EEE; width: 165px; boder: 1px; border-color: #CFCFCF; position: absolute; text-align: center;'>		<input class='LdtSearchInput'			style='margin-top: 2px; margin-bottom: 2px;' />	</div></div><div class='cleaner'></div>";
+IriSP.share_template = "{{! social network sharing template }}<a onclick='__IriSP.MyApiPlayer.share(\'delicious\');' title='partager avec delicious'><span class='share shareDelicious'>&nbsp;</span></a>		<a onclick='__IriSP.MyApiPlayer.share(\'facebook\');' title='partager avec facebook'> <span class='share shareFacebook'>&nbsp;</span></a><a onclick='__IriSP.MyApiPlayer.share(\'twitter\');' title='partager avec twitter'>  <span class='share shareTwitter'>&nbsp;</span></a><a onclick='__IriSP.MyApiPlayer.share(\'myspace\');' title='partager avec Myspace'>  <span class='share shareMySpace'>&nbsp;</span></a>";
+IriSP.sliceWidget_template = "{{! template for the slice widget }}<div class='Ldt-sliceWidget'>  {{! the whole bar }}  <div class='Ldt-sliceBackground'></div>    <div class='Ldt-sliceLeftHandle'></div>  {{! the zone which represents our slice }}  <div class='Ldt-sliceZone'></div>     <div class='Ldt-sliceRightHandle'></div></div>";
+IriSP.sliderWidget_template = "{{! template for the slider widget - it's composed of two divs we one overlayed on top    of the other }}<div class='Ldt-sliderBackground'></div><div class='Ldt-sliderForeground'></div><div class='Ldt-sliderPositionMarker'></div>";
+IriSP.tooltip_template = "{{! template used by the jquery ui tooltip }}<div class='Ldt-tooltip'>  <div class='title'>{{title}}</div>  <div class='time'>{{begin}} : {{end}} </div>  <div class='description'>{{description}}</div></div>";
+IriSP.tooltipWidget_template = "{{! template for the tooltip widget }}<div class='tip'>	<div class='tipcolor' style='height:10px;width:10px'></div>	<div class='tiptext'></div>";
+IriSP.tweetWidget_template = "{{! template for the tweet widget }}<div class='Ldt-tweetWidget'>  <div class='Ldt-tweet-DoubleBorder'>      <img src='{{img_dir}}/minimize.png' class='Ldt-tweetWidgetKeepOpen' alt='dont minimize automatically'></img>      <img src='{{img_dir}}/minimize.png' class='Ldt-tweetWidgetMinimize' alt='minimize window'></img>      <div class='Ldt-tweetAvatar'></div>      <img src='{{img_dir}}/profile_arrow.png' class='Ldt-tweetAvatar-profileArrow'></img>      <div class='Ldt-tweetContents'></div>      <a href='' target='_blank' class='Ldt-Retweet'><div class='Ldt-RetweetIcon'></div> - Retweet </a>      <a href='' target='_blank' class='Ldt-TweetReply'><div class='Ldt-TweetReplyIcon'></div> - Reply</a>  </div></div>";/* wrapper that simulates popcorn.js because
+   popcorn is a bit unstable at the time */
+
+IriSP.PopcornReplacement = {
+  msgPump : {} /* used by jquery to receive and send messages */,
+  __delay_seek_signal : false
+};
+
+IriSP.PopcornReplacement.media = { 
+  "paused": true,
+  "muted": false
+};
+
+IriSP.PopcornReplacement.listen = function(msg, callback) {
+//  IriSP.jQuery(IriSP.PopcornReplacement.msgPump).bind(msg, function(event, rest) { callback(rest); });
+  if (!IriSP.PopcornReplacement.msgPump.hasOwnProperty(msg))
+    IriSP.PopcornReplacement.msgPump[msg] = [];
+
+  IriSP.PopcornReplacement.msgPump[msg].push(callback);
+};
+
+IriSP.PopcornReplacement.trigger = function(msg, params) {
+//  IriSP.jQuery(IriSP.PopcornReplacement.msgPump).trigger(msg, params);
+  
+  if (!IriSP.PopcornReplacement.msgPump.hasOwnProperty(msg))
+    return;
+
+  var d = IriSP.PopcornReplacement.msgPump[msg];
+
+  for(var i = 0; i < d.length; i++) {
+    d[i].call(window, params);
+  }
+
+};
+
+IriSP.PopcornReplacement.guid = function(prefix) {
+  var str = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
+      return v.toString(16);
+   });
+
+  return prefix + str;
+};
+
+IriSP.PopcornReplacement.__initApi = function() {
+  IriSP.PopcornReplacement.trigger("loadedmetadata"); // we've done more than loading metadata of course,
+                                                      // but popcorn doesn't need to know more.
+  IriSP.PopcornReplacement.media.muted = jwplayer(IriSP.PopcornReplacement._container).getMute();
+  
+  /* some programmed segments are supposed to be run at the beginning */
+  var i = 0;
+  for(i = 0; i < IriSP.PopcornReplacement.__codes.length; i++) {
+    var c = IriSP.PopcornReplacement.__codes[i];
+    if (0 == c.start) {
+      c.onStart();
+    }
+    
+    if (0 == c.end) {
+      c.onEnd();
+    }
+  }
+};
+
+IriSP.PopcornReplacement.jwplayer = function(container, options) {
+  IriSP.PopcornReplacement._container = container.slice(1); //eschew the '#'
+  options.events = {
+      onReady: IriSP.PopcornReplacement.__initApi,
+      onTime: IriSP.PopcornReplacement.__timeHandler,
+      onPlay: IriSP.PopcornReplacement.__playHandler,
+      onPause: IriSP.PopcornReplacement.__pauseHandler,
+      onSeek: IriSP.PopcornReplacement.__seekHandler 
+      }
+      
+  jwplayer(IriSP.PopcornReplacement._container).setup(options);
+  IriSP.PopcornReplacement.media.duration = options.duration;
+  return IriSP.PopcornReplacement;
+};
+
+IriSP.PopcornReplacement.currentTime = function(time) {
+  if (typeof(time) === "undefined") {        
+      return jwplayer(IriSP.PopcornReplacement._container).getPosition();            
+  } else {
+     var currentTime = +time;
+     jwplayer( IriSP.PopcornReplacement._container ).seek( currentTime );
+     IriSP.PopcornReplacement.__delay_seek_signal = true;     
+     //return jwplayer(IriSP.PopcornReplacement._container).getPosition();            
+     return currentTime;
+  }
+};
+
+IriSP.PopcornReplacement.play = function() {
+      IriSP.PopcornReplacement.media.paused = false;
+      IriSP.PopcornReplacement.trigger("play");
+//      IriSP.PopcornReplacement.trigger("playing");
+      jwplayer( IriSP.PopcornReplacement._container ).play();
+};
+    
+IriSP.PopcornReplacement.pause = function() {
+      if ( !IriSP.PopcornReplacement.media.paused ) {
+        IriSP.PopcornReplacement.media.paused = true;
+        IriSP.PopcornReplacement.trigger( "pause" );
+        jwplayer( IriSP.PopcornReplacement._container ).pause();
+      }
+};
+
+IriSP.PopcornReplacement.muted = function(val) {
+  if (typeof(val) !== "undefined") {
+
+    if (jwplayer(IriSP.PopcornReplacement._container).getMute() !== val) {
+      if (val) {
+        jwplayer(IriSP.PopcornReplacement._container).setMute(true);
+        IriSP.PopcornReplacement.media.muted = true;
+      } else {
+        jwplayer( IriSP.PopcornReplacement._container ).setMute(false);
+        IriSP.PopcornReplacement.media.muted = false;
+      }
+
+      IriSP.PopcornReplacement.trigger( "volumechange" );
+    }
+    
+    return jwplayer( IriSP.PopcornReplacement._container ).getMute();
+  } else {
+    return jwplayer( IriSP.PopcornReplacement._container ).getMute();
+  }
+};
+
+IriSP.PopcornReplacement.mute = IriSP.PopcornReplacement.muted;
+
+IriSP.PopcornReplacement.__codes = [];
+IriSP.PopcornReplacement.code = function(options) {
+  IriSP.PopcornReplacement.__codes.push(options);
+  return IriSP.PopcornReplacement;
+};
+
+/* called everytime the player updates itself 
+   (onTime event)
+ */
+
+IriSP.PopcornReplacement.__timeHandler = function(event) {
+  var pos = event.position;
+  
+  var i = 0;
+  for(i = 0; i < IriSP.PopcornReplacement.__codes.length; i++) {
+     var c = IriSP.PopcornReplacement.__codes[i];
+
+     if (pos >= c.start && pos < c.end && 
+         pos - 1 <= c.start) {       
+        c.onStart();
+     }
+ 
+     if (pos > c.start && pos > c.end && 
+         pos - 1 <= c.end) {
+         c.onEnd();
+     }
+   
+  }
+ 
+  IriSP.PopcornReplacement.trigger("timeupdate");
+};
+
+IriSP.PopcornReplacement.__seekHandler = function(event) {
+  var i = 0;
+  
+  for(i = 0; i < IriSP.PopcornReplacement.__codes.length; i++) {
+     var c = IriSP.PopcornReplacement.__codes[i];
+    
+     if (event.position >= c.start && event.position < c.end) {        
+        c.onEnd();
+     }         
+   }
+  
+   for(i = 0; i < IriSP.PopcornReplacement.__codes.length; i++) {
+     var c = IriSP.PopcornReplacement.__codes[i];
+
+     if (typeof(event.offset) === "undefined")
+       event.offset = 0;
+           
+     if (event.offset >= c.start && event.offset < c.end) { 
+       c.onStart();
+     }
+     
+   }
+
+  if (IriSP.PopcornReplacement.__delay_seek_signal === true) {
+    console.log(IriSP.PopcornReplacement.currentTime());
+    IriSP.PopcornReplacement.trigger("seeked");
+  }
+  IriSP.PopcornReplacement.trigger("timeupdate");
+};
+
+
+IriSP.PopcornReplacement.__playHandler = function(event) {
+  IriSP.PopcornReplacement.media.paused = false;
+  IriSP.PopcornReplacement.trigger("play");
+};
+
+IriSP.PopcornReplacement.__pauseHandler = function(event) {
+  IriSP.PopcornReplacement.media.paused = true;
+  IriSP.PopcornReplacement.trigger("pause");
+};
+
+IriSP.PopcornReplacement.roundTime = function() {
+  var currentTime = IriSP.PopcornReplacement.currentTime();
+  return Math.round(currentTime);
+};
+/* utils.js - various utils that don't belong anywhere else */
+
+/* trace function, for debugging */
+
+IriSP.traceNum = 0;
+IriSP.trace = function( msg, value ) {
+/*
+	if( IriSP.config.gui.debug === true ) {
+		IriSP.traceNum += 1;
+		IriSP.jQuery( "<div>"+IriSP.traceNum+" - "+msg+" : "+value+"</div>" ).appendTo( "#Ldt-output" );
+	}
+*/
+};
+
+/* used in callbacks - because in callbacks we lose "this",
+   we need to have a special function which wraps "this" in 
+   a closure. This way, the 
+*/   
+IriSP.wrap = function (obj, fn) {
+  return function() {    
+    var args = Array.prototype.slice.call(arguments, 0);
+    return fn.apply(obj, args);
+  }
+}
+
+/* convert a time to a percentage in the media */
+IriSP.timeToPourcent = function(time, timetotal){
+	var time = Math.abs(time);
+  var timetotal = Math.abs(timetotal);
+  
+	return Math.floor((time/timetotal) * 100);
+};
+
+IriSP.padWithZeros = function(num) {
+  if (Math.abs(num) < 10) {
+    return "0" + num.toString();
+  } else {
+    return num.toString();
+  }
+};
+
+/* convert a number of milliseconds to a tuple of the form 
+   [hours, minutes, seconds]
+*/
+IriSP.msToTime = function(ms) {
+  return IriSP.secondsToTime(ms / 1000);
+}
+/* convert a number of seconds to a tuple of the form 
+   [hours, minutes, seconds]
+*/
+IriSP.secondsToTime = function(secs) {  
+  var hours = Math.abs(parseInt( secs / 3600 ) % 24);
+  var minutes = Math.abs(parseInt( secs / 60 ) % 60);
+  var seconds = parseFloat(Math.abs(secs % 60).toFixed(0));
+  
+  var toString_fn = function() {
+    var ret = "";
+    if (hours > 0)
+       ret = IriSP.padWithZeros(this.hours) + ":";
+    ret += IriSP.padWithZeros(this.minutes) + ":" + IriSP.padWithZeros(this.seconds);
+
+    return ret;
+  }
+  return {"hours" : hours, "minutes" : minutes, "seconds" : seconds, toString: toString_fn};
+};
+
+/* format a tweet - replaces @name by a link to the profile, #hashtag, etc. */
+IriSP.formatTweet = function(tweet) {
+  /*
+    an array of arrays which hold a regexp and its replacement.
+  */
+  var regExps = [
+    /* copied from http://codegolf.stackexchange.com/questions/464/shortest-url-regex-match-in-javascript/480#480 */
+    [/((https?:\/\/)?[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?)/gi, "<a href='$1'>$1</a>"],
+    [/@(\w+)/gi, "<a href='http://twitter.com/$1'>@$1</a>"], // matches a @handle
+    [/#(\w+)/gi, "<a href='http://twitter.com/search?q=%23$1'>#$1</a>"],// matches a hashtag
+    [/(\+\+)/gi, "<span class='Ldt-PolemicPlusPlus'>$1</span>"],
+    [/(--)/gi, "<span class='Ldt-PolemicMinusMinus'>$1</span>"],
+    [/(==)/gi, "<span class='Ldt-PolemicEqualEqual'>$1</span>"],
+    [/(\?\?)/gi, "<span class='Ldt-PolemicQuestion'>$1</span>"]
+  ]; 
+
+  var i = 0;
+  for(i = 0; i < regExps.length; i++) {
+     tweet = tweet.replace(regExps[i][0], regExps[i][1]);
+  }
+  
+  return tweet;
+};
+
+IriSP.countProperties = function(obj) {
+    var count = 0;
+
+    for(var prop in obj) {
+        if(obj.hasOwnProperty(prop))
+                ++count;
+    }
+
+    return count;
+};
+
+// conversion de couleur Decimal vers HexaDecimal || 000 si fff
+IriSP.DEC_HEXA_COLOR = function (dec) {
+	 var hexa='0123456789ABCDEF';
+   var hex='';
+	 var tmp;
+	 while (dec>15){
+		  tmp = dec-(Math.floor(dec/16))*16;
+		  hex = hexa.charAt(tmp)+hex;
+		  dec = Math.floor(dec/16);
+	 }
+	 hex = hexa.charAt(dec)+hex;	 
+	 return(hex);
+};
+
+/* shortcut to have global variables in templates */
+IriSP.templToHTML = function(template, values) {
+  var params = IriSP.jQuery.extend(IriSP.default_templates_vars, values);
+  return Mustache.to_html(template, params);
+};
+
+/* we need to be stricter than encodeURIComponent,
+   because of twitter
+*/  
+IriSP.encodeURI = function(str) {
+  return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').  
+                                 replace(/\)/g, '%29').replace(/\*/g, '%2A');  
+}  
+
+IriSP.__guidCounter = 0;
+IriSP.guid = function(prefix) {
+  IriSP.__guidCounter += 1;
+  return prefix + IriSP.__guidCounter;
+};
+
+/** returns an url to share on facebook */
+IriSP.mkFbUrl = function(url) {
+  return "http://www.facebook.com/share.php?u=" + "I'm watching " + url;
+};
+
+/** returns an url to share on twitter */
+IriSP.mkTweetUrl = function(url) {
+  return "http://twitter.com/home?status=" + "I'm sharing " + url;
+};
+
+/** returns an url to share on google + */
+IriSP.mkGplusUrl = function(url) {
+  return "";
+};
+
+/* for ie compatibility
+if (Object.prototype.__defineGetter__&&!Object.defineProperty) {
+   Object.defineProperty=function(obj,prop,desc) {
+      if ("get" in desc) obj.__defineGetter__(prop,desc.get);
+      if ("set" in desc) obj.__defineSetter__(prop,desc.set);
+   }
+}
+*/
+/* data.js - this file deals with how the players gets and sends data */
+
+IriSP.DataLoader = function() {
+  this._cache = {};
+  
+  /*
+    A structure to hold callbacks for specific urls. We need it because
+    ajax calls are asynchronous, so it means that sometimes we ask
+    multiple times for a ressource because the first call hasn't been
+    received yet.
+  */
+  this._callbacks = {};
+};
+
+IriSP.DataLoader.prototype.get = function(url, callback) {
+
+  var base_url = url.split("&")[0]
+  if (this._cache.hasOwnProperty(base_url)) {
+    callback(this._cache[base_url]);
+  } else {  
+    if (!this._callbacks.hasOwnProperty(base_url)) {
+      this._callbacks[base_url] = [];
+      this._callbacks[base_url].push(callback);   
+      /* we need a closure because this gets lost when it's called back */
+  
+      // uncomment you don't want to use caching.
+      // IriSP.jQuery.get(url, callback);
+      
+      var func = function(data) {
+                  this._cache[base_url] = data;                                
+                  var i = 0;
+                  
+                  for (i = 0; i < this._callbacks[base_url].length; i++) {
+                    this._callbacks[base_url][i](this._cache[base_url]);                                  
+                  }
+      };
+      
+      /* automagically choose between json and jsonp */
+      if (url.indexOf(document.location.hostname) === -1 &&
+          url.indexOf("http://") !== -1 /* not a relative url */ ) {
+        // we contacting a foreign domain, use JSONP
+
+        IriSP.jQuery.get(url, {}, IriSP.wrap(this, func), "jsonp");
+      } else {
+
+        // otherwise, hey, whatever rows your boat
+        IriSP.jQuery.get(url, IriSP.wrap(this, func));
+      }
+    
+    } else {
+      /* simply push the callback - it'll get called when the ressource
+         has been received */
+      
+      this._callbacks[base_url].push(callback);   
+   
+    }
+  }
+}
+
+/* the base abstract "class" */
+IriSP.Serializer = function(DataLoader, url) {
+  this._DataLoader = DataLoader;
+  this._url = url;
+  this._data = [];
+};
+
+IriSP.Serializer.prototype.serialize = function(data) { };
+IriSP.Serializer.prototype.deserialize = function(data) {};
+
+IriSP.Serializer.prototype.currentMedia = function() {  
+};
+
+IriSP.Serializer.prototype.sync = function(callback) {  
+  callback.call(this, this._data);  
+};
+
+IriSP.SerializerFactory = function(DataLoader) {
+  this._dataloader = DataLoader;
+};
+
+IriSP.SerializerFactory.prototype.getSerializer = function(metadataOptions) {
+  /* This function returns serializer set-up with the correct
+     configuration - takes a metadata struct describing the metadata source
+  */
+  
+  if (metadataOptions === undefined)
+    /* return an empty serializer */
+    return IriSP.Serializer("", "");
+            
+  switch(metadataOptions.type) {
+    case "json":
+      return new IriSP.JSONSerializer(this._dataloader, metadataOptions.src);
+      break;
+    
+    case "dummy": /* only used for unit testing - not defined in production */
+      return new IriSP.MockSerializer(this._dataloader, metadataOptions.src);
+      break;
+    
+    case "empty":
+      return new IriSP.Serializer("", "empty");
+      break;
+      
+    default:      
+      return undefined;
+  }
+};
+/* site.js - all our site-dependent config : player chrome, cdn locations, etc...*/
+
+IriSP.libdir = "/mdp/src/js/libs/";
+IriSP.jwplayer_swf_path = "/mdp/test/libs/player.swf";
+
+IriSP.lib = { 
+		jQuery : "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js",
+		jQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.js",
+		jQueryToolTip : "http://cdn.jquerytools.org/1.2.4/all/jquery.tools.min.js",
+		swfObject : "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js",
+		cssjQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css",
+    popcorn : IriSP.libdir + "popcorn.js",
+    jwplayer : IriSP.libdir + "jwplayer.js",
+    popcornReplacement: IriSP.libdir + "pop.js",
+    raphael: IriSP.libdir + "raphael.js",
+    jquery_sparkline: IriSP.libdir + "jquery.sparkline.js",
+    "popcorn.mediafragment" : IriSP.libdir + "popcorn.mediafragment.js",
+    "popcorn.code" : IriSP.libdir + "popcorn.code.js",
+    "popcorn.jwplayer": IriSP.libdir + "popcorn.jwplayer.js",
+    "popcorn.youtube": IriSP.libdir + "popcorn.youtube.js"    
+};
+
+//Player Configuration 
+IriSP.config = undefined;
+
+IriSP.widgetsDefaults = {
+  "LayoutManager" : {spacer_div_height : "0px" },
+  "PlayerWidget" : {},
+  "AnnotationsWidget": {
+    "share_text" : "I'm watching ",     
+    "fb_link" : "http://www.facebook.com/share.php?u=",
+    "tw_link" : "http://twitter.com/home?status=",
+    "gplus_link" : ""
+    },
+  "TweetsWidget" : {
+      default_profile_picture : "https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png",
+      tweet_display_period: 10000 // how long do we show a tweet ?
+  },
+  "SliderWidget" : {
+      minimize_period: 850 // how long does the slider stays maximized after the user leaves the zone ?
+  },
+  "createAnnotationWidget" : {
+      keywords: ["#faux-raccord", "#mot-clef"],
+      cinecast_version: true /* put to false to enable the platform version, true for the festival cinecast one. */
+  },
+  "Main" : {
+      autoplay: true
+  }
+  
+};
+
+IriSP.platform_url = "http://localhost/pf";
+
+IriSP.paths = {
+//  "imgs": "/tweetlive/res/metadataplayer/src/css/imgs"
+  "imgs": "/mdp/src/css/imgs"
+};
+IriSP.default_templates_vars = {
+  "img_dir" : IriSP.paths.imgs 
+};
+
+/* ui.js - ui related functions */
+
+/* FIXME: use an sharing library */
+IriSP.LdtShareTool = IriSP.share_template; /* the contents come from share.html */
+
+IriSP.createPlayerChrome = function(){
+	var width = IriSP.config.gui.width;
+	var height = IriSP.config.gui.height;
+	var heightS = IriSP.config.gui.height-20;
+	
+	// AUDIO  */
+	// PB dans le html : ; 
+	IriSP.trace( "__IriSP.createMyHtml",IriSP.config.gui.container );
+
+	
+	/* FIXME : factor this in another file */
+	if( IriSP.config.gui.mode=="radio" ){
+
+		IriSP.jQuery( "#"+IriSP.config.gui.container ).before(IriSP.search_template);
+		var radioPlayer = Mustache.to_html(IriSP.radio_template, {"share_template" : IriSP.share_template});
+		IriSP.jQuery(radioPlayer).appendTo("#"+IriSP.config.gui.container);
+
+		// special tricks for IE 7
+		if (IriSP.jQuery.browser.msie==true && IriSP.jQuery.browser.version=="7.0"){
+			//LdtSearchContainer
+			//__IriSP.jQuery("#LdtPlayer").attr("margin-top","50px");
+			IriSP.jQuery("#Ldt-Root").css("padding-top","25px");
+			IriSP.trace("__IriSP.createHtml","IE7 SPECIAL ");
+		}
+	} else if(IriSP.config.gui.mode=="video") {
+	
+		var videoPlayer = Mustache.to_html(IriSP.video_template, {"share_template" : IriSP.share_template, "heightS" : heightS});
+		IriSP.jQuery(videoPlayer).appendTo("#"+IriSP.config.gui.container);
+	}
+	
+	IriSP.jQuery("#Ldt-Annotations").width(width-(75*2));
+	IriSP.jQuery("#Ldt-Show-Arrow-container").width(width-(75*2));
+	IriSP.jQuery("#Ldt-ShowAnnotation-audio").width(width-10);
+	IriSP.jQuery("#Ldt-ShowAnnotation-video").width(width-10);
+	IriSP.jQuery("#Ldt-SaKeyword").width(width-10);
+	IriSP.jQuery("#Ldt-controler").width(width-10);
+	IriSP.jQuery("#Ldt-Control").attr("z-index","100");
+	IriSP.jQuery("#Ldt-controler").hide();
+	
+	IriSP.jQuery(IriSP.annotation_loading_template).appendTo("#Ldt-ShowAnnotation-audio");
+
+	if(IriSP.config.gui.mode=='radio'){
+		IriSP.jQuery("#Ldt-load-container").attr("width",IriSP.config.gui.width);
+	}
+	// Show or not the output
+	if(IriSP.config.gui.debug===true){
+		IriSP.jQuery("#Ldt-output").show();
+	} else {
+		IriSP.jQuery("#Ldt-output").hide();
+	}
+	
+};
+
+
+/* create the buttons and the slider   */
+IriSP.createInterface = function( width, height, duration ) {
+		
+		IriSP.jQuery( "#Ldt-controler" ).show();
+		//__IriSP.jQuery("#Ldt-Root").css('display','visible');
+		IriSP.trace( "__IriSP.createInterface" , width+","+height+","+duration+"," );
+		
+		IriSP.jQuery( "#Ldt-ShowAnnotation").click( function () { 
+			 //__IriSP.jQuery(this).slideUp(); 
+		} );
+
+		var LdtpPlayerY = IriSP.jQuery("#Ldt-PlaceHolder").attr("top");
+		var LdtpPlayerX = IriSP.jQuery("#Ldt-PlaceHolder").attr("left");
+		
+		IriSP.jQuery( "#slider-range-min" ).slider( { //range: "min",
+			value: 0,
+			min: 1,
+			max: duration/1000,//1:54:52.66 = 3600+3240+
+			step: 0.1,
+			slide: function(event, ui) {
+				
+				//__IriSP.jQuery("#amount").val(ui.value+" s");
+				//player.sendEvent('SEEK', ui.value)
+				IriSP.MyApiPlayer.seek(ui.value);
+				//changePageUrlOffset(ui.value);
+				//player.sendEvent('PAUSE')
+			}
+		} );
+		
+		IriSP.trace("__IriSP.createInterface","ICI");
+		IriSP.jQuery("#amount").val(IriSP.jQuery("#slider-range-min").slider("value")+" s");
+		IriSP.jQuery(".Ldt-Control1 button:first").button({
+			icons: {
+				primary: 'ui-icon-play'
+			},
+			text: false
+		}).next().button({
+			icons: {
+				primary: 'ui-icon-seek-next'
+			},
+			 text: false
+		});
+		IriSP.jQuery(".Ldt-Control2 button:first").button({
+			icons: {
+				primary: 'ui-icon-search'//,
+				//secondary: 'ui-icon-volume-off'
+			},
+			text: false
+		}).next().button({
+			icons: {
+				primary: 'ui-icon-volume-on'
+			},
+			 text: false
+		});
+
+		// /!\ PB A MODIFIER 
+		//__IriSP.MyTags.draw();
+		IriSP.trace("__IriSP.createInterface","ICI2");
+		IriSP.jQuery( "#ldt-CtrlPlay" ).attr( "style", "background-color:#CD21C24;" );
+		
+		IriSP.jQuery( "#Ldt-load-container" ).hide();
+		
+		if( IriSP.config.gui.mode=="radio" & IriSP.jQuery.browser.msie != true ) {
+			IriSP.jQuery( "#Ldtplayer1" ).attr( "height", "0" );
+		}
+		IriSP.trace( "__IriSP.createInterface" , "3" );
+
+		IriSP.trace( "__IriSP.createInterface", "END" );
+		
+	};
+/* the widget classes and definitions */
+
+/**
+  * @class Widget is an "abstract" class. It's mostly used to define some properties common to every widget.
+  *
+  *  Note that widget constructors are never called directly by the user. Instead, the widgets are instantiated by functions
+  *  defined in init.js
+  *  
+  * @constructor
+  * @param Popcorn a reference to the popcorn Object
+  * @param config configuration options for the widget
+  * @param Serializer a serializer instance from which the widget reads data fromCharCode  
+*/
+IriSP.Widget = function(Popcorn, config, Serializer) {
+
+  if (config === undefined || config === null) {
+    config = {}
+  }
+  
+  this._Popcorn = Popcorn;
+  this._config = config;  
+  this._serializer = Serializer;
+  
+  if (config.hasOwnProperty("container")) {
+     this._id = config.container;
+     this.selector = IriSP.jQuery("#" + this._id);
+  }
+
+  if (config.hasOwnProperty("spacer")) {
+     this._spacerId = config.spacer;
+     this.spacer = IriSP.jQuery("#" + this._spacerId);
+  }
+
+
+  if (config.hasOwnProperty("width")) {
+     // this.width and not this._width because we consider it public.
+     this.width = config.width;     
+  }
+  
+  if (config.hasOwnProperty("height")) {    
+     this.height = config.height;     
+  }
+  
+  if (config.hasOwnProperty("heightmax")) {
+     this.heightmax = config.heightmax;     
+  }
+
+  if (config.hasOwnProperty("widthmax")) {
+     this.widthmax = config.widthmax;     
+  } 
+
+  if (config.hasOwnProperty("layoutManager")) {
+     this.layoutManager = config.layoutManager;     
+  }
+  
+};
+
+/**
+  * This method responsible of drawing a widget on screen.
+  */
+IriSP.Widget.prototype.draw = function() {
+  /* implemented by "sub-classes" */  
+};
+
+/**
+  * Optional method if you want your widget to support redraws.
+  */
+IriSP.Widget.prototype.redraw = function() {
+  /* implemented by "sub-classes" */  
+};
+/* modules are non-graphical entities, similar to widgets */
+
+IriSP.Module = function(Popcorn, config, Serializer) {
+
+  if (config === undefined || config === null) {
+    config = {}
+  }
+  
+  this._Popcorn = Popcorn;
+  this._config = config;  
+  this._serializer = Serializer;
+};
+/* layout.js - very basic layout management */
+
+/**
+  @class a layout manager manages a div and the layout of objects
+  inside it.
+*/
+IriSP.LayoutManager = function(options) {
+    this._Popcorn = null;
+    this._widgets = [];
+    
+    this._div = "LdtPlayer";
+    this._width = 640;
+    
+    if (options === undefined) {
+      options = {};
+    };
+    
+    if (options.hasOwnProperty('container')) {
+      this._div = options.container;
+    }
+
+    if (options.hasOwnProperty('width')) {
+      this._width = options.width;
+    }    
+    
+    if (options.hasOwnProperty('height')) {
+      this._height = options.height;
+    } 
+    
+    /* this is a shortcut */
+    this.selector = IriSP.jQuery("#" + this._div);
+    
+    this.selector.css("width", this._width);
+    
+    if (this._height !== undefined)
+      this.selector.css("height", this._height);
+};
+
+/** 
+   Set the popcorn instance used by the manager.
+   
+   we need this special setter because of a chicken and egg problem :
+   we want the manager to use popcorn but the popcorn div will be managed
+   by the manager. So we need a way to set the instance the manager uses
+*/
+   
+IriSP.LayoutManager.prototype.setPopcornInstance = function(popcorn) {
+    this._Popcorn = popcorn;
+}
+
+/** create a subdiv with an unique id, and a spacer div as well.
+    @param widgetName the name of the widget.
+    @return an array of the form [createdivId, spacerdivId].
+*/
+IriSP.LayoutManager.prototype.createDiv = function(widgetName) {
+    if (typeof(widgetName) === "undefined")
+       widgetName = "";
+
+    var newDiv = IriSP.guid(this._div + "_widget_" + widgetName + "_");
+    var spacerDiv = IriSP.guid("LdtPlayer_spacer_");
+    this._widgets.push([widgetName, newDiv]);    
+
+    var divTempl = "<div id='{{id}}' style='width: {{width}}px; position: relative;'></div";
+    var spacerTempl = "<div id='{{spacer_id}}' style='width: {{width}}px; position: relative; height: {{spacer_div_height}};'></div";
+    
+    var divCode = Mustache.to_html(divTempl, {id: newDiv, width: this._width});
+    var spacerCode = Mustache.to_html(spacerTempl, {spacer_id: spacerDiv, width: this._width,
+                                                    spacer_div_height: IriSP.widgetsDefaults.LayoutManager.spacer_div_height });
+
+    this.selector.append(divCode);
+    this.selector.append(spacerCode);
+
+    return [newDiv, spacerDiv];
+};/* init.js - initialization and configuration of Popcorn and the widgets
+exemple json configuration:
+ 
+ */
+
+/**
+    set up the IriSP.__dataloader instance - 
+    we need it because we have to get the metadata
+    about the video before that the widget have even
+    loaded.
+*/
+IriSP.setupDataLoader = function() {
+  /* we set it up separately because we need to
+     get data at the very beginning, for instance when
+     setting up the video */
+  IriSP.__dataloader = new IriSP.DataLoader();
+};
+
+/** do some magic to configure popcorn according to the options object passed.
+    Works for html5, jwplayer and youtube videos 
+*/
+IriSP.configurePopcorn = function (layoutManager, options) {
+    var pop;
+    var ret = layoutManager.createDiv(); 
+    var containerDiv = ret[0];
+    
+    switch(options.type) {
+      /*
+        todo : dynamically create the div/video tag which
+        will contain the video.
+      */
+      case "html5":
+           var tmpId = Popcorn.guid("video"); 
+           IriSP.jQuery("#" + containerDiv).append("<video src='" + options.file + "' id='" + tmpId + "'></video>");
+
+           if (options.hasOwnProperty("width"))
+             IriSP.jQuery("#" + containerDiv).css("width", options.width);
+           
+           if (options.hasOwnProperty("height"))
+             IriSP.jQuery("#" + containerDiv).css("height", options.height);
+
+           pop = Popcorn("#" + tmpId);
+        break;
+        
+      case "jwplayer":
+          var opts = IriSP.jQuery.extend({}, options);
+          delete opts.container;
+          delete opts.type;
+
+          if (options.provider === "rtmp") {
+            /* exit if we can't access the metadata */
+            if (typeof(IriSP.__jsonMetadata) === "undefined") {
+                break;
+            };
+
+
+            // the json format is totally illogical
+            opts.streamer = IriSP.__jsonMetadata["medias"][0]["meta"]["item"]["value"];
+            var source = IriSP.__jsonMetadata["medias"][0]["href"];
+            
+            // the source if a full url but jwplayer wants an url relative to the
+            // streamer url, so we've got to remove the common part.
+            opts.file = source.slice(opts.streamer.length);
+            console.log(opts.streamer, opts.file);
+            
+            // HACK - do not commit
+            opts.streamer = "rtmp://media.iri.centrepompidou.fr/ddc_player/";
+            opts.file = "video/ldtplatform/museologie_inaugurale_20111018_flat.f4v";
+            
+            /*opts.streamer = "rtmp://media.iri.centrepompidou.fr/ddc_player/video/ldtplatform/";
+            opts.file = "laurentcantet_entrelesmurs.flv";
+            */
+            console.log(opts.streamer, opts.file);
+          } else {
+            /* other providers type, video for instance -
+               pass everything as is */
+          }
+
+          if (!options.hasOwnProperty("flashplayer")) {
+            opts.flashplayer = IriSP.jwplayer_swf_path;
+          }
+
+          if (!options.hasOwnProperty("controlbar.position")) {
+            opts["controlbar.position"] = "none";
+          }
+
+          pop = IriSP.PopcornReplacement.jwplayer("#" + containerDiv, opts);
+        break;
+      
+      case "youtube":
+          var opts = IriSP.jQuery.extend({}, options);
+          delete opts.container;
+          opts.controls = 0;
+          opts.autostart = false;
+          templ = "width: {{width}}px; height: {{height}}px;";
+          var str = Mustache.to_html(templ, {width: opts.width, height: opts.height});    
+          // Popcorn.youtube wants us to specify the size of the player in the style attribute of its container div.
+          IriSP.jQuery("#" + containerDiv).attr("style", str);
+          
+          pop = Popcorn.youtube("#" + containerDiv, opts.video, opts);
+        break;
+        
+      default:
+        pop = undefined;
+    };
+    
+    return pop;
+};
+
+/** Configure the gui and instantiate the widgets passed as parameters
+    @param guiOptions the gui object as seen in the examples.
+ */
+IriSP.configureWidgets = function (popcornInstance, layoutManager, guiOptions) {
+ 
+  var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader);
+  var params = {width: guiOptions.width, height: guiOptions.height};
+
+  var ret_widgets = [];
+  var index;
+  
+  for (index = 0; index < guiOptions.widgets.length; index++) {    
+    var widgetConfig = guiOptions.widgets[index];
+    var widget = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, widgetConfig);
+    ret_widgets.push(widget);
+   
+  };
+
+  return ret_widgets;
+};
+
+/** configure modules. @see configureWidgets */
+IriSP.configureModules = function (popcornInstance, modulesList) {
+ 
+  var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader);
+  var ret_modules = [];
+  var index;
+  
+  for (index = 0; index < modulesList.length; index++) {    
+    var moduleConfig = modulesList[index];
+    
+    var serializer = serialFactory.getSerializer(moduleConfig.metadata);
+    var module = new IriSP[moduleConfig.type](popcornInstance, moduleConfig, serializer);    
+    ret_modules.push(module);
+  };
+
+  return ret_modules;
+};
+
+/** instantiate a widget - only called by configureWidgets, never by the user. Handles widget 
+    dependencies.
+    @param popcornInstance popcorn instance the widget will user
+    @param serialFactory serializer factory to instantiate the widget with
+    @param layoutManager layout manager
+    @param widgetConfig configuration options for the widget
+ */
+IriSP.instantiateWidget = function(popcornInstance, serialFactory, layoutManager, widgetConfig) {
+
+    var arr = IriSP.jQuery.extend({}, widgetConfig);
+    
+    /* create a div for those widgets who didn't already specify a container; */
+    if (!arr.hasOwnProperty("container")) {
+      /* create div returns us a container for the widget and a spacer */    
+      var ret = layoutManager.createDiv(widgetConfig.type);        
+      var container = ret[0];
+      var spacer = ret[1];           
+      arr.container = container;
+      arr.spacer = spacer;
+      arr.layoutManager = layoutManager;
+    }
+    var serializer = serialFactory.getSerializer(widgetConfig.metadata);    
+    
+    if (typeof serializer == "undefined")   
+      debugger;
+    
+    // instantiate the object passed as a string
+    var widget = new IriSP[widgetConfig.type](popcornInstance, arr, serializer);    
+    
+    if (widgetConfig.hasOwnProperty("requires")) {
+      // also create the widgets this one depends on.
+      // the dependency widget is available in the parent widget context as
+      // this.WidgetName (for instance, this.TipWidget);
+      
+      var i = 0;
+      for(i = 0; i < widgetConfig.requires.length; i++) {
+        var widgetName = widgetConfig.requires[i]["type"];
+        widget[widgetName] = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, widgetConfig.requires[i]);
+      }
+    }       
+     
+    serializer.sync(IriSP.wrap(widget, function() { this.draw(); }));
+    return widget;
+};
+/* mediafragment module */
+
+IriSP.MediaFragment = function(Popcorn, config, Serializer) {
+  IriSP.Module.call(this, Popcorn, config, Serializer);
+
+  this.mutex = false; /* a mutex because we access the url from two different functions */
+
+  this._Popcorn.listen( "loadedmetadata", IriSP.wrap(this,this.advanceTime));
+  this._Popcorn.listen( "pause", IriSP.wrap(this,this.updateTime));
+  this._Popcorn.listen( "seeked", IriSP.wrap(this,this.updateTime));
+  this._Popcorn.listen( "IriSP.PolemicTweet.click", IriSP.wrap(this,this.updateAnnotation));
+  this._Popcorn.listen( "IriSP.SegmentsWidget.click", IriSP.wrap(this,this.updateAnnotation));
+  
+  window.onhashchange = IriSP.wrap(this, this.advanceTime);
+};
+
+IriSP.MediaFragment.prototype = new IriSP.Module();
+
+IriSP.MediaFragment.prototype.advanceTime = function() {
+             var url = window.location.href;
+
+              if ( url.split( "#" )[ 1 ] != null ) {
+                  pageoffset = url.split( "#" )[1];
+
+                  if ( pageoffset.substring(0, 2) === "t=") {
+                    // timecode 
+                    if ( pageoffset.substring( 2 ) != null ) {
+                    var offsettime = pageoffset.substring( 2 );
+                    this._Popcorn.currentTime( parseFloat( offsettime ) );
+                    }
+                  } else if ( pageoffset.substring(0, 2) === "a=") {
+                    // annotation
+                    var annotationId = pageoffset.substring( 2 );
+
+                    // there's no better way than that because
+                    // of possible race conditions
+                    this._serializer.sync(IriSP.wrap(this, function() {
+                          this.lookupAnnotation.call(this, annotationId); 
+                          }));
+                  }
+              }
+};
+
+IriSP.MediaFragment.prototype.updateTime = function() {
+  if (this.mutex === true) {
+    return;
+  }
+
+  var history = window.history;
+  if ( !history.pushState ) {
+    return false;
+  }
+  
+  splitArr = window.location.href.split( "#" )
+  history.replaceState( {}, "", splitArr[0] + "#t=" + this._Popcorn.currentTime().toFixed( 2 ) );
+};
+
+
+IriSP.MediaFragment.prototype.updateAnnotation = function(annotationId) {
+  var _this = this;
+  this.mutex = true;
+
+  var history = window.history;
+  if ( !history.pushState ) {
+    return false;
+  }
+  
+  splitArr = window.location.href.split( "#" )
+  history.replaceState( {}, "", splitArr[0] + "#a=" + annotationId);
+ 
+  window.setTimeout(function() { _this.mutex = false }, 50);
+};
+
+// lookup and seek to the beginning of an annotation
+IriSP.MediaFragment.prototype.lookupAnnotation = function(annotationId) {
+  var _this = this;
+  this.mutex = true;
+
+  var annotation = undefined;
+  var annotations = this._serializer._data.annotations;
+
+  var i;
+  for (i = 0; i < annotations.length; i++) {
+      if (annotations[i].id === annotationId) {
+        annotation = annotations[i];
+        break;
+      }
+  }
+
+  if (typeof(annotation) !== "undefined") {
+    this._Popcorn.currentTime(annotation.begin / 1000);
+  }
+  
+  window.setTimeout(function() { _this.mutex = false }, 50);
+};
+IriSP.AnnotationsListWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+  this.__counter = 0;
+  this.__oldList = [];
+};
+
+
+IriSP.AnnotationsListWidget.prototype = new IriSP.Widget();
+
+IriSP.AnnotationsListWidget.prototype.clear = function() {
+};
+
+IriSP.AnnotationsListWidget.prototype.clearWidget = function() {
+};
+
+/** draw the annotation list */
+IriSP.AnnotationsListWidget.prototype.drawList = function(force_redraw) {
+  var _this = this;
+
+  var view_type = this._serializer.getContributions();
+  var annotations = this._serializer._data.annotations;
+  var currentTime = this._Popcorn.currentTime();
+    
+  var list = [];
+
+  if (typeof(view_type) === "undefined") {
+    console.log("no type suitable for display");
+    return;
+  }
+
+  for (i = 0; i < annotations.length; i++) {
+    var annotation = annotations[i];
+
+    /* filter the annotations whose type is not the one we want */
+    if (typeof(annotation.meta) !== "undefined" && typeof(annotation.meta["id-ref"]) !== "undefined"
+          && annotation.meta["id-ref"] != view_type) {
+        continue;
+    }
+
+    /* only get the annotations happening in the current chapter */
+    if (!(annotation.begin <= currentTime * 1000 && annotation.end > currentTime * 1000)) {        
+        continue;
+    }
+
+    var a = annotation;
+    var obj = {};
+
+    obj["id"] = a.id;
+    obj["title"] = a.content.title;
+    obj["desc"] = a.content.description;
+    obj["begin"] = IriSP.msToTime(annotation.begin);
+    obj["end"] = IriSP.msToTime(annotation.end);
+
+    list.push(obj);
+  }
+  
+  var idList = IriSP.underscore.pluck(list, "id").sort();
+  
+  if (idList.length !== this.__oldList.length) {
+    var widgetMarkup = IriSP.templToHTML(IriSP.annotationsListWidget_template, {annotations: list});
+    this.selector.html(widgetMarkup);
+  }
+    
+  var res = 1;
+  for (var i = 0; i < idList.length; i++) {
+    if (idList[i] !== this.__oldList[i])
+      res = 0;
+      break;
+  }
+  
+  this.__oldList = idList; /* save for next call */
+
+  if (typeof(force_redraw) !== "undefined") {
+    console.log("forced redraw");
+    var widgetMarkup = IriSP.templToHTML(IriSP.annotationsListWidget_template, {annotations: list});
+    this.selector.html(widgetMarkup);
+  }
+  
+  /* the two lists are equal, no need to redraw */
+  if (res === 1) {
+    return;
+  } else {
+    var widgetMarkup = IriSP.templToHTML(IriSP.annotationsListWidget_template, {annotations: list});
+    this.selector.html(widgetMarkup);
+  }
+  
+};
+
+IriSP.AnnotationsListWidget.prototype.draw = function() {
+
+  this.drawList();
+  this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation", IriSP.wrap(this, function() { this.redraw(true); }));
+  this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.redraw));
+};
+
+IriSP.AnnotationsListWidget.prototype.redraw = function() {
+  this.drawList();
+};IriSP.AnnotationsWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+  /* flag used when we're creating an annotation */
+  this._hidden = false;
+};
+
+
+IriSP.AnnotationsWidget.prototype = new IriSP.Widget();
+
+IriSP.AnnotationsWidget.prototype.clear = function() {
+    this.selector.find(".Ldt-SaTitle").text("");
+    this.selector.find(".Ldt-SaDescription").text("");
+    this.selector.find(".Ldt-SaKeywordText").text("");
+};
+
+IriSP.AnnotationsWidget.prototype.displayAnnotation = function(annotation) {       
+    var title = annotation.content.title;
+    var description = annotation.content.description;
+    var keywords =  "" // FIXME;
+    var begin = +annotation.begin / 1000;
+    var end = +annotation.end / 1000;
+    var duration = +this._serializer.currentMedia().meta["dc:duration"];
+    
+    var title_templ = "{{title}} - ( {{begin}} - {{end}} )";
+    var endstr = Mustache.to_html(title_templ, {title: title, begin: IriSP.secondsToTime(begin), end: IriSP.secondsToTime(end)});
+
+    this.selector.find(".Ldt-SaTitle").text(endstr);
+    this.selector.find(".Ldt-SaDescription").text(description);
+    
+    // update sharing buttons
+    var defaults = IriSP.widgetsDefaults.AnnotationsWidget;
+    var text = defaults.share_text;
+    var fb_link = defaults.fb_link;
+    var tw_link = defaults.tw_link;
+    var gplus_link = defaults.gplus_link;
+    var url = document.location.href + "#a=" + annotation.id;
+    this.selector.find(".Ldt-fbShare").attr("href", fb_link + IriSP.encodeURI(text) + IriSP.encodeURI(url));
+    this.selector.find(".Ldt-TwShare").attr("href", tw_link + IriSP.encodeURI(text) + IriSP.encodeURI(url));
+    this.selector.find(".Ldt-GplusShare").attr("href", fb_link + IriSP.encodeURI(text) + IriSP.encodeURI(url));
+};
+
+IriSP.AnnotationsWidget.prototype.clearWidget = function() {   
+    /* retract the pane between two annotations */
+    this.selector.find(".Ldt-SaTitle").text("");
+    this.selector.find(".Ldt-SaDescription").text("");
+    this.selector.find(".Ldt-SaKeywordText").html("");
+    this.selector.find(".Ldt-ShowAnnotation").slideUp();
+};
+
+IriSP.AnnotationsWidget.prototype.draw = function() {
+  var _this = this;
+
+  var annotationMarkup = IriSP.templToHTML(IriSP.annotationWidget_template);
+	this.selector.append(annotationMarkup);
+
+  this._Popcorn.listen("IriSP.PlayerWidget.AnnotateButton.clicked", 
+                        IriSP.wrap(this, this.handleAnnotateSignal));  
+  var legal_ids = [];
+  if (typeof(this._serializer.getChapitrage()) !== "undefined")
+    legal_ids.push(this._serializer.getChapitrage());
+  else 
+    legal_ids = this._serializer.getNonTweetIds();
+  
+  var annotations = this._serializer._data.annotations;
+  var i;
+  
+	for (i in annotations) {    
+    var annotation = annotations[i];
+    var begin = Math.round((+ annotation.begin) / 1000);
+    var end = Math.round((+ annotation.end) / 1000);
+
+    if (typeof(annotation.meta) !== "undefined" && typeof(annotation.meta["id-ref"]) !== "undefined"
+          && !IriSP.underscore.include(legal_ids, annotation.meta["id-ref"])) {
+        continue;
+    }
+
+
+    var conf = {start: begin, end: end, 
+                onStart: 
+                       function(annotation) { 
+                        return function() { 
+                            _this.displayAnnotation(annotation); 
+                          
+                        } }(annotation),
+                onEnd: 
+                       function() { _this.clearWidget.call(_this); }
+                };
+    this._Popcorn = this._Popcorn.code(conf);                                             
+  }
+
+};
+
+IriSP.AnnotationsWidget.prototype.handleAnnotateSignal = function() {
+  if (this._hidden == false) {
+    this.selector.hide();
+    this._hidden = true;
+  } else {
+    this.selector.show();
+    this._hidden = false;
+  }
+};IriSP.ArrowWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+
+  this._oldAnnotation = null;
+  this._blockArrow = false;
+};
+
+
+IriSP.ArrowWidget.prototype = new IriSP.Widget();
+
+IriSP.ArrowWidget.prototype.clear = function() {
+
+};
+
+IriSP.ArrowWidget.prototype.clearWidget = function() {
+};
+
+IriSP.ArrowWidget.prototype.draw = function() {
+  var templ = Mustache.to_html(IriSP.arrowWidget_template, {});
+  this.selector.append(templ);
+  this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeUpdateHandler));
+  this._Popcorn.listen("IriSP.ArrowWidget.blockArrow", IriSP.wrap(this, this.blockArrow));
+  this._Popcorn.listen("IriSP.ArrowWidget.releaseArrow", IriSP.wrap(this, this.releaseArrow));
+  
+};
+
+IriSP.ArrowWidget.prototype.timeUpdateHandler = function(percents) {
+  if (this._blockArrow)
+    return;
+  
+  var currentTime = this._Popcorn.currentTime();
+  var currentAnnotation = this._serializer.currentAnnotations(currentTime)[0]; // FIXME : use the others ?
+
+  /* move the arrow only if the current annotation changes */
+  if (currentAnnotation != this._oldAnnotation) {
+    var begin = (+ currentAnnotation.begin) / 1000;
+    var end = (+ currentAnnotation.end) / 1000;
+
+    var duration = +this._serializer.currentMedia().meta["dc:duration"] / 1000;
+    var middle_time = (begin + end) / 2;
+    var percents = middle_time / duration;
+
+    // we need to apply a fix because the arrow has a certain length
+    // it's half the length of the arrow (27 / 2). We need to convert
+    // it in percents though.
+    var totalWidth = this.selector.width();
+    var pixels = percents * totalWidth;
+    var correction = (27 / 2);
+    var corrected_pixels = pixels - correction;
+    
+    /* make sure that the arrow is aligned with the pattern
+       of the widget under it */
+    if (corrected_pixels % 3 != 0)
+      corrected_pixels -= (corrected_pixels % 3 - 1);
+    
+    /* don't move out of the screen */
+    if (corrected_pixels <= 0)
+      corrected_pixels = 0;
+    
+    if (corrected_pixels <= 15) {
+      var left_edge_img_templ = IriSP.templToHTML("url('{{img_dir}}/left_edge_arrow.png')"); 
+      this.selector.children(".Ldt-arrowWidget").css("background-image", left_edge_img_templ); 
+    } else if (corrected_pixels >= totalWidth - 25) {
+      var right_edge_img_templ = IriSP.templToHTML("url('{{img_dir}}/right_edge_arrow.png')"); 
+      this.selector.children(".Ldt-arrowWidget").css("background-image", right_edge_img_templ);
+    } else {
+      var img_templ = IriSP.templToHTML("url('{{img_dir}}/arrow.png')"); 
+      this.selector.children(".Ldt-arrowWidget").css("background-image", img_templ);
+    }
+    
+    this.selector.children(".Ldt-arrowWidget").animate({"left" : corrected_pixels + "px"});
+
+    this._oldAnnotation = currentAnnotation;
+  }
+};
+
+/** Block the arrow for instance when the user is annotating */
+IriSP.ArrowWidget.prototype.blockArrow = function() {
+  this._blockArrow = true;
+};
+
+IriSP.ArrowWidget.prototype.releaseArrow = function() {
+  this._blockArrow = false;   
+};
+IriSP.createAnnotationWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+  this._hidden = true;
+  this.keywords = IriSP.widgetsDefaults["createAnnotationWidget"].keywords;
+  this.cinecast_version = IriSP.widgetsDefaults["createAnnotationWidget"].cinecast_version;
+  this.ids = {}; /* a dictionnary linking buttons ids to keywords */
+};
+
+
+IriSP.createAnnotationWidget.prototype = new IriSP.Widget();
+
+IriSP.createAnnotationWidget.prototype.clear = function() {
+    this.selector.find(".Ldt-SaTitle").text("");
+    this.selector.find(".Ldt-SaDescription").text("");
+    this.selector.find(".Ldt-SaKeywordText").text("");
+};
+
+IriSP.createAnnotationWidget.prototype.draw = function() {
+  var _this = this;
+
+  if (this.cinecast_version) {    
+    var annotationMarkup = IriSP.templToHTML(IriSP.createAnnotationWidget_festivalCinecast_template);
+  } else {
+    var annotationMarkup = IriSP.templToHTML(IriSP.createAnnotationWidget_template);
+  }
+  
+	this.selector.append(annotationMarkup);
+  
+  this.selector.hide();
+  for (var i = 0; i < this.keywords.length; i++) {
+    var keyword = this.keywords[i];
+    var id = IriSP.guid("button_");
+    var templ = IriSP.templToHTML("<button id={{id}} class='Ldt-createAnnotation-absent-keyword'>{{keyword}}</button>", 
+                                  {keyword: keyword, id: id});
+                                  
+    this.ids[keyword] = id; // save it for the function that handle textarea changes.
+    
+    this.selector.find(".Ldt-createAnnotation-keywords").append(templ);
+    this.selector.find("#" + id).click(function(keyword) { return function() {
+      var contents = _this.selector.find(".Ldt-createAnnotation-Description").val();
+      if (contents.indexOf(keyword) != -1) {
+        var newVal = contents.replace(keyword, "");        
+      } else {
+        var newVal = contents + keyword;      
+      }
+      
+      _this.selector.find(".Ldt-createAnnotation-Description").val(newVal);
+      // we use a custom event because there's no simple way to test for a js
+      // change in a textfield.
+      _this.selector.find(".Ldt-createAnnotation-Description").trigger("js_mod");
+      // also call our update function.
+      _this.handleTextChanges();
+    }
+   }(keyword));
+  }
+  
+  this.selector.find(".Ldt-createAnnotation-Description")
+               .bind("propertychange keyup input paste", IriSP.wrap(this, this.handleTextChanges));
+  
+  this.selector.find(".Ldt-createAnnotation-submitButton").click(IriSP.wrap(this, this.handleButtonClick));
+  this._Popcorn.listen("IriSP.PlayerWidget.AnnotateButton.clicked", 
+                        IriSP.wrap(this, this.handleAnnotateSignal));  
+};
+
+IriSP.createAnnotationWidget.prototype.handleAnnotateSignal = function() {
+  if (this._hidden == false) {
+    this.selector.hide();
+    this._hidden = true;
+    /* reinit the fields */
+    
+    this.selector.find(".Ldt-createAnnotation-DoubleBorder").children().show();
+    this.selector.find("Ldt-createAnnotation-Description").val("");
+    this.selector.find(".Ldt-createAnnotation-endScreen").hide();
+    
+    // free the arrow.
+    this._Popcorn.trigger("IriSP.ArrowWidget.releaseArrow");
+  } else {
+    if (this.cinecast_version) {
+      var currentTime = this._Popcorn.currentTime();
+      var currentAnnotation = this._serializer.currentAnnotations(currentTime)[0];
+
+      var beginTime = IriSP.msToTime(currentAnnotation.begin);
+      var endTime = IriSP.msToTime(currentAnnotation.end);
+      
+      /* save the variable because the user may take some time writing his 
+         comment so the currentAnnottion may change when it's time to post it */
+      this._currentAnnotation = currentAnnotation;
+      
+      if (typeof(currentAnnotation.content) !== "undefined")
+        this.selector.find(".Ldt-createAnnotation-Title").html(currentAnnotation.content.title);
+
+      var timeTemplate = IriSP.templToHTML("- ({{begin}} - {{ end }})", {begin: beginTime, end: endTime });
+      this.selector.find(".Ldt-createAnnotation-TimeFrame").html(timeTemplate);
+    }
+    
+    this.selector.show();
+    this._hidden = false;
+    
+    // block the arrow.
+    this._Popcorn.trigger("IriSP.ArrowWidget.blockArrow");
+  }
+};
+
+/** watch for changes in the textfield and change the buttons accordingly */
+IriSP.createAnnotationWidget.prototype.handleTextChanges = function(event) {
+  var contents = this.selector.find(".Ldt-createAnnotation-Description").val();
+
+  for(var keyword in this.ids) {
+  
+    var id = this.ids[keyword];
+
+    if (contents.indexOf(keyword) != -1) {
+      /* the word is present in the textarea but the button is not toggled */
+      if (this.selector.find("#" + id).hasClass("Ldt-createAnnotation-absent-keyword"))
+          this.selector.find("#" + id).removeClass("Ldt-createAnnotation-absent-keyword")
+                                      .addClass("Ldt-createAnnotation-present-keyword");      
+    } else {
+      /* the word is absent from the textarea but the button is toggled */
+      if (this.selector.find("#" + id).hasClass("Ldt-createAnnotation-present-keyword")) {
+          this.selector.find("#" + id).removeClass("Ldt-createAnnotation-present-keyword")
+                                      .addClass("Ldt-createAnnotation-absent-keyword");
+      }
+    }
+  }
+};
+
+/** handle clicks on "send annotation" button */
+IriSP.createAnnotationWidget.prototype.handleButtonClick = function(event) {
+  var _this = this;
+  var textfield = this.selector.find(".Ldt-createAnnotation-Description");
+  var contents = textfield.val();
+
+  if (contents === "") {
+  
+    if (this.selector.find(".Ldt-createAnnotation-errorMessage").length === 0) {
+      this.selector.find(".Ldt-createAnnotation-Container")
+                   .after(IriSP.templToHTML(IriSP.createAnnotation_errorMessage_template));
+      textfield.css("background-color", "#d93c71");      
+    } else {
+      this.selector.find(".Ldt-createAnnotation-errorMessage").show();
+    }
+      // use namespaced events to be able to unbind them quickly and without unbinding
+      // the other event handlers.
+      textfield.bind("js_mod.tmp propertychange.tmp keyup.tmp input.tmp paste.tmp", IriSP.wrap(this, function() {
+                      var contents = textfield.val();
+                      console.log(contents);
+                      if (contents !== "") {
+                        this.selector.find(".Ldt-createAnnotation-errorMessage").hide();
+                        textfield.css("background-color", "");
+                        textfield.unbind(".tmp");
+                      }
+                   }));
+  } else {
+    this.selector.find(".Ldt-createAnnotation-DoubleBorder").children().hide();
+    
+    if (this.cinecast_version) {
+      this.selector.find(".Ldt-createAnnotation-Title").parent().show();      
+    }
+
+    var twStatus = IriSP.mkTweetUrl(document.location.href);
+    var gpStatus = IriSP.mkGplusUrl(document.location.href);
+    var fbStatus = IriSP.mkFbUrl(document.location.href);
+    
+    this.selector.find(".Ldt-createAnnotation-endScreen-TweetLink").attr("href", twStatus);
+    this.selector.find(".Ldt-createAnnotation-endScreen-FbLink").attr("href", fbStatus);
+    this.selector.find(".Ldt-createAnnotation-endScreen-GplusLink").attr("href", gpStatus);
+            
+    this.selector.find(".Ldt-createAnnotation-endScreen").show();
+
+        
+    if (typeof(this._currentAnnotation) === "undefined") {      
+      console.log("this._currentAnnotation undefined");
+      return;
+    }
+    
+    var apiJson = {annotations : [{}], meta: {}};
+    var annotation = apiJson["annotations"][0];
+    //annotation["type_title"] = "Contributions";
+    annotation["type_title"] = "";
+    annotation["media"] = this._serializer.currentMedia()["id"];
+    annotation["begin"] = this._currentAnnotation.begin;
+    annotation["end"] = this._currentAnnotation.end;
+    annotation["type"] = this._serializer.getContributions();
+    annotation.content = {};
+    annotation.content["data"] = contents;
+    
+    var meta = apiJson["meta"];
+    meta.creator = "An User";    
+    meta.created = Date().toString();
+    
+    annotation["tags"] = [];
+    
+    for (var i = 0; i < this.keywords.length; i++) {
+      var keyword = this.keywords[i];
+      if (contents.indexOf(keyword) != -1)
+        annotation["tags"].push(keyword);
+    }
+    
+    var jsonString = JSON.stringify(apiJson);
+    var project_id = this._serializer._data.meta.id;
+    
+    var url = Mustache.to_html("{{platf_url}}/ldtplatform/api/ldt/projects/{{id}}.json",
+                                {platf_url: IriSP.platform_url, id: project_id});
+    console.log(url);
+    IriSP.jQuery.ajax({
+                url: url,
+                type: 'PUT',
+                contentType: 'application/json',
+                data: jsonString,
+                // bug with jquery >= 1.5, "json" adds a callback so we don't specify dataType
+                dataType: 'json',
+                success: function(json, textStatus, XMLHttpRequest) {
+                    /* add the annotation to the annotations and tell the world */
+                    delete annotation.tags;
+                    annotation.content.description = annotation.content.data;
+                    delete annotation.content.data;
+                    annotation.id = json.annotations[0].id;
+                    annotation.title = _this._currentAnnotation.content.title;
+                    annotation.meta = meta;
+                    annotation.meta["id-ref"] = annotation["type"];
+                    // everything is shared so there's no need to propagate the change
+                    _this._serializer._data.annotations.push(annotation);
+                    _this._Popcorn.trigger("IriSP.createAnnotationWidget.addedAnnotation");
+                },
+                error: function(jqXHR, textStatus, errorThrown) {
+                    alert("ERROR = " + jqXHR.responseText + ", " + errorThrown);
+                }
+            });
+  }
+};IriSP.PlayerWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+  
+  this._searchBlockOpen = false;
+  this._searchLastValue = "";
+};
+
+IriSP.PlayerWidget.prototype = new IriSP.Widget();
+
+IriSP.PlayerWidget.prototype.draw = function() {
+  var self = this;
+  var width = this.width;
+	var height = this.height;
+	var heightS = this.height-20;
+	  
+	var playerTempl = IriSP.templToHTML(IriSP.player_template, {"share_template" : IriSP.share_template});
+  this.selector.append(playerTempl);		
+	
+  this.selector.children(".Ldt-controler").show();
+    
+  // handle clicks by the user on the video.
+  this._Popcorn.listen("play", IriSP.wrap(this, this.playButtonUpdater));
+  this._Popcorn.listen("pause", IriSP.wrap(this, this.playButtonUpdater));
+  
+  this._Popcorn.listen("volumechange", IriSP.wrap(this, this.muteButtonUpdater));
+
+  this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeDisplayUpdater));  
+  // update the time display for the first time.
+  this._Popcorn.listen("loadedmetadata", IriSP.wrap(this, this.timeDisplayUpdater));
+  
+  this._Popcorn.listen("IriSP.search.matchFound", IriSP.wrap(this, this.searchMatch));
+  this._Popcorn.listen("IriSP.search.noMatchFound", IriSP.wrap(this, this.searchNoMatch));
+  
+  
+  this.selector.find(".Ldt-CtrlPlay").click(function() { self.playHandler.call(self); });
+  this.selector.find(".Ldt-CtrlAnnotate").click(function() 
+                                            { self._Popcorn.trigger("IriSP.PlayerWidget.AnnotateButton.clicked"); });
+  this.selector.find(".Ldt-CtrlSearch").click(function() { self.searchButtonHandler.call(self); });
+  
+  this.selector.find('.Ldt-CtrlSound').click(function() { self.muteHandler.call(self); } );
+
+  this.selector.find(".Ldt-CtrlPlay").attr( "style", "background-color:#CD21C24;" );
+  
+  /*
+  var searchButtonPos = this.selector.find(".Ldt-CtrlSearch").position();
+  var searchBox = Mustache.to_html(IriSP.search_template, {margin_left : searchButtonPos.left + "px"});
+  this.selector.find(".Ldt-CtrlSearch").after(searchBox);
+  */
+  
+  // trigger an IriSP.PlayerWidget.MouseOver to the widgets that are interested (i.e : sliderWidget)
+  this.selector.hover(function() { self._Popcorn.trigger("IriSP.PlayerWidget.MouseOver"); }, 
+                      function() { self._Popcorn.trigger("IriSP.PlayerWidget.MouseOut"); });
+ 
+  this.muteButtonUpdater(); /* some player - jwplayer notable - save the state of the mute button between sessions */
+};
+
+/* Update the elasped time div */
+IriSP.PlayerWidget.prototype.timeDisplayUpdater = function() {
+  
+  if (this._previousSecond === undefined)
+    this._previousSecond = this._Popcorn.roundTime();
+  
+  else {
+    /* we're still in the same second, so it's not necessary to update time */
+    if (this._Popcorn.roundTime() == this._previousSecond)
+      return;
+      
+  }
+  
+  // we get it at each call because it may change.
+  var duration = +this._serializer.currentMedia().meta["dc:duration"] / 1000; 
+  var totalTime = IriSP.secondsToTime(duration);
+  var elapsedTime = IriSP.secondsToTime(this._Popcorn.currentTime());
+  
+  this.selector.find(".Ldt-ElapsedTime").html(elapsedTime.toString());
+  this.selector.find(".Ldt-TotalTime").html(totalTime.toString());
+  this._previousSecond = this._Popcorn.roundTime();
+};
+
+/* update the icon of the button - separate function from playHandler
+   because in some cases (for instance, when the user directly clicks on
+   the jwplayer window) we have to change the icon without playing/pausing
+*/
+IriSP.PlayerWidget.prototype.playButtonUpdater = function() {
+  var status = this._Popcorn.media.paused;
+  
+  if ( status == true ){        
+    this.selector.find(".Ldt-CtrlPlay").attr("title", "Play");
+   
+    // we use templToHTML because it has some predefined
+    // vars like where to get the images
+    var templ = IriSP.templToHTML("url({{img_dir}}/play_sprite.png)");
+    this.selector.find(".Ldt-CtrlPlay").css("background-image", templ);
+
+  } else {
+    this.selector.find(".Ldt-CtrlPlay").attr("title", "Pause");
+
+    // we use templToHTML because it has some predefined
+    // vars like where to get the images
+    var templ = IriSP.templToHTML("url({{img_dir}}/pause_sprite.png)");
+    this.selector.find(".Ldt-CtrlPlay").css("background-image", templ);
+  }  
+
+  return;
+};
+
+
+IriSP.PlayerWidget.prototype.playHandler = function() {
+  var status = this._Popcorn.media.paused;
+  
+  if ( status == true ){        
+    this._Popcorn.play();   
+  } else {
+    this._Popcorn.pause();
+  }  
+};
+
+IriSP.PlayerWidget.prototype.muteHandler = function() {
+  if (!this._Popcorn.muted()) {    
+      this._Popcorn.mute(true);
+    } else {
+      this._Popcorn.mute(false);
+    }
+};
+
+IriSP.PlayerWidget.prototype.muteButtonUpdater = function() {
+  var status = this._Popcorn.media.muted;
+  
+  if ( status == true ){        
+    this.selector.find(".Ldt-CtrlSound").attr("title", "Unmute");
+   
+    // we use templToHTML because it has some predefined
+    // vars like where to get the images
+    var templ = IriSP.templToHTML("url({{img_dir}}/sound_sprite.png)");
+    this.selector.find(".Ldt-CtrlSound").css("background-image", templ);
+
+  } else {
+    this.selector.find(".Ldt-CtrlSound").attr("title", "Mute");
+
+    // we use templToHTML because it has some predefined
+    // vars like where to get the images
+    var templ = IriSP.templToHTML("url({{img_dir}}/mute_sprite.png)");
+    this.selector.find(".Ldt-CtrlSound").css("background-image", templ);
+  }  
+
+  return;
+};
+
+
+IriSP.PlayerWidget.prototype.searchButtonHandler = function() {
+    var self = this;
+
+    /* show the search field if it is not shown */
+  	if ( this._searchBlockOpen == false ) {      
+      this.selector.find(".LdtSearch").show("blind", { direction: "horizontal"}, 100);
+      
+      this.selector.find(".LdtSearchInput").css('background-color','#fff');
+      this.selector.find(".LdtSearchInput").focus();
+      this.selector.find(".LdtSearchInput").attr('value', this._searchLastValue);      
+      this._Popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural.
+      
+      this._searchBlockOpen = true;           
+      this.selector.find(".LdtSearchInput").bind('keyup', null, function() { self.searchHandler.call(self); } );
+      
+      // we need this variable because some widget can find a match in
+      // their data while at the same time other's don't. As we want the
+      // search field to become green when there's a match, we need a 
+      // variable to remember that we had one.
+      this._positiveMatch = false;
+
+      // tell the world the field is open
+      this._Popcorn.trigger("IriSP.search.open");
+      
+	} else {
+      this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value');
+      this.selector.find(".LdtSearchInput").attr('value','');
+      this.selector.find(".LdtSearch").hide("blind", { direction: "horizontal"}, 75);
+      
+      // unbind the watcher event.
+      this.selector.find(".LdtSearchInput").unbind('keypress set');
+      this._searchBlockOpen = false;
+
+      this._positiveMatch = false;
+      
+      this._Popcorn.trigger("IriSP.search.closed");
+  }
+};
+
+/* this handler is called whenever the content of the search
+   field changes */
+IriSP.PlayerWidget.prototype.searchHandler = function() {
+  this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value');
+  this._positiveMatch = false;
+  
+  // do nothing if the search field is empty, instead of highlighting everything.
+  if (this._searchLastValue == "") {
+    this._Popcorn.trigger("IriSP.search.cleared");
+    this.selector.find(".LdtSearchInput").css('background-color','');
+  } else {
+    this._Popcorn.trigger("IriSP.search", this._searchLastValue);
+  }
+};
+
+/*
+  handler for the IriSP.search.found message, which is sent by some views when they
+  highlight a match.
+*/
+IriSP.PlayerWidget.prototype.searchMatch = function() {
+  this._positiveMatch = true;
+  this.selector.find(".LdtSearchInput").css('background-color','#e1ffe1');
+}
+
+/* the same, except that no value could be found */
+IriSP.PlayerWidget.prototype.searchNoMatch = function() {
+  if (this._positiveMatch !== true)
+    this.selector.find(".LdtSearchInput").css('background-color', "#d62e3a");
+}
+
+/* 
+ *   
+ *  Copyright 2010 Institut de recherche et d'innovation 
+ *  contributor(s) : Samuel Huron 
+ *   
+ *  contact@iri.centrepompidou.fr
+ *  http://www.iri.centrepompidou.fr 
+ *   
+ *  This software is a computer program whose purpose is to show and add annotations on a video .
+ *  This software is governed by the CeCILL-C license under French law and
+ *  abiding by the rules of distribution of free software. You can  use, 
+ *  modify and/ or redistribute the software under the terms of the CeCILL-C
+ *  license as circulated by CEA, CNRS and INRIA at the following URL
+ *  "http://www.cecill.info". 
+ *  
+ *  The fact that you are presently reading this means that you have had
+ *  knowledge of the CeCILL-C license and that you accept its terms.
+*/
+// CHART TIMELINE / VERSION PROTOTYPE  ::
+
+/** the polemic widget */
+IriSP.PolemicWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+ 
+  this.userPol    = new Array();
+  this.userNoPol  = new Array();
+  this.userst      = new Array();
+  this.numberOfTweet = 0;
+  this.Users;
+  this.TweetPolemic;
+  this.yMax        = this.height; 
+  this.PaperSlider;
+  this.heightOfChart;
+  this.tweets  = new Array();
+  this.svgElements = {};
+  
+  this.oldSearchMatches = [];
+  // Make and define the Raphael area
+  this.paper = Raphael(document.getElementById(this._id), config.width, config.height);
+  
+  // event handlers
+  this._Popcorn.listen("IriSP.search", IriSP.wrap(this, function(searchString) { this.searchHandler(searchString); }));
+  this._Popcorn.listen("IriSP.search.closed", IriSP.wrap(this, this.searchFieldClosedHandler));
+  this._Popcorn.listen("IriSP.search.cleared", IriSP.wrap(this, this.searchFieldClearedHandler));
+
+};
+
+IriSP.PolemicWidget.prototype = new IriSP.Widget();
+  
+IriSP.PolemicWidget.prototype.draw = function() {
+  
+    // variable 
+    // yMax
+    
+    var self = this;
+    var yCoef        = 2;             // coef for height of 1 tweet 
+    var frameSize     = 5;             // frame size 
+    var margin         = 1;            // marge between frame
+    var lineSize      = this.width;        // timeline pixel width 
+    var nbrframes     = lineSize/frameSize;     // frame numbers
+    var numberOfTweet   = 0;            // number of tweet overide later 
+    var duration      = +this._serializer.currentMedia().meta["dc:duration"];      // timescale width 
+    var frameLength   = lineSize / frameSize;    // frame timescale  
+    var timeline;
+    var colors  = new Array("","#1D973D","#C5A62D","#CE0A15","#036AAE","#585858");
+    
+    // array 
+    //var tweets  = new Array();
+    var element = new Array();
+    var cluster = new Array();
+    var frames  = new Array(frameLength);
+    var slices  = new Array();
+    
+    
+    // Classes =======================================================================
+    var Frames = function(){
+      
+      var Myclusters;
+      var x;
+      var y;
+      var width;
+      var height;
+    };
+    Frames = function(json){
+      // make my clusters
+      // ou Frame vide 
+    };
+    Frames.prototype.draw = function(){
+    };
+    Frames.prototype.zoom = function(){
+    };
+    Frames.prototype.inside = function(){
+    };
+    var Clusters = function(){
+      var Object;
+      var yDist;
+      var x;
+      var y;
+      var width;
+      var height;
+    };
+    Clusters = function(json){
+      // make my object
+    };
+    var Tweet = function(){
+    };
+    // Classes =======================================================================
+
+    // Refactoring (parametere) ************************************************************
+    // color translastion
+    var qTweet_0  =0;
+    var qTweet_Q  =0;
+    var qTweet_REF=0;
+    var qTweet_OK =0;
+    var qTweet_KO =0;
+    function colorTranslation(value){
+      if(value == "Q"){
+        qTweet_Q+=1;
+        return 2;
+      }else if(value =="REF"){
+        qTweet_REF+=1;
+        return 4;
+      }else if(value =="OK"){
+        qTweet_OK+=1;
+        return 1;
+      }else if(value =="KO"){
+        qTweet_KO+=1;
+        return 3;
+      }else if(value ==""){
+        qTweet_0+=1;
+        return 5;
+      }
+    }
+    
+
+      this._serializer.sync(function(data) { loaded_callback.call(self, data) });
+      
+      function loaded_callback (json) {
+      var view_type = this._serializer.getTweets();
+
+      if (typeof(view_type) === "undefined") {
+        var view_type = this._serializer.getTweetIds()[0];      
+        if (typeof(view_type) === "undefined") {
+          // default to guessing if nothing else works.
+          view = json.views[0];
+          
+          if(typeof(view.annotation_types) !== "undefined") {
+            if (view.annotation_types.length >= 1) {
+              view_type = view.annotation_types[0];
+            } else {
+              console.log("PolemicWidget: invalid file");
+            }
+          }      
+        }
+      }
+      
+      for(var i = 0; i < json.annotations.length; i++) {
+        var item = json.annotations[i];        
+        var MyTime  = Math.floor(item.begin/duration*lineSize);
+        var Myframe = Math.floor(MyTime/lineSize*frameLength);
+
+        if (typeof(item.meta) !== "undefined" 
+          && typeof(item.meta["id-ref"]) !== "undefined"
+          && item.meta["id-ref"] === view_type) {
+            
+            var MyTJson = {};
+            if (typeof(item.meta['dc:source']) !== "undefined") {
+              var MyTJson = JSON.parse(item.meta['dc:source']['content']);
+            }
+            
+            if (item.content['polemics'] != undefined 
+            && item.content['polemics'][0] != null) {
+            
+              // a tweet can have many polemics at the same time.
+              for(var j=0; j<item.content['polemics'].length; j++){
+                  
+                  this.tweets[numberOfTweet] = {
+                        id:i,
+                        qualification:colorTranslation(item.content['polemics'][j]),
+                        yIndicator:MyTime,
+                        yframe:Myframe,
+                        title:item.content['title'],
+                        timeframe:item.begin,
+                        userId: MyTJson.id,
+                        userScreenName: MyTJson.screen_name,
+                        tsource:MyTJson,
+                        cinecast_id: item.id
+                        };
+                  numberOfTweet+=1;
+                  
+              }
+          }
+          else {
+            this.tweets[numberOfTweet] = {
+                  id:i,
+                  qualification:colorTranslation(""),
+                  yIndicator:MyTime,
+                  yframe:Myframe,
+                  title:item.content['title'],
+                  timeframe:item.begin,
+                  userId: MyTJson.id,
+                  userScreenName: MyTJson.screen_name,
+                  tsource:MyTJson,
+                  cinecast_id: item.id
+            };
+            numberOfTweet+=1;
+          }
+          
+        } 
+      };  
+      
+       DrawTweets.call (this); // FIXME: ugly.
+       
+      };      
+
+    // tweet Drawing (in raphael) 
+    function DrawTweets (){
+    // GROUPES TWEET ============================================
+    // Count nbr of cluster and tweet in a frame an save int in "frames"
+      numberOfTweet = this.tweets.length;
+      for(var i=0; i<nbrframes; i++) {  
+        for(var j=0; j<numberOfTweet; j++) {  
+        
+          if (i==this.tweets[j].yframe){
+            
+            var k = this.tweets[j].qualification;
+            
+            // make array for frame cluster
+            if(frames[i]==undefined){
+              frames[i] = {id:i,
+                     qualifVol:new Array(),
+                     mytweetsID:new Array()
+                    };
+            }
+            // add my tweet to frame
+            frames[i].mytweetsID.push(this.tweets[j]);
+            
+            // count opinion by frame
+            if( frames[i].qualifVol[k] == undefined){
+              frames[i].qualifVol[k] = 1;
+            }else{
+              frames[i].qualifVol[k] += 1;
+            }
+            
+          }
+        }
+      }
+    
+    // GROUPES TWEET ============================================    
+    // max of tweet by Frame 
+      var max = 0; 
+      for(var i = 0; i < nbrframes; i++) {
+        var moy  = 0;
+        for (var j = 0; j < 6; j++) {    
+          if (frames[i] != undefined) {
+            if (frames[i].qualifVol[j] != undefined) {
+              moy += frames[i].qualifVol[j];
+            }
+          }
+        }
+        
+        if (moy > max) {
+          max = moy;
+        }
+      }
+    
+      var tweetDrawed = new Array();
+      var TweetHeight = 5;
+      var newHeight = TweetHeight * max + 10;
+
+      
+      if (newHeight > this.height) {
+        this.paper.setSize(this.width, newHeight);
+        this.height = newHeight;
+        console.log("resizeing");
+      }
+      
+  
+      // DRAW  TWEETS ============================================
+      for(var i = 0; i < nbrframes; i++) {
+        var addEheight = 5;
+        if (frames[i] != undefined){                
+          // by type 
+          
+          for (var j = 6; j > -1; j--) {
+            if (frames[i].qualifVol[j] != undefined) {
+              // show tweet by type 
+              for (var k = 0; k < frames[i].mytweetsID.length; k++) {
+              
+                if (frames[i].mytweetsID[k].qualification == j) {                
+                  var x = i * frameSize;
+                  var y = this.height - addEheight;
+                  
+                  if (this.yMax > y) {
+                    this.yMax = y;
+                  }
+                  
+                  /* some tweets seem to be duplicated - so we make a check before
+                     creating a new rect */
+                  if (this.svgElements.hasOwnProperty(frames[i].mytweetsID[k].cinecast_id))
+                    continue;
+                  
+                  var e = this.paper.rect(x, y, frameSize - margin, TweetHeight /* height */)
+                                    .attr({stroke:"#00","stroke-width":0.1,  fill: colors[j]});  
+                  
+                  addEheight += TweetHeight;
+                  
+                  e.color = colors[j];
+                  e.time = frames[i].mytweetsID[k].timeframe;
+                  e.title = frames[i].mytweetsID[k].title;
+                  e.id = frames[i].mytweetsID[k].cinecast_id;
+                  
+                  this.svgElements[e.id] = e;
+                  
+                  IriSP.jQuery(e.node).mouseenter(function(element) { return function (event) {                        
+                        // event.clientX and event.clientY are to raphael what event.pageX and pageY are to jquery.                        
+                        self.TooltipWidget.show.call(self.TooltipWidget, element.title, element.attr("fill"), event.pageX - 106, event.pageY - 160);
+                        element.displayed = true;
+                  }}(e)).mousedown(function(element) { return function () {                    
+                    self._Popcorn.currentTime(element.time/1000);
+                    self._Popcorn.trigger("IriSP.PolemicTweet.click", element.id); 
+                    }
+                  }(e));                  
+                  
+                  IriSP.jQuery(e.node).attr('id', 't' + k + '');
+                  IriSP.jQuery(e.node).attr('title', frames[i].mytweetsID[k].title);
+                  IriSP.jQuery(e.node).attr('begin',  frames[i].mytweetsID[k].timeframe);                  
+                }
+              }
+            }
+          }
+        }
+
+      }    
+      // DRAW UI :: resize border and bgd      
+      this.paperBackground = this.paper.rect(0, 0, this.width, this.height).attr({fill:"#F8F8F8","stroke-width":0.1,opacity: 1});  
+
+      // outer borders
+      this.outerBorders   = [];
+      this.outerBorders.push(this.paper.rect(0, this.height - 1, this.width, 1).attr({fill:"#ababab",stroke: "none",opacity: 1}));  
+      this.outerBorders.push(this.paper.rect(0, 0, this.width, 1).attr({fill:"#ababab",stroke: "none",opacity: 1}));  
+
+      // inner borders
+      this.innerBorders   = [];
+      this.innerBorders.push(this.paper.rect(1, this.height - 2, this.width, 1).attr({fill:"#efefef",stroke: "none",opacity: 1}));  
+      this.innerBorders.push(this.paper.rect(1, 1, this.width, 1).attr({fill:"#efefef",stroke: "none",opacity: 1}));  
+      this.innerBorders.push(this.paper.rect(1, 1, 1, this.height - 2).attr({fill:"#d0d1d1",stroke: "none",opacity: 0.8}));  
+      this.innerBorders.push(this.paper.rect(this.width - 2, 1, 1, this.height - 2).attr({fill:"#efefef",stroke: "none",opacity: 1}));  
+
+
+
+      this.paperSlider   = this.paper.rect(0, 0, 0, this.height).attr({fill:"#D4D5D5", stroke: "none", opacity: 1});
+      
+      // the small white line displayed over the slider.
+      this.sliderTip = this.paper.rect(0, 0, 1, this.height).attr({fill:"#fc00ff", stroke: "none", opacity: 1});
+      // decalage 
+      // tweetSelection = this.paper.rect(-100,-100,5,5).attr({fill:"#fff",stroke: "none",opacity: 1});  
+      
+      
+      this.paperSlider.toBack();
+      this.paperBackground.toBack();
+      this.sliderTip.toFront();
+    }
+    
+    this.selector.mouseleave(IriSP.wrap(this, function() { self.TooltipWidget.hide.call(self.TooltipWidget); }));
+    this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater));
+}
+
+/** update the positionMarker as time passes */
+IriSP.PolemicWidget.prototype.sliderUpdater = function() {
+
+    var time = +this._Popcorn.currentTime();
+    var duration = +this._serializer.currentMedia().meta["dc:duration"];
+    
+    this.paperSlider.attr("width", time * (this.width / (duration / 1000)));
+        
+    this.sliderTip.attr("x", time * (this.width / (duration / 1000)));
+};
+
+/** reacts to IriSP.search events */    
+IriSP.PolemicWidget.prototype.searchHandler = function(searchString) {
+  if (searchString == "")
+    return;
+
+  var matches = this._serializer.searchTweetsOccurences(searchString);
+
+  if (IriSP.countProperties(matches) > 0) {
+    this._Popcorn.trigger("IriSP.search.matchFound");
+  } else {
+    this._Popcorn.trigger("IriSP.search.noMatchFound");
+  }
+
+  
+  // decrease the opacity of the other elements.
+  for (var id in this.svgElements) {
+    var e = this.svgElements[id];
+    e.attr({fill: e.color, opacity: 0.4});   
+  }
+  
+
+  for (var id in matches) {    
+    if (this.svgElements.hasOwnProperty(id)) {
+      var e = this.svgElements[id];
+      this.svgElements[id].attr({fill: "#fc00ff", opacity: 1});
+    }
+  }
+
+  this.oldSearchMatches = matches;
+};
+
+/** reacts to IriSP.search.cleared messages */
+IriSP.PolemicWidget.prototype.searchFieldClearedHandler = function() {
+  for (var id in this.svgElements) {
+    var e = this.svgElements[id];
+    e.attr({fill: e.color, opacity: 1});
+  }
+};
+
+/** reacts to IriSP.search.closed messages by clearing the highlighted elements */
+IriSP.PolemicWidget.prototype.searchFieldClosedHandler = function() {
+  for (var id in this.svgElements) {
+    var e = this.svgElements[id];
+    e.attr({fill: e.color, opacity: 1});
+  }
+ 
+};
+   
+IriSP.SegmentsWidget = function(Popcorn, config, Serializer) {
+
+  var self = this;
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+  this.oldSearchMatches = [];
+
+  // event handlers
+  this._Popcorn.listen("IriSP.search", function(searchString) { self.searchHandler.call(self, searchString); });
+  this._Popcorn.listen("IriSP.search.closed", function() { self.searchFieldClosedHandler.call(self); });
+  this._Popcorn.listen("IriSP.search.cleared", function() { self.searchFieldClearedHandler.call(self); });
+};
+
+IriSP.SegmentsWidget.prototype = new IriSP.Widget();
+
+/* Get the width of a segment, in pixels. */
+IriSP.SegmentsWidget.prototype.segmentToPixel = function(annotation) {  
+  var begin = Math.round((+ annotation.begin) / 1000);
+  var end = Math.round((+ annotation.end) / 1000);    
+  var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000;
+  
+  var startPourcent 	= IriSP.timeToPourcent(begin, duration);
+  var startPixel = Math.floor(this.selector.parent().width() * (startPourcent / 100));
+  
+  var endPourcent 	= Math.floor(IriSP.timeToPourcent(end, duration) - startPourcent);
+  var endPixel = Math.floor(this.selector.parent().width() * (endPourcent / 100));
+  
+  return endPixel;
+};
+
+/* compute the total length of a group of segments */
+IriSP.SegmentsWidget.prototype.segmentsLength = function(segmentsList) {
+  var self = this;
+  var total = 0;
+  
+  for (var i = 0; i < segmentsList.length; i++)
+    total += self.segmentToPixel(segmentsList[i].annotation);
+  
+  return total;  
+};
+
+IriSP.SegmentsWidget.prototype.draw = function() {
+
+  var self = this;
+  var annotations = this._serializer._data.annotations;
+
+  this.selector.addClass("Ldt-SegmentsWidget");
+  this.selector.append(Mustache.to_html(IriSP.overlay_marker_template));
+          
+  var view_type = this._serializer.getChapitrage();
+  if (typeof(view_type) === "undefined")
+    view_type = this._serializer.getNonTweetIds()[0];    
+  
+  this.positionMarker = this.selector.children(":first");
+  
+  this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.positionUpdater));
+  
+  
+  var i = 0;
+  
+  var segments_annotations = [];
+  
+  for (i = 0; i < annotations.length; i++) {
+    var annotation = annotations[i];
+
+    /* filter the annotations whose type is not the one we want */
+    if (view_type != "" && typeof(annotation.meta) !== "undefined" && typeof(annotation.meta["id-ref"]) !== "undefined"
+          && annotation.meta["id-ref"] != view_type) {
+        continue;
+    }
+
+    segments_annotations.push(annotation);
+  }
+    
+  var totalWidth = this.selector.width() - segments_annotations.length;
+  var lastSegment = IriSP.underscore.max(segments_annotations, function(annotation) { return annotation.end; });
+  
+  for (i = 0; i < segments_annotations.length; i++) {
+  
+    var annotation = segments_annotations[i];
+    var begin = (+ annotation.begin);
+    var end = (+ annotation.end);
+    var duration = this._serializer.currentMedia().meta["dc:duration"];
+    var id = annotation.id;
+        
+    var startPixel = Math.floor(this.selector.parent().width() * (begin / duration));
+
+    var endPixel = Math.floor(this.selector.parent().width() * (end / duration));
+    
+    if (annotation.id !== lastSegment.id) 
+      var pxWidth = endPixel - startPixel -1;
+    else
+      /* the last segment has no segment following it */
+      var pxWidth = endPixel - startPixel;
+ 
+    var divTitle = (annotation.content.title + " - " + annotation.content.description).substr(0,55);
+
+    if (typeof(annotation.content.color) !== "undefined")
+      var color = annotation.content.color;
+    else
+      var color = annotation.color;
+    
+    var hexa_color = IriSP.DEC_HEXA_COLOR(color);
+
+    if (hexa_color === "FFCC00")
+      hexa_color = "333";
+    if (hexa_color.length == 4)
+      hexa_color = hexa_color + '00';
+    
+    var annotationTemplate = Mustache.to_html(IriSP.annotation_template,
+        {"divTitle" : divTitle, "id" : id, "startPixel" : startPixel,
+        "pxWidth" : pxWidth, "hexa_color" : hexa_color,
+        "seekPlace" : Math.round(begin/1000)});
+
+        
+    this.selector.append(annotationTemplate);
+    
+    /* add a special class to the last segment and change its border */
+    if (annotation.id === lastSegment.id) {
+        this.selector.find("#" + id).addClass("Ldt-lastSegment");        
+        this.selector.find(".Ldt-lastSegment").css("border-color", "#" + hexa_color);        
+    }
+
+    IriSP.jQuery("#" + id).fadeTo(0, 0.3);
+
+    IriSP.jQuery("#" + id).mouseover(
+    /* we wrap the handler in another function because js's scoping
+       rules are function-based - otherwise, the internal vars like
+       divTitle are preserved but they are looked-up from the draw
+       method scope, so after that the loop is run, so they're not
+       preserved */
+    (function(divTitle) { 
+     return function(event) {
+          IriSP.jQuery(this).animate({opacity: 0.6}, 5);
+          var offset = IriSP.jQuery(this).offset();
+          var correction = IriSP.jQuery(this).outerWidth() / 2;
+
+          var offset_x = offset.left + correction - 106;
+          if (offset_x < 0)
+            offset_x = 0;
+          
+          var offset_y = offset.top;          
+
+          self.TooltipWidget.show(divTitle, color, offset_x, offset_y - 160);
+    } })(divTitle)).mouseout(function(){
+      IriSP.jQuery(this).animate({opacity: 0.3}, 5);
+      self.TooltipWidget.hide();
+    });
+
+    IriSP.jQuery("#" + id).click(function(_this, annotation) {
+                                    return function() { _this.clickHandler(annotation)};
+                                 }(this, annotation));
+  }
+};
+
+/* restores the view after a search */
+IriSP.SegmentsWidget.prototype.clear = function() {
+  this.selector.children(".Ldt-iri-chapter").animate({opacity:0.3}, 100);
+};
+
+IriSP.SegmentsWidget.prototype.clickHandler = function(annotation) {
+  this._Popcorn.trigger("IriSP.SegmentsWidget.click", annotation.id);
+  var begin = (+ annotation.begin) / 1000;
+  this._Popcorn.currentTime(Math.round(begin));
+};
+
+IriSP.SegmentsWidget.prototype.searchHandler = function(searchString) {
+
+  if (searchString == "")
+    return;
+
+  var matches = this._serializer.searchOccurences(searchString);
+
+  if (IriSP.countProperties(matches) > 0) {
+    this._Popcorn.trigger("IriSP.search.matchFound");
+  } else {
+    this._Popcorn.trigger("IriSP.search.noMatchFound");
+  }
+
+  // un-highlight all the blocks
+  this.selector.children(".Ldt-iri-chapter").css("opacity", 0.1);
+ 
+  // then highlight the ones with matches.
+  for (var id in matches) {
+    var factor = 0.5 + matches[id] * 0.2;
+    this.selector.find("#"+id).dequeue();
+    this.selector.find("#"+id).animate({opacity:factor}, 200);
+  }
+
+ 
+  this.oldSearchMatches = matches;
+};
+
+IriSP.SegmentsWidget.prototype.searchFieldClearedHandler = function() {
+  this.clear();
+};
+
+IriSP.SegmentsWidget.prototype.searchFieldClosedHandler = function() {
+  this.clear();
+};
+
+IriSP.SegmentsWidget.prototype.positionUpdater = function() {  
+  var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000;
+  var time = this._Popcorn.currentTime();
+  //var position 	= ((time / duration) * 100).toFixed(2);
+  var position 	= ((time / duration) * 100).toFixed(2);
+
+  this.positionMarker.css("left", position + "%");  
+};
+/** A widget to create a new segment */
+IriSP.SliceWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+  
+};
+
+IriSP.SliceWidget.prototype = new IriSP.Widget();
+
+IriSP.SliceWidget.prototype.draw = function() {
+  var templ = Mustache.to_html(IriSP.sliceWidget_template);
+  this.selector.append(templ);
+  
+  this.sliceZone = this.selector.find(".Ldt-sliceZone");
+  
+  /* global variables used to keep the position and width
+     of the zone.
+  */  
+  this.zoneLeft = 0;
+  this.zoneWidth = 0;
+  
+  this.leftHandle = this.selector.find(".Ldt-sliceLeftHandle");
+  this.rightHandle = this.selector.find(".Ldt-sliceRightHandle");
+
+  this.leftHandle.draggable({axis: "x",
+  drag: IriSP.wrap(this, this.leftHandleDragged),  
+  containment: "parent"
+  });
+
+  this.rightHandle.draggable({axis: "x",
+  drag: IriSP.wrap(this, this.rightHandleDragged),    
+  containment: "parent"
+  });
+
+  this.leftHandle.css("position", "absolute");
+  this.rightHandle.css("position", "absolute");
+  
+  this._Popcorn.listen("IriSP.SliceWidget.position", 
+                        IriSP.wrap(this, this.positionSliceHandler));
+  this._Popcorn.trigger("IriSP.SliceWidget.position", [57, 24]);
+};
+
+IriSP.SliceWidget.prototype.positionSliceHandler = function(params) {
+  left = params[0];
+  width = params[1];
+  
+  this.zoneLeft = left;
+  this.zoneWidth = width;
+  this.sliceZone.css("left", left + "px");
+  this.sliceZone.css("width", width + "px");
+  this.leftHandle.css("left", (left - 7) + "px");
+  this.rightHandle.css("left", left + width + "px");
+  
+  this._leftHandleOldLeft = left - 7;
+  this._rightHandleOldLeft = left + width;
+};
+
+/** handle a dragging of the left handle */
+IriSP.SliceWidget.prototype.leftHandleDragged = function(event, ui) {
+  /* we have a special variable, this._leftHandleOldLeft, to keep the
+     previous position of the handle. We do that to know in what direction
+     is the handle being dragged
+  */
+  
+  var currentX = this.leftHandle.position()["left"];
+  var rightHandleX = this.rightHandle.position()["left"];
+  
+  if (currentX >= rightHandleX - 7 && ui.position.left >= this._leftHandleOldLeft) {
+    /* prevent the handle from moving past the right handle */
+    ui.position.left = this._leftHandleOldLeft;
+  }
+  
+  var increment = this.zoneLeft - (currentX + 7);
+  
+  this.zoneWidth += increment;
+  this.zoneLeft = currentX + 7;
+  this.sliceZone.css("width", this.zoneWidth);
+  this.sliceZone.css("left", this.zoneLeft + "px");
+  this.broadcastChanges();
+  
+  this._leftHandleOldLeft = ui.position.left;  
+};
+
+/** handle a dragging of the right handle */
+IriSP.SliceWidget.prototype.rightHandleDragged = function(event, ui) { 
+  var currentX = this.rightHandle.position()["left"];
+  var leftHandleX = this.leftHandle.position()["left"];
+  
+  if (currentX <= leftHandleX + 7 && ui.position.left <= this._rightHandleOldLeft) {
+    /* prevent the handle from moving past the right handle */
+    ui.position.left = this._rightHandleOldLeft;
+  }
+  
+  var increment = currentX - (this.zoneLeft + this.zoneWidth);  
+
+  this.zoneWidth += increment;  
+  this.sliceZone.css("width", this.zoneWidth);
+  this.broadcastChanges();
+  
+  this._rightHandleOldLeft = ui.position.left; 
+};
+
+/** tell to the world that the coordinates of the slice have
+    changed 
+*/
+IriSP.SliceWidget.prototype.broadcastChanges = function() {
+  var leftPercent = (this.zoneLeft / this.selector.width()) * 100;
+  var zonePercent = (this.zoneWidth / this.selector.width()) * 100;
+  
+  this._Popcorn.trigger("IriSP.SliceWidget.zoneChange", [leftPercent, zonePercent]);  
+};IriSP.SliderWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+};
+
+IriSP.SliderWidget.prototype = new IriSP.Widget();
+
+IriSP.SliderWidget.prototype.draw = function() {
+  var self = this;
+
+  this.selector.append(Mustache.to_html(IriSP.sliderWidget_template, {}));
+  this.selector.addClass("Ldt-SliderMinimized");
+
+  this.sliderBackground = this.selector.find(".Ldt-sliderBackground");
+  this.sliderForeground = this.selector.find(".Ldt-sliderForeground");
+  this.positionMarker = this.selector.find(".Ldt-sliderPositionMarker");
+
+
+  // a special variable to stop methods from tinkering
+  // with the positionMarker when the user is dragging it
+  this.draggingOngoing = false;
+
+  // another special variable used by the timeout handler to
+  // open or close the slider.
+  this.sliderMaximized = false;
+  this.timeOutId = null;
+
+  
+  this.positionMarker.draggable({axis: "x",
+  start: IriSP.wrap(this, this.positionMarkerDraggingStartedHandler),
+  stop: IriSP.wrap(this, this.positionMarkerDraggedHandler),
+  containment: "parent"
+  });
+  this.positionMarker.css("position", "absolute");
+  
+  this.sliderBackground.click(function(event) { self.backgroundClickHandler.call(self, event); });
+  this.sliderForeground.click(function(event) { self.foregroundClickHandler.call(self, event); });
+
+  this.selector.hover(IriSP.wrap(this, this.mouseOverHandler), IriSP.wrap(this, this.mouseOutHandler));
+
+  // update the positions
+  this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater));
+
+  // special messages :
+  this._Popcorn.listen("IriSP.PlayerWidget.MouseOver", IriSP.wrap(this, this.mouseOverHandler));
+  this._Popcorn.listen("IriSP.PlayerWidget.MouseOut", IriSP.wrap(this, this.mouseOutHandler));
+};
+
+/* update the slider and the position marker as time passes */
+IriSP.SliderWidget.prototype.sliderUpdater = function() {
+  if(this.draggingOngoing || this._disableUpdate)
+    return;
+  
+  var time = this._Popcorn.currentTime();
+
+  var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000;
+  var percent = ((time / duration) * 100).toFixed(2);
+  
+  /* we do these complicated calculations to center exactly
+     the position Marker */
+  var pixels_to_percents = 100 / this.selector.width(); /* how much is a pixel in percents */
+  var positionMarker_width = this.positionMarker.width();
+  var correction = (pixels_to_percents * positionMarker_width) / 2;
+
+  var newPos = percent - correction;
+  if (newPos <= 0)
+    newPos = 0;
+  
+	this.sliderForeground.css("width", percent + "%");
+	this.positionMarker.css("left", newPos + "%");
+
+};
+
+IriSP.SliderWidget.prototype.backgroundClickHandler = function(event) {
+  /* this piece of code is a little bit convoluted - here's how it works :
+     we want to handle clicks on the progress bar and convert those to seeks in the media.
+     However, jquery only gives us a global position, and we want a number of pixels relative
+     to our container div, so we get the parent position, and compute an offset to this position,
+     and finally compute the progress ratio in the media.
+     Finally we multiply this ratio with the duration to get the correct time
+  */
+
+  var parentOffset = this.sliderBackground.parent().offset();
+  var width = this.sliderBackground.width();
+  var relX = event.pageX - parentOffset.left;
+
+  var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000;
+  var newTime = ((relX / width) * duration).toFixed(2);
+
+  this._Popcorn.currentTime(newTime);
+};
+
+/* same function as the previous one, except that it handles clicks
+   on the foreground element */
+IriSP.SliderWidget.prototype.foregroundClickHandler = function(event) {
+  var parentOffset = this.sliderForeground.parent().offset();
+  var width = this.sliderBackground.width();
+  var relX = event.pageX - parentOffset.left;
+
+  var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000;
+  var newTime = ((relX / width) * duration).toFixed(2);
+
+  this._Popcorn.currentTime(newTime);
+};
+
+/* handles mouse over the slider */
+IriSP.SliderWidget.prototype.mouseOverHandler = function(event) {
+  
+  if (this.timeOutId !== null) {
+    window.clearTimeout(this.timeOutId);
+  }
+ 
+  this.sliderMaximized = true;
+
+  this.sliderBackground.animate({"height": "9px"}, 100);
+  this.sliderForeground.animate({"height": "9px"}, 100);
+  this.positionMarker.animate({"height": "9px", "width": "9px"}, 100);
+  //this.positionMarker.css("margin-top", "-4px");
+  
+//  this.selector.removeClass("Ldt-SliderMinimized");
+//  this.selector.addClass("Ldt-SliderMaximized");
+};
+
+/* handles when the mouse leaves the slider */
+IriSP.SliderWidget.prototype.mouseOutHandler = function(event) {
+
+  this.timeOutId = window.setTimeout(IriSP.wrap(this, this.minimizeOnTimeout),
+                                     IriSP.widgetsDefaults.SliderWidget.minimize_period);
+};
+
+IriSP.SliderWidget.prototype.minimizeOnTimeout = function(event) {
+  this.sliderBackground.animate({"height": "5px"}, 100);
+  this.sliderForeground.animate({"height": "5px"}, 100);
+  this.positionMarker.animate({"height": "5px", "width": "5px"}, 100);
+  this.positionMarker.css("margin-top", "0px");
+  this.sliderMinimized = true;
+  
+//  this.selector.removeClass("Ldt-SliderMaximized");
+//  this.selector.addClass("Ldt-SliderMinimized");
+
+};
+
+// called when the user starts dragging the position indicator
+IriSP.SliderWidget.prototype.positionMarkerDraggingStartedHandler = function(event, ui) {  
+  this.draggingOngoing = true;
+};
+
+IriSP.SliderWidget.prototype.positionMarkerDraggedHandler = function(event, ui) {   
+  this._disableUpdate = true; // disable slider position updates while dragging is ongoing.
+  window.setTimeout(IriSP.wrap(this, function() { this._disableUpdate = false; }), 500);
+
+  var parentOffset = this.sliderForeground.parent().offset();
+  var width = this.sliderBackground.width();
+  var relX = event.pageX - parentOffset.left;
+
+  var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000;
+  var newTime = ((relX / width) * duration).toFixed(2);
+
+  this._Popcorn.currentTime(newTime);
+  
+  this.draggingOngoing = false;
+};
+
+/** @class The constructor for the sparkline widget */
+IriSP.SparklineWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+
+  this._oldAnnotation = null;
+  
+};
+
+
+IriSP.SparklineWidget.prototype = new IriSP.Widget();
+
+IriSP.SparklineWidget.prototype.clear = function() {
+
+};
+
+/** draw the sparkline using jquery sparkline */
+IriSP.SparklineWidget.prototype.draw = function() {
+  var templ = Mustache.to_html(IriSP.SparklineWidget_template, {width: this.width, height: this.height});
+  /** this widget uses three divs -
+    the first is the sparkline, which is generated by jquery sparkline,
+    the second is an overlay div to display the progression in the video,
+    and the third is a div to react to clicks
+  */
+    
+  /* we suppose that a column is 5 pixels wide */
+  var num_columns = (this.selector.width()) / 10;
+  var duration = +this._serializer.currentMedia().meta["dc:duration"];
+  var time_step = duration / num_columns; /* the time interval between two columns */
+  var results = [];
+  var i = 0; /* the index in the loop */  
+
+  /* this algorithm makes one assumption : that the array is sorted 
+     (it's done for us by the JSONSerializer). We go through the array 
+     and count how many comments fall within a peculiar time piece.
+     As i is preserved between each iteration, it's O(n).
+  */
+  
+  for(var j = 0; j < num_columns && i < this._serializer._data.annotations.length; j++) {    
+    var count = 0;
+    var annotation_begin = +(this._serializer._data.annotations[i].begin);
+    
+    while(annotation_begin >= j * time_step && annotation_begin <= (j + 1) * time_step ) {
+      count++;
+      i++;
+      if (i >= this._serializer._data.annotations.length)
+        break;
+        
+      annotation_begin = +(this._serializer._data.annotations[i].begin);
+      
+    }
+    
+    results.push(count);
+  }
+
+  
+  this.selector.append(templ);
+  this.selector.find(".Ldt-sparkLine").css("background", "#c7c8cc");
+  this.selector.find(".Ldt-sparkLine").sparkline(results, {lineColor: "#7492b4", fillColor: "#aeaeb8",
+                                                           spotColor: "#b70056",
+                                                           width: this.width, height: this.height});
+  this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeUpdateHandler));
+  IriSP.jQuery(".Ldt-sparkLineClickOverlay").click(IriSP.wrap(this, this.clickHandler));  
+};
+
+/** react to a timeupdate event */
+IriSP.SparklineWidget.prototype.timeUpdateHandler = function() {
+  var currentTime = this._Popcorn.currentTime();  
+  var duration = +this._serializer.currentMedia().meta["dc:duration"] / 1000;
+  var proportion = ((currentTime / duration) * 100).toFixed(4);
+  
+  IriSP.jQuery(".Ldt-sparkLinePositionMarker").css("width", proportion + "%");                                    
+}
+
+/** handle clicks on the widget */
+IriSP.SparklineWidget.prototype.clickHandler = function(event) {
+  /* this piece of code is a little bit convoluted - here's how it works :
+     we want to handle clicks on the progress bar and convert those to seeks in the media.
+     However, jquery only gives us a global position, and we want a number of pixels relative
+     to our container div, so we get the parent position, and compute an offset to this position,
+     and finally compute the progress ratio in the media.
+     Finally we multiply this ratio with the duration to get the correct time
+  */
+
+  var parentOffset = this.selector.offset();
+  var width = this.selector.width();
+  var relX = event.pageX - parentOffset.left;
+
+  var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000;
+  var newTime = ((relX / width) * duration).toFixed(2);
+  
+  
+  this._Popcorn.trigger("IriSP.SparklineWidget.clicked", newTime);
+  this._Popcorn.currentTime(newTime);                                 
+};/* this widget displays a small tooltip */
+IriSP.TooltipWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+  this._shown = false;
+  this._displayedText = "";
+  this._hideTimeout = -1;
+};
+
+
+IriSP.TooltipWidget.prototype = new IriSP.Widget();
+
+IriSP.TooltipWidget.prototype.draw = function() {
+  var templ = Mustache.to_html(IriSP.tooltipWidget_template);
+  // position the widget absolutely relative to document.
+  this.selector.css("position", "static");
+  this.selector.append(templ);
+  this.hide();
+
+};
+
+IriSP.TooltipWidget.prototype.clear = function() {
+	this.selector.find(".tiptext").text("");
+};
+
+IriSP.TooltipWidget.prototype.show = function(text, color, x, y) {
+
+  if (this._displayedText == text && this._shown)
+    return;
+
+  this.selector.find(".tipcolor").css("background-color", color);
+  this._displayedText = text;
+	this.selector.find(".tiptext").text(text);
+  //this.selector.find(".tip").css("left", x).css("top", y);  
+  this.selector.find(".tip").css("left", x).css("top", y);
+  this.selector.find(".tip").show();
+  this._shown = true;
+};
+
+IriSP.TooltipWidget.prototype.hide = function() {                                                   
+  this.selector.find(".tip").hide();
+  this._shown = false;  
+};/* a widget that displays tweet - used in conjunction with the polemicWidget */
+
+IriSP.TweetsWidget = function(Popcorn, config, Serializer) {
+  IriSP.Widget.call(this, Popcorn, config, Serializer);
+
+  this._displayingTweet = false;
+  this._timeoutId = undefined; 
+  this._hidden = false; /* hidden means that the createAnnotationWidget is shown */
+};
+
+
+IriSP.TweetsWidget.prototype = new IriSP.Widget();
+
+
+IriSP.TweetsWidget.prototype.drawTweet = function(annotation) {
+    if (this._hidden)
+      return;
+    
+    var title = IriSP.formatTweet(annotation.content.title);
+    var img = annotation.content.img.src;
+    if (typeof(img) === "undefined" || img === "" || img === "None") {
+      img = IriSP.widgetsDefaults.TweetsWidget.default_profile_picture;
+    }
+
+    var imageMarkup = IriSP.templToHTML("<img src='{{src}}' alt='user image'></img>", 
+                                       {src : img});
+    
+    if (typeof(annotation.meta["dc:source"].content) !== "undefined") {
+      var tweetContents = JSON.parse(annotation.meta["dc:source"].content);
+      var creator = tweetContents.user.screen_name;
+      var real_name = tweetContents.user.name;
+
+      imageMarkup = IriSP.templToHTML("<a href='http://twitter.com/{{creator}}'><img src='{{src}}' alt='user image'></img></a>", 
+                                       {src : img, creator: creator});
+            
+      var formatted_date = new Date(tweetContents.created_at).toLocaleDateString();
+      title = IriSP.templToHTML("<a class='Ldt-tweet_userHandle' href='http://twitter.com/{{creator}}'>@{{creator}}</a> - " + 
+                                "<div class='Ldt-tweet_realName'>{{real_name}}</div>" +
+                                "<div class='Ldt-tweet_tweetContents'>{{{ contents }}}</div>" +
+                                "<div class='Ldt-tweet_date'>{{ date }}</div>", 
+                                {creator: creator, real_name: real_name, contents : title, date : formatted_date});
+
+      this.selector.find(".Ldt-TweetReply").attr("href", "http://twitter.com/home?status=@" + creator + ":%20");
+
+
+      var rtText = Mustache.to_html("http://twitter.com/home?status=RT @{{creator}}: {{text}}",
+                                    {creator: creator, text: IriSP.encodeURI(annotation.content.title)});
+      this.selector.find(".Ldt-Retweet").attr("href", rtText);
+    }
+
+    this.selector.find(".Ldt-tweetContents").html(title);
+    this.selector.find(".Ldt-tweetAvatar").html(imageMarkup);
+    this.selector.show("blind", 250); 
+};
+
+IriSP.TweetsWidget.prototype.displayTweet = function(annotation) {
+  if (this._displayingTweet === false) {
+    this._displayingTweet = true;
+  } else {
+    window.clearTimeout(this._timeoutId);
+  }
+
+  this.drawTweet(annotation);
+
+  var time = this._Popcorn.currentTime();  
+  this._timeoutId = window.setTimeout(IriSP.wrap(this, this.clearPanel), IriSP.widgetsDefaults.TweetsWidget.tweet_display_period);
+};
+
+
+IriSP.TweetsWidget.prototype.clearPanel = function() {  
+    this._displayingTweet = false;
+    this._timeoutId = undefined;
+    this.closePanel();
+    
+};
+
+IriSP.TweetsWidget.prototype.closePanel = function() {
+    if (this._timeoutId != undefined) {
+      /* we're called from the "close window" link */
+      /* cancel the timeout */
+      window.clearTimeout(this._timeoutId);
+      this._timeoutId = null;
+    }
+    
+    this.selector.hide("blind", 400);
+    
+};
+
+/* cancel the timeout if the user clicks on the keep panel open button */
+IriSP.TweetsWidget.prototype.keepPanel = function() {
+    if (this._timeoutId != undefined) {
+      /* we're called from the "close window" link */
+      /* cancel the timeout */
+      window.clearTimeout(this._timeoutId);
+      this._timeoutId = null;
+    }
+};
+
+IriSP.TweetsWidget.prototype.draw = function() {
+  var _this = this;
+  
+  var tweetMarkup = IriSP.templToHTML(IriSP.tweetWidget_template, {"share_template" : IriSP.share_template});
+  this.selector.append(tweetMarkup);
+  this.selector.hide();
+  this.selector.find(".Ldt-tweetWidgetMinimize").click(IriSP.wrap(this, this.closePanel));
+  this.selector.find(".Ldt-tweetWidgetKeepOpen").click(IriSP.wrap(this, this.keepPanel));
+  
+  this._Popcorn.listen("IriSP.PolemicTweet.click", IriSP.wrap(this, this.PolemicTweetClickHandler));
+  this._Popcorn.listen("IriSP.PlayerWidget.AnnotateButton.clicked", 
+                        IriSP.wrap(this, this.handleAnnotateSignal));  
+};
+
+IriSP.TweetsWidget.prototype.PolemicTweetClickHandler = function(tweet_id) {  
+  var index, annotation;
+  for (index in this._serializer._data.annotations) {
+    annotation = this._serializer._data.annotations[index];
+    
+    if (annotation.id === tweet_id)
+      break;
+  }
+    
+  if (annotation.id !== tweet_id)
+      /* we haven't found it */
+      return;
+  
+  this.displayTweet(annotation);
+  return;
+};
+
+/** handle clicks on the annotate button by hiding/showing itself */
+IriSP.TweetsWidget.prototype.handleAnnotateSignal = function() {
+  if (this._hidden == false) {
+    this.selector.hide();
+    this._hidden = true;
+  } else {
+    if (this._displayingTweet !== false)
+      this.selector.show();
+      
+    
+    this._hidden = false;
+  }
+};/** @class This class implement a serializer for the JSON-Cinelab format
+    @params DataLoader a dataloader reference
+    @url the url from which to get our cinelab
+ */
+IriSP.JSONSerializer = function(DataLoader, url) {
+  IriSP.Serializer.call(this, DataLoader, url);
+};
+
+IriSP.JSONSerializer.prototype = new IriSP.Serializer();
+
+/** serialize data */
+IriSP.JSONSerializer.prototype.serialize = function(data) {
+  return JSON.stringify(data);
+};
+
+/** deserialize data */
+IriSP.JSONSerializer.prototype.deserialize = function(data) {
+  return JSON.parse(data);
+};
+
+/** load JSON-cinelab data and also sort the annotations by start time
+    @param callback function to call when the data is ready.
+ */
+IriSP.JSONSerializer.prototype.sync = function(callback) {
+  /* we don't have to do much because jQuery handles json for us */
+
+  var self = this;
+
+  var fn = function(data) {      
+      self._data = data;  
+      if (typeof(self._data["annotations"]) === "undefined" ||
+          self._data["annotations"] === null)
+          self._data["annotations"] = [];
+      
+      // sort the data too       
+      self._data["annotations"].sort(function(a, b) 
+          { var a_begin = +a.begin;
+            var b_begin = +b.begin;
+            return a_begin - b_begin;
+          });
+     
+      callback(data);      
+  };
+  
+  this._DataLoader.get(this._url, fn);
+};
+
+/** @return the metadata about the media being read FIXME: always return the first media. */
+IriSP.JSONSerializer.prototype.currentMedia = function() {  
+  return this._data.medias[0]; /* FIXME: don't hardcode it */
+};
+
+/** searches for an annotation which matches title, description and keyword 
+   "" matches any field. 
+   Note: it ignores tweets.
+   @return a list of matching ids.
+*/    
+IriSP.JSONSerializer.prototype.searchAnnotations = function(title, description, keyword) {
+    /* we can have many types of annotations. We want search to only look for regular segments */
+    /* the next two lines are a bit verbose because for some test data, _serializer.data.view is either
+       null or undefined.
+    */
+    var view;
+
+    if (typeof(this._data.views) !== "undefined" && this._data.views !== null)
+       view = this._data.views[0];
+
+    var searchViewType = "";
+
+    if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) {
+            searchViewType = view.annotation_types[0];
+    }
+
+    var filterfn = function(annotation) {
+      if( searchViewType  != "" && 
+          typeof(annotation.meta) !== "undefined" && 
+          typeof(annotation.meta["id-ref"]) !== "undefined" &&
+          annotation.meta["id-ref"] !== searchViewType) {
+        return true; // don't pass
+      } else {
+          return false;
+      }
+    };
+
+    return this.searchAnnotationsFilter(title, description, keyword, filterfn);
+
+};
+
+/* only look for tweets */
+IriSP.JSONSerializer.prototype.searchTweets = function(title, description, keyword) {
+    /* we can have many types of annotations. We want search to only look for regular segments */
+    /* the next two lines are a bit verbose because for some test data, _serializer.data.view is either
+       null or undefined.
+    */
+    var view;
+
+    if (typeof(this._data.views) !== "undefined" && this._data.views !== null)
+       view = this._data.views[0];
+
+    var searchViewType = "";
+
+    if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) {
+            searchViewType = view.annotation_types[0];
+    }
+
+    var filterfn = function(annotation) {
+      if( searchViewType  != "" && 
+          typeof(annotation.meta) !== "undefined" && 
+          typeof(annotation.meta["id-ref"]) !== "undefined" &&
+          annotation.meta["id-ref"] !== searchViewType) {
+        return false; // pass
+      } else {
+          return true;
+      }
+    };
+
+    return this.searchAnnotationsFilter(title, description, keyword, filterfn);
+
+};
+
+/**
+  search an annotation according to its title, description and keyword
+  @param filter a function to filter the results with. Used to select between annotation types.
+ */    
+IriSP.JSONSerializer.prototype.searchAnnotationsFilter = function(title, description, keyword, filter) {
+
+    var rTitle;
+    var rDescription;
+    var rKeyword;
+    /* match anything if given the empty string */
+    if (title == "")
+      title = ".*";
+    if (description == "")
+      description = ".*";
+    if (keyword == "")
+      keyword = ".*";
+    
+    rTitle = new RegExp(title, "i");  
+    rDescription = new RegExp(description, "i");  
+    rKeyword = new RegExp(keyword, "i");  
+    
+    var ret_array = [];
+    
+    var i;
+    for (i in this._data.annotations) {
+      var annotation = this._data.annotations[i];
+      
+      /* filter the annotations whose type is not the one we want */
+      if (filter(annotation)) {
+          continue;
+      }
+      
+      if (rTitle.test(annotation.content.title) && 
+          rDescription.test(annotation.content.description)) {
+          /* FIXME : implement keyword support */
+          ret_array.push(annotation);
+      }
+    }
+    
+    return ret_array;
+};
+
+/** breaks a string in words and searches each of these words. Returns an array
+   of objects with the id of the annotation and its number of occurences.
+   
+   @param searchString a string of words.
+   FIXME: optimize ? seems to be n^2 in the worst case.
+*/
+IriSP.JSONSerializer.prototype.searchOccurences = function(searchString) {
+  var ret = { };
+  var keywords = searchString.split(/\s+/);
+  
+  for (var i in keywords) {
+    var keyword = keywords[i];
+    
+    // search this keyword in descriptions and title
+    var found_annotations = []
+    found_annotations = found_annotations.concat(this.searchAnnotations(keyword, "", ""));
+    found_annotations = found_annotations.concat(this.searchAnnotations("", keyword, ""));
+    
+    for (var j in found_annotations) {
+      var current_annotation = found_annotations[j];
+      
+      if (!ret.hasOwnProperty(current_annotation.id)) {
+        ret[current_annotation.id] = 1;
+      } else {
+        ret[current_annotation.id] += 1;
+      }
+      
+    }
+
+  };
+  
+  return ret;
+};
+
+/** breaks a string in words and searches each of these words. Returns an array
+   of objects with the id of the annotation and its number of occurences.
+   
+   FIXME: optimize ? seems to be n^2 in the worst case.
+*/
+IriSP.JSONSerializer.prototype.searchTweetsOccurences = function(searchString) {
+  var ret = { };
+  var keywords = searchString.split(/\s+/);
+  
+  for (var i in keywords) {
+    var keyword = keywords[i];
+    
+    // search this keyword in descriptions and title
+    var found_annotations = []
+    found_annotations = found_annotations.concat(this.searchTweets(keyword, "", ""));
+    found_annotations = found_annotations.concat(this.searchTweets("", keyword, ""));
+    
+    for (var j in found_annotations) {
+      var current_annotation = found_annotations[j];
+      
+      if (!ret.hasOwnProperty(current_annotation.id)) {
+        ret[current_annotation.id] = 1;
+      } else {
+        ret[current_annotation.id] += 1;
+      }
+      
+    }
+
+  };
+  
+  return ret;
+};
+
+/** returns all the annotations that are displayable at the moment 
+   NB: only takes account the first type of annotations - ignores tweets 
+   currentTime is in seconds.
+   
+   @param currentTime the time at which we search.
+   @param (optional) the if of the type of the annotations we want to get.
+ */
+
+IriSP.JSONSerializer.prototype.currentAnnotations = function(currentTime, id) {
+  var view;
+  var currentTimeMs = 1000 * currentTime;
+
+  if (typeof(id) === "undefined") {
+      var legal_ids = this.getNonTweetIds();
+  } else {
+      legal_ids = [id];
+  }
+  
+  var ret_array = [];
+  
+  var i;
+  
+  for (i in this._data.annotations) {
+    var annotation = this._data.annotations[i];
+    
+    if (IriSP.underscore.include(legal_ids, annotation.meta["id-ref"]) && 
+        annotation.begin <= currentTimeMs &&
+        annotation.end >= currentTimeMs)
+          ret_array.push(annotation);
+  }
+ 
+  if (ret_array == []) {
+    console.log("ret_array empty, ", legal_ids);
+  }
+  
+  return ret_array;
+};
+
+
+/** returns a list of ids of tweet lines (aka: groups in cinelab) */
+IriSP.JSONSerializer.prototype.getTweetIds = function() {
+  if (typeof(this._data.lists) === "undefined" || this._data.lists === null)
+    return [];
+
+  var tweetsId = [];
+  
+  /* first get the list containing the tweets */
+  var tweets = IriSP.underscore.filter(this._data.lists, function(entry) { return entry.id.indexOf("tweet") !== -1 });
+  
+  if (tweets.length === 0)
+    return [];
+  
+  // FIXME: collect tweets from multiple sources ?
+  tweetsId = IriSP.underscore.pluck(tweets[0].items, "id-ref");
+
+  return tweetsId;
+};
+
+/** this function returns a list of lines which are not tweet lines */
+IriSP.JSONSerializer.prototype.getNonTweetIds = function() {
+  if (typeof(this._data.lists) === "undefined" || this._data.lists === null)
+    return [];
+  
+  /* complicated : for each list in this._data.lists, get the id-ref.
+     flatten the returned array because pluck returns a string afterwards.
+  */
+  var ids = IriSP.underscore.flatten(IriSP.underscore.map(this._data.lists, function(entry) {                                                         
+                                                         return IriSP.underscore.pluck(entry.items, "id-ref"); }));
+                                                         
+  var illegal_values = this.getTweetIds();
+  return IriSP.underscore.difference(ids, illegal_values);
+  
+};
+
+/** return the id of the ligne de temps which contains name
+    @param name of the ligne de temps
+*/
+IriSP.JSONSerializer.prototype.getId = function(name) {
+  if (typeof(this._data.lists) === "undefined" || this._data.lists === null)
+    return;
+
+  var e;
+  /* first get the list containing the tweets */
+  e = IriSP.underscore.find(this._data["annotation-types"], 
+                                  function(entry) { return (entry["dc:title"].indexOf(name) !== -1) });
+  
+  if (typeof(e) === "undefined")
+    return;
+    
+  var id = e.id;
+
+  return id;
+};
+
+/** return the id of the ligne de temps named "Chapitrage" */
+IriSP.JSONSerializer.prototype.getChapitrage = function() {
+  return this.getId("Chapitrage");
+};
+
+/** return the id of the ligne de temps named "Tweets" */
+IriSP.JSONSerializer.prototype.getTweets = function() {
+  return this.getId("Tweets");
+};
+
+/** return the id of the ligne de temps named "Contributions" */
+IriSP.JSONSerializer.prototype.getContributions = function() {
+  return this.getId("Contributions");
+};
--- a/src/ldt/ldt/static/ldt/js/LdtPlayer.min.js	Thu Jan 12 10:13:00 2012 +0100
+++ b/src/ldt/ldt/static/ldt/js/LdtPlayer.min.js	Thu Jan 12 10:19:47 2012 +0100
@@ -16,72 +16,203 @@
  *	The fact that you are presently reading this means that you have had
  *	knowledge of the CeCILL-C license and that you accept its terms.
 */
-if(window.__IriSP===undefined)var __IriSP={};__IriSP.traceNum=0;__IriSP.trace=function(a,b){if(__IriSP.config.gui.debug===true){__IriSP.traceNum+=1;__IriSP.jQuery("<div>"+__IriSP.traceNum+" - "+a+" : "+b+"</div>").appendTo("#Ldt-output")}};__IriSP.config=undefined;
-__IriSP.configDefault={metadata:{format:"cinelab",src:"",load:"jsonp"},gui:{width:650,height:0,mode:"radio",container:"LdtPlayer",debug:false,css:"../src/css/LdtPlayer.css"},player:{type:"jwplayer",src:"../res/swf/player.swf",params:{allowfullscreen:"true",allowscriptaccess:"always",wmode:"transparent"},flashvars:{streamer:"streamer",file:"file",live:"true",autostart:"false",controlbar:"none",playerready:"__IriSP.playerReady"},attributes:{id:"Ldtplayer1",name:"Ldtplayer1"}},module:null};
-__IriSP.lib={jQuery:"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js",jQueryUI:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.min.js",jQueryToolTip:"http://cdn.jquerytools.org/1.2.4/all/jquery.tools.min.js",swfObject:"http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js",cssjQueryUI:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css"};__IriSP.LdtShareTool="\n<a onclick=\"__IriSP.MyApiPlayer.share('delicious');\" title='partager avec delicious'><span class='share shareDelicious'>&nbsp;</span></a>\n<a onclick=\"__IriSP.MyApiPlayer.share('facebook');\" title='partager avec facebook'> <span class='share shareFacebook'>&nbsp;</span></a>\n<a onclick=\"__IriSP.MyApiPlayer.share('twitter');\" title='partager avec twitter'>  <span class='share shareTwitter'>&nbsp;</span></a>\n<a onclick=\"__IriSP.MyApiPlayer.share('myspace');\" title='partager avec Myspace'>  <span class='share shareMySpace'>&nbsp;</span></a>";
-__IriSP.MyLdt=null;__IriSP.MyTags=null;__IriSP.MyApiPlayer=null;__IriSP.player=null;__IriSP.Durration=null;__IriSP.playerLdtWidth=null;__IriSP.playerLdtHeight=null;
-__IriSP.init=function(a){function b(){var h=document.createElement("script");h.setAttribute("type","text/javascript");h.setAttribute("src",__IriSP.lib.jQueryToolTip);h.onload=c;h.onreadystatechange=function(){if(this.readyState=="complete"||this.readyState=="loaded")c("jquery.tools.min.js loded")};var i=document.createElement("script");i.setAttribute("type","text/javascript");i.setAttribute("src",__IriSP.lib.swfObject);i.onload=c;i.onreadystatechange=function(){if(this.readyState=="complete"||this.readyState==
-"loaded")c("swfobject.js loded")};var j=document.createElement("script");j.setAttribute("type","text/javascript");j.setAttribute("src",__IriSP.lib.jQueryUI);j.onload=c;j.onreadystatechange=function(){if(this.readyState=="complete"||this.readyState=="loaded")c("jquery-ui.min.js loded")};(document.getElementsByTagName("head")[0]||document.documentElement).appendChild(h);(document.getElementsByTagName("head")[0]||document.documentElement).appendChild(j);(document.getElementsByTagName("head")[0]||document.documentElement).appendChild(i)}
-function c(){e+=1;e===3&&d()}function d(){__IriSP.jQuery=window.jQuery.noConflict(true);__IriSP.jQuery(document).ready(function(h){var i=__IriSP.jQuery("<link>",{rel:"stylesheet",type:"text/css",href:__IriSP.lib.cssjQueryUI,"class":"dynamic_css"}),j=__IriSP.jQuery("<link>",{rel:"stylesheet",type:"text/css",href:__IriSP.config.gui.css,"class":"dynamic_css"});i.appendTo("head");j.appendTo("head");h.browser.msie&&h(".dynamic_css").clone().appendTo("head");__IriSP.createMyHtml();__IriSP.jQuery.ajax({dataType:__IriSP.config.metadata.load,
-url:f,success:function(g){__IriSP.trace("ajax","success");if(g==="")alert("ERREUR DE CHARGEMENT JSON");else{new __IriSP.Media(g.medias[0].id,g.medias[0].href,g.medias[0].meta["dc:duration"],g.medias[0]["dc:title"],g.medias[0]["dc:description"]);__IriSP.trace("__IriSP.MyApiPlayer",__IriSP.config.gui.width+"   "+__IriSP.config.gui.height+" "+g.medias[0].href+" "+g.medias[0].meta["dc:duration"]+" "+g.medias[0].meta.item.value);__IriSP.MyApiPlayer=new __IriSP.APIplayer(__IriSP.config.gui.width,__IriSP.config.gui.height,
-g.medias[0].href,g.medias[0].meta["dc:duration"],g.medias[0].meta.item.value);__IriSP.trace("__IriSP.init.main","__IriSP.Ligne");__IriSP.MyLdt=new __IriSP.Ligne(g["annotation-types"][0].id,g["annotation-types"][0]["dc:title"],g["annotation-types"][0]["dc:description"],g.medias[0].meta["dc:duration"]);__IriSP.trace("__IriSP.init.main","__IriSP.Tags");__IriSP.MyTags=new __IriSP.Tags(g.tags);__IriSP.jQuery.each(g.annotations,function(l,k){k.meta["id-ref"]==__IriSP.MyLdt.id&&__IriSP.MyLdt.addAnnotation(k.id,
-k.begin,k.end,k.media,k.content.title,k.content.description,k.content.color,k.tags)});__IriSP.jQuery.each(g.lists,function(){__IriSP.trace("lists","")});__IriSP.jQuery.each(g.views,function(){__IriSP.trace("views","")})}},error:function(g){alert("ERROR : "+g)}})})}if(a===null)__IriSP.config=__IriSP.configDefault;else{__IriSP.config=a;if(__IriSP.config.player.params==null)__IriSP.config.player.params=__IriSP.configDefault.player.params;if(__IriSP.config.player.flashvars==null)__IriSP.config.player.flashvars=
-__IriSP.configDefault.player.flashvars;if(__IriSP.config.player.attributes==null)__IriSP.config.player.attributes=__IriSP.configDefault.player.attributes}var f=__IriSP.config.metadata.src;__IriSP.jQuery=null;if(window.jQuery===undefined||window.jQuery.fn.jquery!=="1.4.2"){a=document.createElement("script");a.setAttribute("type","text/javascript");a.setAttribute("src",__IriSP.lib.jQuery);a.onload=b;a.onreadystatechange=function(){if(this.readyState=="complete"||this.readyState=="loaded")b()};(document.getElementsByTagName("head")[0]||
-document.documentElement).appendChild(a)}else{__IriSP.jQuery=window.jQuery;b()}var e=0};
-__IriSP.createMyHtml=function(){var a=__IriSP.config.gui.width,b=__IriSP.config.gui.height-20;__IriSP.trace("__IriSP.createMyHtml",__IriSP.config.gui.container);if(__IriSP.config.gui.mode=="radio"){__IriSP.jQuery("#"+__IriSP.config.gui.container).before("<div id='LdtSearchContainer'  style='margin-left:445px;position:absolute;'>\n<div id='LdtSearch' style='display:none;background-color:#EEE;width:165px;boder:1px;border-color:#CFCFCF;position:absolute;text-align:center;'><input id='LdtSearchInput' style='margin-top:2px;margin-bottom:2px;' /></div>\t\n</div>\n <div class='cleaner'></div>");__IriSP.trace("__IriSP.createHtml",
-__IriSP.config.gui.container);__IriSP.jQuery("<div id='Ldt-Root'>\n\t<div id='Ldt-PlaceHolder'>\n\t\t<a href='http://www.adobe.com/go/getflashplayer'>Get flash</a> to see this player\t\n\t</div>\n\t<div id='Ldt-controler' class='demo'>\n\t\t<div class='Ldt-Control1' >\n\t\t\t<button id='ldt-CtrlPlay' onclick='__IriSP.MyApiPlayer.play()'>Lecture / Pause </button>\n\t\t\t<button id='ldt-CtrlNext' onclick='__IriSP.MyLdt.nextAnnotation()'>Suivant</button>\n\t\t</div>\n\t\t<div id='Ldt-Annotations' class='ui-slider'>\n\t\t\t<div id='slider-range-min'></div>\n\t</div>\n\t\t<div class='Ldt-Control2'>\n\t\t\t<button id='ldt-CtrlLink'  onclick='__IriSP.searchblock()'> Rechercher </button>\n\t\t\t<button id='ldt-CtrlSound' onclick='__IriSP.MyApiPlayer.mute()'>Sound</button>\n\t\t</div>\n  <div class='cleaner'>&nbsp;</div> \n  <div id='Ldt-Show-Arrow-container'>\n  \t<div id='Ldt-Show-Arrow'> </div>\n  </div>\n</div>\n<div>\n <div id='ldt-Show'> </div>\n\t<div id='Ldt-ShowAnnotation-audio' class='demo' >\n\t\t<div id='Ldt-SaTitle'></div>\n\t\t<div id='Ldt-SaDescription'></div>\n \t\t<div class='cleaner'><!--&nbsp;--\></div>\n </div>\n <div id='Ldt-SaKeyword'>\n <div id='Ldt-SaKeywordText'>  </div>\n <div class='cleaner'></div>\n <div id='Ldt-SaShareTools'>\n \n "+
-__IriSP.LdtShareTool+"\n \n  </div>\n <div class='cleaner'></div></div>  </div><div id='Ldt-output' style='clear:left;float:none;position:relative;height:200px;width:"+a+"px;overflow:scroll;' ></div>").appendTo("#"+__IriSP.config.gui.container);if(__IriSP.jQuery.browser.msie==true&&__IriSP.jQuery.browser.version=="7.0"){__IriSP.jQuery("#Ldt-Root").css("padding-top","25px");__IriSP.trace("__IriSP.createHtml","IE7 SPECIAL ")}}else __IriSP.config.gui.mode=="video"&&__IriSP.jQuery("<div id='LdtSearchContainer'  style='margin-top:"+
-b+"px;margin-left:445px;position:absolute;'>\n<div id='LdtSearch' style='background-color:#EEE;display:none;width:165px;boder:1px;border-color:#CFCFCF;position:absolute;text-align:center;z-index:999;'><input id='LdtSearchInput' style='margin-top:2px;margin-bottom:2px;' /></div>\t\n</div>\n<div id='Ldt-Root'>\n\t<div id='Ldt-PlaceHolder'>\n\t\t<a href='http://www.adobe.com/go/getflashplayer'>Get flash</a> to see this player\t\n\t</div>\n\t<div id='Ldt-controler' class='demo'>\n\t\t<div class='Ldt-Control1' >\n\t\t\t<button id='ldt-CtrlPlay' onclick='__IriSP.MyApiPlayer.play()'>Lecture / Pause </button>\n\t\t\t<button id='ldt-CtrlNext' onclick='__IriSP.MyLdt.nextAnnotation()'>Suivant</button>\n\t\t</div>\n\t\t<div id='Ldt-Annotations' class='ui-slider'>\n\t\t\t<div id='slider-range-min'></div>\n\t</div>\n\t\t<div class='Ldt-Control2'>\n\t\t\t<button id='ldt-CtrlLink'  onclick='__IriSP.searchblock()'> Rechercher </button>\n\t\t\t<button id='ldt-CtrlSound' onclick='__IriSP.MyApiPlayer.mute()'>Sound</button>\n\t\t</div>\n  <div class='cleaner'>&nbsp;</div> \n  <div id='Ldt-Show-Arrow-container'>\n  \t<div id='Ldt-Show-Arrow'> </div>\n  </div>\n</div>\n<div>\n <div id='ldt-Show'> </div>\n\t<div id='Ldt-ShowAnnotation-audio' class='demo' >\n\t\t<div id='Ldt-SaTitle'></div>\n\t\t<div id='Ldt-SaDescription'></div>\n \t\t<div class='cleaner'><!--&nbsp;--\></div>\n </div>\n <div id='Ldt-SaKeyword'>\n <div id='Ldt-SaKeywordText'>  </div>\n <div class='cleaner'></div>\n <div id='Ldt-SaShareTools'>\n \n "+
-__IriSP.LdtShareTool+"\n \n  </div>\n <div class='cleaner'></div></div>  </div><div id='Ldt-output'></div>").appendTo("#"+__IriSP.config.gui.container);__IriSP.trace("__IriSP.createHtml",__IriSP.jQuery.browser.msie+" "+__IriSP.jQuery.browser.version);__IriSP.trace("__IriSP.createHtml","end");__IriSP.jQuery("#Ldt-Annotations").width(a-150);__IriSP.jQuery("#Ldt-Show-Arrow-container").width(a-150);__IriSP.jQuery("#Ldt-ShowAnnotation-audio").width(a-10);__IriSP.jQuery("#Ldt-ShowAnnotation-video").width(a-
-10);__IriSP.jQuery("#Ldt-SaKeyword").width(a-10);__IriSP.jQuery("#Ldt-controler").width(a-10);__IriSP.jQuery("#Ldt-Control").attr("z-index","100");__IriSP.jQuery("#Ldt-controler").hide();__IriSP.jQuery("<div id='Ldt-load-container'><div id='Ldt-loader'>&nbsp;</div> Chargement... </div>").appendTo("#Ldt-ShowAnnotation-audio");__IriSP.config.gui.mode=="radio"&&__IriSP.jQuery("#Ldt-load-container").attr("width",__IriSP.config.gui.width);__IriSP.config.gui.debug===true?__IriSP.jQuery("#Ldt-output").show():
-__IriSP.jQuery("#Ldt-output").hide()};__IriSP.Media=function(a,b,c,d,f){this.id=a;this.url=b;this.title=d;this.description=f;this.duration=c;this.lignes=[];__IriSP.trace("__IriSP.Media","Media ID : "+a);__IriSP.trace("__IriSP.Media","Media URL : "+b);__IriSP.trace("__IriSP.Media","Media title : "+d)};__IriSP.Media.prototype.createPlayerMedia=function(a,b,c,d){__IriSP.MyApiPlayer=new __IriSP.APIplayer(a,b,this.url,this.duration,c,d)};__IriSP.Media.prototype.getMediaDuration=function(){return this.duration};
-__IriSP.Media.prototype.getMediaTitle=function(){return this.title};
-__IriSP.createInterface=function(a,b,c){__IriSP.jQuery("#Ldt-controler").show();__IriSP.trace("__IriSP.createInterface",a+","+b+","+c+",");__IriSP.jQuery("#Ldt-ShowAnnotation").click(function(){});__IriSP.jQuery("#Ldt-PlaceHolder").attr("top");__IriSP.jQuery("#Ldt-PlaceHolder").attr("left");__IriSP.jQuery("#slider-range-min").slider({value:0,min:1,max:c/1E3,step:0.1,slide:function(d,f){__IriSP.MyApiPlayer.seek(f.value)}});__IriSP.trace("__IriSP.createInterface","ICI");__IriSP.jQuery("#amount").val(__IriSP.jQuery("#slider-range-min").slider("value")+
-" s");__IriSP.jQuery(".Ldt-Control1 button:first").button({icons:{primary:"ui-icon-play"},text:false}).next().button({icons:{primary:"ui-icon-seek-next"},text:false});__IriSP.jQuery(".Ldt-Control2 button:first").button({icons:{primary:"ui-icon-search"},text:false}).next().button({icons:{primary:"ui-icon-volume-on"},text:false});__IriSP.trace("__IriSP.createInterface","ICI2");__IriSP.jQuery("#ldt-CtrlPlay").attr("style","background-color:#CD21C24;");__IriSP.jQuery("#Ldt-load-container").hide();__IriSP.config.gui.mode==
-"radio"&__IriSP.jQuery.browser.msie!=true&&__IriSP.jQuery("#Ldtplayer1").attr("height","0");__IriSP.trace("__IriSP.createInterface","3");__IriSP.trace("__IriSP.createInterface","END")};__IriSP.APIplayer=function(a,b,c,d,f,e){this.hashchangeUpdate=this.player=null;this.width=a;this.height=b;this.url=c;this.duration=d;this.streamerPath=f;this.MySwfPath=e;__IriSP.MyApiPlayer=this;__IriSP.createPlayer(this.url,this.streamerPath);__IriSP.trace("__IriSP.APIplayer","__IriSP.createPlayer")};
-__IriSP.APIplayer.prototype.ready=function(){__IriSP.createInterface(this.width,this.height,this.duration);if(window.addEventListener)window.addEventListener("hashchange",function(){var a=__IriSP.retrieveTimeFragment(window.location.href);__IriSP.trace("__IriSP.APIplayer.prototype.ready",a);if(__IriSP.MyApiPlayer.hashchangeUpdate==null)__IriSP.MyApiPlayer.seek(a);else __IriSP.MyApiPlayer.hashchangeUpdate=null},false);else window.attachEvent&&window.attachEvent("onhashchange",function(){__IriSP.trace("hashchange",
-a);var a=__IriSP.retrieveTimeFragment(window.location.href);if(__IriSP.MyApiPlayer.hashchangeUpdate==null)__IriSP.MyApiPlayer.seek(a);else __IriSP.MyApiPlayer.hashchangeUpdate=null},false);__IriSP.jQuery("#LdtSearchInput").keydown(function(){__IriSP.Search(this.value)});__IriSP.jQuery("#LdtSearchInput").keyup(function(){__IriSP.Search(this.value)})};__IriSP.APIplayer.prototype.pause=function(){this.hashchangeUpdate=true;__IriSP.player.sendEvent("PAUSE")};
-__IriSP.APIplayer.prototype.play=function(){this.hashchangeUpdate=true;if(__IriSP.config.player.type=="jwplayer")__IriSP.player.sendEvent("PLAY");else if(__IriSP.config.player.type=="dailymotion"||__IriSP.config.player.type=="youtube"){var a=__IriSP.player.getPlayerState();__IriSP.trace("__IriSP.APIplayer.prototype.play.status",a);a!=1?__IriSP.player.playVideo():__IriSP.player.pauseVideo()}};
-__IriSP.APIplayer.prototype.mute=function(){__IriSP.player.sendEvent("MUTE");__IriSP.jQuery(".ui-icon-volume-on").css("background-position")=="-144px -160px"?__IriSP.jQuery(".ui-icon-volume-on").css("background-position","-130px -160px"):__IriSP.jQuery(".ui-icon-volume-on").css("background-position","-144px -160px")};
-__IriSP.APIplayer.prototype.share=function(a){var b=encodeURIComponent("J'\u00e9coute Les Retours du Dimanche : "),c=window.location.href,d;if(a=="facebook")d="http://www.facebook.com/share.php?u=";else if(a=="twitter")d="http://twitter.com/home?status="+b;else if(a=="myspace")d="http://www.myspace.com/Modules/PostTo/Pages/?u=";else if(a=="delicious")d="http://delicious.com/save?url=";else if(a=="JameSpot")d="http://www.jamespot.com/?action=spotit&u=";window.open(d+encodeURIComponent(c))};
-__IriSP.APIplayer.prototype.seek=function(a){if(a==0)a=1;__IriSP.trace("__IriSP.APIplayer.prototype.seek",a);if(__IriSP.config.player.type=="jwplayer")__IriSP.player.sendEvent("SEEK",a);else if(__IriSP.config.player.type=="dailymotion"||__IriSP.config.player.type=="youtube")__IriSP.player.seekTo(a);this.changePageUrlOffset(a)};__IriSP.APIplayer.prototype.update=function(a){if(a!=0){this.hashchangeUpdate=true;__IriSP.trace("__IriSP.APIplayer.prototype.update",a);__IriSP.player.sendEvent("SEEK",a)}};
-__IriSP.APIplayer.prototype.changePageUrlOffset=function(a){__IriSP.trace("__IriSP.APIplayer.prototype.changePageUrlOffset","CHANGE URL "+a);window.location.hash="#t="+a;window.location.href=window.location.href};__IriSP.jumpToTimeoffset=function(a){__IriSP.MyApiPlayer.changePageUrlOffset(a.time.value)};__IriSP.retrieveTimeFragment=function(a){var b=0,c=0;if(a.split("#")[1]!=null){b=a.split("#")[1];if(b.substring(2)!=null)c=b.substring(2)}return c};
-__IriSP.ignoreTimeFragment=function(a){if(a.split("#")[1]!=null)var b=a.split("#")[0];return b};__IriSP.currentPosition=0;__IriSP.currentVolume=50;__IriSP.player=null;__IriSP.startPosition=null;__IriSP.firstplay=false;
-__IriSP.createPlayer=function(a,b){if(__IriSP.config.player.type=="dailymotion")__IriSP.config.player.src+="&chromeless=1&enableApi=1";else if(__IriSP.config.player.type=="youtube")__IriSP.config.player.src+="&enablejsapi=1&version=3";__IriSP.trace("__IriSP.createPlayer","start");__IriSP.myUrlFragment=a.split(b);var c=__IriSP.jQuery.extend(true,{},__IriSP.config);c.player.flashvars.autostart="true";c.player.flashvars.streamer=b;c.player.flashvars.file=__IriSP.myUrlFragment[1];var d=c.player.flashvars,
-f=c.player.params;c=c.player.attributes;__IriSP.trace("__IriSP.createPlayer","SWFOBJECT src:"+__IriSP.config.player.src+" "+__IriSP.config.gui.width+" "+__IriSP.config.gui.height);swfobject.embedSWF(__IriSP.config.player.src,"Ldt-PlaceHolder",__IriSP.config.gui.width,__IriSP.config.gui.height,"9.0.115",false,d,f,c)};
-__IriSP.playerReady=function(a){__IriSP.player=window.document[a.id];__IriSP.MyApiPlayer.ready(__IriSP.player);a=__IriSP.retrieveTimeFragment(document.location.href);__IriSP.startPosition=a;__IriSP.addListeners()};
-__IriSP.addListeners=function(){if(__IriSP.player){__IriSP.trace("__IriSP.addListeners","ADD  Listener ");__IriSP.player.addModelListener("TIME","__IriSP.positionListener");__IriSP.player.addControllerListener("VOLUME","__IriSP.volumeListener");__IriSP.player.addModelListener("STATE","__IriSP.stateMonitor")}else __IriSP.setTimeout("__IriSP.addListeners()",100)};
-__IriSP.stateMonitor=function(a){if(a.newstate=="PAUSED"){__IriSP.trace("__IriSP.stateMonitor","PAUSE");__IriSP.MyApiPlayer.changePageUrlOffset(__IriSP.currentPosition);__IriSP.jQuery(".ui-icon-play").css("background-position","0px -160px")}else if(a.newstate=="PLAYING"){__IriSP.trace("__IriSP.stateMonitor","PLAYING "+__IriSP.startPosition);if(__IriSP.config.player.flashvars.autostart=="false"&&__IriSP.firstplay==false&&__IriSP.startPosition==0){__IriSP.trace("__IriSP.stateMonitor","first stop ???");
-__IriSP.MyApiPlayer.play();__IriSP.firstplay=true;__IriSP.MyLdt.checkTime(1)}if(__IriSP.startPosition!=null){__IriSP.MyApiPlayer.update(__IriSP.startPosition);__IriSP.startPosition=null}__IriSP.jQuery(".ui-icon-play").css("background-position","-16px -160px")}else a.newstate=="BUFFERING"&&__IriSP.trace("__IriSP.stateMonitor","BUFFERING : "+__IriSP.config.player.flashvars.autostart)};
-__IriSP.positionListener=function(a){__IriSP.currentPosition=a.position;var b=document.getElementById("posit");if(b)b.innerHTML="position: "+__IriSP.currentPosition;__IriSP.jQuery("#slider-range-min").slider("value",a.position);__IriSP.jQuery("#amount").val(a.position+" s");__IriSP.MyLdt.checkTime(__IriSP.currentPosition)};__IriSP.volumeListener=function(a){__IriSP.currentVolume=a.percentage;if(a=document.getElementById("vol"))a.innerHTML="volume: "+__IriSP.currentVolume};
-onDailymotionPlayerReady=function(a){__IriSP.player=document.getElementById(__IriSP.config.player.attributes.id);__IriSP.MyApiPlayer.ready(__IriSP.player);var b=__IriSP.retrieveTimeFragment(document.location.href);__IriSP.startPosition=b;__IriSP.DailymotionAddListeners();__IriSP.MyApiPlayer.ready(a)};
-__IriSP.DailymotionAddListeners=function(){if(__IriSP.player){__IriSP.trace("__IriSP.addListeners","ADD  Listener ");setTimeout("__IriSP.DailymotionPositionListener()",100);__IriSP.DailymotionPositionListener();__IriSP.player.addModelListener("VOLUME","__IriSP.volumeListener")}else __IriSP.setTimeout("__IriSP.DailymotionAddListeners()",100)};
-__IriSP.DailymotionPositionListener=function(){__IriSP.currentPosition=__IriSP.player.getCurrentTime();__IriSP.jQuery("#slider-range-min").slider("value",__IriSP.currentPosition);__IriSP.jQuery("#amount").val(__IriSP.currentPosition+" s");setTimeout("__IriSP.DailymotionPositionListener()",10)};
-onYouTubePlayerReady=function(){var a=__IriSP.retrieveTimeFragment(document.location.href);__IriSP.player=document.getElementById(__IriSP.config.player.attributes.id);__IriSP.startPosition=a;__IriSP.MyApiPlayer.ready(__IriSP.player);__IriSP.MyApiPlayer.seek(a);__IriSP.MyApiPlayer.play();__IriSP.YouTubeAddListeners();__IriSP.trace("onYouTubePlayerReady=",a)};
-__IriSP.YouTubeAddListeners=function(){if(__IriSP.player){__IriSP.trace("__IriSP.addListeners","ADD  Listener ");__IriSP.player.addEventListener("onStateChange","__IriSP.YouTubeStateMonitor");setTimeout("__IriSP.YouTubePositionListener()",100);__IriSP.player.addModelListener("VOLUME","__IriSP.volumeListener")}else __IriSP.setTimeout("__IriSP.YouTubePositionListener()",100)};
-__IriSP.YouTubePositionListener=function(){__IriSP.currentPosition=__IriSP.player.getCurrentTime();__IriSP.MyLdt.checkTime(__IriSP.currentPosition);__IriSP.jQuery("#slider-range-min").slider("value",__IriSP.currentPosition);__IriSP.jQuery("#amount").val(__IriSP.currentPosition+" s");__IriSP.MyLdt.checkTime(__IriSP.currentPosition);setTimeout("__IriSP.YouTubePositionListener()",10)};
-__IriSP.YouTubeStateMonitor=function(){__IriSP.player.addModelListener("__IriSP.YouTubeStateMonitor ",newstate);if(newstate=="2"){__IriSP.trace("__IriSP.stateMonitor","PAUSE");__IriSP.MyApiPlayer.changePageUrlOffset(__IriSP.currentPosition)}else if(newstate=="1"){if(__IriSP.startPosition!=null){__IriSP.MyApiPlayer.update(__IriSP.startPosition);__IriSP.startPosition=null}}else if(newstate=="-1"){if(__IriSP.startPosition!=null){__IriSP.MyApiPlayer.update(__IriSP.startPosition);__IriSP.startPosition=
-null}}else newstate=="3"&&__IriSP.trace("__IriSP.stateMonitor","BUFFERING : ")};__IriSP.stripHtml=function(a){return a.replace(/\\&/g,"&amp;").replace(/\\</g,"&lt;").replace(/\\>/g,"&gt;").replace(/\\t/g,"&nbsp;&nbsp;&nbsp;").replace(/\\n/g,"<br />").replace(/'/g,"&#39;").replace(/"/g,"&quot;")};__IriSP.DEC_HEXA_COLOR=function(a){for(var b="",c;a>15;){c=a-Math.floor(a/16)*16;b="0123456789ABCDEF".charAt(c)+b;a=Math.floor(a/16)}b="0123456789ABCDEF".charAt(a)+b;if(b=="FFCC00")b="";return b};
-__IriSP.SearchOldValue="";__IriSP.searchblockOpen=false;
-__IriSP.searchblock=function(){__IriSP.trace("__IriSP.searchblock",__IriSP.searchblockOpen);if(__IriSP.searchblockOpen==false){__IriSP.jQuery(".ui-icon-search").css("background-position","-144px -112px");__IriSP.jQuery("#LdtSearch").show(250);__IriSP.jQuery("#LdtSearchInput").css("background-color","#fff");__IriSP.jQuery("#LdtSearchInput").focus();__IriSP.jQuery("#LdtSearchInput").attr("value",__IriSP.SearchOldValue);__IriSP.Search(__IriSP.SearchOldValue);__IriSP.searchblockOpen=true}else{__IriSP.SearchOldValue=
-__IriSP.jQuery("#LdtSearchInput").attr("value");__IriSP.jQuery("#LdtSearchInput").attr("value","");__IriSP.SearchClean();__IriSP.jQuery(".ui-icon-search").css("background-position","-160px -112px");__IriSP.jQuery("#LdtSearch").hide(250);__IriSP.searchblockOpen=false}};
-__IriSP.Search=function(a){annotations=__IriSP.LDTligne.annotations;__IriSP.trace("__IriSP.Search",annotations.length+" "+a);var b=0,c=0,d=0;__IriSP.trace(a,a.length);var f=a.toLowerCase();__IriSP.trace("__IriSP.Search",annotations.length+" "+f);if(f.length>=3){for(var e=0;e<annotations.length;++e){annotation=annotations[e];__IriSP.jQuery("#output2").text(annotation.title+" ?= "+a);chaine1=annotation.title.toLowerCase();chaine2=annotation.description.toLowerCase();chaine3=annotation.htmlTags.toLowerCase();
-if(chaine1.indexOf(f,0)!=-1)b+=1;if(chaine2.indexOf(f,0)!=-1)b+=1;if(chaine3.indexOf(f,0)!=-1)b+=1;c+=b;if(b>0){d=b*8;__IriSP.jQuery("#"+annotation.id).dequeue();__IriSP.jQuery("#"+annotation.id).animate({height:d},200);__IriSP.jQuery("#"+annotation.id).css("border","2px");__IriSP.jQuery("#"+annotation.id).css("border-color","red");__IriSP.jQuery("#"+annotation.id).animate({opacity:0.6},200);__IriSP.trace("!!!!!!!!!!!!!!!!!!"," ?= "+annotation.id);__IriSP.jQuery("#LdtSearchInput").css("background-color",
-"#e1ffe1")}else{__IriSP.jQuery("#"+annotation.id).dequeue();__IriSP.jQuery("#"+annotation.id).animate({height:0},250);__IriSP.jQuery("#"+annotation.id).animate({opacity:0.3},200)}b=0}c==0&&__IriSP.jQuery("#LdtSearchInput").css("background-color","#f6f6f6")}else if(a.length==0){__IriSP.SearchClean();__IriSP.jQuery("#LdtSearchInput").css("background-color","#fff")}else{__IriSP.SearchClean();__IriSP.jQuery("#LdtSearchInput").css("background-color","#f6f6f6")}};
-__IriSP.SearchClean=function(){annotations=__IriSP.LDTligne.annotations;for(var a=0;a<annotations.length;++a){annotation=annotations[a];__IriSP.jQuery("#"+annotation.id).dequeue();__IriSP.jQuery("#"+annotation.id).animate({height:0},100);__IriSP.jQuery("#"+annotation.id).css("border","0px");__IriSP.jQuery("#"+annotation.id).css("border-color","red");__IriSP.jQuery("#"+annotation.id).animate({opacity:0.3},100)}};__IriSP.SearchCleanString=function(a){var b=RegExp("(chien)","g");a.replace(b,"");return a};
-__IriSP.SearchThisSegment=function(a){__IriSP.jQuery("#LdtSearchInput").text(a.title);__IriSP.trace("__IriSP.Ligne.prototype.checkTimeLigne",a.title)};__IriSP.LDTligne=null;__IriSP.Ligne=function(a,b,c,d){this.id=a;this.title=b;this.description=c;this.annotations=[];this.duration=d;this.annotationOldRead="";__IriSP.LDTligne=this;__IriSP.trace("__IriSP.Ligne","CREATE "+__IriSP.LDTligne)};
-__IriSP.Ligne.prototype.addAnnotation=function(a,b,c,d,f,e,h,i){this.annotations.push(new __IriSP.Annotation(a,b,c,d,f,e,h,i,this.duration))};__IriSP.Ligne.prototype.onClickLigneAnnotation=function(){};__IriSP.Ligne.prototype.searchLigneAnnotation=function(){};__IriSP.Ligne.prototype.listAnnotations=function(){};
-__IriSP.Ligne.prototype.nextAnnotation=function(){var a=this.numAnnotation(this.annotationOldRead)+1,b=this.annotations[a];if(a<this.annotations.length-1){__IriSP.player.sendEvent("SEEK",b.begin/1E3);__IriSP.trace("LIGNE  ","| next = "+a+" - "+this.annotations.length+" | seek :"+b.begin/1E3)}else __IriSP.player.sendEvent("SEEK",this.annotations[0].begin/1E3)};__IriSP.Ligne.prototype.numAnnotation=function(a){for(var b=0;b<this.annotations.length;++b)if(a==this.annotations[b])return b};
-__IriSP.Ligne.prototype.checkTime=function(a){for(var b=-1,c=0;c<this.annotations.length;++c){b=this.annotations[c];if(a>b.begin/1E3&&a<b.end/1E3){if(b!=this.annotationOldRead){this.annotationOldRead=b;__IriSP.jQuery("#Ldt-SaTitle").text(b.title);__IriSP.jQuery("#Ldt-SaDescription").text(b.description);__IriSP.jQuery("#Ldt-SaKeywordText").html("Mots clefs : "+b.htmlTags);a=b.timeToPourcent(b.begin*1+(b.end*1-b.begin*1)/2,b.duration*1);__IriSP.jQuery("#Ldt-Show-Arrow").animate({left:a+"%"},1E3);__IriSP.jQuery("#"+
-b.id).animate({alpha:"100%"},1E3);__IriSP.ignoreTimeFragment(window.location.href)}break}else b=-1}if(b==-1)if(b!=this.annotationOldRead){__IriSP.trace("Check : ","pas d'annotation ici ");__IriSP.jQuery("#Ldt-SaTitle").text("");__IriSP.jQuery("#Ldt-SaDescription").text("");__IriSP.jQuery("#Ldt-SaKeywordText").html("");__IriSP.jQuery("#Ldt-ShowAnnotation").slideUp();this.annotationOldRead&&__IriSP.jQuery("#"+this.annotationOldRead.id).animate({alpha:"70%"},1E3);this.annotationOldRead=b}};
-__IriSP.Annotation=function(){__IriSP.trace("annotation ","r\u00e9ussi")};__IriSP.Annotation=function(a,b,c,d,f,e,h,i,j){this.id=a;this.begin=b;this.end=c;this.media=d;this.description=e;this.title=f;this.color=h;this.tags=i;this.htmlTags="";this.duration=j;this.draw();this.drawTags();__IriSP.trace("Annotation created : ",a)};
-__IriSP.Annotation.prototype.draw=function(){var a=this.timeToPourcent(this.begin,this.duration),b=this.timeToPourcent(this.end,this.duration)-a,c=this.title.substr(0,55);__IriSP.jQueryAnnotationTemplate="<div title='"+__IriSP.stripHtml(c)+"' id='"+this.id+"'  class='ui-slider-range ui-slider-range-min ui-widget-header iri-chapter' width='100%' style=\"left:"+a+"%; width:"+b+"%; padding-top:15px; border-left:solid 1px #aaaaaa; border-right:solid 1px #aaaaaa; background:#"+__IriSP.DEC_HEXA_COLOR(this.color)+
-';" onClick="__IriSP.MyApiPlayer.seek(\''+Math.round(this.begin/1E3)+"');__IriSP.jQuery('#Ldt-ShowAnnotation').slideDown();\"    ></div> ";__IriSP.jQuerytoolTipTemplate="<div class='Ldt-tooltip'><div class='title'>"+__IriSP.stripHtml(this.title)+"</div><div class='time'>"+this.begin+" : "+this.end+"</div><div class='description'>"+__IriSP.stripHtml(this.description)+"</div></div>";__IriSP.jQuery("<div>"+__IriSP.jQueryAnnotationTemplate+"</div>").appendTo("#Ldt-Annotations");__IriSP.jQuery("#"+this.id).tooltip({effect:"slide"});
-__IriSP.jQuery("#"+this.id).fadeTo(0,0.3);__IriSP.jQuery("#"+this.id).mouseover(function(){__IriSP.jQuery("#"+this.id).animate({opacity:0.6},5)}).mouseout(function(){__IriSP.jQuery("#"+this.id).animate({opacity:0.3},5)});__IriSP.trace("__IriSP.Annotation.prototype.draw","ADD ANOTATION : "+this.begin+" "+this.end+" "+__IriSP.stripHtml(this.title)+" | "+a+" | "+b+" | duration = "+this.duration)};
-__IriSP.Annotation.prototype.drawTags=function(){if(this.tags!=undefined)for(var a=0;a<this.tags.length;++a)this.htmlTags+="<span> "+__IriSP.MyTags.getTitle(this.tags[a]["id-ref"])+" </span> , "};__IriSP.Annotation.prototype.tootTipAnnotation=function(){return this.color+" "+this.type+" apple"};__IriSP.Annotation.prototype.onRollOverAnnotation=function(){this.tootTip()};__IriSP.Annotation.prototype.timeToPourcent=function(a,b){return parseInt(Math.round(a/b*100))};
-__IriSP.Tags=function(a){this.myTags=a;this.htmlTags=null;this.weigthMax=0};__IriSP.Tags.prototype.addAnnotation=function(a){for(var b=0;b<this.myTags.length;++b){this.myTags[b].mySegments=[];if(a.tags!=null)for(var c=0;c<a.tags.length;++c)if(this.myTags[b].id==a.tags[c]["id-ref"]){this.myTags[b].mySegments.push([a.begin,a.end,a.id]);var d=this.myTags[b].mySegments.length;if(this.weigthMax<d)this.weigthMax=d}}};
-__IriSP.Tags.prototype.getTitle=function(a){for(var b=0;b<this.myTags.length;++b)if(this.myTags[b].id==a)return this.myTags[b].meta["dc:title"]};
-__IriSP.Tags.prototype.draw=function(){__IriSP.trace("__IriSP.Tags.prototype.draw"," !!! WELL START ");for(var a=0;a<this.myTags.length;++a){__IriSP.trace("__IriSP.Tags.prototype.draw"," ADD Tags : "+this.myTags[a].id);if(this.myTags[a].id!=null)this.htmlTags+="<span onclick=\"MyTags.show( '"+this.myTags[a].id+'\');" style="font-size:'+(this.myTags[a].mySegments.length/this.weigthMax*10+8)+'px;" alt="'+this.myTags[a].mySegments.length+'"> '+this.myTags[a].meta["dc:title"]+" </span> , "}__IriSP.jQuery("#Ldt-Tags").html(this.htmlTags);
-__IriSP.trace("__IriSP.Tags.prototype.draw"," !!!!  END WMAX= "+this.weigthMax)};
-__IriSP.Tags.prototype.show=function(a){for(var b=1.0E20,c=1.0E20,d=0,f=0,e=0;e<this.myTags.length;++e)if(this.myTags[e].id==a){__IriSP.trace("######### TAG DRAWing : "," END");for(var h=0;h<this.myTags[e].mySegments.length;++h){if(void 0>this.myTags[e].mySegments[h][0]){b=this.myTags[e].mySegments[h][0];c=this.myTags[e].mySegments[h][1]}if(void 0>this.myTags[e].mySegments[h][0]){d=this.myTags[e].mySegments[h][0];f=this.myTags[e].mySegments[h][1]}}}a=__IriSP.timeToPourcent(b*1+(c-b)/2,__IriSP.MyLdt.duration);
-d=__IriSP.timeToPourcent(d*1+(f-d)/2,__IriSP.MyLdt.duration)-a;__IriSP.jQuery("#Ldt-Show-Tags").css("left",a+"%");__IriSP.jQuery("#Ldt-Show-Tags").css("width",d+"%")};
\ No newline at end of file
+(function(a){function c(r,D){var F=/^\w+\:\/\//;if(/^\/\/\/?/.test(r))r=location.protocol+r;else if(!F.test(r)&&r.charAt(0)!="/")r=(D||"")+r;return F.test(r)?r:(r.charAt(0)=="/"?N:E)+r}function d(r,D){for(var F in r)if(r.hasOwnProperty(F))D[F]=r[F];return D}function i(r,D,F,L){r.onload=r.onreadystatechange=function(){if(!(r.readyState&&r.readyState!="complete"&&r.readyState!="loaded"||D[F])){r.onload=r.onreadystatechange=null;L()}}}function h(r){r.ready=r.finished=true;for(var D=0;D<r.finished_listeners.length;D++)r.finished_listeners[D]();
+r.ready_listeners=[];r.finished_listeners=[]}function m(r,D,F,L,U){setTimeout(function(){var b,e=D.real_src,g;if("item"in J){if(!J[0]){setTimeout(arguments.callee,25);return}J=J[0]}b=document.createElement("script");if(D.type)b.type=D.type;if(D.charset)b.charset=D.charset;if(U)if(f){r[o]&&H("start script preload: "+e);F.elem=b;if(B){b.preload=true;b.onpreload=L}else b.onreadystatechange=function(){b.readyState=="loaded"&&L()};b.src=e}else if(U&&e.indexOf(N)==0&&r[x]){g=new XMLHttpRequest;r[o]&&H("start script preload (xhr): "+
+e);g.onreadystatechange=function(){if(g.readyState==4){g.onreadystatechange=function(){};F.text=g.responseText+"\n//@ sourceURL="+e;L()}};g.open("GET",e);g.send()}else{r[o]&&H("start script preload (cache): "+e);b.type="text/cache-script";i(b,F,"ready",function(){J.removeChild(b);L()});b.src=e;J.insertBefore(b,J.firstChild)}else{if(z){r[o]&&H("start script load (ordered async): "+e);b.async=false}else r[o]&&H("start script load: "+e);i(b,F,"finished",L);b.src=e;J.insertBefore(b,J.firstChild)}},0)}
+function n(){function r(j,k,p){function w(){if(A!=null){A=null;h(p)}}var A;if(!e[k.src].finished){if(!j[q])e[k.src].finished=true;A=p.elem||document.createElement("script");if(k.type)A.type=k.type;if(k.charset)A.charset=k.charset;i(A,p,"finished",w);if(p.elem)p.elem=null;else if(p.text){A.onload=A.onreadystatechange=null;A.text=p.text}else A.src=k.real_src;J.insertBefore(A,J.firstChild);p.text&&w()}}function D(j,k,p,w){var A,M,R=function(){k.ready_cb(k,function(){r(j,k,A)})},T=function(){k.finished_cb(k,
+p)};k.src=c(k.src,j[v]);k.real_src=k.src+(j[s]?(/\?.*$/.test(k.src)?"&_":"?_")+~~(Math.random()*1E9)+"=":"");e[k.src]||(e[k.src]={items:[],finished:false});M=e[k.src].items;if(j[q]||M.length==0){A=M[M.length]={ready:false,finished:false,ready_listeners:[R],finished_listeners:[T]};m(j,k,A,w?function(){A.ready=true;for(var O=0;O<A.ready_listeners.length;O++)A.ready_listeners[O]();A.ready_listeners=[]}:function(){h(A)},w)}else{A=M[0];A.finished?T():A.finished_listeners.push(T)}}function F(){function j(K,
+G){A[o]&&H("script preload finished: "+K.real_src);K.ready=true;K.exec_trigger=G;p()}function k(K,G){A[o]&&H("script execution finished: "+K.real_src);K.ready=K.finished=true;K.exec_trigger=null;for(var P=0;P<G.scripts.length;P++)if(!G.scripts[P].finished)return;G.finished=true;p()}function p(){for(;R<M.length;)if(Object.prototype.toString.call(M[R])=="[object Function]"){A[o]&&H("$LAB.wait() executing: "+M[R]);try{M[R++]()}catch(K){A[o]&&u("$LAB.wait() error caught: ",K)}}else{if(!M[R].finished){for(var G=
+M[R],P=false,S=0;S<G.scripts.length;S++)if(G.scripts[S].ready&&G.scripts[S].exec_trigger){P=true;G.scripts[S].exec_trigger();G.scripts[S].exec_trigger=null}if(P)continue;break}R++}if(R==M.length)O=T=false}var w,A=d(L,{}),M=[],R=0,T=false,O;w={script:function(){for(var K=0;K<arguments.length;K++)(function(G,P){var S;Object.prototype.toString.call(G)=="[object Array]"||(P=[G]);for(var V=0;V<P.length;V++){if(!O||!O.scripts)M.push(O={scripts:[],finished:true});G=P[V];if(Object.prototype.toString.call(G)==
+"[object Function]")G=G();if(G)if(Object.prototype.toString.call(G)=="[object Array]"){S=[].slice.call(G);S.unshift(V,1);[].splice.apply(P,S);V--}else{if(typeof G=="string")G={src:G};G=d(G,{ready:false,ready_cb:j,finished:false,finished_cb:k});O.finished=false;O.scripts.push(G);D(A,G,O,U&&T);T=true;A[l]&&w.wait()}}})(arguments[K],arguments[K]);return w},wait:function(){if(arguments.length>0){for(var K=0;K<arguments.length;K++)M.push(arguments[K]);O=M[M.length-1]}else O=false;p();return w}};return{script:w.script,
+wait:w.wait,setOptions:function(K){d(K,A);return w}}}var L={},U=f||Q,b=[],e={},g;L[x]=true;L[l]=false;L[q]=false;L[s]=false;L[o]=false;L[v]="";return g={setGlobalDefaults:function(j){d(j,L);return g},setOptions:function(){return F().setOptions.apply(null,arguments)},script:function(){return F().script.apply(null,arguments)},wait:function(){return F().wait.apply(null,arguments)},queueScript:function(){b[b.length]={type:"script",args:[].slice.call(arguments)};return g},queueWait:function(){b[b.length]=
+{type:"wait",args:[].slice.call(arguments)};return g},runQueue:function(){for(var j=g,k=b.length,p;--k>=0;){p=b.shift();j=j[p.type].apply(null,p.args)}return j},noConflict:function(){a.$LAB=C;return g},sandbox:function(){return n()}}}var C=a.$LAB,x="UseLocalXHR",l="AlwaysPreserveOrder",q="AllowDuplicates",s="CacheBust",o="Debug",v="BasePath",E=/^[^?#]*\//.exec(location.href)[0],N=/^\w+\:\/\/\/?[^\/]+/.exec(E)[0],J=document.head||document.getElementsByTagName("head"),I=a.opera&&Object.prototype.toString.call(a.opera)==
+"[object Opera]"||"MozAppearance"in document.documentElement.style,H=function(){},u=H,y=document.createElement("script"),B=typeof y.preload=="boolean",f=B||y.readyState&&y.readyState=="uninitialized",z=!f&&y.async===true,Q=!f&&!z&&!I;if(a.console&&a.console.log){if(!a.console.error)a.console.error=a.console.log;H=function(r){a.console.log(r)};u=function(r,D){a.console.error(r,D)}}a.$LAB=n();(function(r,D,F){if(document.readyState==null&&document[r]){document.readyState="loading";document[r](D,F=function(){document.removeEventListener(D,
+F,false);document.readyState="complete"},false)}})("addEventListener","DOMContentLoaded")})(this);
+var Mustache=function(){function a(l){return String(l).replace(/&(?!\w+;)|[<>"']/g,function(q){return n[q]||q})}var c=Object.prototype.toString;Array.isArray=Array.isArray||function(l){return c.call(l)=="[object Array]"};var d=String.prototype.trim,i;if(d)i=function(l){return l==null?"":d.call(l)};else{var h,m;if(/\S/.test("\u00a0")){h=/^[\s\xA0]+/;m=/[\s\xA0]+$/}else{h=/^\s+/;m=/\s+$/}i=function(l){return l==null?"":l.toString().replace(h,"").replace(m,"")}}var n={"&":"&amp;","<":"&lt;",">":"&gt;",
+'"':"&quot;","'":"&#39;"},C={},x=function(){};x.prototype={otag:"{{",ctag:"}}",pragmas:{},buffer:[],pragmas_implemented:{"IMPLICIT-ITERATOR":true},context:{},render:function(l,q,s,o){if(!o){this.context=q;this.buffer=[]}if(!this.includes("",l))if(o)return l;else{this.send(l);return}l=this.render_pragmas(l);var v=this.render_section(l,q,s);if(v===false)v=this.render_tags(l,q,s,o);if(o)return v;else this.sendLines(v)},send:function(l){l!==""&&this.buffer.push(l)},sendLines:function(l){if(l){l=l.split("\n");
+for(var q=0;q<l.length;q++)this.send(l[q])}},render_pragmas:function(l){if(!this.includes("%",l))return l;var q=this,s=this.getCachedRegex("render_pragmas",function(o,v){return RegExp(o+"%([\\w-]+) ?([\\w]+=[\\w]+)?"+v,"g")});return l.replace(s,function(o,v,E){if(!q.pragmas_implemented[v])throw{message:"This implementation of mustache doesn't understand the '"+v+"' pragma"};q.pragmas[v]={};if(E){o=E.split("=");q.pragmas[v][o[0]]=o[1]}return""})},render_partial:function(l,q,s){l=i(l);if(!s||s[l]===
+undefined)throw{message:"unknown_partial '"+l+"'"};if(!q||typeof q[l]!="object")return this.render(s[l],q,s,true);return this.render(s[l],q[l],s,true)},render_section:function(l,q,s){if(!this.includes("#",l)&&!this.includes("^",l))return false;var o=this,v=this.getCachedRegex("render_section",function(E,N){return RegExp("^([\\s\\S]*?)"+E+"(\\^|\\#)\\s*(.+)\\s*"+N+"\n*([\\s\\S]*?)"+E+"\\/\\s*\\3\\s*"+N+"\\s*([\\s\\S]*)$","g")});return l.replace(v,function(E,N,J,I,H,u){E=N?o.render_tags(N,q,s,true):
+"";u=u?o.render(u,q,s,true):"";var y;I=o.find(I,q);if(J==="^")y=!I||Array.isArray(I)&&I.length===0?o.render(H,q,s,true):"";else if(J==="#")y=Array.isArray(I)?o.map(I,function(B){return o.render(H,o.create_context(B),s,true)}).join(""):o.is_object(I)?o.render(H,o.create_context(I),s,true):typeof I=="function"?I.call(q,H,function(B){return o.render(B,q,s,true)}):I?o.render(H,q,s,true):"";return E+y+u})},render_tags:function(l,q,s,o){var v=this,E=function(){return v.getCachedRegex("render_tags",function(H,
+u){return RegExp(H+"(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?"+u+"+","g")})},N=E(),J=function(H,u,y){switch(u){case "!":return"";case "=":v.set_delimiters(y);N=E();return"";case ">":return v.render_partial(y,q,s);case "{":case "&":return v.find(y,q);default:return a(v.find(y,q))}};l=l.split("\n");for(var I=0;I<l.length;I++){l[I]=l[I].replace(N,J,this);o||this.send(l[I])}if(o)return l.join("\n")},set_delimiters:function(l){l=l.split(" ");this.otag=this.escape_regex(l[0]);this.ctag=this.escape_regex(l[1])},escape_regex:function(l){if(!arguments.callee.sRE)arguments.callee.sRE=
+RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\)","g");return l.replace(arguments.callee.sRE,"\\$1")},find:function(l,q){function s(E){return E===false||E===0||E}l=i(l);var o;if(l.match(/([a-z_]+)\./ig)){var v=this.walk_context(l,q);if(s(v))o=v}else if(s(q[l]))o=q[l];else if(s(this.context[l]))o=this.context[l];if(typeof o=="function")return o.apply(q);if(o!==undefined)return o;return""},walk_context:function(l,q){for(var s=l.split("."),o=q[s[0]]!=undefined?q:this.context,v=o[s.shift()];v!=
+undefined&&s.length>0;){o=v;v=v[s.shift()]}if(typeof v=="function")return v.apply(o);return v},includes:function(l,q){return q.indexOf(this.otag+l)!=-1},create_context:function(l){if(this.is_object(l))return l;else{var q=".";if(this.pragmas["IMPLICIT-ITERATOR"])q=this.pragmas["IMPLICIT-ITERATOR"].iterator;var s={};s[q]=l;return s}},is_object:function(l){return l&&typeof l=="object"},map:function(l,q){if(typeof l.map=="function")return l.map(q);else{for(var s=[],o=l.length,v=0;v<o;v++)s.push(q(l[v]));
+return s}},getCachedRegex:function(l,q){var s=C[this.otag];s||(s=C[this.otag]={});var o=s[this.ctag];o||(o=s[this.ctag]={});(s=o[l])||(s=o[l]=q(this.otag,this.ctag));return s}};return{name:"mustache.js",version:"0.5.0-dev",to_html:function(l,q,s,o){var v=new x;if(o)v.send=o;v.render(l,q||{},s);if(!o)return v.buffer.join("\n")}}}();
+(function(){function a(b,e,g){if(b===e)return b!==0||1/b==1/e;if(b==null||e==null)return b===e;if(b._chain)b=b._wrapped;if(e._chain)e=e._wrapped;if(b.isEqual&&f.isFunction(b.isEqual))return b.isEqual(e);if(e.isEqual&&f.isFunction(e.isEqual))return e.isEqual(b);var j=l.call(b);if(j!=l.call(e))return false;switch(j){case "[object String]":return b==String(e);case "[object Number]":return b!=+b?e!=+e:b==0?1/b==1/e:b==+e;case "[object Date]":case "[object Boolean]":return+b==+e;case "[object RegExp]":return b.source==
+e.source&&b.global==e.global&&b.multiline==e.multiline&&b.ignoreCase==e.ignoreCase}if(typeof b!="object"||typeof e!="object")return false;for(var k=g.length;k--;)if(g[k]==b)return true;g.push(b);k=0;var p=true;if(j=="[object Array]"){if(k=b.length,p=k==e.length)for(;k--;)if(!(p=k in b==k in e&&a(b[k],e[k],g)))break}else{if("constructor"in b!="constructor"in e||b.constructor!=e.constructor)return false;for(var w in b)if(q.call(b,w)&&(k++,!(p=q.call(e,w)&&a(b[w],e[w],g))))break;if(p){for(w in e)if(q.call(e,
+w)&&!k--)break;p=!k}}g.pop();return p}var c=this,d=c._,i={},h=Array.prototype,m=Object.prototype,n=h.slice,C=h.concat,x=h.unshift,l=m.toString,q=m.hasOwnProperty,s=h.forEach,o=h.map,v=h.reduce,E=h.reduceRight,N=h.filter,J=h.every,I=h.some,H=h.indexOf,u=h.lastIndexOf;m=Array.isArray;var y=Object.keys,B=Function.prototype.bind,f=function(b){return new F(b)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=f;exports._=f}else typeof define==="function"&&
+define.amd?define("underscore",function(){return f}):c._=f;f.VERSION="1.2.3";var z=f.each=f.forEach=function(b,e,g){if(b!=null)if(s&&b.forEach===s)b.forEach(e,g);else if(b.length===+b.length)for(var j=0,k=b.length;j<k;j++){if(j in b&&e.call(g,b[j],j,b)===i)break}else for(j in b)if(q.call(b,j)&&e.call(g,b[j],j,b)===i)break};f.map=function(b,e,g){var j=[];if(b==null)return j;if(o&&b.map===o)return b.map(e,g);z(b,function(k,p,w){j[j.length]=e.call(g,k,p,w)});return j};f.reduce=f.foldl=f.inject=function(b,
+e,g,j){var k=arguments.length>2;b==null&&(b=[]);if(v&&b.reduce===v)return j&&(e=f.bind(e,j)),k?b.reduce(e,g):b.reduce(e);z(b,function(p,w,A){k?g=e.call(j,g,p,w,A):(g=p,k=true)});if(!k)throw new TypeError("Reduce of empty array with no initial value");return g};f.reduceRight=f.foldr=function(b,e,g,j){var k=arguments.length>2;b==null&&(b=[]);if(E&&b.reduceRight===E)return j&&(e=f.bind(e,j)),k?b.reduceRight(e,g):b.reduceRight(e);var p=f.toArray(b).reverse();j&&!k&&(e=f.bind(e,j));return k?f.reduce(p,
+e,g,j):f.reduce(p,e)};f.find=f.detect=function(b,e,g){var j;Q(b,function(k,p,w){if(e.call(g,k,p,w))return j=k,true});return j};f.filter=f.select=function(b,e,g){var j=[];if(b==null)return j;if(N&&b.filter===N)return b.filter(e,g);z(b,function(k,p,w){e.call(g,k,p,w)&&(j[j.length]=k)});return j};f.reject=function(b,e,g){var j=[];if(b==null)return j;z(b,function(k,p,w){e.call(g,k,p,w)||(j[j.length]=k)});return j};f.every=f.all=function(b,e,g){var j=true;if(b==null)return j;if(J&&b.every===J)return b.every(e,
+g);z(b,function(k,p,w){if(!(j=j&&e.call(g,k,p,w)))return i});return j};var Q=f.some=f.any=function(b,e,g){e||(e=f.identity);var j=false;if(b==null)return j;if(I&&b.some===I)return b.some(e,g);z(b,function(k,p,w){if(j||(j=e.call(g,k,p,w)))return i});return!!j};f.include=f.contains=function(b,e){var g=false;if(b==null)return g;return H&&b.indexOf===H?b.indexOf(e)!=-1:g=Q(b,function(j){return j===e})};f.invoke=function(b,e){var g=n.call(arguments,2);return f.map(b,function(j){return(e.call?e||j:j[e]).apply(j,
+g)})};f.pluck=function(b,e){return f.map(b,function(g){return g[e]})};f.max=function(b,e,g){if(!e&&f.isArray(b))return Math.max.apply(Math,b);if(!e&&f.isEmpty(b))return-Infinity;var j={computed:-Infinity};z(b,function(k,p,w){p=e?e.call(g,k,p,w):k;p>=j.computed&&(j={value:k,computed:p})});return j.value};f.min=function(b,e,g){if(!e&&f.isArray(b))return Math.min.apply(Math,b);if(!e&&f.isEmpty(b))return Infinity;var j={computed:Infinity};z(b,function(k,p,w){p=e?e.call(g,k,p,w):k;p<j.computed&&(j={value:k,
+computed:p})});return j.value};f.shuffle=function(b){var e=[],g;z(b,function(j,k){k==0?e[0]=j:(g=Math.floor(Math.random()*(k+1)),e[k]=e[g],e[g]=j)});return e};f.sortBy=function(b,e,g){return f.pluck(f.map(b,function(j,k,p){return{value:j,criteria:e.call(g,j,k,p)}}).sort(function(j,k){var p=j.criteria,w=k.criteria;return p<w?-1:p>w?1:0}),"value")};f.groupBy=function(b,e){var g={},j=f.isFunction(e)?e:function(k){return k[e]};z(b,function(k,p){var w=j(k,p);(g[w]||(g[w]=[])).push(k)});return g};f.sortedIndex=
+function(b,e,g){g||(g=f.identity);for(var j=0,k=b.length;j<k;){var p=j+k>>1;g(b[p])<g(e)?j=p+1:k=p}return j};f.toArray=function(b){return!b?[]:b.toArray?b.toArray():f.isArray(b)?n.call(b):f.isArguments(b)?n.call(b):f.values(b)};f.size=function(b){return f.toArray(b).length};f.first=f.head=function(b,e,g){return e!=null&&!g?n.call(b,0,e):b[0]};f.initial=function(b,e,g){return n.call(b,0,b.length-(e==null||g?1:e))};f.last=function(b,e,g){return e!=null&&!g?n.call(b,Math.max(b.length-e,0)):b[b.length-
+1]};f.rest=f.tail=function(b,e,g){return n.call(b,e==null||g?1:e)};f.compact=function(b){return f.filter(b,function(e){return!!e})};f.flatten=function(b,e){return f.reduce(b,function(g,j){if(f.isArray(j))return g.concat(e?j:f.flatten(j));g[g.length]=j;return g},[])};f.without=function(b){return f.difference(b,n.call(arguments,1))};f.uniq=f.unique=function(b,e,g){g=g?f.map(b,g):b;var j=[];f.reduce(g,function(k,p,w){if(0==w||(e===true?f.last(k)!=p:!f.include(k,p))){k[k.length]=p;j[j.length]=b[w]}return k},
+[]);return j};f.union=function(){return f.uniq(f.flatten(arguments,true))};f.intersection=f.intersect=function(b){var e=n.call(arguments,1);return f.filter(f.uniq(b),function(g){return f.every(e,function(j){return f.indexOf(j,g)>=0})})};f.difference=function(b){var e=f.flatten(n.call(arguments,1));return f.filter(b,function(g){return!f.include(e,g)})};f.zip=function(){for(var b=n.call(arguments),e=f.max(f.pluck(b,"length")),g=Array(e),j=0;j<e;j++)g[j]=f.pluck(b,""+j);return g};f.indexOf=function(b,
+e,g){if(b==null)return-1;var j;if(g)return g=f.sortedIndex(b,e),b[g]===e?g:-1;if(H&&b.indexOf===H)return b.indexOf(e);g=0;for(j=b.length;g<j;g++)if(g in b&&b[g]===e)return g;return-1};f.lastIndexOf=function(b,e){if(b==null)return-1;if(u&&b.lastIndexOf===u)return b.lastIndexOf(e);for(var g=b.length;g--;)if(g in b&&b[g]===e)return g;return-1};f.range=function(b,e,g){arguments.length<=1&&(e=b||0,b=0);g=arguments[2]||1;for(var j=Math.max(Math.ceil((e-b)/g),0),k=0,p=Array(j);k<j;){p[k++]=b;b+=g}return p};
+var r=function(){};f.bind=function(b,e){var g,j;if(b.bind===B&&B)return B.apply(b,n.call(arguments,1));if(!f.isFunction(b))throw new TypeError;j=n.call(arguments,2);return g=function(){if(!(this instanceof g))return b.apply(e,j.concat(n.call(arguments)));r.prototype=b.prototype;var k=new r,p=b.apply(k,j.concat(n.call(arguments)));return Object(p)===p?p:k}};f.bindAll=function(b){var e=n.call(arguments,1);e.length==0&&(e=f.functions(b));z(e,function(g){b[g]=f.bind(b[g],b)});return b};f.memoize=function(b,
+e){var g={};e||(e=f.identity);return function(){var j=e.apply(this,arguments);return q.call(g,j)?g[j]:g[j]=b.apply(this,arguments)}};f.delay=function(b,e){var g=n.call(arguments,2);return setTimeout(function(){return b.apply(b,g)},e)};f.defer=function(b){return f.delay.apply(f,[b,1].concat(n.call(arguments,1)))};f.throttle=function(b,e){var g,j,k,p,w,A=f.debounce(function(){w=p=false},e);return function(){g=this;j=arguments;k||(k=setTimeout(function(){k=null;w&&b.apply(g,j);A()},e));p?w=true:b.apply(g,
+j);A();p=true}};f.debounce=function(b,e){var g;return function(){var j=this,k=arguments;clearTimeout(g);g=setTimeout(function(){g=null;b.apply(j,k)},e)}};f.once=function(b){var e=false,g;return function(){if(e)return g;e=true;return g=b.apply(this,arguments)}};f.wrap=function(b,e){return function(){var g=C.apply([b],arguments);return e.apply(this,g)}};f.compose=function(){var b=arguments;return function(){for(var e=arguments,g=b.length-1;g>=0;g--)e=[b[g].apply(this,e)];return e[0]}};f.after=function(b,
+e){return b<=0?e():function(){if(--b<1)return e.apply(this,arguments)}};f.keys=y||function(b){if(b!==Object(b))throw new TypeError("Invalid object");var e=[],g;for(g in b)q.call(b,g)&&(e[e.length]=g);return e};f.values=function(b){return f.map(b,f.identity)};f.functions=f.methods=function(b){var e=[],g;for(g in b)f.isFunction(b[g])&&e.push(g);return e.sort()};f.extend=function(b){z(n.call(arguments,1),function(e){for(var g in e)e[g]!==void 0&&(b[g]=e[g])});return b};f.defaults=function(b){z(n.call(arguments,
+1),function(e){for(var g in e)b[g]==null&&(b[g]=e[g])});return b};f.clone=function(b){return!f.isObject(b)?b:f.isArray(b)?b.slice():f.extend({},b)};f.tap=function(b,e){e(b);return b};f.isEqual=function(b,e){return a(b,e,[])};f.isEmpty=function(b){if(f.isArray(b)||f.isString(b))return b.length===0;for(var e in b)if(q.call(b,e))return false;return true};f.isElement=function(b){return!!(b&&b.nodeType==1)};f.isArray=m||function(b){return l.call(b)=="[object Array]"};f.isObject=function(b){return b===
+Object(b)};f.isArguments=function(b){return l.call(b)=="[object Arguments]"};if(!f.isArguments(arguments))f.isArguments=function(b){return!(!b||!q.call(b,"callee"))};f.isFunction=function(b){return l.call(b)=="[object Function]"};f.isString=function(b){return l.call(b)=="[object String]"};f.isNumber=function(b){return l.call(b)=="[object Number]"};f.isNaN=function(b){return b!==b};f.isBoolean=function(b){return b===true||b===false||l.call(b)=="[object Boolean]"};f.isDate=function(b){return l.call(b)==
+"[object Date]"};f.isRegExp=function(b){return l.call(b)=="[object RegExp]"};f.isNull=function(b){return b===null};f.isUndefined=function(b){return b===void 0};f.noConflict=function(){c._=d;return this};f.identity=function(b){return b};f.times=function(b,e,g){for(var j=0;j<b;j++)e.call(g,j)};f.escape=function(b){return(""+b).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")};f.mixin=function(b){z(f.functions(b),function(e){U(e,
+f[e]=b[e])})};var D=0;f.uniqueId=function(b){var e=D++;return b?b+e:e};f.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};f.template=function(b,e){var g=f.templateSettings;g="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+b.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(g.escape,function(k,p){return"',_.escape("+p.replace(/\\'/g,"'")+"),'"}).replace(g.interpolate,function(k,p){return"',"+p.replace(/\\'/g,
+"'")+",'"}).replace(g.evaluate||null,function(k,p){return"');"+p.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";var j=new Function("obj","_",g);return e?j(e,f):function(k){return j.call(this,k,f)}};var F=function(b){this._wrapped=b};f.prototype=F.prototype;var L=function(b,e){return e?f(b).chain():b},U=function(b,e){F.prototype[b]=function(){var g=n.call(arguments);x.call(g,this._wrapped);return L(e.apply(f,
+g),this._chain)}};f.mixin(f);z("pop,push,reverse,shift,sort,splice,unshift".split(","),function(b){var e=h[b];F.prototype[b]=function(){e.apply(this._wrapped,arguments);return L(this._wrapped,this._chain)}});z(["concat","join","slice"],function(b){var e=h[b];F.prototype[b]=function(){return L(e.apply(this._wrapped,arguments),this._chain)}});F.prototype.chain=function(){this._chain=true;return this};F.prototype.value=function(){return this._wrapped}}).call(this);
+if(window.IriSP===undefined&&window.__IriSP===undefined)__IriSP=IriSP={};
+IriSP.loadLibs=function(a,c,d,i){IriSP.jQuery=null;var h=$LAB.script(a.jQuery).script(a.swfObject).wait().script(a.jQueryUI);if(c.player.type==="jwplayer")h=h.script(a.jwplayer);else{h=h.script(a.popcorn).script(a["popcorn.code"]);if(c.player.type==="youtube")h=h.script(a["popcorn.youtube"]);if(c.player.type==="vimeo")h=h.script(a["popcorn.vimeo"])}for(var m in c.gui.widgets){c.gui.widgets[m].type==="PolemicWidget"&&h.script(a.raphael);c.gui.widgets[m].type==="SparklineWidget"&&h.script(a.jquery_sparkline)}h.wait(function(){IriSP.jQuery=
+window.jQuery.noConflict(true);IriSP._=window._.noConflict();IriSP.underscore=IriSP._;var n=IriSP.jQuery("<link>",{rel:"stylesheet",type:"text/css",href:a.cssjQueryUI,"class":"dynamic_css"}),C=IriSP.jQuery("<link>",{rel:"stylesheet",type:"text/css",href:c.gui.css,"class":"dynamic_css"});n.appendTo("head");C.appendTo("head");IriSP.setupDataLoader();IriSP.__dataloader.get(d,function(x){IriSP.__jsonMetadata=x;i.call(window)})})};IriSP.SparklineWidget_template="<div class='Ldt-sparklineWidget' style='width: {{width}}px; height: {{height}}px'>    <div class='Ldt-sparkLinePositionMarker' style='width: 0px; height: {{height}}px'></div>    <div class='Ldt-sparkLineClickOverlay' style='width: {{width}}px; height: {{height}}px'></div>    <div class='Ldt-sparkLine' style='width: {{width}}px; height: {{height}}px'>Loading</div></div>";
+IriSP.annotation_template="{{! template for an annotation displayed in a segmentWidget }}<div title='{{divTitle}}' id='{{id}}'\tclass='Ldt-iri-chapter' \tstyle='left: {{startPixel}}px;          width: {{pxWidth}}px;          background-color:#{{hexa_color}};' \t></div>";IriSP.annotationWidget_template="{{! template for the annotation widget }}<div class='Ldt-AnnotationsWidget'>  <!-- ugly div because we want to have a double border --\>  <div class='Ldt-Annotation-DoubleBorder'>      <div class='Ldt-AnnotationContent'>        <div class='Ldt-AnnotationShareIcons'>         <a target='_blank' class='Ldt-fbShare' href=''><img src='{{img_dir}}/facebook.png' alt='share on facebook'></img></a>         <a target='_blank' class='Ldt-TwShare' href=''><img src='{{img_dir}}/twitter.png' alt='share on twitter'></img></a>         <a target='_blank'  class='Ldt-GplusShare' href=''><img src='{{img_dir}}/google.png' alt='share on google+'></img></a>      </div>\t\t  <div class='Ldt-SaTitle'></div>\t  \t<div class='Ldt-SaDescription'></div>    </div>  </div></div>";
+IriSP.annotation_loading_template="{{! template shown while the annotation widget is loading }}<div id='Ldt-load-container'><div id='Ldt-loader'>&nbsp;</div> Chargement... </div>";IriSP.annotationsListWidget_template="{{! template for the annotation list widget }}<div class='Ldt-AnnotationsListWidget'>  <!-- ugly div because we want to have a double border --\>  <div class='Ldt-Annotation-DoubleBorder'>    <ul>    {{#annotations}}      <li>        <a href='#a={{id}}'>          <div style='overflow: auto; margin-top: 5px; margin-bottom: 5px;'>            <div class='Ldt-AnnotationsList-Caption'>              <img src='http://i.imgur.com/aoUlC.jpg'></img>            </div>            <div class='Ldt-AnnotationsList-Duration'>{{begin}} - {{end}}</div>            <div class='Ldt-AnnotationsList-Title'>{{title}}</div>            <div class='Ldt-AnnotationsList-Description'>{{desc}}</div>          </div>        </a>      </li>    {{/annotations}}    </ul>  </div></div>";
+IriSP.arrowWidget_template="<div class='Ldt-arrowWidget'></div>";IriSP.createAnnotationWidget_template="{{! template for the annotation creation widget }}<div class='Ldt-createAnnotationWidget'>  <!-- ugly div because we want to have a double border --\>  <div class='Ldt-createAnnotation-DoubleBorder'>    <div style='margin-bottom: 7px; overflow: auto;'>      <div class='Ldt-createAnnotation-Title'></div>      <div class='Ldt-createAnnotation-TimeFrame'></div>    </div>        <div class='Ldt-createAnnotation-Container'>      <textarea class='Ldt-createAnnotation-Description'></textarea>      <div class='Ldt-createAnnotation-profileArrow'>        <img src='{{img_dir}}/annotate_arrow.png'></img>      </div>      <div class='Ldt-createAnnotation-userAvatar'>                <img src='https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png'></img>      </div>    </div>        <div class='Ldt-createAnnotation-keywords'>      Add keywords :           </div>              <div class='Ldt-createAnnotation-submitButton'>      <div style='position: absolute; bottom: 10pt; right: 11pt;'>Submit</div>    </div>        <div class='Ldt-createAnnotation-endScreen' style='display: none'>      Thank you, your annotation has been saved.<br>      Would you like to share it on social networks ?      <div style='margin-top: 12px; text-align: center;'>          <a target='_blank' class='Ldt-createAnnotation-endScreen-TweetLink'><img src='{{img_dir}}/tweet_button.png' style='margin-right: 20px;'></img></a>          <a target='_blank' class='Ldt-createAnnotation-endScreen-FbLink'><img src='{{img_dir}}/facebook_button.png' style='margin-right: 20px;'></img></a>          <a target='_blank' class='Ldt-createAnnotation-endScreen-GplusLink'><img src='{{img_dir}}/gplus_button.png' style='margin-right: 20px;'></img></a>                          </div>    </div>  </div></div>";
+IriSP.createAnnotationWidget_festivalCinecast_template="{{! template for the annotation creation widget specific for the cinecast festival}}<div class='Ldt-createAnnotationWidget'>  <!-- ugly div because we want to have a double border --\>  <div class='Ldt-createAnnotation-DoubleBorder'>    <div style='margin-bottom: 7px; overflow: auto;'>      <div class='Ldt-createAnnotation-Title'></div>      <div class='Ldt-createAnnotation-TimeFrame'></div>    </div>        <div class='Ldt-createAnnotation-Container'>      <textarea class='Ldt-createAnnotation-Description'></textarea>      <div class='Ldt-createAnnotation-profileArrow'>        <img src='{{img_dir}}/annotate_arrow.png'></img>      </div>      <div class='Ldt-createAnnotation-userAvatar'>                <img src='https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png'></img>      </div>    </div>        <div class='Ldt-createAnnotation-keywords'>      Add keywords :           </div>              <div class='Ldt-createAnnotation-submitButton'>      <div style='position: absolute; bottom: 10pt; right: 11pt;'>Submit</div>    </div>        <div class='Ldt-createAnnotation-endScreen' style='display: none'>      Thank you, your annotation has been saved.<br>      Would you like to share it on social networks ?      <div style='margin-top: 12px; text-align: center;'>          <a target='_blank' class='Ldt-createAnnotation-endScreen-TweetLink'><img src='{{img_dir}}/tweet_button.png' style='margin-right: 20px;'></img></a>          <a target='_blank' class='Ldt-createAnnotation-endScreen-FbLink'><img src='{{img_dir}}/facebook_button.png' style='margin-right: 20px;'></img></a>          <a target='_blank' class='Ldt-createAnnotation-endScreen-GplusLink'><img src='{{img_dir}}/gplus_button.png' style='margin-right: 20px;'></img></a>                          </div>    </div>  </div></div>";
+IriSP.createAnnotation_errorMessage_template="<p class='Ldt-createAnnotation-errorMessage'>  You must enter text to submit an annotation</p>";IriSP.overlay_marker_template="{{! the template for the small bars which is z-indexed over our segment widget }}<div class='Ldt-SegmentPositionMarker' style='background-color: #F7268E;'></div>";IriSP.player_template="{{! template for the radio player }}<div class='Ldt-controler demo'>\t<div class='Ldt-LeftPlayerControls'>    <div class='Ldt-button Ldt-CtrlPlay' title='Play/Pause'></div>\t\t<div class='Ldt-button Ldt-CtrlAnnotate' title='Annotate'></div>    <div class='Ldt-button Ldt-CtrlSearch' title='Search'></div>    <div class='LdtSearch'>      <input class='LdtSearchInput' style='margin-top: 2px; margin-bottom: 2px;'></input>    </div>    \t</div>\t<div class='Ldt-RightPlayerControls'>    <div class='Ldt-Time'>      <div class='Ldt-ElapsedTime' title='Elapsed time'>00:00</div>      <div class='Ldt-TimeSeparator'>/</div>      <div class='Ldt-TotalTime' title='Total time'>00:00</div>    </div>\t\t<div class='Ldt-button Ldt-CtrlSound' title='Mute/Unmute'></div>\t</div></div>";
+IriSP.search_template="{{! template for the search container }}<div class='LdtSearchContainer'\tstyle='margin-left: {{margin_left}}; position: absolute; margin-top: -60px;'>\t<div class='LdtSearch'\t\tstyle='display: none; background-color: #EEE; width: 165px; boder: 1px; border-color: #CFCFCF; position: absolute; text-align: center;'>\t\t<input class='LdtSearchInput'\t\t\tstyle='margin-top: 2px; margin-bottom: 2px;' />\t</div></div><div class='cleaner'></div>";IriSP.share_template="{{! social network sharing template }}<a onclick='__IriSP.MyApiPlayer.share('delicious');' title='partager avec delicious'><span class='share shareDelicious'>&nbsp;</span></a>\t\t<a onclick='__IriSP.MyApiPlayer.share('facebook');' title='partager avec facebook'> <span class='share shareFacebook'>&nbsp;</span></a><a onclick='__IriSP.MyApiPlayer.share('twitter');' title='partager avec twitter'>  <span class='share shareTwitter'>&nbsp;</span></a><a onclick='__IriSP.MyApiPlayer.share('myspace');' title='partager avec Myspace'>  <span class='share shareMySpace'>&nbsp;</span></a>";
+IriSP.sliceWidget_template="{{! template for the slice widget }}<div class='Ldt-sliceWidget'>  {{! the whole bar }}  <div class='Ldt-sliceBackground'></div>    <div class='Ldt-sliceLeftHandle'></div>  {{! the zone which represents our slice }}  <div class='Ldt-sliceZone'></div>     <div class='Ldt-sliceRightHandle'></div></div>";IriSP.sliderWidget_template="{{! template for the slider widget - it's composed of two divs we one overlayed on top    of the other }}<div class='Ldt-sliderBackground'></div><div class='Ldt-sliderForeground'></div><div class='Ldt-sliderPositionMarker'></div>";
+IriSP.tooltip_template="{{! template used by the jquery ui tooltip }}<div class='Ldt-tooltip'>  <div class='title'>{{title}}</div>  <div class='time'>{{begin}} : {{end}} </div>  <div class='description'>{{description}}</div></div>";IriSP.tooltipWidget_template="{{! template for the tooltip widget }}<div class='tip'>\t<div class='tipcolor' style='height:10px;width:10px'></div>\t<div class='tiptext'></div>";IriSP.tweetWidget_template="{{! template for the tweet widget }}<div class='Ldt-tweetWidget'>  <div class='Ldt-tweet-DoubleBorder'>      <img src='{{img_dir}}/minimize.png' class='Ldt-tweetWidgetKeepOpen' alt='dont minimize automatically'></img>      <img src='{{img_dir}}/minimize.png' class='Ldt-tweetWidgetMinimize' alt='minimize window'></img>      <div class='Ldt-tweetAvatar'></div>      <img src='{{img_dir}}/profile_arrow.png' class='Ldt-tweetAvatar-profileArrow'></img>      <div class='Ldt-tweetContents'></div>      <a href='' target='_blank' class='Ldt-Retweet'><div class='Ldt-RetweetIcon'></div> - Retweet </a>      <a href='' target='_blank' class='Ldt-TweetReply'><div class='Ldt-TweetReplyIcon'></div> - Reply</a>  </div></div>";
+IriSP.PopcornReplacement={msgPump:{},__delay_seek_signal:false};IriSP.PopcornReplacement.media={paused:true,muted:false};IriSP.PopcornReplacement.listen=function(a,c){IriSP.PopcornReplacement.msgPump.hasOwnProperty(a)||(IriSP.PopcornReplacement.msgPump[a]=[]);IriSP.PopcornReplacement.msgPump[a].push(c)};IriSP.PopcornReplacement.trigger=function(a,c){if(IriSP.PopcornReplacement.msgPump.hasOwnProperty(a))for(var d=IriSP.PopcornReplacement.msgPump[a],i=0;i<d.length;i++)d[i].call(window,c)};
+IriSP.PopcornReplacement.guid=function(a){var c="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(d){var i=Math.random()*16|0;return(d=="x"?i:i&3|8).toString(16)});return a+c};
+IriSP.PopcornReplacement.__initApi=function(){IriSP.PopcornReplacement.trigger("loadedmetadata");IriSP.PopcornReplacement.media.muted=jwplayer(IriSP.PopcornReplacement._container).getMute();var a=0;for(a=0;a<IriSP.PopcornReplacement.__codes.length;a++){var c=IriSP.PopcornReplacement.__codes[a];0==c.start&&c.onStart();0==c.end&&c.onEnd()}};
+IriSP.PopcornReplacement.jwplayer=function(a,c){IriSP.PopcornReplacement._container=a.slice(1);c.events={onReady:IriSP.PopcornReplacement.__initApi,onTime:IriSP.PopcornReplacement.__timeHandler,onPlay:IriSP.PopcornReplacement.__playHandler,onPause:IriSP.PopcornReplacement.__pauseHandler,onSeek:IriSP.PopcornReplacement.__seekHandler};jwplayer(IriSP.PopcornReplacement._container).setup(c);IriSP.PopcornReplacement.media.duration=c.duration;return IriSP.PopcornReplacement};
+IriSP.PopcornReplacement.currentTime=function(a){if(typeof a==="undefined")return jwplayer(IriSP.PopcornReplacement._container).getPosition();else{a=+a;jwplayer(IriSP.PopcornReplacement._container).seek(a);IriSP.PopcornReplacement.__delay_seek_signal=true;return a}};IriSP.PopcornReplacement.play=function(){IriSP.PopcornReplacement.media.paused=false;IriSP.PopcornReplacement.trigger("play");jwplayer(IriSP.PopcornReplacement._container).play()};
+IriSP.PopcornReplacement.pause=function(){if(!IriSP.PopcornReplacement.media.paused){IriSP.PopcornReplacement.media.paused=true;IriSP.PopcornReplacement.trigger("pause");jwplayer(IriSP.PopcornReplacement._container).pause()}};
+IriSP.PopcornReplacement.muted=function(a){if(typeof a!=="undefined")if(jwplayer(IriSP.PopcornReplacement._container).getMute()!==a){if(a){jwplayer(IriSP.PopcornReplacement._container).setMute(true);IriSP.PopcornReplacement.media.muted=true}else{jwplayer(IriSP.PopcornReplacement._container).setMute(false);IriSP.PopcornReplacement.media.muted=false}IriSP.PopcornReplacement.trigger("volumechange")}return jwplayer(IriSP.PopcornReplacement._container).getMute()};IriSP.PopcornReplacement.mute=IriSP.PopcornReplacement.muted;
+IriSP.PopcornReplacement.__codes=[];IriSP.PopcornReplacement.code=function(a){IriSP.PopcornReplacement.__codes.push(a);return IriSP.PopcornReplacement};IriSP.PopcornReplacement.__timeHandler=function(a){a=a.position;var c=0;for(c=0;c<IriSP.PopcornReplacement.__codes.length;c++){var d=IriSP.PopcornReplacement.__codes[c];a>=d.start&&a<d.end&&a-1<=d.start&&d.onStart();a>d.start&&a>d.end&&a-1<=d.end&&d.onEnd()}IriSP.PopcornReplacement.trigger("timeupdate")};
+IriSP.PopcornReplacement.__seekHandler=function(a){var c=0;for(c=0;c<IriSP.PopcornReplacement.__codes.length;c++){var d=IriSP.PopcornReplacement.__codes[c];a.position>=d.start&&a.position<d.end&&d.onEnd()}for(c=0;c<IriSP.PopcornReplacement.__codes.length;c++){d=IriSP.PopcornReplacement.__codes[c];if(typeof a.offset==="undefined")a.offset=0;a.offset>=d.start&&a.offset<d.end&&d.onStart()}if(IriSP.PopcornReplacement.__delay_seek_signal===true){console.log(IriSP.PopcornReplacement.currentTime());IriSP.PopcornReplacement.trigger("seeked")}IriSP.PopcornReplacement.trigger("timeupdate")};
+IriSP.PopcornReplacement.__playHandler=function(){IriSP.PopcornReplacement.media.paused=false;IriSP.PopcornReplacement.trigger("play")};IriSP.PopcornReplacement.__pauseHandler=function(){IriSP.PopcornReplacement.media.paused=true;IriSP.PopcornReplacement.trigger("pause")};IriSP.PopcornReplacement.roundTime=function(){var a=IriSP.PopcornReplacement.currentTime();return Math.round(a)};IriSP.traceNum=0;IriSP.trace=function(){};
+IriSP.wrap=function(a,c){return function(){var d=Array.prototype.slice.call(arguments,0);return c.apply(a,d)}};IriSP.timeToPourcent=function(a,c){a=Math.abs(a);c=Math.abs(c);return Math.floor(a/c*100)};IriSP.padWithZeros=function(a){return Math.abs(a)<10?"0"+a.toString():a.toString()};IriSP.msToTime=function(a){return IriSP.secondsToTime(a/1E3)};
+IriSP.secondsToTime=function(a){var c=Math.abs(parseInt(a/3600)%24),d=Math.abs(parseInt(a/60)%60);a=parseFloat(Math.abs(a%60).toFixed(0));return{hours:c,minutes:d,seconds:a,toString:function(){var i="";if(c>0)i=IriSP.padWithZeros(this.hours)+":";i+=IriSP.padWithZeros(this.minutes)+":"+IriSP.padWithZeros(this.seconds);return i}}};
+IriSP.formatTweet=function(a){var c=[[/((https?:\/\/)?[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?)/gi,"<a href='$1'>$1</a>"],[/@(\w+)/gi,"<a href='http://twitter.com/$1'>@$1</a>"],[/#(\w+)/gi,"<a href='http://twitter.com/search?q=%23$1'>#$1</a>"],[/(\+\+)/gi,"<span class='Ldt-PolemicPlusPlus'>$1</span>"],[/(--)/gi,"<span class='Ldt-PolemicMinusMinus'>$1</span>"],[/(==)/gi,"<span class='Ldt-PolemicEqualEqual'>$1</span>"],[/(\?\?)/gi,"<span class='Ldt-PolemicQuestion'>$1</span>"]],d=0;for(d=0;d<c.length;d++)a=
+a.replace(c[d][0],c[d][1]);return a};IriSP.countProperties=function(a){var c=0;for(var d in a)a.hasOwnProperty(d)&&++c;return c};IriSP.DEC_HEXA_COLOR=function(a){for(var c="",d;a>15;){d=a-Math.floor(a/16)*16;c="0123456789ABCDEF".charAt(d)+c;a=Math.floor(a/16)}return c="0123456789ABCDEF".charAt(a)+c};IriSP.templToHTML=function(a,c){var d=IriSP.jQuery.extend(IriSP.default_templates_vars,c);return Mustache.to_html(a,d)};
+IriSP.encodeURI=function(a){return encodeURIComponent(a).replace(/!/g,"%21").replace(/'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/\*/g,"%2A")};IriSP.__guidCounter=0;IriSP.guid=function(a){IriSP.__guidCounter+=1;return a+IriSP.__guidCounter};IriSP.mkFbUrl=function(a){return"http://www.facebook.com/share.php?u=I'm watching "+a};IriSP.mkTweetUrl=function(a){return"http://twitter.com/home?status=I'm sharing "+a};IriSP.mkGplusUrl=function(){return""};
+IriSP.DataLoader=function(){this._cache={};this._callbacks={}};
+IriSP.DataLoader.prototype.get=function(a,c){var d=a.split("&")[0];if(this._cache.hasOwnProperty(d))c(this._cache[d]);else if(this._callbacks.hasOwnProperty(d))this._callbacks[d].push(c);else{this._callbacks[d]=[];this._callbacks[d].push(c);var i=function(h){this._cache[d]=h;for(h=h=0;h<this._callbacks[d].length;h++)this._callbacks[d][h](this._cache[d])};a.indexOf(document.location.hostname)===-1&&a.indexOf("http://")!==-1?IriSP.jQuery.get(a,{},IriSP.wrap(this,i),"jsonp"):IriSP.jQuery.get(a,IriSP.wrap(this,
+i))}};IriSP.Serializer=function(a,c){this._DataLoader=a;this._url=c;this._data=[]};IriSP.Serializer.prototype.serialize=function(){};IriSP.Serializer.prototype.deserialize=function(){};IriSP.Serializer.prototype.currentMedia=function(){};IriSP.Serializer.prototype.sync=function(a){a.call(this,this._data)};IriSP.SerializerFactory=function(a){this._dataloader=a};
+IriSP.SerializerFactory.prototype.getSerializer=function(a){if(a===undefined)return IriSP.Serializer("","");switch(a.type){case "json":return new IriSP.JSONSerializer(this._dataloader,a.src);case "dummy":return new IriSP.MockSerializer(this._dataloader,a.src);case "empty":return new IriSP.Serializer("","empty");default:return}};IriSP.libdir="/mdp/src/js/libs/";IriSP.jwplayer_swf_path="/mdp/test/libs/player.swf";
+IriSP.lib={jQuery:"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js",jQueryUI:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.js",jQueryToolTip:"http://cdn.jquerytools.org/1.2.4/all/jquery.tools.min.js",swfObject:"http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js",cssjQueryUI:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css",popcorn:IriSP.libdir+"popcorn.js",jwplayer:IriSP.libdir+"jwplayer.js",popcornReplacement:IriSP.libdir+"pop.js",
+raphael:IriSP.libdir+"raphael.js",jquery_sparkline:IriSP.libdir+"jquery.sparkline.js","popcorn.mediafragment":IriSP.libdir+"popcorn.mediafragment.js","popcorn.code":IriSP.libdir+"popcorn.code.js","popcorn.jwplayer":IriSP.libdir+"popcorn.jwplayer.js","popcorn.youtube":IriSP.libdir+"popcorn.youtube.js"};IriSP.config=undefined;
+IriSP.widgetsDefaults={LayoutManager:{spacer_div_height:"0px"},PlayerWidget:{},AnnotationsWidget:{share_text:"I'm watching ",fb_link:"http://www.facebook.com/share.php?u=",tw_link:"http://twitter.com/home?status=",gplus_link:""},TweetsWidget:{default_profile_picture:"https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png",tweet_display_period:1E4},SliderWidget:{minimize_period:850},createAnnotationWidget:{keywords:["#faux-raccord","#mot-clef"],cinecast_version:true},Main:{autoplay:true}};
+IriSP.platform_url="http://localhost/pf";IriSP.paths={imgs:"/mdp/src/css/imgs"};IriSP.default_templates_vars={img_dir:IriSP.paths.imgs};IriSP.LdtShareTool=IriSP.share_template;
+IriSP.createPlayerChrome=function(){var a=IriSP.config.gui.width,c=IriSP.config.gui.height-20;IriSP.trace("__IriSP.createMyHtml",IriSP.config.gui.container);if(IriSP.config.gui.mode=="radio"){IriSP.jQuery("#"+IriSP.config.gui.container).before(IriSP.search_template);c=Mustache.to_html(IriSP.radio_template,{share_template:IriSP.share_template});IriSP.jQuery(c).appendTo("#"+IriSP.config.gui.container);if(IriSP.jQuery.browser.msie==true&&IriSP.jQuery.browser.version=="7.0"){IriSP.jQuery("#Ldt-Root").css("padding-top",
+"25px");IriSP.trace("__IriSP.createHtml","IE7 SPECIAL ")}}else if(IriSP.config.gui.mode=="video"){c=Mustache.to_html(IriSP.video_template,{share_template:IriSP.share_template,heightS:c});IriSP.jQuery(c).appendTo("#"+IriSP.config.gui.container)}IriSP.jQuery("#Ldt-Annotations").width(a-150);IriSP.jQuery("#Ldt-Show-Arrow-container").width(a-150);IriSP.jQuery("#Ldt-ShowAnnotation-audio").width(a-10);IriSP.jQuery("#Ldt-ShowAnnotation-video").width(a-10);IriSP.jQuery("#Ldt-SaKeyword").width(a-10);IriSP.jQuery("#Ldt-controler").width(a-
+10);IriSP.jQuery("#Ldt-Control").attr("z-index","100");IriSP.jQuery("#Ldt-controler").hide();IriSP.jQuery(IriSP.annotation_loading_template).appendTo("#Ldt-ShowAnnotation-audio");IriSP.config.gui.mode=="radio"&&IriSP.jQuery("#Ldt-load-container").attr("width",IriSP.config.gui.width);IriSP.config.gui.debug===true?IriSP.jQuery("#Ldt-output").show():IriSP.jQuery("#Ldt-output").hide()};
+IriSP.createInterface=function(a,c,d){IriSP.jQuery("#Ldt-controler").show();IriSP.trace("__IriSP.createInterface",a+","+c+","+d+",");IriSP.jQuery("#Ldt-ShowAnnotation").click(function(){});IriSP.jQuery("#Ldt-PlaceHolder").attr("top");IriSP.jQuery("#Ldt-PlaceHolder").attr("left");IriSP.jQuery("#slider-range-min").slider({value:0,min:1,max:d/1E3,step:0.1,slide:function(i,h){IriSP.MyApiPlayer.seek(h.value)}});IriSP.trace("__IriSP.createInterface","ICI");IriSP.jQuery("#amount").val(IriSP.jQuery("#slider-range-min").slider("value")+
+" s");IriSP.jQuery(".Ldt-Control1 button:first").button({icons:{primary:"ui-icon-play"},text:false}).next().button({icons:{primary:"ui-icon-seek-next"},text:false});IriSP.jQuery(".Ldt-Control2 button:first").button({icons:{primary:"ui-icon-search"},text:false}).next().button({icons:{primary:"ui-icon-volume-on"},text:false});IriSP.trace("__IriSP.createInterface","ICI2");IriSP.jQuery("#ldt-CtrlPlay").attr("style","background-color:#CD21C24;");IriSP.jQuery("#Ldt-load-container").hide();IriSP.config.gui.mode==
+"radio"&IriSP.jQuery.browser.msie!=true&&IriSP.jQuery("#Ldtplayer1").attr("height","0");IriSP.trace("__IriSP.createInterface","3");IriSP.trace("__IriSP.createInterface","END")};
+IriSP.Widget=function(a,c,d){if(c===undefined||c===null)c={};this._Popcorn=a;this._config=c;this._serializer=d;if(c.hasOwnProperty("container")){this._id=c.container;this.selector=IriSP.jQuery("#"+this._id)}if(c.hasOwnProperty("spacer")){this._spacerId=c.spacer;this.spacer=IriSP.jQuery("#"+this._spacerId)}if(c.hasOwnProperty("width"))this.width=c.width;if(c.hasOwnProperty("height"))this.height=c.height;if(c.hasOwnProperty("heightmax"))this.heightmax=c.heightmax;if(c.hasOwnProperty("widthmax"))this.widthmax=
+c.widthmax;if(c.hasOwnProperty("layoutManager"))this.layoutManager=c.layoutManager};IriSP.Widget.prototype.draw=function(){};IriSP.Widget.prototype.redraw=function(){};IriSP.Module=function(a,c,d){if(c===undefined||c===null)c={};this._Popcorn=a;this._config=c;this._serializer=d};
+IriSP.LayoutManager=function(a){this._Popcorn=null;this._widgets=[];this._div="LdtPlayer";this._width=640;if(a===undefined)a={};if(a.hasOwnProperty("container"))this._div=a.container;if(a.hasOwnProperty("width"))this._width=a.width;if(a.hasOwnProperty("height"))this._height=a.height;this.selector=IriSP.jQuery("#"+this._div);this.selector.css("width",this._width);this._height!==undefined&&this.selector.css("height",this._height)};
+IriSP.LayoutManager.prototype.setPopcornInstance=function(a){this._Popcorn=a};
+IriSP.LayoutManager.prototype.createDiv=function(a){if(typeof a==="undefined")a="";var c=IriSP.guid(this._div+"_widget_"+a+"_"),d=IriSP.guid("LdtPlayer_spacer_");this._widgets.push([a,c]);a=Mustache.to_html("<div id='{{id}}' style='width: {{width}}px; position: relative;'></div",{id:c,width:this._width});var i=Mustache.to_html("<div id='{{spacer_id}}' style='width: {{width}}px; position: relative; height: {{spacer_div_height}};'></div",{spacer_id:d,width:this._width,spacer_div_height:IriSP.widgetsDefaults.LayoutManager.spacer_div_height});
+this.selector.append(a);this.selector.append(i);return[c,d]};IriSP.setupDataLoader=function(){IriSP.__dataloader=new IriSP.DataLoader};
+IriSP.configurePopcorn=function(a,c){var d,i=a.createDiv()[0];switch(c.type){case "html5":var h=Popcorn.guid("video");IriSP.jQuery("#"+i).append("<video src='"+c.file+"' id='"+h+"'></video>");c.hasOwnProperty("width")&&IriSP.jQuery("#"+i).css("width",c.width);c.hasOwnProperty("height")&&IriSP.jQuery("#"+i).css("height",c.height);d=Popcorn("#"+h);break;case "jwplayer":h=IriSP.jQuery.extend({},c);delete h.container;delete h.type;if(c.provider==="rtmp"){if(typeof IriSP.__jsonMetadata==="undefined")break;
+h.streamer=IriSP.__jsonMetadata.medias[0].meta.item.value;h.file=IriSP.__jsonMetadata.medias[0].href.slice(h.streamer.length);console.log(h.streamer,h.file);h.streamer="rtmp://media.iri.centrepompidou.fr/ddc_player/video/ldtplatform/";h.file="laurentcantet_entrelesmurs.flv";console.log(h.streamer,h.file)}if(!c.hasOwnProperty("flashplayer"))h.flashplayer=IriSP.jwplayer_swf_path;c.hasOwnProperty("controlbar.position")||(h["controlbar.position"]="none");d=IriSP.PopcornReplacement.jwplayer("#"+i,h);break;
+case "youtube":h=IriSP.jQuery.extend({},c);delete h.container;h.controls=0;h.autostart=false;templ="width: {{width}}px; height: {{height}}px;";d=Mustache.to_html(templ,{width:h.width,height:h.height});IriSP.jQuery("#"+i).attr("style",d);d=Popcorn.youtube("#"+i,h.video,h);break;default:d=undefined}return d};IriSP.configureWidgets=function(a,c,d){var i=new IriSP.SerializerFactory(IriSP.__dataloader),h=[],m;for(m=0;m<d.widgets.length;m++){var n=IriSP.instantiateWidget(a,i,c,d.widgets[m]);h.push(n)}return h};
+IriSP.configureModules=function(a,c){var d=new IriSP.SerializerFactory(IriSP.__dataloader),i=[],h;for(h=0;h<c.length;h++){var m=c[h],n=d.getSerializer(m.metadata);m=new IriSP[m.type](a,m,n);i.push(m)}return i};
+IriSP.instantiateWidget=function(a,c,d,i){var h=IriSP.jQuery.extend({},i);if(!h.hasOwnProperty("container")){var m=d.createDiv(i.type),n=m[1];h.container=m[0];h.spacer=n;h.layoutManager=d}m=c.getSerializer(i.metadata);if(typeof m=="undefined")debugger;h=new IriSP[i.type](a,h,m);if(i.hasOwnProperty("requires"))for(n=n=0;n<i.requires.length;n++)h[i.requires[n].type]=IriSP.instantiateWidget(a,c,d,i.requires[n]);m.sync(IriSP.wrap(h,function(){this.draw()}));return h};
+IriSP.MediaFragment=function(a,c,d){IriSP.Module.call(this,a,c,d);this.mutex=false;this._Popcorn.listen("loadedmetadata",IriSP.wrap(this,this.advanceTime));this._Popcorn.listen("pause",IriSP.wrap(this,this.updateTime));this._Popcorn.listen("seeked",IriSP.wrap(this,this.updateTime));this._Popcorn.listen("IriSP.PolemicTweet.click",IriSP.wrap(this,this.updateAnnotation));this._Popcorn.listen("IriSP.SegmentsWidget.click",IriSP.wrap(this,this.updateAnnotation));window.onhashchange=IriSP.wrap(this,this.advanceTime)};
+IriSP.MediaFragment.prototype=new IriSP.Module;IriSP.MediaFragment.prototype.advanceTime=function(){var a=window.location.href;if(a.split("#")[1]!=null){pageoffset=a.split("#")[1];if(pageoffset.substring(0,2)==="t="){if(pageoffset.substring(2)!=null){a=pageoffset.substring(2);this._Popcorn.currentTime(parseFloat(a))}}else if(pageoffset.substring(0,2)==="a="){var c=pageoffset.substring(2);this._serializer.sync(IriSP.wrap(this,function(){this.lookupAnnotation.call(this,c)}))}}};
+IriSP.MediaFragment.prototype.updateTime=function(){if(this.mutex!==true){var a=window.history;if(!a.pushState)return false;splitArr=window.location.href.split("#");a.replaceState({},"",splitArr[0]+"#t="+this._Popcorn.currentTime().toFixed(2))}};
+IriSP.MediaFragment.prototype.updateAnnotation=function(a){var c=this;this.mutex=true;var d=window.history;if(!d.pushState)return false;splitArr=window.location.href.split("#");d.replaceState({},"",splitArr[0]+"#a="+a);window.setTimeout(function(){c.mutex=false},50)};
+IriSP.MediaFragment.prototype.lookupAnnotation=function(a){var c=this;this.mutex=true;var d=undefined,i=this._serializer._data.annotations,h;for(h=0;h<i.length;h++)if(i[h].id===a){d=i[h];break}typeof d!=="undefined"&&this._Popcorn.currentTime(d.begin/1E3);window.setTimeout(function(){c.mutex=false},50)};IriSP.AnnotationsListWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this.__counter=0;this.__oldList=[]};IriSP.AnnotationsListWidget.prototype=new IriSP.Widget;
+IriSP.AnnotationsListWidget.prototype.clear=function(){};IriSP.AnnotationsListWidget.prototype.clearWidget=function(){};
+IriSP.AnnotationsListWidget.prototype.drawList=function(a){var c=this._serializer.getContributions(),d=this._serializer._data.annotations,i=this._Popcorn.currentTime(),h=[];if(typeof c==="undefined")console.log("no type suitable for display");else{for(x=0;x<d.length;x++){var m=d[x];if(!(typeof m.meta!=="undefined"&&typeof m.meta["id-ref"]!=="undefined"&&m.meta["id-ref"]!=c))if(m.begin<=i*1E3&&m.end>i*1E3){var n=m,C={};C.id=n.id;C.title=n.content.title;C.desc=n.content.description;C.begin=IriSP.msToTime(m.begin);
+C.end=IriSP.msToTime(m.end);h.push(C)}}c=IriSP.underscore.pluck(h,"id").sort();if(c.length!==this.__oldList.length){x=IriSP.templToHTML(IriSP.annotationsListWidget_template,{annotations:h});this.selector.html(x)}d=1;for(var x=0;x<c.length;){if(c[x]!==this.__oldList[x])d=0;break}this.__oldList=c;if(typeof a!=="undefined"){console.log("forced redraw");x=IriSP.templToHTML(IriSP.annotationsListWidget_template,{annotations:h});this.selector.html(x)}if(d!==1){x=IriSP.templToHTML(IriSP.annotationsListWidget_template,
+{annotations:h});this.selector.html(x)}}};IriSP.AnnotationsListWidget.prototype.draw=function(){this.drawList();this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation",IriSP.wrap(this,function(){this.redraw(true)}));this._Popcorn.listen("timeupdate",IriSP.wrap(this,this.redraw))};IriSP.AnnotationsListWidget.prototype.redraw=function(){this.drawList()};IriSP.AnnotationsWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this._hidden=false};IriSP.AnnotationsWidget.prototype=new IriSP.Widget;
+IriSP.AnnotationsWidget.prototype.clear=function(){this.selector.find(".Ldt-SaTitle").text("");this.selector.find(".Ldt-SaDescription").text("");this.selector.find(".Ldt-SaKeywordText").text("")};
+IriSP.AnnotationsWidget.prototype.displayAnnotation=function(a){var c=a.content.title,d=a.content.description,i=+a.begin/1E3,h=+a.end/1E3;this._serializer.currentMedia();c=Mustache.to_html("{{title}} - ( {{begin}} - {{end}} )",{title:c,begin:IriSP.secondsToTime(i),end:IriSP.secondsToTime(h)});this.selector.find(".Ldt-SaTitle").text(c);this.selector.find(".Ldt-SaDescription").text(d);i=IriSP.widgetsDefaults.AnnotationsWidget;d=i.share_text;c=i.fb_link;i=i.tw_link;a=document.location.href+"#a="+a.id;
+this.selector.find(".Ldt-fbShare").attr("href",c+IriSP.encodeURI(d)+IriSP.encodeURI(a));this.selector.find(".Ldt-TwShare").attr("href",i+IriSP.encodeURI(d)+IriSP.encodeURI(a));this.selector.find(".Ldt-GplusShare").attr("href",c+IriSP.encodeURI(d)+IriSP.encodeURI(a))};IriSP.AnnotationsWidget.prototype.clearWidget=function(){this.selector.find(".Ldt-SaTitle").text("");this.selector.find(".Ldt-SaDescription").text("");this.selector.find(".Ldt-SaKeywordText").html("");this.selector.find(".Ldt-ShowAnnotation").slideUp()};
+IriSP.AnnotationsWidget.prototype.draw=function(){var a=this;this.selector.append(IriSP.templToHTML(IriSP.annotationWidget_template));this._Popcorn.listen("IriSP.PlayerWidget.AnnotateButton.clicked",IriSP.wrap(this,this.handleAnnotateSignal));var c=[];if(typeof this._serializer.getChapitrage()!=="undefined")c.push(this._serializer.getChapitrage());else c=this._serializer.getNonTweetIds();var d=this._serializer._data.annotations,i;for(i in d){var h=d[i],m=Math.round(+h.begin/1E3),n=Math.round(+h.end/
+1E3);if(!(typeof h.meta!=="undefined"&&typeof h.meta["id-ref"]!=="undefined"&&!IriSP.underscore.include(c,h.meta["id-ref"])))this._Popcorn=this._Popcorn.code({start:m,end:n,onStart:function(C){return function(){a.displayAnnotation(C)}}(h),onEnd:function(){a.clearWidget.call(a)}})}};IriSP.AnnotationsWidget.prototype.handleAnnotateSignal=function(){if(this._hidden==false){this.selector.hide();this._hidden=true}else{this.selector.show();this._hidden=false}};
+IriSP.ArrowWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this._oldAnnotation=null;this._blockArrow=false};IriSP.ArrowWidget.prototype=new IriSP.Widget;IriSP.ArrowWidget.prototype.clear=function(){};IriSP.ArrowWidget.prototype.clearWidget=function(){};
+IriSP.ArrowWidget.prototype.draw=function(){this.selector.append(Mustache.to_html(IriSP.arrowWidget_template,{}));this._Popcorn.listen("timeupdate",IriSP.wrap(this,this.timeUpdateHandler));this._Popcorn.listen("IriSP.ArrowWidget.blockArrow",IriSP.wrap(this,this.blockArrow));this._Popcorn.listen("IriSP.ArrowWidget.releaseArrow",IriSP.wrap(this,this.releaseArrow))};
+IriSP.ArrowWidget.prototype.timeUpdateHandler=function(a){if(!this._blockArrow){var c=this._serializer.currentAnnotations(this._Popcorn.currentTime())[0];if(c!=this._oldAnnotation){a=+c.begin/1E3;var d=+c.end/1E3,i=+this._serializer.currentMedia().meta["dc:duration"]/1E3;a=(a+d)/2/i;d=this.selector.width();a=a*d-13.5;if(a%3!=0)a-=a%3-1;if(a<=0)a=0;if(a<=15){d=IriSP.templToHTML("url('{{img_dir}}/left_edge_arrow.png')");this.selector.children(".Ldt-arrowWidget").css("background-image",d)}else if(a>=
+d-25){d=IriSP.templToHTML("url('{{img_dir}}/right_edge_arrow.png')");this.selector.children(".Ldt-arrowWidget").css("background-image",d)}else{d=IriSP.templToHTML("url('{{img_dir}}/arrow.png')");this.selector.children(".Ldt-arrowWidget").css("background-image",d)}this.selector.children(".Ldt-arrowWidget").animate({left:a+"px"});this._oldAnnotation=c}}};IriSP.ArrowWidget.prototype.blockArrow=function(){this._blockArrow=true};IriSP.ArrowWidget.prototype.releaseArrow=function(){this._blockArrow=false};
+IriSP.createAnnotationWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this._hidden=true;this.keywords=IriSP.widgetsDefaults.createAnnotationWidget.keywords;this.cinecast_version=IriSP.widgetsDefaults.createAnnotationWidget.cinecast_version;this.ids={}};IriSP.createAnnotationWidget.prototype=new IriSP.Widget;IriSP.createAnnotationWidget.prototype.clear=function(){this.selector.find(".Ldt-SaTitle").text("");this.selector.find(".Ldt-SaDescription").text("");this.selector.find(".Ldt-SaKeywordText").text("")};
+IriSP.createAnnotationWidget.prototype.draw=function(){var a=this;this.selector.append(this.cinecast_version?IriSP.templToHTML(IriSP.createAnnotationWidget_festivalCinecast_template):IriSP.templToHTML(IriSP.createAnnotationWidget_template));this.selector.hide();for(var c=0;c<this.keywords.length;c++){var d=this.keywords[c],i=IriSP.guid("button_"),h=IriSP.templToHTML("<button id={{id}} class='Ldt-createAnnotation-absent-keyword'>{{keyword}}</button>",{keyword:d,id:i});this.ids[d]=i;this.selector.find(".Ldt-createAnnotation-keywords").append(h);
+this.selector.find("#"+i).click(function(m){return function(){var n=a.selector.find(".Ldt-createAnnotation-Description").val();n=n.indexOf(m)!=-1?n.replace(m,""):n+m;a.selector.find(".Ldt-createAnnotation-Description").val(n);a.selector.find(".Ldt-createAnnotation-Description").trigger("js_mod");a.handleTextChanges()}}(d))}this.selector.find(".Ldt-createAnnotation-Description").bind("propertychange keyup input paste",IriSP.wrap(this,this.handleTextChanges));this.selector.find(".Ldt-createAnnotation-submitButton").click(IriSP.wrap(this,
+this.handleButtonClick));this._Popcorn.listen("IriSP.PlayerWidget.AnnotateButton.clicked",IriSP.wrap(this,this.handleAnnotateSignal))};
+IriSP.createAnnotationWidget.prototype.handleAnnotateSignal=function(){if(this._hidden==false){this.selector.hide();this._hidden=true;this.selector.find(".Ldt-createAnnotation-DoubleBorder").children().show();this.selector.find("Ldt-createAnnotation-Description").val("");this.selector.find(".Ldt-createAnnotation-endScreen").hide();this._Popcorn.trigger("IriSP.ArrowWidget.releaseArrow")}else{if(this.cinecast_version){var a=this._serializer.currentAnnotations(this._Popcorn.currentTime())[0],c=IriSP.msToTime(a.begin),
+d=IriSP.msToTime(a.end);this._currentAnnotation=a;typeof a.content!=="undefined"&&this.selector.find(".Ldt-createAnnotation-Title").html(a.content.title);a=IriSP.templToHTML("- ({{begin}} - {{ end }})",{begin:c,end:d});this.selector.find(".Ldt-createAnnotation-TimeFrame").html(a)}this.selector.show();this._hidden=false;this._Popcorn.trigger("IriSP.ArrowWidget.blockArrow")}};
+IriSP.createAnnotationWidget.prototype.handleTextChanges=function(){var a=this.selector.find(".Ldt-createAnnotation-Description").val();for(var c in this.ids){var d=this.ids[c];if(a.indexOf(c)!=-1)this.selector.find("#"+d).hasClass("Ldt-createAnnotation-absent-keyword")&&this.selector.find("#"+d).removeClass("Ldt-createAnnotation-absent-keyword").addClass("Ldt-createAnnotation-present-keyword");else this.selector.find("#"+d).hasClass("Ldt-createAnnotation-present-keyword")&&this.selector.find("#"+
+d).removeClass("Ldt-createAnnotation-present-keyword").addClass("Ldt-createAnnotation-absent-keyword")}};
+IriSP.createAnnotationWidget.prototype.handleButtonClick=function(){var a=this,c=this.selector.find(".Ldt-createAnnotation-Description"),d=c.val();if(d===""){if(this.selector.find(".Ldt-createAnnotation-errorMessage").length===0){this.selector.find(".Ldt-createAnnotation-Container").after(IriSP.templToHTML(IriSP.createAnnotation_errorMessage_template));c.css("background-color","#d93c71")}else this.selector.find(".Ldt-createAnnotation-errorMessage").show();c.bind("js_mod.tmp propertychange.tmp keyup.tmp input.tmp paste.tmp",
+IriSP.wrap(this,function(){var x=c.val();console.log(x);if(x!==""){this.selector.find(".Ldt-createAnnotation-errorMessage").hide();c.css("background-color","");c.unbind(".tmp")}}))}else{this.selector.find(".Ldt-createAnnotation-DoubleBorder").children().hide();this.cinecast_version&&this.selector.find(".Ldt-createAnnotation-Title").parent().show();var i=IriSP.mkTweetUrl(document.location.href),h=IriSP.mkGplusUrl(document.location.href),m=IriSP.mkFbUrl(document.location.href);this.selector.find(".Ldt-createAnnotation-endScreen-TweetLink").attr("href",
+i);this.selector.find(".Ldt-createAnnotation-endScreen-FbLink").attr("href",m);this.selector.find(".Ldt-createAnnotation-endScreen-GplusLink").attr("href",h);this.selector.find(".Ldt-createAnnotation-endScreen").show();if(typeof this._currentAnnotation==="undefined")console.log("this._currentAnnotation undefined");else{i={annotations:[{}],meta:{}};var n=i.annotations[0];n.type_title="";n.media=this._serializer.currentMedia().id;n.begin=this._currentAnnotation.begin;n.end=this._currentAnnotation.end;
+n.type=this._serializer.getContributions();n.content={};n.content.data=d;var C=i.meta;C.creator="An User";C.created=Date().toString();n.tags=[];for(h=0;h<this.keywords.length;h++){m=this.keywords[h];d.indexOf(m)!=-1&&n.tags.push(m)}d=JSON.stringify(i);i=Mustache.to_html("{{platf_url}}/ldtplatform/api/ldt/projects/{{id}}.json",{platf_url:IriSP.platform_url,id:this._serializer._data.meta.id});console.log(i);IriSP.jQuery.ajax({url:i,type:"PUT",contentType:"application/json",data:d,dataType:"json",success:function(x){delete n.tags;
+n.content.description=n.content.data;delete n.content.data;n.id=x.annotations[0].id;n.title=a._currentAnnotation.content.title;n.meta=C;n.meta["id-ref"]=n.type;a._serializer._data.annotations.push(n);a._Popcorn.trigger("IriSP.createAnnotationWidget.addedAnnotation")},error:function(x,l,q){alert("ERROR = "+x.responseText+", "+q)}})}}};IriSP.PlayerWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this._searchBlockOpen=false;this._searchLastValue=""};IriSP.PlayerWidget.prototype=new IriSP.Widget;
+IriSP.PlayerWidget.prototype.draw=function(){var a=this;this.selector.append(IriSP.templToHTML(IriSP.player_template,{share_template:IriSP.share_template}));this.selector.children(".Ldt-controler").show();this._Popcorn.listen("play",IriSP.wrap(this,this.playButtonUpdater));this._Popcorn.listen("pause",IriSP.wrap(this,this.playButtonUpdater));this._Popcorn.listen("volumechange",IriSP.wrap(this,this.muteButtonUpdater));this._Popcorn.listen("timeupdate",IriSP.wrap(this,this.timeDisplayUpdater));this._Popcorn.listen("loadedmetadata",
+IriSP.wrap(this,this.timeDisplayUpdater));this._Popcorn.listen("IriSP.search.matchFound",IriSP.wrap(this,this.searchMatch));this._Popcorn.listen("IriSP.search.noMatchFound",IriSP.wrap(this,this.searchNoMatch));this.selector.find(".Ldt-CtrlPlay").click(function(){a.playHandler.call(a)});this.selector.find(".Ldt-CtrlAnnotate").click(function(){a._Popcorn.trigger("IriSP.PlayerWidget.AnnotateButton.clicked")});this.selector.find(".Ldt-CtrlSearch").click(function(){a.searchButtonHandler.call(a)});this.selector.find(".Ldt-CtrlSound").click(function(){a.muteHandler.call(a)});
+this.selector.find(".Ldt-CtrlPlay").attr("style","background-color:#CD21C24;");this.selector.hover(function(){a._Popcorn.trigger("IriSP.PlayerWidget.MouseOver")},function(){a._Popcorn.trigger("IriSP.PlayerWidget.MouseOut")});this.muteButtonUpdater()};
+IriSP.PlayerWidget.prototype.timeDisplayUpdater=function(){if(this._previousSecond===undefined)this._previousSecond=this._Popcorn.roundTime();else if(this._Popcorn.roundTime()==this._previousSecond)return;var a=+this._serializer.currentMedia().meta["dc:duration"]/1E3;a=IriSP.secondsToTime(a);var c=IriSP.secondsToTime(this._Popcorn.currentTime());this.selector.find(".Ldt-ElapsedTime").html(c.toString());this.selector.find(".Ldt-TotalTime").html(a.toString());this._previousSecond=this._Popcorn.roundTime()};
+IriSP.PlayerWidget.prototype.playButtonUpdater=function(){if(this._Popcorn.media.paused==true){this.selector.find(".Ldt-CtrlPlay").attr("title","Play");var a=IriSP.templToHTML("url({{img_dir}}/play_sprite.png)")}else{this.selector.find(".Ldt-CtrlPlay").attr("title","Pause");a=IriSP.templToHTML("url({{img_dir}}/pause_sprite.png)")}this.selector.find(".Ldt-CtrlPlay").css("background-image",a)};
+IriSP.PlayerWidget.prototype.playHandler=function(){this._Popcorn.media.paused==true?this._Popcorn.play():this._Popcorn.pause()};IriSP.PlayerWidget.prototype.muteHandler=function(){this._Popcorn.muted()?this._Popcorn.mute(false):this._Popcorn.mute(true)};
+IriSP.PlayerWidget.prototype.muteButtonUpdater=function(){if(this._Popcorn.media.muted==true){this.selector.find(".Ldt-CtrlSound").attr("title","Unmute");var a=IriSP.templToHTML("url({{img_dir}}/sound_sprite.png)")}else{this.selector.find(".Ldt-CtrlSound").attr("title","Mute");a=IriSP.templToHTML("url({{img_dir}}/mute_sprite.png)")}this.selector.find(".Ldt-CtrlSound").css("background-image",a)};
+IriSP.PlayerWidget.prototype.searchButtonHandler=function(){var a=this;if(this._searchBlockOpen==false){this.selector.find(".LdtSearch").show("blind",{direction:"horizontal"},100);this.selector.find(".LdtSearchInput").css("background-color","#fff");this.selector.find(".LdtSearchInput").focus();this.selector.find(".LdtSearchInput").attr("value",this._searchLastValue);this._Popcorn.trigger("IriSP.search",this._searchLastValue);this._searchBlockOpen=true;this.selector.find(".LdtSearchInput").bind("keyup",
+null,function(){a.searchHandler.call(a)});this._positiveMatch=false;this._Popcorn.trigger("IriSP.search.open")}else{this._searchLastValue=this.selector.find(".LdtSearchInput").attr("value");this.selector.find(".LdtSearchInput").attr("value","");this.selector.find(".LdtSearch").hide("blind",{direction:"horizontal"},75);this.selector.find(".LdtSearchInput").unbind("keypress set");this._positiveMatch=this._searchBlockOpen=false;this._Popcorn.trigger("IriSP.search.closed")}};
+IriSP.PlayerWidget.prototype.searchHandler=function(){this._searchLastValue=this.selector.find(".LdtSearchInput").attr("value");this._positiveMatch=false;if(this._searchLastValue==""){this._Popcorn.trigger("IriSP.search.cleared");this.selector.find(".LdtSearchInput").css("background-color","")}else this._Popcorn.trigger("IriSP.search",this._searchLastValue)};IriSP.PlayerWidget.prototype.searchMatch=function(){this._positiveMatch=true;this.selector.find(".LdtSearchInput").css("background-color","#e1ffe1")};
+IriSP.PlayerWidget.prototype.searchNoMatch=function(){this._positiveMatch!==true&&this.selector.find(".LdtSearchInput").css("background-color","#d62e3a")};
+IriSP.PolemicWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this.userPol=[];this.userNoPol=[];this.userst=[];this.numberOfTweet=0;this.yMax=this.height;this.tweets=[];this.svgElements={};this.oldSearchMatches=[];this.paper=Raphael(document.getElementById(this._id),c.width,c.height);this._Popcorn.listen("IriSP.search",IriSP.wrap(this,function(i){this.searchHandler(i)}));this._Popcorn.listen("IriSP.search.closed",IriSP.wrap(this,this.searchFieldClosedHandler));this._Popcorn.listen("IriSP.search.cleared",
+IriSP.wrap(this,this.searchFieldClearedHandler))};IriSP.PolemicWidget.prototype=new IriSP.Widget;
+IriSP.PolemicWidget.prototype.draw=function(){function a(u){if(u=="Q"){N+=1;return 2}else if(u=="REF"){J+=1;return 4}else if(u=="OK"){I+=1;return 1}else if(u=="KO"){H+=1;return 3}else if(u==""){E+=1;return 5}}function c(u){var y=this._serializer.getTweets();if(typeof y==="undefined"){y=this._serializer.getTweetIds()[0];if(typeof y==="undefined"){view=u.views[0];if(typeof view.annotation_types!=="undefined")if(view.annotation_types.length>=1)y=view.annotation_types[0];else console.log("PolemicWidget: invalid file")}}for(var B=
+0;B<u.annotations.length;B++){var f=u.annotations[B],z=Math.floor(f.begin/l*n),Q=Math.floor(z/n*q);if(typeof f.meta!=="undefined"&&typeof f.meta["id-ref"]!=="undefined"&&f.meta["id-ref"]===y){var r={};if(typeof f.meta["dc:source"]!=="undefined")r=JSON.parse(f.meta["dc:source"].content);if(f.content.polemics!=undefined&&f.content.polemics[0]!=null)for(var D=0;D<f.content.polemics.length;D++){this.tweets[x]={id:B,qualification:a(f.content.polemics[D]),yIndicator:z,yframe:Q,title:f.content.title,timeframe:f.begin,
+userId:r.id,userScreenName:r.screen_name,tsource:r,cinecast_id:f.id};x+=1}else{this.tweets[x]={id:B,qualification:a(""),yIndicator:z,yframe:Q,title:f.content.title,timeframe:f.begin,userId:r.id,userScreenName:r.screen_name,tsource:r,cinecast_id:f.id};x+=1}}}d.call(this)}function d(){x=this.tweets.length;for(var u=0;u<C;u++)for(var y=0;y<x;y++)if(u==this.tweets[y].yframe){var B=this.tweets[y].qualification;if(o[u]==undefined)o[u]={id:u,qualifVol:[],mytweetsID:[]};o[u].mytweetsID.push(this.tweets[y]);
+if(o[u].qualifVol[B]==undefined)o[u].qualifVol[B]=1;else o[u].qualifVol[B]+=1}for(u=B=0;u<C;u++){var f=0;for(y=0;y<6;y++)if(o[u]!=undefined)if(o[u].qualifVol[y]!=undefined)f+=o[u].qualifVol[y];if(f>B)B=f}u=5*B+10;if(u>this.height){this.paper.setSize(this.width,u);this.height=u;console.log("resizeing")}for(u=0;u<C;u++){f=5;if(o[u]!=undefined)for(y=6;y>-1;y--)if(o[u].qualifVol[y]!=undefined)for(B=0;B<o[u].mytweetsID.length;B++)if(o[u].mytweetsID[B].qualification==y){var z=u*h,Q=this.height-f;if(this.yMax>
+Q)this.yMax=Q;if(!this.svgElements.hasOwnProperty(o[u].mytweetsID[B].cinecast_id)){z=this.paper.rect(z,Q,h-m,5).attr({stroke:"#00","stroke-width":0.1,fill:s[y]});f+=5;z.color=s[y];z.time=o[u].mytweetsID[B].timeframe;z.title=o[u].mytweetsID[B].title;z.id=o[u].mytweetsID[B].cinecast_id;this.svgElements[z.id]=z;IriSP.jQuery(z.node).mouseenter(function(r){return function(D){i.TooltipWidget.show.call(i.TooltipWidget,r.title,r.attr("fill"),D.pageX-106,D.pageY-160);r.displayed=true}}(z)).mousedown(function(r){return function(){i._Popcorn.currentTime(r.time/
+1E3);i._Popcorn.trigger("IriSP.PolemicTweet.click",r.id)}}(z));IriSP.jQuery(z.node).attr("id","t"+B+"");IriSP.jQuery(z.node).attr("title",o[u].mytweetsID[B].title);IriSP.jQuery(z.node).attr("begin",o[u].mytweetsID[B].timeframe)}}}this.paperBackground=this.paper.rect(0,0,this.width,this.height).attr({fill:"#F8F8F8","stroke-width":0.1,opacity:1});this.outerBorders=[];this.outerBorders.push(this.paper.rect(0,this.height-1,this.width,1).attr({fill:"#ababab",stroke:"none",opacity:1}));this.outerBorders.push(this.paper.rect(0,
+0,this.width,1).attr({fill:"#ababab",stroke:"none",opacity:1}));this.innerBorders=[];this.innerBorders.push(this.paper.rect(1,this.height-2,this.width,1).attr({fill:"#efefef",stroke:"none",opacity:1}));this.innerBorders.push(this.paper.rect(1,1,this.width,1).attr({fill:"#efefef",stroke:"none",opacity:1}));this.innerBorders.push(this.paper.rect(1,1,1,this.height-2).attr({fill:"#d0d1d1",stroke:"none",opacity:0.8}));this.innerBorders.push(this.paper.rect(this.width-2,1,1,this.height-2).attr({fill:"#efefef",
+stroke:"none",opacity:1}));this.paperSlider=this.paper.rect(0,0,0,this.height).attr({fill:"#D4D5D5",stroke:"none",opacity:1});this.sliderTip=this.paper.rect(0,0,1,this.height).attr({fill:"#fc00ff",stroke:"none",opacity:1});this.paperSlider.toBack();this.paperBackground.toBack();this.sliderTip.toFront()}var i=this,h=5,m=1,n=this.width,C=n/h,x=0,l=+this._serializer.currentMedia().meta["dc:duration"],q=n/h,s=Array("","#1D973D","#C5A62D","#CE0A15","#036AAE","#585858"),o=Array(q),v=function(){};v=function(){};
+v.prototype.draw=function(){};v.prototype.zoom=function(){};v.prototype.inside=function(){};v=function(){};v=function(){};var E=0,N=0,J=0,I=0,H=0;this._serializer.sync(function(u){c.call(i,u)});this.selector.mouseleave(IriSP.wrap(this,function(){i.TooltipWidget.hide.call(i.TooltipWidget)}));this._Popcorn.listen("timeupdate",IriSP.wrap(this,this.sliderUpdater))};
+IriSP.PolemicWidget.prototype.sliderUpdater=function(){var a=+this._Popcorn.currentTime(),c=+this._serializer.currentMedia().meta["dc:duration"];this.paperSlider.attr("width",a*(this.width/(c/1E3)));this.sliderTip.attr("x",a*(this.width/(c/1E3)))};
+IriSP.PolemicWidget.prototype.searchHandler=function(a){if(a!=""){a=this._serializer.searchTweetsOccurences(a);IriSP.countProperties(a)>0?this._Popcorn.trigger("IriSP.search.matchFound"):this._Popcorn.trigger("IriSP.search.noMatchFound");for(var c in this.svgElements){var d=this.svgElements[c];d.attr({fill:d.color,opacity:0.4})}for(c in a)this.svgElements.hasOwnProperty(c)&&this.svgElements[c].attr({fill:"#fc00ff",opacity:1});this.oldSearchMatches=a}};
+IriSP.PolemicWidget.prototype.searchFieldClearedHandler=function(){for(var a in this.svgElements){var c=this.svgElements[a];c.attr({fill:c.color,opacity:1})}};IriSP.PolemicWidget.prototype.searchFieldClosedHandler=function(){for(var a in this.svgElements){var c=this.svgElements[a];c.attr({fill:c.color,opacity:1})}};
+IriSP.SegmentsWidget=function(a,c,d){var i=this;IriSP.Widget.call(this,a,c,d);this.oldSearchMatches=[];this._Popcorn.listen("IriSP.search",function(h){i.searchHandler.call(i,h)});this._Popcorn.listen("IriSP.search.closed",function(){i.searchFieldClosedHandler.call(i)});this._Popcorn.listen("IriSP.search.cleared",function(){i.searchFieldClearedHandler.call(i)})};IriSP.SegmentsWidget.prototype=new IriSP.Widget;
+IriSP.SegmentsWidget.prototype.segmentToPixel=function(a){var c=Math.round(+a.begin/1E3);a=Math.round(+a.end/1E3);var d=this._serializer.currentMedia().meta["dc:duration"]/1E3;c=IriSP.timeToPourcent(c,d);this.selector.parent().width();c=Math.floor(IriSP.timeToPourcent(a,d)-c);return Math.floor(this.selector.parent().width()*(c/100))};IriSP.SegmentsWidget.prototype.segmentsLength=function(a){for(var c=0,d=0;d<a.length;d++)c+=this.segmentToPixel(a[d].annotation);return c};
+IriSP.SegmentsWidget.prototype.draw=function(){var a=this,c=this._serializer._data.annotations;this.selector.addClass("Ldt-SegmentsWidget");this.selector.append(Mustache.to_html(IriSP.overlay_marker_template));var d=this._serializer.getChapitrage();if(typeof d==="undefined")d=this._serializer.getNonTweetIds()[0];this.positionMarker=this.selector.children(":first");this._Popcorn.listen("timeupdate",IriSP.wrap(this,this.positionUpdater));var i=0,h=[];for(i=0;i<c.length;i++){var m=c[i];d!=""&&typeof m.meta!==
+"undefined"&&typeof m.meta["id-ref"]!=="undefined"&&m.meta["id-ref"]!=d||h.push(m)}this.selector.width();c=IriSP.underscore.max(h,function(o){return o.end});for(i=0;i<h.length;i++){m=h[i];d=+m.begin;var n=+m.end,C=this._serializer.currentMedia().meta["dc:duration"],x=m.id,l=Math.floor(this.selector.parent().width()*(d/C));n=Math.floor(this.selector.parent().width()*(n/C));n=m.id!==c.id?n-l-1:n-l;C=(m.content.title+" - "+m.content.description).substr(0,55);var q=typeof m.content.color!=="undefined"?
+m.content.color:m.color,s=IriSP.DEC_HEXA_COLOR(q);if(s==="FFCC00")s="333";if(s.length==4)s+="00";this.selector.append(Mustache.to_html(IriSP.annotation_template,{divTitle:C,id:x,startPixel:l,pxWidth:n,hexa_color:s,seekPlace:Math.round(d/1E3)}));if(m.id===c.id){this.selector.find("#"+x).addClass("Ldt-lastSegment");this.selector.find(".Ldt-lastSegment").css("border-color","#"+s)}IriSP.jQuery("#"+x).fadeTo(0,0.3);IriSP.jQuery("#"+x).mouseover(function(o){return function(){IriSP.jQuery(this).animate({opacity:0.6},
+5);var v=IriSP.jQuery(this).offset(),E=IriSP.jQuery(this).outerWidth()/2;E=v.left+E-106;if(E<0)E=0;a.TooltipWidget.show(o,q,E,v.top-160)}}(C)).mouseout(function(){IriSP.jQuery(this).animate({opacity:0.3},5);a.TooltipWidget.hide()});IriSP.jQuery("#"+x).click(function(o,v){return function(){o.clickHandler(v)}}(this,m))}};IriSP.SegmentsWidget.prototype.clear=function(){this.selector.children(".Ldt-iri-chapter").animate({opacity:0.3},100)};
+IriSP.SegmentsWidget.prototype.clickHandler=function(a){this._Popcorn.trigger("IriSP.SegmentsWidget.click",a.id);this._Popcorn.currentTime(Math.round(+a.begin/1E3))};
+IriSP.SegmentsWidget.prototype.searchHandler=function(a){if(a!=""){a=this._serializer.searchOccurences(a);IriSP.countProperties(a)>0?this._Popcorn.trigger("IriSP.search.matchFound"):this._Popcorn.trigger("IriSP.search.noMatchFound");this.selector.children(".Ldt-iri-chapter").css("opacity",0.1);for(var c in a){var d=0.5+a[c]*0.2;this.selector.find("#"+c).dequeue();this.selector.find("#"+c).animate({opacity:d},200)}this.oldSearchMatches=a}};IriSP.SegmentsWidget.prototype.searchFieldClearedHandler=function(){this.clear()};
+IriSP.SegmentsWidget.prototype.searchFieldClosedHandler=function(){this.clear()};IriSP.SegmentsWidget.prototype.positionUpdater=function(){var a=this._serializer.currentMedia().meta["dc:duration"]/1E3;this.positionMarker.css("left",(this._Popcorn.currentTime()/a*100).toFixed(2)+"%")};IriSP.SliceWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d)};IriSP.SliceWidget.prototype=new IriSP.Widget;
+IriSP.SliceWidget.prototype.draw=function(){this.selector.append(Mustache.to_html(IriSP.sliceWidget_template));this.sliceZone=this.selector.find(".Ldt-sliceZone");this.zoneWidth=this.zoneLeft=0;this.leftHandle=this.selector.find(".Ldt-sliceLeftHandle");this.rightHandle=this.selector.find(".Ldt-sliceRightHandle");this.leftHandle.draggable({axis:"x",drag:IriSP.wrap(this,this.leftHandleDragged),containment:"parent"});this.rightHandle.draggable({axis:"x",drag:IriSP.wrap(this,this.rightHandleDragged),
+containment:"parent"});this.leftHandle.css("position","absolute");this.rightHandle.css("position","absolute");this._Popcorn.listen("IriSP.SliceWidget.position",IriSP.wrap(this,this.positionSliceHandler));this._Popcorn.trigger("IriSP.SliceWidget.position",[57,24])};
+IriSP.SliceWidget.prototype.positionSliceHandler=function(a){left=a[0];width=a[1];this.zoneLeft=left;this.zoneWidth=width;this.sliceZone.css("left",left+"px");this.sliceZone.css("width",width+"px");this.leftHandle.css("left",left-7+"px");this.rightHandle.css("left",left+width+"px");this._leftHandleOldLeft=left-7;this._rightHandleOldLeft=left+width};
+IriSP.SliceWidget.prototype.leftHandleDragged=function(a,c){var d=this.leftHandle.position().left,i=this.rightHandle.position().left;if(d>=i-7&&c.position.left>=this._leftHandleOldLeft)c.position.left=this._leftHandleOldLeft;this.zoneWidth+=this.zoneLeft-(d+7);this.zoneLeft=d+7;this.sliceZone.css("width",this.zoneWidth);this.sliceZone.css("left",this.zoneLeft+"px");this.broadcastChanges();this._leftHandleOldLeft=c.position.left};
+IriSP.SliceWidget.prototype.rightHandleDragged=function(a,c){var d=this.rightHandle.position().left,i=this.leftHandle.position().left;if(d<=i+7&&c.position.left<=this._rightHandleOldLeft)c.position.left=this._rightHandleOldLeft;this.zoneWidth+=d-(this.zoneLeft+this.zoneWidth);this.sliceZone.css("width",this.zoneWidth);this.broadcastChanges();this._rightHandleOldLeft=c.position.left};
+IriSP.SliceWidget.prototype.broadcastChanges=function(){var a=this.zoneLeft/this.selector.width()*100,c=this.zoneWidth/this.selector.width()*100;this._Popcorn.trigger("IriSP.SliceWidget.zoneChange",[a,c])};IriSP.SliderWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d)};IriSP.SliderWidget.prototype=new IriSP.Widget;
+IriSP.SliderWidget.prototype.draw=function(){var a=this;this.selector.append(Mustache.to_html(IriSP.sliderWidget_template,{}));this.selector.addClass("Ldt-SliderMinimized");this.sliderBackground=this.selector.find(".Ldt-sliderBackground");this.sliderForeground=this.selector.find(".Ldt-sliderForeground");this.positionMarker=this.selector.find(".Ldt-sliderPositionMarker");this.sliderMaximized=this.draggingOngoing=false;this.timeOutId=null;this.positionMarker.draggable({axis:"x",start:IriSP.wrap(this,
+this.positionMarkerDraggingStartedHandler),stop:IriSP.wrap(this,this.positionMarkerDraggedHandler),containment:"parent"});this.positionMarker.css("position","absolute");this.sliderBackground.click(function(c){a.backgroundClickHandler.call(a,c)});this.sliderForeground.click(function(c){a.foregroundClickHandler.call(a,c)});this.selector.hover(IriSP.wrap(this,this.mouseOverHandler),IriSP.wrap(this,this.mouseOutHandler));this._Popcorn.listen("timeupdate",IriSP.wrap(this,this.sliderUpdater));this._Popcorn.listen("IriSP.PlayerWidget.MouseOver",
+IriSP.wrap(this,this.mouseOverHandler));this._Popcorn.listen("IriSP.PlayerWidget.MouseOut",IriSP.wrap(this,this.mouseOutHandler))};
+IriSP.SliderWidget.prototype.sliderUpdater=function(){if(!(this.draggingOngoing||this._disableUpdate)){var a=this._Popcorn.currentTime(),c=this._serializer.currentMedia().meta["dc:duration"]/1E3;a=(a/c*100).toFixed(2);c=100/this.selector.width();var d=this.positionMarker.width();c=a-c*d/2;if(c<=0)c=0;this.sliderForeground.css("width",a+"%");this.positionMarker.css("left",c+"%")}};
+IriSP.SliderWidget.prototype.backgroundClickHandler=function(a){var c=this.sliderBackground.parent().offset(),d=this.sliderBackground.width();a=a.pageX-c.left;c=this._serializer.currentMedia().meta["dc:duration"]/1E3;this._Popcorn.currentTime((a/d*c).toFixed(2))};
+IriSP.SliderWidget.prototype.foregroundClickHandler=function(a){var c=this.sliderForeground.parent().offset(),d=this.sliderBackground.width();a=a.pageX-c.left;c=this._serializer.currentMedia().meta["dc:duration"]/1E3;this._Popcorn.currentTime((a/d*c).toFixed(2))};
+IriSP.SliderWidget.prototype.mouseOverHandler=function(){this.timeOutId!==null&&window.clearTimeout(this.timeOutId);this.sliderMaximized=true;this.sliderBackground.animate({height:"9px"},100);this.sliderForeground.animate({height:"9px"},100);this.positionMarker.animate({height:"9px",width:"9px"},100)};IriSP.SliderWidget.prototype.mouseOutHandler=function(){this.timeOutId=window.setTimeout(IriSP.wrap(this,this.minimizeOnTimeout),IriSP.widgetsDefaults.SliderWidget.minimize_period)};
+IriSP.SliderWidget.prototype.minimizeOnTimeout=function(){this.sliderBackground.animate({height:"5px"},100);this.sliderForeground.animate({height:"5px"},100);this.positionMarker.animate({height:"5px",width:"5px"},100);this.positionMarker.css("margin-top","0px");this.sliderMinimized=true};IriSP.SliderWidget.prototype.positionMarkerDraggingStartedHandler=function(){this.draggingOngoing=true};
+IriSP.SliderWidget.prototype.positionMarkerDraggedHandler=function(a){this._disableUpdate=true;window.setTimeout(IriSP.wrap(this,function(){this._disableUpdate=false}),500);var c=this.sliderForeground.parent().offset(),d=this.sliderBackground.width();a=a.pageX-c.left;c=this._serializer.currentMedia().meta["dc:duration"]/1E3;this._Popcorn.currentTime((a/d*c).toFixed(2));this.draggingOngoing=false};IriSP.SparklineWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this._oldAnnotation=null};
+IriSP.SparklineWidget.prototype=new IriSP.Widget;IriSP.SparklineWidget.prototype.clear=function(){};
+IriSP.SparklineWidget.prototype.draw=function(){for(var a=Mustache.to_html(IriSP.SparklineWidget_template,{width:this.width,height:this.height}),c=this.selector.width()/10,d=+this._serializer.currentMedia().meta["dc:duration"]/c,i=[],h=0,m=0;m<c&&h<this._serializer._data.annotations.length;m++){for(var n=0,C=+this._serializer._data.annotations[h].begin;C>=m*d&&C<=(m+1)*d;){n++;h++;if(h>=this._serializer._data.annotations.length)break;C=+this._serializer._data.annotations[h].begin}i.push(n)}this.selector.append(a);
+this.selector.find(".Ldt-sparkLine").css("background","#c7c8cc");this.selector.find(".Ldt-sparkLine").sparkline(i,{lineColor:"#7492b4",fillColor:"#aeaeb8",spotColor:"#b70056",width:this.width,height:this.height});this._Popcorn.listen("timeupdate",IriSP.wrap(this,this.timeUpdateHandler));IriSP.jQuery(".Ldt-sparkLineClickOverlay").click(IriSP.wrap(this,this.clickHandler))};
+IriSP.SparklineWidget.prototype.timeUpdateHandler=function(){var a=this._Popcorn.currentTime(),c=+this._serializer.currentMedia().meta["dc:duration"]/1E3;a=(a/c*100).toFixed(4);IriSP.jQuery(".Ldt-sparkLinePositionMarker").css("width",a+"%")};
+IriSP.SparklineWidget.prototype.clickHandler=function(a){var c=this.selector.offset(),d=this.selector.width();a=a.pageX-c.left;c=this._serializer.currentMedia().meta["dc:duration"]/1E3;d=(a/d*c).toFixed(2);this._Popcorn.trigger("IriSP.SparklineWidget.clicked",d);this._Popcorn.currentTime(d)};IriSP.TooltipWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this._shown=false;this._displayedText="";this._hideTimeout=-1};IriSP.TooltipWidget.prototype=new IriSP.Widget;
+IriSP.TooltipWidget.prototype.draw=function(){var a=Mustache.to_html(IriSP.tooltipWidget_template);this.selector.css("position","static");this.selector.append(a);this.hide()};IriSP.TooltipWidget.prototype.clear=function(){this.selector.find(".tiptext").text("")};
+IriSP.TooltipWidget.prototype.show=function(a,c,d,i){if(!(this._displayedText==a&&this._shown)){this.selector.find(".tipcolor").css("background-color",c);this._displayedText=a;this.selector.find(".tiptext").text(a);this.selector.find(".tip").css("left",d).css("top",i);this.selector.find(".tip").show();this._shown=true}};IriSP.TooltipWidget.prototype.hide=function(){this.selector.find(".tip").hide();this._shown=false};
+IriSP.TweetsWidget=function(a,c,d){IriSP.Widget.call(this,a,c,d);this._displayingTweet=false;this._timeoutId=undefined;this._hidden=false};IriSP.TweetsWidget.prototype=new IriSP.Widget;
+IriSP.TweetsWidget.prototype.drawTweet=function(a){if(!this._hidden){var c=IriSP.formatTweet(a.content.title),d=a.content.img.src;if(typeof d==="undefined"||d===""||d==="None")d=IriSP.widgetsDefaults.TweetsWidget.default_profile_picture;var i=IriSP.templToHTML("<img src='{{src}}' alt='user image'></img>",{src:d});if(typeof a.meta["dc:source"].content!=="undefined"){var h=JSON.parse(a.meta["dc:source"].content),m=h.user.screen_name,n=h.user.name;i=IriSP.templToHTML("<a href='http://twitter.com/{{creator}}'><img src='{{src}}' alt='user image'></img></a>",
+{src:d,creator:m});d=(new Date(h.created_at)).toLocaleDateString();c=IriSP.templToHTML("<a class='Ldt-tweet_userHandle' href='http://twitter.com/{{creator}}'>@{{creator}}</a> - <div class='Ldt-tweet_realName'>{{real_name}}</div><div class='Ldt-tweet_tweetContents'>{{{ contents }}}</div><div class='Ldt-tweet_date'>{{ date }}</div>",{creator:m,real_name:n,contents:c,date:d});this.selector.find(".Ldt-TweetReply").attr("href","http://twitter.com/home?status=@"+m+":%20");a=Mustache.to_html("http://twitter.com/home?status=RT @{{creator}}: {{text}}",
+{creator:m,text:IriSP.encodeURI(a.content.title)});this.selector.find(".Ldt-Retweet").attr("href",a)}this.selector.find(".Ldt-tweetContents").html(c);this.selector.find(".Ldt-tweetAvatar").html(i);this.selector.show("blind",250)}};IriSP.TweetsWidget.prototype.displayTweet=function(a){if(this._displayingTweet===false)this._displayingTweet=true;else window.clearTimeout(this._timeoutId);this.drawTweet(a);this._Popcorn.currentTime();this._timeoutId=window.setTimeout(IriSP.wrap(this,this.clearPanel),IriSP.widgetsDefaults.TweetsWidget.tweet_display_period)};
+IriSP.TweetsWidget.prototype.clearPanel=function(){this._displayingTweet=false;this._timeoutId=undefined;this.closePanel()};IriSP.TweetsWidget.prototype.closePanel=function(){if(this._timeoutId!=undefined){window.clearTimeout(this._timeoutId);this._timeoutId=null}this.selector.hide("blind",400)};IriSP.TweetsWidget.prototype.keepPanel=function(){if(this._timeoutId!=undefined){window.clearTimeout(this._timeoutId);this._timeoutId=null}};
+IriSP.TweetsWidget.prototype.draw=function(){this.selector.append(IriSP.templToHTML(IriSP.tweetWidget_template,{share_template:IriSP.share_template}));this.selector.hide();this.selector.find(".Ldt-tweetWidgetMinimize").click(IriSP.wrap(this,this.closePanel));this.selector.find(".Ldt-tweetWidgetKeepOpen").click(IriSP.wrap(this,this.keepPanel));this._Popcorn.listen("IriSP.PolemicTweet.click",IriSP.wrap(this,this.PolemicTweetClickHandler));this._Popcorn.listen("IriSP.PlayerWidget.AnnotateButton.clicked",
+IriSP.wrap(this,this.handleAnnotateSignal))};IriSP.TweetsWidget.prototype.PolemicTweetClickHandler=function(a){var c,d;for(c in this._serializer._data.annotations){d=this._serializer._data.annotations[c];if(d.id===a)break}d.id===a&&this.displayTweet(d)};IriSP.TweetsWidget.prototype.handleAnnotateSignal=function(){if(this._hidden==false){this.selector.hide();this._hidden=true}else{this._displayingTweet!==false&&this.selector.show();this._hidden=false}};
+IriSP.JSONSerializer=function(a,c){IriSP.Serializer.call(this,a,c)};IriSP.JSONSerializer.prototype=new IriSP.Serializer;IriSP.JSONSerializer.prototype.serialize=function(a){return JSON.stringify(a)};IriSP.JSONSerializer.prototype.deserialize=function(a){return JSON.parse(a)};IriSP.JSONSerializer.prototype.sync=function(a){var c=this;this._DataLoader.get(this._url,function(d){c._data=d;c._data.annotations.sort(function(i,h){return+i.begin-+h.begin});a(d)})};
+IriSP.JSONSerializer.prototype.currentMedia=function(){return this._data.medias[0]};
+IriSP.JSONSerializer.prototype.searchAnnotations=function(a,c,d){var i;if(typeof this._data.views!=="undefined"&&this._data.views!==null)i=this._data.views[0];var h="";if(typeof i!=="undefined"&&typeof i.annotation_types!=="undefined"&&i.annotation_types.length>1)h=i.annotation_types[0];return this.searchAnnotationsFilter(a,c,d,function(m){return h!=""&&typeof m.meta!=="undefined"&&typeof m.meta["id-ref"]!=="undefined"&&m.meta["id-ref"]!==h?true:false})};
+IriSP.JSONSerializer.prototype.searchTweets=function(a,c,d){var i;if(typeof this._data.views!=="undefined"&&this._data.views!==null)i=this._data.views[0];var h="";if(typeof i!=="undefined"&&typeof i.annotation_types!=="undefined"&&i.annotation_types.length>1)h=i.annotation_types[0];return this.searchAnnotationsFilter(a,c,d,function(m){return h!=""&&typeof m.meta!=="undefined"&&typeof m.meta["id-ref"]!=="undefined"&&m.meta["id-ref"]!==h?false:true})};
+IriSP.JSONSerializer.prototype.searchAnnotationsFilter=function(a,c,d,i){if(a=="")a=".*";if(c=="")c=".*";if(d=="")d=".*";a=RegExp(a,"i");c=RegExp(c,"i");RegExp(d,"i");d=[];var h;for(h in this._data.annotations){var m=this._data.annotations[h];i(m)||a.test(m.content.title)&&c.test(m.content.description)&&d.push(m)}return d};
+IriSP.JSONSerializer.prototype.searchOccurences=function(a){var c={};a=a.split(/\s+/);for(var d in a){var i=a[d],h=[];h=h.concat(this.searchAnnotations(i,"",""));h=h.concat(this.searchAnnotations("",i,""));for(var m in h){i=h[m];if(c.hasOwnProperty(i.id))c[i.id]+=1;else c[i.id]=1}}return c};
+IriSP.JSONSerializer.prototype.searchTweetsOccurences=function(a){var c={};a=a.split(/\s+/);for(var d in a){var i=a[d],h=[];h=h.concat(this.searchTweets(i,"",""));h=h.concat(this.searchTweets("",i,""));for(var m in h){i=h[m];if(c.hasOwnProperty(i.id))c[i.id]+=1;else c[i.id]=1}}return c};
+IriSP.JSONSerializer.prototype.currentAnnotations=function(a,c){var d=1E3*a,i=typeof c==="undefined"?this.getNonTweetIds():[c],h=[],m;for(m in this._data.annotations){var n=this._data.annotations[m];IriSP.underscore.include(i,n.meta["id-ref"])&&n.begin<=d&&n.end>=d&&h.push(n)}h==[]&&console.log("ret_array empty, ",i);return h};
+IriSP.JSONSerializer.prototype.getTweetIds=function(){if(typeof this._data.lists==="undefined"||this._data.lists===null)return[];var a=[];a=IriSP.underscore.filter(this._data.lists,function(c){return c.id.indexOf("tweet")!==-1});if(a.length===0)return[];return a=IriSP.underscore.pluck(a[0].items,"id-ref")};
+IriSP.JSONSerializer.prototype.getNonTweetIds=function(){if(typeof this._data.lists==="undefined"||this._data.lists===null)return[];var a=IriSP.underscore.flatten(IriSP.underscore.map(this._data.lists,function(d){return IriSP.underscore.pluck(d.items,"id-ref")})),c=this.getTweetIds();return IriSP.underscore.difference(a,c)};
+IriSP.JSONSerializer.prototype.getId=function(a){if(!(typeof this._data.lists==="undefined"||this._data.lists===null)){var c;c=IriSP.underscore.find(this._data["annotation-types"],function(d){return d["dc:title"].indexOf(a)!==-1});if(typeof c!=="undefined")return c.id}};IriSP.JSONSerializer.prototype.getChapitrage=function(){return this.getId("Chapitrage")};IriSP.JSONSerializer.prototype.getTweets=function(){return this.getId("Tweets")};IriSP.JSONSerializer.prototype.getContributions=function(){return this.getId("Contributions")};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/jquery.sparkline.js	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,1271 @@
+/**
+*
+* jquery.sparkline.js
+*
+* v1.6
+* (c) Splunk, Inc 
+* Contact: Gareth Watts (gareth@splunk.com)
+* http://omnipotent.net/jquery.sparkline/
+*
+* Generates inline sparkline charts from data supplied either to the method
+* or inline in HTML
+* 
+* Compatible with Internet Explorer 6.0+ and modern browsers equipped with the canvas tag
+* (Firefox 2.0+, Safari, Opera, etc)
+*
+* License: New BSD License
+* 
+* Copyright (c) 2010, Splunk Inc.
+* 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 Splunk Inc nor the names of its 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 OWNER 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.
+* 
+*
+* Usage: 
+*  $(selector).sparkline(values, options)
+*
+* If values is undefined or set to 'html' then the data values are read from the specified tag:
+*   <p>Sparkline: <span class="sparkline">1,4,6,6,8,5,3,5</span></p>
+*   $('.sparkline').sparkline();
+* There must be no spaces in the enclosed data set
+*
+* Otherwise values must be an array of numbers or null values
+*    <p>Sparkline: <span id="sparkline1">This text replaced if the browser is compatible</span></p>
+*    $('#sparkline1').sparkline([1,4,6,6,8,5,3,5])
+*    $('#sparkline2').sparkline([1,4,6,null,null,5,3,5])
+*
+* Values can also be specified in an HTML comment, or as a values attribute:
+*    <p>Sparkline: <span class="sparkline"><!--1,4,6,6,8,5,3,5 --></span></p>
+*    <p>Sparkline: <span class="sparkline" values="1,4,6,6,8,5,3,5"></span></p>
+*    $('.sparkline').sparkline();
+*
+* For line charts, x values can also be specified:
+*   <p>Sparkline: <span class="sparkline">1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5</span></p>
+*    $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5], [9,3], [10,5] ])
+*
+* By default, options should be passed in as teh second argument to the sparkline function:
+*   $('.sparkline').sparkline([1,2,3,4], {type: 'bar'})
+*
+* Options can also be set by passing them on the tag itself.  This feature is disabled by default though
+* as there's a slight performance overhead:
+*   $('.sparkline').sparkline([1,2,3,4], {enableTagOptions: true})
+*   <p>Sparkline: <span class="sparkline" sparkType="bar" sparkBarColor="red">loading</span></p>
+* Prefix all options supplied as tag attribute with "spark" (configurable by setting tagOptionPrefix)
+*
+* Supported options:
+*   lineColor - Color of the line used for the chart
+*   fillColor - Color used to fill in the chart - Set to '' or false for a transparent chart
+*   width - Width of the chart - Defaults to 3 times the number of values in pixels
+*   height - Height of the chart - Defaults to the height of the containing element
+*   chartRangeMin - Specify the minimum value to use for the Y range of the chart - Defaults to the minimum value supplied
+*   chartRangeMax - Specify the maximum value to use for the Y range of the chart - Defaults to the maximum value supplied
+*   chartRangeClip - Clip out of range values to the max/min specified by chartRangeMin and chartRangeMax
+*   chartRangeMinX - Specify the minimum value to use for the X range of the chart - Defaults to the minimum value supplied
+*   chartRangeMaxX - Specify the maximum value to use for the X range of the chart - Defaults to the maximum value supplied
+*   composite - If true then don't erase any existing chart attached to the tag, but draw
+*           another chart over the top - Note that width and height are ignored if an
+*           existing chart is detected.
+*   tagValuesAttribute - Name of tag attribute to check for data values - Defaults to 'values'
+*   enableTagOptions - Whether to check tags for sparkline options 
+*   tagOptionPrefix - Prefix used for options supplied as tag attributes - Defaults to 'spark'
+*
+* There are 7 types of sparkline, selected by supplying a "type" option of 'line' (default),
+* 'bar', 'tristate', 'bullet', 'discrete', 'pie' or 'box'
+*    line - Line chart.  Options:
+*       spotColor - Set to '' to not end each line in a circular spot
+*       minSpotColor - If set, color of spot at minimum value
+*       maxSpotColor - If set, color of spot at maximum value
+*       spotRadius - Radius in pixels
+*       lineWidth - Width of line in pixels
+*       normalRangeMin 
+*       normalRangeMax - If set draws a filled horizontal bar between these two values marking the "normal"
+*                      or expected range of values
+*       normalRangeColor - Color to use for the above bar
+*       drawNormalOnTop - Draw the normal range above the chart fill color if true
+*       defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the chart
+*
+*   bar - Bar chart.  Options:
+*       barColor - Color of bars for postive values
+*       negBarColor - Color of bars for negative values
+*       zeroColor - Color of bars with zero values
+*       nullColor - Color of bars with null values - Defaults to omitting the bar entirely
+*       barWidth - Width of bars in pixels
+*       colorMap - Optional mappnig of values to colors to override the *BarColor values above
+*                  can be an Array of values to control the color of individual bars
+*       barSpacing - Gap between bars in pixels
+*       zeroAxis - Centers the y-axis around zero if true
+*
+*   tristate - Charts values of win (>0), lose (<0) or draw (=0)
+*       posBarColor - Color of win values
+*       negBarColor - Color of lose values
+*       zeroBarColor - Color of draw values
+*       barWidth - Width of bars in pixels
+*       barSpacing - Gap between bars in pixels
+*       colorMap - Optional mappnig of values to colors to override the *BarColor values above
+*                  can be an Array of values to control the color of individual bars
+*
+*   discrete - Options:
+*       lineHeight - Height of each line in pixels - Defaults to 30% of the graph height
+*       thesholdValue - Values less than this value will be drawn using thresholdColor instead of lineColor
+*       thresholdColor
+*
+*   bullet - Values for bullet graphs msut be in the order: target, performance, range1, range2, range3, ...
+*       options:
+*       targetColor - The color of the vertical target marker
+*       targetWidth - The width of the target marker in pixels
+*       performanceColor - The color of the performance measure horizontal bar
+*       rangeColors - Colors to use for each qualitative range background color
+*
+*   pie - Pie chart. Options:
+*       sliceColors - An array of colors to use for pie slices
+*       offset - Angle in degrees to offset the first slice - Try -90 or +90
+*
+*   box - Box plot. Options:
+*       raw - Set to true to supply pre-computed plot points as values
+*             values should be: low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier
+*             When set to false you can supply any number of values and the box plot will
+*             be computed for you.  Default is false.
+*       showOutliers - Set to true (default) to display outliers as circles
+*       outlierIRQ - Interquartile range used to determine outliers.  Default 1.5
+*       boxLineColor - Outline color of the box
+*       boxFillColor - Fill color for the box
+*       whiskerColor - Line color used for whiskers
+*       outlierLineColor - Outline color of outlier circles
+*       outlierFillColor - Fill color of the outlier circles
+*       spotRadius - Radius of outlier circles
+*       medianColor - Line color of the median line
+*       target - Draw a target cross hair at the supplied value (default undefined)
+*      
+*   
+*       
+*   Examples:
+*   $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor: false });
+*   $('.barsparks').sparkline('html', { type:'bar', height:'40px', barWidth:5 });
+*   $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }):
+*   $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' });
+*   $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' });
+*   $('#pie').sparkline([1,1,2], { type:'pie' });
+*/
+
+
+(function($) {
+
+    /*
+     * Default configuration settings
+     */
+    var defaults = {
+        // Settings common to most/all chart types
+        common: {
+            type : 'line',
+            lineColor : '#00f',
+            fillColor : '#cdf',
+            defaultPixelsPerValue : 3,
+            width : 'auto', 
+            height : 'auto',
+            composite : false,
+            tagValuesAttribute: 'values',
+            tagOptionsPrefix: 'spark',
+            enableTagOptions: false
+        },
+        // Defaults for line charts
+        line: {
+            spotColor : '#f80',
+            spotRadius : 1.5,
+            minSpotColor : '#f80',
+            maxSpotColor : '#f80',
+            lineWidth: 1, 
+            normalRangeMin : undefined,
+            normalRangeMax : undefined,
+            normalRangeColor : '#ccc',
+            drawNormalOnTop: false,
+            chartRangeMin : undefined,
+            chartRangeMax : undefined,
+            chartRangeMinX : undefined,
+            chartRangeMaxX : undefined
+        },
+        // Defaults for bar charts
+        bar: {
+            barColor : '#00f',
+            negBarColor : '#f44',
+            zeroColor: undefined,
+            nullColor: undefined,
+            zeroAxis : undefined,
+            barWidth : 4,
+            barSpacing : 1,
+            chartRangeMax: undefined,
+            chartRangeMin: undefined,
+            chartRangeClip: false,
+            colorMap : undefined
+        },
+        // Defaults for tristate charts
+        tristate: {
+            barWidth : 4,
+            barSpacing : 1,
+            posBarColor: '#6f6',
+            negBarColor : '#f44',
+            zeroBarColor : '#999',
+            colorMap : {}
+        },
+        // Defaults for discrete charts
+        discrete: {
+            lineHeight: 'auto',
+            thresholdColor: undefined,
+            thresholdValue : 0,
+            chartRangeMax: undefined,
+            chartRangeMin: undefined,
+            chartRangeClip: false
+        },
+        // Defaults for bullet charts
+        bullet: {
+            targetColor : 'red',
+            targetWidth : 3, // width of the target bar in pixels
+            performanceColor : 'blue',
+            rangeColors : ['#D3DAFE', '#A8B6FF', '#7F94FF' ],
+            base : undefined // set this to a number to change the base start number
+        },
+        // Defaults for pie charts
+        pie: {
+            sliceColors : ['#f00', '#0f0', '#00f']
+        },
+        // Defaults for box plots
+        box: {
+            raw: false,
+            boxLineColor: 'black',
+            boxFillColor: '#cdf',
+            whiskerColor: 'black',
+            outlierLineColor: '#333',
+            outlierFillColor: 'white',
+            medianColor: 'red',
+            showOutliers: true,
+            outlierIQR: 1.5,
+            spotRadius: 1.5,
+            target: undefined,
+            targetColor: '#4a2',
+            chartRangeMax: undefined,
+            chartRangeMin: undefined
+        }
+    };
+
+    // Provide a cross-browser interface to a few simple drawing primitives
+    var VCanvas_base, VCanvas_canvas, VCanvas_vml;
+    $.fn.simpledraw = function(width, height, use_existing) {
+        if (use_existing && this[0].VCanvas) {
+            return this[0].VCanvas;
+        }
+        if (width === undefined) { 
+            width=$(this).innerWidth();
+        }
+        if (height === undefined) {
+            height=$(this).innerHeight();
+        }
+        if ($.browser.hasCanvas) {
+            return new VCanvas_canvas(width, height, this);
+        } else if ($.browser.msie) {
+            return new VCanvas_vml(width, height, this);
+        } else {
+            return false;
+        }
+    };
+
+    var pending = [];
+
+
+    $.fn.sparkline = function(uservalues, userOptions) {
+        return this.each(function() {
+            var options = new $.fn.sparkline.options(this, userOptions);
+            var render = function() {
+                var values, width, height;
+                if (uservalues==='html' || uservalues===undefined) {
+                    var vals = this.getAttribute(options.get('tagValuesAttribute'));
+                    if (vals===undefined || vals===null) {
+                        vals = $(this).html();
+                    }
+                    values = vals.replace(/(^\s*<!--)|(-->\s*$)|\s+/g, '').split(',');
+                } else {
+                    values = uservalues;
+                }
+
+                width = options.get('width')=='auto' ? values.length*options.get('defaultPixelsPerValue') : options.get('width');
+                if (options.get('height') == 'auto') {
+                    if (!options.get('composite') || !this.VCanvas) {
+                        // must be a better way to get the line height
+                        var tmp = document.createElement('span');
+                        tmp.innerHTML = 'a';
+                        $(this).html(tmp);
+                        height = $(tmp).innerHeight();
+                        $(tmp).remove();
+                    }
+                } else {
+                    height = options.get('height');
+                }
+
+                $.fn.sparkline[options.get('type')].call(this, values, options, width, height);
+            };
+            // jQuery 1.3.0 completely changed the meaning of :hidden :-/
+            if (($(this).html() && $(this).is(':hidden')) || ($.fn.jquery < "1.3.0" && $(this).parents().is(':hidden')) || !$(this).parents('body').length) {
+                pending.push([this, render]);
+            } else {
+                render.call(this);
+            }
+        });
+    };
+
+    $.fn.sparkline.defaults = defaults;
+
+
+    $.sparkline_display_visible = function() {
+        for (var i=pending.length-1; i>=0; i--) {
+            var el = pending[i][0];
+            if ($(el).is(':visible') && !$(el).parents().is(':hidden')) {
+                pending[i][1].call(el);
+                pending.splice(i, 1);
+            }
+        }
+    };
+
+
+    /**
+     * User option handler
+     */
+    var UNSET_OPTION = {};
+    var normalizeValue = function(val) {
+        switch(val) {
+            case 'undefined':
+                val = undefined;
+                break;
+            case 'null':
+                val = null;
+                break;
+            case 'true':
+                val = true;
+                break;
+            case 'false':
+                val = false;
+                break;
+            default:
+                var nf = parseFloat(val);
+                if (val == nf) {
+                    val = nf;
+                }
+        }
+        return val;
+    };
+    $.fn.sparkline.options = function(tag, userOptions) {
+        var extendedOptions;
+        this.userOptions = userOptions = userOptions || {};
+        this.tag = tag;
+        this.tagValCache = {};
+        var defaults = $.fn.sparkline.defaults;
+        var base = defaults.common;
+        this.tagOptionsPrefix = userOptions.enableTagOptions && (userOptions.tagOptionsPrefix || base.tagOptionsPrefix);
+            
+        var tagOptionType = this.getTagSetting('type');
+        if (tagOptionType === UNSET_OPTION) {
+            extendedOptions = defaults[userOptions.type || base.type];
+        } else {
+            extendedOptions = defaults[tagOptionType];
+        }
+        this.mergedOptions = $.extend({}, base, extendedOptions, userOptions);
+    };
+
+
+    $.fn.sparkline.options.prototype.getTagSetting = function(key) {
+        var val, i, prefix = this.tagOptionsPrefix;
+        if (prefix === false || prefix === undefined) {
+            return UNSET_OPTION;
+        }
+        if (this.tagValCache.hasOwnProperty(key)) {
+            val = this.tagValCache.key;
+        } else {
+            val = this.tag.getAttribute(prefix + key);
+            if (val === undefined || val === null) {
+                val = UNSET_OPTION;
+            } else if (val.substr(0, 1) == '[') {
+                val = val.substr(1, val.length-2).split(',');
+                for(i=val.length; i--;) {
+                    val[i] = normalizeValue(val[i].replace(/(^\s*)|(\s*$)/g, ''));
+                }
+            } else if (val.substr(0, 1) == '{') {
+                var pairs= val.substr(1, val.length-2).split(',');
+                val = {};
+                for(i=pairs.length; i--;) {
+                    var keyval = pairs[i].split(':', 2);
+                    val[keyval[0].replace(/(^\s*)|(\s*$)/g, '')] = normalizeValue(keyval[1].replace(/(^\s*)|(\s*$)/g, ''));
+                }
+            } else {
+                val = normalizeValue(val);
+            }
+            this.tagValCache.key = val;
+        }
+        return val; 
+    };
+
+    $.fn.sparkline.options.prototype.get = function(key) {
+        var tagOption = this.getTagSetting(key);
+        if (tagOption !== UNSET_OPTION) {
+            return tagOption;
+        }
+        return this.mergedOptions[key];
+    };
+
+
+    /**
+     * Line charts
+     */
+    $.fn.sparkline.line = function(values, options, width, height) {
+        var xvalues = [], yvalues = [], yminmax = [];
+        for (var i=0; i<values.length; i++) {
+            var val = values[i];
+            var isstr = typeof(values[i])=='string';
+            var isarray = typeof(values[i])=='object' && values[i] instanceof Array;
+            var sp = isstr && values[i].split(':');
+            if (isstr && sp.length == 2) { // x:y
+                xvalues.push(Number(sp[0]));
+                yvalues.push(Number(sp[1]));
+                yminmax.push(Number(sp[1]));
+            } else if (isarray) {
+                xvalues.push(val[0]);
+                yvalues.push(val[1]);
+                yminmax.push(val[1]);
+            } else {
+                xvalues.push(i);
+                if (values[i]===null || values[i]=='null') {
+                    yvalues.push(null);
+                } else {
+                    yvalues.push(Number(val));
+                    yminmax.push(Number(val));
+                }
+            }
+        }
+        if (options.get('xvalues')) {
+            xvalues = options.get('xvalues');
+        }
+
+        var maxy = Math.max.apply(Math, yminmax);
+        var maxyval = maxy;
+        var miny = Math.min.apply(Math, yminmax);
+        var minyval = miny;
+
+        var maxx = Math.max.apply(Math, xvalues);
+        var minx = Math.min.apply(Math, xvalues);
+
+        var normalRangeMin = options.get('normalRangeMin');
+        var normalRangeMax = options.get('normalRangeMax');
+
+        if (normalRangeMin!==undefined) {
+            if (normalRangeMin<miny) {
+                miny = normalRangeMin;
+            }
+            if (normalRangeMax>maxy) {
+                maxy = normalRangeMax;
+            }
+        }
+        if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') ||  options.get('chartRangeMin')<miny)) {
+            miny = options.get('chartRangeMin');
+        }
+        if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMax')>maxy)) {
+            maxy = options.get('chartRangeMax');
+        }
+        if (options.get('chartRangeMinX')!==undefined && (options.get('chartRangeClipX') || options.get('chartRangeMinX')<minx)) {
+            minx = options.get('chartRangeMinX');
+        }
+        if (options.get('chartRangeMaxX')!==undefined && (options.get('chartRangeClipX') || options.get('chartRangeMaxX')>maxx)) {
+            maxx = options.get('chartRangeMaxX');
+        }
+        var rangex = maxx-minx === 0 ? 1 : maxx-minx;
+        var rangey = maxy-miny === 0 ? 1 : maxy-miny;
+        var vl = yvalues.length-1;
+
+        if (vl<1) {
+            this.innerHTML = '';
+            return;
+        }
+
+        var target = $(this).simpledraw(width, height, options.get('composite'));
+        if (target) {
+            var canvas_width = target.pixel_width;
+            var canvas_height = target.pixel_height;
+            var canvas_top = 0;
+            var canvas_left = 0;
+
+            var spotRadius = options.get('spotRadius');
+            if (spotRadius && (canvas_width < (spotRadius*4) || canvas_height < (spotRadius*4))) {
+                spotRadius = 0;
+            }
+            if (spotRadius) {
+                // adjust the canvas size as required so that spots will fit
+                if (options.get('minSpotColor') || (options.get('spotColor') && yvalues[vl]==miny)) {
+                    canvas_height -= Math.ceil(spotRadius);
+                }
+                if (options.get('maxSpotColor') || (options.get('spotColor') && yvalues[vl]==maxy)) {
+                    canvas_height -= Math.ceil(spotRadius);
+                    canvas_top += Math.ceil(spotRadius);
+                }
+                if (options.get('minSpotColor') || options.get('maxSpotColor') && (yvalues[0]==miny || yvalues[0]==maxy)) {
+                    canvas_left += Math.ceil(spotRadius);
+                    canvas_width -= Math.ceil(spotRadius);
+                }
+                if (options.get('spotColor') || (options.get('minSpotColor') || options.get('maxSpotColor') && (yvalues[vl]==miny||yvalues[vl]==maxy))) {
+                    canvas_width -= Math.ceil(spotRadius);
+                }
+            }
+
+
+            canvas_height--;
+
+            var drawNormalRange = function() {
+                if (normalRangeMin!==undefined) {
+                    var ytop = canvas_top+Math.round(canvas_height-(canvas_height*((normalRangeMax-miny)/rangey)));
+                    var height = Math.round((canvas_height*(normalRangeMax-normalRangeMin))/rangey);
+                    target.drawRect(canvas_left, ytop, canvas_width, height, undefined, options.get('normalRangeColor'));
+                }
+            };
+
+            if (!options.get('drawNormalOnTop')) {
+                drawNormalRange();
+            }
+
+            var path = [];
+            var paths = [path];
+            var x, y, vlen=yvalues.length;
+            for(i=0; i<vlen; i++) {
+                x=xvalues[i];
+                y=yvalues[i];
+                if (y===null) {
+                    if (i) {
+                        if (yvalues[i-1]!==null) {
+                            path = [];
+                            paths.push(path);
+                        }
+                    }
+                } else {
+                    if (y < miny) {
+                        y=miny;
+                    }
+                    if (y > maxy) {
+                        y=maxy;
+                    }
+                    if (!path.length) {
+                        // previous value was null
+                        path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+canvas_height]);
+                    }
+                    path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((y-miny)/rangey)))]);
+                }
+            }
+            var lineshapes = [];
+            var fillshapes = [];
+            var plen=paths.length;
+            for(i=0; i<plen; i++) {
+                path = paths[i];
+                if (!path.length) {
+                    continue; // last value was null
+                }
+                if (options.get('fillColor')) {
+                    path.push([path[path.length-1][0], canvas_top+canvas_height-1]);
+                    fillshapes.push(path.slice(0));
+                    path.pop();
+                }
+                // if there's only a single point in this path, then we want to display it as a vertical line
+                // which means we keep path[0]  as is
+                if (path.length>2) {
+                    // else we want the first value 
+                    path[0] = [ path[0][0], path[1][1] ];
+                }
+                lineshapes.push(path);
+            }
+
+            // draw the fill first, then optionally the normal range, then the line on top of that
+            plen = fillshapes.length;
+            for(i=0; i<plen; i++) {
+                target.drawShape(fillshapes[i], undefined, options.get('fillColor'));
+            }
+
+            if (options.get('drawNormalOnTop')) {
+                drawNormalRange();
+            }
+
+            plen = lineshapes.length;
+            for(i=0; i<plen; i++) {
+                target.drawShape(lineshapes[i], options.get('lineColor'), undefined, options.get('lineWidth'));
+            }
+                
+            if (spotRadius && options.get('spotColor')) {
+                target.drawCircle(canvas_left+Math.round(xvalues[xvalues.length-1]*(canvas_width/rangex)),  canvas_top+Math.round(canvas_height-(canvas_height*((yvalues[vl]-miny)/rangey))), spotRadius, undefined, options.get('spotColor'));
+            }
+            if (maxy!=minyval) {
+                if (spotRadius && options.get('minSpotColor')) {
+                    x = xvalues[$.inArray(minyval, yvalues)];
+                    target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)),  canvas_top+Math.round(canvas_height-(canvas_height*((minyval-miny)/rangey))), spotRadius, undefined, options.get('minSpotColor'));
+                }
+                if (spotRadius && options.get('maxSpotColor')) {
+                    x = xvalues[$.inArray(maxyval, yvalues)];
+                    target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)),  canvas_top+Math.round(canvas_height-(canvas_height*((maxyval-miny)/rangey))), spotRadius, undefined, options.get('maxSpotColor'));
+                }
+            }
+
+        } else {
+            // Remove the tag contents if sparklines aren't supported
+            this.innerHTML = '';
+        }
+    };
+
+    
+    /** 
+     * Bar charts
+     */
+    $.fn.sparkline.bar = function(values, options, width, height) {
+        width = (values.length * options.get('barWidth')) + ((values.length-1) * options.get('barSpacing'));
+        var num_values = [];
+        for(var i=0, vlen=values.length; i<vlen; i++) {
+            if (values[i]=='null' || values[i]===null) {
+                values[i] = null;
+            } else {
+                values[i] = Number(values[i]);
+                num_values.push(Number(values[i]));
+            }
+        }
+        var max = Math.max.apply(Math, num_values),
+            min = Math.min.apply(Math, num_values);
+        if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMin')<min)) {
+            min = options.get('chartRangeMin');
+        }
+        if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMax')>max)) {
+            max = options.get('chartRangeMax');
+        }
+        var zeroAxis = options.get('zeroAxis');
+        if (zeroAxis === undefined) {
+            zeroAxis = min<0;
+        }
+        var range = max-min === 0 ? 1 : max-min;
+
+        var colorMapByIndex, colorMapByValue;
+        if ($.isArray(options.get('colorMap'))) {
+            colorMapByIndex = options.get('colorMap');
+            colorMapByValue = null;
+        } else {
+            colorMapByIndex = null;
+            colorMapByValue = options.get('colorMap');
+        }
+
+        var target = $(this).simpledraw(width, height, options.get('composite'));
+        if (target) {
+            var color,
+                canvas_height = target.pixel_height,
+                yzero = min<0 && zeroAxis ? canvas_height-Math.round(canvas_height * (Math.abs(min)/range))-1 : canvas_height-1;
+
+            for(i=values.length; i--;) {
+                var x = i*(options.get('barWidth')+options.get('barSpacing')),
+                    y, 
+                    val = values[i];
+                if (val===null) {
+                    if (options.get('nullColor')) {
+                        color = options.get('nullColor');
+                        val = (zeroAxis && min<0) ? 0 : min;
+                        height = 1;
+                        y = (zeroAxis && min<0) ? yzero : canvas_height - height;
+                    } else {
+                        continue;
+                    }
+                } else {
+                    if (val < min) {
+                        val=min;
+                    }
+                    if (val > max) {
+                        val=max;
+                    }
+                    color = (val < 0) ? options.get('negBarColor') : options.get('barColor');
+                    if (zeroAxis && min<0) {
+                        height = Math.round(canvas_height*((Math.abs(val)/range)))+1;
+                        y = (val < 0) ? yzero : yzero-height;
+                    } else {
+                        height = Math.round(canvas_height*((val-min)/range))+1;
+                        y = canvas_height-height;
+                    }
+                    if (val===0 && options.get('zeroColor')!==undefined) {
+                        color = options.get('zeroColor');
+                    }
+                    if (colorMapByValue && colorMapByValue[val]) {
+                        color = colorMapByValue[val];
+                    } else if (colorMapByIndex && colorMapByIndex.length>i) {
+                        color = colorMapByIndex[i];
+                    }
+                    if (color===null) {
+                        continue;
+                    }
+                }
+                target.drawRect(x, y, options.get('barWidth')-1, height-1, color, color);
+            }
+        } else {
+            // Remove the tag contents if sparklines aren't supported
+            this.innerHTML = '';
+        }
+    };
+
+
+    /**
+     * Tristate charts
+     */
+    $.fn.sparkline.tristate = function(values, options, width, height) {
+        values = $.map(values, Number);
+        width = (values.length * options.get('barWidth')) + ((values.length-1) * options.get('barSpacing'));
+
+        var colorMapByIndex, colorMapByValue;
+        if ($.isArray(options.get('colorMap'))) {
+            colorMapByIndex = options.get('colorMap');
+            colorMapByValue = null;
+        } else {
+            colorMapByIndex = null;
+            colorMapByValue = options.get('colorMap');
+        }
+
+        var target = $(this).simpledraw(width, height, options.get('composite'));
+        if (target) {
+            var canvas_height = target.pixel_height,
+                half_height = Math.round(canvas_height/2);
+
+            for(var i=values.length; i--;) {
+                var x = i*(options.get('barWidth')+options.get('barSpacing')),
+                    y, color;
+                if (values[i] < 0) {
+                    y = half_height;
+                    height = half_height-1;
+                    color = options.get('negBarColor');
+                } else if (values[i] > 0) {
+                    y = 0;
+                    height = half_height-1;
+                    color = options.get('posBarColor');
+                } else {
+                    y = half_height-1;
+                    height = 2;
+                    color = options.get('zeroBarColor');
+                }
+                if (colorMapByValue && colorMapByValue[values[i]]) {
+                    color = colorMapByValue[values[i]];
+                } else if (colorMapByIndex && colorMapByIndex.length>i) {
+                    color = colorMapByIndex[i];
+                }
+                if (color===null) {
+                    continue;
+                }
+                target.drawRect(x, y, options.get('barWidth')-1, height-1, color, color);
+            }
+        } else {
+            // Remove the tag contents if sparklines aren't supported
+            this.innerHTML = '';
+        }
+    };
+
+
+    /** 
+     * Discrete charts
+     */
+    $.fn.sparkline.discrete = function(values, options, width, height) {
+        values = $.map(values, Number);
+        width = options.get('width')=='auto' ? values.length*2 : width;
+        var interval = Math.floor(width / values.length);
+
+        var target = $(this).simpledraw(width, height, options.get('composite'));
+        if (target) {
+            var canvas_height = target.pixel_height,
+                line_height = options.get('lineHeight') == 'auto' ? Math.round(canvas_height * 0.3) : options.get('lineHeight'),
+                pheight = canvas_height - line_height,
+                min = Math.min.apply(Math, values),
+                max = Math.max.apply(Math, values);
+            if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMin')<min)) {
+                min = options.get('chartRangeMin');
+            }
+            if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip')  || options.get('chartRangeMax')>max)) {
+                max = options.get('chartRangeMax');
+            }
+            var range = max-min;
+
+            for(var i=values.length; i--;) {
+                var val = values[i];
+                if (val < min) {
+                    val=min;
+                }
+                if (val > max) {
+                    val=max;
+                }
+                var x = (i*interval),
+                    ytop = Math.round(pheight-pheight*((val-min)/range));
+                target.drawLine(x, ytop, x, ytop+line_height, (options.get('thresholdColor') && val < options.get('thresholdValue')) ? options.get('thresholdColor') : options.get('lineColor'));
+            }
+        }  else {
+            // Remove the tag contents if sparklines aren't supported
+            this.innerHTML = '';
+        }
+                
+    };
+
+
+    /**
+     * Bullet charts
+     */
+    $.fn.sparkline.bullet = function(values, options, width, height) {
+        values = $.map(values, Number);
+        // target, performance, range1, range2, range3
+        
+        width = options.get('width')=='auto' ? '4.0em' : width;
+
+        var target = $(this).simpledraw(width, height, options.get('composite'));
+        if (target && values.length>1) {
+            var canvas_width = target.pixel_width-Math.ceil(options.get('targetWidth')/2),
+                canvas_height = target.pixel_height,
+                min = Math.min.apply(Math, values),
+                max = Math.max.apply(Math, values);
+
+            if (options.get('base') === undefined) {
+                min = min < 0 ? min : 0;
+            } else {
+                min = options.get('base');
+            }
+            var range = max-min;
+
+            // draw range values
+            for(var i=2, vlen=values.length; i<vlen; i++) {
+                var rangeval = values[i],
+                    rangewidth = Math.round(canvas_width*((rangeval-min)/range));
+                target.drawRect(0, 0, rangewidth-1, canvas_height-1, options.get('rangeColors')[i-2], options.get('rangeColors')[i-2]);
+            }
+
+            // draw the performance bar
+            var perfval = values[1],
+                perfwidth = Math.round(canvas_width*((perfval-min)/range));
+            target.drawRect(0, Math.round(canvas_height*0.3), perfwidth-1, Math.round(canvas_height*0.4)-1, options.get('performanceColor'), options.get('performanceColor'));
+
+            // draw the target line
+            var targetval = values[0],
+                x = Math.round(canvas_width*((targetval-min)/range)-(options.get('targetWidth')/2)),
+                targettop = Math.round(canvas_height*0.10),
+                targetheight = canvas_height-(targettop*2);
+            target.drawRect(x, targettop, options.get('targetWidth')-1, targetheight-1, options.get('targetColor'), options.get('targetColor'));
+        }  else {
+            // Remove the tag contents if sparklines aren't supported
+            this.innerHTML = '';
+        }
+    };
+
+
+    /**
+     * Pie charts
+     */
+    $.fn.sparkline.pie = function(values, options, width, height) {
+        values = $.map(values, Number);
+        width = options.get('width')=='auto' ? height : width;
+
+        var target = $(this).simpledraw(width, height, options.get('composite'));
+        if (target && values.length>1) {
+            var canvas_width = target.pixel_width,
+                canvas_height = target.pixel_height,
+                radius = Math.floor(Math.min(canvas_width, canvas_height)/2),
+                total = 0,
+                next = 0,
+                circle = 2*Math.PI;
+
+            for(var i=values.length; i--;) {
+                total += values[i];
+            }
+
+            if (options.get('offset')) {
+                next += (2*Math.PI)*(options.get('offset')/360);
+            }
+            var vlen = values.length;
+            for(i=0; i<vlen; i++) {
+                var start = next;
+                var end = next;
+                if (total > 0) {  // avoid divide by zero
+                    end = next + (circle*(values[i]/total));
+                }
+                target.drawPieSlice(radius, radius, radius, start, end, undefined, options.get('sliceColors')[i % options.get('sliceColors').length]);
+                next = end;
+            }
+        }
+    };
+
+
+    /**
+     * Box plots
+     */
+    var quartile = function(values, q) {
+        if (q==2) {
+            var vl2 = Math.floor(values.length/2);
+            return values.length % 2 ? values[vl2] : (values[vl2]+values[vl2+1])/2;
+        } else {
+            var vl4 = Math.floor(values.length/4);
+            return values.length % 2 ? (values[vl4*q]+values[vl4*q+1])/2 : values[vl4*q];
+        }
+    };
+
+    $.fn.sparkline.box = function(values, options, width, height) {
+        values = $.map(values, Number);
+        width = options.get('width')=='auto' ? '4.0em' : width;
+
+        var minvalue = options.get('chartRangeMin')===undefined ? Math.min.apply(Math, values) : options.get('chartRangeMin'),
+            maxvalue = options.get('chartRangeMax')===undefined ? Math.max.apply(Math, values) : options.get('chartRangeMax'),
+            target = $(this).simpledraw(width, height, options.get('composite')),
+            vlen = values.length,
+            lwhisker, loutlier, q1, q2, q3, rwhisker, routlier;
+
+        if (target && values.length>1) {
+            var canvas_width = target.pixel_width,
+                canvas_height = target.pixel_height;
+            if (options.get('raw')) {
+                if (options.get('showOutliers') && values.length>5) {
+                    loutlier=values[0]; lwhisker=values[1]; q1=values[2]; q2=values[3]; q3=values[4]; rwhisker=values[5]; routlier=values[6];
+                } else {
+                    lwhisker=values[0]; q1=values[1]; q2=values[2]; q3=values[3]; rwhisker=values[4];
+                }
+            } else {
+                values.sort(function(a, b) { return a-b; });
+                q1 = quartile(values, 1);
+                q2 = quartile(values, 2);
+                q3 = quartile(values, 3);
+                var iqr = q3-q1;
+                if (options.get('showOutliers')) {
+                    lwhisker=undefined; rwhisker=undefined;
+                    for(var i=0; i<vlen; i++) {
+                        if (lwhisker===undefined && values[i] > q1-(iqr*options.get('outlierIQR'))) {
+                            lwhisker = values[i];
+                        }
+                        if (values[i] < q3+(iqr*options.get('outlierIQR'))) {
+                            rwhisker = values[i];
+                        }
+                    }
+                    loutlier = values[0];
+                    routlier = values[vlen-1];
+                } else {
+                    lwhisker = values[0];
+                    rwhisker = values[vlen-1];
+                }
+            }
+
+            var unitsize = canvas_width / (maxvalue-minvalue+1),
+                canvas_left = 0;
+            if (options.get('showOutliers')) {
+                canvas_left = Math.ceil(options.get('spotRadius'));
+                canvas_width -= 2*Math.ceil(options.get('spotRadius'));
+                unitsize = canvas_width / (maxvalue-minvalue+1);
+                if (loutlier < lwhisker) {
+                    target.drawCircle((loutlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.get('spotRadius'), options.get('outlierLineColor'), options.get('outlierFillColor'));
+                }
+                if (routlier > rwhisker) {
+                    target.drawCircle((routlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.get('spotRadius'), options.get('outlierLineColor'), options.get('outlierFillColor'));
+                }
+            }
+
+            // box
+            target.drawRect(
+                Math.round((q1-minvalue)*unitsize+canvas_left),
+                Math.round(canvas_height*0.1),
+                Math.round((q3-q1)*unitsize), 
+                Math.round(canvas_height*0.8), 
+                options.get('boxLineColor'), 
+                options.get('boxFillColor'));
+            // left whisker
+            target.drawLine(
+                Math.round((lwhisker-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height/2), 
+                Math.round((q1-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height/2), 
+                options.get('lineColor'));
+            target.drawLine(
+                Math.round((lwhisker-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height/4), 
+                Math.round((lwhisker-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height-canvas_height/4), 
+                options.get('whiskerColor'));
+            // right whisker
+            target.drawLine(Math.round((rwhisker-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height/2), 
+                Math.round((q3-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height/2), 
+                options.get('lineColor'));
+            target.drawLine(
+                Math.round((rwhisker-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height/4), 
+                Math.round((rwhisker-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height-canvas_height/4), 
+                options.get('whiskerColor'));
+            // median line
+            target.drawLine(
+                Math.round((q2-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height*0.1),
+                Math.round((q2-minvalue)*unitsize+canvas_left), 
+                Math.round(canvas_height*0.9),
+                options.get('medianColor'));
+            if (options.get('target')) {
+                var size = Math.ceil(options.get('spotRadius'));
+                target.drawLine(
+                    Math.round((options.get('target')-minvalue)*unitsize+canvas_left), 
+                    Math.round((canvas_height/2)-size), 
+                    Math.round((options.get('target')-minvalue)*unitsize+canvas_left), 
+                    Math.round((canvas_height/2)+size), 
+                    options.get('targetColor'));
+                target.drawLine(
+                    Math.round((options.get('target')-minvalue)*unitsize+canvas_left-size), 
+                    Math.round(canvas_height/2), 
+                    Math.round((options.get('target')-minvalue)*unitsize+canvas_left+size), 
+                    Math.round(canvas_height/2), 
+                    options.get('targetColor'));
+            }
+        }  else {
+            // Remove the tag contents if sparklines aren't supported
+            this.innerHTML = '';
+        }
+    };
+
+
+    // Setup a very simple "virtual canvas" to make drawing the few shapes we need easier
+    // This is accessible as $(foo).simpledraw()
+
+    if ($.browser.msie && !document.namespaces.v) {
+        document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');
+    }
+
+    if ($.browser.hasCanvas === undefined) {
+        var t = document.createElement('canvas');
+        $.browser.hasCanvas = t.getContext!==undefined;
+    }
+
+    VCanvas_base = function(width, height, target) {
+    };
+
+    VCanvas_base.prototype = {
+        init : function(width, height, target) {
+            this.width = width;
+            this.height = height;
+            this.target = target;
+            if (target[0]) {
+                target=target[0];
+            }
+            target.VCanvas = this;
+        },
+
+        drawShape : function(path, lineColor, fillColor, lineWidth) {
+            alert('drawShape not implemented');
+        },
+
+        drawLine : function(x1, y1, x2, y2, lineColor, lineWidth) {
+            return this.drawShape([ [x1,y1], [x2,y2] ], lineColor, lineWidth);
+        },
+
+        drawCircle : function(x, y, radius, lineColor, fillColor) {
+            alert('drawCircle not implemented');
+        },
+
+        drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
+            alert('drawPieSlice not implemented');
+        },
+
+        drawRect : function(x, y, width, height, lineColor, fillColor) {
+            alert('drawRect not implemented');
+        },
+
+        getElement : function() {
+            return this.canvas;
+        },
+
+        _insert : function(el, target) {
+            $(target).html(el);
+        }
+    };
+
+    VCanvas_canvas = function(width, height, target) {
+        return this.init(width, height, target);
+    };
+
+    VCanvas_canvas.prototype = $.extend(new VCanvas_base(), {
+        _super : VCanvas_base.prototype,
+
+        init : function(width, height, target) {
+            this._super.init(width, height, target);
+            this.canvas = document.createElement('canvas');
+            if (target[0]) {
+                target=target[0];
+            }
+            target.VCanvas = this;
+            $(this.canvas).css({ display:'inline-block', width:width, height:height, verticalAlign:'top' });
+            this._insert(this.canvas, target);
+            this.pixel_height = $(this.canvas).height();
+            this.pixel_width = $(this.canvas).width();
+            this.canvas.width = this.pixel_width;
+            this.canvas.height = this.pixel_height;
+            $(this.canvas).css({width: this.pixel_width, height: this.pixel_height});
+        },
+
+        _getContext : function(lineColor, fillColor, lineWidth) {
+            var context = this.canvas.getContext('2d');
+            if (lineColor !== undefined) {
+                context.strokeStyle = lineColor;
+            }
+            context.lineWidth = lineWidth===undefined ? 1 : lineWidth;
+            if (fillColor !== undefined) {
+                context.fillStyle = fillColor;
+            }
+            return context;
+        },
+
+        drawShape : function(path, lineColor, fillColor, lineWidth) {
+            var context = this._getContext(lineColor, fillColor, lineWidth);
+            context.beginPath();
+            context.moveTo(path[0][0]+0.5, path[0][1]+0.5);
+            for(var i=1, plen=path.length; i<plen; i++) {
+                context.lineTo(path[i][0]+0.5, path[i][1]+0.5); // the 0.5 offset gives us crisp pixel-width lines
+            }
+            if (lineColor !== undefined) {
+                context.stroke();
+            }
+            if (fillColor !== undefined) {
+                context.fill();
+            }
+        },
+
+        drawCircle : function(x, y, radius, lineColor, fillColor) {
+            var context = this._getContext(lineColor, fillColor);
+            context.beginPath();
+            context.arc(x, y, radius, 0, 2*Math.PI, false);
+            if (lineColor !== undefined) {
+                context.stroke();
+            }
+            if (fillColor !== undefined) {
+                context.fill();
+            }
+        }, 
+
+        drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
+            var context = this._getContext(lineColor, fillColor);
+            context.beginPath();
+            context.moveTo(x, y);
+            context.arc(x, y, radius, startAngle, endAngle, false);
+            context.lineTo(x, y);
+            context.closePath();
+            if (lineColor !== undefined) {
+                context.stroke();
+            }
+            if (fillColor) {
+                context.fill();
+            }
+        },
+
+        drawRect : function(x, y, width, height, lineColor, fillColor) {
+            return this.drawShape([ [x,y], [x+width, y], [x+width, y+height], [x, y+height], [x, y] ], lineColor, fillColor);
+        }
+        
+    });
+
+    VCanvas_vml = function(width, height, target) {
+        return this.init(width, height, target);
+    };
+
+    VCanvas_vml.prototype = $.extend(new VCanvas_base(), {
+        _super : VCanvas_base.prototype,
+
+        init : function(width, height, target) {
+            this._super.init(width, height, target);
+            if (target[0]) {
+                target=target[0];
+            }
+            target.VCanvas = this;
+            this.canvas = document.createElement('span');
+            $(this.canvas).css({ display:'inline-block', position: 'relative', overflow:'hidden', width:width, height:height, margin:'0px', padding:'0px', verticalAlign: 'top'});
+            this._insert(this.canvas, target);
+            this.pixel_height = $(this.canvas).height();
+            this.pixel_width = $(this.canvas).width();
+            this.canvas.width = this.pixel_width;
+            this.canvas.height = this.pixel_height;
+            var groupel = '<v:group coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'"' +
+                    ' style="position:absolute;top:0;left:0;width:'+this.pixel_width+'px;height='+this.pixel_height+'px;"></v:group>';
+            this.canvas.insertAdjacentHTML('beforeEnd', groupel);
+            this.group = $(this.canvas).children()[0];
+        },
+
+        drawShape : function(path, lineColor, fillColor, lineWidth) {
+            var vpath = [];
+            for(var i=0, plen=path.length; i<plen; i++) {
+                vpath[i] = ''+(path[i][0])+','+(path[i][1]);
+            }
+            var initial = vpath.splice(0,1);
+            lineWidth = lineWidth === undefined ? 1 : lineWidth;
+            var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="'+lineWidth+'" strokeColor="'+lineColor+'" ';
+            var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
+            var closed = vpath[0] == vpath[vpath.length-1] ? 'x ' : '';
+            var vel = '<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" ' +
+                 stroke +
+                 fill +
+                ' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" ' +
+                ' path="m '+initial+' l '+vpath.join(', ')+' '+closed+'e">' +
+                ' </v:shape>';
+             this.group.insertAdjacentHTML('beforeEnd', vel);
+        },
+
+        drawCircle : function(x, y, radius, lineColor, fillColor) {
+            x -= radius+1;
+            y -= radius+1;
+            var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
+            var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
+            var vel = '<v:oval ' +
+                stroke +
+                fill +
+                ' style="position:absolute;top:'+y+'px; left:'+x+'px; width:'+(radius*2)+'px; height:'+(radius*2)+'px"></v:oval>';
+            this.group.insertAdjacentHTML('beforeEnd', vel);
+            
+        },
+        
+        drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
+            if (startAngle == endAngle) {
+                return;  // VML seems to have problem when start angle equals end angle.
+            }
+            if ((endAngle - startAngle) == (2*Math.PI)) {
+                startAngle = 0.0;  // VML seems to have a problem when drawing a full circle that doesn't start 0
+                endAngle = (2*Math.PI);
+            }
+
+            var startx = x + Math.round(Math.cos(startAngle) * radius);
+            var starty = y + Math.round(Math.sin(startAngle) * radius);
+            var endx = x + Math.round(Math.cos(endAngle) * radius);
+            var endy = y + Math.round(Math.sin(endAngle) * radius);
+
+            // Prevent very small slices from being mistaken as a whole pie
+            if (startx==endx && starty==endy && (endAngle-startAngle) < Math.PI) {
+                return;
+            }
+
+            var vpath = [  x-radius, y-radius, x+radius, y+radius, startx, starty, endx, endy ]; 
+            var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
+            var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
+            var vel = '<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" ' +
+                 stroke +
+                 fill +
+                ' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" ' +
+                ' path="m '+x+','+y+' wa '+vpath.join(', ')+' x e">' +
+                ' </v:shape>';
+             this.group.insertAdjacentHTML('beforeEnd', vel);
+        },
+
+        drawRect : function(x, y, width, height, lineColor, fillColor) {
+            return this.drawShape( [ [x, y], [x, y+height], [x+width, y+height], [x+width, y], [x, y] ], lineColor, fillColor);
+        }
+    });
+
+})(jQuery);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/jwplayer.js	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,1 @@
+if(typeof jwplayer=="undefined"){var jwplayer=function(a){if(jwplayer.api){return jwplayer.api.selectPlayer(a)}};var $jw=jwplayer;jwplayer.version="5.7.1896";jwplayer.vid=document.createElement("video");jwplayer.audio=document.createElement("audio");jwplayer.source=document.createElement("source");(function(b){b.utils=function(){};b.utils.typeOf=function(d){var c=typeof d;if(c==="object"){if(d){if(d instanceof Array){c="array"}}else{c="null"}}return c};b.utils.extend=function(){var c=b.utils.extend["arguments"];if(c.length>1){for(var e=1;e<c.length;e++){for(var d in c[e]){c[0][d]=c[e][d]}}return c[0]}return null};b.utils.clone=function(f){var c;var d=b.utils.clone["arguments"];if(d.length==1){switch(b.utils.typeOf(d[0])){case"object":c={};for(var e in d[0]){c[e]=b.utils.clone(d[0][e])}break;case"array":c=[];for(var e in d[0]){c[e]=b.utils.clone(d[0][e])}break;default:return d[0];break}}return c};b.utils.extension=function(c){if(!c){return""}c=c.substring(c.lastIndexOf("/")+1,c.length);c=c.split("?")[0];if(c.lastIndexOf(".")>-1){return c.substr(c.lastIndexOf(".")+1,c.length).toLowerCase()}return};b.utils.html=function(c,d){c.innerHTML=d};b.utils.wrap=function(c,d){if(c.parentNode){c.parentNode.replaceChild(d,c)}d.appendChild(c)};b.utils.ajax=function(g,f,c){var e;if(window.XMLHttpRequest){e=new XMLHttpRequest()}else{e=new ActiveXObject("Microsoft.XMLHTTP")}e.onreadystatechange=function(){if(e.readyState===4){if(e.status===200){if(f){f(e)}}else{if(c){c(g)}}}};try{e.open("GET",g,true);e.send(null)}catch(d){if(c){c(g)}}return e};b.utils.load=function(d,e,c){d.onreadystatechange=function(){if(d.readyState===4){if(d.status===200){if(e){e()}}else{if(c){c()}}}}};b.utils.find=function(d,c){return d.getElementsByTagName(c)};b.utils.append=function(c,d){c.appendChild(d)};b.utils.isIE=function(){return((!+"\v1")||(typeof window.ActiveXObject!="undefined"))};b.utils.isLegacyAndroid=function(){var c=navigator.userAgent.toLowerCase();return(c.match(/android 2.[012]/i)!==null)};b.utils.isIOS=function(d){if(typeof d=="undefined"){d=/iP(hone|ad|od)/i}var c=navigator.userAgent.toLowerCase();return(c.match(d)!==null)};b.utils.isIPad=function(){return b.utils.isIOS(/iPad/i)};b.utils.isIPod=function(){return b.utils.isIOS(/iP(hone|od)/i)};b.utils.getFirstPlaylistItemFromConfig=function(c){var d={};var e;if(c.playlist&&c.playlist.length){e=c.playlist[0]}else{e=c}d.file=e.file;d.levels=e.levels;d.streamer=e.streamer;d.playlistfile=e.playlistfile;d.provider=e.provider;if(!d.provider){if(d.file&&(d.file.toLowerCase().indexOf("youtube.com")>-1||d.file.toLowerCase().indexOf("youtu.be")>-1)){d.provider="youtube"}if(d.streamer&&d.streamer.toLowerCase().indexOf("rtmp://")==0){d.provider="rtmp"}if(e.type){d.provider=e.type.toLowerCase()}}if(d.provider=="audio"){d.provider="sound"}return d};b.utils.getOuterHTML=function(c){if(c.outerHTML){return c.outerHTML}else{try{return new XMLSerializer().serializeToString(c)}catch(d){return""}}};b.utils.setOuterHTML=function(f,e){if(f.outerHTML){f.outerHTML=e}else{var g=document.createElement("div");g.innerHTML=e;var c=document.createRange();c.selectNodeContents(g);var d=c.extractContents();f.parentNode.insertBefore(d,f);f.parentNode.removeChild(f)}};b.utils.hasFlash=function(){if(typeof navigator.plugins!="undefined"&&typeof navigator.plugins["Shockwave Flash"]!="undefined"){return true}if(typeof window.ActiveXObject!="undefined"){try{new ActiveXObject("ShockwaveFlash.ShockwaveFlash");return true}catch(c){}}return false};b.utils.getPluginName=function(c){if(c.lastIndexOf("/")>=0){c=c.substring(c.lastIndexOf("/")+1,c.length)}if(c.lastIndexOf("-")>=0){c=c.substring(0,c.lastIndexOf("-"))}if(c.lastIndexOf(".swf")>=0){c=c.substring(0,c.lastIndexOf(".swf"))}if(c.lastIndexOf(".js")>=0){c=c.substring(0,c.lastIndexOf(".js"))}return c};b.utils.getPluginVersion=function(c){if(c.lastIndexOf("-")>=0){if(c.lastIndexOf(".js")>=0){return c.substring(c.lastIndexOf("-")+1,c.lastIndexOf(".js"))}else{if(c.lastIndexOf(".swf")>=0){return c.substring(c.lastIndexOf("-")+1,c.lastIndexOf(".swf"))}else{return c.substring(c.lastIndexOf("-")+1)}}}return""};b.utils.getAbsolutePath=function(j,h){if(!b.utils.exists(h)){h=document.location.href}if(!b.utils.exists(j)){return undefined}if(a(j)){return j}var k=h.substring(0,h.indexOf("://")+3);var g=h.substring(k.length,h.indexOf("/",k.length+1));var d;if(j.indexOf("/")===0){d=j.split("/")}else{var e=h.split("?")[0];e=e.substring(k.length+g.length+1,e.lastIndexOf("/"));d=e.split("/").concat(j.split("/"))}var c=[];for(var f=0;f<d.length;f++){if(!d[f]||!b.utils.exists(d[f])||d[f]=="."){continue}else{if(d[f]==".."){c.pop()}else{c.push(d[f])}}}return k+g+"/"+c.join("/")};function a(d){if(!b.utils.exists(d)){return}var e=d.indexOf("://");var c=d.indexOf("?");return(e>0&&(c<0||(c>e)))}b.utils.pluginPathType={ABSOLUTE:"ABSOLUTE",RELATIVE:"RELATIVE",CDN:"CDN"};b.utils.getPluginPathType=function(d){if(typeof d!="string"){return}d=d.split("?")[0];var e=d.indexOf("://");if(e>0){return b.utils.pluginPathType.ABSOLUTE}var c=d.indexOf("/");var f=b.utils.extension(d);if(e<0&&c<0&&(!f||!isNaN(f))){return b.utils.pluginPathType.CDN}return b.utils.pluginPathType.RELATIVE};b.utils.mapEmpty=function(c){for(var d in c){return false}return true};b.utils.mapLength=function(d){var c=0;for(var e in d){c++}return c};b.utils.log=function(d,c){if(typeof console!="undefined"&&typeof console.log!="undefined"){if(c){console.log(d,c)}else{console.log(d)}}};b.utils.css=function(d,g,c){if(b.utils.exists(d)){for(var e in g){try{if(typeof g[e]==="undefined"){continue}else{if(typeof g[e]=="number"&&!(e=="zIndex"||e=="opacity")){if(isNaN(g[e])){continue}if(e.match(/color/i)){g[e]="#"+b.utils.strings.pad(g[e].toString(16),6)}else{g[e]=Math.ceil(g[e])+"px"}}}d.style[e]=g[e]}catch(f){}}}};b.utils.isYouTube=function(c){return(c.indexOf("youtube.com")>-1||c.indexOf("youtu.be")>-1)};b.utils.transform=function(c,d){c.style.webkitTransform=d;c.style.MozTransform=d;c.style.OTransform=d};b.utils.stretch=function(h,n,m,f,l,g){if(typeof m=="undefined"||typeof f=="undefined"||typeof l=="undefined"||typeof g=="undefined"){return}var d=m/l;var e=f/g;var k=0;var j=0;n.style.overflow="hidden";b.utils.transform(n,"");var c={};switch(h.toUpperCase()){case b.utils.stretching.NONE:c.width=l;c.height=g;break;case b.utils.stretching.UNIFORM:if(d>e){c.width=l*e;c.height=g*e}else{c.width=l*d;c.height=g*d}break;case b.utils.stretching.FILL:if(d>e){c.width=l*d;c.height=g*d}else{c.width=l*e;c.height=g*e}break;case b.utils.stretching.EXACTFIT:b.utils.transform(n,["scale(",d,",",e,")"," translate(0px,0px)"].join(""));c.width=l;c.height=g;break;default:break}c.top=(f-c.height)/2;c.left=(m-c.width)/2;b.utils.css(n,c)};b.utils.stretching={NONE:"NONE",FILL:"FILL",UNIFORM:"UNIFORM",EXACTFIT:"EXACTFIT"};b.utils.deepReplaceKeyName=function(h,e,c){switch(b.utils.typeOf(h)){case"array":for(var g=0;g<h.length;g++){h[g]=b.utils.deepReplaceKeyName(h[g],e,c)}break;case"object":for(var f in h){var d=f.replace(new RegExp(e,"g"),c);h[d]=b.utils.deepReplaceKeyName(h[f],e,c);if(f!=d){delete h[f]}}break}return h};b.utils.isInArray=function(e,d){if(!(e)||!(e instanceof Array)){return false}for(var c=0;c<e.length;c++){if(d===e[c]){return true}}return false};b.utils.exists=function(c){switch(typeof(c)){case"string":return(c.length>0);break;case"object":return(c!==null);case"undefined":return false}return true};b.utils.empty=function(c){if(typeof c.hasChildNodes=="function"){while(c.hasChildNodes()){c.removeChild(c.firstChild)}}};b.utils.parseDimension=function(c){if(typeof c=="string"){if(c===""){return 0}else{if(c.lastIndexOf("%")>-1){return c}else{return parseInt(c.replace("px",""),10)}}}return c};b.utils.getDimensions=function(c){if(c&&c.style){return{x:b.utils.parseDimension(c.style.left),y:b.utils.parseDimension(c.style.top),width:b.utils.parseDimension(c.style.width),height:b.utils.parseDimension(c.style.height)}}else{return{}}};b.utils.timeFormat=function(c){str="00:00";if(c>0){str=Math.floor(c/60)<10?"0"+Math.floor(c/60)+":":Math.floor(c/60)+":";str+=Math.floor(c%60)<10?"0"+Math.floor(c%60):Math.floor(c%60)}return str}})(jwplayer);(function(a){a.events=function(){};a.events.COMPLETE="COMPLETE";a.events.ERROR="ERROR"})(jwplayer);(function(jwplayer){jwplayer.events.eventdispatcher=function(debug){var _debug=debug;var _listeners;var _globallisteners;this.resetEventListeners=function(){_listeners={};_globallisteners=[]};this.resetEventListeners();this.addEventListener=function(type,listener,count){try{if(!jwplayer.utils.exists(_listeners[type])){_listeners[type]=[]}if(typeof(listener)=="string"){eval("listener = "+listener)}_listeners[type].push({listener:listener,count:count})}catch(err){jwplayer.utils.log("error",err)}return false};this.removeEventListener=function(type,listener){if(!_listeners[type]){return}try{for(var listenerIndex=0;listenerIndex<_listeners[type].length;listenerIndex++){if(_listeners[type][listenerIndex].listener.toString()==listener.toString()){_listeners[type].splice(listenerIndex,1);break}}}catch(err){jwplayer.utils.log("error",err)}return false};this.addGlobalListener=function(listener,count){try{if(typeof(listener)=="string"){eval("listener = "+listener)}_globallisteners.push({listener:listener,count:count})}catch(err){jwplayer.utils.log("error",err)}return false};this.removeGlobalListener=function(listener){if(!_globallisteners[type]){return}try{for(var globalListenerIndex=0;globalListenerIndex<_globallisteners.length;globalListenerIndex++){if(_globallisteners[globalListenerIndex].listener.toString()==listener.toString()){_globallisteners.splice(globalListenerIndex,1);break}}}catch(err){jwplayer.utils.log("error",err)}return false};this.sendEvent=function(type,data){if(!jwplayer.utils.exists(data)){data={}}if(_debug){jwplayer.utils.log(type,data)}if(typeof _listeners[type]!="undefined"){for(var listenerIndex=0;listenerIndex<_listeners[type].length;listenerIndex++){try{_listeners[type][listenerIndex].listener(data)}catch(err){jwplayer.utils.log("There was an error while handling a listener: "+err.toString(),_listeners[type][listenerIndex].listener)}if(_listeners[type][listenerIndex]){if(_listeners[type][listenerIndex].count===1){delete _listeners[type][listenerIndex]}else{if(_listeners[type][listenerIndex].count>0){_listeners[type][listenerIndex].count=_listeners[type][listenerIndex].count-1}}}}}for(var globalListenerIndex=0;globalListenerIndex<_globallisteners.length;globalListenerIndex++){try{_globallisteners[globalListenerIndex].listener(data)}catch(err){jwplayer.utils.log("There was an error while handling a listener: "+err.toString(),_globallisteners[globalListenerIndex].listener)}if(_globallisteners[globalListenerIndex]){if(_globallisteners[globalListenerIndex].count===1){delete _globallisteners[globalListenerIndex]}else{if(_globallisteners[globalListenerIndex].count>0){_globallisteners[globalListenerIndex].count=_globallisteners[globalListenerIndex].count-1}}}}}}})(jwplayer);(function(a){var b={};a.utils.animations=function(){};a.utils.animations.transform=function(c,d){c.style.webkitTransform=d;c.style.MozTransform=d;c.style.OTransform=d;c.style.msTransform=d};a.utils.animations.transformOrigin=function(c,d){c.style.webkitTransformOrigin=d;c.style.MozTransformOrigin=d;c.style.OTransformOrigin=d;c.style.msTransformOrigin=d};a.utils.animations.rotate=function(c,d){a.utils.animations.transform(c,["rotate(",d,"deg)"].join(""))};a.utils.cancelAnimation=function(c){delete b[c.id]};a.utils.fadeTo=function(m,f,e,j,h,d){if(b[m.id]!=d&&a.utils.exists(d)){return}if(m.style.opacity==f){return}var c=new Date().getTime();if(d>c){setTimeout(function(){a.utils.fadeTo(m,f,e,j,0,d)},d-c)}if(m.style.display=="none"){m.style.display="block"}if(!a.utils.exists(j)){j=m.style.opacity===""?1:m.style.opacity}if(m.style.opacity==f&&m.style.opacity!==""&&a.utils.exists(d)){if(f===0){m.style.display="none"}return}if(!a.utils.exists(d)){d=c;b[m.id]=d}if(!a.utils.exists(h)){h=0}var k=(e>0)?((c-d)/(e*1000)):0;k=k>1?1:k;var l=f-j;var g=j+(k*l);if(g>1){g=1}else{if(g<0){g=0}}m.style.opacity=g;if(h>0){b[m.id]=d+h*1000;a.utils.fadeTo(m,f,e,j,0,b[m.id]);return}setTimeout(function(){a.utils.fadeTo(m,f,e,j,0,d)},10)}})(jwplayer);(function(a){a.utils.arrays=function(){};a.utils.arrays.indexOf=function(c,d){for(var b=0;b<c.length;b++){if(c[b]==d){return b}}return -1};a.utils.arrays.remove=function(c,d){var b=a.utils.arrays.indexOf(c,d);if(b>-1){c.splice(b,1)}}})(jwplayer);(function(a){a.utils.extensionmap={"3gp":{html5:"video/3gpp",flash:"video"},"3gpp":{html5:"video/3gpp"},"3g2":{html5:"video/3gpp2",flash:"video"},"3gpp2":{html5:"video/3gpp2"},flv:{flash:"video"},f4a:{html5:"audio/mp4"},f4b:{html5:"audio/mp4",flash:"video"},f4v:{html5:"video/mp4",flash:"video"},mov:{html5:"video/quicktime",flash:"video"},m4a:{html5:"audio/mp4",flash:"video"},m4b:{html5:"audio/mp4"},m4p:{html5:"audio/mp4"},m4v:{html5:"video/mp4",flash:"video"},mp4:{html5:"video/mp4",flash:"video"},rbs:{flash:"sound"},aac:{html5:"audio/aac",flash:"video"},mp3:{html5:"audio/mp3",flash:"sound"},ogg:{html5:"audio/ogg"},oga:{html5:"audio/ogg"},ogv:{html5:"video/ogg"},webm:{html5:"video/webm"},m3u8:{html5:"audio/x-mpegurl"},gif:{flash:"image"},jpeg:{flash:"image"},jpg:{flash:"image"},swf:{flash:"image"},png:{flash:"image"},wav:{html5:"audio/x-wav"}}})(jwplayer);(function(e){e.utils.mediaparser=function(){};var g={element:{width:"width",height:"height",id:"id","class":"className",name:"name"},media:{src:"file",preload:"preload",autoplay:"autostart",loop:"repeat",controls:"controls"},source:{src:"file",type:"type",media:"media","data-jw-width":"width","data-jw-bitrate":"bitrate"},video:{poster:"image"}};var f={};e.utils.mediaparser.parseMedia=function(j){return d(j)};function c(k,j){if(!e.utils.exists(j)){j=g[k]}else{e.utils.extend(j,g[k])}return j}function d(n,j){if(f[n.tagName.toLowerCase()]&&!e.utils.exists(j)){return f[n.tagName.toLowerCase()](n)}else{j=c("element",j);var o={};for(var k in j){if(k!="length"){var m=n.getAttribute(k);if(e.utils.exists(m)){o[j[k]]=m}}}var l=n.style["#background-color"];if(l&&!(l=="transparent"||l=="rgba(0, 0, 0, 0)")){o.screencolor=l}return o}}function h(n,k){k=c("media",k);var l=[];var j=e.utils.selectors("source",n);for(var m in j){if(!isNaN(m)){l.push(a(j[m]))}}var o=d(n,k);if(e.utils.exists(o.file)){l[0]={file:o.file}}o.levels=l;return o}function a(l,k){k=c("source",k);var j=d(l,k);j.width=j.width?j.width:0;j.bitrate=j.bitrate?j.bitrate:0;return j}function b(l,k){k=c("video",k);var j=h(l,k);return j}f.media=h;f.audio=h;f.source=a;f.video=b})(jwplayer);(function(a){a.utils.loaderstatus={NEW:"NEW",LOADING:"LOADING",ERROR:"ERROR",COMPLETE:"COMPLETE"};a.utils.scriptloader=function(c){var d=a.utils.loaderstatus.NEW;var b=new a.events.eventdispatcher();a.utils.extend(this,b);this.load=function(){if(d==a.utils.loaderstatus.NEW){d=a.utils.loaderstatus.LOADING;var e=document.createElement("script");e.onload=function(f){d=a.utils.loaderstatus.COMPLETE;b.sendEvent(a.events.COMPLETE)};e.onerror=function(f){d=a.utils.loaderstatus.ERROR;b.sendEvent(a.events.ERROR)};e.onreadystatechange=function(){if(e.readyState=="loaded"||e.readyState=="complete"){d=a.utils.loaderstatus.COMPLETE;b.sendEvent(a.events.COMPLETE)}};document.getElementsByTagName("head")[0].appendChild(e);e.src=c}};this.getStatus=function(){return d}}})(jwplayer);(function(a){a.utils.selectors=function(b,e){if(!a.utils.exists(e)){e=document}b=a.utils.strings.trim(b);var c=b.charAt(0);if(c=="#"){return e.getElementById(b.substr(1))}else{if(c=="."){if(e.getElementsByClassName){return e.getElementsByClassName(b.substr(1))}else{return a.utils.selectors.getElementsByTagAndClass("*",b.substr(1))}}else{if(b.indexOf(".")>0){var d=b.split(".");return a.utils.selectors.getElementsByTagAndClass(d[0],d[1])}else{return e.getElementsByTagName(b)}}}return null};a.utils.selectors.getElementsByTagAndClass=function(e,h,g){var j=[];if(!a.utils.exists(g)){g=document}var f=g.getElementsByTagName(e);for(var d=0;d<f.length;d++){if(a.utils.exists(f[d].className)){var c=f[d].className.split(" ");for(var b=0;b<c.length;b++){if(c[b]==h){j.push(f[d])}}}}return j}})(jwplayer);(function(a){a.utils.strings=function(){};a.utils.strings.trim=function(b){return b.replace(/^\s*/,"").replace(/\s*$/,"")};a.utils.strings.pad=function(c,d,b){if(!b){b="0"}while(c.length<d){c=b+c}return c};a.utils.strings.serialize=function(b){if(b==null){return null}else{if(b=="true"){return true}else{if(b=="false"){return false}else{if(isNaN(Number(b))||b.length>5||b.length==0){return b}else{return Number(b)}}}}};a.utils.strings.seconds=function(d){d=d.replace(",",".");var b=d.split(":");var c=0;if(d.substr(-1)=="s"){c=Number(d.substr(0,d.length-1))}else{if(d.substr(-1)=="m"){c=Number(d.substr(0,d.length-1))*60}else{if(d.substr(-1)=="h"){c=Number(d.substr(0,d.length-1))*3600}else{if(b.length>1){c=Number(b[b.length-1]);c+=Number(b[b.length-2])*60;if(b.length==3){c+=Number(b[b.length-3])*3600}}else{c=Number(d)}}}}return c};a.utils.strings.xmlAttribute=function(b,c){for(var d=0;d<b.attributes.length;d++){if(b.attributes[d].name&&b.attributes[d].name.toLowerCase()==c.toLowerCase()){return b.attributes[d].value.toString()}}return""};a.utils.strings.jsonToString=function(f){var h=h||{};if(h&&h.stringify){return h.stringify(f)}var c=typeof(f);if(c!="object"||f===null){if(c=="string"){f='"'+f+'"'}else{return String(f)}}else{var g=[],b=(f&&f.constructor==Array);for(var d in f){var e=f[d];switch(typeof(e)){case"string":e='"'+e+'"';break;case"object":if(a.utils.exists(e)){e=a.utils.strings.jsonToString(e)}break}if(b){if(typeof(e)!="function"){g.push(String(e))}}else{if(typeof(e)!="function"){g.push('"'+d+'":'+String(e))}}}if(b){return"["+String(g)+"]"}else{return"{"+String(g)+"}"}}}})(jwplayer);(function(c){var d=new RegExp(/^(#|0x)[0-9a-fA-F]{3,6}/);c.utils.typechecker=function(g,f){f=!c.utils.exists(f)?b(g):f;return e(g,f)};function b(f){var g=["true","false","t","f"];if(g.toString().indexOf(f.toLowerCase().replace(" ",""))>=0){return"boolean"}else{if(d.test(f)){return"color"}else{if(!isNaN(parseInt(f,10))&&parseInt(f,10).toString().length==f.length){return"integer"}else{if(!isNaN(parseFloat(f))&&parseFloat(f).toString().length==f.length){return"float"}}}}return"string"}function e(g,f){if(!c.utils.exists(f)){return g}switch(f){case"color":if(g.length>0){return a(g)}return null;case"integer":return parseInt(g,10);case"float":return parseFloat(g);case"boolean":if(g.toLowerCase()=="true"){return true}else{if(g=="1"){return true}}return false}return g}function a(f){switch(f.toLowerCase()){case"blue":return parseInt("0000FF",16);case"green":return parseInt("00FF00",16);case"red":return parseInt("FF0000",16);case"cyan":return parseInt("00FFFF",16);case"magenta":return parseInt("FF00FF",16);case"yellow":return parseInt("FFFF00",16);case"black":return parseInt("000000",16);case"white":return parseInt("FFFFFF",16);default:f=f.replace(/(#|0x)?([0-9A-F]{3,6})$/gi,"$2");if(f.length==3){f=f.charAt(0)+f.charAt(0)+f.charAt(1)+f.charAt(1)+f.charAt(2)+f.charAt(2)}return parseInt(f,16)}return parseInt("000000",16)}})(jwplayer);(function(a){a.utils.parsers=function(){};a.utils.parsers.localName=function(b){if(!b){return""}else{if(b.localName){return b.localName}else{if(b.baseName){return b.baseName}else{return""}}}};a.utils.parsers.textContent=function(b){if(!b){return""}else{if(b.textContent){return b.textContent}else{if(b.text){return b.text}else{return""}}}}})(jwplayer);(function(a){a.utils.parsers.jwparser=function(){};a.utils.parsers.jwparser.PREFIX="jwplayer";a.utils.parsers.jwparser.parseEntry=function(c,d){for(var b=0;b<c.childNodes.length;b++){if(c.childNodes[b].prefix==a.utils.parsers.jwparser.PREFIX){d[a.utils.parsers.localName(c.childNodes[b])]=a.utils.strings.serialize(a.utils.parsers.textContent(c.childNodes[b]))}if(!d.file&&String(d.link).toLowerCase().indexOf("youtube")>-1){d.file=d.link}}return d};a.utils.parsers.jwparser.getProvider=function(c){if(c.type){return c.type}else{if(c.file.indexOf("youtube.com/w")>-1||c.file.indexOf("youtube.com/v")>-1||c.file.indexOf("youtu.be/")>-1){return"youtube"}else{if(c.streamer&&c.streamer.indexOf("rtmp")==0){return"rtmp"}else{if(c.streamer&&c.streamer.indexOf("http")==0){return"http"}else{var b=a.utils.strings.extension(c.file);if(extensions.hasOwnProperty(b)){return extensions[b]}}}}}return""}})(jwplayer);(function(a){a.utils.parsers.mediaparser=function(){};a.utils.parsers.mediaparser.PREFIX="media";a.utils.parsers.mediaparser.parseGroup=function(d,f){var e=false;for(var c=0;c<d.childNodes.length;c++){if(d.childNodes[c].prefix==a.utils.parsers.mediaparser.PREFIX){if(!a.utils.parsers.localName(d.childNodes[c])){continue}switch(a.utils.parsers.localName(d.childNodes[c]).toLowerCase()){case"content":if(!e){f.file=a.utils.strings.xmlAttribute(d.childNodes[c],"url")}if(a.utils.strings.xmlAttribute(d.childNodes[c],"duration")){f.duration=a.utils.strings.seconds(a.utils.strings.xmlAttribute(d.childNodes[c],"duration"))}if(a.utils.strings.xmlAttribute(d.childNodes[c],"start")){f.start=a.utils.strings.seconds(a.utils.strings.xmlAttribute(d.childNodes[c],"start"))}if(d.childNodes[c].childNodes&&d.childNodes[c].childNodes.length>0){f=a.utils.parsers.mediaparser.parseGroup(d.childNodes[c],f)}if(a.utils.strings.xmlAttribute(d.childNodes[c],"width")||a.utils.strings.xmlAttribute(d.childNodes[c],"bitrate")||a.utils.strings.xmlAttribute(d.childNodes[c],"url")){if(!f.levels){f.levels=[]}f.levels.push({width:a.utils.strings.xmlAttribute(d.childNodes[c],"width"),bitrate:a.utils.strings.xmlAttribute(d.childNodes[c],"bitrate"),file:a.utils.strings.xmlAttribute(d.childNodes[c],"url")})}break;case"title":f.title=a.utils.parsers.textContent(d.childNodes[c]);break;case"description":f.description=a.utils.parsers.textContent(d.childNodes[c]);break;case"keywords":f.tags=a.utils.parsers.textContent(d.childNodes[c]);break;case"thumbnail":f.image=a.utils.strings.xmlAttribute(d.childNodes[c],"url");break;case"credit":f.author=a.utils.parsers.textContent(d.childNodes[c]);break;case"player":var b=d.childNodes[c].url;if(b.indexOf("youtube.com")>=0||b.indexOf("youtu.be")>=0){e=true;f.file=a.utils.strings.xmlAttribute(d.childNodes[c],"url")}break;case"group":a.utils.parsers.mediaparser.parseGroup(d.childNodes[c],f);break}}}return f}})(jwplayer);(function(b){b.utils.parsers.rssparser=function(){};b.utils.parsers.rssparser.parse=function(f){var c=[];for(var e=0;e<f.childNodes.length;e++){if(b.utils.parsers.localName(f.childNodes[e]).toLowerCase()=="channel"){for(var d=0;d<f.childNodes[e].childNodes.length;d++){if(b.utils.parsers.localName(f.childNodes[e].childNodes[d]).toLowerCase()=="item"){c.push(a(f.childNodes[e].childNodes[d]))}}}}return c};function a(d){var e={};for(var c=0;c<d.childNodes.length;c++){if(!b.utils.parsers.localName(d.childNodes[c])){continue}switch(b.utils.parsers.localName(d.childNodes[c]).toLowerCase()){case"enclosure":e.file=b.utils.strings.xmlAttribute(d.childNodes[c],"url");break;case"title":e.title=b.utils.parsers.textContent(d.childNodes[c]);break;case"pubdate":e.date=b.utils.parsers.textContent(d.childNodes[c]);break;case"description":e.description=b.utils.parsers.textContent(d.childNodes[c]);break;case"link":e.link=b.utils.parsers.textContent(d.childNodes[c]);break;case"category":if(e.tags){e.tags+=b.utils.parsers.textContent(d.childNodes[c])}else{e.tags=b.utils.parsers.textContent(d.childNodes[c])}break}}e=b.utils.parsers.mediaparser.parseGroup(d,e);e=b.utils.parsers.jwparser.parseEntry(d,e);return new b.html5.playlistitem(e)}})(jwplayer);(function(a){var c={};var b={};a.plugins=function(){};a.plugins.loadPlugins=function(e,d){b[e]=new a.plugins.pluginloader(new a.plugins.model(c),d);return b[e]};a.plugins.registerPlugin=function(h,f,e){var d=a.utils.getPluginName(h);if(c[d]){c[d].registerPlugin(h,f,e)}else{a.utils.log("A plugin ("+h+") was registered with the player that was not loaded. Please check your configuration.");for(var g in b){b[g].pluginFailed()}}}})(jwplayer);(function(a){a.plugins.model=function(b){this.addPlugin=function(c){var d=a.utils.getPluginName(c);if(!b[d]){b[d]=new a.plugins.plugin(c)}return b[d]}}})(jwplayer);(function(a){a.plugins.pluginmodes={FLASH:"FLASH",JAVASCRIPT:"JAVASCRIPT",HYBRID:"HYBRID"};a.plugins.plugin=function(b){var d="http://plugins.longtailvideo.com";var j=a.utils.loaderstatus.NEW;var k;var h;var l;var c=new a.events.eventdispatcher();a.utils.extend(this,c);function e(){switch(a.utils.getPluginPathType(b)){case a.utils.pluginPathType.ABSOLUTE:return b;case a.utils.pluginPathType.RELATIVE:return a.utils.getAbsolutePath(b,window.location.href);case a.utils.pluginPathType.CDN:var n=a.utils.getPluginName(b);var m=a.utils.getPluginVersion(b);return d+"/"+a.version.split(".")[0]+"/"+n+"/"+n+(m!==""?("-"+m):"")+".js"}}function g(m){l=setTimeout(function(){j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)},1000)}function f(m){j=a.utils.loaderstatus.ERROR;c.sendEvent(a.events.ERROR)}this.load=function(){if(j==a.utils.loaderstatus.NEW){if(b.lastIndexOf(".swf")>0){k=b;j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE);return}j=a.utils.loaderstatus.LOADING;var m=new a.utils.scriptloader(e());m.addEventListener(a.events.COMPLETE,g);m.addEventListener(a.events.ERROR,f);m.load()}};this.registerPlugin=function(o,n,m){if(l){clearTimeout(l);l=undefined}if(n&&m){k=m;h=n}else{if(typeof n=="string"){k=n}else{if(typeof n=="function"){h=n}else{if(!n&&!m){k=o}}}}j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)};this.getStatus=function(){return j};this.getPluginName=function(){return a.utils.getPluginName(b)};this.getFlashPath=function(){if(k){switch(a.utils.getPluginPathType(k)){case a.utils.pluginPathType.ABSOLUTE:return k;case a.utils.pluginPathType.RELATIVE:if(b.lastIndexOf(".swf")>0){return a.utils.getAbsolutePath(k,window.location.href)}return a.utils.getAbsolutePath(k,e());case a.utils.pluginPathType.CDN:if(k.indexOf("-")>-1){return k+"h"}return k+"-h"}}return null};this.getJS=function(){return h};this.getPluginmode=function(){if(typeof k!="undefined"&&typeof h!="undefined"){return a.plugins.pluginmodes.HYBRID}else{if(typeof k!="undefined"){return a.plugins.pluginmodes.FLASH}else{if(typeof h!="undefined"){return a.plugins.pluginmodes.JAVASCRIPT}}}};this.getNewInstance=function(n,m,o){return new h(n,m,o)};this.getURL=function(){return b}}})(jwplayer);(function(a){a.plugins.pluginloader=function(h,e){var g={};var k=a.utils.loaderstatus.NEW;var d=false;var b=false;var c=new a.events.eventdispatcher();a.utils.extend(this,c);function f(){if(!b){b=true;k=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)}}function j(){if(!b){var m=0;for(plugin in g){var l=g[plugin].getStatus();if(l==a.utils.loaderstatus.LOADING||l==a.utils.loaderstatus.NEW){m++}}if(m==0){f()}}}this.setupPlugins=function(n,l,s){var m={length:0,plugins:{}};var p={length:0,plugins:{}};for(var o in g){var q=g[o].getPluginName();if(g[o].getFlashPath()){m.plugins[g[o].getFlashPath()]=l.plugins[o];m.plugins[g[o].getFlashPath()].pluginmode=g[o].getPluginmode();m.length++}if(g[o].getJS()){var r=document.createElement("div");r.id=n.id+"_"+q;r.style.position="absolute";r.style.zIndex=p.length+10;p.plugins[q]=g[o].getNewInstance(n,l.plugins[o],r);p.length++;if(typeof p.plugins[q].resize!="undefined"){n.onReady(s(p.plugins[q],r,true));n.onResize(s(p.plugins[q],r))}}}n.plugins=p.plugins;return m};this.load=function(){k=a.utils.loaderstatus.LOADING;d=true;for(var l in e){if(a.utils.exists(l)){g[l]=h.addPlugin(l);g[l].addEventListener(a.events.COMPLETE,j);g[l].addEventListener(a.events.ERROR,j)}}for(l in g){g[l].load()}d=false;j()};this.pluginFailed=function(){f()};this.getStatus=function(){return k}}})(jwplayer);(function(b){var a=[];b.api=function(d){this.container=d;this.id=d.id;var n={};var s={};var q={};var c=[];var h=undefined;var l=false;var j=[];var p=b.utils.getOuterHTML(d);var r={};var k={};this.getBuffer=function(){return this.callInternal("jwGetBuffer")};this.getContainer=function(){return this.container};function e(u,t){return function(z,v,w,x){if(u.renderingMode=="flash"||u.renderingMode=="html5"){var y;if(v){k[z]=v;y="jwplayer('"+u.id+"').callback('"+z+"')"}else{if(!v&&k[z]){delete k[z]}}h.jwDockSetButton(z,y,w,x)}return t}}this.getPlugin=function(t){var v=this;var u={};if(t=="dock"){return b.utils.extend(u,{setButton:e(v,u),show:function(){v.callInternal("jwDockShow");return u},hide:function(){v.callInternal("jwDockHide");return u},onShow:function(w){v.componentListener("dock",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("dock",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{if(t=="controlbar"){return b.utils.extend(u,{show:function(){v.callInternal("jwControlbarShow");return u},hide:function(){v.callInternal("jwControlbarHide");return u},onShow:function(w){v.componentListener("controlbar",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("controlbar",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{if(t=="display"){return b.utils.extend(u,{show:function(){v.callInternal("jwDisplayShow");return u},hide:function(){v.callInternal("jwDisplayHide");return u},onShow:function(w){v.componentListener("display",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("display",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{return this.plugins[t]}}}};this.callback=function(t){if(k[t]){return k[t]()}};this.getDuration=function(){return this.callInternal("jwGetDuration")};this.getFullscreen=function(){return this.callInternal("jwGetFullscreen")};this.getHeight=function(){return this.callInternal("jwGetHeight")};this.getLockState=function(){return this.callInternal("jwGetLockState")};this.getMeta=function(){return this.getItemMeta()};this.getMute=function(){return this.callInternal("jwGetMute")};this.getPlaylist=function(){var u=this.callInternal("jwGetPlaylist");if(this.renderingMode=="flash"){b.utils.deepReplaceKeyName(u,"__dot__",".")}for(var t=0;t<u.length;t++){if(!b.utils.exists(u[t].index)){u[t].index=t}}return u};this.getPlaylistItem=function(t){if(!b.utils.exists(t)){t=this.getCurrentItem()}return this.getPlaylist()[t]};this.getPosition=function(){return this.callInternal("jwGetPosition")};this.getRenderingMode=function(){return this.renderingMode};this.getState=function(){return this.callInternal("jwGetState")};this.getVolume=function(){return this.callInternal("jwGetVolume")};this.getWidth=function(){return this.callInternal("jwGetWidth")};this.setFullscreen=function(t){if(!b.utils.exists(t)){this.callInternal("jwSetFullscreen",!this.callInternal("jwGetFullscreen"))}else{this.callInternal("jwSetFullscreen",t)}return this};this.setMute=function(t){if(!b.utils.exists(t)){this.callInternal("jwSetMute",!this.callInternal("jwGetMute"))}else{this.callInternal("jwSetMute",t)}return this};this.lock=function(){return this};this.unlock=function(){return this};this.load=function(t){this.callInternal("jwLoad",t);return this};this.playlistItem=function(t){this.callInternal("jwPlaylistItem",t);return this};this.playlistPrev=function(){this.callInternal("jwPlaylistPrev");return this};this.playlistNext=function(){this.callInternal("jwPlaylistNext");return this};this.resize=function(u,t){if(this.renderingMode=="html5"){h.jwResize(u,t)}else{this.container.width=u;this.container.height=t}return this};this.play=function(t){if(typeof t=="undefined"){t=this.getState();if(t==b.api.events.state.PLAYING||t==b.api.events.state.BUFFERING){this.callInternal("jwPause")}else{this.callInternal("jwPlay")}}else{this.callInternal("jwPlay",t)}return this};this.pause=function(t){if(typeof t=="undefined"){t=this.getState();if(t==b.api.events.state.PLAYING||t==b.api.events.state.BUFFERING){this.callInternal("jwPause")}else{this.callInternal("jwPlay")}}else{this.callInternal("jwPause",t)}return this};this.stop=function(){this.callInternal("jwStop");return this};this.seek=function(t){this.callInternal("jwSeek",t);return this};this.setVolume=function(t){this.callInternal("jwSetVolume",t);return this};this.onBufferChange=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BUFFER,t)};this.onBufferFull=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL,t)};this.onError=function(t){return this.eventListener(b.api.events.JWPLAYER_ERROR,t)};this.onFullscreen=function(t){return this.eventListener(b.api.events.JWPLAYER_FULLSCREEN,t)};this.onMeta=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_META,t)};this.onMute=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_MUTE,t)};this.onPlaylist=function(t){return this.eventListener(b.api.events.JWPLAYER_PLAYLIST_LOADED,t)};this.onPlaylistItem=function(t){return this.eventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,t)};this.onReady=function(t){return this.eventListener(b.api.events.API_READY,t)};this.onResize=function(t){return this.eventListener(b.api.events.JWPLAYER_RESIZE,t)};this.onComplete=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_COMPLETE,t)};this.onSeek=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_SEEK,t)};this.onTime=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_TIME,t)};this.onVolume=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_VOLUME,t)};this.onBuffer=function(t){return this.stateListener(b.api.events.state.BUFFERING,t)};this.onPause=function(t){return this.stateListener(b.api.events.state.PAUSED,t)};this.onPlay=function(t){return this.stateListener(b.api.events.state.PLAYING,t)};this.onIdle=function(t){return this.stateListener(b.api.events.state.IDLE,t)};this.remove=function(){n={};j=[];if(b.utils.getOuterHTML(this.container)!=p){b.api.destroyPlayer(this.id,p)}};this.setup=function(u){if(b.embed){var t=this.id;this.remove();var v=b(t);v.config=u;return new b.embed(v)}return this};this.registerPlugin=function(v,u,t){b.plugins.registerPlugin(v,u,t)};this.setPlayer=function(t,u){h=t;this.renderingMode=u};this.stateListener=function(t,u){if(!s[t]){s[t]=[];this.eventListener(b.api.events.JWPLAYER_PLAYER_STATE,g(t))}s[t].push(u);return this};function g(t){return function(v){var u=v.newstate,x=v.oldstate;if(u==t){var w=s[u];if(w){for(var y=0;y<w.length;y++){if(typeof w[y]=="function"){w[y].call(this,{oldstate:x,newstate:u})}}}}}}this.componentListener=function(t,u,v){if(!q[t]){q[t]={}}if(!q[t][u]){q[t][u]=[];this.eventListener(u,m(t,u))}q[t][u].push(v);return this};function m(t,u){return function(w){if(t==w.component){var v=q[t][u];if(v){for(var x=0;x<v.length;x++){if(typeof v[x]=="function"){v[x].call(this,w)}}}}}}this.addInternalListener=function(t,u){t.jwAddEventListener(u,'function(dat) { jwplayer("'+this.id+'").dispatchEvent("'+u+'", dat); }')};this.eventListener=function(t,u){if(!n[t]){n[t]=[];if(h&&l){this.addInternalListener(h,t)}}n[t].push(u);return this};this.dispatchEvent=function(v){if(n[v]){var u=f(v,arguments[1]);for(var t=0;t<n[v].length;t++){if(typeof n[v][t]=="function"){n[v][t].call(this,u)}}}};function f(v,t){var x=b.utils.extend({},t);if(v==b.api.events.JWPLAYER_FULLSCREEN&&!x.fullscreen){x.fullscreen=x.message=="true"?true:false;delete x.message}else{if(typeof x.data=="object"){x=b.utils.extend(x,x.data);delete x.data}}var u=["position","duration","offset"];for(var w in u){if(x[u[w]]){x[u[w]]=Math.round(x[u[w]]*1000)/1000}}return x}this.callInternal=function(u,t){if(l){if(typeof h!="undefined"&&typeof h[u]=="function"){if(b.utils.exists(t)){return(h[u])(t)}else{return(h[u])()}}return null}else{j.push({method:u,parameters:t})}};this.playerReady=function(v){l=true;if(!h){this.setPlayer(document.getElementById(v.id))}this.container=document.getElementById(this.id);for(var t in n){this.addInternalListener(h,t)}this.eventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,function(w){r={}});this.eventListener(b.api.events.JWPLAYER_MEDIA_META,function(w){b.utils.extend(r,w.metadata)});this.dispatchEvent(b.api.events.API_READY);while(j.length>0){var u=j.shift();this.callInternal(u.method,u.parameters)}};this.getItemMeta=function(){return r};this.getCurrentItem=function(){return this.callInternal("jwGetPlaylistIndex")};function o(v,x,w){var t=[];if(!x){x=0}if(!w){w=v.length-1}for(var u=x;u<=w;u++){t.push(v[u])}return t}return this};b.api.selectPlayer=function(d){var c;if(!b.utils.exists(d)){d=0}if(d.nodeType){c=d}else{if(typeof d=="string"){c=document.getElementById(d)}}if(c){var e=b.api.playerById(c.id);if(e){return e}else{return b.api.addPlayer(new b.api(c))}}else{if(typeof d=="number"){return b.getPlayers()[d]}}return null};b.api.events={API_READY:"jwplayerAPIReady",JWPLAYER_READY:"jwplayerReady",JWPLAYER_FULLSCREEN:"jwplayerFullscreen",JWPLAYER_RESIZE:"jwplayerResize",JWPLAYER_ERROR:"jwplayerError",JWPLAYER_COMPONENT_SHOW:"jwplayerComponentShow",JWPLAYER_COMPONENT_HIDE:"jwplayerComponentHide",JWPLAYER_MEDIA_BUFFER:"jwplayerMediaBuffer",JWPLAYER_MEDIA_BUFFER_FULL:"jwplayerMediaBufferFull",JWPLAYER_MEDIA_ERROR:"jwplayerMediaError",JWPLAYER_MEDIA_LOADED:"jwplayerMediaLoaded",JWPLAYER_MEDIA_COMPLETE:"jwplayerMediaComplete",JWPLAYER_MEDIA_SEEK:"jwplayerMediaSeek",JWPLAYER_MEDIA_TIME:"jwplayerMediaTime",JWPLAYER_MEDIA_VOLUME:"jwplayerMediaVolume",JWPLAYER_MEDIA_META:"jwplayerMediaMeta",JWPLAYER_MEDIA_MUTE:"jwplayerMediaMute",JWPLAYER_PLAYER_STATE:"jwplayerPlayerState",JWPLAYER_PLAYLIST_LOADED:"jwplayerPlaylistLoaded",JWPLAYER_PLAYLIST_ITEM:"jwplayerPlaylistItem"};b.api.events.state={BUFFERING:"BUFFERING",IDLE:"IDLE",PAUSED:"PAUSED",PLAYING:"PLAYING"};b.api.playerById=function(d){for(var c=0;c<a.length;c++){if(a[c].id==d){return a[c]}}return null};b.api.addPlayer=function(c){for(var d=0;d<a.length;d++){if(a[d]==c){return c}}a.push(c);return c};b.api.destroyPlayer=function(g,d){var f=-1;for(var j=0;j<a.length;j++){if(a[j].id==g){f=j;continue}}if(f>=0){var c=document.getElementById(a[f].id);if(document.getElementById(a[f].id+"_wrapper")){c=document.getElementById(a[f].id+"_wrapper")}if(c){if(d){b.utils.setOuterHTML(c,d)}else{var h=document.createElement("div");var e=c.id;if(c.id.indexOf("_wrapper")==c.id.length-8){newID=c.id.substring(0,c.id.length-8)}h.setAttribute("id",e);c.parentNode.replaceChild(h,c)}}a.splice(f,1)}return null};b.getPlayers=function(){return a.slice(0)}})(jwplayer);var _userPlayerReady=(typeof playerReady=="function")?playerReady:undefined;playerReady=function(b){var a=jwplayer.api.playerById(b.id);if(a){a.playerReady(b)}else{jwplayer.api.selectPlayer(b.id).playerReady(b)}if(_userPlayerReady){_userPlayerReady.call(this,b)}};(function(a){a.embed=function(g){var j={width:400,height:300,components:{controlbar:{position:"over"}}};var f=a.utils.mediaparser.parseMedia(g.container);var e=new a.embed.config(a.utils.extend(j,f,g.config),this);var h=a.plugins.loadPlugins(g.id,e.plugins);function c(m,l){for(var k in l){if(typeof m[k]=="function"){(m[k]).call(m,l[k])}}}function d(){if(h.getStatus()==a.utils.loaderstatus.COMPLETE){for(var m=0;m<e.modes.length;m++){if(e.modes[m].type&&a.embed[e.modes[m].type]){var k=e;if(e.modes[m].config){k=a.utils.extend(a.utils.clone(e),e.modes[m].config)}var l=new a.embed[e.modes[m].type](document.getElementById(g.id),e.modes[m],k,h,g);if(l.supportsConfig()){l.embed();c(g,e.events);return g}}}a.utils.log("No suitable players found");new a.embed.logo(a.utils.extend({hide:true},e.components.logo),"none",g.id)}}h.addEventListener(a.events.COMPLETE,d);h.addEventListener(a.events.ERROR,d);h.load();return g};function b(){if(!document.body){return setTimeout(b,15)}var c=a.utils.selectors.getElementsByTagAndClass("video","jwplayer");for(var d=0;d<c.length;d++){var e=c[d];a(e.id).setup({})}}b()})(jwplayer);(function(e){function h(){return[{type:"flash",src:"/jwplayer/player.swf"},{type:"html5"},{type:"download"}]}var a={players:"modes",autoplay:"autostart"};function b(n){var m=n.toLowerCase();var l=["left","right","top","bottom"];for(var k=0;k<l.length;k++){if(m==l[k]){return true}}return false}function c(l){var k=false;k=(l instanceof Array)||(typeof l=="object"&&!l.position&&!l.size);return k}function j(k){if(typeof k=="string"){if(parseInt(k).toString()==k||k.toLowerCase().indexOf("px")>-1){return parseInt(k)}}return k}var g=["playlist","dock","controlbar","logo","display"];function f(k){var n={};switch(e.utils.typeOf(k.plugins)){case"object":for(var m in k.plugins){n[e.utils.getPluginName(m)]=m}break;case"string":var o=k.plugins.split(",");for(var l=0;l<o.length;l++){n[e.utils.getPluginName(o[l])]=o[l]}break}return n}function d(o,n,m,k){if(e.utils.typeOf(o[n])!="object"){o[n]={}}var l=o[n][m];if(e.utils.typeOf(l)!="object"){o[n][m]=l={}}if(k){if(n=="plugins"){var p=e.utils.getPluginName(m);l[k]=o[p+"."+k];delete o[p+"."+k]}else{l[k]=o[m+"."+k];delete o[m+"."+k]}}}e.embed.deserialize=function(l){var m=f(l);for(var k in m){d(l,"plugins",m[k])}for(var p in l){if(p.indexOf(".")>-1){var o=p.split(".");var n=o[0];var p=o[1];if(e.utils.isInArray(g,n)){d(l,"components",n,p)}else{if(m[n]){d(l,"plugins",m[n],p)}}}}return l};e.embed.config=function(k,u){var t=e.utils.extend({},k);var r;if(c(t.playlist)){r=t.playlist;delete t.playlist}t=e.embed.deserialize(t);t.height=j(t.height);t.width=j(t.width);if(typeof t.plugins=="string"){var l=t.plugins.split(",");if(typeof t.plugins!="object"){t.plugins={}}for(var p=0;p<l.length;p++){var q=e.utils.getPluginName(l[p]);if(typeof t[q]=="object"){t.plugins[l[p]]=t[q];delete t[q]}else{t.plugins[l[p]]={}}}}for(var s=0;s<g.length;s++){var o=g[s];if(e.utils.exists(t[o])){if(typeof t[o]!="object"){if(!t.components[o]){t.components[o]={}}if(o=="logo"){t.components[o].file=t[o]}else{t.components[o].position=t[o]}delete t[o]}else{if(!t.components[o]){t.components[o]={}}e.utils.extend(t.components[o],t[o]);delete t[o]}}if(typeof t[o+"size"]!="undefined"){if(!t.components[o]){t.components[o]={}}t.components[o].size=t[o+"size"];delete t[o+"size"]}}if(typeof t.icons!="undefined"){if(!t.components.display){t.components.display={}}t.components.display.icons=t.icons;delete t.icons}for(var n in a){if(t[n]){if(!t[a[n]]){t[a[n]]=t[n]}delete t[n]}}var m;if(t.flashplayer&&!t.modes){m=h();m[0].src=t.flashplayer;delete t.flashplayer}else{if(t.modes){if(typeof t.modes=="string"){m=h();m[0].src=t.modes}else{if(t.modes instanceof Array){m=t.modes}else{if(typeof t.modes=="object"&&t.modes.type){m=[t.modes]}}}delete t.modes}else{m=h()}}t.modes=m;if(r){t.playlist=r}return t}})(jwplayer);(function(a){a.embed.download=function(c,g,b,d,f){this.embed=function(){var k=a.utils.extend({},b);var q={};var j=b.width?b.width:480;if(typeof j!="number"){j=parseInt(j,10)}var m=b.height?b.height:320;if(typeof m!="number"){m=parseInt(m,10)}var u,o,n;var s={};if(b.playlist&&b.playlist.length){s.file=b.playlist[0].file;o=b.playlist[0].image;s.levels=b.playlist[0].levels}else{s.file=b.file;o=b.image;s.levels=b.levels}if(s.file){u=s.file}else{if(s.levels&&s.levels.length){u=s.levels[0].file}}n=u?"pointer":"auto";var l={display:{style:{cursor:n,width:j,height:m,backgroundColor:"#000",position:"relative",textDecoration:"none",border:"none",display:"block"}},display_icon:{style:{cursor:n,position:"absolute",display:u?"block":"none",top:0,left:0,border:0,margin:0,padding:0,zIndex:3,width:50,height:50,backgroundImage:"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALdJREFUeNrs18ENgjAYhmFouDOCcQJGcARHgE10BDcgTOIosAGwQOuPwaQeuFRi2p/3Sb6EC5L3QCxZBgAAAOCorLW1zMn65TrlkH4NcV7QNcUQt7Gn7KIhxA+qNIR81spOGkL8oFJDyLJRdosqKDDkK+iX5+d7huzwM40xptMQMkjIOeRGo+VkEVvIPfTGIpKASfYIfT9iCHkHrBEzf4gcUQ56aEzuGK/mw0rHpy4AAACAf3kJMACBxjAQNRckhwAAAABJRU5ErkJggg==)"}},display_iconBackground:{style:{cursor:n,position:"absolute",display:u?"block":"none",top:((m-50)/2),left:((j-50)/2),border:0,width:50,height:50,margin:0,padding:0,zIndex:2,backgroundImage:"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNrszwENADAIA7DhX8ENoBMZ5KR10EryckCJiIiIiIiIiIiIiIiIiIiIiIh8GmkRERERERERERERERERERERERGRHSPAAPlXH1phYpYaAAAAAElFTkSuQmCC)"}},display_image:{style:{width:j,height:m,display:o?"block":"none",position:"absolute",cursor:n,left:0,top:0,margin:0,padding:0,textDecoration:"none",zIndex:1,border:"none"}}};var h=function(v,x,y){var w=document.createElement(v);if(y){w.id=y}else{w.id=c.id+"_jwplayer_"+x}a.utils.css(w,l[x].style);return w};q.display=h("a","display",c.id);if(u){q.display.setAttribute("href",a.utils.getAbsolutePath(u))}q.display_image=h("img","display_image");q.display_image.setAttribute("alt","Click to download...");if(o){q.display_image.setAttribute("src",a.utils.getAbsolutePath(o))}if(true){q.display_icon=h("div","display_icon");q.display_iconBackground=h("div","display_iconBackground");q.display.appendChild(q.display_image);q.display_iconBackground.appendChild(q.display_icon);q.display.appendChild(q.display_iconBackground)}_css=a.utils.css;_hide=function(v){_css(v,{display:"none"})};function r(v){_imageWidth=q.display_image.naturalWidth;_imageHeight=q.display_image.naturalHeight;t()}function t(){a.utils.stretch(a.utils.stretching.UNIFORM,q.display_image,j,m,_imageWidth,_imageHeight)}q.display_image.onerror=function(v){_hide(q.display_image)};q.display_image.onload=r;c.parentNode.replaceChild(q.display,c);var p=(b.plugins&&b.plugins.logo)?b.plugins.logo:{};q.display.appendChild(new a.embed.logo(b.components.logo,"download",c.id));f.container=document.getElementById(f.id);f.setPlayer(q.display,"download")};this.supportsConfig=function(){if(b){var j=a.utils.getFirstPlaylistItemFromConfig(b);if(typeof j.file=="undefined"&&typeof j.levels=="undefined"){return true}else{if(j.file){return e(j.file,j.provider,j.playlistfile)}else{if(j.levels&&j.levels.length){for(var h=0;h<j.levels.length;h++){if(j.levels[h].file&&e(j.levels[h].file,j.provider,j.playlistfile)){return true}}}}}}else{return true}};function e(j,l,h){if(h){return false}var k=["image","sound","youtube","http"];if(l&&(k.toString().indexOf(l)>-1)){return true}if(!l||(l&&l=="video")){var m=a.utils.extension(j);if(m&&a.utils.extensionmap[m]){return true}}return false}}})(jwplayer);(function(a){a.embed.flash=function(f,g,l,e,j){function m(o,n,p){var q=document.createElement("param");q.setAttribute("name",n);q.setAttribute("value",p);o.appendChild(q)}function k(o,p,n){return function(q){if(n){document.getElementById(j.id+"_wrapper").appendChild(p)}var s=document.getElementById(j.id).getPluginConfig("display");o.resize(s.width,s.height);var r={left:s.x,top:s.y};a.utils.css(p,r)}}function d(p){if(!p){return{}}var r={};for(var o in p){var n=p[o];for(var q in n){r[o+"."+q]=n[q]}}return r}function h(q,p){if(q[p]){var s=q[p];for(var o in s){var n=s[o];if(typeof n=="string"){if(!q[o]){q[o]=n}}else{for(var r in n){if(!q[o+"."+r]){q[o+"."+r]=n[r]}}}}delete q[p]}}function b(q){if(!q){return{}}var t={},s=[];for(var n in q){var p=a.utils.getPluginName(n);var o=q[n];s.push(n);for(var r in o){t[p+"."+r]=o[r]}}t.plugins=s.join(",");return t}function c(p){var n=p.netstreambasepath?"":"netstreambasepath="+encodeURIComponent(window.location.href.split("#")[0])+"&";for(var o in p){if(typeof(p[o])=="object"){n+=o+"="+encodeURIComponent("[[JSON]]"+a.utils.strings.jsonToString(p[o]))+"&"}else{n+=o+"="+encodeURIComponent(p[o])+"&"}}return n.substring(0,n.length-1)}this.embed=function(){l.id=j.id;var y;var q=a.utils.extend({},l);var n=q.width;var w=q.height;if(f.id+"_wrapper"==f.parentNode.id){y=document.getElementById(f.id+"_wrapper")}else{y=document.createElement("div");y.id=f.id+"_wrapper";a.utils.wrap(f,y);a.utils.css(y,{position:"relative",width:n,height:w})}var o=e.setupPlugins(j,q,k);if(o.length>0){a.utils.extend(q,b(o.plugins))}else{delete q.plugins}var r=["height","width","modes","events"];for(var u=0;u<r.length;u++){delete q[r[u]]}var p="opaque";if(q.wmode){p=q.wmode}h(q,"components");h(q,"providers");if(typeof q["dock.position"]!="undefined"){if(q["dock.position"].toString().toLowerCase()=="false"){q.dock=q["dock.position"];delete q["dock.position"]}}var x="#000000";var t;if(a.utils.isIE()){var v='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" bgcolor="'+x+'" width="100%" height="100%" id="'+f.id+'" name="'+f.id+'" tabindex=0"">';v+='<param name="movie" value="'+g.src+'">';v+='<param name="allowfullscreen" value="true">';v+='<param name="allowscriptaccess" value="always">';v+='<param name="seamlesstabbing" value="true">';v+='<param name="wmode" value="'+p+'">';v+='<param name="flashvars" value="'+c(q)+'">';v+="</object>";a.utils.setOuterHTML(f,v);t=document.getElementById(f.id)}else{var s=document.createElement("object");s.setAttribute("type","application/x-shockwave-flash");s.setAttribute("data",g.src);s.setAttribute("width","100%");s.setAttribute("height","100%");s.setAttribute("bgcolor","#000000");s.setAttribute("id",f.id);s.setAttribute("name",f.id);s.setAttribute("tabindex",0);m(s,"allowfullscreen","true");m(s,"allowscriptaccess","always");m(s,"seamlesstabbing","true");m(s,"wmode",p);m(s,"flashvars",c(q));f.parentNode.replaceChild(s,f);t=s}j.container=t;j.setPlayer(t,"flash")};this.supportsConfig=function(){if(a.utils.hasFlash()){if(l){var o=a.utils.getFirstPlaylistItemFromConfig(l);if(typeof o.file=="undefined"&&typeof o.levels=="undefined"){return true}else{if(o.file){return flashCanPlay(o.file,o.provider)}else{if(o.levels&&o.levels.length){for(var n=0;n<o.levels.length;n++){if(o.levels[n].file&&flashCanPlay(o.levels[n].file,o.provider)){return true}}}}}}else{return true}}return false};flashCanPlay=function(n,p){var o=["video","http","sound","image"];if(p&&(o.toString().indexOf(p<0))){return true}var q=a.utils.extension(n);if(!q){return true}if(a.utils.exists(a.utils.extensionmap[q])&&!a.utils.exists(a.utils.extensionmap[q].flash)){return false}return true}}})(jwplayer);(function(a){a.embed.html5=function(c,g,b,d,f){function e(j,k,h){return function(l){var m=document.getElementById(c.id+"_displayarea");if(h){m.appendChild(k)}var n=m.style;j.resize(parseInt(n.width.replace("px","")),parseInt(n.height.replace("px","")));k.left=n.left;k.top=n.top}}this.embed=function(){if(a.html5){d.setupPlugins(f,b,e);c.innerHTML="";var j=a.utils.extend({screencolor:"0x000000"},b);var h=["plugins","modes","events"];for(var k=0;k<h.length;k++){delete j[h[k]]}if(j.levels&&!j.sources){j.sources=b.levels}if(j.skin&&j.skin.toLowerCase().indexOf(".zip")>0){j.skin=j.skin.replace(/\.zip/i,".xml")}var l=new (a.html5(c)).setup(j);f.container=document.getElementById(f.id);f.setPlayer(l,"html5")}else{return null}};this.supportsConfig=function(){if(!!a.vid.canPlayType){if(b){var j=a.utils.getFirstPlaylistItemFromConfig(b);if(typeof j.file=="undefined"&&typeof j.levels=="undefined"){return true}else{if(j.file){return html5CanPlay(a.vid,j.file,j.provider,j.playlistfile)}else{if(j.levels&&j.levels.length){for(var h=0;h<j.levels.length;h++){if(j.levels[h].file&&html5CanPlay(a.vid,j.levels[h].file,j.provider,j.playlistfile)){return true}}}}}}else{return true}}return false};html5CanPlay=function(k,j,l,h){if(h){return false}if(l&&l=="youtube"){return true}if(l&&l!="video"&&l!="http"&&l!="sound"){return false}var m=a.utils.extension(j);if(!a.utils.exists(m)||!a.utils.exists(a.utils.extensionmap[m])){return true}if(!a.utils.exists(a.utils.extensionmap[m].html5)){return false}if(a.utils.isLegacyAndroid()&&m.match(/m4v|mp4/)){return true}return browserCanPlay(k,a.utils.extensionmap[m].html5)};browserCanPlay=function(j,h){if(!h){return true}if(j.canPlayType(h)){return true}else{if(h=="audio/mp3"&&navigator.userAgent.match(/safari/i)){return j.canPlayType("audio/mpeg")}else{return false}}}}})(jwplayer);(function(a){a.embed.logo=function(m,l,d){var j={prefix:"http://l.longtailvideo.com/"+l+"/",file:"logo.png",link:"http://www.longtailvideo.com/players/jw-flv-player/",margin:8,out:0.5,over:1,timeout:5,hide:false,position:"bottom-left"};_css=a.utils.css;var b;var h;k();function k(){o();c();f()}function o(){if(j.prefix){var q=a.version.split(/\W/).splice(0,2).join("/");if(j.prefix.indexOf(q)<0){j.prefix+=q+"/"}}h=a.utils.extend({},j)}function p(){var s={border:"none",textDecoration:"none",position:"absolute",cursor:"pointer",zIndex:10};s.display=h.hide?"none":"block";var r=h.position.toLowerCase().split("-");for(var q in r){s[r[q]]=h.margin}return s}function c(){b=document.createElement("img");b.id=d+"_jwplayer_logo";b.style.display="none";b.onload=function(q){_css(b,p());e()};if(!h.file){return}if(h.file.indexOf("http://")===0){b.src=h.file}else{b.src=h.prefix+h.file}}if(!h.file){return}function f(){if(h.link){b.onmouseover=g;b.onmouseout=e;b.onclick=n}else{this.mouseEnabled=false}}function n(q){if(typeof q!="undefined"){q.preventDefault();q.stopPropagation()}if(h.link){window.open(h.link,"_blank")}return}function e(q){if(h.link){b.style.opacity=h.out}return}function g(q){if(h.hide){b.style.opacity=h.over}return}return b}})(jwplayer);(function(a){a.html5=function(b){var c=b;this.setup=function(d){a.utils.extend(this,new a.html5.api(c,d));return this};return this}})(jwplayer);(function(b){var d=b.utils;var c=d.css;b.html5.view=function(r,q,f){var u=r;var n=q;var x=f;var w;var g;var C;var s;var D;var p;var A;function z(){w=document.createElement("div");w.id=n.id;w.className=n.className;_videowrapper=document.createElement("div");_videowrapper.id=w.id+"_video_wrapper";n.id=w.id+"_video";c(w,{position:"relative",height:x.height,width:x.width,padding:0,backgroundColor:E(),zIndex:0});function E(){if(u.skin.getComponentSettings("display")&&u.skin.getComponentSettings("display").backgroundcolor){return u.skin.getComponentSettings("display").backgroundcolor}return parseInt("000000",16)}c(n,{width:x.width,height:x.height,top:0,left:0,zIndex:1,margin:"auto",display:"block"});c(_videowrapper,{overflow:"hidden",position:"absolute",top:0,left:0,bottom:0,right:0});d.wrap(n,w);d.wrap(n,_videowrapper);s=document.createElement("div");s.id=w.id+"_displayarea";w.appendChild(s)}function k(){for(var E=0;E<x.plugins.order.length;E++){var F=x.plugins.order[E];if(d.exists(x.plugins.object[F].getDisplayElement)){x.plugins.object[F].height=d.parseDimension(x.plugins.object[F].getDisplayElement().style.height);x.plugins.object[F].width=d.parseDimension(x.plugins.object[F].getDisplayElement().style.width);x.plugins.config[F].currentPosition=x.plugins.config[F].position}}v()}function m(E){c(s,{display:x.getMedia().hasChrome()?"none":"block"})}function v(F){var H=x.getMedia()?x.getMedia().getDisplayElement():null;if(d.exists(H)){if(A!=H){if(A&&A.parentNode){A.parentNode.replaceChild(H,A)}A=H}for(var E=0;E<x.plugins.order.length;E++){var G=x.plugins.order[E];if(d.exists(x.plugins.object[G].getDisplayElement)){x.plugins.config[G].currentPosition=x.plugins.config[G].position}}}j(x.width,x.height)}this.setup=function(){if(x&&x.getMedia()){n=x.getMedia().getDisplayElement()}z();k();u.jwAddEventListener(b.api.events.JWPLAYER_PLAYER_STATE,m);u.jwAddEventListener(b.api.events.JWPLAYER_MEDIA_LOADED,v);u.jwAddEventListener(b.api.events.JWPLAYER_MEDIA_META,function(){y()});var E;if(d.exists(window.onresize)){E=window.onresize}window.onresize=function(F){if(d.exists(E)){try{E(F)}catch(H){}}if(u.jwGetFullscreen()){var G=document.body.getBoundingClientRect();x.width=Math.abs(G.left)+Math.abs(G.right);x.height=window.innerHeight}j(x.width,x.height)}};function h(E){switch(E.keyCode){case 27:if(u.jwGetFullscreen()){u.jwSetFullscreen(false)}break;case 32:if(u.jwGetState()!=b.api.events.state.IDLE&&u.jwGetState()!=b.api.events.state.PAUSED){u.jwPause()}else{u.jwPlay()}break}}function j(H,E){if(w.style.display=="none"){return}var G=[].concat(x.plugins.order);G.reverse();D=G.length+2;if(!x.fullscreen){x.width=H;x.height=E;g=H;C=E;c(s,{top:0,bottom:0,left:0,right:0,width:H,height:E,position:"relative"});c(w,{height:C,width:g});var F=o(t,G);if(F.length>0){D+=F.length;var J=F.indexOf("playlist"),I=F.indexOf("controlbar");if(J>=0&&I>=0){F[J]=F.splice(I,1,F[J])[0]}o(l,F,true)}}else{if(!(navigator&&navigator.vendor&&navigator.vendor.indexOf("Apple")==0)){o(B,G,true)}}y()}function o(J,G,H){var F=[];for(var E=0;E<G.length;E++){var K=G[E];if(d.exists(x.plugins.object[K].getDisplayElement)){if(x.plugins.config[K].currentPosition!=b.html5.view.positions.NONE){var I=J(K,D--);if(!I){F.push(K)}else{x.plugins.object[K].resize(I.width,I.height);if(H){delete I.width;delete I.height}c(x.plugins.object[K].getDisplayElement(),I)}}else{c(x.plugins.object[K].getDisplayElement(),{display:"none"})}}}return F}function t(F,G){if(d.exists(x.plugins.object[F].getDisplayElement)){if(x.plugins.config[F].position&&a(x.plugins.config[F].position)){if(!d.exists(x.plugins.object[F].getDisplayElement().parentNode)){w.appendChild(x.plugins.object[F].getDisplayElement())}var E=e(F);E.zIndex=G;return E}}return false}function l(G,H){if(!d.exists(x.plugins.object[G].getDisplayElement().parentNode)){s.appendChild(x.plugins.object[G].getDisplayElement())}var E=x.width,F=x.height;if(typeof x.width=="string"&&x.width.lastIndexOf("%")>-1){percentage=parseFloat(x.width.substring(0,x.width.lastIndexOf("%")))/100;E=Math.round(window.innerWidth*percentage)}if(typeof x.height=="string"&&x.height.lastIndexOf("%")>-1){percentage=parseFloat(x.height.substring(0,x.height.lastIndexOf("%")))/100;F=Math.round(window.innerHeight*percentage)}return{position:"absolute",width:(E-d.parseDimension(s.style.left)-d.parseDimension(s.style.right)),height:(F-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom)),zIndex:H}}function B(E,F){return{position:"fixed",width:x.width,height:x.height,zIndex:F}}function y(){if(!d.exists(x.getMedia())){return}s.style.position="absolute";var H=x.getMedia().getDisplayElement();if(H&&H.tagName.toLowerCase()=="video"){H.style.position="absolute";var E,I;if(s.style.width.toString().lastIndexOf("%")>-1||s.style.width.toString().lastIndexOf("%")>-1){var F=s.getBoundingClientRect();E=Math.abs(F.left)+Math.abs(F.right);I=Math.abs(F.top)+Math.abs(F.bottom)}else{E=d.parseDimension(s.style.width);I=d.parseDimension(s.style.height)}if(H.parentNode){H.parentNode.style.left=s.style.left;H.parentNode.style.top=s.style.top}d.stretch(u.jwGetStretching(),H,E,I,H.videoWidth?H.videoWidth:400,H.videoHeight?H.videoHeight:300)}else{var G=x.plugins.object.display.getDisplayElement();if(G){x.getMedia().resize(d.parseDimension(G.style.width),d.parseDimension(G.style.height))}else{x.getMedia().resize(d.parseDimension(s.style.width),d.parseDimension(s.style.height))}}}function e(F){var G={position:"absolute",margin:0,padding:0,top:null};var E=x.plugins.config[F].currentPosition.toLowerCase();switch(E.toUpperCase()){case b.html5.view.positions.TOP:G.top=d.parseDimension(s.style.top);G.left=d.parseDimension(s.style.left);G.width=g-d.parseDimension(s.style.left)-d.parseDimension(s.style.right);G.height=x.plugins.object[F].height;s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].height+"px";s.style.height=d.parseDimension(s.style.height)-G.height+"px";break;case b.html5.view.positions.RIGHT:G.top=d.parseDimension(s.style.top);G.right=d.parseDimension(s.style.right);G.width=x.plugins.object[F].width;G.height=C-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom);s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].width+"px";s.style.width=d.parseDimension(s.style.width)-G.width+"px";break;case b.html5.view.positions.BOTTOM:G.bottom=d.parseDimension(s.style.bottom);G.left=d.parseDimension(s.style.left);G.width=g-d.parseDimension(s.style.left)-d.parseDimension(s.style.right);G.height=x.plugins.object[F].height;s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].height+"px";s.style.height=d.parseDimension(s.style.height)-G.height+"px";break;case b.html5.view.positions.LEFT:G.top=d.parseDimension(s.style.top);G.left=d.parseDimension(s.style.left);G.width=x.plugins.object[F].width;G.height=C-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom);s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].width+"px";s.style.width=d.parseDimension(s.style.width)-G.width+"px";break;default:break}return G}this.resize=j;this.fullscreen=function(H){if(navigator&&navigator.vendor&&navigator.vendor.indexOf("Apple")===0){if(x.getMedia().getDisplayElement().webkitSupportsFullscreen){if(H){try{x.getMedia().getDisplayElement().webkitEnterFullscreen()}catch(G){}}else{try{x.getMedia().getDisplayElement().webkitExitFullscreen()}catch(G){}}}}else{if(H){document.onkeydown=h;clearInterval(p);var F=document.body.getBoundingClientRect();x.width=Math.abs(F.left)+Math.abs(F.right);x.height=window.innerHeight;var E={position:"fixed",width:"100%",height:"100%",top:0,left:0,zIndex:2147483000};c(w,E);E.zIndex=1;if(x.getMedia()&&x.getMedia().getDisplayElement()){c(x.getMedia().getDisplayElement(),E)}E.zIndex=2;c(s,E)}else{document.onkeydown="";x.width=g;x.height=C;c(w,{position:"relative",height:x.height,width:x.width,zIndex:0})}j(x.width,x.height)}}};function a(e){return([b.html5.view.positions.TOP,b.html5.view.positions.RIGHT,b.html5.view.positions.BOTTOM,b.html5.view.positions.LEFT].toString().indexOf(e.toUpperCase())>-1)}b.html5.view.positions={TOP:"TOP",RIGHT:"RIGHT",BOTTOM:"BOTTOM",LEFT:"LEFT",OVER:"OVER",NONE:"NONE"}})(jwplayer);(function(a){var b={backgroundcolor:"",margin:10,font:"Arial,sans-serif",fontsize:10,fontcolor:parseInt("000000",16),fontstyle:"normal",fontweight:"bold",buttoncolor:parseInt("ffffff",16),position:a.html5.view.positions.BOTTOM,idlehide:false,layout:{left:{position:"left",elements:[{name:"play",type:"button"},{name:"divider",type:"divider"},{name:"prev",type:"button"},{name:"divider",type:"divider"},{name:"next",type:"button"},{name:"divider",type:"divider"},{name:"elapsed",type:"text"}]},center:{position:"center",elements:[{name:"time",type:"slider"}]},right:{position:"right",elements:[{name:"duration",type:"text"},{name:"blank",type:"button"},{name:"divider",type:"divider"},{name:"mute",type:"button"},{name:"volume",type:"slider"},{name:"divider",type:"divider"},{name:"fullscreen",type:"button"}]}}};_utils=a.utils;_css=_utils.css;_hide=function(c){_css(c,{display:"none"})};_show=function(c){_css(c,{display:"block"})};a.html5.controlbar=function(l,V){var k=l;var D=_utils.extend({},b,k.skin.getComponentSettings("controlbar"),V);if(D.position==a.html5.view.positions.NONE||typeof a.html5.view.positions[D.position]=="undefined"){return}if(_utils.mapLength(k.skin.getComponentLayout("controlbar"))>0){D.layout=k.skin.getComponentLayout("controlbar")}var ac;var P;var ab;var E;var v="none";var g;var j;var ad;var f;var e;var y;var Q={};var p=false;var c={};var Y;var h=false;var o;var d;var S=false;var G=false;var W=new a.html5.eventdispatcher();_utils.extend(this,W);function J(){if(!Y){Y=k.skin.getSkinElement("controlbar","background");if(!Y){Y={width:0,height:0,src:null}}}return Y}function N(){ab=0;E=0;P=0;if(!p){var ak={height:J().height,backgroundColor:D.backgroundcolor};ac=document.createElement("div");ac.id=k.id+"_jwplayer_controlbar";_css(ac,ak)}var aj=(k.skin.getSkinElement("controlbar","capLeft"));var ai=(k.skin.getSkinElement("controlbar","capRight"));if(aj){x("capLeft","left",false,ac)}var al={position:"absolute",height:J().height,left:(aj?aj.width:0),zIndex:0};Z("background",ac,al,"img");if(J().src){Q.background.src=J().src}al.zIndex=1;Z("elements",ac,al);if(ai){x("capRight","right",false,ac)}}this.getDisplayElement=function(){return ac};this.resize=function(ak,ai){_utils.cancelAnimation(ac);document.getElementById(k.id).onmousemove=A;e=ak;y=ai;if(G!=k.jwGetFullscreen()){G=k.jwGetFullscreen();d=undefined}var aj=w();A();I({id:k.id,duration:ad,position:j});u({id:k.id,bufferPercent:f});return aj};this.show=function(){if(h){h=false;_show(ac);T()}};this.hide=function(){if(!h){h=true;_hide(ac);aa()}};function q(){var aj=["timeSlider","volumeSlider","timeSliderRail","volumeSliderRail"];for(var ak in aj){var ai=aj[ak];if(typeof Q[ai]!="undefined"){c[ai]=Q[ai].getBoundingClientRect()}}}function A(ai){if(h){return}if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){clearTimeout(o);switch(k.jwGetState()){case a.api.events.state.PAUSED:case a.api.events.state.IDLE:if(!D.idlehide||_utils.exists(ai)){U()}if(D.idlehide){o=setTimeout(function(){z()},2000)}break;default:if(ai){U()}o=setTimeout(function(){z()},2000);break}}}function z(ai){aa();_utils.cancelAnimation(ac);_utils.fadeTo(ac,0,0.1,1,0)}function U(){T();_utils.cancelAnimation(ac);_utils.fadeTo(ac,1,0,1,0)}function H(ai){return function(){if(S&&d!=ai){d=ai;W.sendEvent(ai,{component:"controlbar",boundingRect:O()})}}}var T=H(a.api.events.JWPLAYER_COMPONENT_SHOW);var aa=H(a.api.events.JWPLAYER_COMPONENT_HIDE);function O(){if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){return _utils.getDimensions(ac)}else{return{x:0,y:0,width:0,height:0}}}function Z(am,al,ak,ai){var aj;if(!p){if(!ai){ai="div"}aj=document.createElement(ai);Q[am]=aj;aj.id=ac.id+"_"+am;al.appendChild(aj)}else{aj=document.getElementById(ac.id+"_"+am)}if(_utils.exists(ak)){_css(aj,ak)}return aj}function M(){ah(D.layout.left);ah(D.layout.right,-1);ah(D.layout.center)}function ah(al,ai){var am=al.position=="right"?"right":"left";var ak=_utils.extend([],al.elements);if(_utils.exists(ai)){ak.reverse()}for(var aj=0;aj<ak.length;aj++){C(ak[aj],am)}}function K(){return P++}function C(am,ao){var al,aj,ak,ai,aq;if(am.type=="divider"){x("divider"+K(),ao,true,undefined,undefined,am.width,am.element);return}switch(am.name){case"play":x("playButton",ao,false);x("pauseButton",ao,true);R("playButton","jwPlay");R("pauseButton","jwPause");break;case"prev":x("prevButton",ao,true);R("prevButton","jwPlaylistPrev");break;case"stop":x("stopButton",ao,true);R("stopButton","jwStop");break;case"next":x("nextButton",ao,true);R("nextButton","jwPlaylistNext");break;case"elapsed":x("elapsedText",ao,true);break;case"time":aj=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","timeSliderCapLeft").width;ak=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapRight"))?0:k.skin.getSkinElement("controlbar","timeSliderCapRight").width;al=ao=="left"?aj:ak;ai=k.skin.getSkinElement("controlbar","timeSliderRail").width+aj+ak;aq={height:J().height,position:"absolute",top:0,width:ai};aq[ao]=ao=="left"?ab:E;var an=Z("timeSlider",Q.elements,aq);x("timeSliderCapLeft",ao,true,an,ao=="left"?0:al);x("timeSliderRail",ao,false,an,al);x("timeSliderBuffer",ao,false,an,al);x("timeSliderProgress",ao,false,an,al);x("timeSliderThumb",ao,false,an,al);x("timeSliderCapRight",ao,true,an,ao=="right"?0:al);X("time");break;case"fullscreen":x("fullscreenButton",ao,false);x("normalscreenButton",ao,true);R("fullscreenButton","jwSetFullscreen",true);R("normalscreenButton","jwSetFullscreen",false);break;case"volume":aj=!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","volumeSliderCapLeft").width;ak=!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapRight"))?0:k.skin.getSkinElement("controlbar","volumeSliderCapRight").width;al=ao=="left"?aj:ak;ai=k.skin.getSkinElement("controlbar","volumeSliderRail").width+aj+ak;aq={height:J().height,position:"absolute",top:0,width:ai};aq[ao]=ao=="left"?ab:E;var ap=Z("volumeSlider",Q.elements,aq);x("volumeSliderCapLeft",ao,true,ap,ao=="left"?0:al);x("volumeSliderRail",ao,true,ap,al);x("volumeSliderProgress",ao,false,ap,al);x("volumeSliderCapRight",ao,true,ap,ao=="right"?0:al);X("volume");break;case"mute":x("muteButton",ao,false);x("unmuteButton",ao,true);R("muteButton","jwSetMute",true);R("unmuteButton","jwSetMute",false);break;case"duration":x("durationText",ao,true);break}}function x(al,ao,aj,ar,am,ai,ak){if(_utils.exists(k.skin.getSkinElement("controlbar",al))||al.indexOf("Text")>0||al.indexOf("divider")===0){var an={height:J().height,position:"absolute",display:"block",top:0};if((al.indexOf("next")===0||al.indexOf("prev")===0)&&k.jwGetPlaylist().length<2){aj=false;an.display="none"}var at;if(al.indexOf("Text")>0){al.innerhtml="00:00";an.font=D.fontsize+"px/"+(J().height+1)+"px "+D.font;an.color=D.fontcolor;an.textAlign="center";an.fontWeight=D.fontweight;an.fontStyle=D.fontstyle;an.cursor="default";at=14+3*D.fontsize}else{if(al.indexOf("divider")===0){if(ai){if(!isNaN(parseInt(ai))){at=parseInt(ai)}}else{if(ak){var ap=k.skin.getSkinElement("controlbar",ak);if(ap){an.background="url("+ap.src+") repeat-x center left";at=ap.width}}else{an.background="url("+k.skin.getSkinElement("controlbar","divider").src+") repeat-x center left";at=k.skin.getSkinElement("controlbar","divider").width}}}else{an.background="url("+k.skin.getSkinElement("controlbar",al).src+") repeat-x center left";at=k.skin.getSkinElement("controlbar",al).width}}if(ao=="left"){an.left=isNaN(am)?ab:am;if(aj){ab+=at}}else{if(ao=="right"){an.right=isNaN(am)?E:am;if(aj){E+=at}}}if(_utils.typeOf(ar)=="undefined"){ar=Q.elements}an.width=at;if(p){_css(Q[al],an)}else{var aq=Z(al,ar,an);if(_utils.exists(k.skin.getSkinElement("controlbar",al+"Over"))){aq.onmouseover=function(au){aq.style.backgroundImage=["url(",k.skin.getSkinElement("controlbar",al+"Over").src,")"].join("")};aq.onmouseout=function(au){aq.style.backgroundImage=["url(",k.skin.getSkinElement("controlbar",al).src,")"].join("")}}}}}function F(){k.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,B);k.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,s);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_BUFFER,u);k.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,r);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_TIME,I);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_MUTE,ag);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_VOLUME,m);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_COMPLETE,L)}function B(){N();M();w();ae()}function s(ai){ad=k.jwGetPlaylist()[ai.index].duration;I({id:k.id,duration:ad,position:0});u({id:k.id,bufferProgress:0})}function ae(){I({id:k.id,duration:k.jwGetDuration(),position:0});u({id:k.id,bufferProgress:0});ag({id:k.id,mute:k.jwGetMute()});r({id:k.id,newstate:a.api.events.state.IDLE});m({id:k.id,volume:k.jwGetVolume()})}function R(ak,al,aj){if(p){return}if(_utils.exists(k.skin.getSkinElement("controlbar",ak))){var ai=Q[ak];if(_utils.exists(ai)){_css(ai,{cursor:"pointer"});if(al=="fullscreen"){ai.onmouseup=function(am){am.stopPropagation();k.jwSetFullscreen(!k.jwGetFullscreen())}}else{ai.onmouseup=function(am){am.stopPropagation();if(_utils.exists(aj)){k[al](aj)}else{k[al]()}}}}}}function X(ai){if(p){return}var aj=Q[ai+"Slider"];_css(Q.elements,{cursor:"pointer"});_css(aj,{cursor:"pointer"});aj.onmousedown=function(ak){v=ai};aj.onmouseup=function(ak){ak.stopPropagation();af(ak.pageX)};aj.onmousemove=function(ak){if(v=="time"){g=true;var al=ak.pageX-c[ai+"Slider"].left-window.pageXOffset;_css(Q.timeSliderThumb,{left:al})}}}function af(aj){g=false;var ai;if(v=="time"){ai=aj-c.timeSliderRail.left+window.pageXOffset;var al=ai/c.timeSliderRail.width*ad;if(al<0){al=0}else{if(al>ad){al=ad-3}}if(k.jwGetState()==a.api.events.state.PAUSED||k.jwGetState()==a.api.events.state.IDLE){k.jwPlay()}k.jwSeek(al)}else{if(v=="volume"){ai=aj-c.volumeSliderRail.left-window.pageXOffset;var ak=Math.round(ai/c.volumeSliderRail.width*100);if(ak<0){ak=0}else{if(ak>100){ak=100}}if(k.jwGetMute()){k.jwSetMute(false)}k.jwSetVolume(ak)}}v="none"}function u(aj){if(_utils.exists(aj.bufferPercent)){f=aj.bufferPercent}if(c.timeSliderRail){var ak=c.timeSliderRail.width;var ai=isNaN(Math.round(ak*f/100))?0:Math.round(ak*f/100);_css(Q.timeSliderBuffer,{width:ai})}}function ag(ai){if(ai.mute){_hide(Q.muteButton);_show(Q.unmuteButton);_hide(Q.volumeSliderProgress)}else{_show(Q.muteButton);_hide(Q.unmuteButton);_show(Q.volumeSliderProgress)}}function r(ai){if(ai.newstate==a.api.events.state.BUFFERING||ai.newstate==a.api.events.state.PLAYING){_show(Q.pauseButton);_hide(Q.playButton)}else{_hide(Q.pauseButton);_show(Q.playButton)}A();if(ai.newstate==a.api.events.state.IDLE){_hide(Q.timeSliderBuffer);_hide(Q.timeSliderProgress);_hide(Q.timeSliderThumb);I({id:k.id,duration:k.jwGetDuration(),position:0})}else{_show(Q.timeSliderBuffer);if(ai.newstate!=a.api.events.state.BUFFERING){_show(Q.timeSliderProgress);_show(Q.timeSliderThumb)}}}function L(ai){u({bufferPercent:0});I(_utils.extend(ai,{position:0,duration:ad}))}function I(al){if(_utils.exists(al.position)){j=al.position}if(_utils.exists(al.duration)){ad=al.duration}var aj=(j===ad===0)?0:j/ad;var am=c.timeSliderRail;if(am){var ai=isNaN(Math.round(am.width*aj))?0:Math.round(am.width*aj);var ak=ai;if(Q.timeSliderProgress){Q.timeSliderProgress.style.width=ai+"px";if(!g){if(Q.timeSliderThumb){Q.timeSliderThumb.style.left=ak+"px"}}}}if(Q.durationText){Q.durationText.innerHTML=_utils.timeFormat(ad)}if(Q.elapsedText){Q.elapsedText.innerHTML=_utils.timeFormat(j)}}function n(){var am,aj;var ak=document.getElementById(ac.id+"_elements");if(!ak){return}var al=ak.childNodes;for(var ai in ak.childNodes){if(isNaN(parseInt(ai,10))){continue}if(al[ai].id.indexOf(ac.id+"_divider")===0&&aj&&aj.id.indexOf(ac.id+"_divider")===0&&al[ai].style.backgroundImage==aj.style.backgroundImage){al[ai].style.display="none"}else{if(al[ai].id.indexOf(ac.id+"_divider")===0&&am&&am.style.display!="none"){al[ai].style.display="block"}}if(al[ai].style.display!="none"){aj=al[ai]}am=al[ai]}}function w(){n();if(k.jwGetFullscreen()){_show(Q.normalscreenButton);_hide(Q.fullscreenButton)}else{_hide(Q.normalscreenButton);_show(Q.fullscreenButton)}var aj={width:e};var ai={};if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){aj.left=D.margin;aj.width-=2*D.margin;aj.top=y-J().height-D.margin;aj.height=J().height}var al=k.skin.getSkinElement("controlbar","capLeft");var ak=k.skin.getSkinElement("controlbar","capRight");ai.left=al?al.width:0;ai.width=aj.width-ai.left-(ak?ak.width:0);var am=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","timeSliderCapLeft").width;_css(Q.timeSliderRail,{width:(ai.width-ab-E),left:am});if(_utils.exists(Q.timeSliderCapRight)){_css(Q.timeSliderCapRight,{left:am+(ai.width-ab-E)})}_css(ac,aj);_css(Q.elements,ai);_css(Q.background,ai);q();return aj}function m(am){if(_utils.exists(Q.volumeSliderRail)){var ak=isNaN(am.volume/100)?1:am.volume/100;var al=_utils.parseDimension(Q.volumeSliderRail.style.width);var ai=isNaN(Math.round(al*ak))?0:Math.round(al*ak);var an=_utils.parseDimension(Q.volumeSliderRail.style.right);var aj=(!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapLeft")))?0:k.skin.getSkinElement("controlbar","volumeSliderCapLeft").width;_css(Q.volumeSliderProgress,{width:ai,left:aj});if(_utils.exists(Q.volumeSliderCapLeft)){_css(Q.volumeSliderCapLeft,{left:0})}}}function t(){N();M();q();p=true;F();D.idlehide=(D.idlehide.toString().toLowerCase()=="true");if(D.position==a.html5.view.positions.OVER&&D.idlehide){ac.style.opacity=0;S=true}else{setTimeout((function(){S=true;T()}),1)}ae()}t();return this}})(jwplayer);(function(b){var a=["width","height","state","playlist","item","position","buffer","duration","volume","mute","fullscreen"];var c=b.utils;b.html5.controller=function(z,w,h,v){var C=z;var G=h;var g=v;var o=w;var J=true;var e=-1;var A=c.exists(G.config.debug)&&(G.config.debug.toString().toLowerCase()=="console");var m=new b.html5.eventdispatcher(o.id,A);c.extend(this,m);var E=[];var d=false;function r(M){if(d){m.sendEvent(M.type,M)}else{E.push(M)}}function K(M){if(!d){m.sendEvent(b.api.events.JWPLAYER_READY,M);if(b.utils.exists(window.playerReady)){playerReady(M)}if(b.utils.exists(window[h.config.playerReady])){window[h.config.playerReady](M)}while(E.length>0){var O=E.shift();m.sendEvent(O.type,O)}if(h.config.autostart&&!b.utils.isIOS()){t(G.item)}while(p.length>0){var N=p.shift();x(N.method,N.arguments)}d=true}}G.addGlobalListener(r);G.addEventListener(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL,function(){G.getMedia().play()});G.addEventListener(b.api.events.JWPLAYER_MEDIA_TIME,function(M){if(M.position>=G.playlist[G.item].start&&e>=0){G.playlist[G.item].start=e;e=-1}});G.addEventListener(b.api.events.JWPLAYER_MEDIA_COMPLETE,function(M){setTimeout(s,25)});function u(){try{f(G.item);if(G.playlist[G.item].levels[0].file.length>0){if(J||G.state==b.api.events.state.IDLE){G.getMedia().load(G.playlist[G.item]);J=false}else{if(G.state==b.api.events.state.PAUSED){G.getMedia().play()}}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function I(){try{if(G.playlist[G.item].levels[0].file.length>0){switch(G.state){case b.api.events.state.PLAYING:case b.api.events.state.BUFFERING:G.getMedia().pause();break}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function D(M){try{if(G.playlist[G.item].levels[0].file.length>0){if(typeof M!="number"){M=parseFloat(M)}switch(G.state){case b.api.events.state.IDLE:if(e<0){e=G.playlist[G.item].start;G.playlist[G.item].start=M}u();break;case b.api.events.state.PLAYING:case b.api.events.state.PAUSED:case b.api.events.state.BUFFERING:G.seek(M);break}}return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}function n(M){if(!c.exists(M)){M=true}try{G.getMedia().stop(M);return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}function k(){try{if(G.playlist[G.item].levels[0].file.length>0){if(G.config.shuffle){f(y())}else{if(G.item+1==G.playlist.length){f(0)}else{f(G.item+1)}}}if(G.state!=b.api.events.state.IDLE){var N=G.state;G.state=b.api.events.state.IDLE;m.sendEvent(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:N,newstate:b.api.events.state.IDLE})}u();return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function j(){try{if(G.playlist[G.item].levels[0].file.length>0){if(G.config.shuffle){f(y())}else{if(G.item===0){f(G.playlist.length-1)}else{f(G.item-1)}}}if(G.state!=b.api.events.state.IDLE){var N=G.state;G.state=b.api.events.state.IDLE;m.sendEvent(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:N,newstate:b.api.events.state.IDLE})}u();return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function y(){var M=null;if(G.playlist.length>1){while(!c.exists(M)){M=Math.floor(Math.random()*G.playlist.length);if(M==G.item){M=null}}}else{M=0}return M}function t(N){if(!G.playlist||!G.playlist[N]){return false}try{if(G.playlist[N].levels[0].file.length>0){var O=G.state;if(O!==b.api.events.state.IDLE){if(G.playlist[G.item].provider==G.playlist[N].provider){n(false)}else{n()}}f(N);u()}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function f(M){if(!G.playlist[M]){return}G.setActiveMediaProvider(G.playlist[M]);if(G.item!=M){G.item=M;J=true;m.sendEvent(b.api.events.JWPLAYER_PLAYLIST_ITEM,{index:M})}}function H(N){try{f(G.item);var O=G.getMedia();switch(typeof(N)){case"number":O.volume(N);break;case"string":O.volume(parseInt(N,10));break}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function q(N){try{f(G.item);var O=G.getMedia();if(typeof N=="undefined"){O.mute(!G.mute)}else{if(N.toString().toLowerCase()=="true"){O.mute(true)}else{O.mute(false)}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function l(N,M){try{G.width=N;G.height=M;g.resize(N,M);m.sendEvent(b.api.events.JWPLAYER_RESIZE,{width:G.width,height:G.height});return true}catch(O){m.sendEvent(b.api.events.JWPLAYER_ERROR,O)}return false}function B(N){try{if(typeof N=="undefined"){G.fullscreen=!G.fullscreen;g.fullscreen(!G.fullscreen)}else{if(N.toString().toLowerCase()=="true"){G.fullscreen=true;g.fullscreen(true)}else{G.fullscreen=false;g.fullscreen(false)}}m.sendEvent(b.api.events.JWPLAYER_RESIZE,{width:G.width,height:G.height});m.sendEvent(b.api.events.JWPLAYER_FULLSCREEN,{fullscreen:N});return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function L(M){try{n();G.loadPlaylist(M);f(G.item);return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}b.html5.controller.repeatoptions={LIST:"LIST",ALWAYS:"ALWAYS",SINGLE:"SINGLE",NONE:"NONE"};function s(){switch(G.config.repeat.toUpperCase()){case b.html5.controller.repeatoptions.SINGLE:u();break;case b.html5.controller.repeatoptions.ALWAYS:if(G.item==G.playlist.length-1&&!G.config.shuffle){t(0)}else{k()}break;case b.html5.controller.repeatoptions.LIST:if(G.item==G.playlist.length-1&&!G.config.shuffle){n();f(0)}else{k()}break;default:n();break}}var p=[];function F(M){return function(){if(d){x(M,arguments)}else{p.push({method:M,arguments:arguments})}}}function x(O,N){var M=[];for(i=0;i<N.length;i++){M.push(N[i])}O.apply(this,M)}this.play=F(u);this.pause=F(I);this.seek=F(D);this.stop=F(n);this.next=F(k);this.prev=F(j);this.item=F(t);this.setVolume=F(H);this.setMute=F(q);this.resize=F(l);this.setFullscreen=F(B);this.load=F(L);this.playerReady=K}})(jwplayer);(function(a){a.html5.defaultSkin=function(){this.text='<?xml version="1.0" ?><skin author="LongTail Video" name="Five" version="1.0"><settings><setting name="backcolor" value="0xFFFFFF"/><setting name="frontcolor" value="0x000000"/><setting name="lightcolor" value="0x000000"/><setting name="screencolor" value="0x000000"/></settings><components><component name="controlbar"><settings><setting name="margin" value="20"/><setting name="fontsize" value="11"/></settings><elements><element name="background" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFJJREFUeNrslLENwAAIwxLU/09j5AiOgD5hVQzNAVY8JK4qEfHMIKBnd2+BQlBINaiRtL/aV2rdzYBsM6CIONbI1NZENTr3RwdB2PlnJgJ6BRgA4hwu5Qg5iswAAAAASUVORK5CYII="/><element name="capLeft" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="capRight" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="divider" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="playButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEhJREFUeNpiYqABYBo1dNRQ+hr6H4jvA3E8NS39j4SpZvh/LJig4YxEGEqy3kET+w+AOGFQRhTJhrEQkGcczfujhg4CQwECDADpTRWU/B3wHQAAAABJRU5ErkJggg=="/><element name="pauseButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAChJREFUeNpiYBgFo2DwA0YC8v/R1P4nRu+ooaOGUtnQUTAKhgIACDAAFCwQCfAJ4gwAAAAASUVORK5CYII="/><element name="prevButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEtJREFUeNpiYBgFo2Dog/9QDAPyQHweTYwiQ/2B+D0Wi8g2tB+JTdBQRiIMJVkvEy0iglhDF9Aq9uOpHVEwoE+NJDUKRsFgAAABBgDe2hqZcNNL0AAAAABJRU5ErkJggg=="/><element name="nextButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAElJREFUeNpiYBgFo2Dog/9AfB6I5dHE/lNqKAi/B2J/ahsKw/3EGMpIhKEk66WJoaR6fz61IyqemhEFSlL61ExSo2AUDAYAEGAAiG4hj+5t7M8AAAAASUVORK5CYII="/><element name="timeSliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADxJREFUeNpiYBgFo2AU0Bwwzluw+D8tLWARFhKiqQ9YuLg4aWsBGxs7bS1gZ6e5BWyjSX0UjIKhDgACDABlYQOGh5pYywAAAABJRU5ErkJggg=="/><element name="timeSliderBuffer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYBgFo2AU0Bww1jc0/aelBSz8/Pw09QELOzs7bS1gY2OjrQWsrKy09gHraFIfBaNgqAOAAAMAvy0DChXHsZMAAAAASUVORK5CYII="/><element name="timeSliderProgress" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAClJREFUeNpiYBgFo2AU0BwwAvF/WlrARGsfjFow8BaMglEwCugAAAIMAOHfAQunR+XzAAAAAElFTkSuQmCC"/><element name="timeSliderThumb" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAICAYAAAA870V8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABZJREFUeNpiZICA/yCCiQEJUJcDEGAAY0gBD1/m7Q0AAAAASUVORK5CYII="/><element name="muteButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAYCAYAAADKx8xXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiYBgFIw3MB+L/5Gj8j6yRiRTFyICJXHfTXyMLAXlGati4YDRFDj8AEGAABk8GSqqS4CoAAAAASUVORK5CYII="/><element name="unmuteButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAYCAYAAADKx8xXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYBgFgxz8p7bm+cQa+h8LHy7GhEcjIz4bmAjYykiun/8j0fakGPIfTfPgiSr6aB4FVAcAAQYAWdwR1G1Wd2gAAAAASUVORK5CYII="/><element name="volumeSliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAYCAYAAADkgu3FAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGpJREFUeNpi/P//PwM9ABMDncCoRYPfIqqDZcuW1UPp/6AUDcNM1DQYKtRAlaAj1mCSLSLXYIIWUctgDItoZfDA5aOoqKhGEANIM9LVR7SymGDQUctikuOIXkFNdhHEOFrDjlpEd4sAAgwAriRMub95fu8AAAAASUVORK5CYII="/><element name="volumeSliderProgress" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAYCAYAAADkgu3FAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFtJREFUeNpi/P//PwM9ABMDncCoRYPfIlqAeij9H5SiYZiqBqPTlFqE02BKLSLaYFItIttgQhZRzWB8FjENiuRJ7aAbsMQwYMl7wDIsWUUQ42gNO2oR3S0CCDAAKhKq6MLLn8oAAAAASUVORK5CYII="/><element name="fullscreenButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAE5JREFUeNpiYBgFo2DQA0YC8v/xqP1PjDlMRDrEgUgxkgHIlfZoriVGjmzLsLFHAW2D6D8eA/9Tw7L/BAwgJE90PvhPpNgoGAVDEQAEGAAMdhTyXcPKcAAAAABJRU5ErkJggg=="/><element name="normalscreenButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEZJREFUeNpiYBgFo2DIg/9UUkOUAf8JiFFsyX88fJyAkcQgYMQjNkzBoAgiezyRbE+tFGSPxQJ7auYBmma0UTAKBhgABBgAJAEY6zON61sAAAAASUVORK5CYII="/></elements></component><component name="display"><elements><element name="background" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNrszwENADAIA7DhX8ENoBMZ5KR10EryckCJiIiIiIiIiIiIiIiIiIiIiIh8GmkRERERERERERERERERERERERGRHSPAAPlXH1phYpYaAAAAAElFTkSuQmCC"/><element name="playIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALdJREFUeNrs18ENgjAYhmFouDOCcQJGcARHgE10BDcgTOIosAGwQOuPwaQeuFRi2p/3Sb6EC5L3QCxZBgAAAOCorLW1zMn65TrlkH4NcV7QNcUQt7Gn7KIhxA+qNIR81spOGkL8oFJDyLJRdosqKDDkK+iX5+d7huzwM40xptMQMkjIOeRGo+VkEVvIPfTGIpKASfYIfT9iCHkHrBEzf4gcUQ56aEzuGK/mw0rHpy4AAACAf3kJMACBxjAQNRckhwAAAABJRU5ErkJggg=="/><element name="muteIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNrs1jEOgCAMBVAg7t5/8qaoIy4uoobyXsLCxA+0NCUAAADGUWvdQoQ41x4ixNBB2hBvBskdD3w5ZCkl3+33VqI0kjBBlh9rp+uTcyOP33TnolfsU85XX3yIRpQph8ZQY3wTZtU5AACASA4BBgDHoVuY1/fvOQAAAABJRU5ErkJggg=="/><element name="errorIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWlJREFUeNrsl+1twjAQhsHq/7BBYQLYIBmBDcoGMAIjtBPQTcII2SDtBDBBwrU6pGsUO7YbO470PtKJkz9iH++d4ywWAAAAAABgljRNsyWr2bZzDuJG1rLdZhcMbTjrBCGDyUKsqQLFciJb9bSvuG/WagRVRUVUI6gqy5HVeKWfSgRyJruKIU//TrZTSn2nmlaXThrloi/v9F2STC1W4+Aw5cBzkquRc09bofFNc6YLxEON0VUZS5FPTftO49vMjRsIF3RhOGr7/D/pJw+FKU+q0vDyq8W42jCunDqI3LC5XxNj2wHLU1XjaRnb0Lhykhqhhd8MtSF5J9tbjCv4mXGvKJz/65FF/qJryyaaIvzP2QRxZTX2nTuXjvV/VPFSwyLnW7mpH99yTh1FEVro6JBSd40/pMrRdV8vPtcKl28T2pT8TnFZ4yNosct3Q0io6JfBiz1FlGdqVQH3VHnepAEAAAAAADDzEGAAcTwB10jWgxcAAAAASUVORK5CYII="/><element name="bufferIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAuhJREFUeNrsWr9rU1EUznuNGqvFQh1ULOhiBx0KDtIuioO4pJuik3FxFfUPaAV1FTdx0Q5d2g4FFxehTnEpZHFoBy20tCIWtGq0TZP4HfkeHB5N8m6Sl/sa74XDybvv3vvOd8/Pe4lXrVZT3dD8VJc0B8QBcUAcEAfESktHGeR5XtMfqFQq/f92zPe/NbtGlKTdCY30kuxrpMGO94BlQCXs+rbh3ONgA6BlzP1p20d80gEI5hmA2A92Qua1Q2PtAFISM+bvjMG8U+Q7oA3rQGASwrYCU6WpNdLGYbA+Pq5jjXIiwi8EEa2UDbQSaKOIuV+SlkcCrfjY8XTI9EpKGwP0C2kru2hLtHqa4zoXtZRWyvi4CLwv9Opr6Hkn6A9HKgEANsQ1iqC3Ub/vRUk2JgmRkatK36kVrnt0qObunwUdUUMXMWYpakJsO5Am8tAw2GBIgwWA+G2S2dMpiw0gDioQRQJoKhRb1QiDwlHZUABYbaXWsm5ae6loTE4ZDxN4CZar8foVzOJ2iyZ2kWF3t7YIevffaMT5yJ70kQb2fQ1sE5SHr2wazs2wgMxgbsEKEAgxAvZUJbQLBGTSBMgNrncJbA6AljtS/eKDJ0Ez+DmrQEzXS2h1Ck25kAg0IZcUOaydCy4sYnN2fOA+2AP16gNoHALlQ+fwH7XO4CxLenUpgj4xr6ugY2roPMbMx+Xs18m/E8CVEIhxsNeg83XWOAN6grG3lGbk8uE5fr4B/WH3cJw+co/l9nTYsSGYCJ/lY5/qv0thn6nrIWmjeJcPSnWOeY++AkF8tpJHIMAUs/MaBBpj3znZfQo5psY+ZrG4gv5HickjEOymKjEeRpgyST6IuZcTcWbnjcgdPi5ghxciRKsl1lDSsgwA1i8fssonJgzmTSqfGUkCENndNdAL7PS6QQ7ZYISTo+1qq0LEWjTWcvY4isa4z+yfQB+7ooyHVg5RI7/i1Ijn/vnggDggDogD4oC00P4KMACd/juEHOrS4AAAAABJRU5ErkJggg=="/></elements></component><component name="dock"><elements><element name="button" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFBJREFUeNrs0cEJACAQA8Eofu0fu/W6EM5ZSAFDRpKTBs00CQQEBAQEBAQEBAQEBAQEBATkK8iqbY+AgICAgICAgICAgICAgICAgIC86QowAG5PAQzEJ0lKAAAAAElFTkSuQmCC"/></elements></component><component name="playlist"><elements><element name="item" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAIAAAC1nk4lAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHhJREFUeNrs2NEJwCAMBcBYuv/CFuIE9VN47WWCR7iocXR3pdWdGPqqwIoMjYfQeAiNh9B4JHc6MHQVHnjggQceeOCBBx77TifyeOY0iHi8DqIdEY8dD5cL094eePzINB5CO/LwcOTptNB4CP25L4TIbZzpU7UEGAA5wz1uF5rF9AAAAABJRU5ErkJggg=="/><element name="sliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAA8CAIAAADpFA0BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADhJREFUeNrsy6ENACAMAMHClp2wYxZLAg5Fcu9e3OjuOKqqfTMzbs14CIZhGIZhGIZhGP4VLwEGAK/BBnVFpB0oAAAAAElFTkSuQmCC"/><element name="sliderThumb" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAA8CAIAAADpFA0BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrsy7ENACAMBLE8++8caFFKKiRffU53112SGs3ttOohGIZhGIZhGIZh+Fe8BRgAiaUGde6NOSEAAAAASUVORK5CYII="/></elements></component></components></skin>';this.xml=null;if(window.DOMParser){parser=new DOMParser();this.xml=parser.parseFromString(this.text,"text/xml")}else{this.xml=new ActiveXObject("Microsoft.XMLDOM");this.xml.async="false";this.xml.loadXML(this.text)}return this}})(jwplayer);(function(a){_utils=a.utils;_css=_utils.css;_hide=function(b){_css(b,{display:"none"})};_show=function(b){_css(b,{display:"block"})};a.html5.display=function(k,G){var j={icons:true,showmute:false};var Q=_utils.extend({},j,G);var h=k;var P={};var e;var u;var w;var N;var s;var I;var A;var J=!_utils.exists(h.skin.getComponentSettings("display").bufferrotation)?15:parseInt(h.skin.getComponentSettings("display").bufferrotation,10);var q=!_utils.exists(h.skin.getComponentSettings("display").bufferinterval)?100:parseInt(h.skin.getComponentSettings("display").bufferinterval,10);var z=-1;var t="";var K=true;var d;var g=false;var n=false;var H=new a.html5.eventdispatcher();_utils.extend(this,H);var D={display:{style:{cursor:"pointer",top:0,left:0,overflow:"hidden"},click:m},display_icon:{style:{cursor:"pointer",position:"absolute",top:((h.skin.getSkinElement("display","background").height-h.skin.getSkinElement("display","playIcon").height)/2),left:((h.skin.getSkinElement("display","background").width-h.skin.getSkinElement("display","playIcon").width)/2),border:0,margin:0,padding:0,zIndex:3,display:"none"}},display_iconBackground:{style:{cursor:"pointer",position:"absolute",top:((u-h.skin.getSkinElement("display","background").height)/2),left:((e-h.skin.getSkinElement("display","background").width)/2),border:0,backgroundImage:(["url(",h.skin.getSkinElement("display","background").src,")"]).join(""),width:h.skin.getSkinElement("display","background").width,height:h.skin.getSkinElement("display","background").height,margin:0,padding:0,zIndex:2,display:"none"}},display_image:{style:{display:"none",width:e,height:u,position:"absolute",cursor:"pointer",left:0,top:0,margin:0,padding:0,textDecoration:"none",zIndex:1}},display_text:{style:{zIndex:4,position:"relative",opacity:0.8,backgroundColor:parseInt("000000",16),color:parseInt("ffffff",16),textAlign:"center",fontFamily:"Arial,sans-serif",padding:"0 5px",fontSize:14}}};h.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,p);h.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_MUTE,p);h.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,p);h.jwAddEventListener(a.api.events.JWPLAYER_ERROR,o);L();function L(){P.display=C("div","display");P.display_text=C("div","display_text");P.display.appendChild(P.display_text);P.display_image=C("img","display_image");P.display_image.onerror=function(R){_hide(P.display_image)};P.display_image.onload=y;P.display_icon=C("div","display_icon");P.display_iconBackground=C("div","display_iconBackground");P.display.appendChild(P.display_image);P.display_iconBackground.appendChild(P.display_icon);P.display.appendChild(P.display_iconBackground);f();setTimeout((function(){n=true;if(Q.icons.toString()=="true"){F()}}),1)}this.getDisplayElement=function(){return P.display};this.resize=function(S,R){_css(P.display,{width:S,height:R});_css(P.display_text,{width:(S-10),top:((R-P.display_text.getBoundingClientRect().height)/2)});_css(P.display_iconBackground,{top:((R-h.skin.getSkinElement("display","background").height)/2),left:((S-h.skin.getSkinElement("display","background").width)/2)});if(e!=S||u!=R){e=S;u=R;d=undefined;F()}c();p({})};this.show=function(){if(g){g=false;r(h.jwGetState())}};this.hide=function(){if(!g){B();g=true}};function y(R){w=P.display_image.naturalWidth;N=P.display_image.naturalHeight;c()}function c(){_utils.stretch(h.jwGetStretching(),P.display_image,e,u,w,N)}function C(R,T){var S=document.createElement(R);S.id=h.id+"_jwplayer_"+T;_css(S,D[T].style);return S}function f(){for(var R in P){if(_utils.exists(D[R].click)){P[R].onclick=D[R].click}}}function m(R){if(typeof R.preventDefault!="undefined"){R.preventDefault()}else{R.returnValue=false}if(h.jwGetState()!=a.api.events.state.PLAYING){h.jwPlay()}else{h.jwPause()}}function O(R){if(A){B();return}P.display_icon.style.backgroundImage=(["url(",h.skin.getSkinElement("display",R).src,")"]).join("");_css(P.display_icon,{width:h.skin.getSkinElement("display",R).width,height:h.skin.getSkinElement("display",R).height,top:(h.skin.getSkinElement("display","background").height-h.skin.getSkinElement("display",R).height)/2,left:(h.skin.getSkinElement("display","background").width-h.skin.getSkinElement("display",R).width)/2});b();if(_utils.exists(h.skin.getSkinElement("display",R+"Over"))){P.display_icon.onmouseover=function(S){P.display_icon.style.backgroundImage=["url(",h.skin.getSkinElement("display",R+"Over").src,")"].join("")};P.display_icon.onmouseout=function(S){P.display_icon.style.backgroundImage=["url(",h.skin.getSkinElement("display",R).src,")"].join("")}}else{P.display_icon.onmouseover=null;P.display_icon.onmouseout=null}}function B(){if(Q.icons.toString()=="true"){_hide(P.display_icon);_hide(P.display_iconBackground);M()}}function b(){if(!g&&Q.icons.toString()=="true"){_show(P.display_icon);_show(P.display_iconBackground);F()}}function o(R){A=true;B();P.display_text.innerHTML=R.error;_show(P.display_text);P.display_text.style.top=((u-P.display_text.getBoundingClientRect().height)/2)+"px"}function E(){P.display_image.style.display="none"}function p(R){if((R.type==a.api.events.JWPLAYER_PLAYER_STATE||R.type==a.api.events.JWPLAYER_PLAYLIST_ITEM)&&A){A=false;_hide(P.display_text)}var S=h.jwGetState();if(S==t){return}t=S;if(z>=0){clearTimeout(z)}if(K||h.jwGetState()==a.api.events.state.PLAYING||h.jwGetState()==a.api.events.state.PAUSED){r(h.jwGetState())}else{z=setTimeout(l(h.jwGetState()),500)}}function l(R){return(function(){r(R)})}function r(R){if(_utils.exists(I)){clearInterval(I);I=null;_utils.animations.rotate(P.display_icon,0)}switch(R){case a.api.events.state.BUFFERING:if(_utils.isIOS()){E();B()}else{if(h.jwGetPlaylist()[h.jwGetItem()].provider=="sound"){v()}s=0;I=setInterval(function(){s+=J;_utils.animations.rotate(P.display_icon,s%360)},q);O("bufferIcon");K=true}break;case a.api.events.state.PAUSED:if(!_utils.isIOS()){if(h.jwGetPlaylist()[h.jwGetItem()].provider!="sound"){_css(P.display_image,{background:"transparent no-repeat center center"})}O("playIcon");K=true}break;case a.api.events.state.IDLE:if(h.jwGetPlaylist()[h.jwGetItem()]&&h.jwGetPlaylist()[h.jwGetItem()].image){v()}else{E()}O("playIcon");K=true;break;default:if(h.jwGetPlaylist()[h.jwGetItem()]&&h.jwGetPlaylist()[h.jwGetItem()].provider=="sound"){if(_utils.isIOS()){E();K=false}else{v()}}else{E();K=false}if(h.jwGetMute()&&Q.showmute){O("muteIcon")}else{B()}break}z=-1}function v(){if(h.jwGetPlaylist()[h.jwGetItem()]&&h.jwGetPlaylist()[h.jwGetItem()].image){_css(P.display_image,{display:"block"});P.display_image.src=_utils.getAbsolutePath(h.jwGetPlaylist()[h.jwGetItem()].image)}}function x(R){return function(){if(!n){return}if(!g&&d!=R){d=R;H.sendEvent(R,{component:"display",boundingRect:_utils.getDimensions(P.display_iconBackground)})}}}var F=x(a.api.events.JWPLAYER_COMPONENT_SHOW);var M=x(a.api.events.JWPLAYER_COMPONENT_HIDE);return this}})(jwplayer);(function(a){_css=a.utils.css;a.html5.dock=function(p,u){function q(){return{align:a.html5.view.positions.RIGHT}}var k=a.utils.extend({},q(),u);if(k.align=="FALSE"){return}var f={};var s=[];var g;var v;var d=false;var t=false;var e={x:0,y:0,width:0,height:0};var r;var j=new a.html5.eventdispatcher();_utils.extend(this,j);var m=document.createElement("div");m.id=p.id+"_jwplayer_dock";p.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,l);this.getDisplayElement=function(){return m};this.setButton=function(A,x,y,z){if(!x&&f[A]){a.utils.arrays.remove(s,A);m.removeChild(f[A].div);delete f[A]}else{if(x){if(!f[A]){f[A]={}}f[A].handler=x;f[A].outGraphic=y;f[A].overGraphic=z;if(!f[A].div){s.push(A);f[A].div=document.createElement("div");f[A].div.style.position="relative";m.appendChild(f[A].div);f[A].div.appendChild(document.createElement("img"));f[A].div.childNodes[0].style.position="absolute";f[A].div.childNodes[0].style.left=0;f[A].div.childNodes[0].style.top=0;f[A].div.childNodes[0].style.zIndex=10;f[A].div.childNodes[0].style.cursor="pointer";f[A].div.appendChild(document.createElement("img"));f[A].div.childNodes[1].style.position="absolute";f[A].div.childNodes[1].style.left=0;f[A].div.childNodes[1].style.top=0;if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}f[A].div.childNodes[1].style.zIndex=9;f[A].div.childNodes[1].style.cursor="pointer";f[A].div.onmouseover=function(){if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(p.skin.getSkinElement("dock","buttonOver")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","buttonOver").src}};f[A].div.onmouseout=function(){if(f[A].outGraphic){f[A].div.childNodes[0].src=f[A].outGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}};if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(f[A].outGraphic){f[A].div.childNodes[0].src=f[A].outGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}}if(x){f[A].div.onclick=function(B){B.preventDefault();a(p.id).callback(A);if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}}}}}h(g,v)};function h(x,J){if(s.length>0){var y=10;var I=y;var F=-1;var G=p.skin.getSkinElement("dock","button").height;var E=p.skin.getSkinElement("dock","button").width;var C=x-E-y;var H,B;if(k.align==a.html5.view.positions.LEFT){F=1;C=y}for(var z=0;z<s.length;z++){var K=Math.floor(I/J);if((I+G+y)>((K+1)*J)){I=((K+1)*J)+y;K=Math.floor(I/J)}var A=f[s[z]].div;A.style.top=(I%J)+"px";A.style.left=(C+(p.skin.getSkinElement("dock","button").width+y)*K*F)+"px";var D={x:a.utils.parseDimension(A.style.left),y:a.utils.parseDimension(A.style.top),width:E,height:G};if(!H||(D.x<=H.x&&D.y<=H.y)){H=D}if(!B||(D.x>=B.x&&D.y>=B.y)){B=D}I+=p.skin.getSkinElement("dock","button").height+y}e={x:H.x,y:H.y,width:B.x-H.x+B.width,height:H.y-B.y+B.height}}if(t!=p.jwGetFullscreen()||g!=x||v!=J){g=x;v=J;t=p.jwGetFullscreen();r=undefined;setTimeout(n,1)}}function b(x){return function(){if(!d&&r!=x&&s.length>0){r=x;j.sendEvent(x,{component:"dock",boundingRect:e})}}}function l(x){if(a.utils.isIOS()){switch(x.newstate){case a.api.events.state.IDLE:o();break;default:c();break}}}var n=b(a.api.events.JWPLAYER_COMPONENT_SHOW);var w=b(a.api.events.JWPLAYER_COMPONENT_HIDE);this.resize=h;var o=function(){_css(m,{display:"block"});if(d){d=false;n()}};var c=function(){_css(m,{display:"none"});if(!d){w();d=true}};this.hide=c;this.show=o;return this}})(jwplayer);(function(a){a.html5.eventdispatcher=function(d,b){var c=new a.events.eventdispatcher(b);a.utils.extend(this,c);this.sendEvent=function(e,f){if(!a.utils.exists(f)){f={}}a.utils.extend(f,{id:d,version:a.version,type:e});c.sendEvent(e,f)}}})(jwplayer);(function(a){var b={prefix:"http://l.longtailvideo.com/html5/",file:"logo.png",link:"http://www.longtailvideo.com/players/jw-flv-player/",margin:8,out:0.5,over:1,timeout:5,hide:true,position:"bottom-left"};_css=a.utils.css;a.html5.logo=function(n,r){var q=n;var u;var d;var t;var h=false;g();function g(){o();c();l()}function o(){if(b.prefix){var v=n.version.split(/\W/).splice(0,2).join("/");if(b.prefix.indexOf(v)<0){b.prefix+=v+"/"}}if(r.position==a.html5.view.positions.OVER){r.position=b.position}d=a.utils.extend({},b)}function c(){t=document.createElement("img");t.id=q.id+"_jwplayer_logo";t.style.display="none";t.onload=function(v){_css(t,k());q.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,j);p()};if(!d.file){return}if(d.file.indexOf("http://")===0){t.src=d.file}else{t.src=d.prefix+d.file}}if(!d.file){return}this.resize=function(w,v){};this.getDisplayElement=function(){return t};function l(){if(d.link){t.onmouseover=f;t.onmouseout=p;t.onclick=s}else{this.mouseEnabled=false}}function s(v){if(typeof v!="undefined"){v.stopPropagation()}if(!h){return}q.jwPause();q.jwSetFullscreen(false);if(d.link){window.open(d.link,"_top")}return}function p(v){if(d.link&&h){t.style.opacity=d.out}return}function f(v){if(d.hide.toString()=="true"&&h){t.style.opacity=d.over}return}function k(){var x={textDecoration:"none",position:"absolute",cursor:"pointer"};x.display=(d.hide.toString()=="true")?"none":"block";var w=d.position.toLowerCase().split("-");for(var v in w){x[w[v]]=d.margin}return x}function m(){if(d.hide.toString()=="true"){t.style.display="block";t.style.opacity=0;a.utils.fadeTo(t,d.out,0.1,parseFloat(t.style.opacity));u=setTimeout(function(){e()},d.timeout*1000)}h=true}function e(){h=false;if(d.hide.toString()=="true"){a.utils.fadeTo(t,0,0.1,parseFloat(t.style.opacity))}}function j(v){if(v.newstate==a.api.events.state.BUFFERING){clearTimeout(u);m()}}return this}})(jwplayer);(function(a){var c={ended:a.api.events.state.IDLE,playing:a.api.events.state.PLAYING,pause:a.api.events.state.PAUSED,buffering:a.api.events.state.BUFFERING};var e=a.utils;var b=e.css;var d=e.isIOS();a.html5.mediavideo=function(h,s){var r={abort:n,canplay:k,canplaythrough:k,durationchange:G,emptied:n,ended:k,error:u,loadeddata:G,loadedmetadata:G,loadstart:k,pause:k,play:n,playing:k,progress:v,ratechange:n,seeked:k,seeking:k,stalled:k,suspend:k,timeupdate:D,volumechange:n,waiting:k,canshowcurrentframe:n,dataunavailable:n,empty:n,load:z,loadedfirstframe:n};var j=new a.html5.eventdispatcher();e.extend(this,j);var y=h,l=s,m,B,A,x,f,H=false,C,p,q;o();this.load=function(J,K){if(typeof K=="undefined"){K=true}x=J;e.empty(m);q=0;if(J.levels&&J.levels.length>0){if(J.levels.length==1){m.src=J.levels[0].file}else{if(m.src){m.removeAttribute("src")}for(var I=0;I<J.levels.length;I++){var L=m.ownerDocument.createElement("source");L.src=J.levels[I].file;m.appendChild(L);q++}}}else{m.src=J.file}if(d){if(J.image){m.poster=J.image}m.controls="controls";m.style.display="block"}C=p=A=false;y.buffer=0;if(!e.exists(J.start)){J.start=0}y.duration=J.duration;j.sendEvent(a.api.events.JWPLAYER_MEDIA_LOADED);if((!d&&J.levels.length==1)||!H){m.load()}H=false;if(K){E(a.api.events.state.BUFFERING);j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:0});this.play()}};this.play=function(){if(B!=a.api.events.state.PLAYING){t();if(p){E(a.api.events.state.PLAYING)}else{E(a.api.events.state.BUFFERING)}m.play()}};this.pause=function(){m.pause();E(a.api.events.state.PAUSED)};this.seek=function(I){if(!(y.duration<=0||isNaN(y.duration))&&!(y.position<=0||isNaN(y.position))){m.currentTime=I;m.play()}};_stop=this.stop=function(I){if(!e.exists(I)){I=true}g();if(I){m.style.display="none";p=false;var J=navigator.userAgent;if(J.match(/chrome/i)){m.src=undefined}else{if(J.match(/safari/i)){m.removeAttribute("src")}else{m.src=""}}m.removeAttribute("controls");m.removeAttribute("poster");e.empty(m);m.load();H=true;if(m.webkitSupportsFullscreen){try{m.webkitExitFullscreen()}catch(K){}}}E(a.api.events.state.IDLE)};this.fullscreen=function(I){if(I===true){this.resize("100%","100%")}else{this.resize(y.config.width,y.config.height)}};this.resize=function(J,I){if(false){b(l,{width:J,height:I})}j.sendEvent(a.api.events.JWPLAYER_MEDIA_RESIZE,{fullscreen:y.fullscreen,width:J,hieght:I})};this.volume=function(I){if(!d){m.volume=I/100;y.volume=I;j.sendEvent(a.api.events.JWPLAYER_MEDIA_VOLUME,{volume:Math.round(I)})}};this.mute=function(I){if(!d){m.muted=I;y.mute=I;j.sendEvent(a.api.events.JWPLAYER_MEDIA_MUTE,{mute:I})}};this.getDisplayElement=function(){return m};this.hasChrome=function(){return false};function o(){m=document.createElement("video");B=a.api.events.state.IDLE;for(var I in r){m.addEventListener(I,function(J){if(e.exists(J.target.parentNode)){r[J.type](J)}},true)}m.setAttribute("x-webkit-airplay","allow");if(l.parentNode){l.parentNode.replaceChild(m,l)}if(!m.id){m.id=l.id}}function E(I){if(I==a.api.events.state.PAUSED&&B==a.api.events.state.IDLE){return}if(B!=I){var J=B;y.state=B=I;j.sendEvent(a.api.events.JWPLAYER_PLAYER_STATE,{oldstate:J,newstate:I})}}function n(I){}function v(K){var J;if(e.exists(K)&&K.lengthComputable&&K.total){J=K.loaded/K.total*100}else{if(e.exists(m.buffered)&&(m.buffered.length>0)){var I=m.buffered.length-1;if(I>=0){J=m.buffered.end(I)/m.duration*100}}}if(p===false&&B==a.api.events.state.BUFFERING){j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER_FULL);p=true}if(!C){if(J==100){C=true}if(e.exists(J)&&(J>y.buffer)){y.buffer=Math.round(J);j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:Math.round(J)})}}}function D(J){if(e.exists(J)&&e.exists(J.target)){if(!isNaN(J.target.duration)&&(isNaN(y.duration)||y.duration<1)){if(J.target.duration==Infinity){y.duration=0}else{y.duration=Math.round(J.target.duration*10)/10}}if(!A&&m.readyState>0){m.style.display="block";E(a.api.events.state.PLAYING)}if(B==a.api.events.state.PLAYING){if(!A&&m.readyState>0){A=true;try{if(m.currentTime<x.start){m.currentTime=x.start}}catch(I){}m.volume=y.volume/100;m.muted=y.mute}y.position=y.duration>0?(Math.round(J.target.currentTime*10)/10):0;j.sendEvent(a.api.events.JWPLAYER_MEDIA_TIME,{position:y.position,duration:y.duration});if(y.position>=y.duration&&(y.position>0||y.duration>0)){w()}}}v(J)}function z(I){}function k(I){if(c[I.type]){if(I.type=="ended"){w()}else{E(c[I.type])}}}function G(I){var J={height:I.target.videoHeight,width:I.target.videoWidth,duration:Math.round(I.target.duration*10)/10};if((y.duration===0||isNaN(y.duration))&&I.target.duration!=Infinity){y.duration=Math.round(I.target.duration*10)/10}j.sendEvent(a.api.events.JWPLAYER_MEDIA_META,{metadata:J})}function u(K){if(B==a.api.events.state.IDLE){return}var J="There was an error: ";if((K.target.error&&K.target.tagName.toLowerCase()=="video")||K.target.parentNode.error&&K.target.parentNode.tagName.toLowerCase()=="video"){var I=!e.exists(K.target.error)?K.target.parentNode.error:K.target.error;switch(I.code){case I.MEDIA_ERR_ABORTED:J="You aborted the video playback: ";break;case I.MEDIA_ERR_NETWORK:J="A network error caused the video download to fail part-way: ";break;case I.MEDIA_ERR_DECODE:J="The video playback was aborted due to a corruption problem or because the video used features your browser did not support: ";break;case I.MEDIA_ERR_SRC_NOT_SUPPORTED:J="The video could not be loaded, either because the server or network failed or because the format is not supported: ";break;default:J="An unknown error occurred: ";break}}else{if(K.target.tagName.toLowerCase()=="source"){q--;if(q>0){return}J="The video could not be loaded, either because the server or network failed or because the format is not supported: "}else{e.log("An unknown error occurred.  Continuing...");return}}_stop(false);J+=F();_error=true;j.sendEvent(a.api.events.JWPLAYER_ERROR,{error:J});return}function F(){var K="";for(var J in x.levels){var I=x.levels[J];var L=l.ownerDocument.createElement("source");K+=a.utils.getAbsolutePath(I.file);if(J<(x.levels.length-1)){K+=", "}}return K}function t(){if(!e.exists(f)){f=setInterval(function(){v()},100)}}function g(){clearInterval(f);f=null}function w(){if(B!=a.api.events.state.IDLE){_stop(false);j.sendEvent(a.api.events.JWPLAYER_MEDIA_COMPLETE)}}}})(jwplayer);(function(a){var c={ended:a.api.events.state.IDLE,playing:a.api.events.state.PLAYING,pause:a.api.events.state.PAUSED,buffering:a.api.events.state.BUFFERING};var b=a.utils.css;a.html5.mediayoutube=function(j,e){var f=new a.html5.eventdispatcher();a.utils.extend(this,f);var l=j;var h=document.getElementById(e.id);var g=a.api.events.state.IDLE;var n,m;function k(p){if(g!=p){var q=g;l.state=p;g=p;f.sendEvent(a.api.events.JWPLAYER_PLAYER_STATE,{oldstate:q,newstate:p})}}this.getDisplayElement=function(){return h};this.play=function(){if(g==a.api.events.state.IDLE){f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:100});f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER_FULL);k(a.api.events.state.PLAYING)}else{if(g==a.api.events.state.PAUSED){k(a.api.events.state.PLAYING)}}};this.pause=function(){k(a.api.events.state.PAUSED)};this.seek=function(p){};this.stop=function(p){if(!_utils.exists(p)){p=true}l.position=0;k(a.api.events.state.IDLE);if(p){b(h,{display:"none"})}};this.volume=function(p){l.volume=p;f.sendEvent(a.api.events.JWPLAYER_MEDIA_VOLUME,{volume:Math.round(p)})};this.mute=function(p){h.muted=p;l.mute=p;f.sendEvent(a.api.events.JWPLAYER_MEDIA_MUTE,{mute:p})};this.resize=function(q,p){if(q*p>0&&n){n.width=m.width=q;n.height=m.height=p}f.sendEvent(a.api.events.JWPLAYER_MEDIA_RESIZE,{fullscreen:l.fullscreen,width:q,height:p})};this.fullscreen=function(p){if(p===true){this.resize("100%","100%")}else{this.resize(l.config.width,l.config.height)}};this.load=function(p){o(p);b(n,{display:"block"});k(a.api.events.state.BUFFERING);f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:0});f.sendEvent(a.api.events.JWPLAYER_MEDIA_LOADED);this.play()};this.hasChrome=function(){return(g!=a.api.events.state.IDLE)};function o(v){var s=v.levels[0].file;s=["http://www.youtube.com/v/",d(s),"&amp;hl=en_US&amp;fs=1&autoplay=1"].join("");n=document.createElement("object");n.id=h.id;n.style.position="absolute";var u={movie:s,allowfullscreen:"true",allowscriptaccess:"always"};for(var p in u){var t=document.createElement("param");t.name=p;t.value=u[p];n.appendChild(t)}m=document.createElement("embed");n.appendChild(m);var q={src:s,type:"application/x-shockwave-flash",allowfullscreen:"true",allowscriptaccess:"always",width:n.width,height:n.height};for(var r in q){m.setAttribute(r,q[r])}n.appendChild(m);n.style.zIndex=2147483000;if(h!=n&&h.parentNode){h.parentNode.replaceChild(n,h)}h=n}function d(q){var p=q.split(/\?|\#\!/);var s="";for(var r=0;r<p.length;r++){if(p[r].substr(0,2)=="v="){s=p[r].substr(2)}}if(s==""){if(q.indexOf("/v/")>=0){s=q.substr(q.indexOf("/v/")+3)}else{if(q.indexOf("youtu.be")>=0){s=q.substr(q.indexOf("youtu.be/")+9)}else{s=q}}}if(s.indexOf("?")>-1){s=s.substr(0,s.indexOf("?"))}if(s.indexOf("&")>-1){s=s.substr(0,s.indexOf("&"))}return s}this.embed=m;return this}})(jwplayer);(function(jwplayer){var _configurableStateVariables=["width","height","start","duration","volume","mute","fullscreen","item","plugins","stretching"];jwplayer.html5.model=function(api,container,options){var _api=api;var _container=container;var _model={id:_container.id,playlist:[],state:jwplayer.api.events.state.IDLE,position:0,buffer:0,config:{width:480,height:320,item:-1,skin:undefined,file:undefined,image:undefined,start:0,duration:0,bufferlength:5,volume:90,mute:false,fullscreen:false,repeat:"",stretching:jwplayer.utils.stretching.UNIFORM,autostart:false,debug:undefined,screencolor:undefined}};var _media;var _eventDispatcher=new jwplayer.html5.eventdispatcher();var _components=["display","logo","controlbar","playlist","dock"];jwplayer.utils.extend(_model,_eventDispatcher);for(var option in options){if(typeof options[option]=="string"){var type=/color$/.test(option)?"color":null;options[option]=jwplayer.utils.typechecker(options[option],type)}var config=_model.config;var path=option.split(".");for(var edge in path){if(edge==path.length-1){config[path[edge]]=options[option]}else{if(!jwplayer.utils.exists(config[path[edge]])){config[path[edge]]={}}config=config[path[edge]]}}}for(var index in _configurableStateVariables){var configurableStateVariable=_configurableStateVariables[index];_model[configurableStateVariable]=_model.config[configurableStateVariable]}var pluginorder=_components.concat([]);if(jwplayer.utils.exists(_model.plugins)){if(typeof _model.plugins=="string"){var userplugins=_model.plugins.split(",");for(var userplugin in userplugins){if(typeof userplugins[userplugin]=="string"){pluginorder.push(userplugins[userplugin].replace(/^\s+|\s+$/g,""))}}}}if(jwplayer.utils.isIOS()){pluginorder=["display","logo","dock","playlist"];if(!jwplayer.utils.exists(_model.config.repeat)){_model.config.repeat="list"}}else{if(_model.config.chromeless){pluginorder=["logo","dock","playlist"];if(!jwplayer.utils.exists(_model.config.repeat)){_model.config.repeat="list"}}}_model.plugins={order:pluginorder,config:{},object:{}};if(typeof _model.config.components!="undefined"){for(var component in _model.config.components){_model.plugins.config[component]=_model.config.components[component]}}for(var pluginIndex in _model.plugins.order){var pluginName=_model.plugins.order[pluginIndex];var pluginConfig=!jwplayer.utils.exists(_model.plugins.config[pluginName])?{}:_model.plugins.config[pluginName];_model.plugins.config[pluginName]=!jwplayer.utils.exists(_model.plugins.config[pluginName])?pluginConfig:jwplayer.utils.extend(_model.plugins.config[pluginName],pluginConfig);if(!jwplayer.utils.exists(_model.plugins.config[pluginName].position)){if(pluginName=="playlist"){_model.plugins.config[pluginName].position=jwplayer.html5.view.positions.NONE}else{_model.plugins.config[pluginName].position=jwplayer.html5.view.positions.OVER}}else{_model.plugins.config[pluginName].position=_model.plugins.config[pluginName].position.toString().toUpperCase()}}if(typeof _model.plugins.config.dock!="undefined"){if(typeof _model.plugins.config.dock!="object"){var position=_model.plugins.config.dock.toString().toUpperCase();_model.plugins.config.dock={position:position}}if(typeof _model.plugins.config.dock.position!="undefined"){_model.plugins.config.dock.align=_model.plugins.config.dock.position;_model.plugins.config.dock.position=jwplayer.html5.view.positions.OVER}}function _loadExternal(playlistfile){var loader=new jwplayer.html5.playlistloader();loader.addEventListener(jwplayer.api.events.JWPLAYER_PLAYLIST_LOADED,function(evt){_model.playlist=new jwplayer.html5.playlist(evt);_loadComplete(true)});loader.addEventListener(jwplayer.api.events.JWPLAYER_ERROR,function(evt){_model.playlist=new jwplayer.html5.playlist({playlist:[]});_loadComplete(false)});loader.load(playlistfile)}function _loadComplete(){if(_model.config.shuffle){_model.item=_getShuffleItem()}else{if(_model.config.item>=_model.playlist.length){_model.config.item=_model.playlist.length-1}else{if(_model.config.item<0){_model.config.item=0}}_model.item=_model.config.item}_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_PLAYLIST_LOADED,{playlist:_model.playlist});_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_PLAYLIST_ITEM,{index:_model.item})}_model.loadPlaylist=function(arg){var input;if(typeof arg=="string"){if(arg.indexOf("[")==0||arg.indexOf("{")=="0"){try{input=eval(arg)}catch(err){input=arg}}else{input=arg}}else{input=arg}var config;switch(jwplayer.utils.typeOf(input)){case"object":config=input;break;case"array":config={playlist:input};break;default:_loadExternal(input);return;break}_model.playlist=new jwplayer.html5.playlist(config);if(jwplayer.utils.extension(_model.playlist[0].file)=="xml"){_loadExternal(_model.playlist[0].file)}else{_loadComplete()}};function _getShuffleItem(){var result=null;if(_model.playlist.length>1){while(!jwplayer.utils.exists(result)){result=Math.floor(Math.random()*_model.playlist.length);if(result==_model.item){result=null}}}else{result=0}return result}function forward(evt){if(evt.type==jwplayer.api.events.JWPLAYER_MEDIA_LOADED){_container=_media.getDisplayElement()}_eventDispatcher.sendEvent(evt.type,evt)}var _mediaProviders={};_model.setActiveMediaProvider=function(playlistItem){if(playlistItem.provider=="audio"){playlistItem.provider="sound"}var provider=playlistItem.provider;var current=_media?_media.getDisplayElement():null;if(provider=="sound"||provider=="http"||provider==""){provider="video"}if(!jwplayer.utils.exists(_mediaProviders[provider])){switch(provider){case"video":_media=new jwplayer.html5.mediavideo(_model,current?current:_container);break;case"youtube":_media=new jwplayer.html5.mediayoutube(_model,current?current:_container);break}if(!jwplayer.utils.exists(_media)){return false}_media.addGlobalListener(forward);_mediaProviders[provider]=_media}else{if(_media!=_mediaProviders[provider]){if(_media){_media.stop()}_media=_mediaProviders[provider]}}return true};_model.getMedia=function(){return _media};_model.seek=function(pos){_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_MEDIA_SEEK,{position:_model.position,offset:pos});return _media.seek(pos)};_model.setupPlugins=function(){if(!jwplayer.utils.exists(_model.plugins)||!jwplayer.utils.exists(_model.plugins.order)||_model.plugins.order.length==0){jwplayer.utils.log("No plugins to set up");return _model}for(var i=0;i<_model.plugins.order.length;i++){try{var pluginName=_model.plugins.order[i];if(jwplayer.utils.exists(jwplayer.html5[pluginName])){if(pluginName=="playlist"){_model.plugins.object[pluginName]=new jwplayer.html5.playlistcomponent(_api,_model.plugins.config[pluginName])}else{_model.plugins.object[pluginName]=new jwplayer.html5[pluginName](_api,_model.plugins.config[pluginName])}}else{_model.plugins.order.splice(plugin,plugin+1)}if(typeof _model.plugins.object[pluginName].addGlobalListener=="function"){_model.plugins.object[pluginName].addGlobalListener(forward)}}catch(err){jwplayer.utils.log("Could not setup "+pluginName)}}};return _model}})(jwplayer);(function(a){a.html5.playlist=function(b){var d=[];if(b.playlist&&b.playlist instanceof Array&&b.playlist.length>0){for(var c in b.playlist){if(!isNaN(parseInt(c))){d.push(new a.html5.playlistitem(b.playlist[c]))}}}else{d.push(new a.html5.playlistitem(b))}return d}})(jwplayer);(function(a){var c={size:180,position:a.html5.view.positions.NONE,itemheight:60,thumbs:true,fontcolor:"#000000",overcolor:"",activecolor:"",backgroundcolor:"#f8f8f8",font:"_sans",fontsize:"",fontstyle:"",fontweight:""};var b={_sans:"Arial, Helvetica, sans-serif",_serif:"Times, Times New Roman, serif",_typewriter:"Courier New, Courier, monospace"};_utils=a.utils;_css=_utils.css;_hide=function(d){_css(d,{display:"none"})};_show=function(d){_css(d,{display:"block"})};a.html5.playlistcomponent=function(r,B){var w=r;var e=a.utils.extend({},c,w.skin.getComponentSettings("playlist"),B);if(e.position==a.html5.view.positions.NONE||typeof a.html5.view.positions[e.position]=="undefined"){return}var x;var l;var C;var d;var g;var f;var k=-1;var h={background:undefined,item:undefined,itemOver:undefined,itemImage:undefined,itemActive:undefined};this.getDisplayElement=function(){return x};this.resize=function(F,D){l=F;C=D;if(w.jwGetFullscreen()){_hide(x)}else{var E={display:"block",width:l,height:C};_css(x,E)}};this.show=function(){_show(x)};this.hide=function(){_hide(x)};function j(){x=document.createElement("div");x.id=w.id+"_jwplayer_playlistcomponent";switch(e.position){case a.html5.view.positions.RIGHT:case a.html5.view.positions.LEFT:x.style.width=e.size+"px";break;case a.html5.view.positions.TOP:case a.html5.view.positions.BOTTOM:x.style.height=e.size+"px";break}A();if(h.item){e.itemheight=h.item.height}x.style.backgroundColor="#C6C6C6";w.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,s);w.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,u);w.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,m)}function p(){var D=document.createElement("ul");_css(D,{width:x.style.width,minWidth:x.style.width,height:x.style.height,backgroundColor:e.backgroundcolor,backgroundImage:h.background?"url("+h.background.src+")":"",color:e.fontcolor,listStyle:"none",margin:0,padding:0,fontFamily:b[e.font]?b[e.font]:b._sans,fontSize:(e.fontsize?e.fontsize:11)+"px",fontStyle:e.fontstyle,fontWeight:e.fontweight,overflowY:"auto"});return D}function y(D){return function(){var E=f.getElementsByClassName("item")[D];var F=e.fontcolor;var G=h.item?"url("+h.item.src+")":"";if(D==w.jwGetPlaylistIndex()){if(e.activecolor!==""){F=e.activecolor}if(h.itemActive){G="url("+h.itemActive.src+")"}}_css(E,{color:e.overcolor!==""?e.overcolor:F,backgroundImage:h.itemOver?"url("+h.itemOver.src+")":G})}}function o(D){return function(){var E=f.getElementsByClassName("item")[D];var F=e.fontcolor;var G=h.item?"url("+h.item.src+")":"";if(D==w.jwGetPlaylistIndex()){if(e.activecolor!==""){F=e.activecolor}if(h.itemActive){G="url("+h.itemActive.src+")"}}_css(E,{color:F,backgroundImage:G})}}function q(I){var P=d[I];var O=document.createElement("li");O.className="item";_css(O,{height:e.itemheight,display:"block",cursor:"pointer",backgroundImage:h.item?"url("+h.item.src+")":"",backgroundSize:"100% "+e.itemheight+"px"});O.onmouseover=y(I);O.onmouseout=o(I);var J=document.createElement("div");var F=new Image();var K=0;var L=0;var M=0;if(v()&&(P.image||P["playlist.image"]||h.itemImage)){F.className="image";if(h.itemImage){K=(e.itemheight-h.itemImage.height)/2;L=h.itemImage.width;M=h.itemImage.height}else{L=e.itemheight*4/3;M=e.itemheight}_css(J,{height:M,width:L,"float":"left",styleFloat:"left",cssFloat:"left",margin:"0 5px 0 0",background:"black",overflow:"hidden",margin:K+"px",position:"relative"});_css(F,{position:"relative"});J.appendChild(F);F.onload=function(){a.utils.stretch(a.utils.stretching.FILL,F,L,M,this.naturalWidth,this.naturalHeight)};if(P["playlist.image"]){F.src=P["playlist.image"]}else{if(P.image){F.src=P.image}else{if(h.itemImage){F.src=h.itemImage.src}}}O.appendChild(J)}var E=l-L-K*2;if(C<e.itemheight*d.length){E-=15}var D=document.createElement("div");_css(D,{position:"relative",height:"100%",overflow:"hidden"});var G=document.createElement("span");if(P.duration>0){G.className="duration";_css(G,{fontSize:(e.fontsize?e.fontsize:11)+"px",fontWeight:(e.fontweight?e.fontweight:"bold"),width:"40px",height:e.fontsize?e.fontsize+10:20,lineHeight:24,"float":"right",styleFloat:"right",cssFloat:"right"});G.innerHTML=_utils.timeFormat(P.duration);D.appendChild(G)}var N=document.createElement("span");N.className="title";_css(N,{padding:"5px 5px 0 "+(K?0:"5px"),height:e.fontsize?e.fontsize+10:20,lineHeight:e.fontsize?e.fontsize+10:20,overflow:"hidden","float":"left",styleFloat:"left",cssFloat:"left",width:((P.duration>0)?E-50:E)-10+"px",fontSize:(e.fontsize?e.fontsize:13)+"px",fontWeight:(e.fontweight?e.fontweight:"bold")});N.innerHTML=P?P.title:"";D.appendChild(N);if(P.description){var H=document.createElement("span");H.className="description";_css(H,{display:"block","float":"left",styleFloat:"left",cssFloat:"left",margin:0,paddingLeft:N.style.paddingLeft,paddingRight:N.style.paddingRight,lineHeight:(e.fontsize?e.fontsize+4:16)+"px",overflow:"hidden",position:"relative"});H.innerHTML=P.description;D.appendChild(H)}O.appendChild(D);return O}function s(E){x.innerHTML="";d=w.jwGetPlaylist();if(!d){return}items=[];f=p();for(var F=0;F<d.length;F++){var D=q(F);D.onclick=z(F);f.appendChild(D);items.push(D)}k=w.jwGetPlaylistIndex();o(k)();x.appendChild(f);if(_utils.isIOS()&&window.iScroll){f.style.height=e.itemheight*d.length+"px";var G=new iScroll(x.id)}}function z(D){return function(){w.jwPlaylistItem(D);w.jwPlay(true)}}function n(){f.scrollTop=w.jwGetPlaylistIndex()*e.itemheight}function v(){return e.thumbs.toString().toLowerCase()=="true"}function u(D){if(k>=0){o(k)();k=D.index}o(D.index)();n()}function m(){if(e.position==a.html5.view.positions.OVER){switch(w.jwGetState()){case a.api.events.state.IDLE:_show(x);break;default:_hide(x);break}}}function A(){for(var D in h){h[D]=t(D)}}function t(D){return w.skin.getSkinElement("playlist",D)}j();return this}})(jwplayer);(function(b){b.html5.playlistitem=function(d){var e={author:"",date:"",description:"",image:"",link:"",mediaid:"",tags:"",title:"",provider:"",file:"",streamer:"",duration:-1,start:0,currentLevel:-1,levels:[]};var c=b.utils.extend({},e,d);if(c.type){c.provider=c.type;delete c.type}if(c.levels.length===0){c.levels[0]=new b.html5.playlistitemlevel(c)}if(!c.provider){c.provider=a(c.levels[0])}else{c.provider=c.provider.toLowerCase()}return c};function a(e){if(b.utils.isYouTube(e.file)){return"youtube"}else{var f=b.utils.extension(e.file);var c;if(f&&b.utils.extensionmap[f]){if(f=="m3u8"){return"video"}c=b.utils.extensionmap[f].html5}else{if(e.type){c=e.type}}if(c){var d=c.split("/")[0];if(d=="audio"){return"sound"}else{if(d=="video"){return d}}}}return""}})(jwplayer);(function(a){a.html5.playlistitemlevel=function(b){var d={file:"",streamer:"",bitrate:0,width:0};for(var c in d){if(a.utils.exists(b[c])){d[c]=b[c]}}return d}})(jwplayer);(function(a){a.html5.playlistloader=function(){var c=new a.html5.eventdispatcher();a.utils.extend(this,c);this.load=function(e){a.utils.ajax(e,d,b)};function d(g){var f=[];try{var f=a.utils.parsers.rssparser.parse(g.responseXML.firstChild);c.sendEvent(a.api.events.JWPLAYER_PLAYLIST_LOADED,{playlist:new a.html5.playlist({playlist:f})})}catch(h){b("Could not parse the playlist")}}function b(e){c.sendEvent(a.api.events.JWPLAYER_ERROR,{error:e?e:"could not load playlist for whatever reason.  too bad"})}}})(jwplayer);(function(a){a.html5.skin=function(){var b={};var c=false;this.load=function(d,e){new a.html5.skinloader(d,function(f){c=true;b=f;e()},function(){new a.html5.skinloader("",function(f){c=true;b=f;e()})})};this.getSkinElement=function(d,e){if(c){try{return b[d].elements[e]}catch(f){a.utils.log("No such skin component / element: ",[d,e])}}return null};this.getComponentSettings=function(d){if(c){return b[d].settings}return null};this.getComponentLayout=function(d){if(c){return b[d].layout}return null}}})(jwplayer);(function(a){a.html5.skinloader=function(f,p,k){var o={};var c=p;var l=k;var e=true;var j;var n=f;var s=false;function m(){if(typeof n!="string"||n===""){d(a.html5.defaultSkin().xml)}else{a.utils.ajax(a.utils.getAbsolutePath(n),function(t){try{if(a.utils.exists(t.responseXML)){d(t.responseXML);return}}catch(u){h()}d(a.html5.defaultSkin().xml)},function(t){d(a.html5.defaultSkin().xml)})}}function d(y){var E=y.getElementsByTagName("component");if(E.length===0){return}for(var H=0;H<E.length;H++){var C=E[H].getAttribute("name");var B={settings:{},elements:{},layout:{}};o[C]=B;var G=E[H].getElementsByTagName("elements")[0].getElementsByTagName("element");for(var F=0;F<G.length;F++){b(G[F],C)}var z=E[H].getElementsByTagName("settings")[0];if(z&&z.childNodes.length>0){var K=z.getElementsByTagName("setting");for(var P=0;P<K.length;P++){var Q=K[P].getAttribute("name");var I=K[P].getAttribute("value");var x=/color$/.test(Q)?"color":null;o[C].settings[Q]=a.utils.typechecker(I,x)}}var L=E[H].getElementsByTagName("layout")[0];if(L&&L.childNodes.length>0){var M=L.getElementsByTagName("group");for(var w=0;w<M.length;w++){var A=M[w];o[C].layout[A.getAttribute("position")]={elements:[]};for(var O=0;O<A.attributes.length;O++){var D=A.attributes[O];o[C].layout[A.getAttribute("position")][D.name]=D.value}var N=A.getElementsByTagName("*");for(var v=0;v<N.length;v++){var t=N[v];o[C].layout[A.getAttribute("position")].elements.push({type:t.tagName});for(var u=0;u<t.attributes.length;u++){var J=t.attributes[u];o[C].layout[A.getAttribute("position")].elements[v][J.name]=J.value}if(!a.utils.exists(o[C].layout[A.getAttribute("position")].elements[v].name)){o[C].layout[A.getAttribute("position")].elements[v].name=t.tagName}}}}e=false;r()}}function r(){clearInterval(j);if(!s){j=setInterval(function(){q()},100)}}function b(y,x){var w=new Image();var t=y.getAttribute("name");var v=y.getAttribute("src");var A;if(v.indexOf("data:image/png;base64,")===0){A=v}else{var u=a.utils.getAbsolutePath(n);var z=u.substr(0,u.lastIndexOf("/"));A=[z,x,v].join("/")}o[x].elements[t]={height:0,width:0,src:"",ready:false,image:w};w.onload=function(B){g(w,t,x)};w.onerror=function(B){s=true;r();l()};w.src=A}function h(){for(var u in o){var w=o[u];for(var t in w.elements){var x=w.elements[t];var v=x.image;v.onload=null;v.onerror=null;delete x.image;delete w.elements[t]}delete o[u]}}function q(){for(var t in o){if(t!="properties"){for(var u in o[t].elements){if(!o[t].elements[u].ready){return}}}}if(e===false){clearInterval(j);c(o)}}function g(t,v,u){if(o[u]&&o[u].elements[v]){o[u].elements[v].height=t.height;o[u].elements[v].width=t.width;o[u].elements[v].src=t.src;o[u].elements[v].ready=true;r()}else{a.utils.log("Loaded an image for a missing element: "+u+"."+v)}}m()}})(jwplayer);(function(a){a.html5.api=function(c,n){var m={};var f=document.createElement("div");c.parentNode.replaceChild(f,c);f.id=c.id;m.version=a.version;m.id=f.id;var l=new a.html5.model(m,f,n);var j=new a.html5.view(m,f,l);var k=new a.html5.controller(m,f,l,j);m.skin=new a.html5.skin();m.jwPlay=function(o){if(typeof o=="undefined"){e()}else{if(o.toString().toLowerCase()=="true"){k.play()}else{k.pause()}}};m.jwPause=function(o){if(typeof o=="undefined"){e()}else{if(o.toString().toLowerCase()=="true"){k.pause()}else{k.play()}}};function e(){if(l.state==a.api.events.state.PLAYING||l.state==a.api.events.state.BUFFERING){k.pause()}else{k.play()}}m.jwStop=k.stop;m.jwSeek=k.seek;m.jwPlaylistItem=k.item;m.jwPlaylistNext=k.next;m.jwPlaylistPrev=k.prev;m.jwResize=k.resize;m.jwLoad=k.load;function h(o){return function(){return l[o]}}function d(o,q,p){return function(){var r=l.plugins.object[o];if(r&&r[q]&&typeof r[q]=="function"){r[q].apply(r,p)}}}m.jwGetItem=h("item");m.jwGetPosition=h("position");m.jwGetDuration=h("duration");m.jwGetBuffer=h("buffer");m.jwGetWidth=h("width");m.jwGetHeight=h("height");m.jwGetFullscreen=h("fullscreen");m.jwSetFullscreen=k.setFullscreen;m.jwGetVolume=h("volume");m.jwSetVolume=k.setVolume;m.jwGetMute=h("mute");m.jwSetMute=k.setMute;m.jwGetStretching=h("stretching");m.jwGetState=h("state");m.jwGetVersion=function(){return m.version};m.jwGetPlaylist=function(){return l.playlist};m.jwGetPlaylistIndex=m.jwGetItem;m.jwAddEventListener=k.addEventListener;m.jwRemoveEventListener=k.removeEventListener;m.jwSendEvent=k.sendEvent;m.jwDockSetButton=function(r,o,p,q){if(l.plugins.object.dock&&l.plugins.object.dock.setButton){l.plugins.object.dock.setButton(r,o,p,q)}};m.jwControlbarShow=d("controlbar","show");m.jwControlbarHide=d("controlbar","hide");m.jwDockShow=d("dock","show");m.jwDockHide=d("dock","hide");m.jwDisplayShow=d("display","show");m.jwDisplayHide=d("display","hide");m.jwGetLevel=function(){};m.jwGetBandwidth=function(){};m.jwGetLockState=function(){};m.jwLock=function(){};m.jwUnlock=function(){};function b(){if(l.config.playlistfile){l.addEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.loadPlaylist(l.config.playlistfile)}else{if(typeof l.config.playlist=="string"){l.addEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.loadPlaylist(l.config.playlist)}else{l.loadPlaylist(l.config);setTimeout(g,25)}}}function g(o){l.removeEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.setupPlugins();j.setup();var o={id:m.id,version:m.version};k.playerReady(o)}if(l.config.chromeless&&!a.utils.isIOS()){b()}else{m.skin.load(l.config.skin,b)}return m}})(jwplayer)};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/popcorn.code.js	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,182 @@
+// PLUGIN: Code
+
+(function ( Popcorn ) {
+
+  /**
+   * Code Popcorn Plug-in
+   *
+   * Adds the ability to run arbitrary code (JavaScript functions) according to video timing.
+   *
+   * @param {Object} options
+   *
+   * Required parameters: start, end, template, data, and target.
+   * Optional parameter: static.
+   *
+   *   start: the time in seconds when the mustache template should be rendered
+   *          in the target div.
+   *
+   *   end: the time in seconds when the rendered mustache template should be
+   *        removed from the target div.
+   *
+   *   onStart: the function to be run when the start time is reached.
+   *
+   *   onFrame: [optional] a function to be run on each paint call
+   *            (e.g., called ~60 times per second) between the start and end times.
+   *
+   *   onEnd: [optional] a function to be run when the end time is reached.
+   *
+   * Example:
+     var p = Popcorn('#video')
+
+        // onStart function only
+        .code({
+          start: 1,
+          end: 4,
+          onStart: function( options ) {
+            // called on start
+          }
+        })
+
+        // onStart + onEnd only
+        .code({
+          start: 6,
+          end: 8,
+          onStart: function( options ) {
+            // called on start
+          },
+          onEnd: function ( options ) {
+            // called on end
+          }
+        })
+
+        // onStart, onEnd, onFrame
+        .code({
+          start: 10,
+          end: 14,
+          onStart: function( options ) {
+            // called on start
+          },
+          onFrame: function ( options ) {
+            // called on every paint frame between start and end.
+            // uses mozRequestAnimationFrame, webkitRequestAnimationFrame,
+            // or setTimeout with 16ms window.
+          },
+          onEnd: function ( options ) {
+            // called on end
+          }
+        });
+  *
+  */
+
+  Popcorn.plugin( "code" , function( options ) {
+    var running = false;
+
+    // Setup a proper frame interval function (60fps), favouring paint events.
+    var step = (function() {
+
+      var buildFrameRunner = function( runner ) {
+        return function( f, options ) {
+
+          var _f = function() {
+            running && f();
+            running && runner( _f );
+          };
+
+          _f();
+        };
+      };
+
+      // Figure out which level of browser support we have for this
+      if ( window.webkitRequestAnimationFrame ) {
+        return buildFrameRunner( window.webkitRequestAnimationFrame );
+      } else if ( window.mozRequestAnimationFrame ) {
+        return buildFrameRunner( window.mozRequestAnimationFrame );
+      } else {
+        return buildFrameRunner( function( f ) {
+          window.setTimeout( f, 16 );
+        });
+      }
+
+    })();
+
+    if ( !options.onStart || typeof options.onStart !== "function" ) {
+
+      if ( Popcorn.plugin.debug ) {
+        throw new Error( "Popcorn Code Plugin Error: onStart must be a function." );
+      }
+      options.onStart = Popcorn.nop;
+    }
+
+    if ( options.onEnd && typeof options.onEnd !== "function" ) {
+
+      if ( Popcorn.plugin.debug ) {
+        throw new Error( "Popcorn Code Plugin Error: onEnd  must be a function." );
+      }
+      options.onEnd = undefined;
+    }
+
+    if ( options.onFrame && typeof options.onFrame !== "function" ) {
+
+      if ( Popcorn.plugin.debug ) {
+        throw new Error( "Popcorn Code Plugin Error: onFrame  must be a function." );
+      }
+      options.onFrame = undefined;
+    }
+
+    return {
+      start: function( event, options ) {
+        options.onStart( options );
+
+        if ( options.onFrame ) {
+          running = true;
+          step( options.onFrame, options );
+        }
+      },
+
+      end: function( event, options ) {
+        if ( options.onFrame ) {
+          running = false;
+        }
+
+        if ( options.onEnd ) {
+          options.onEnd( options );
+        }
+      }
+    };
+  },
+  {
+    about: {
+      name: "Popcorn Code Plugin",
+      version: "0.1",
+      author: "David Humphrey (@humphd)",
+      website: "http://vocamus.net/dave"
+    },
+    options: {
+      start: {
+       elem: "input",
+       type: "text",
+       label: "In"
+      },
+      end: {
+        elem: "input",
+        type: "text",
+        label: "Out"
+      },
+      onStart: {
+        elem: "input",
+        type: "function",
+        label: "onStart"
+      },
+      onFrame: {
+        elem: "input",
+        type: "function",
+        label: "onFrame"
+      },
+      onEnd: {
+        elem: "input",
+        type: "function",
+        label: "onEnd"
+      }
+    }
+  });
+})( Popcorn );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/popcorn.js	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,2191 @@
+(function(global, document) {
+
+  // Popcorn.js does not support archaic browsers
+  if ( !document.addEventListener ) {
+    global.Popcorn = {
+      isSupported: false
+    };
+
+    var methods = ( "forEach extend effects error guid sizeOf isArray nop position disable enable destroy " +
+          "addTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId " +
+          "timeUpdate plugin removePlugin compose effect parser xhr getJSONP getScript" ).split(/\s+/);
+
+    while ( methods.length ) {
+      global.Popcorn[ methods.shift() ] = function() {};
+    }
+    return;
+  }
+
+  var
+
+  AP = Array.prototype,
+  OP = Object.prototype,
+
+  forEach = AP.forEach,
+  slice = AP.slice,
+  hasOwn = OP.hasOwnProperty,
+  toString = OP.toString,
+
+  // Copy global Popcorn (may not exist)
+  _Popcorn = global.Popcorn,
+
+  //  ID string matching
+  rIdExp  = /^(#([\w\-\_\.]+))$/,
+
+  //  Ready fn cache
+  readyStack = [],
+  readyBound = false,
+  readyFired = false,
+
+  //  Non-public internal data object
+  internal = {
+    events: {
+      hash: {},
+      apis: {}
+    }
+  },
+
+  //  Non-public `requestAnimFrame`
+  //  http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+  requestAnimFrame = (function(){
+    return global.requestAnimationFrame ||
+      global.webkitRequestAnimationFrame ||
+      global.mozRequestAnimationFrame ||
+      global.oRequestAnimationFrame ||
+      global.msRequestAnimationFrame ||
+      function( callback, element ) {
+        global.setTimeout( callback, 16 );
+      };
+  }()),
+
+  refresh = function( obj ) {
+    var currentTime = obj.media.currentTime,
+      animation = obj.options.frameAnimation,
+      disabled = obj.data.disabled,
+      tracks = obj.data.trackEvents,
+      animating = tracks.animating,
+      start = tracks.startIndex,
+      registryByName = Popcorn.registryByName,
+      animIndex = 0,
+      byStart, natives, type;
+
+    start = Math.min( start + 1, tracks.byStart.length - 2 );
+
+    while ( start > 0 && tracks.byStart[ start ] ) {
+
+      byStart = tracks.byStart[ start ];
+      natives = byStart._natives;
+      type = natives && natives.type;
+
+      if ( !natives ||
+          ( !!registryByName[ type ] || !!obj[ type ] ) ) {
+
+        if ( ( byStart.start <= currentTime && byStart.end > currentTime ) &&
+                disabled.indexOf( type ) === -1 ) {
+
+          if ( !byStart._running ) {
+            byStart._running = true;
+            natives.start.call( obj, null, byStart );
+
+            // if the 'frameAnimation' option is used,
+            // push the current byStart object into the `animating` cue
+            if ( animation &&
+                ( byStart && byStart._running && byStart.natives.frame ) ) {
+
+              natives.frame.call( obj, null, byStart, currentTime );
+            }
+          }
+        } else if ( byStart._running === true ) {
+
+          byStart._running = false;
+          natives.end.call( obj, null, byStart );
+
+          if ( animation && byStart._natives.frame ) {
+            animIndex = animating.indexOf( byStart );
+            if ( animIndex >= 0 ) {
+              animating.splice( animIndex, 1 );
+            }
+          }
+        }
+      }
+
+      start--;
+    }
+  },
+
+  //  Declare constructor
+  //  Returns an instance object.
+  Popcorn = function( entity, options ) {
+    //  Return new Popcorn object
+    return new Popcorn.p.init( entity, options || null );
+  };
+
+  //  Popcorn API version, automatically inserted via build system.
+  Popcorn.version = "@VERSION";
+
+  //  Boolean flag allowing a client to determine if Popcorn can be supported
+  Popcorn.isSupported = true;
+
+  //  Instance caching
+  Popcorn.instances = [];
+
+  //  Declare a shortcut (Popcorn.p) to and a definition of
+  //  the new prototype for our Popcorn constructor
+  Popcorn.p = Popcorn.prototype = {
+
+    init: function( entity, options ) {
+
+      var matches;
+
+      //  Supports Popcorn(function () { /../ })
+      //  Originally proposed by Daniel Brooks
+
+      if ( typeof entity === "function" ) {
+
+        //  If document ready has already fired
+        if ( document.readyState === "interactive" || document.readyState === "complete" ) {
+
+          entity( document, Popcorn );
+
+          return;
+        }
+        //  Add `entity` fn to ready stack
+        readyStack.push( entity );
+
+        //  This process should happen once per page load
+        if ( !readyBound ) {
+
+          //  set readyBound flag
+          readyBound = true;
+
+          var DOMContentLoaded  = function() {
+
+            readyFired = true;
+
+            //  Remove global DOM ready listener
+            document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+            //  Execute all ready function in the stack
+            for ( var i = 0, readyStackLength = readyStack.length; i < readyStackLength; i++ ) {
+
+              readyStack[ i ].call( document, Popcorn );
+
+            }
+            //  GC readyStack
+            readyStack = null;
+          };
+
+          //  Register global DOM ready listener
+          document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+        }
+
+        return;
+      }
+
+      //  Check if entity is a valid string id
+      matches = rIdExp.exec( entity );
+
+      //  Get media element by id or object reference
+      this.media = matches && matches.length && matches[ 2 ] ?
+                     document.getElementById( matches[ 2 ] ) :
+                     entity;
+
+      //  Create an audio or video element property reference
+      this[ ( this.media.nodeName && this.media.nodeName.toLowerCase() ) || "video" ] = this.media;
+
+      //  Register new instance
+      Popcorn.instances.push( this );
+
+      this.options = options || {};
+
+      this.isDestroyed = false;
+
+      this.data = {
+
+        // Executed by either timeupdate event or in rAF loop
+        timeUpdate: Popcorn.nop,
+
+        // Allows disabling a plugin per instance
+        disabled: [],
+
+        // Stores DOM event queues by type
+        events: {},
+
+        // Stores Special event hooks data
+        hooks: {},
+
+        // Store track event history data
+        history: [],
+
+        // Stores ad-hoc state related data]
+        state: {
+          volume: this.media.volume
+        },
+
+        // Store track event object references by trackId
+        trackRefs: {},
+
+        // Playback track event queues
+        trackEvents: {
+          byStart: [{
+
+            start: -1,
+            end: -1
+          }],
+          byEnd: [{
+            start: -1,
+            end: -1
+          }],
+          animating: [],
+          startIndex: 0,
+          endIndex: 0,
+          previousUpdateTime: -1
+        }
+      };
+
+      //  Wrap true ready check
+      var isReady = function( that ) {
+
+        var duration, videoDurationPlus;
+
+        if ( that.media.readyState >= 2 ) {
+          //  Adding padding to the front and end of the arrays
+          //  this is so we do not fall off either end
+
+          duration = that.media.duration;
+          //  Check for no duration info (NaN)
+          videoDurationPlus = duration != duration ? Number.MAX_VALUE : duration + 1;
+
+          Popcorn.addTrackEvent( that, {
+            start: videoDurationPlus,
+            end: videoDurationPlus
+          });
+
+          if ( that.options.frameAnimation ) {
+            //  if Popcorn is created with frameAnimation option set to true,
+            //  requestAnimFrame is used instead of "timeupdate" media event.
+            //  This is for greater frame time accuracy, theoretically up to
+            //  60 frames per second as opposed to ~4 ( ~every 15-250ms)
+            that.data.timeUpdate = function () {
+
+              Popcorn.timeUpdate( that, {} );
+
+              that.trigger( "timeupdate" );
+
+              !that.isDestroyed && requestAnimFrame( that.data.timeUpdate );
+            };
+
+            !that.isDestroyed && requestAnimFrame( that.data.timeUpdate );
+
+          } else {
+
+            that.data.timeUpdate = function( event ) {
+              Popcorn.timeUpdate( that, event );
+            };
+
+            if ( !that.isDestroyed ) {
+              that.media.addEventListener( "timeupdate", that.data.timeUpdate, false );
+            }
+          }
+        } else {
+          global.setTimeout(function() {
+            isReady( that );
+          }, 1 );
+        }
+      };
+
+      isReady( this );
+
+      return this;
+    }
+  };
+
+  //  Extend constructor prototype to instance prototype
+  //  Allows chaining methods to instances
+  Popcorn.p.init.prototype = Popcorn.p;
+
+  Popcorn.forEach = function( obj, fn, context ) {
+
+    if ( !obj || !fn ) {
+      return {};
+    }
+
+    context = context || this;
+
+    var key, len;
+
+    // Use native whenever possible
+    if ( forEach && obj.forEach === forEach ) {
+      return obj.forEach( fn, context );
+    }
+
+    if ( toString.call( obj ) === "[object NodeList]" ) {
+      for ( key = 0, len = obj.length; key < len; key++ ) {
+        fn.call( context, obj[ key ], key, obj );
+      }
+      return obj;
+    }
+
+    for ( key in obj ) {
+      if ( hasOwn.call( obj, key ) ) {
+        fn.call( context, obj[ key ], key, obj );
+      }
+    }
+    return obj;
+  };
+
+  Popcorn.extend = function( obj ) {
+    var dest = obj, src = slice.call( arguments, 1 );
+
+    Popcorn.forEach( src, function( copy ) {
+      for ( var prop in copy ) {
+        dest[ prop ] = copy[ prop ];
+      }
+    });
+
+    return dest;
+  };
+
+
+  // A Few reusable utils, memoized onto Popcorn
+  Popcorn.extend( Popcorn, {
+    noConflict: function( deep ) {
+
+      if ( deep ) {
+        global.Popcorn = _Popcorn;
+      }
+
+      return Popcorn;
+    },
+    error: function( msg ) {
+      throw new Error( msg );
+    },
+    guid: function( prefix ) {
+      Popcorn.guid.counter++;
+      return  ( prefix ? prefix : "" ) + ( +new Date() + Popcorn.guid.counter );
+    },
+    sizeOf: function( obj ) {
+      var size = 0;
+
+      for ( var prop in obj ) {
+        size++;
+      }
+
+      return size;
+    },
+    isArray: Array.isArray || function( array ) {
+      return toString.call( array ) === "[object Array]";
+    },
+
+    nop: function() {},
+
+    position: function( elem ) {
+
+      var clientRect = elem.getBoundingClientRect(),
+          bounds = {},
+          doc = elem.ownerDocument,
+          docElem = document.documentElement,
+          body = document.body,
+          clientTop, clientLeft, scrollTop, scrollLeft, top, left;
+
+      //  Determine correct clientTop/Left
+      clientTop = docElem.clientTop || body.clientTop || 0;
+      clientLeft = docElem.clientLeft || body.clientLeft || 0;
+
+      //  Determine correct scrollTop/Left
+      scrollTop = ( global.pageYOffset && docElem.scrollTop || body.scrollTop );
+      scrollLeft = ( global.pageXOffset && docElem.scrollLeft || body.scrollLeft );
+
+      //  Temp top/left
+      top = Math.ceil( clientRect.top + scrollTop - clientTop );
+      left = Math.ceil( clientRect.left + scrollLeft - clientLeft );
+
+      for ( var p in clientRect ) {
+        bounds[ p ] = Math.round( clientRect[ p ] );
+      }
+
+      return Popcorn.extend({}, bounds, { top: top, left: left });
+    },
+
+    disable: function( instance, plugin ) {
+
+      var disabled = instance.data.disabled;
+
+      if ( disabled.indexOf( plugin ) === -1 ) {
+        disabled.push( plugin );
+      }
+
+      refresh( instance );
+
+      return instance;
+    },
+    enable: function( instance, plugin ) {
+
+      var disabled = instance.data.disabled,
+          index = disabled.indexOf( plugin );
+
+      if ( index > -1 ) {
+        disabled.splice( index, 1 );
+      }
+
+      refresh( instance );
+
+      return instance;
+    },
+    destroy: function( instance ) {
+      var events = instance.data.events,
+          singleEvent, item, fn;
+
+      //  Iterate through all events and remove them
+      for ( item in events ) {
+        singleEvent = events[ item ];
+        for ( fn in singleEvent ) {
+          delete singleEvent[ fn ];
+        }
+        events[ item ] = null;
+      }
+
+      if ( !instance.isDestroyed ) {
+        instance.data.timeUpdate && instance.media.removeEventListener( "timeupdate", instance.data.timeUpdate, false );
+        instance.isDestroyed = true;
+      }
+    }
+  });
+
+  //  Memoized GUID Counter
+  Popcorn.guid.counter = 1;
+
+  //  Factory to implement getters, setters and controllers
+  //  as Popcorn instance methods. The IIFE will create and return
+  //  an object with defined methods
+  Popcorn.extend(Popcorn.p, (function() {
+
+      var methods = "load play pause currentTime playbackRate volume duration preload playbackRate " +
+                    "autoplay loop controls muted buffered readyState seeking paused played seekable ended",
+          ret = {};
+
+
+      //  Build methods, store in object that is returned and passed to extend
+      Popcorn.forEach( methods.split( /\s+/g ), function( name ) {
+
+        ret[ name ] = function( arg ) {
+
+          if ( typeof this.media[ name ] === "function" ) {
+
+            // Support for shorthanded play(n)/pause(n) jump to currentTime
+            // If arg is not null or undefined and called by one of the
+            // allowed shorthandable methods, then set the currentTime
+            // Supports time as seconds or SMPTE
+            if ( arg != null && /play|pause/.test( name ) ) {
+              this.media.currentTime = Popcorn.util.toSeconds( arg );
+            }
+
+            this.media[ name ]();
+
+            return this;
+          }
+
+
+          if ( arg != null ) {
+
+            this.media[ name ] = arg;
+
+            return this;
+          }
+
+          return this.media[ name ];
+        };
+      });
+
+      return ret;
+
+    })()
+  );
+
+  Popcorn.forEach( "enable disable".split(" "), function( method ) {
+    Popcorn.p[ method ] = function( plugin ) {
+      return Popcorn[ method ]( this, plugin );
+    };
+  });
+
+  Popcorn.extend(Popcorn.p, {
+
+    //  Rounded currentTime
+    roundTime: function() {
+      return -~this.media.currentTime;
+    },
+
+    //  Attach an event to a single point in time
+    exec: function( time, fn ) {
+
+      //  Creating a one second track event with an empty end
+      Popcorn.addTrackEvent( this, {
+        start: time,
+        end: time + 1,
+        _running: false,
+        _natives: {
+          start: fn || Popcorn.nop,
+          end: Popcorn.nop,
+          type: "exec"
+        }
+      });
+
+      return this;
+    },
+
+    // Mute the calling media, optionally toggle
+    mute: function( toggle ) {
+
+      var event = toggle == null || toggle === true ? "muted" : "unmuted";
+
+      // If `toggle` is explicitly `false`,
+      // unmute the media and restore the volume level
+      if ( event === "unmuted" ) {
+        this.media.muted = false;
+        this.media.volume = this.data.state.volume;
+      }
+
+      // If `toggle` is either null or undefined,
+      // save the current volume and mute the media element
+      if ( event === "muted" ) {
+        this.data.state.volume = this.media.volume;
+        this.media.muted = true;
+      }
+
+      // Trigger either muted|unmuted event
+      this.trigger( event );
+
+      return this;
+    },
+
+    // Convenience method, unmute the calling media
+    unmute: function( toggle ) {
+
+      return this.mute( toggle == null ? false : !toggle );
+    },
+
+    // Get the client bounding box of an instance element
+    position: function() {
+      return Popcorn.position( this.media );
+    },
+
+    // Toggle a plugin's playback behaviour (on or off) per instance
+    toggle: function( plugin ) {
+      return Popcorn[ this.data.disabled.indexOf( plugin ) > -1 ? "enable" : "disable" ]( this, plugin );
+    },
+
+    // Set default values for plugin options objects per instance
+    defaults: function( plugin, defaults ) {
+
+      // If an array of default configurations is provided,
+      // iterate and apply each to this instance
+      if ( Popcorn.isArray( plugin ) ) {
+
+        Popcorn.forEach( plugin, function( obj ) {
+          for ( var name in obj ) {
+            this.defaults( name, obj[ name ] );
+          }
+        }, this );
+
+        return this;
+      }
+
+      if ( !this.options.defaults ) {
+        this.options.defaults = {};
+      }
+
+      if ( !this.options.defaults[ plugin ] ) {
+        this.options.defaults[ plugin ] = {};
+      }
+
+      Popcorn.extend( this.options.defaults[ plugin ], defaults );
+
+      return this;
+    }
+  });
+
+  Popcorn.Events  = {
+    UIEvents: "blur focus focusin focusout load resize scroll unload",
+    MouseEvents: "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave click dblclick",
+    Events: "loadstart progress suspend emptied stalled play pause " +
+            "loadedmetadata loadeddata waiting playing canplay canplaythrough " +
+            "seeking seeked timeupdate ended ratechange durationchange volumechange"
+  };
+
+  Popcorn.Events.Natives = Popcorn.Events.UIEvents + " " +
+                           Popcorn.Events.MouseEvents + " " +
+                           Popcorn.Events.Events;
+
+  internal.events.apiTypes = [ "UIEvents", "MouseEvents", "Events" ];
+
+  // Privately compile events table at load time
+  (function( events, data ) {
+
+    var apis = internal.events.apiTypes,
+    eventsList = events.Natives.split( /\s+/g ),
+    idx = 0, len = eventsList.length, prop;
+
+    for( ; idx < len; idx++ ) {
+      data.hash[ eventsList[idx] ] = true;
+    }
+
+    apis.forEach(function( val, idx ) {
+
+      data.apis[ val ] = {};
+
+      var apiEvents = events[ val ].split( /\s+/g ),
+      len = apiEvents.length,
+      k = 0;
+
+      for ( ; k < len; k++ ) {
+        data.apis[ val ][ apiEvents[ k ] ] = true;
+      }
+    });
+  })( Popcorn.Events, internal.events );
+
+  Popcorn.events = {
+
+    isNative: function( type ) {
+      return !!internal.events.hash[ type ];
+    },
+    getInterface: function( type ) {
+
+      if ( !Popcorn.events.isNative( type ) ) {
+        return false;
+      }
+
+      var eventApi = internal.events,
+        apis = eventApi.apiTypes,
+        apihash = eventApi.apis,
+        idx = 0, len = apis.length, api, tmp;
+
+      for ( ; idx < len; idx++ ) {
+        tmp = apis[ idx ];
+
+        if ( apihash[ tmp ][ type ] ) {
+          api = tmp;
+          break;
+        }
+      }
+      return api;
+    },
+    //  Compile all native events to single array
+    all: Popcorn.Events.Natives.split( /\s+/g ),
+    //  Defines all Event handling static functions
+    fn: {
+      trigger: function( type, data ) {
+
+        var eventInterface, evt;
+        //  setup checks for custom event system
+        if ( this.data.events[ type ] && Popcorn.sizeOf( this.data.events[ type ] ) ) {
+
+          eventInterface  = Popcorn.events.getInterface( type );
+
+          if ( eventInterface ) {
+
+            evt = document.createEvent( eventInterface );
+            evt.initEvent( type, true, true, global, 1 );
+
+            this.media.dispatchEvent( evt );
+
+            return this;
+          }
+
+          //  Custom events
+          Popcorn.forEach( this.data.events[ type ], function( obj, key ) {
+
+            obj.call( this, data );
+
+          }, this );
+
+        }
+
+        return this;
+      },
+      listen: function( type, fn ) {
+
+        var self = this,
+            hasEvents = true,
+            eventHook = Popcorn.events.hooks[ type ],
+            origType = type,
+            tmp;
+
+        if ( !this.data.events[ type ] ) {
+          this.data.events[ type ] = {};
+          hasEvents = false;
+        }
+
+        // Check and setup event hooks
+        if ( eventHook ) {
+
+          // Execute hook add method if defined
+          if ( eventHook.add ) {
+            eventHook.add.call( this, {}, fn );
+          }
+
+          // Reassign event type to our piggyback event type if defined
+          if ( eventHook.bind ) {
+            type = eventHook.bind;
+          }
+
+          // Reassign handler if defined
+          if ( eventHook.handler ) {
+            tmp = fn;
+
+            fn = function wrapper( event ) {
+              eventHook.handler.call( self, event, tmp );
+            };
+          }
+
+          // assume the piggy back event is registered
+          hasEvents = true;
+
+          // Setup event registry entry
+          if ( !this.data.events[ type ] ) {
+            this.data.events[ type ] = {};
+            // Toggle if the previous assumption was untrue
+            hasEvents = false;
+          }
+        }
+
+        //  Register event and handler
+        this.data.events[ type ][ fn.name || ( fn.toString() + Popcorn.guid() ) ] = fn;
+
+        // only attach one event of any type
+        if ( !hasEvents && Popcorn.events.all.indexOf( type ) > -1 ) {
+
+          this.media.addEventListener( type, function( event ) {
+
+            Popcorn.forEach( self.data.events[ type ], function( obj, key ) {
+              if ( typeof obj === "function" ) {
+                obj.call( self, event );
+              }
+            });
+
+          }, false);
+        }
+        return this;
+      },
+      unlisten: function( type, fn ) {
+
+        if ( this.data.events[ type ] && this.data.events[ type ][ fn ] ) {
+
+          delete this.data.events[ type ][ fn ];
+
+          return this;
+        }
+
+        this.data.events[ type ] = null;
+
+        return this;
+      }
+    },
+    hooks: {
+      canplayall: {
+        bind: "canplaythrough",
+        add: function( event, callback ) {
+
+          var state = false;
+
+          if ( this.media.readyState ) {
+
+            callback.call( this, event );
+
+            state = true;
+          }
+
+          this.data.hooks.canplayall = {
+            fired: state
+          };
+        },
+        // declare special handling instructions
+        handler: function canplayall( event, callback ) {
+
+          if ( !this.data.hooks.canplayall.fired ) {
+            // trigger original user callback once
+            callback.call( this, event );
+
+            this.data.hooks.canplayall.fired = true;
+          }
+        }
+      }
+    }
+  };
+
+  //  Extend Popcorn.events.fns (listen, unlisten, trigger) to all Popcorn instances
+  Popcorn.forEach( [ "trigger", "listen", "unlisten" ], function( key ) {
+    Popcorn.p[ key ] = Popcorn.events.fn[ key ];
+  });
+
+  // Internal Only - Adds track events to the instance object
+  Popcorn.addTrackEvent = function( obj, track ) {
+
+    // Determine if this track has default options set for it
+    // If so, apply them to the track object
+    if ( track && track._natives && track._natives.type &&
+        ( obj.options.defaults && obj.options.defaults[ track._natives.type ] ) ) {
+
+      track = Popcorn.extend( {}, obj.options.defaults[ track._natives.type ], track );
+    }
+
+    if ( track._natives ) {
+      //  Supports user defined track event id
+      track._id = !track.id ? Popcorn.guid( track._natives.type ) : track.id;
+
+      //  Push track event ids into the history
+      obj.data.history.push( track._id );
+    }
+
+    track.start = Popcorn.util.toSeconds( track.start, obj.options.framerate );
+    track.end   = Popcorn.util.toSeconds( track.end, obj.options.framerate );
+
+    //  Store this definition in an array sorted by times
+    var byStart = obj.data.trackEvents.byStart,
+        byEnd = obj.data.trackEvents.byEnd,
+        startIndex, endIndex,
+        currentTime;
+
+    for ( startIndex = byStart.length - 1; startIndex >= 0; startIndex-- ) {
+
+      if ( track.start >= byStart[ startIndex ].start ) {
+        byStart.splice( startIndex + 1, 0, track );
+        break;
+      }
+    }
+
+    for ( endIndex = byEnd.length - 1; endIndex >= 0; endIndex-- ) {
+
+      if ( track.end > byEnd[ endIndex ].end ) {
+        byEnd.splice( endIndex + 1, 0, track );
+        break;
+      }
+    }
+
+    // Display track event immediately if it's enabled and current
+    if ( track._natives &&
+        ( !!Popcorn.registryByName[ track._natives.type ] || !!obj[ track._natives.type ] ) ) {
+
+      currentTime = obj.media.currentTime;
+      if ( track.end > currentTime &&
+        track.start <= currentTime &&
+        obj.data.disabled.indexOf( track._natives.type ) === -1 ) {
+
+        track._running = true;
+        track._natives.start.call( obj, null, track );
+
+        if ( obj.options.frameAnimation &&
+          track._natives.frame ) {
+
+          obj.data.trackEvents.animating.push( track );
+          track._natives.frame.call( obj, null, track, currentTime );
+        }
+      }
+    }
+
+    // update startIndex and endIndex
+    if ( startIndex <= obj.data.trackEvents.startIndex &&
+      track.start <= obj.data.trackEvents.previousUpdateTime ) {
+
+      obj.data.trackEvents.startIndex++;
+    }
+
+    if ( endIndex <= obj.data.trackEvents.endIndex &&
+      track.end < obj.data.trackEvents.previousUpdateTime ) {
+
+      obj.data.trackEvents.endIndex++;
+    }
+
+    this.timeUpdate( obj, null, true );
+
+    // Store references to user added trackevents in ref table
+    if ( track._id ) {
+      Popcorn.addTrackEvent.ref( obj, track );
+    }
+  };
+
+  // Internal Only - Adds track event references to the instance object's trackRefs hash table
+  Popcorn.addTrackEvent.ref = function( obj, track ) {
+    obj.data.trackRefs[ track._id ] = track;
+
+    return obj;
+  };
+
+  Popcorn.removeTrackEvent  = function( obj, trackId ) {
+
+    var historyLen = obj.data.history.length,
+        indexWasAt = 0,
+        byStart = [],
+        byEnd = [],
+        animating = [],
+        history = [];
+
+    Popcorn.forEach( obj.data.trackEvents.byStart, function( o, i, context ) {
+      // Preserve the original start/end trackEvents
+      if ( !o._id ) {
+        byStart.push( obj.data.trackEvents.byStart[i] );
+        byEnd.push( obj.data.trackEvents.byEnd[i] );
+      }
+
+      // Filter for user track events (vs system track events)
+      if ( o._id ) {
+
+        // Filter for the trackevent to remove
+        if ( o._id !== trackId ) {
+          byStart.push( obj.data.trackEvents.byStart[i] );
+          byEnd.push( obj.data.trackEvents.byEnd[i] );
+        }
+
+        //  Capture the position of the track being removed.
+        if ( o._id === trackId ) {
+          indexWasAt = i;
+          o._natives._teardown && o._natives._teardown.call( obj, o );
+        }
+      }
+
+    });
+
+    if ( obj.data.trackEvents.animating.length ) {
+      Popcorn.forEach( obj.data.trackEvents.animating, function( o, i, context ) {
+        // Preserve the original start/end trackEvents
+        if ( !o._id ) {
+          animating.push( obj.data.trackEvents.animating[i] );
+        }
+
+        // Filter for user track events (vs system track events)
+        if ( o._id ) {
+          // Filter for the trackevent to remove
+          if ( o._id !== trackId ) {
+            animating.push( obj.data.trackEvents.animating[i] );
+          }
+        }
+      });
+    }
+
+    //  Update
+    if ( indexWasAt <= obj.data.trackEvents.startIndex ) {
+      obj.data.trackEvents.startIndex--;
+    }
+
+    if ( indexWasAt <= obj.data.trackEvents.endIndex ) {
+      obj.data.trackEvents.endIndex--;
+    }
+
+    obj.data.trackEvents.byStart = byStart;
+    obj.data.trackEvents.byEnd = byEnd;
+    obj.data.trackEvents.animating = animating;
+
+    for ( var i = 0; i < historyLen; i++ ) {
+      if ( obj.data.history[ i ] !== trackId ) {
+        history.push( obj.data.history[ i ] );
+      }
+    }
+
+    // Update ordered history array
+    obj.data.history = history;
+
+    // Update track event references
+    Popcorn.removeTrackEvent.ref( obj, trackId );
+  };
+
+  // Internal Only - Removes track event references from instance object's trackRefs hash table
+  Popcorn.removeTrackEvent.ref = function( obj, trackId ) {
+    delete obj.data.trackRefs[ trackId ];
+
+    return obj;
+  };
+
+  // Return an array of track events bound to this instance object
+  Popcorn.getTrackEvents = function( obj ) {
+
+    var trackevents = [],
+      refs = obj.data.trackEvents.byStart,
+      length = refs.length,
+      idx = 0,
+      ref;
+
+    for ( ; idx < length; idx++ ) {
+      ref = refs[ idx ];
+      // Return only user attributed track event references
+      if ( ref._id ) {
+        trackevents.push( ref );
+      }
+    }
+
+    return trackevents;
+  };
+
+  // Internal Only - Returns an instance object's trackRefs hash table
+  Popcorn.getTrackEvents.ref = function( obj ) {
+    return obj.data.trackRefs;
+  };
+
+  // Return a single track event bound to this instance object
+  Popcorn.getTrackEvent = function( obj, trackId ) {
+    return obj.data.trackRefs[ trackId ];
+  };
+
+  // Internal Only - Returns an instance object's track reference by track id
+  Popcorn.getTrackEvent.ref = function( obj, trackId ) {
+    return obj.data.trackRefs[ trackId ];
+  };
+
+  Popcorn.getLastTrackEventId = function( obj ) {
+    return obj.data.history[ obj.data.history.length - 1 ];
+  };
+
+  Popcorn.timeUpdate = function( obj, event ) {
+
+    var currentTime = obj.media.currentTime,
+        previousTime = obj.data.trackEvents.previousUpdateTime,
+        tracks = obj.data.trackEvents,
+        animating = tracks.animating,
+        end = tracks.endIndex,
+        start = tracks.startIndex,
+        animIndex = 0,
+
+        registryByName = Popcorn.registryByName,
+
+        byEnd, byStart, byAnimate, natives, type;
+
+    //  Playbar advancing
+    if ( previousTime <= currentTime ) {
+
+      while ( tracks.byEnd[ end ] && tracks.byEnd[ end ].end <= currentTime ) {
+
+        byEnd = tracks.byEnd[ end ];
+        natives = byEnd._natives;
+        type = natives && natives.type;
+
+        //  If plugin does not exist on this instance, remove it
+        if ( !natives ||
+            ( !!registryByName[ type ] ||
+              !!obj[ type ] ) ) {
+
+          if ( byEnd._running === true ) {
+            byEnd._running = false;
+            natives.end.call( obj, event, byEnd );
+          }
+
+          end++;
+        } else {
+          // remove track event
+          Popcorn.removeTrackEvent( obj, byEnd._id );
+          return;
+        }
+      }
+
+      while ( tracks.byStart[ start ] && tracks.byStart[ start ].start <= currentTime ) {
+
+        byStart = tracks.byStart[ start ];
+        natives = byStart._natives;
+        type = natives && natives.type;
+
+        //  If plugin does not exist on this instance, remove it
+        if ( !natives ||
+            ( !!registryByName[ type ] ||
+              !!obj[ type ] ) ) {
+
+          if ( byStart.end > currentTime &&
+                byStart._running === false &&
+                  obj.data.disabled.indexOf( type ) === -1 ) {
+
+            byStart._running = true;
+            natives.start.call( obj, event, byStart );
+
+            // If the `frameAnimation` option is used,
+            // push the current byStart object into the `animating` cue
+            if ( obj.options.frameAnimation &&
+                ( byStart && byStart._running && byStart._natives.frame ) ) {
+
+              animating.push( byStart );
+            }
+          }
+          start++;
+        } else {
+          // remove track event
+          Popcorn.removeTrackEvent( obj, byStart._id );
+          return;
+        }
+      }
+
+      // If the `frameAnimation` option is used, iterate the animating track
+      // and execute the `frame` callback
+      if ( obj.options.frameAnimation ) {
+        while ( animIndex < animating.length ) {
+
+          byAnimate = animating[ animIndex ];
+
+          if ( !byAnimate._running ) {
+            animating.splice( animIndex, 1 );
+          } else {
+            byAnimate._natives.frame.call( obj, event, byAnimate, currentTime );
+            animIndex++;
+          }
+        }
+      }
+
+    // Playbar receding
+    } else if ( previousTime > currentTime ) {
+
+      while ( tracks.byStart[ start ] && tracks.byStart[ start ].start > currentTime ) {
+
+        byStart = tracks.byStart[ start ];
+        natives = byStart._natives;
+        type = natives && natives.type;
+
+        // if plugin does not exist on this instance, remove it
+        if ( !natives ||
+            ( !!registryByName[ type ] ||
+              !!obj[ type ] ) ) {
+
+          if ( byStart._running === true ) {
+            byStart._running = false;
+            natives.end.call( obj, event, byStart );
+          }
+          start--;
+        } else {
+          // remove track event
+          Popcorn.removeTrackEvent( obj, byStart._id );
+          return;
+        }
+      }
+
+      while ( tracks.byEnd[ end ] && tracks.byEnd[ end ].end > currentTime ) {
+
+        byEnd = tracks.byEnd[ end ];
+        natives = byEnd._natives;
+        type = natives && natives.type;
+
+        // if plugin does not exist on this instance, remove it
+        if ( !natives ||
+            ( !!registryByName[ type ] ||
+              !!obj[ type ] ) ) {
+
+          if ( byEnd.start <= currentTime &&
+                byEnd._running === false  &&
+                  obj.data.disabled.indexOf( type ) === -1 ) {
+
+            byEnd._running = true;
+            natives.start.call( obj, event, byEnd );
+
+            // If the `frameAnimation` option is used,
+            // push the current byEnd object into the `animating` cue
+            if ( obj.options.frameAnimation &&
+                  ( byEnd && byEnd._running && byEnd._natives.frame ) ) {
+
+              animating.push( byEnd );
+            }
+          }
+          end--;
+        } else {
+          // remove track event
+          Popcorn.removeTrackEvent( obj, byEnd._id );
+          return;
+        }
+      }
+
+      // If the `frameAnimation` option is used, iterate the animating track
+      // and execute the `frame` callback
+      if ( obj.options.frameAnimation ) {
+        while ( animIndex < animating.length ) {
+
+          byAnimate = animating[ animIndex ];
+
+          if ( !byAnimate._running ) {
+            animating.splice( animIndex, 1 );
+          } else {
+            byAnimate._natives.frame.call( obj, event, byAnimate, currentTime );
+            animIndex++;
+          }
+        }
+      }
+    // time bar is not moving ( video is paused )
+    }
+
+    tracks.endIndex = end;
+    tracks.startIndex = start;
+    tracks.previousUpdateTime = currentTime;
+  };
+
+  //  Map and Extend TrackEvent functions to all Popcorn instances
+  Popcorn.extend( Popcorn.p, {
+
+    getTrackEvents: function() {
+      return Popcorn.getTrackEvents.call( null, this );
+    },
+
+    getTrackEvent: function( id ) {
+      return Popcorn.getTrackEvent.call( null, this, id );
+    },
+
+    getLastTrackEventId: function() {
+      return Popcorn.getLastTrackEventId.call( null, this );
+    },
+
+    removeTrackEvent: function( id ) {
+
+      Popcorn.removeTrackEvent.call( null, this, id );
+      return this;
+    },
+
+    removePlugin: function( name ) {
+      Popcorn.removePlugin.call( null, this, name );
+      return this;
+    },
+
+    timeUpdate: function( event ) {
+      Popcorn.timeUpdate.call( null, this, event );
+      return this;
+    },
+
+    destroy: function() {
+      Popcorn.destroy.call( null, this );
+      return this;
+    }
+  });
+
+  //  Plugin manifests
+  Popcorn.manifest = {};
+  //  Plugins are registered
+  Popcorn.registry = [];
+  Popcorn.registryByName = {};
+  //  An interface for extending Popcorn
+  //  with plugin functionality
+  Popcorn.plugin = function( name, definition, manifest ) {
+
+    if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) {
+      Popcorn.error( "'" + name + "' is a protected function name" );
+      return;
+    }
+
+    //  Provides some sugar, but ultimately extends
+    //  the definition into Popcorn.p
+    var reserved = [ "start", "end" ],
+        plugin = {},
+        setup,
+        isfn = typeof definition === "function",
+        methods = [ "_setup", "_teardown", "start", "end", "frame" ];
+
+    // combines calls of two function calls into one
+    var combineFn = function( first, second ) {
+
+      first = first || Popcorn.nop;
+      second = second || Popcorn.nop;
+
+      return function() {
+        first.apply( this, arguments );
+        second.apply( this, arguments );
+      };
+    };
+
+    //  If `manifest` arg is undefined, check for manifest within the `definition` object
+    //  If no `definition.manifest`, an empty object is a sufficient fallback
+    Popcorn.manifest[ name ] = manifest = manifest || definition.manifest || {};
+
+    // apply safe, and empty default functions
+    methods.forEach(function( method ) {
+      definition[ method ] = safeTry( definition[ method ] || Popcorn.nop, name );
+    });
+
+    var pluginFn = function( setup, options ) {
+
+      if ( !options ) {
+        return this;
+      }
+
+      //  Storing the plugin natives
+      var natives = options._natives = {},
+          compose = "",
+          defaults, originalOpts, manifestOpts, mergedSetupOpts;
+
+      Popcorn.extend( natives, setup );
+
+      options._natives.type = name;
+      options._running = false;
+
+      natives.start = natives.start || natives[ "in" ];
+      natives.end = natives.end || natives[ "out" ];
+
+      // extend teardown to always call end if running
+      natives._teardown = combineFn(function() {
+
+        var args = slice.call( arguments );
+
+        // end function signature is not the same as teardown,
+        // put null on the front of arguments for the event parameter
+        args.unshift( null );
+
+        // only call end if event is running
+        args[ 1 ]._running && natives.end.apply( this, args );
+      }, natives._teardown );
+
+      // Check for previously set default options
+      defaults = this.options.defaults && this.options.defaults[ options._natives && options._natives.type ];
+
+      // default to an empty string if no effect exists
+      // split string into an array of effects
+      options.compose = options.compose && options.compose.split( " " ) || [];
+      options.effect = options.effect && options.effect.split( " " ) || [];
+
+      // join the two arrays together
+      options.compose = options.compose.concat( options.effect );
+
+      options.compose.forEach(function( composeOption ) {
+
+        // if the requested compose is garbage, throw it away
+        compose = Popcorn.compositions[ composeOption ] || {};
+
+        // extends previous functions with compose function
+        methods.forEach(function( method ) {
+          natives[ method ] = combineFn( natives[ method ], compose[ method ] );
+        });
+      });
+
+      //  Ensure a manifest object, an empty object is a sufficient fallback
+      options._natives.manifest = manifest;
+
+      //  Checks for expected properties
+      if ( !( "start" in options ) ) {
+        options.start = options[ "in" ] || 0;
+      }
+
+      if ( !( "end" in options ) ) {
+        options.end = options[ "out" ] || this.duration() || Number.MAX_VALUE;
+      }
+
+      // Merge with defaults if they exist, make sure per call is prioritized
+      mergedSetupOpts = defaults ? Popcorn.extend( {}, defaults, options ) :
+                          options;
+
+      // Resolves 239, 241, 242
+      if ( !mergedSetupOpts.target ) {
+
+        //  Sometimes the manifest may be missing entirely
+        //  or it has an options object that doesn't have a `target` property
+        manifestOpts = "options" in manifest && manifest.options;
+
+        mergedSetupOpts.target = manifestOpts && "target" in manifestOpts && manifestOpts.target;
+      }
+
+      // Trigger _setup method if exists
+      options._natives._setup && options._natives._setup.call( this, mergedSetupOpts );
+
+      // Create new track event for this instance
+      Popcorn.addTrackEvent( this, Popcorn.extend( mergedSetupOpts, options ) );
+
+      //  Future support for plugin event definitions
+      //  for all of the native events
+      Popcorn.forEach( setup, function( callback, type ) {
+
+        if ( type !== "type" ) {
+
+          if ( reserved.indexOf( type ) === -1 ) {
+
+            this.listen( type, callback );
+          }
+        }
+
+      }, this );
+
+      return this;
+    };
+
+    //  Assign new named definition
+    plugin[ name ] = function( options ) {
+      return pluginFn.call( this, isfn ? definition.call( this, options ) : definition,
+                                  options );
+    };
+
+    //  Extend Popcorn.p with new named definition
+    Popcorn.extend( Popcorn.p, plugin );
+
+    //  Push into the registry
+    var entry = {
+      fn: plugin[ name ],
+      definition: definition,
+      base: definition,
+      parents: [],
+      name: name
+    };
+    Popcorn.registry.push(
+       Popcorn.extend( plugin, entry, {
+        type: name
+      })
+    );
+    Popcorn.registryByName[ name ] = entry;
+
+    return plugin;
+  };
+
+  // Storage for plugin function errors
+  Popcorn.plugin.errors = [];
+
+  // Returns wrapped plugin function
+  function safeTry( fn, pluginName ) {
+    return function() {
+
+      //  When Popcorn.plugin.debug is true, do not suppress errors
+      if ( Popcorn.plugin.debug ) {
+        return fn.apply( this, arguments );
+      }
+
+      try {
+        return fn.apply( this, arguments );
+      } catch ( ex ) {
+
+        // Push plugin function errors into logging queue
+        Popcorn.plugin.errors.push({
+          plugin: pluginName,
+          thrown: ex,
+          source: fn.toString()
+        });
+
+        // Trigger an error that the instance can listen for
+        // and react to
+        this.trigger( "error", Popcorn.plugin.errors );
+      }
+    };
+  }
+
+  // Debug-mode flag for plugin development
+  Popcorn.plugin.debug = false;
+
+  //  removePlugin( type ) removes all tracks of that from all instances of popcorn
+  //  removePlugin( obj, type ) removes all tracks of type from obj, where obj is a single instance of popcorn
+  Popcorn.removePlugin = function( obj, name ) {
+
+    //  Check if we are removing plugin from an instance or from all of Popcorn
+    if ( !name ) {
+
+      //  Fix the order
+      name = obj;
+      obj = Popcorn.p;
+
+      if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) {
+        Popcorn.error( "'" + name + "' is a protected function name" );
+        return;
+      }
+
+      var registryLen = Popcorn.registry.length,
+          registryIdx;
+
+      // remove plugin reference from registry
+      for ( registryIdx = 0; registryIdx < registryLen; registryIdx++ ) {
+        if ( Popcorn.registry[ registryIdx ].name === name ) {
+          Popcorn.registry.splice( registryIdx, 1 );
+          delete Popcorn.registryByName[ name ];
+          delete Popcorn.manifest[ name ];
+
+          // delete the plugin
+          delete obj[ name ];
+
+          // plugin found and removed, stop checking, we are done
+          return;
+        }
+      }
+
+    }
+
+    var byStart = obj.data.trackEvents.byStart,
+        byEnd = obj.data.trackEvents.byEnd,
+        animating = obj.data.trackEvents.animating,
+        idx, sl;
+
+    // remove all trackEvents
+    for ( idx = 0, sl = byStart.length; idx < sl; idx++ ) {
+
+      if ( ( byStart[ idx ] && byStart[ idx ]._natives && byStart[ idx ]._natives.type === name ) &&
+                ( byEnd[ idx ] && byEnd[ idx ]._natives && byEnd[ idx ]._natives.type === name ) ) {
+
+        byStart[ idx ]._natives._teardown && byStart[ idx ]._natives._teardown.call( obj, byStart[ idx ] );
+
+        byStart.splice( idx, 1 );
+        byEnd.splice( idx, 1 );
+
+        // update for loop if something removed, but keep checking
+        idx--; sl--;
+        if ( obj.data.trackEvents.startIndex <= idx ) {
+          obj.data.trackEvents.startIndex--;
+          obj.data.trackEvents.endIndex--;
+        }
+      }
+    }
+
+    //remove all animating events
+    for ( idx = 0, sl = animating.length; idx < sl; idx++ ) {
+
+      if ( animating[ idx ] && animating[ idx ]._natives && animating[ idx ]._natives.type === name ) {
+
+        animating.splice( idx, 1 );
+
+        // update for loop if something removed, but keep checking
+        idx--; sl--;
+      }
+    }
+
+  };
+
+  Popcorn.compositions = {};
+
+  //  Plugin inheritance
+  Popcorn.compose = function( name, definition, manifest ) {
+
+    //  If `manifest` arg is undefined, check for manifest within the `definition` object
+    //  If no `definition.manifest`, an empty object is a sufficient fallback
+    Popcorn.manifest[ name ] = manifest = manifest || definition.manifest || {};
+
+    // register the effect by name
+    Popcorn.compositions[ name ] = definition;
+  };
+
+  Popcorn.plugin.effect = Popcorn.effect = Popcorn.compose;
+
+  // stores parsers keyed on filetype
+  Popcorn.parsers = {};
+
+  // An interface for extending Popcorn
+  // with parser functionality
+  Popcorn.parser = function( name, type, definition ) {
+
+    if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) {
+      Popcorn.error( "'" + name + "' is a protected function name" );
+      return;
+    }
+
+    // fixes parameters for overloaded function call
+    if ( typeof type === "function" && !definition ) {
+      definition = type;
+      type = "";
+    }
+
+    if ( typeof definition !== "function" || typeof type !== "string" ) {
+      return;
+    }
+
+    // Provides some sugar, but ultimately extends
+    // the definition into Popcorn.p
+
+    var natives = Popcorn.events.all,
+        parseFn,
+        parser = {};
+
+    parseFn = function( filename, callback ) {
+
+      if ( !filename ) {
+        return this;
+      }
+
+      var that = this;
+
+      Popcorn.xhr({
+        url: filename,
+        dataType: type,
+        success: function( data ) {
+
+          var tracksObject = definition( data ),
+              tracksData,
+              tracksDataLen,
+              tracksDef,
+              idx = 0;
+
+          tracksData = tracksObject.data || [];
+          tracksDataLen = tracksData.length;
+          tracksDef = null;
+
+          //  If no tracks to process, return immediately
+          if ( !tracksDataLen ) {
+            return;
+          }
+
+          //  Create tracks out of parsed object
+          for ( ; idx < tracksDataLen; idx++ ) {
+
+            tracksDef = tracksData[ idx ];
+
+            for ( var key in tracksDef ) {
+
+              if ( hasOwn.call( tracksDef, key ) && !!that[ key ] ) {
+
+                that[ key ]( tracksDef[ key ] );
+              }
+            }
+          }
+          if ( callback ) {
+            callback();
+          }
+        }
+      });
+
+      return this;
+    };
+
+    // Assign new named definition
+    parser[ name ] = parseFn;
+
+    // Extend Popcorn.p with new named definition
+    Popcorn.extend( Popcorn.p, parser );
+
+    // keys the function name by filetype extension
+    //Popcorn.parsers[ name ] = true;
+
+    return parser;
+  };
+
+  Popcorn.player = function( name, player ) {
+
+    player = player || {};
+
+    var playerFn = function( target, src, options ) {
+
+      options = options || {};
+
+      // List of events
+      var date = new Date() / 1000,
+          baselineTime = date,
+          currentTime = 0,
+          volume = 1,
+          muted = false,
+          events = {},
+
+          // The container div of the resource
+          container = document.getElementById( rIdExp.exec( target ) && rIdExp.exec( target )[ 2 ] ) ||
+                        document.getElementById( target ) ||
+                          target,
+          basePlayer = {},
+          timeout,
+          popcorn;
+
+      // copies a div into the media object
+      for( var val in container ) {
+
+        if ( typeof container[ val ] === "object" ) {
+
+          basePlayer[ val ] = container[ val ];
+        } else if ( typeof container[ val ] === "function" ) {
+
+          basePlayer[ val ] = (function( value ) {
+
+            // this is a stupid ugly kludgy hack in honour of Safari
+            // in Safari a NodeList is a function, not an object
+            if ( "length" in container[ value ] && !container[ value ].call ) {
+
+              return container[ value ];
+            } else {
+
+              return function() {
+
+                return container[ value ].apply( container, arguments );
+              };
+            }
+          }( val ));
+        } else {
+
+          Popcorn.player.defineProperty( basePlayer, val, {
+            get: (function( value ) {
+
+              return function() {
+
+                return container[ value ];
+              };
+            }( val )),
+            set: Popcorn.nop,
+            configurable: true
+          });
+        }
+      }
+
+      var timeupdate = function() {
+
+        date = new Date() / 1000;
+
+        if ( !basePlayer.paused ) {
+
+          basePlayer.currentTime = basePlayer.currentTime + ( date - baselineTime );
+          basePlayer.dispatchEvent( "timeupdate" );
+          timeout = setTimeout( timeupdate, 10 );
+        }
+
+        baselineTime = date;
+      };
+
+      basePlayer.play = function() {
+
+        this.paused = false;
+
+        if ( basePlayer.readyState >= 4 ) {
+
+          baselineTime = new Date() / 1000;
+          basePlayer.dispatchEvent( "play" );
+          timeupdate();
+        }
+      };
+
+      basePlayer.pause = function() {
+
+        this.paused = true;
+        basePlayer.dispatchEvent( "pause" );
+      };
+
+      Popcorn.player.defineProperty( basePlayer, "currentTime", {
+        get: function() {
+
+          return currentTime;
+        },
+        set: function( val ) {
+
+          // make sure val is a number
+          currentTime = +val;
+          basePlayer.dispatchEvent( "timeupdate" );
+          return currentTime;
+        },
+        configurable: true
+      });
+
+      Popcorn.player.defineProperty( basePlayer, "volume", {
+        get: function() {
+
+          return volume;
+        },
+        set: function( val ) {
+
+          // make sure val is a number
+          volume = +val;
+          basePlayer.dispatchEvent( "volumechange" );
+          return volume;
+        },
+        configurable: true
+      });
+
+      Popcorn.player.defineProperty( basePlayer, "muted", {
+        get: function() {
+
+          return muted;
+        },
+        set: function( val ) {
+
+          // make sure val is a number
+          muted = +val;
+          basePlayer.dispatchEvent( "volumechange" );
+          return muted;
+        },
+        configurable: true
+      });
+
+      // Adds an event listener to the object
+      basePlayer.addEventListener = function( evtName, fn ) {
+
+        if ( !events[ evtName ] ) {
+
+          events[ evtName ] = [];
+        }
+
+        events[ evtName ].push( fn );
+        return fn;
+      };
+
+      // Can take event object or simple string
+      basePlayer.dispatchEvent = function( oEvent ) {
+
+        var evt,
+            self = this,
+            eventInterface,
+            eventName = oEvent.type;
+
+        // A string was passed, create event object
+        if ( !eventName ) {
+
+          eventName = oEvent;
+          eventInterface  = Popcorn.events.getInterface( eventName );
+
+          if ( eventInterface ) {
+
+            evt = document.createEvent( eventInterface );
+            evt.initEvent( eventName, true, true, window, 1 );
+          }
+        }
+
+        Popcorn.forEach( events[ eventName ], function( val ) {
+
+          val.call( self, evt, self );
+        });
+      };
+
+      // Attempt to get src from playerFn parameter
+      basePlayer.src = src || "";
+      basePlayer.readyState = 0;
+      basePlayer.duration = 0;
+      basePlayer.paused = true;
+      basePlayer.ended = 0;
+
+      if ( player._setup ) {
+
+        player._setup.call( basePlayer, options );
+      } else {
+
+        // there is no setup, which means there is nothing to load
+        basePlayer.readyState = 4;
+        basePlayer.dispatchEvent( "load" );
+        basePlayer.dispatchEvent( "loadeddata" );
+      }
+
+      // when a custom player is loaded, load basePlayer state into custom player
+      basePlayer.addEventListener( "load", function() {
+
+        // if a player is not ready before currentTime is called, this will set it after it is ready
+        basePlayer.currentTime = currentTime;
+
+        // same as above with volume and muted
+        basePlayer.volume = volume;
+        basePlayer.muted = muted;
+      });
+
+      basePlayer.addEventListener( "loadeddata", function() {
+
+        // if play was called before player ready, start playing video
+        !basePlayer.paused && basePlayer.play();
+      });
+
+      popcorn = new Popcorn.p.init( basePlayer, options );
+
+      return popcorn;
+    };
+
+    Popcorn[ name ] = Popcorn[ name ] || playerFn;
+  };
+
+  Popcorn.player.defineProperty = Object.defineProperty || function( object, description, options ) {
+
+    object.__defineGetter__( description, options.get || Popcorn.nop );
+    object.__defineSetter__( description, options.set || Popcorn.nop );
+  };
+
+  //  Cache references to reused RegExps
+  var rparams = /\?/,
+  //  XHR Setup object
+  setup = {
+    url: "",
+    data: "",
+    dataType: "",
+    success: Popcorn.nop,
+    type: "GET",
+    async: true,
+    xhr: function() {
+      return new global.XMLHttpRequest();
+    }
+  };
+
+  Popcorn.xhr = function( options ) {
+
+    options.dataType = options.dataType && options.dataType.toLowerCase() || null;
+
+    if ( options.dataType &&
+         ( options.dataType === "jsonp" || options.dataType === "script" ) ) {
+
+      Popcorn.xhr.getJSONP(
+        options.url,
+        options.success,
+        options.dataType === "script"
+      );
+      return;
+    }
+
+    var settings = Popcorn.extend( {}, setup, options );
+
+    //  Create new XMLHttpRequest object
+    settings.ajax  = settings.xhr();
+
+    if ( settings.ajax ) {
+
+      if ( settings.type === "GET" && settings.data ) {
+
+        //  append query string
+        settings.url += ( rparams.test( settings.url ) ? "&" : "?" ) + settings.data;
+
+        //  Garbage collect and reset settings.data
+        settings.data = null;
+      }
+
+
+      settings.ajax.open( settings.type, settings.url, settings.async );
+      settings.ajax.send( settings.data || null );
+
+      return Popcorn.xhr.httpData( settings );
+    }
+  };
+
+
+  Popcorn.xhr.httpData = function( settings ) {
+
+    var data, json = null,
+        parser, xml = null;
+
+    settings.ajax.onreadystatechange = function() {
+
+      if ( settings.ajax.readyState === 4 ) {
+
+        try {
+          json = JSON.parse( settings.ajax.responseText );
+        } catch( e ) {
+          //suppress
+        }
+
+        data = {
+          xml: settings.ajax.responseXML,
+          text: settings.ajax.responseText,
+          json: json
+        };
+
+        // Normalize: data.xml is non-null in IE9 regardless of if response is valid xml
+        if ( !data.xml || !data.xml.documentElement ) {
+          data.xml = null;
+
+          try {
+            parser = new DOMParser();
+            xml = parser.parseFromString( settings.ajax.responseText, "text/xml" );
+
+            if ( !xml.getElementsByTagName( "parsererror" ).length ) {
+              data.xml = xml;
+            }
+          } catch ( e ) {
+            // data.xml remains null
+          }
+        }
+
+        //  If a dataType was specified, return that type of data
+        if ( settings.dataType ) {
+          data = data[ settings.dataType ];
+        }
+
+
+        settings.success.call( settings.ajax, data );
+
+      }
+    };
+    return data;
+  };
+
+  Popcorn.xhr.getJSONP = function( url, success, isScript ) {
+
+    var head = document.head || document.getElementsByTagName( "head" )[ 0 ] || document.documentElement,
+      script = document.createElement( "script" ),
+      paramStr = url.split( "?" )[ 1 ],
+      isFired = false,
+      params = [],
+      callback, parts, callparam;
+
+    if ( paramStr && !isScript ) {
+      params = paramStr.split( "&" );
+    }
+
+    if ( params.length ) {
+      parts = params[ params.length - 1 ].split( "=" );
+    }
+
+    callback = params.length ? ( parts[ 1 ] ? parts[ 1 ] : parts[ 0 ]  ) : "jsonp";
+
+    if ( !paramStr && !isScript ) {
+      url += "?callback=" + callback;
+    }
+
+    if ( callback && !isScript ) {
+
+      //  If a callback name already exists
+      if ( !!window[ callback ] ) {
+        //  Create a new unique callback name
+        callback = Popcorn.guid( callback );
+      }
+
+      //  Define the JSONP success callback globally
+      window[ callback ] = function( data ) {
+        // Fire success callbacks
+        success && success( data );
+        isFired = true;
+      };
+
+      //  Replace callback param and callback name
+      url = url.replace( parts.join( "=" ), parts[ 0 ] + "=" + callback );
+    }
+
+    script.onload = function() {
+
+      //  Handling remote script loading callbacks
+      if ( isScript ) {
+        //  getScript
+        success && success();
+      }
+
+      //  Executing for JSONP requests
+      if ( isFired ) {
+        //  Garbage collect the callback
+        delete window[ callback ];
+      }
+      //  Garbage collect the script resource
+      head.removeChild( script );
+    };
+
+    script.src = url;
+
+    head.insertBefore( script, head.firstChild );
+
+    return;
+  };
+
+  Popcorn.getJSONP = Popcorn.xhr.getJSONP;
+
+  Popcorn.getScript = Popcorn.xhr.getScript = function( url, success ) {
+
+    return Popcorn.xhr.getJSONP( url, success, true );
+  };
+
+  Popcorn.util = {
+    // Simple function to parse a timestamp into seconds
+    // Acceptable formats are:
+    // HH:MM:SS.MMM
+    // HH:MM:SS;FF
+    // Hours and minutes are optional. They default to 0
+    toSeconds: function( timeStr, framerate ) {
+      // Hours and minutes are optional
+      // Seconds must be specified
+      // Seconds can be followed by milliseconds OR by the frame information
+      var validTimeFormat = /^([0-9]+:){0,2}[0-9]+([.;][0-9]+)?$/,
+          errorMessage = "Invalid time format",
+          digitPairs, lastIndex, lastPair, firstPair,
+          frameInfo, frameTime;
+
+      if ( typeof timeStr === "number" ) {
+        return timeStr;
+      }
+
+      if ( typeof timeStr === "string" &&
+            !validTimeFormat.test( timeStr ) ) {
+        Popcorn.error( errorMessage );
+      }
+
+      digitPairs = timeStr.split( ":" );
+      lastIndex = digitPairs.length - 1;
+      lastPair = digitPairs[ lastIndex ];
+
+      // Fix last element:
+      if ( lastPair.indexOf( ";" ) > -1 ) {
+
+        frameInfo = lastPair.split( ";" );
+        frameTime = 0;
+
+        if ( framerate && ( typeof framerate === "number" ) ) {
+          frameTime = parseFloat( frameInfo[ 1 ], 10 ) / framerate;
+        }
+
+        digitPairs[ lastIndex ] = parseInt( frameInfo[ 0 ], 10 ) + frameTime;
+      }
+
+      firstPair = digitPairs[ 0 ];
+
+      return {
+
+        1: parseFloat( firstPair, 10 ),
+
+        2: ( parseInt( firstPair, 10 ) * 60 ) +
+              parseFloat( digitPairs[ 1 ], 10 ),
+
+        3: ( parseInt( firstPair, 10 ) * 3600 ) +
+            ( parseInt( digitPairs[ 1 ], 10 ) * 60 ) +
+              parseFloat( digitPairs[ 2 ], 10 )
+
+      }[ digitPairs.length || 1 ];
+    }
+  };
+
+
+  // Initialize locale data
+  // Based on http://en.wikipedia.org/wiki/Language_localisation#Language_tags_and_codes
+  function initLocale( arg ) {
+
+    var locale = typeof arg === "string" ? arg : [ arg.language, arg.region ].join( "-" ),
+        parts = locale.split( "-" );
+
+    // Setup locale data table
+    return {
+      iso6391: locale,
+      language: parts[ 0 ] || "",
+      region: parts[ 1 ] || ""
+    };
+  }
+
+  // Declare locale data table
+  var localeData = initLocale( global.navigator.userLanguage || global.navigator.language );
+
+  Popcorn.locale = {
+
+    // Popcorn.locale.get()
+    // returns reference to privately
+    // defined localeData
+    get: function() {
+      return localeData;
+    },
+
+    // Popcorn.locale.set( string|object );
+    set: function( arg ) {
+
+      localeData = initLocale( arg );
+
+      Popcorn.locale.broadcast();
+
+      return localeData;
+    },
+
+    // Popcorn.locale.broadcast( type )
+    // Sends events to all popcorn media instances that are
+    // listening for locale events
+    broadcast: function( type ) {
+
+      var instances = Popcorn.instances,
+          length = instances.length,
+          idx = 0,
+          instance;
+
+      type = type || "locale:changed";
+
+      // Iterate all current instances
+      for ( ; idx < length; idx++ ) {
+        instance = instances[ idx ];
+
+        // For those instances with locale event listeners,
+        // trigger a locale change event
+        if ( type in instance.data.events  ) {
+          instance.trigger( type );
+        }
+      }
+    }
+  };
+
+  // alias for exec function
+  Popcorn.p.cue = Popcorn.p.exec;
+
+  function getItems() {
+
+    var item,
+        list = [];
+
+    if ( Object.keys ) {
+      list = Object.keys( Popcorn.p );
+    } else {
+
+      for ( item in Popcorn.p ) {
+        if ( hasOwn.call( Popcorn.p, item ) ) {
+          list.push( item );
+        }
+      }
+    }
+
+    return list.join( "," ).toLowerCase().split( ",");
+  }
+
+  //  Protected API methods
+  Popcorn.protect = {
+    natives: getItems()
+  };
+
+  //  Exposes Popcorn to global context
+  global.Popcorn = Popcorn;
+
+})(window, window.document);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/popcorn.youtube.js	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,220 @@
+// A global callback for youtube... that makes me angry
+var onYouTubePlayerReady = function( containerId ) {
+
+  onYouTubePlayerReady[ containerId ] && onYouTubePlayerReady[ containerId ]();
+};
+onYouTubePlayerReady.stateChangeEventHandler = {};
+
+Popcorn.player( "youtube", {
+  _setup: function( options ) {
+
+    var media = this,
+        youtubeObject,
+        container = document.createElement( "div" ),
+        currentTime = 0,
+        seekTime = 0,
+        seeking = false,
+
+        // state code for volume changed polling
+        volumeChanged = false,
+        lastMuted = false,
+        lastVolume = 0;
+
+    container.id = media.id + Popcorn.guid();
+
+    media.appendChild( container );
+
+    var youtubeInit = function() {
+
+      var flashvars,
+          params,
+          attributes,
+          src;
+
+      // expose a callback to this scope, that is called from the global callback youtube calls
+      onYouTubePlayerReady[ container.id ] = function() {
+
+        youtubeObject = document.getElementById( container.id );
+
+        // more youtube callback nonsense
+        onYouTubePlayerReady.stateChangeEventHandler[ container.id ] = function( state ) {
+
+          // playing is state 1
+          // paused is state 2
+          if ( state === 1 ) {
+
+            media.paused && media.play();
+          // youtube fires paused events while seeking
+          // this is the only way to get seeking events
+          } else if ( state === 2 ) {
+
+            // silly logic forced on me by the youtube API
+            // calling youtube.seekTo triggers multiple events
+            // with the second events getCurrentTime being the old time
+            if ( seeking && seekTime === currentTime && seekTime !== youtubeObject.getCurrentTime() ) {
+
+              seeking = false;
+              youtubeObject.seekTo( currentTime );
+              return;
+            }
+
+            currentTime = youtubeObject.getCurrentTime();
+            media.dispatchEvent( "timeupdate" );
+            !media.paused && media.pause();
+          }
+        };
+
+        // youtube requires callbacks to be a string to a function path from the global scope
+        youtubeObject.addEventListener( "onStateChange", "onYouTubePlayerReady.stateChangeEventHandler." + container.id );
+
+        var timeupdate = function() {
+
+          if ( !media.paused ) {
+
+            currentTime = youtubeObject.getCurrentTime();
+            media.dispatchEvent( "timeupdate" );
+            setTimeout( timeupdate, 10 );
+          }
+        };
+
+        var volumeupdate = function() {
+
+          if ( lastMuted !== youtubeObject.isMuted() ) {
+
+            lastMuted = youtubeObject.isMuted();
+            media.dispatchEvent( "volumechange" );
+          }
+
+          if ( lastVolume !== youtubeObject.getVolume() ) {
+
+            lastVolume = youtubeObject.getVolume();
+            media.dispatchEvent( "volumechange" );
+          }
+
+          setTimeout( volumeupdate, 250 );
+        };
+
+        media.play = function() {
+
+          media.paused = false;
+          media.dispatchEvent( "play" );
+
+          media.dispatchEvent( "playing" );
+          timeupdate();
+          youtubeObject.playVideo();
+        };
+
+        media.pause = function() {
+
+          if ( !media.paused ) {
+
+            media.paused = true;
+            media.dispatchEvent( "pause" );
+            youtubeObject.pauseVideo();
+          }
+        };
+
+        Popcorn.player.defineProperty( media, "currentTime", {
+          set: function( val ) {
+
+            // make sure val is a number
+            currentTime = seekTime = +val;
+            seeking = true;
+            media.dispatchEvent( "seeked" );
+            media.dispatchEvent( "timeupdate" );
+            youtubeObject.seekTo( currentTime );
+            return currentTime;
+          },
+          get: function() {
+
+            return currentTime;
+          }
+        });
+
+        Popcorn.player.defineProperty( media, "muted", {
+          set: function( val ) {
+
+            if ( youtubeObject.isMuted() !== val ) {
+
+              if ( val ) {
+
+                youtubeObject.mute();
+              } else {
+
+                youtubeObject.unMute();
+              }
+
+              lastMuted = youtubeObject.isMuted();
+              media.dispatchEvent( "volumechange" );
+            }
+
+            return youtubeObject.isMuted();
+          },
+          get: function() {
+
+            return youtubeObject.isMuted();
+          }
+        });
+
+        Popcorn.player.defineProperty( media, "volume", {
+          set: function( val ) {
+
+            if ( youtubeObject.getVolume() !== val ) {
+
+              youtubeObject.setVolume( val );
+              lastVolume = youtubeObject.getVolume();
+              media.dispatchEvent( "volumechange" );
+            }
+
+            return youtubeObject.getVolume();
+          },
+          get: function() {
+
+            return youtubeObject.getVolume();
+          }
+        });
+
+        media.readyState = 4;
+        media.dispatchEvent( "load" );
+        media.duration = youtubeObject.getDuration();
+        media.dispatchEvent( "durationchange" );
+        volumeupdate();
+
+        media.dispatchEvent( "loadeddata" );
+      };
+
+      options.controls = +options.controls === 0 || +options.controls === 1 ? options.controls : 1;
+      options.annotations = +options.annotations === 1 || +options.annotations === 3 ? options.annotations : 1;
+
+      flashvars = {
+        playerapiid: container.id,
+        controls: options.controls,
+        iv_load_policy: options.annotations
+      };
+
+      params = {
+        wmode: "transparent",
+        allowScriptAccess: "always"
+      };
+
+      attributes = {
+        id: container.id
+      };
+
+      src = /^.*[\/=](.{11})/.exec( media.src )[ 1 ];
+
+      swfobject.embedSWF( "http://www.youtube.com/e/" + src + "?enablejsapi=1&playerapiid=" + container.id + "&version=3",
+                          container.id, media.offsetWidth, media.offsetHeight, "8", null,
+                          flashvars, params, attributes );
+    };
+
+    if ( !window.swfobject ) {
+
+      Popcorn.getScript( "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js", youtubeInit );
+    } else {
+
+      youtubeInit();
+    }
+  }
+});
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/raphael.js	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,5436 @@
+// ┌─────────────────────────────────────────────────────────────────────┐ \\
+// │ Raphaël 2.0 - JavaScript Vector Library                             │ \\
+// ├─────────────────────────────────────────────────────────────────────┤ \\
+// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\
+// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\
+// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
+// └─────────────────────────────────────────────────────────────────────┘ \\
+
+// ┌──────────────────────────────────────────────────────────────────────────────────────┐ \\
+// │ Eve 0.3.2 - JavaScript Events Library                                                │ \\
+// ├──────────────────────────────────────────────────────────────────────────────────────┤ \\
+// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/)          │ \\
+// │ Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. │ \\
+// └──────────────────────────────────────────────────────────────────────────────────────┘ \\
+
+(function (glob) {
+    var version = "0.3.2",
+        has = "hasOwnProperty",
+        separator = /[\.\/]/,
+        wildcard = "*",
+        fun = function () {},
+        numsort = function (a, b) {
+            return a - b;
+        },
+        current_event,
+        stop,
+        events = {n: {}},
+    
+        eve = function (name, scope) {
+            var e = events,
+                oldstop = stop,
+                args = Array.prototype.slice.call(arguments, 2),
+                listeners = eve.listeners(name),
+                z = 0,
+                f = false,
+                l,
+                indexed = [],
+                queue = {},
+                out = [],
+                errors = [];
+            current_event = name;
+            stop = 0;
+            for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) {
+                indexed.push(listeners[i].zIndex);
+                if (listeners[i].zIndex < 0) {
+                    queue[listeners[i].zIndex] = listeners[i];
+                }
+            }
+            indexed.sort(numsort);
+            while (indexed[z] < 0) {
+                l = queue[indexed[z++]];
+                out.push(l.apply(scope, args));
+                if (stop) {
+                    stop = oldstop;
+                    return out;
+                }
+            }
+            for (i = 0; i < ii; i++) {
+                l = listeners[i];
+                if ("zIndex" in l) {
+                    if (l.zIndex == indexed[z]) {
+                        out.push(l.apply(scope, args));
+                        if (stop) {
+                            stop = oldstop;
+                            return out;
+                        }
+                        do {
+                            z++;
+                            l = queue[indexed[z]];
+                            l && out.push(l.apply(scope, args));
+                            if (stop) {
+                                stop = oldstop;
+                                return out;
+                            }
+                        } while (l)
+                    } else {
+                        queue[l.zIndex] = l;
+                    }
+                } else {
+                    out.push(l.apply(scope, args));
+                    if (stop) {
+                        stop = oldstop;
+                        return out;
+                    }
+                }
+            }
+            stop = oldstop;
+            return out.length ? out : null;
+        };
+    
+    eve.listeners = function (name) {
+        var names = name.split(separator),
+            e = events,
+            item,
+            items,
+            k,
+            i,
+            ii,
+            j,
+            jj,
+            nes,
+            es = [e],
+            out = [];
+        for (i = 0, ii = names.length; i < ii; i++) {
+            nes = [];
+            for (j = 0, jj = es.length; j < jj; j++) {
+                e = es[j].n;
+                items = [e[names[i]], e[wildcard]];
+                k = 2;
+                while (k--) {
+                    item = items[k];
+                    if (item) {
+                        nes.push(item);
+                        out = out.concat(item.f || []);
+                    }
+                }
+            }
+            es = nes;
+        }
+        return out;
+    };
+    
+    
+    eve.on = function (name, f) {
+        var names = name.split(separator),
+            e = events;
+        for (var i = 0, ii = names.length; i < ii; i++) {
+            e = e.n;
+            !e[names[i]] && (e[names[i]] = {n: {}});
+            e = e[names[i]];
+        }
+        e.f = e.f || [];
+        for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
+            return fun;
+        }
+        e.f.push(f);
+        return function (zIndex) {
+            if (+zIndex == +zIndex) {
+                f.zIndex = +zIndex;
+            }
+        };
+    };
+    
+    eve.stop = function () {
+        stop = 1;
+    };
+    
+    eve.nt = function (subname) {
+        if (subname) {
+            return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event);
+        }
+        return current_event;
+    };
+    
+    eve.unbind = function (name, f) {
+        var names = name.split(separator),
+            e,
+            key,
+            splice,
+            cur = [events];
+        for (var i = 0, ii = names.length; i < ii; i++) {
+            for (var j = 0; j < cur.length; j += splice.length - 2) {
+                splice = [j, 1];
+                e = cur[j].n;
+                if (names[i] != wildcard) {
+                    if (e[names[i]]) {
+                        splice.push(e[names[i]]);
+                    }
+                } else {
+                    for (key in e) if (e[has](key)) {
+                        splice.push(e[key]);
+                    }
+                }
+                cur.splice.apply(cur, splice);
+            }
+        }
+        for (i = 0, ii = cur.length; i < ii; i++) {
+            e = cur[i];
+            while (e.n) {
+                if (f) {
+                    if (e.f) {
+                        for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) {
+                            e.f.splice(j, 1);
+                            break;
+                        }
+                        !e.f.length && delete e.f;
+                    }
+                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {
+                        var funcs = e.n[key].f;
+                        for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) {
+                            funcs.splice(j, 1);
+                            break;
+                        }
+                        !funcs.length && delete e.n[key].f;
+                    }
+                } else {
+                    delete e.f;
+                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {
+                        delete e.n[key].f;
+                    }
+                }
+                e = e.n;
+            }
+        }
+    };
+    
+    eve.version = version;
+    eve.toString = function () {
+        return "You are running Eve " + version;
+    };
+    (typeof module != "undefined" && module.exports) ? (module.exports = eve) : (glob.eve = eve);
+})(this);
+
+// ┌─────────────────────────────────────────────────────────────────────┐ \\
+// │ "Raphaël 2.0" - JavaScript Vector Library                           │ \\
+// ├─────────────────────────────────────────────────────────────────────┤ \\
+// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\
+// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\
+// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
+// └─────────────────────────────────────────────────────────────────────┘ \\
+(function () {
+    
+    function R(first) {
+        if (R.is(first, "function")) {
+            return loaded ? first() : eve.on("DOMload", first);
+        } else if (R.is(first, array)) {
+            var a = first,
+                cnv = R._engine.create[apply](R, a.splice(0, 3 + R.is(a[0], nu))),
+                res = cnv.set(),
+                i = 0,
+                ii = a.length,
+                j;
+            for (; i < ii; i++) {
+                j = a[i] || {};
+                elements[has](j.type) && res.push(cnv[j.type]().attr(j));
+            }
+            return res;
+        } else {
+            var args = Array.prototype.slice.call(arguments, 0);
+            if (R.is(args[args.length - 1], "function")) {
+                var f = args.pop();
+                return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("DOMload", function () {
+                    f.call(R._engine.create[apply](R, args));
+                });
+            } else {
+                return R._engine.create[apply](R, arguments);
+            }
+        }
+    }
+    R.version = "2.0.0";
+    R.eve = eve;
+    var loaded,
+        separator = /[, ]+/,
+        elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},
+        formatrg = /\{(\d+)\}/g,
+        proto = "prototype",
+        has = "hasOwnProperty",
+        g = {
+            doc: document,
+            win: window
+        },
+        oldRaphael = {
+            was: Object.prototype[has].call(g.win, "Raphael"),
+            is: g.win.Raphael
+        },
+        Paper = function () {
+            
+            
+            this.ca = this.customAttributes = {};
+        },
+        paperproto,
+        appendChild = "appendChild",
+        apply = "apply",
+        concat = "concat",
+        supportsTouch = "createTouch" in g.doc,
+        E = "",
+        S = " ",
+        Str = String,
+        split = "split",
+        events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S),
+        touchMap = {
+            mousedown: "touchstart",
+            mousemove: "touchmove",
+            mouseup: "touchend"
+        },
+        lowerCase = Str.prototype.toLowerCase,
+        math = Math,
+        mmax = math.max,
+        mmin = math.min,
+        abs = math.abs,
+        pow = math.pow,
+        PI = math.PI,
+        nu = "number",
+        string = "string",
+        array = "array",
+        toString = "toString",
+        fillString = "fill",
+        objectToString = Object.prototype.toString,
+        paper = {},
+        push = "push",
+        ISURL = R._ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i,
+        colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,
+        isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1},
+        bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
+        round = math.round,
+        setAttribute = "setAttribute",
+        toFloat = parseFloat,
+        toInt = parseInt,
+        upperCase = Str.prototype.toUpperCase,
+        availableAttrs = R._availableAttrs = {
+            "arrow-end": "none",
+            "arrow-start": "none",
+            blur: 0,
+            "clip-rect": "0 0 1e9 1e9",
+            cursor: "default",
+            cx: 0,
+            cy: 0,
+            fill: "#fff",
+            "fill-opacity": 1,
+            font: '10px "Arial"',
+            "font-family": '"Arial"',
+            "font-size": "10",
+            "font-style": "normal",
+            "font-weight": 400,
+            gradient: 0,
+            height: 0,
+            href: "http://raphaeljs.com/",
+            opacity: 1,
+            path: "M0,0",
+            r: 0,
+            rx: 0,
+            ry: 0,
+            src: "",
+            stroke: "#000",
+            "stroke-dasharray": "",
+            "stroke-linecap": "butt",
+            "stroke-linejoin": "butt",
+            "stroke-miterlimit": 0,
+            "stroke-opacity": 1,
+            "stroke-width": 1,
+            target: "_blank",
+            "text-anchor": "middle",
+            title: "Raphael",
+            transform: "",
+            width: 0,
+            x: 0,
+            y: 0
+        },
+        availableAnimAttrs = R._availableAnimAttrs = {
+            blur: nu,
+            "clip-rect": "csv",
+            cx: nu,
+            cy: nu,
+            fill: "colour",
+            "fill-opacity": nu,
+            "font-size": nu,
+            height: nu,
+            opacity: nu,
+            path: "path",
+            r: nu,
+            rx: nu,
+            ry: nu,
+            stroke: "colour",
+            "stroke-opacity": nu,
+            "stroke-width": nu,
+            transform: "transform",
+            width: nu,
+            x: nu,
+            y: nu
+        },
+        commaSpaces = /\s*,\s*/,
+        hsrg = {hs: 1, rg: 1},
+        p2s = /,?([achlmqrstvxz]),?/gi,
+        pathCommand = /([achlmrqstvz])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig,
+        tCommand = /([rstm])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig,
+        pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)\s*,?\s*/ig,
+        radial_gradient = R._radial_gradient = /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/,
+        eldata = {},
+        sortByKey = function (a, b) {
+            return a.key - b.key;
+        },
+        sortByNumber = function (a, b) {
+            return toFloat(a) - toFloat(b);
+        },
+        fun = function () {},
+        pipe = function (x) {
+            return x;
+        },
+        rectPath = R._rectPath = function (x, y, w, h, r) {
+            if (r) {
+                return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]];
+            }
+            return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
+        },
+        ellipsePath = function (x, y, rx, ry) {
+            if (ry == null) {
+                ry = rx;
+            }
+            return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]];
+        },
+        getPath = R._getPath = {
+            path: function (el) {
+                return el.attr("path");
+            },
+            circle: function (el) {
+                var a = el.attrs;
+                return ellipsePath(a.cx, a.cy, a.r);
+            },
+            ellipse: function (el) {
+                var a = el.attrs;
+                return ellipsePath(a.cx, a.cy, a.rx, a.ry);
+            },
+            rect: function (el) {
+                var a = el.attrs;
+                return rectPath(a.x, a.y, a.width, a.height, a.r);
+            },
+            image: function (el) {
+                var a = el.attrs;
+                return rectPath(a.x, a.y, a.width, a.height);
+            },
+            text: function (el) {
+                var bbox = el._getBBox();
+                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
+            }
+        },
+        mapPath = R.mapPath = function (path, matrix) {
+            if (!matrix) {
+                return path;
+            }
+            var x, y, i, j, pathi;
+            path = path2curve(path);
+            for (i = 0, ii = path.length; i < ii; i++) {
+                pathi = path[i];
+                for (j = 1, jj = pathi.length; j < jj; j += 2) {
+                    x = matrix.x(pathi[j], pathi[j + 1]);
+                    y = matrix.y(pathi[j], pathi[j + 1]);
+                    pathi[j] = x;
+                    pathi[j + 1] = y;
+                }
+            }
+            return path;
+        };
+
+    R._g = g;
+    
+    R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
+    if (R.type == "VML") {
+        var d = g.doc.createElement("div"),
+            b;
+        d.innerHTML = '<v:shape adj="1"/>';
+        b = d.firstChild;
+        b.style.behavior = "url(#default#VML)";
+        if (!(b && typeof b.adj == "object")) {
+            return (R.type = E);
+        }
+        d = null;
+    }
+    
+    
+    R.svg = !(R.vml = R.type == "VML");
+    R._Paper = Paper;
+    
+    R.fn = paperproto = Paper.prototype = R.prototype;
+    R._id = 0;
+    R._oid = 0;
+    
+    R.is = function (o, type) {
+        type = lowerCase.call(type);
+        if (type == "finite") {
+            return !isnan[has](+o);
+        }
+        if (type == "array") {
+            return o instanceof Array;
+        }
+        return  (type == "null" && o === null) ||
+                (type == typeof o && o !== null) ||
+                (type == "object" && o === Object(o)) ||
+                (type == "array" && Array.isArray && Array.isArray(o)) ||
+                objectToString.call(o).slice(8, -1).toLowerCase() == type;
+    };
+    
+    R.angle = function (x1, y1, x2, y2, x3, y3) {
+        if (x3 == null) {
+            var x = x1 - x2,
+                y = y1 - y2;
+            if (!x && !y) {
+                return 0;
+            }
+            return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;
+        } else {
+            return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);
+        }
+    };
+    
+    R.rad = function (deg) {
+        return deg % 360 * PI / 180;
+    };
+    
+    R.deg = function (rad) {
+        return rad * 180 / PI % 360;
+    };
+    
+    R.snapTo = function (values, value, tolerance) {
+        tolerance = R.is(tolerance, "finite") ? tolerance : 10;
+        if (R.is(values, array)) {
+            var i = values.length;
+            while (i--) if (abs(values[i] - value) <= tolerance) {
+                return values[i];
+            }
+        } else {
+            values = +values;
+            var rem = value % values;
+            if (rem < tolerance) {
+                return value - rem;
+            }
+            if (rem > values - tolerance) {
+                return value - rem + values;
+            }
+        }
+        return value;
+    };
+    
+    
+    var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {
+        return function () {
+            return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase();
+        };
+    })(/[xy]/g, function (c) {
+        var r = math.random() * 16 | 0,
+            v = c == "x" ? r : (r & 3 | 8);
+        return v.toString(16);
+    });
+
+    
+    R.setWindow = function (newwin) {
+        eve("setWindow", R, g.win, newwin);
+        g.win = newwin;
+        g.doc = g.win.document;
+        if (initWin) {
+            initWin(g.win);
+        }
+    };
+    var toHex = function (color) {
+        if (R.vml) {
+            // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/
+            var trim = /^\s+|\s+$/g;
+            var bod;
+            try {
+                var docum = new ActiveXObject("htmlfile");
+                docum.write("<body>");
+                docum.close();
+                bod = docum.body;
+            } catch(e) {
+                bod = createPopup().document.body;
+            }
+            var range = bod.createTextRange();
+            toHex = cacher(function (color) {
+                try {
+                    bod.style.color = Str(color).replace(trim, E);
+                    var value = range.queryCommandValue("ForeColor");
+                    value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);
+                    return "#" + ("000000" + value.toString(16)).slice(-6);
+                } catch(e) {
+                    return "none";
+                }
+            });
+        } else {
+            var i = g.doc.createElement("i");
+            i.title = "Rapha\xebl Colour Picker";
+            i.style.display = "none";
+            g.doc.body.appendChild(i);
+            toHex = cacher(function (color) {
+                i.style.color = color;
+                return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color");
+            });
+        }
+        return toHex(color);
+    },
+    hsbtoString = function () {
+        return "hsb(" + [this.h, this.s, this.b] + ")";
+    },
+    hsltoString = function () {
+        return "hsl(" + [this.h, this.s, this.l] + ")";
+    },
+    rgbtoString = function () {
+        return this.hex;
+    },
+    prepareRGB = function (r, g, b) {
+        if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) {
+            b = r.b;
+            g = r.g;
+            r = r.r;
+        }
+        if (g == null && R.is(r, string)) {
+            var clr = R.getRGB(r);
+            r = clr.r;
+            g = clr.g;
+            b = clr.b;
+        }
+        if (r > 1 || g > 1 || b > 1) {
+            r /= 255;
+            g /= 255;
+            b /= 255;
+        }
+        
+        return [r, g, b];
+    },
+    packageRGB = function (r, g, b, o) {
+        r *= 255;
+        g *= 255;
+        b *= 255;
+        var rgb = {
+            r: r,
+            g: g,
+            b: b,
+            hex: R.rgb(r, g, b),
+            toString: rgbtoString
+        };
+        R.is(o, "finite") && (rgb.opacity = o);
+        return rgb;
+    };
+    
+    
+    R.color = function (clr) {
+        var rgb;
+        if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) {
+            rgb = R.hsb2rgb(clr);
+            clr.r = rgb.r;
+            clr.g = rgb.g;
+            clr.b = rgb.b;
+            clr.hex = rgb.hex;
+        } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) {
+            rgb = R.hsl2rgb(clr);
+            clr.r = rgb.r;
+            clr.g = rgb.g;
+            clr.b = rgb.b;
+            clr.hex = rgb.hex;
+        } else {
+            if (R.is(clr, "string")) {
+                clr = R.getRGB(clr);
+            }
+            if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) {
+                rgb = R.rgb2hsl(clr);
+                clr.h = rgb.h;
+                clr.s = rgb.s;
+                clr.l = rgb.l;
+                rgb = R.rgb2hsb(clr);
+                clr.v = rgb.b;
+            } else {
+                clr = {hex: "none"};
+                crl.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;
+            }
+        }
+        clr.toString = rgbtoString;
+        return clr;
+    };
+    
+    R.hsb2rgb = function (h, s, v, o) {
+        if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) {
+            v = h.b;
+            s = h.s;
+            h = h.h;
+            o = h.o;
+        }
+        h *= 360;
+        var R, G, B, X, C;
+        h = (h % 360) / 60;
+        C = v * s;
+        X = C * (1 - abs(h % 2 - 1));
+        R = G = B = v - C;
+
+        h = ~~h;
+        R += [C, X, 0, 0, X, C][h];
+        G += [X, C, C, X, 0, 0][h];
+        B += [0, 0, X, C, C, X][h];
+        return packageRGB(R, G, B, o);
+    };
+    
+    R.hsl2rgb = function (h, s, l, o) {
+        if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) {
+            l = h.l;
+            s = h.s;
+            h = h.h;
+        }
+        if (h > 1 || s > 1 || l > 1) {
+            h /= 360;
+            s /= 100;
+            l /= 100;
+        }
+        h *= 360;
+        var R, G, B, X, C;
+        h = (h % 360) / 60;
+        C = 2 * s * (l < .5 ? l : 1 - l);
+        X = C * (1 - abs(h % 2 - 1));
+        R = G = B = l - C / 2;
+
+        h = ~~h;
+        R += [C, X, 0, 0, X, C][h];
+        G += [X, C, C, X, 0, 0][h];
+        B += [0, 0, X, C, C, X][h];
+        return packageRGB(R, G, B, o);
+    };
+    
+    R.rgb2hsb = function (r, g, b) {
+        b = prepareRGB(r, g, b);
+        r = b[0];
+        g = b[1];
+        b = b[2];
+
+        var H, S, V, C;
+        V = mmax(r, g, b);
+        C = V - mmin(r, g, b);
+        H = (C == 0 ? null :
+             V == r ? (g - b) / C :
+             V == g ? (b - r) / C + 2 :
+                      (r - g) / C + 4
+            );
+        H = ((H + 360) % 6) * 60 / 360;
+        S = C == 0 ? 0 : C / V;
+        return {h: H, s: S, b: V, toString: hsbtoString};
+    };
+    
+    R.rgb2hsl = function (r, g, b) {
+        b = prepareRGB(r, g, b);
+        r = b[0];
+        g = b[1];
+        b = b[2];
+
+        var H, S, L, M, m, C;
+        M = mmax(r, g, b);
+        m = mmin(r, g, b);
+        C = M - m;
+        H = (C == 0 ? null :
+             M == r ? (g - b) / C :
+             M == g ? (b - r) / C + 2 :
+                      (r - g) / C + 4);
+        H = ((H + 360) % 6) * 60 / 360;
+        L = (M + m) / 2;
+        S = (C == 0 ? 0 :
+             L < .5 ? C / (2 * L) :
+                      C / (2 - 2 * L));
+        return {h: H, s: S, l: L, toString: hsltoString};
+    };
+    R._path2string = function () {
+        return this.join(",").replace(p2s, "$1");
+    };
+    function repush(array, item) {
+        for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
+            return array.push(array.splice(i, 1)[0]);
+        }
+    }
+    function cacher(f, scope, postprocessor) {
+        function newf() {
+            var arg = Array.prototype.slice.call(arguments, 0),
+                args = arg.join("\u2400"),
+                cache = newf.cache = newf.cache || {},
+                count = newf.count = newf.count || [];
+            if (cache[has](args)) {
+                repush(count, args);
+                return postprocessor ? postprocessor(cache[args]) : cache[args];
+            }
+            count.length >= 1e3 && delete cache[count.shift()];
+            count.push(args);
+            cache[args] = f[apply](scope, arg);
+            return postprocessor ? postprocessor(cache[args]) : cache[args];
+        }
+        return newf;
+    }
+
+    var preload = R._preload = function (src, f) {
+        var img = g.doc.createElement("img");
+        img.style.cssText = "position:absolute;left:-9999em;top-9999em";
+        img.onload = function () {
+            f.call(this);
+            this.onload = null;
+            g.doc.body.removeChild(this);
+        };
+        img.onerror = function () {
+            g.doc.body.removeChild(this);
+        };
+        g.doc.body.appendChild(img);
+        img.src = src;
+    };
+    
+    function clrToString() {
+        return this.hex;
+    }
+
+    
+    R.getRGB = cacher(function (colour) {
+        if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) {
+            return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
+        }
+        if (colour == "none") {
+            return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString};
+        }
+        !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour));
+        var res,
+            red,
+            green,
+            blue,
+            opacity,
+            t,
+            values,
+            rgb = colour.match(colourRegExp);
+        if (rgb) {
+            if (rgb[2]) {
+                blue = toInt(rgb[2].substring(5), 16);
+                green = toInt(rgb[2].substring(3, 5), 16);
+                red = toInt(rgb[2].substring(1, 3), 16);
+            }
+            if (rgb[3]) {
+                blue = toInt((t = rgb[3].charAt(3)) + t, 16);
+                green = toInt((t = rgb[3].charAt(2)) + t, 16);
+                red = toInt((t = rgb[3].charAt(1)) + t, 16);
+            }
+            if (rgb[4]) {
+                values = rgb[4][split](commaSpaces);
+                red = toFloat(values[0]);
+                values[0].slice(-1) == "%" && (red *= 2.55);
+                green = toFloat(values[1]);
+                values[1].slice(-1) == "%" && (green *= 2.55);
+                blue = toFloat(values[2]);
+                values[2].slice(-1) == "%" && (blue *= 2.55);
+                rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3]));
+                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
+            }
+            if (rgb[5]) {
+                values = rgb[5][split](commaSpaces);
+                red = toFloat(values[0]);
+                values[0].slice(-1) == "%" && (red *= 2.55);
+                green = toFloat(values[1]);
+                values[1].slice(-1) == "%" && (green *= 2.55);
+                blue = toFloat(values[2]);
+                values[2].slice(-1) == "%" && (blue *= 2.55);
+                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
+                rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3]));
+                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
+                return R.hsb2rgb(red, green, blue, opacity);
+            }
+            if (rgb[6]) {
+                values = rgb[6][split](commaSpaces);
+                red = toFloat(values[0]);
+                values[0].slice(-1) == "%" && (red *= 2.55);
+                green = toFloat(values[1]);
+                values[1].slice(-1) == "%" && (green *= 2.55);
+                blue = toFloat(values[2]);
+                values[2].slice(-1) == "%" && (blue *= 2.55);
+                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
+                rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3]));
+                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
+                return R.hsl2rgb(red, green, blue, opacity);
+            }
+            rgb = {r: red, g: green, b: blue, toString: clrToString};
+            rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
+            R.is(opacity, "finite") && (rgb.opacity = opacity);
+            return rgb;
+        }
+        return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
+    }, R);
+    
+    R.hsb = cacher(function (h, s, b) {
+        return R.hsb2rgb(h, s, b).hex;
+    });
+    
+    R.hsl = cacher(function (h, s, l) {
+        return R.hsl2rgb(h, s, l).hex;
+    });
+    
+    R.rgb = cacher(function (r, g, b) {
+        return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1);
+    });
+    
+    R.getColor = function (value) {
+        var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},
+            rgb = this.hsb2rgb(start.h, start.s, start.b);
+        start.h += .075;
+        if (start.h > 1) {
+            start.h = 0;
+            start.s -= .2;
+            start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});
+        }
+        return rgb.hex;
+    };
+    
+    R.getColor.reset = function () {
+        delete this.start;
+    };
+
+    // http://schepers.cc/getting-to-the-point
+    function catmullRom2bezier(crp) {
+        var d = [];
+        for (var i = 0, iLen = crp.length; iLen - 2 > i; i += 2) {
+            var p = [{x: +crp[i],     y: +crp[i + 1]},
+                     {x: +crp[i],     y: +crp[i + 1]},
+                     {x: +crp[i + 2], y: +crp[i + 3]},
+                     {x: +crp[i + 4], y: +crp[i + 5]}];
+            if (iLen - 4 == i) {
+                p[0] = {x: +crp[i - 2], y: +crp[i - 1]};
+                p[3] = p[2];
+            } else if (i) {
+                p[0] = {x: +crp[i - 2], y: +crp[i - 1]};
+            }
+            d.push(["C",
+                (-p[0].x + 6 * p[1].x + p[2].x) / 6,
+                (-p[0].y + 6 * p[1].y + p[2].y) / 6,
+                (p[1].x + 6 * p[2].x - p[3].x) / 6,
+                (p[1].y + 6*p[2].y - p[3].y) / 6,
+                p[2].x,
+                p[2].y
+            ]);
+        }
+
+        return d;
+    }
+    
+    R.parsePathString = cacher(function (pathString) {
+        if (!pathString) {
+            return null;
+        }
+        var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},
+            data = [];
+        if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption
+            data = pathClone(pathString);
+        }
+        if (!data.length) {
+            Str(pathString).replace(pathCommand, function (a, b, c) {
+                var params = [],
+                    name = b.toLowerCase();
+                c.replace(pathValues, function (a, b) {
+                    b && params.push(+b);
+                });
+                if (name == "m" && params.length > 2) {
+                    data.push([b][concat](params.splice(0, 2)));
+                    name = "l";
+                    b = b == "m" ? "l" : "L";
+                }
+                if (name == "r") {
+                    data.push([b][concat](params));
+                } else while (params.length >= paramCounts[name]) {
+                    data.push([b][concat](params.splice(0, paramCounts[name])));
+                    if (!paramCounts[name]) {
+                        break;
+                    }
+                }
+            });
+        }
+        data.toString = R._path2string;
+        return data;
+    });
+    
+    R.parseTransformString = cacher(function (TString) {
+        if (!TString) {
+            return null;
+        }
+        var paramCounts = {r: 3, s: 4, t: 2, m: 6},
+            data = [];
+        if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption
+            data = pathClone(TString);
+        }
+        if (!data.length) {
+            Str(TString).replace(tCommand, function (a, b, c) {
+                var params = [],
+                    name = lowerCase.call(b);
+                c.replace(pathValues, function (a, b) {
+                    b && params.push(+b);
+                });
+                data.push([b][concat](params));
+            });
+        }
+        data.toString = R._path2string;
+        return data;
+    });
+    
+    R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
+        var t1 = 1 - t,
+            t13 = pow(t1, 3),
+            t12 = pow(t1, 2),
+            t2 = t * t,
+            t3 = t2 * t,
+            x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
+            y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,
+            mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
+            my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
+            nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
+            ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
+            ax = t1 * p1x + t * c1x,
+            ay = t1 * p1y + t * c1y,
+            cx = t1 * c2x + t * p2x,
+            cy = t1 * c2y + t * p2y,
+            alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);
+        (mx > nx || my < ny) && (alpha += 180);
+        return {
+            x: x,
+            y: y,
+            m: {x: mx, y: my},
+            n: {x: nx, y: ny},
+            start: {x: ax, y: ay},
+            end: {x: cx, y: cy},
+            alpha: alpha
+        };
+    };
+    var pathDimensions = cacher(function (path) {
+        if (!path) {
+            return {x: 0, y: 0, width: 0, height: 0};
+        }
+        path = path2curve(path);
+        var x = 0, 
+            y = 0,
+            X = [],
+            Y = [],
+            p;
+        for (var i = 0, ii = path.length; i < ii; i++) {
+            p = path[i];
+            if (p[0] == "M") {
+                x = p[1];
+                y = p[2];
+                X.push(x);
+                Y.push(y);
+            } else {
+                var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
+                X = X[concat](dim.min.x, dim.max.x);
+                Y = Y[concat](dim.min.y, dim.max.y);
+                x = p[5];
+                y = p[6];
+            }
+        }
+        var xmin = mmin[apply](0, X),
+            ymin = mmin[apply](0, Y);
+        return {
+            x: xmin,
+            y: ymin,
+            width: mmax[apply](0, X) - xmin,
+            height: mmax[apply](0, Y) - ymin
+        };
+    }, null, function (o) {
+        return {
+            x: o.x,
+            y: o.y,
+            width: o.width,
+            height: o.height
+        };
+    }),
+        pathClone = function (pathArray) {
+            var res = [];
+            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
+                pathArray = R.parsePathString(pathArray);
+            }
+            for (var i = 0, ii = pathArray.length; i < ii; i++) {
+                res[i] = [];
+                for (var j = 0, jj = pathArray[i].length; j < jj; j++) {
+                    res[i][j] = pathArray[i][j];
+                }
+            }
+            res.toString = R._path2string;
+            return res;
+        },
+        pathToRelative = R._pathToRelative = cacher(function (pathArray) {
+            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
+                pathArray = R.parsePathString(pathArray);
+            }
+            var res = [],
+                x = 0,
+                y = 0,
+                mx = 0,
+                my = 0,
+                start = 0;
+            if (pathArray[0][0] == "M") {
+                x = pathArray[0][1];
+                y = pathArray[0][2];
+                mx = x;
+                my = y;
+                start++;
+                res.push(["M", x, y]);
+            }
+            for (var i = start, ii = pathArray.length; i < ii; i++) {
+                var r = res[i] = [],
+                    pa = pathArray[i];
+                if (pa[0] != lowerCase.call(pa[0])) {
+                    r[0] = lowerCase.call(pa[0]);
+                    switch (r[0]) {
+                        case "a":
+                            r[1] = pa[1];
+                            r[2] = pa[2];
+                            r[3] = pa[3];
+                            r[4] = pa[4];
+                            r[5] = pa[5];
+                            r[6] = +(pa[6] - x).toFixed(3);
+                            r[7] = +(pa[7] - y).toFixed(3);
+                            break;
+                        case "v":
+                            r[1] = +(pa[1] - y).toFixed(3);
+                            break;
+                        case "m":
+                            mx = pa[1];
+                            my = pa[2];
+                        default:
+                            for (var j = 1, jj = pa.length; j < jj; j++) {
+                                r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
+                            }
+                    }
+                } else {
+                    r = res[i] = [];
+                    if (pa[0] == "m") {
+                        mx = pa[1] + x;
+                        my = pa[2] + y;
+                    }
+                    for (var k = 0, kk = pa.length; k < kk; k++) {
+                        res[i][k] = pa[k];
+                    }
+                }
+                var len = res[i].length;
+                switch (res[i][0]) {
+                    case "z":
+                        x = mx;
+                        y = my;
+                        break;
+                    case "h":
+                        x += +res[i][len - 1];
+                        break;
+                    case "v":
+                        y += +res[i][len - 1];
+                        break;
+                    default:
+                        x += +res[i][len - 2];
+                        y += +res[i][len - 1];
+                }
+            }
+            res.toString = R._path2string;
+            return res;
+        }, 0, pathClone),
+        pathToAbsolute = R._pathToAbsolute = cacher(function (pathArray) {
+            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
+                pathArray = R.parsePathString(pathArray);
+            }
+            if (!pathArray || !pathArray.length) {
+                return [["M", 0, 0]];
+            }
+            var res = [],
+                x = 0,
+                y = 0,
+                mx = 0,
+                my = 0,
+                start = 0;
+            if (pathArray[0][0] == "M") {
+                x = +pathArray[0][1];
+                y = +pathArray[0][2];
+                mx = x;
+                my = y;
+                start++;
+                res[0] = ["M", x, y];
+            }
+            for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
+                res.push(r = []);
+                pa = pathArray[i];
+                if (pa[0] != upperCase.call(pa[0])) {
+                    r[0] = upperCase.call(pa[0]);
+                    switch (r[0]) {
+                        case "A":
+                            r[1] = pa[1];
+                            r[2] = pa[2];
+                            r[3] = pa[3];
+                            r[4] = pa[4];
+                            r[5] = pa[5];
+                            r[6] = +(pa[6] + x);
+                            r[7] = +(pa[7] + y);
+                            break;
+                        case "V":
+                            r[1] = +pa[1] + y;
+                            break;
+                        case "H":
+                            r[1] = +pa[1] + x;
+                            break;
+                        case "R":
+                            var dots = [x, y][concat](pa.slice(1));
+                            for (var j = 2, jj = dots.length; j < jj; j++) {
+                                dots[j] = +dots[j] + x;
+                                dots[++j] = +dots[j] + y;
+                            }
+                            res.pop();
+                            res = res[concat](catmullRom2bezier(dots));
+                            break;
+                        case "M":
+                            mx = +pa[1] + x;
+                            my = +pa[2] + y;
+                        default:
+                            for (j = 1, jj = pa.length; j < jj; j++) {
+                                r[j] = +pa[j] + ((j % 2) ? x : y);
+                            }
+                    }
+                } else if (pa[0] == "R") {
+                    dots = [x, y][concat](pa.slice(1));
+                    res.pop();
+                    res = res[concat](catmullRom2bezier(dots));
+                    r = ["R"][concat](pa.slice(-2));
+                } else {
+                    for (var k = 0, kk = pa.length; k < kk; k++) {
+                        r[k] = pa[k];
+                    }
+                }
+                switch (r[0]) {
+                    case "Z":
+                        x = mx;
+                        y = my;
+                        break;
+                    case "H":
+                        x = r[1];
+                        break;
+                    case "V":
+                        y = r[1];
+                        break;
+                    case "M":
+                        mx = r[r.length - 2];
+                        my = r[r.length - 1];
+                    default:
+                        x = r[r.length - 2];
+                        y = r[r.length - 1];
+                }
+            }
+            res.toString = R._path2string;
+            return res;
+        }, null, pathClone),
+        l2c = function (x1, y1, x2, y2) {
+            return [x1, y1, x2, y2, x2, y2];
+        },
+        q2c = function (x1, y1, ax, ay, x2, y2) {
+            var _13 = 1 / 3,
+                _23 = 2 / 3;
+            return [
+                    _13 * x1 + _23 * ax,
+                    _13 * y1 + _23 * ay,
+                    _13 * x2 + _23 * ax,
+                    _13 * y2 + _23 * ay,
+                    x2,
+                    y2
+                ];
+        },
+        a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
+            // for more information of where this math came from visit:
+            // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+            var _120 = PI * 120 / 180,
+                rad = PI / 180 * (+angle || 0),
+                res = [],
+                xy,
+                rotate = cacher(function (x, y, rad) {
+                    var X = x * math.cos(rad) - y * math.sin(rad),
+                        Y = x * math.sin(rad) + y * math.cos(rad);
+                    return {x: X, y: Y};
+                });
+            if (!recursive) {
+                xy = rotate(x1, y1, -rad);
+                x1 = xy.x;
+                y1 = xy.y;
+                xy = rotate(x2, y2, -rad);
+                x2 = xy.x;
+                y2 = xy.y;
+                var cos = math.cos(PI / 180 * angle),
+                    sin = math.sin(PI / 180 * angle),
+                    x = (x1 - x2) / 2,
+                    y = (y1 - y2) / 2;
+                var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
+                if (h > 1) {
+                    h = math.sqrt(h);
+                    rx = h * rx;
+                    ry = h * ry;
+                }
+                var rx2 = rx * rx,
+                    ry2 = ry * ry,
+                    k = (large_arc_flag == sweep_flag ? -1 : 1) *
+                        math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
+                    cx = k * rx * y / ry + (x1 + x2) / 2,
+                    cy = k * -ry * x / rx + (y1 + y2) / 2,
+                    f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
+                    f2 = math.asin(((y2 - cy) / ry).toFixed(9));
+
+                f1 = x1 < cx ? PI - f1 : f1;
+                f2 = x2 < cx ? PI - f2 : f2;
+                f1 < 0 && (f1 = PI * 2 + f1);
+                f2 < 0 && (f2 = PI * 2 + f2);
+                if (sweep_flag && f1 > f2) {
+                    f1 = f1 - PI * 2;
+                }
+                if (!sweep_flag && f2 > f1) {
+                    f2 = f2 - PI * 2;
+                }
+            } else {
+                f1 = recursive[0];
+                f2 = recursive[1];
+                cx = recursive[2];
+                cy = recursive[3];
+            }
+            var df = f2 - f1;
+            if (abs(df) > _120) {
+                var f2old = f2,
+                    x2old = x2,
+                    y2old = y2;
+                f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
+                x2 = cx + rx * math.cos(f2);
+                y2 = cy + ry * math.sin(f2);
+                res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
+            }
+            df = f2 - f1;
+            var c1 = math.cos(f1),
+                s1 = math.sin(f1),
+                c2 = math.cos(f2),
+                s2 = math.sin(f2),
+                t = math.tan(df / 4),
+                hx = 4 / 3 * rx * t,
+                hy = 4 / 3 * ry * t,
+                m1 = [x1, y1],
+                m2 = [x1 + hx * s1, y1 - hy * c1],
+                m3 = [x2 + hx * s2, y2 - hy * c2],
+                m4 = [x2, y2];
+            m2[0] = 2 * m1[0] - m2[0];
+            m2[1] = 2 * m1[1] - m2[1];
+            if (recursive) {
+                return [m2, m3, m4][concat](res);
+            } else {
+                res = [m2, m3, m4][concat](res).join()[split](",");
+                var newres = [];
+                for (var i = 0, ii = res.length; i < ii; i++) {
+                    newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
+                }
+                return newres;
+            }
+        },
+        findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
+            var t1 = 1 - t;
+            return {
+                x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,
+                y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y
+            };
+        },
+        curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
+            var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
+                b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
+                c = p1x - c1x,
+                t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,
+                t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,
+                y = [p1y, p2y],
+                x = [p1x, p2x],
+                dot;
+            abs(t1) > "1e12" && (t1 = .5);
+            abs(t2) > "1e12" && (t2 = .5);
+            if (t1 > 0 && t1 < 1) {
+                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
+                x.push(dot.x);
+                y.push(dot.y);
+            }
+            if (t2 > 0 && t2 < 1) {
+                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
+                x.push(dot.x);
+                y.push(dot.y);
+            }
+            a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
+            b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
+            c = p1y - c1y;
+            t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;
+            t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;
+            abs(t1) > "1e12" && (t1 = .5);
+            abs(t2) > "1e12" && (t2 = .5);
+            if (t1 > 0 && t1 < 1) {
+                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
+                x.push(dot.x);
+                y.push(dot.y);
+            }
+            if (t2 > 0 && t2 < 1) {
+                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
+                x.push(dot.x);
+                y.push(dot.y);
+            }
+            return {
+                min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},
+                max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}
+            };
+        }),
+        path2curve = R._path2curve = cacher(function (path, path2) {
+            var p = pathToAbsolute(path),
+                p2 = path2 && pathToAbsolute(path2),
+                attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
+                attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
+                processPath = function (path, d) {
+                    var nx, ny;
+                    if (!path) {
+                        return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
+                    }
+                    !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null);
+                    switch (path[0]) {
+                        case "M":
+                            d.X = path[1];
+                            d.Y = path[2];
+                            break;
+                        case "A":
+                            path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));
+                            break;
+                        case "S":
+                            nx = d.x + (d.x - (d.bx || d.x));
+                            ny = d.y + (d.y - (d.by || d.y));
+                            path = ["C", nx, ny][concat](path.slice(1));
+                            break;
+                        case "T":
+                            d.qx = d.x + (d.x - (d.qx || d.x));
+                            d.qy = d.y + (d.y - (d.qy || d.y));
+                            path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
+                            break;
+                        case "Q":
+                            d.qx = path[1];
+                            d.qy = path[2];
+                            path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
+                            break;
+                        case "L":
+                            path = ["C"][concat](l2c(d.x, d.y, path[1], path[2]));
+                            break;
+                        case "H":
+                            path = ["C"][concat](l2c(d.x, d.y, path[1], d.y));
+                            break;
+                        case "V":
+                            path = ["C"][concat](l2c(d.x, d.y, d.x, path[1]));
+                            break;
+                        case "Z":
+                            path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y));
+                            break;
+                    }
+                    return path;
+                },
+                fixArc = function (pp, i) {
+                    if (pp[i].length > 7) {
+                        pp[i].shift();
+                        var pi = pp[i];
+                        while (pi.length) {
+                            pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6)));
+                        }
+                        pp.splice(i, 1);
+                        ii = mmax(p.length, p2 && p2.length || 0);
+                    }
+                },
+                fixM = function (path1, path2, a1, a2, i) {
+                    if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
+                        path2.splice(i, 0, ["M", a2.x, a2.y]);
+                        a1.bx = 0;
+                        a1.by = 0;
+                        a1.x = path1[i][1];
+                        a1.y = path1[i][2];
+                        ii = mmax(p.length, p2 && p2.length || 0);
+                    }
+                };
+            for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {
+                p[i] = processPath(p[i], attrs);
+                fixArc(p, i);
+                p2 && (p2[i] = processPath(p2[i], attrs2));
+                p2 && fixArc(p2, i);
+                fixM(p, p2, attrs, attrs2, i);
+                fixM(p2, p, attrs2, attrs, i);
+                var seg = p[i],
+                    seg2 = p2 && p2[i],
+                    seglen = seg.length,
+                    seg2len = p2 && seg2.length;
+                attrs.x = seg[seglen - 2];
+                attrs.y = seg[seglen - 1];
+                attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;
+                attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
+                attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);
+                attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);
+                attrs2.x = p2 && seg2[seg2len - 2];
+                attrs2.y = p2 && seg2[seg2len - 1];
+            }
+            return p2 ? [p, p2] : p;
+        }, null, pathClone),
+        parseDots = R._parseDots = cacher(function (gradient) {
+            var dots = [];
+            for (var i = 0, ii = gradient.length; i < ii; i++) {
+                var dot = {},
+                    par = gradient[i].match(/^([^:]*):?([\d\.]*)/);
+                dot.color = R.getRGB(par[1]);
+                if (dot.color.error) {
+                    return null;
+                }
+                dot.color = dot.color.hex;
+                par[2] && (dot.offset = par[2] + "%");
+                dots.push(dot);
+            }
+            for (i = 1, ii = dots.length - 1; i < ii; i++) {
+                if (!dots[i].offset) {
+                    var start = toFloat(dots[i - 1].offset || 0),
+                        end = 0;
+                    for (var j = i + 1; j < ii; j++) {
+                        if (dots[j].offset) {
+                            end = dots[j].offset;
+                            break;
+                        }
+                    }
+                    if (!end) {
+                        end = 100;
+                        j = ii;
+                    }
+                    end = toFloat(end);
+                    var d = (end - start) / (j - i + 1);
+                    for (; i < j; i++) {
+                        start += d;
+                        dots[i].offset = start + "%";
+                    }
+                }
+            }
+            return dots;
+        }),
+        tear = R._tear = function (el, paper) {
+            el == paper.top && (paper.top = el.prev);
+            el == paper.bottom && (paper.bottom = el.next);
+            el.next && (el.next.prev = el.prev);
+            el.prev && (el.prev.next = el.next);
+        },
+        tofront = R._tofront = function (el, paper) {
+            if (paper.top === el) {
+                return;
+            }
+            tear(el, paper);
+            el.next = null;
+            el.prev = paper.top;
+            paper.top.next = el;
+            paper.top = el;
+        },
+        toback = R._toback = function (el, paper) {
+            if (paper.bottom === el) {
+                return;
+            }
+            tear(el, paper);
+            el.next = paper.bottom;
+            el.prev = null;
+            paper.bottom.prev = el;
+            paper.bottom = el;
+        },
+        insertafter = R._insertafter = function (el, el2, paper) {
+            tear(el, paper);
+            el2 == paper.top && (paper.top = el);
+            el2.next && (el2.next.prev = el);
+            el.next = el2.next;
+            el.prev = el2;
+            el2.next = el;
+        },
+        insertbefore = R._insertbefore = function (el, el2, paper) {
+            tear(el, paper);
+            el2 == paper.bottom && (paper.bottom = el);
+            el2.prev && (el2.prev.next = el);
+            el.prev = el2.prev;
+            el2.prev = el;
+            el.next = el2;
+        },
+        removed = function (methodname) {
+            return function () {
+                throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object");
+            };
+        },
+        extractTransform = R._extractTransform = function (el, tstr) {
+            if (tstr == null) {
+                return el._.transform;
+            }
+            tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E);
+            var tdata = R.parseTransformString(tstr),
+                deg = 0,
+                dx = 0,
+                dy = 0,
+                sx = 1,
+                sy = 1,
+                _ = el._,
+                m = new Matrix;
+            _.transform = tdata || [];
+            if (tdata) {
+                for (var i = 0, ii = tdata.length; i < ii; i++) {
+                    var t = tdata[i],
+                        tlen = t.length,
+                        command = Str(t[0]).toLowerCase(),
+                        absolute = t[0] != command,
+                        inver = absolute ? m.invert() : 0,
+                        x1,
+                        y1,
+                        x2,
+                        y2,
+                        bb;
+                    if (command == "t" && tlen == 3) {
+                        if (absolute) {
+                            x1 = inver.x(0, 0);
+                            y1 = inver.y(0, 0);
+                            x2 = inver.x(t[1], t[2]);
+                            y2 = inver.y(t[1], t[2]);
+                            m.translate(x2 - x1, y2 - y1);
+                        } else {
+                            m.translate(t[1], t[2]);
+                        }
+                    } else if (command == "r") {
+                        if (tlen == 2) {
+                            bb = bb || el.getBBox(1);
+                            m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);
+                            deg += t[1];
+                        } else if (tlen == 4) {
+                            if (absolute) {
+                                x2 = inver.x(t[2], t[3]);
+                                y2 = inver.y(t[2], t[3]);
+                                m.rotate(t[1], x2, y2);
+                            } else {
+                                m.rotate(t[1], t[2], t[3]);
+                            }
+                            deg += t[1];
+                        }
+                    } else if (command == "s") {
+                        if (tlen == 2 || tlen == 3) {
+                            bb = bb || el.getBBox(1);
+                            m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);
+                            sx *= t[1];
+                            sy *= t[tlen - 1];
+                        } else if (tlen == 5) {
+                            if (absolute) {
+                                x2 = inver.x(t[3], t[4]);
+                                y2 = inver.y(t[3], t[4]);
+                                m.scale(t[1], t[2], x2, y2);
+                            } else {
+                                m.scale(t[1], t[2], t[3], t[4]);
+                            }
+                            sx *= t[1];
+                            sy *= t[2];
+                        }
+                    } else if (command == "m" && tlen == 7) {
+                        m.add(t[1], t[2], t[3], t[4], t[5], t[6]);
+                    }
+                    _.dirtyT = 1;
+                    el.matrix = m;
+                }
+            }
+
+            el.matrix = m;
+
+            _.sx = sx;
+            _.sy = sy;
+            _.deg = deg;
+            _.dx = dx = m.e;
+            _.dy = dy = m.f;
+
+            if (sx == 1 && sy == 1 && !deg && _.bbox) {
+                _.bbox.x += +dx;
+                _.bbox.y += +dy;
+            } else {
+                _.dirtyT = 1;
+            }
+        },
+        getEmpty = function (item) {
+            var l = item[0];
+            switch (l.toLowerCase()) {
+                case "t": return [l, 0, 0];
+                case "m": return [l, 1, 0, 0, 1, 0, 0];
+                case "r": if (item.length == 4) {
+                    return [l, 0, item[2], item[3]];
+                } else {
+                    return [l, 0];
+                }
+                case "s": if (item.length == 5) {
+                    return [l, 1, 1, item[3], item[4]];
+                } else if (item.length == 3) {
+                    return [l, 1, 1];
+                } else {
+                    return [l, 1];
+                }
+            }
+        },
+        equaliseTransform = R._equaliseTransform = function (t1, t2) {
+            t2 = Str(t2).replace(/\.{3}|\u2026/g, t1);
+            t1 = R.parseTransformString(t1) || [];
+            t2 = R.parseTransformString(t2) || [];
+            var maxlength = mmax(t1.length, t2.length),
+                from = [],
+                to = [],
+                i = 0, j, jj,
+                tt1, tt2;
+            for (; i < maxlength; i++) {
+                tt1 = t1[i] || getEmpty(t2[i]);
+                tt2 = t2[i] || getEmpty(tt1);
+                if ((tt1[0] != tt2[0]) ||
+                    (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
+                    (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
+                    ) {
+                    return;
+                }
+                from[i] = [];
+                to[i] = [];
+                for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {
+                    j in tt1 && (from[i][j] = tt1[j]);
+                    j in tt2 && (to[i][j] = tt2[j]);
+                }
+            }
+            return {
+                from: from,
+                to: to
+            };
+        };
+    R._getContainer = function (x, y, w, h) {
+        var container;
+        container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x;
+        if (container == null) {
+            return;
+        }
+        if (container.tagName) {
+            if (y == null) {
+                return {
+                    container: container,
+                    width: container.style.pixelWidth || container.offsetWidth,
+                    height: container.style.pixelHeight || container.offsetHeight
+                };
+            } else {
+                return {
+                    container: container,
+                    width: y,
+                    height: w
+                };
+            }
+        }
+        return {
+            container: 1,
+            x: x,
+            y: y,
+            width: w,
+            height: h
+        };
+    };
+    
+    R.pathToRelative = pathToRelative;
+    R._engine = {};
+    
+    R.path2curve = path2curve;
+    
+    R.matrix = function (a, b, c, d, e, f) {
+        return new Matrix(a, b, c, d, e, f);
+    };
+    function Matrix(a, b, c, d, e, f) {
+        if (a != null) {
+            this.a = +a;
+            this.b = +b;
+            this.c = +c;
+            this.d = +d;
+            this.e = +e;
+            this.f = +f;
+        } else {
+            this.a = 1;
+            this.b = 0;
+            this.c = 0;
+            this.d = 1;
+            this.e = 0;
+            this.f = 0;
+        }
+    }
+    (function (matrixproto) {
+        
+        matrixproto.add = function (a, b, c, d, e, f) {
+            var out = [[], [], []],
+                m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],
+                matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
+                x, y, z, res;
+
+            if (a && a instanceof Matrix) {
+                matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];
+            }
+
+            for (x = 0; x < 3; x++) {
+                for (y = 0; y < 3; y++) {
+                    res = 0;
+                    for (z = 0; z < 3; z++) {
+                        res += m[x][z] * matrix[z][y];
+                    }
+                    out[x][y] = res;
+                }
+            }
+            this.a = out[0][0];
+            this.b = out[1][0];
+            this.c = out[0][1];
+            this.d = out[1][1];
+            this.e = out[0][2];
+            this.f = out[1][2];
+        };
+        
+        matrixproto.invert = function () {
+            var me = this,
+                x = me.a * me.d - me.b * me.c;
+            return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);
+        };
+        
+        matrixproto.clone = function () {
+            return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
+        };
+        
+        matrixproto.translate = function (x, y) {
+            this.add(1, 0, 0, 1, x, y);
+        };
+        
+        matrixproto.scale = function (x, y, cx, cy) {
+            y == null && (y = x);
+            (cx || cy) && this.add(1, 0, 0, 1, cx, cy);
+            this.add(x, 0, 0, y, 0, 0);
+            (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);
+        };
+        
+        matrixproto.rotate = function (a, x, y) {
+            a = R.rad(a);
+            x = x || 0;
+            y = y || 0;
+            var cos = +math.cos(a).toFixed(9),
+                sin = +math.sin(a).toFixed(9);
+            this.add(cos, sin, -sin, cos, x, y);
+            this.add(1, 0, 0, 1, -x, -y);
+        };
+        
+        matrixproto.x = function (x, y) {
+            return x * this.a + y * this.c + this.e;
+        };
+        
+        matrixproto.y = function (x, y) {
+            return x * this.b + y * this.d + this.f;
+        };
+        matrixproto.get = function (i) {
+            return +this[Str.fromCharCode(97 + i)].toFixed(4);
+        };
+        matrixproto.toString = function () {
+            return R.svg ?
+                "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" :
+                [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();
+        };
+        matrixproto.toFilter = function () {
+            return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) +
+                ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) +
+                ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')";
+        };
+        matrixproto.offset = function () {
+            return [this.e.toFixed(4), this.f.toFixed(4)];
+        };
+        function norm(a) {
+            return a[0] * a[0] + a[1] * a[1];
+        }
+        function normalize(a) {
+            var mag = math.sqrt(norm(a));
+            a[0] && (a[0] /= mag);
+            a[1] && (a[1] /= mag);
+        }
+        
+        matrixproto.split = function () {
+            var out = {};
+            // translation
+            out.dx = this.e;
+            out.dy = this.f;
+
+            // scale and shear
+            var row = [[this.a, this.c], [this.b, this.d]];
+            out.scalex = math.sqrt(norm(row[0]));
+            normalize(row[0]);
+
+            out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
+            row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
+
+            out.scaley = math.sqrt(norm(row[1]));
+            normalize(row[1]);
+            out.shear /= out.scaley;
+
+            // rotation
+            var sin = -row[0][1],
+                cos = row[1][1];
+            if (cos < 0) {
+                out.rotate = R.deg(math.acos(cos));
+                if (sin < 0) {
+                    out.rotate = 360 - out.rotate;
+                }
+            } else {
+                out.rotate = R.deg(math.asin(sin));
+            }
+
+            out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);
+            out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;
+            out.noRotation = !+out.shear.toFixed(9) && !out.rotate;
+            return out;
+        };
+        
+        matrixproto.toTransformString = function (shorter) {
+            var s = shorter || this[split]();
+            if (s.isSimple) {
+                return "t" + [s.dx, s.dy] + "s" + [s.scalex, s.scaley, 0, 0] + "r" + [s.rotate, 0, 0];
+            } else {
+                return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
+            }
+        };
+    })(Matrix.prototype);
+
+    // WebKit rendering bug workaround method
+    var version = navigator.userAgent.match(/Version\/(.*?)\s/) || navigator.userAgent.match(/Chrome\/(\d+)/);
+    if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP") ||
+        (navigator.vendor == "Google Inc." && version && version[1] < 8)) {
+        
+        paperproto.safari = function () {
+            var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"});
+            setTimeout(function () {rect.remove();});
+        };
+    } else {
+        paperproto.safari = fun;
+    }
+ 
+    var preventDefault = function () {
+        this.returnValue = false;
+    },
+    preventTouch = function () {
+        return this.originalEvent.preventDefault();
+    },
+    stopPropagation = function () {
+        this.cancelBubble = true;
+    },
+    stopTouch = function () {
+        return this.originalEvent.stopPropagation();
+    },
+    addEvent = (function () {
+        if (g.doc.addEventListener) {
+            return function (obj, type, fn, element) {
+                var realName = supportsTouch && touchMap[type] ? touchMap[type] : type,
+                    f = function (e) {
+                        var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
+                            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
+                            x = e.clientX + scrollX,
+                            y = e.clientY + scrollY;
+                    if (supportsTouch && touchMap[has](type)) {
+                        for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {
+                            if (e.targetTouches[i].target == obj) {
+                                var olde = e;
+                                e = e.targetTouches[i];
+                                e.originalEvent = olde;
+                                e.preventDefault = preventTouch;
+                                e.stopPropagation = stopTouch;
+                                break;
+                            }
+                        }
+                    }
+                    return fn.call(element, e, x, y);
+                };
+                obj.addEventListener(realName, f, false);
+                return function () {
+                    obj.removeEventListener(realName, f, false);
+                    return true;
+                };
+            };
+        } else if (g.doc.attachEvent) {
+            return function (obj, type, fn, element) {
+                var f = function (e) {
+                    e = e || g.win.event;
+                    var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
+                        scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
+                        x = e.clientX + scrollX,
+                        y = e.clientY + scrollY;
+                    e.preventDefault = e.preventDefault || preventDefault;
+                    e.stopPropagation = e.stopPropagation || stopPropagation;
+                    return fn.call(element, e, x, y);
+                };
+                obj.attachEvent("on" + type, f);
+                var detacher = function () {
+                    obj.detachEvent("on" + type, f);
+                    return true;
+                };
+                return detacher;
+            };
+        }
+    })(),
+    drag = [],
+    dragMove = function (e) {
+        var x = e.clientX,
+            y = e.clientY,
+            scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
+            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
+            dragi,
+            j = drag.length;
+        while (j--) {
+            dragi = drag[j];
+            if (supportsTouch) {
+                var i = e.touches.length,
+                    touch;
+                while (i--) {
+                    touch = e.touches[i];
+                    if (touch.identifier == dragi.el._drag.id) {
+                        x = touch.clientX;
+                        y = touch.clientY;
+                        (e.originalEvent ? e.originalEvent : e).preventDefault();
+                        break;
+                    }
+                }
+            } else {
+                e.preventDefault();
+            }
+            var node = dragi.el.node,
+                o,
+                next = node.nextSibling,
+                parent = node.parentNode,
+                display = node.style.display;
+            g.win.opera && parent.removeChild(node);
+            node.style.display = "none";
+            o = dragi.el.paper.getElementByPoint(x, y);
+            node.style.display = display;
+            g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));
+            o && eve("drag.over." + dragi.el.id, dragi.el, o);
+            x += scrollX;
+            y += scrollY;
+            eve("drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);
+        }
+    },
+    dragUp = function (e) {
+        R.unmousemove(dragMove).unmouseup(dragUp);
+        var i = drag.length,
+            dragi;
+        while (i--) {
+            dragi = drag[i];
+            dragi.el._drag = {};
+            eve("drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);
+        }
+        drag = [];
+    },
+    
+    elproto = R.el = {};
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    for (var i = events.length; i--;) {
+        (function (eventName) {
+            R[eventName] = elproto[eventName] = function (fn, scope) {
+                if (R.is(fn, "function")) {
+                    this.events = this.events || [];
+                    this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});
+                }
+                return this;
+            };
+            R["un" + eventName] = elproto["un" + eventName] = function (fn) {
+                var events = this.events,
+                    l = events.length;
+                while (l--) if (events[l].name == eventName && events[l].f == fn) {
+                    events[l].unbind();
+                    events.splice(l, 1);
+                    !events.length && delete this.events;
+                    return this;
+                }
+                return this;
+            };
+        })(events[i]);
+    }
+    
+    
+    elproto.data = function (key, value) {
+        var data = eldata[this.id] = eldata[this.id] || {};
+        if (arguments.length == 1) {
+            if (R.is(key, "object")) {
+                for (var i in key) if (key[has](i)) {
+                    this.data(i, key[i]);
+                }
+                return this;
+            }
+            eve("data.get." + this.id, this, data[key], key);
+            return data[key];
+        }
+        data[key] = value;
+        eve("data.set." + this.id, this, value, key);
+        return this;
+    };
+    
+    elproto.removeData = function (key) {
+        if (key == null) {
+            eldata[this.id] = {};
+        } else {
+            eldata[this.id] && delete eldata[this.id][key];
+        }
+        return this;
+    };
+    
+    elproto.hover = function (f_in, f_out, scope_in, scope_out) {
+        return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);
+    };
+    
+    elproto.unhover = function (f_in, f_out) {
+        return this.unmouseover(f_in).unmouseout(f_out);
+    };
+    
+    elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {
+        function start(e) {
+            (e.originalEvent || e).preventDefault();
+            var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
+                scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
+            this._drag.x = e.clientX + scrollX;
+            this._drag.y = e.clientY + scrollY;
+            this._drag.id = e.identifier;
+            !drag.length && R.mousemove(dragMove).mouseup(dragUp);
+            drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});
+            onstart && eve.on("drag.start." + this.id, onstart);
+            onmove && eve.on("drag.move." + this.id, onmove);
+            onend && eve.on("drag.end." + this.id, onend);
+            eve("drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e);
+        }
+        this._drag = {};
+        this.mousedown(start);
+        return this;
+    };
+    
+    elproto.onDragOver = function (f) {
+        f ? eve.on("drag.over." + this.id, f) : eve.unbind("drag.over." + this.id);
+    };
+    
+    elproto.undrag = function () {
+        var i = drag.length;
+        while (i--) if (drag[i].el == this) {
+            R.unmousedown(drag[i].start);
+            drag.splice(i++, 1);
+            eve.unbind("drag.*." + this.id);
+        }
+        !drag.length && R.unmousemove(dragMove).unmouseup(dragUp);
+    };
+    
+    paperproto.circle = function (x, y, r) {
+        var out = R._engine.circle(this, x || 0, y || 0, r || 0);
+        this.__set__ && this.__set__.push(out);
+        return out;
+    };
+    
+    paperproto.rect = function (x, y, w, h, r) {
+        var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);
+        this.__set__ && this.__set__.push(out);
+        return out;
+    };
+    
+    paperproto.ellipse = function (x, y, rx, ry) {
+        var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);
+        this.__set__ && this.__set__.push(out);
+        return out;
+    };
+    
+    paperproto.path = function (pathString) {
+        pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);
+        var out = R._engine.path(R.format[apply](R, arguments), this);
+        this.__set__ && this.__set__.push(out);
+        return out;
+    };
+    
+    paperproto.image = function (src, x, y, w, h) {
+        var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);
+        this.__set__ && this.__set__.push(out);
+        return out;
+    };
+    
+    paperproto.text = function (x, y, text) {
+        var out = R._engine.text(this, x || 0, y || 0, Str(text));
+        this.__set__ && this.__set__.push(out);
+        return out;
+    };
+    
+    paperproto.set = function (itemsArray) {
+        !R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));
+        var out = new Set(itemsArray);
+        this.__set__ && this.__set__.push(out);
+        return out;
+    };
+    
+    paperproto.setStart = function (set) {
+        this.__set__ = set || this.set();
+    };
+    
+    paperproto.setFinish = function (set) {
+        var out = this.__set__;
+        delete this.__set__;
+        return out;
+    };
+    
+    paperproto.setSize = function (width, height) {
+        return R._engine.setSize.call(this, width, height);
+    };
+    
+    paperproto.setViewBox = function (x, y, w, h, fit) {
+        return R._engine.setViewBox.call(this, x, y, w, h, fit);
+    };
+    
+    
+    paperproto.top = paperproto.bottom = null;
+    
+    paperproto.raphael = R;
+    var getOffset = function (elem) {
+        var box = elem.getBoundingClientRect(),
+            doc = elem.ownerDocument,
+            body = doc.body,
+            docElem = doc.documentElement,
+            clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+            top  = box.top  + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,
+            left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;
+        return {
+            y: top,
+            x: left
+        };
+    };
+    
+    paperproto.getElementByPoint = function (x, y) {
+        var paper = this,
+            svg = paper.canvas,
+            target = g.doc.elementFromPoint(x, y);
+        if (g.win.opera && target.tagName == "svg") {
+            var so = getOffset(svg),
+                sr = svg.createSVGRect();
+            sr.x = x - so.x;
+            sr.y = y - so.y;
+            sr.width = sr.height = 1;
+            var hits = svg.getIntersectionList(sr, null);
+            if (hits.length) {
+                target = hits[hits.length - 1];
+            }
+        }
+        if (!target) {
+            return null;
+        }
+        while (target.parentNode && target != svg.parentNode && !target.raphael) {
+            target = target.parentNode;
+        }
+        target == paper.canvas.parentNode && (target = svg);
+        target = target && target.raphael ? paper.getById(target.raphaelid) : null;
+        return target;
+    };
+    
+    paperproto.getById = function (id) {
+        var bot = this.bottom;
+        while (bot) {
+            if (bot.id == id) {
+                return bot;
+            }
+            bot = bot.next;
+        }
+        return null;
+    };
+    
+    paperproto.forEach = function (callback, thisArg) {
+        var bot = this.bottom;
+        while (bot) {
+            if (callback.call(thisArg, bot) === false) {
+                return this;
+            }
+            bot = bot.next;
+        }
+        return this;
+    };
+    function x_y() {
+        return this.x + S + this.y;
+    }
+    function x_y_w_h() {
+        return this.x + S + this.y + S + this.width + " \xd7 " + this.height;
+    }
+    
+    elproto.getBBox = function (isWithoutTransform) {
+        if (this.removed) {
+            return {};
+        }
+        var _ = this._;
+        if (isWithoutTransform) {
+            if (_.dirty || !_.bboxwt) {
+                this.realPath = getPath[this.type](this);
+                _.bboxwt = pathDimensions(this.realPath);
+                _.bboxwt.toString = x_y_w_h;
+                _.dirty = 0;
+            }
+            return _.bboxwt;
+        }
+        if (_.dirty || _.dirtyT || !_.bbox) {
+            if (_.dirty || !this.realPath) {
+                _.bboxwt = 0;
+                this.realPath = getPath[this.type](this);
+            }
+            _.bbox = pathDimensions(mapPath(this.realPath, this.matrix));
+            _.bbox.toString = x_y_w_h;
+            _.dirty = _.dirtyT = 0;
+        }
+        return _.bbox;
+    };
+    
+    elproto.clone = function () {
+        if (this.removed) {
+            return null;
+        }
+        var out = this.paper[this.type]().attr(this.attr());
+        this.__set__ && this.__set__.push(out);
+        return out;
+    };
+    
+    elproto.glow = function (glow) {
+        if (this.type == "text") {
+            return null;
+        }
+        glow = glow || {};
+        var s = {
+            width: (glow.width || 10) + (+this.attr("stroke-width") || 1),
+            fill: glow.fill || false,
+            opacity: glow.opacity || .5,
+            offsetx: glow.offsetx || 0,
+            offsety: glow.offsety || 0,
+            color: glow.color || "#000"
+        },
+            c = s.width / 2,
+            r = this.paper,
+            out = r.set(),
+            path = this.realPath || getPath[this.type](this);
+        path = this.matrix ? mapPath(path, this.matrix) : path;
+        for (var i = 1; i < c + 1; i++) {
+            out.push(r.path(path).attr({
+                stroke: s.color,
+                fill: s.fill ? s.color : "none",
+                "stroke-linejoin": "round",
+                "stroke-linecap": "round",
+                "stroke-width": +(s.width / c * i).toFixed(3),
+                opacity: +(s.opacity / c).toFixed(3)
+            }));
+        }
+        return out.insertBefore(this).translate(s.offsetx, s.offsety);
+    };
+    var curveslengths = {},
+    getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
+        var len = 0,
+            precision = 100,
+            name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(),
+            cache = curveslengths[name],
+            old, dot;
+        !cache && (curveslengths[name] = cache = {data: []});
+        cache.timer && clearTimeout(cache.timer);
+        cache.timer = setTimeout(function () {delete curveslengths[name];}, 2e3);
+        if (length != null && !cache.precision) {
+            var total = getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
+            cache.precision = ~~total * 10;
+            cache.data = [];
+        }
+        precision = cache.precision || precision;
+        for (var i = 0; i < precision + 1; i++) {
+            if (cache.data[i * precision]) {
+                dot = cache.data[i * precision];
+            } else {
+                dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / precision);
+                cache.data[i * precision] = dot;
+            }
+            i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5));
+            if (length != null && len >= length) {
+                return dot;
+            }
+            old = dot;
+        }
+        if (length == null) {
+            return len;
+        }
+    },
+    getLengthFactory = function (istotal, subpath) {
+        return function (path, length, onlystart) {
+            path = path2curve(path);
+            var x, y, p, l, sp = "", subpaths = {}, point,
+                len = 0;
+            for (var i = 0, ii = path.length; i < ii; i++) {
+                p = path[i];
+                if (p[0] == "M") {
+                    x = +p[1];
+                    y = +p[2];
+                } else {
+                    l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
+                    if (len + l > length) {
+                        if (subpath && !subpaths.start) {
+                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
+                            sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];
+                            if (onlystart) {return sp;}
+                            subpaths.start = sp;
+                            sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();
+                            len += l;
+                            x = +p[5];
+                            y = +p[6];
+                            continue;
+                        }
+                        if (!istotal && !subpath) {
+                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
+                            return {x: point.x, y: point.y, alpha: point.alpha};
+                        }
+                    }
+                    len += l;
+                    x = +p[5];
+                    y = +p[6];
+                }
+                sp += p.shift() + p;
+            }
+            subpaths.end = sp;
+            point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
+            point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
+            return point;
+        };
+    };
+    var getTotalLength = getLengthFactory(1),
+        getPointAtLength = getLengthFactory(),
+        getSubpathsAtLength = getLengthFactory(0, 1);
+    
+    R.getTotalLength = getTotalLength;
+    
+    R.getPointAtLength = getPointAtLength;
+    
+    R.getSubpath = function (path, from, to) {
+        if (this.getTotalLength(path) - to < 1e-6) {
+            return getSubpathsAtLength(path, from).end;
+        }
+        var a = getSubpathsAtLength(path, to, 1);
+        return from ? getSubpathsAtLength(a, from).end : a;
+    };
+    
+    elproto.getTotalLength = function () {
+        if (this.type != "path") {return;}
+        if (this.node.getTotalLength) {
+            return this.node.getTotalLength();
+        }
+        return getTotalLength(this.attrs.path);
+    };
+    
+    elproto.getPointAtLength = function (length) {
+        if (this.type != "path") {return;}
+        return getPointAtLength(this.attrs.path, length);
+    };
+    
+    elproto.getSubpath = function (from, to) {
+        if (this.type != "path") {return;}
+        return R.getSubpath(this.attrs.path, from, to);
+    };
+    
+    var ef = R.easing_formulas = {
+        linear: function (n) {
+            return n;
+        },
+        "<": function (n) {
+            return pow(n, 1.7);
+        },
+        ">": function (n) {
+            return pow(n, .48);
+        },
+        "<>": function (n) {
+            var q = .48 - n / 1.04,
+                Q = math.sqrt(.1734 + q * q),
+                x = Q - q,
+                X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
+                y = -Q - q,
+                Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
+                t = X + Y + .5;
+            return (1 - t) * 3 * t * t + t * t * t;
+        },
+        backIn: function (n) {
+            var s = 1.70158;
+            return n * n * ((s + 1) * n - s);
+        },
+        backOut: function (n) {
+            n = n - 1;
+            var s = 1.70158;
+            return n * n * ((s + 1) * n + s) + 1;
+        },
+        elastic: function (n) {
+            if (n == !!n) {
+                return n;
+            }
+            return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;
+        },
+        bounce: function (n) {
+            var s = 7.5625,
+                p = 2.75,
+                l;
+            if (n < (1 / p)) {
+                l = s * n * n;
+            } else {
+                if (n < (2 / p)) {
+                    n -= (1.5 / p);
+                    l = s * n * n + .75;
+                } else {
+                    if (n < (2.5 / p)) {
+                        n -= (2.25 / p);
+                        l = s * n * n + .9375;
+                    } else {
+                        n -= (2.625 / p);
+                        l = s * n * n + .984375;
+                    }
+                }
+            }
+            return l;
+        }
+    };
+    ef.easeIn = ef["ease-in"] = ef["<"];
+    ef.easeOut = ef["ease-out"] = ef[">"];
+    ef.easeInOut = ef["ease-in-out"] = ef["<>"];
+    ef["back-in"] = ef.backIn;
+    ef["back-out"] = ef.backOut;
+
+    var animationElements = [],
+        requestAnimFrame = window.requestAnimationFrame       ||
+                           window.webkitRequestAnimationFrame ||
+                           window.mozRequestAnimationFrame    ||
+                           window.oRequestAnimationFrame      ||
+                           window.msRequestAnimationFrame     ||
+                           function (callback) {
+                               setTimeout(callback, 16);
+                           },
+        animation = function () {
+            var Now = +new Date,
+                l = 0;
+            for (; l < animationElements.length; l++) {
+                var e = animationElements[l];
+                if (e.el.removed || e.paused) {
+                    continue;
+                }
+                var time = Now - e.start,
+                    ms = e.ms,
+                    easing = e.easing,
+                    from = e.from,
+                    diff = e.diff,
+                    to = e.to,
+                    t = e.t,
+                    that = e.el,
+                    set = {},
+                    now,
+                    init = {},
+                    key;
+                if (e.initstatus) {
+                    time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;
+                    e.status = e.initstatus;
+                    delete e.initstatus;
+                    e.stop && animationElements.splice(l--, 1);
+                } else {
+                    e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;
+                }
+                if (time < 0) {
+                    continue;
+                }
+                if (time < ms) {
+                    var pos = easing(time / ms);
+                    for (var attr in from) if (from[has](attr)) {
+                        switch (availableAnimAttrs[attr]) {
+                            case nu:
+                                now = +from[attr] + pos * ms * diff[attr];
+                                break;
+                            case "colour":
+                                now = "rgb(" + [
+                                    upto255(round(from[attr].r + pos * ms * diff[attr].r)),
+                                    upto255(round(from[attr].g + pos * ms * diff[attr].g)),
+                                    upto255(round(from[attr].b + pos * ms * diff[attr].b))
+                                ].join(",") + ")";
+                                break;
+                            case "path":
+                                now = [];
+                                for (var i = 0, ii = from[attr].length; i < ii; i++) {
+                                    now[i] = [from[attr][i][0]];
+                                    for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
+                                        now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];
+                                    }
+                                    now[i] = now[i].join(S);
+                                }
+                                now = now.join(S);
+                                break;
+                            case "transform":
+                                if (diff[attr].real) {
+                                    now = [];
+                                    for (i = 0, ii = from[attr].length; i < ii; i++) {
+                                        now[i] = [from[attr][i][0]];
+                                        for (j = 1, jj = from[attr][i].length; j < jj; j++) {
+                                            now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];
+                                        }
+                                    }
+                                } else {
+                                    var get = function (i) {
+                                        return +from[attr][i] + pos * ms * diff[attr][i];
+                                    };
+                                    // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]];
+                                    now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]];
+                                }
+                                break;
+                            case "csv":
+                                if (attr == "clip-rect") {
+                                    now = [];
+                                    i = 4;
+                                    while (i--) {
+                                        now[i] = +from[attr][i] + pos * ms * diff[attr][i];
+                                    }
+                                }
+                                break;
+                            default:
+                                var from2 = [][concat](from[attr]);
+                                now = [];
+                                i = that.paper.customAttributes[attr].length;
+                                while (i--) {
+                                    now[i] = +from2[i] + pos * ms * diff[attr][i];
+                                }
+                                break;
+                        }
+                        set[attr] = now;
+                    }
+                    that.attr(set);
+                    (function (id, that, anim) {
+                        setTimeout(function () {
+                            eve("anim.frame." + id, that, anim);
+                        });
+                    })(that.id, that, e.anim);
+                } else {
+                    (function(f, el, a) {
+                        setTimeout(function() {
+                            eve("anim.frame." + el.id, el, a);
+                            eve("anim.finish." + el.id, el, a);
+                            R.is(f, "function") && f.call(el);
+                        });
+                    })(e.callback, that, e.anim);
+                    that.attr(to);
+                    animationElements.splice(l--, 1);
+                    if (e.repeat > 1 && !e.next) {
+                        for (key in to) if (to[has](key)) {
+                            init[key] = e.totalOrigin[key];
+                        }
+                        e.el.attr(init);
+                        runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);
+                    }
+                    if (e.next && !e.stop) {
+                        runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);
+                    }
+                }
+            }
+            R.svg && that && that.paper && that.paper.safari();
+            animationElements.length && requestAnimFrame(animation);
+        },
+        upto255 = function (color) {
+            return color > 255 ? 255 : color < 0 ? 0 : color;
+        };
+    
+    elproto.animateWith = function (element, anim, params, ms, easing, callback) {
+        var a = params ? R.animation(params, ms, easing, callback) : anim;
+            status = element.status(anim);
+        return this.animate(a).status(a, status * anim.ms / a.ms);
+    };
+    function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
+        var cx = 3 * p1x,
+            bx = 3 * (p2x - p1x) - cx,
+            ax = 1 - cx - bx,
+            cy = 3 * p1y,
+            by = 3 * (p2y - p1y) - cy,
+            ay = 1 - cy - by;
+        function sampleCurveX(t) {
+            return ((ax * t + bx) * t + cx) * t;
+        }
+        function solve(x, epsilon) {
+            var t = solveCurveX(x, epsilon);
+            return ((ay * t + by) * t + cy) * t;
+        }
+        function solveCurveX(x, epsilon) {
+            var t0, t1, t2, x2, d2, i;
+            for(t2 = x, i = 0; i < 8; i++) {
+                x2 = sampleCurveX(t2) - x;
+                if (abs(x2) < epsilon) {
+                    return t2;
+                }
+                d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
+                if (abs(d2) < 1e-6) {
+                    break;
+                }
+                t2 = t2 - x2 / d2;
+            }
+            t0 = 0;
+            t1 = 1;
+            t2 = x;
+            if (t2 < t0) {
+                return t0;
+            }
+            if (t2 > t1) {
+                return t1;
+            }
+            while (t0 < t1) {
+                x2 = sampleCurveX(t2);
+                if (abs(x2 - x) < epsilon) {
+                    return t2;
+                }
+                if (x > x2) {
+                    t0 = t2;
+                } else {
+                    t1 = t2;
+                }
+                t2 = (t1 - t0) / 2 + t0;
+            }
+            return t2;
+        }
+        return solve(t, 1 / (200 * duration));
+    }
+    elproto.onAnimation = function (f) {
+        f ? eve.on("anim.frame." + this.id, f) : eve.unbind("anim.frame." + this.id);
+        return this;
+    };
+    function Animation(anim, ms) {
+        var percents = [],
+            newAnim = {};
+        this.ms = ms;
+        this.times = 1;
+        if (anim) {
+            for (var attr in anim) if (anim[has](attr)) {
+                newAnim[toFloat(attr)] = anim[attr];
+                percents.push(toFloat(attr));
+            }
+            percents.sort(sortByNumber);
+        }
+        this.anim = newAnim;
+        this.top = percents[percents.length - 1];
+        this.percents = percents;
+    }
+    
+    Animation.prototype.delay = function (delay) {
+        var a = new Animation(this.anim, this.ms);
+        a.times = this.times;
+        a.del = +delay || 0;
+        return a;
+    };
+    
+    Animation.prototype.repeat = function (times) { 
+        var a = new Animation(this.anim, this.ms);
+        a.del = this.del;
+        a.times = math.floor(mmax(times, 0)) || 1;
+        return a;
+    };
+    function runAnimation(anim, element, percent, status, totalOrigin, times) {
+        percent = toFloat(percent);
+        var params,
+            isInAnim,
+            isInAnimSet,
+            percents = [],
+            next,
+            prev,
+            timestamp,
+            ms = anim.ms,
+            from = {},
+            to = {},
+            diff = {};
+        if (status) {
+            for (i = 0, ii = animationElements.length; i < ii; i++) {
+                var e = animationElements[i];
+                if (e.el.id == element.id && e.anim == anim) {
+                    if (e.percent != percent) {
+                        animationElements.splice(i, 1);
+                        isInAnimSet = 1;
+                    } else {
+                        isInAnim = e;
+                    }
+                    element.attr(e.totalOrigin);
+                    break;
+                }
+            }
+        } else {
+            status = +to; // NaN
+        }
+        for (var i = 0, ii = anim.percents.length; i < ii; i++) {
+            if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {
+                percent = anim.percents[i];
+                prev = anim.percents[i - 1] || 0;
+                ms = ms / anim.top * (percent - prev);
+                next = anim.percents[i + 1];
+                params = anim.anim[percent];
+                break;
+            } else if (status) {
+                element.attr(anim.anim[anim.percents[i]]);
+            }
+        }
+        if (!params) {
+            return;
+        }
+        if (!isInAnim) {
+            for (attr in params) if (params[has](attr)) {
+                if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {
+                    from[attr] = element.attr(attr);
+                    (from[attr] == null) && (from[attr] = availableAttrs[attr]);
+                    to[attr] = params[attr];
+                    switch (availableAnimAttrs[attr]) {
+                        case nu:
+                            diff[attr] = (to[attr] - from[attr]) / ms;
+                            break;
+                        case "colour":
+                            from[attr] = R.getRGB(from[attr]);
+                            var toColour = R.getRGB(to[attr]);
+                            diff[attr] = {
+                                r: (toColour.r - from[attr].r) / ms,
+                                g: (toColour.g - from[attr].g) / ms,
+                                b: (toColour.b - from[attr].b) / ms
+                            };
+                            break;
+                        case "path":
+                            var pathes = path2curve(from[attr], to[attr]),
+                                toPath = pathes[1];
+                            from[attr] = pathes[0];
+                            diff[attr] = [];
+                            for (i = 0, ii = from[attr].length; i < ii; i++) {
+                                diff[attr][i] = [0];
+                                for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
+                                    diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;
+                                }
+                            }
+                            break;
+                        case "transform":
+                            var _ = element._,
+                                eq = equaliseTransform(_[attr], to[attr]);
+                            if (eq) {
+                                from[attr] = eq.from;
+                                to[attr] = eq.to;
+                                diff[attr] = [];
+                                diff[attr].real = true;
+                                for (i = 0, ii = from[attr].length; i < ii; i++) {
+                                    diff[attr][i] = [from[attr][i][0]];
+                                    for (j = 1, jj = from[attr][i].length; j < jj; j++) {
+                                        diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;
+                                    }
+                                }
+                            } else {
+                                var m = (element.matrix || new Matrix),
+                                    to2 = {
+                                        _: {transform: _.transform},
+                                        getBBox: function () {
+                                            return element.getBBox(1);
+                                        }
+                                    };
+                                from[attr] = [
+                                    m.a,
+                                    m.b,
+                                    m.c,
+                                    m.d,
+                                    m.e,
+                                    m.f
+                                ];
+                                extractTransform(to2, to[attr]);
+                                to[attr] = to2._.transform;
+                                diff[attr] = [
+                                    (to2.matrix.a - m.a) / ms,
+                                    (to2.matrix.b - m.b) / ms,
+                                    (to2.matrix.c - m.c) / ms,
+                                    (to2.matrix.d - m.d) / ms,
+                                    (to2.matrix.e - m.e) / ms,
+                                    (to2.matrix.e - m.f) / ms
+                                ];
+                                // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];
+                                // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};
+                                // extractTransform(to2, to[attr]);
+                                // diff[attr] = [
+                                //     (to2._.sx - _.sx) / ms,
+                                //     (to2._.sy - _.sy) / ms,
+                                //     (to2._.deg - _.deg) / ms,
+                                //     (to2._.dx - _.dx) / ms,
+                                //     (to2._.dy - _.dy) / ms
+                                // ];
+                            }
+                            break;
+                        case "csv":
+                            var values = Str(params[attr])[split](separator),
+                                from2 = Str(from[attr])[split](separator);
+                            if (attr == "clip-rect") {
+                                from[attr] = from2;
+                                diff[attr] = [];
+                                i = from2.length;
+                                while (i--) {
+                                    diff[attr][i] = (values[i] - from[attr][i]) / ms;
+                                }
+                            }
+                            to[attr] = values;
+                            break;
+                        default:
+                            values = [][concat](params[attr]);
+                            from2 = [][concat](from[attr]);
+                            diff[attr] = [];
+                            i = element.paper.customAttributes[attr].length;
+                            while (i--) {
+                                diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;
+                            }
+                            break;
+                    }
+                }
+            }
+            var easing = params.easing,
+                easyeasy = R.easing_formulas[easing];
+            if (!easyeasy) {
+                easyeasy = Str(easing).match(bezierrg);
+                if (easyeasy && easyeasy.length == 5) {
+                    var curve = easyeasy;
+                    easyeasy = function (t) {
+                        return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);
+                    };
+                } else {
+                    easyeasy = pipe;
+                }
+            }
+            timestamp = params.start || anim.start || +new Date;
+            e = {
+                anim: anim,
+                percent: percent,
+                timestamp: timestamp,
+                start: timestamp + (anim.del || 0),
+                status: 0,
+                initstatus: status || 0,
+                stop: false,
+                ms: ms,
+                easing: easyeasy,
+                from: from,
+                diff: diff,
+                to: to,
+                el: element,
+                callback: params.callback,
+                prev: prev,
+                next: next,
+                repeat: times || anim.times,
+                origin: element.attr(),
+                totalOrigin: totalOrigin
+            };
+            animationElements.push(e);
+            if (status && !isInAnim && !isInAnimSet) {
+                e.stop = true;
+                e.start = new Date - ms * status;
+                if (animationElements.length == 1) {
+                    return animation();
+                }
+            }
+            if (isInAnimSet) {
+                e.start = new Date - e.ms * status;
+            }
+            animationElements.length == 1 && requestAnimFrame(animation);
+        } else {
+            isInAnim.initstatus = status;
+            isInAnim.start = new Date - isInAnim.ms * status;
+        }
+        eve("anim.start." + element.id, element, anim);
+    }
+    
+    R.animation = function (params, ms, easing, callback) {
+        if (params instanceof Animation) {
+            return params;
+        }
+        if (R.is(easing, "function") || !easing) {
+            callback = callback || easing || null;
+            easing = null;
+        }
+        params = Object(params);
+        ms = +ms || 0;
+        var p = {},
+            json,
+            attr;
+        for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + "%" != attr) {
+            json = true;
+            p[attr] = params[attr];
+        }
+        if (!json) {
+            return new Animation(params, ms);
+        } else {
+            easing && (p.easing = easing);
+            callback && (p.callback = callback);
+            return new Animation({100: p}, ms);
+        }
+    };
+    
+    elproto.animate = function (params, ms, easing, callback) {
+        var element = this;
+        if (element.removed) {
+            callback && callback.call(element);
+            return element;
+        }
+        var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);
+        runAnimation(anim, element, anim.percents[0], null, element.attr());
+        return element;
+    };
+    
+    elproto.setTime = function (anim, value) {
+        if (anim && value != null) {
+            this.status(anim, mmin(value, anim.ms) / anim.ms);
+        }
+        return this;
+    };
+    
+    elproto.status = function (anim, value) {
+        var out = [],
+            i = 0,
+            len,
+            e;
+        if (value != null) {
+            runAnimation(anim, this, -1, mmin(value, 1));
+            return this;
+        } else {
+            len = animationElements.length;
+            for (; i < len; i++) {
+                e = animationElements[i];
+                if (e.el.id == this.id && (!anim || e.anim == anim)) {
+                    if (anim) {
+                        return e.status;
+                    }
+                    out.push({
+                        anim: e.anim,
+                        status: e.status
+                    });
+                }
+            }
+            if (anim) {
+                return 0;
+            }
+            return out;
+        }
+    };
+    
+    elproto.pause = function (anim) {
+        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
+            if (eve("anim.pause." + this.id, this, animationElements[i].anim) !== false) {
+                animationElements[i].paused = true;
+            }
+        }
+        return this;
+    };
+    
+    elproto.resume = function (anim) {
+        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
+            var e = animationElements[i];
+            if (eve("anim.resume." + this.id, this, e.anim) !== false) {
+                delete e.paused;
+                this.status(e.anim, e.status);
+            }
+        }
+        return this;
+    };
+    
+    elproto.stop = function (anim) {
+        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
+            if (eve("anim.stop." + this.id, this, animationElements[i].anim) !== false) {
+                animationElements.splice(i--, 1);
+            }
+        }
+        return this;
+    };
+    elproto.toString = function () {
+        return "Rapha\xebl\u2019s object";
+    };
+
+    // Set
+    var Set = function (items) {
+        this.items = [];
+        this.length = 0;
+        this.type = "set";
+        if (items) {
+            for (var i = 0, ii = items.length; i < ii; i++) {
+                if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {
+                    this[this.items.length] = this.items[this.items.length] = items[i];
+                    this.length++;
+                }
+            }
+        }
+    },
+    setproto = Set.prototype;
+    
+    setproto.push = function () {
+        var item,
+            len;
+        for (var i = 0, ii = arguments.length; i < ii; i++) {
+            item = arguments[i];
+            if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {
+                len = this.items.length;
+                this[len] = this.items[len] = item;
+                this.length++;
+            }
+        }
+        return this;
+    };
+    
+    setproto.pop = function () {
+        this.length && delete this[this.length--];
+        return this.items.pop();
+    };
+    
+    setproto.forEach = function (callback, thisArg) {
+        for (var i = 0, ii = this.items.length; i < ii; i++) {
+            if (callback.call(thisArg, this.items[i], i) === false) {
+                return this;
+            }
+        }
+        return this;
+    };
+    for (var method in elproto) if (elproto[has](method)) {
+        setproto[method] = (function (methodname) {
+            return function () {
+                var arg = arguments;
+                return this.forEach(function (el) {
+                    el[methodname][apply](el, arg);
+                });
+            };
+        })(method);
+    }
+    setproto.attr = function (name, value) {
+        if (name && R.is(name, array) && R.is(name[0], "object")) {
+            for (var j = 0, jj = name.length; j < jj; j++) {
+                this.items[j].attr(name[j]);
+            }
+        } else {
+            for (var i = 0, ii = this.items.length; i < ii; i++) {
+                this.items[i].attr(name, value);
+            }
+        }
+        return this;
+    };
+    
+    setproto.clear = function () {
+        while (this.length) {
+            this.pop();
+        }
+    };
+    
+    setproto.splice = function (index, count, insertion) {
+        index = index < 0 ? mmax(this.length + index, 0) : index;
+        count = mmax(0, mmin(this.length - index, count));
+        var tail = [],
+            todel = [],
+            args = [],
+            i;
+        for (i = 2; i < arguments.length; i++) {
+            args.push(arguments[i]);
+        }
+        for (i = 0; i < count; i++) {
+            todel.push(this[index + i]);
+        }
+        for (; i < this.length - index; i++) {
+            tail.push(this[index + i]);
+        }
+        var arglen = args.length;
+        for (i = 0; i < arglen + tail.length; i++) {
+            this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];
+        }
+        i = this.items.length = this.length -= count - arglen;
+        while (this[i]) {
+            delete this[i++];
+        }
+        return new Set(todel);
+    };
+    
+    setproto.exclude = function (el) {
+        for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {
+            this.splice(i, 1);
+            return true;
+        }
+    };
+    setproto.animate = function (params, ms, easing, callback) {
+        (R.is(easing, "function") || !easing) && (callback = easing || null);
+        var len = this.items.length,
+            i = len,
+            item,
+            set = this,
+            collector;
+        if (!len) {
+            return this;
+        }
+        callback && (collector = function () {
+            !--len && callback.call(set);
+        });
+        easing = R.is(easing, string) ? easing : collector;
+        var anim = R.animation(params, ms, easing, collector);
+        item = this.items[--i].animate(anim);
+        while (i--) {
+            this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim);
+        }
+        return this;
+    };
+    setproto.insertAfter = function (el) {
+        var i = this.items.length;
+        while (i--) {
+            this.items[i].insertAfter(el);
+        }
+        return this;
+    };
+    setproto.getBBox = function () {
+        var x = [],
+            y = [],
+            w = [],
+            h = [];
+        for (var i = this.items.length; i--;) if (!this.items[i].removed) {
+            var box = this.items[i].getBBox();
+            x.push(box.x);
+            y.push(box.y);
+            w.push(box.x + box.width);
+            h.push(box.y + box.height);
+        }
+        x = mmin[apply](0, x);
+        y = mmin[apply](0, y);
+        return {
+            x: x,
+            y: y,
+            width: mmax[apply](0, w) - x,
+            height: mmax[apply](0, h) - y
+        };
+    };
+    setproto.clone = function (s) {
+        s = new Set;
+        for (var i = 0, ii = this.items.length; i < ii; i++) {
+            s.push(this.items[i].clone());
+        }
+        return s;
+    };
+    setproto.toString = function () {
+        return "Rapha\xebl\u2018s set";
+    };
+
+    
+    R.registerFont = function (font) {
+        if (!font.face) {
+            return font;
+        }
+        this.fonts = this.fonts || {};
+        var fontcopy = {
+                w: font.w,
+                face: {},
+                glyphs: {}
+            },
+            family = font.face["font-family"];
+        for (var prop in font.face) if (font.face[has](prop)) {
+            fontcopy.face[prop] = font.face[prop];
+        }
+        if (this.fonts[family]) {
+            this.fonts[family].push(fontcopy);
+        } else {
+            this.fonts[family] = [fontcopy];
+        }
+        if (!font.svg) {
+            fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10);
+            for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {
+                var path = font.glyphs[glyph];
+                fontcopy.glyphs[glyph] = {
+                    w: path.w,
+                    k: {},
+                    d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) {
+                            return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M";
+                        }) + "z"
+                };
+                if (path.k) {
+                    for (var k in path.k) if (path[has](k)) {
+                        fontcopy.glyphs[glyph].k[k] = path.k[k];
+                    }
+                }
+            }
+        }
+        return font;
+    };
+    
+    paperproto.getFont = function (family, weight, style, stretch) {
+        stretch = stretch || "normal";
+        style = style || "normal";
+        weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;
+        if (!R.fonts) {
+            return;
+        }
+        var font = R.fonts[family];
+        if (!font) {
+            var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i");
+            for (var fontName in R.fonts) if (R.fonts[has](fontName)) {
+                if (name.test(fontName)) {
+                    font = R.fonts[fontName];
+                    break;
+                }
+            }
+        }
+        var thefont;
+        if (font) {
+            for (var i = 0, ii = font.length; i < ii; i++) {
+                thefont = font[i];
+                if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) {
+                    break;
+                }
+            }
+        }
+        return thefont;
+    };
+    
+    paperproto.print = function (x, y, string, font, size, origin, letter_spacing) {
+        origin = origin || "middle"; // baseline|middle
+        letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);
+        var out = this.set(),
+            letters = Str(string)[split](E),
+            shift = 0,
+            path = E,
+            scale;
+        R.is(font, string) && (font = this.getFont(font));
+        if (font) {
+            scale = (size || 16) / font.face["units-per-em"];
+            var bb = font.face.bbox[split](separator),
+                top = +bb[0],
+                height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2);
+            for (var i = 0, ii = letters.length; i < ii; i++) {
+                var prev = i && font.glyphs[letters[i - 1]] || {},
+                    curr = font.glyphs[letters[i]];
+                shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;
+                curr && curr.d && out.push(this.path(curr.d).attr({
+                    fill: "#000",
+                    stroke: "none",
+                    transform: [["t", shift * scale, 0]]
+                }));
+            }
+            out.transform(["...s", scale, scale, top, height, "t", (x - top) / scale, (y - height) / scale]);
+        }
+        return out;
+    };
+
+    
+    R.format = function (token, params) {
+        var args = R.is(params, array) ? [0][concat](params) : arguments;
+        token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {
+            return args[++i] == null ? E : args[i];
+        }));
+        return token || E;
+    };
+    
+    R.fullfill = (function () {
+        var tokenRegex = /\{([^\}]+)\}/g,
+            objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties
+            replacer = function (all, key, obj) {
+                var res = obj;
+                key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
+                    name = name || quotedName;
+                    if (res) {
+                        if (name in res) {
+                            res = res[name];
+                        }
+                        typeof res == "function" && isFunc && (res = res());
+                    }
+                });
+                res = (res == null || res == obj ? all : res) + "";
+                return res;
+            };
+        return function (str, obj) {
+            return String(str).replace(tokenRegex, function (all, key) {
+                return replacer(all, key, obj);
+            });
+        };
+    })();
+    
+    R.ninja = function () {
+        oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael;
+        return R;
+    };
+    
+    R.st = setproto;
+    // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
+    (function (doc, loaded, f) {
+        if (doc.readyState == null && doc.addEventListener){
+            doc.addEventListener(loaded, f = function () {
+                doc.removeEventListener(loaded, f, false);
+                doc.readyState = "complete";
+            }, false);
+            doc.readyState = "loading";
+        }
+        function isLoaded() {
+            (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve("DOMload");
+        }
+        isLoaded();
+    })(document, "DOMContentLoaded");
+
+    oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R);
+    
+    eve.on("DOMload", function () {
+        loaded = true;
+    });
+})();
+
+// ┌─────────────────────────────────────────────────────────────────────┐ \\
+// │ Raphaël 2 - JavaScript Vector Library                               │ \\
+// ├─────────────────────────────────────────────────────────────────────┤ \\
+// │ SVG Module                                                          │ \\
+// ├─────────────────────────────────────────────────────────────────────┤ \\
+// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\
+// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\
+// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
+// └─────────────────────────────────────────────────────────────────────┘ \\
+window.Raphael.svg && function (R) {
+    var has = "hasOwnProperty",
+        Str = String,
+        toFloat = parseFloat,
+        toInt = parseInt,
+        math = Math,
+        mmax = math.max,
+        abs = math.abs,
+        pow = math.pow,
+        separator = /[, ]+/,
+        eve = R.eve,
+        E = "",
+        S = " ";
+    var xlink = "http://www.w3.org/1999/xlink",
+        markers = {
+            block: "M5,0 0,2.5 5,5z",
+            classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
+            diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z",
+            open: "M6,1 1,3.5 6,6",
+            oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
+        },
+        markerCounter = {};
+    R.toString = function () {
+        return  "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
+    };
+    var $ = function (el, attr) {
+        if (attr) {
+            if (typeof el == "string") {
+                el = $(el);
+            }
+            for (var key in attr) if (attr[has](key)) {
+                if (key.substring(0, 6) == "xlink:") {
+                    el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));
+                } else {
+                    el.setAttribute(key, Str(attr[key]));
+                }
+            }
+        } else {
+            el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el);
+            el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)");
+        }
+        return el;
+    },
+    gradients = {},
+    rgGrad = /^url\(#(.*)\)$/,
+    removeGradientFill = function (node, paper) {
+        var oid = node.getAttribute("fill");
+        oid = oid && oid.match(rgGrad);
+        if (oid && !--gradients[oid[1]]) {
+            delete gradients[oid[1]];
+            paper.defs.removeChild(R._g.doc.getElementById(oid[1]));
+        }
+    },
+    addGradientFill = function (element, gradient) {
+        var type = "linear",
+            id = element.id + gradient,
+            fx = .5, fy = .5,
+            o = element.node,
+            SVG = element.paper,
+            s = o.style,
+            el = R._g.doc.getElementById(id);
+        if (!el) {
+            gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {
+                type = "radial";
+                if (_fx && _fy) {
+                    fx = toFloat(_fx);
+                    fy = toFloat(_fy);
+                    var dir = ((fy > .5) * 2 - 1);
+                    pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&
+                        (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&
+                        fy != .5 &&
+                        (fy = fy.toFixed(5) - 1e-5 * dir);
+                }
+                return E;
+            });
+            gradient = gradient.split(/\s*\-\s*/);
+            if (type == "linear") {
+                var angle = gradient.shift();
+                angle = -toFloat(angle);
+                if (isNaN(angle)) {
+                    return null;
+                }
+                var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],
+                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
+                vector[2] *= max;
+                vector[3] *= max;
+                if (vector[2] < 0) {
+                    vector[0] = -vector[2];
+                    vector[2] = 0;
+                }
+                if (vector[3] < 0) {
+                    vector[1] = -vector[3];
+                    vector[3] = 0;
+                }
+            }
+            var dots = R._parseDots(gradient);
+            if (!dots) {
+                return null;
+            }
+            if (element.gradient) {
+                SVG.defs.removeChild(element.gradient);
+                delete element.gradient;
+            }
+
+            id = id.replace(/[\(\)\s,\xb0#]/g, "-");
+            el = $(type + "Gradient", {id: id});
+            element.gradient = el;
+            $(el, type == "radial" ? {
+                fx: fx,
+                fy: fy
+            } : {
+                x1: vector[0],
+                y1: vector[1],
+                x2: vector[2],
+                y2: vector[3],
+                gradientTransform: element.matrix.invert()
+            });
+            SVG.defs.appendChild(el);
+            for (var i = 0, ii = dots.length; i < ii; i++) {
+                el.appendChild($("stop", {
+                    offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%",
+                    "stop-color": dots[i].color || "#fff"
+                }));
+            }
+        }
+        $(o, {
+            fill: "url(#" + id + ")",
+            opacity: 1,
+            "fill-opacity": 1
+        });
+        s.fill = E;
+        s.opacity = 1;
+        s.fillOpacity = 1;
+        return 1;
+    },
+    updatePosition = function (o) {
+        var bbox = o.getBBox(1);
+        $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"});
+    },
+    addArrow = function (o, value, isEnd) {
+        if (o.type == "path") {
+            var values = Str(value).toLowerCase().split("-"),
+                p = o.paper,
+                se = isEnd ? "end" : "start",
+                node = o.node,
+                attrs = o.attrs,
+                stroke = attrs["stroke-width"],
+                i = values.length,
+                type = "classic",
+                from,
+                to,
+                dx,
+                refX,
+                attr,
+                w = 3,
+                h = 3,
+                t = 5;
+            while (i--) {
+                switch (values[i]) {
+                    case "block":
+                    case "classic":
+                    case "oval":
+                    case "diamond":
+                    case "open":
+                    case "none":
+                        type = values[i];
+                        break;
+                    case "wide": h = 5; break;
+                    case "narrow": h = 2; break;
+                    case "long": w = 5; break;
+                    case "short": w = 2; break;
+                }
+            }
+            if (type == "open") {
+                w += 2;
+                h += 2;
+                t += 2;
+                dx = 1;
+                refX = isEnd ? 4 : 1;
+                attr = {
+                    fill: "none",
+                    stroke: attrs.stroke
+                };
+            } else {
+                refX = dx = w / 2;
+                attr = {
+                    fill: attrs.stroke,
+                    stroke: "none"
+                };
+            }
+            if (o._.arrows) {
+                if (isEnd) {
+                    o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;
+                    o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;
+                } else {
+                    o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;
+                    o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;
+                }
+            } else {
+                o._.arrows = {};
+            }
+            if (type != "none") {
+                var pathId = "raphael-marker-" + type,
+                    markerId = "raphael-marker-" + se + type + w + h;
+                if (!R._g.doc.getElementById(pathId)) {
+                    p.defs.appendChild($($("path"), {
+                        "stroke-linecap": "round",
+                        d: markers[type],
+                        id: pathId
+                    }));
+                    markerCounter[pathId] = 1;
+                } else {
+                    markerCounter[pathId]++;
+                }
+                var marker = R._g.doc.getElementById(markerId),
+                    use;
+                if (!marker) {
+                    marker = $($("marker"), {
+                        id: markerId,
+                        markerHeight: h,
+                        markerWidth: w,
+                        orient: "auto",
+                        refX: refX,
+                        refY: h / 2
+                    });
+                    use = $($("use"), {
+                        "xlink:href": "#" + pathId,
+                        transform: (isEnd ? " rotate(180 " + w / 2 + " " + h / 2 + ") " : S) + "scale(" + w / t + "," + h / t + ")",
+                        "stroke-width": 1 / ((w / t + h / t) / 2)
+                    });
+                    marker.appendChild(use);
+                    p.defs.appendChild(marker);
+                    markerCounter[markerId] = 1;
+                } else {
+                    markerCounter[markerId]++;
+                    use = marker.getElementsByTagName("use")[0];
+                }
+                $(use, attr);
+                var delta = dx * (type != "diamond" && type != "oval");
+                if (isEnd) {
+                    from = o._.arrows.startdx * stroke || 0;
+                    to = R.getTotalLength(attrs.path) - delta * stroke;
+                } else {
+                    from = delta * stroke;
+                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
+                }
+                attr = {};
+                attr["marker-" + se] = "url(#" + markerId + ")";
+                if (to || from) {
+                    attr.d = Raphael.getSubpath(attrs.path, from, to);
+                }
+                $(node, attr);
+                o._.arrows[se + "Path"] = pathId;
+                o._.arrows[se + "Marker"] = markerId;
+                o._.arrows[se + "dx"] = delta;
+                o._.arrows[se + "Type"] = type;
+                o._.arrows[se + "String"] = value;
+            } else {
+                if (isEnd) {
+                    from = o._.arrows.startdx * stroke || 0;
+                    to = R.getTotalLength(attrs.path) - from;
+                } else {
+                    from = 0;
+                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
+                }
+                o._.arrows[se + "Path"] && $(node, {d: Raphael.getSubpath(attrs.path, from, to)});
+                delete o._.arrows[se + "Path"];
+                delete o._.arrows[se + "Marker"];
+                delete o._.arrows[se + "dx"];
+                delete o._.arrows[se + "Type"];
+                delete o._.arrows[se + "String"];
+            }
+            for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {
+                var item = R._g.doc.getElementById(attr);
+                item && item.parentNode.removeChild(item);
+            }
+        }
+    },
+    dasharray = {
+        "": [0],
+        "none": [0],
+        "-": [3, 1],
+        ".": [1, 1],
+        "-.": [3, 1, 1, 1],
+        "-..": [3, 1, 1, 1, 1, 1],
+        ". ": [1, 3],
+        "- ": [4, 3],
+        "--": [8, 3],
+        "- .": [4, 3, 1, 3],
+        "--.": [8, 3, 1, 3],
+        "--..": [8, 3, 1, 3, 1, 3]
+    },
+    addDashes = function (o, value, params) {
+        value = dasharray[Str(value).toLowerCase()];
+        if (value) {
+            var width = o.attrs["stroke-width"] || "1",
+                butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
+                dashes = [],
+                i = value.length;
+            while (i--) {
+                dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
+            }
+            $(o.node, {"stroke-dasharray": dashes.join(",")});
+        }
+    },
+    setFillAndStroke = function (o, params) {
+        var node = o.node,
+            attrs = o.attrs,
+            vis = node.style.visibility;
+        node.style.visibility = "hidden";
+        for (var att in params) {
+            if (params[has](att)) {
+                if (!R._availableAttrs[has](att)) {
+                    continue;
+                }
+                var value = params[att];
+                attrs[att] = value;
+                switch (att) {
+                    case "blur":
+                        o.blur(value);
+                        break;
+                    case "href":
+                    case "title":
+                    case "target":
+                        var pn = node.parentNode;
+                        if (pn.tagName.toLowerCase() != "a") {
+                            var hl = $("a");
+                            pn.insertBefore(hl, node);
+                            hl.appendChild(node);
+                            pn = hl;
+                        }
+                        if (att == "target" && value == "blank") {
+                            pn.setAttributeNS(xlink, "show", "new");
+                        } else {
+                            pn.setAttributeNS(xlink, att, value);
+                        }
+                        break;
+                    case "cursor":
+                        node.style.cursor = value;
+                        break;
+                    case "transform":
+                        o.transform(value);
+                        break;
+                    case "arrow-start":
+                        addArrow(o, value);
+                        break;
+                    case "arrow-end":
+                        addArrow(o, value, 1);
+                        break;
+                    case "clip-rect":
+                        var rect = Str(value).split(separator);
+                        if (rect.length == 4) {
+                            o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);
+                            var el = $("clipPath"),
+                                rc = $("rect");
+                            el.id = R.createUUID();
+                            $(rc, {
+                                x: rect[0],
+                                y: rect[1],
+                                width: rect[2],
+                                height: rect[3]
+                            });
+                            el.appendChild(rc);
+                            o.paper.defs.appendChild(el);
+                            $(node, {"clip-path": "url(#" + el.id + ")"});
+                            o.clip = rc;
+                        }
+                        if (!value) {
+                            var clip = R._g.doc.getElementById(node.getAttribute("clip-path").replace(/(^url\(#|\)$)/g, E));
+                            clip && clip.parentNode.removeChild(clip);
+                            $(node, {"clip-path": E});
+                            delete o.clip;
+                        }
+                    break;
+                    case "path":
+                        if (o.type == "path") {
+                            $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"});
+                            o._.dirty = 1;
+                            if (o._.arrows) {
+                                "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
+                                "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
+                            }
+                        }
+                        break;
+                    case "width":
+                        node.setAttribute(att, value);
+                        o._.dirty = 1;
+                        if (attrs.fx) {
+                            att = "x";
+                            value = attrs.x;
+                        } else {
+                            break;
+                        }
+                    case "x":
+                        if (attrs.fx) {
+                            value = -attrs.x - (attrs.width || 0);
+                        }
+                    case "rx":
+                        if (att == "rx" && o.type == "rect") {
+                            break;
+                        }
+                    case "cx":
+                        node.setAttribute(att, value);
+                        o.pattern && updatePosition(o);
+                        o._.dirty = 1;
+                        break;
+                    case "height":
+                        node.setAttribute(att, value);
+                        o._.dirty = 1;
+                        if (attrs.fy) {
+                            att = "y";
+                            value = attrs.y;
+                        } else {
+                            break;
+                        }
+                    case "y":
+                        if (attrs.fy) {
+                            value = -attrs.y - (attrs.height || 0);
+                        }
+                    case "ry":
+                        if (att == "ry" && o.type == "rect") {
+                            break;
+                        }
+                    case "cy":
+                        node.setAttribute(att, value);
+                        o.pattern && updatePosition(o);
+                        o._.dirty = 1;
+                        break;
+                    case "r":
+                        if (o.type == "rect") {
+                            $(node, {rx: value, ry: value});
+                        } else {
+                            node.setAttribute(att, value);
+                        }
+                        o._.dirty = 1;
+                        break;
+                    case "src":
+                        if (o.type == "image") {
+                            node.setAttributeNS(xlink, "href", value);
+                        }
+                        break;
+                    case "stroke-width":
+                        if (o._.sx != 1 || o._.sy != 1) {
+                            value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;
+                        }
+                        if (o.paper._vbSize) {
+                            value *= o.paper._vbSize;
+                        }
+                        node.setAttribute(att, value);
+                        if (attrs["stroke-dasharray"]) {
+                            addDashes(o, attrs["stroke-dasharray"], params);
+                        }
+                        if (o._.arrows) {
+                            "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
+                            "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
+                        }
+                        break;
+                    case "stroke-dasharray":
+                        addDashes(o, value, params);
+                        break;
+                    case "fill":
+                        var isURL = Str(value).match(R._ISURL);
+                        if (isURL) {
+                            el = $("pattern");
+                            var ig = $("image");
+                            el.id = R.createUUID();
+                            $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1});
+                            $(ig, {x: 0, y: 0, "xlink:href": isURL[1]});
+                            el.appendChild(ig);
+
+                            (function (el) {
+                                R._preload(isURL[1], function () {
+                                    var w = this.offsetWidth,
+                                        h = this.offsetHeight;
+                                    $(el, {width: w, height: h});
+                                    $(ig, {width: w, height: h});
+                                    o.paper.safari();
+                                });
+                            })(el);
+                            o.paper.defs.appendChild(el);
+                            node.style.fill = "url(#" + el.id + ")";
+                            $(node, {fill: "url(#" + el.id + ")"});
+                            o.pattern = el;
+                            o.pattern && updatePosition(o);
+                            break;
+                        }
+                        var clr = R.getRGB(value);
+                        if (!clr.error) {
+                            delete params.gradient;
+                            delete attrs.gradient;
+                            !R.is(attrs.opacity, "undefined") &&
+                                R.is(params.opacity, "undefined") &&
+                                $(node, {opacity: attrs.opacity});
+                            !R.is(attrs["fill-opacity"], "undefined") &&
+                                R.is(params["fill-opacity"], "undefined") &&
+                                $(node, {"fill-opacity": attrs["fill-opacity"]});
+                        } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) {
+                            if ("opacity" in attrs || "fill-opacity" in attrs) {
+                                var gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
+                                if (gradient) {
+                                    var stops = gradient.getElementsByTagName("stop");
+                                    $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)});
+                                }
+                            }
+                            attrs.gradient = value;
+                            attrs.fill = "none";
+                            break;
+                        }
+                        clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
+                    case "stroke":
+                        clr = R.getRGB(value);
+                        node.setAttribute(att, clr.hex);
+                        att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
+                        if (att == "stroke" && o._.arrows) {
+                            "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
+                            "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
+                        }
+                        break;
+                    case "gradient":
+                        (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value);
+                        break;
+                    case "opacity":
+                        if (attrs.gradient && !attrs[has]("stroke-opacity")) {
+                            $(node, {"stroke-opacity": value > 1 ? value / 100 : value});
+                        }
+                        // fall
+                    case "fill-opacity":
+                        if (attrs.gradient) {
+                            gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
+                            if (gradient) {
+                                stops = gradient.getElementsByTagName("stop");
+                                $(stops[stops.length - 1], {"stop-opacity": value});
+                            }
+                            break;
+                        }
+                    default:
+                        att == "font-size" && (value = toInt(value, 10) + "px");
+                        var cssrule = att.replace(/(\-.)/g, function (w) {
+                            return w.substring(1).toUpperCase();
+                        });
+                        node.style[cssrule] = value;
+                        o._.dirty = 1;
+                        node.setAttribute(att, value);
+                        break;
+                }
+            }
+        }
+
+        tuneText(o, params);
+        node.style.visibility = vis;
+    },
+    leading = 1.2,
+    tuneText = function (el, params) {
+        if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) {
+            return;
+        }
+        var a = el.attrs,
+            node = el.node,
+            fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10;
+
+        if (params[has]("text")) {
+            a.text = params.text;
+            while (node.firstChild) {
+                node.removeChild(node.firstChild);
+            }
+            var texts = Str(params.text).split("\n"),
+                tspans = [],
+                tspan;
+            for (var i = 0, ii = texts.length; i < ii; i++) {
+                tspan = $("tspan");
+                i && $(tspan, {dy: fontSize * leading, x: a.x});
+                tspan.appendChild(R._g.doc.createTextNode(texts[i]));
+                node.appendChild(tspan);
+                tspans[i] = tspan;
+            }
+        } else {
+            tspans = node.getElementsByTagName("tspan");
+            for (i = 0, ii = tspans.length; i < ii; i++) if (i) {
+                $(tspans[i], {dy: fontSize * leading, x: a.x});
+            } else {
+                $(tspans[0], {dy: 0});
+            }
+        }
+        $(node, {x: a.x, y: a.y});
+        el._.dirty = 1;
+        var bb = el._getBBox(),
+            dif = a.y - (bb.y + bb.height / 2);
+        dif && R.is(dif, "finite") && $(tspans[0], {dy: dif});
+    },
+    Element = function (node, svg) {
+        var X = 0,
+            Y = 0;
+        
+        this[0] = this.node = node;
+        
+        node.raphael = true;
+        
+        this.id = R._oid++;
+        node.raphaelid = this.id;
+        this.matrix = R.matrix();
+        this.realPath = null;
+        
+        this.paper = svg;
+        this.attrs = this.attrs || {};
+        this._ = {
+            transform: [],
+            sx: 1,
+            sy: 1,
+            deg: 0,
+            dx: 0,
+            dy: 0,
+            dirty: 1
+        };
+        !svg.bottom && (svg.bottom = this);
+        
+        this.prev = svg.top;
+        svg.top && (svg.top.next = this);
+        svg.top = this;
+        
+        this.next = null;
+    },
+    elproto = R.el;
+
+    Element.prototype = elproto;
+    elproto.constructor = Element;
+
+    R._engine.path = function (pathString, SVG) {
+        var el = $("path");
+        SVG.canvas && SVG.canvas.appendChild(el);
+        var p = new Element(el, SVG);
+        p.type = "path";
+        setFillAndStroke(p, {
+            fill: "none",
+            stroke: "#000",
+            path: pathString
+        });
+        return p;
+    };
+    
+    elproto.rotate = function (deg, cx, cy) {
+        if (this.removed) {
+            return this;
+        }
+        deg = Str(deg).split(separator);
+        if (deg.length - 1) {
+            cx = toFloat(deg[1]);
+            cy = toFloat(deg[2]);
+        }
+        deg = toFloat(deg[0]);
+        (cy == null) && (cx = cy);
+        if (cx == null || cy == null) {
+            var bbox = this.getBBox(1);
+            cx = bbox.x + bbox.width / 2;
+            cy = bbox.y + bbox.height / 2;
+        }
+        this.transform(this._.transform.concat([["r", deg, cx, cy]]));
+        return this;
+    };
+    
+    elproto.scale = function (sx, sy, cx, cy) {
+        if (this.removed) {
+            return this;
+        }
+        sx = Str(sx).split(separator);
+        if (sx.length - 1) {
+            sy = toFloat(sx[1]);
+            cx = toFloat(sx[2]);
+            cy = toFloat(sx[3]);
+        }
+        sx = toFloat(sx[0]);
+        (sy == null) && (sy = sx);
+        (cy == null) && (cx = cy);
+        if (cx == null || cy == null) {
+            var bbox = this.getBBox(1);
+        }
+        cx = cx == null ? bbox.x + bbox.width / 2 : cx;
+        cy = cy == null ? bbox.y + bbox.height / 2 : cy;
+        this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
+        return this;
+    };
+    
+    elproto.translate = function (dx, dy) {
+        if (this.removed) {
+            return this;
+        }
+        dx = Str(dx).split(separator);
+        if (dx.length - 1) {
+            dy = toFloat(dx[1]);
+        }
+        dx = toFloat(dx[0]) || 0;
+        dy = +dy || 0;
+        this.transform(this._.transform.concat([["t", dx, dy]]));
+        return this;
+    };
+    
+    elproto.transform = function (tstr) {
+        var _ = this._;
+        if (tstr == null) {
+            return _.transform;
+        }
+        R._extractTransform(this, tstr);
+
+        this.clip && $(this.clip, {transform: this.matrix.invert()});
+        this.pattern && updatePosition(this);
+        this.node && $(this.node, {transform: this.matrix});
+    
+        if (_.sx != 1 || _.sy != 1) {
+            var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1;
+            this.attr({"stroke-width": sw});
+        }
+
+        return this;
+    };
+    
+    elproto.hide = function () {
+        !this.removed && this.paper.safari(this.node.style.display = "none");
+        return this;
+    };
+    
+    elproto.show = function () {
+        !this.removed && this.paper.safari(this.node.style.display = "");
+        return this;
+    };
+    
+    elproto.remove = function () {
+        if (this.removed) {
+            return;
+        }
+        this.paper.__set__ && this.paper.__set__.exclude(this);
+        eve.unbind("*.*." + this.id);
+        R._tear(this, this.paper);
+        this.node.parentNode.removeChild(this.node);
+        for (var i in this) {
+            delete this[i];
+        }
+        this.removed = true;
+    };
+    elproto._getBBox = function () {
+        if (this.node.style.display == "none") {
+            this.show();
+            var hide = true;
+        }
+        var bbox = {};
+        try {
+            bbox = this.node.getBBox();
+        } catch(e) {
+            // Firefox 3.0.x plays badly here
+        } finally {
+            bbox = bbox || {};
+        }
+        hide && this.hide();
+        return bbox;
+    };
+    
+    elproto.attr = function (name, value) {
+        if (this.removed) {
+            return this;
+        }
+        if (name == null) {
+            var res = {};
+            for (var a in this.attrs) if (this.attrs[has](a)) {
+                res[a] = this.attrs[a];
+            }
+            res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
+            res.transform = this._.transform;
+            return res;
+        }
+        if (value == null && R.is(name, "string")) {
+            if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) {
+                return this.attrs.gradient;
+            }
+            if (name == "transform") {
+                return this._.transform;
+            }
+            var names = name.split(separator),
+                out = {};
+            for (var i = 0, ii = names.length; i < ii; i++) {
+                name = names[i];
+                if (name in this.attrs) {
+                    out[name] = this.attrs[name];
+                } else if (R.is(this.paper.customAttributes[name], "function")) {
+                    out[name] = this.paper.customAttributes[name].def;
+                } else {
+                    out[name] = R._availableAttrs[name];
+                }
+            }
+            return ii - 1 ? out : out[names[0]];
+        }
+        if (value == null && R.is(name, "array")) {
+            out = {};
+            for (i = 0, ii = name.length; i < ii; i++) {
+                out[name[i]] = this.attr(name[i]);
+            }
+            return out;
+        }
+        if (value != null) {
+            var params = {};
+            params[name] = value;
+        } else if (name != null && R.is(name, "object")) {
+            params = name;
+        }
+        for (var key in params) {
+            eve("attr." + key + "." + this.id, this, params[key]);
+        }
+        for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
+            var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
+            this.attrs[key] = params[key];
+            for (var subkey in par) if (par[has](subkey)) {
+                params[subkey] = par[subkey];
+            }
+        }
+        setFillAndStroke(this, params);
+        return this;
+    };
+    
+    elproto.toFront = function () {
+        if (this.removed) {
+            return this;
+        }
+        this.node.parentNode.appendChild(this.node);
+        var svg = this.paper;
+        svg.top != this && R._tofront(this, svg);
+        return this;
+    };
+    
+    elproto.toBack = function () {
+        if (this.removed) {
+            return this;
+        }
+        if (this.node.parentNode.firstChild != this.node) {
+            this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
+            R._toback(this, this.paper);
+            var svg = this.paper;
+        }
+        return this;
+    };
+    
+    elproto.insertAfter = function (element) {
+        if (this.removed) {
+            return this;
+        }
+        var node = element.node || element[element.length - 1].node;
+        if (node.nextSibling) {
+            node.parentNode.insertBefore(this.node, node.nextSibling);
+        } else {
+            node.parentNode.appendChild(this.node);
+        }
+        R._insertafter(this, element, this.paper);
+        return this;
+    };
+    
+    elproto.insertBefore = function (element) {
+        if (this.removed) {
+            return this;
+        }
+        var node = element.node || element[0].node;
+        node.parentNode.insertBefore(this.node, node);
+        R._insertbefore(this, element, this.paper);
+        return this;
+    };
+    elproto.blur = function (size) {
+        // Experimental. No Safari support. Use it on your own risk.
+        var t = this;
+        if (+size !== 0) {
+            var fltr = $("filter"),
+                blur = $("feGaussianBlur");
+            t.attrs.blur = size;
+            fltr.id = R.createUUID();
+            $(blur, {stdDeviation: +size || 1.5});
+            fltr.appendChild(blur);
+            t.paper.defs.appendChild(fltr);
+            t._blur = fltr;
+            $(t.node, {filter: "url(#" + fltr.id + ")"});
+        } else {
+            if (t._blur) {
+                t._blur.parentNode.removeChild(t._blur);
+                delete t._blur;
+                delete t.attrs.blur;
+            }
+            t.node.removeAttribute("filter");
+        }
+    };
+    R._engine.circle = function (svg, x, y, r) {
+        var el = $("circle");
+        svg.canvas && svg.canvas.appendChild(el);
+        var res = new Element(el, svg);
+        res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"};
+        res.type = "circle";
+        $(el, res.attrs);
+        return res;
+    };
+    R._engine.rect = function (svg, x, y, w, h, r) {
+        var el = $("rect");
+        svg.canvas && svg.canvas.appendChild(el);
+        var res = new Element(el, svg);
+        res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"};
+        res.type = "rect";
+        $(el, res.attrs);
+        return res;
+    };
+    R._engine.ellipse = function (svg, x, y, rx, ry) {
+        var el = $("ellipse");
+        svg.canvas && svg.canvas.appendChild(el);
+        var res = new Element(el, svg);
+        res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"};
+        res.type = "ellipse";
+        $(el, res.attrs);
+        return res;
+    };
+    R._engine.image = function (svg, src, x, y, w, h) {
+        var el = $("image");
+        $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});
+        el.setAttributeNS(xlink, "href", src);
+        svg.canvas && svg.canvas.appendChild(el);
+        var res = new Element(el, svg);
+        res.attrs = {x: x, y: y, width: w, height: h, src: src};
+        res.type = "image";
+        return res;
+    };
+    R._engine.text = function (svg, x, y, text) {
+        var el = $("text");
+        // $(el, {x: x, y: y, "text-anchor": "middle"});
+        svg.canvas && svg.canvas.appendChild(el);
+        var res = new Element(el, svg);
+        res.attrs = {
+            x: x,
+            y: y,
+            "text-anchor": "middle",
+            text: text,
+            font: R._availableAttrs.font,
+            stroke: "none",
+            fill: "#000"
+        };
+        res.type = "text";
+        setFillAndStroke(res, res.attrs);
+        return res;
+    };
+    R._engine.setSize = function (width, height) {
+        this.width = width || this.width;
+        this.height = height || this.height;
+        this.canvas.setAttribute("width", this.width);
+        this.canvas.setAttribute("height", this.height);
+        if (this._viewBox) {
+            this.setViewBox.apply(this, this._viewBox);
+        }
+        return this;
+    };
+    R._engine.create = function () {
+        var con = R._getContainer.apply(0, arguments),
+            container = con && con.container,
+            x = con.x,
+            y = con.y,
+            width = con.width,
+            height = con.height;
+        if (!container) {
+            throw new Error("SVG container not found.");
+        }
+        var cnvs = $("svg"),
+            css = "overflow:hidden;",
+            isFloating;
+        x = x || 0;
+        y = y || 0;
+        width = width || 512;
+        height = height || 342;
+        $(cnvs, {
+            height: height,
+            version: 1.1,
+            width: width,
+            xmlns: "http://www.w3.org/2000/svg"
+        });
+        if (container == 1) {
+            cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px";
+            R._g.doc.body.appendChild(cnvs);
+            isFloating = 1;
+        } else {
+            cnvs.style.cssText = css + "position:relative";
+            if (container.firstChild) {
+                container.insertBefore(cnvs, container.firstChild);
+            } else {
+                container.appendChild(cnvs);
+            }
+        }
+        container = new R._Paper;
+        container.width = width;
+        container.height = height;
+        container.canvas = cnvs;
+        // plugins.call(container, container, R.fn);
+        container.clear();
+        container._left = container._top = 0;
+        isFloating && (container.renderfix = function () {});
+        container.renderfix();
+        return container;
+    };
+    R._engine.setViewBox = function (x, y, w, h, fit) {
+        eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]);
+        var size = mmax(w / this.width, h / this.height),
+            top = this.top,
+            aspectRatio = fit ? "meet" : "xMinYMin",
+            vb,
+            sw;
+        if (x == null) {
+            if (this._vbSize) {
+                size = 1;
+            }
+            delete this._vbSize;
+            vb = "0 0 " + this.width + S + this.height;
+        } else {
+            this._vbSize = size;
+            vb = x + S + y + S + w + S + h;
+        }
+        $(this.canvas, {
+            viewBox: vb,
+            preserveAspectRatio: aspectRatio
+        });
+        while (size && top) {
+            sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1;
+            top.attr({"stroke-width": sw});
+            top._.dirty = 1;
+            top._.dirtyT = 1;
+            top = top.prev;
+        }
+        this._viewBox = [x, y, w, h, !!fit];
+        return this;
+    };
+    
+    R.prototype.renderfix = function () {
+        var cnvs = this.canvas,
+            s = cnvs.style,
+            pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix(),
+            left = -pos.e % 1,
+            top = -pos.f % 1;
+        if (left || top) {
+            if (left) {
+                this._left = (this._left + left) % 1;
+                s.left = this._left + "px";
+            }
+            if (top) {
+                this._top = (this._top + top) % 1;
+                s.top = this._top + "px";
+            }
+        }
+    };
+    
+    R.prototype.clear = function () {
+        R.eve("clear", this);
+        var c = this.canvas;
+        while (c.firstChild) {
+            c.removeChild(c.firstChild);
+        }
+        this.bottom = this.top = null;
+        (this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version));
+        c.appendChild(this.desc);
+        c.appendChild(this.defs = $("defs"));
+    };
+    
+    R.prototype.remove = function () {
+        eve("remove", this);
+        this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
+        for (var i in this) {
+            this[i] = removed(i);
+        }
+    };
+    var setproto = R.st;
+    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
+        setproto[method] = (function (methodname) {
+            return function () {
+                var arg = arguments;
+                return this.forEach(function (el) {
+                    el[methodname].apply(el, arg);
+                });
+            };
+        })(method);
+    }
+}(window.Raphael);
+
+// ┌─────────────────────────────────────────────────────────────────────┐ \\
+// │ Raphaël 2 - JavaScript Vector Library                               │ \\
+// ├─────────────────────────────────────────────────────────────────────┤ \\
+// │ VML Module                                                          │ \\
+// ├─────────────────────────────────────────────────────────────────────┤ \\
+// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\
+// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\
+// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
+// └─────────────────────────────────────────────────────────────────────┘ \\
+window.Raphael.vml && function (R) {
+    var has = "hasOwnProperty",
+        Str = String,
+        toFloat = parseFloat,
+        math = Math,
+        round = math.round,
+        mmax = math.max,
+        mmin = math.min,
+        abs = math.abs,
+        fillString = "fill",
+        separator = /[, ]+/,
+        eve = R.eve,
+        ms = " progid:DXImageTransform.Microsoft",
+        S = " ",
+        E = "",
+        map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
+        bites = /([clmz]),?([^clmz]*)/gi,
+        blurregexp = / progid:\S+Blur\([^\)]+\)/g,
+        val = /-?[^,\s-]+/g,
+        cssDot = "position:absolute;left:0;top:0;width:1px;height:1px",
+        zoom = 21600,
+        pathTypes = {path: 1, rect: 1, image: 1},
+        ovalTypes = {circle: 1, ellipse: 1},
+        path2vml = function (path) {
+            var total =  /[ahqstv]/ig,
+                command = R._pathToAbsolute;
+            Str(path).match(total) && (command = R._path2curve);
+            total = /[clmz]/g;
+            if (command == R._pathToAbsolute && !Str(path).match(total)) {
+                var res = Str(path).replace(bites, function (all, command, args) {
+                    var vals = [],
+                        isMove = command.toLowerCase() == "m",
+                        res = map[command];
+                    args.replace(val, function (value) {
+                        if (isMove && vals.length == 2) {
+                            res += vals + map[command == "m" ? "l" : "L"];
+                            vals = [];
+                        }
+                        vals.push(round(value * zoom));
+                    });
+                    return res + vals;
+                });
+                return res;
+            }
+            var pa = command(path), p, r;
+            res = [];
+            for (var i = 0, ii = pa.length; i < ii; i++) {
+                p = pa[i];
+                r = pa[i][0].toLowerCase();
+                r == "z" && (r = "x");
+                for (var j = 1, jj = p.length; j < jj; j++) {
+                    r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);
+                }
+                res.push(r);
+            }
+            return res.join(S);
+        },
+        compensation = function (deg, dx, dy) {
+            var m = R.matrix();
+            m.rotate(-deg, .5, .5);
+            return {
+                dx: m.x(dx, dy),
+                dy: m.y(dx, dy)
+            };
+        },
+        setCoords = function (p, sx, sy, dx, dy, deg) {
+            var _ = p._,
+                m = p.matrix,
+                fillpos = _.fillpos,
+                o = p.node,
+                s = o.style,
+                y = 1,
+                flip = "",
+                dxdy,
+                kx = zoom / sx,
+                ky = zoom / sy;
+            s.visibility = "hidden";
+            if (!sx || !sy) {
+                return;
+            }
+            o.coordsize = abs(kx) + S + abs(ky);
+            s.rotation = deg * (sx * sy < 0 ? -1 : 1);
+            if (deg) {
+                var c = compensation(deg, dx, dy);
+                dx = c.dx;
+                dy = c.dy;
+            }
+            sx < 0 && (flip += "x");
+            sy < 0 && (flip += " y") && (y = -1);
+            s.flip = flip;
+            o.coordorigin = (dx * -kx) + S + (dy * -ky);
+            if (fillpos || _.fillsize) {
+                var fill = o.getElementsByTagName(fillString);
+                fill = fill && fill[0];
+                o.removeChild(fill);
+                if (fillpos) {
+                    c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));
+                    fill.position = c.dx * y + S + c.dy * y;
+                }
+                if (_.fillsize) {
+                    fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);
+                }
+                o.appendChild(fill);
+            }
+            s.visibility = "visible";
+        };
+    R.toString = function () {
+        return  "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;
+    };
+    addArrow = function (o, value, isEnd) {
+        var values = Str(value).toLowerCase().split("-"),
+            se = isEnd ? "end" : "start",
+            i = values.length,
+            type = "classic",
+            w = "medium",
+            h = "medium";
+        while (i--) {
+            switch (values[i]) {
+                case "block":
+                case "classic":
+                case "oval":
+                case "diamond":
+                case "open":
+                case "none":
+                    type = values[i];
+                    break;
+                case "wide":
+                case "narrow": h = values[i]; break;
+                case "long":
+                case "short": w = values[i]; break;
+            }
+        }
+        var stroke = o.node.getElementsByTagName("stroke")[0];
+        stroke[se + "arrow"] = type;
+        stroke[se + "arrowlength"] = w;
+        stroke[se + "arrowwidth"] = h;
+    };
+    setFillAndStroke = function (o, params) {
+        // o.paper.canvas.style.display = "none";
+        o.attrs = o.attrs || {};
+        var node = o.node,
+            a = o.attrs,
+            s = node.style,
+            xy,
+            newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),
+            isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),
+            res = o;
+
+
+        for (var par in params) if (params[has](par)) {
+            a[par] = params[par];
+        }
+        if (newpath) {
+            a.path = R._getPath[o.type](o);
+            o._.dirty = 1;
+        }
+        params.href && (node.href = params.href);
+        params.title && (node.title = params.title);
+        params.target && (node.target = params.target);
+        params.cursor && (s.cursor = params.cursor);
+        "blur" in params && o.blur(params.blur);
+        if (params.path && o.type == "path" || newpath) {
+            node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path);
+            if (o.type == "image") {
+                o._.fillpos = [a.x, a.y];
+                o._.fillsize = [a.width, a.height];
+                setCoords(o, 1, 1, 0, 0, 0);
+            }
+        }
+        "transform" in params && o.transform(params.transform);
+        if (isOval) {
+            var cx = +a.cx,
+                cy = +a.cy,
+                rx = +a.rx || +a.r || 0,
+                ry = +a.ry || +a.r || 0;
+            node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));
+        }
+        if ("clip-rect" in params) {
+            var rect = Str(params["clip-rect"]).split(separator);
+            if (rect.length == 4) {
+                rect[2] = +rect[2] + (+rect[0]);
+                rect[3] = +rect[3] + (+rect[1]);
+                var div = node.clipRect || R._g.doc.createElement("div"),
+                    dstyle = div.style;
+                dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);
+                if (!node.clipRect) {
+                    dstyle.position = "absolute";
+                    dstyle.top = 0;
+                    dstyle.left = 0;
+                    dstyle.width = o.paper.width + "px";
+                    dstyle.height = o.paper.height + "px";
+                    node.parentNode.insertBefore(div, node);
+                    div.appendChild(node);
+                    node.clipRect = div;
+                }
+            }
+            if (!params["clip-rect"]) {
+                node.clipRect && (node.clipRect.style.clip = E);
+            }
+        }
+        if (o.textpath) {
+            var textpathStyle = o.textpath.style;
+            params.font && (textpathStyle.font = params.font);
+            params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"');
+            params["font-size"] && (textpathStyle.fontSize = params["font-size"]);
+            params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]);
+            params["font-style"] && (textpathStyle.fontStyle = params["font-style"]);
+        }
+        if ("arrow-start" in params) {
+            addArrow(res, params["arrow-start"]);
+        }
+        if ("arrow-end" in params) {
+            addArrow(res, params["arrow-end"], 1);
+        }
+        if (params.opacity != null || 
+            params["stroke-width"] != null ||
+            params.fill != null ||
+            params.src != null ||
+            params.stroke != null ||
+            params["stroke-width"] != null ||
+            params["stroke-opacity"] != null ||
+            params["fill-opacity"] != null ||
+            params["stroke-dasharray"] != null ||
+            params["stroke-miterlimit"] != null ||
+            params["stroke-linejoin"] != null ||
+            params["stroke-linecap"] != null) {
+            var fill = node.getElementsByTagName(fillString),
+                newfill = false;
+            fill = fill && fill[0];
+            !fill && (newfill = fill = createNode(fillString));
+            if (o.type == "image" && params.src) {
+                fill.src = params.src;
+            }
+            params.fill && (fill.on = true);
+            if (fill.on == null || params.fill == "none" || params.fill === null) {
+                fill.on = false;
+            }
+            if (fill.on && params.fill) {
+                var isURL = Str(params.fill).match(R._ISURL);
+                if (isURL) {
+                    fill.parentNode == node && node.removeChild(fill);
+                    fill.rotate = true;
+                    fill.src = isURL[1];
+                    fill.type = "tile";
+                    var bbox = o.getBBox(1);
+                    fill.position = bbox.x + S + bbox.y;
+                    o._.fillpos = [bbox.x, bbox.y];
+
+                    R._preload(isURL[1], function () {
+                        o._.fillsize = [this.offsetWidth, this.offsetHeight];
+                    });
+                } else {
+                    fill.color = R.getRGB(params.fill).hex;
+                    fill.src = E;
+                    fill.type = "solid";
+                    if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) {
+                        a.fill = "none";
+                        a.gradient = params.fill;
+                        fill.rotate = false;
+                    }
+                }
+            }
+            if ("fill-opacity" in params || "opacity" in params) {
+                var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);
+                opacity = mmin(mmax(opacity, 0), 1);
+                fill.opacity = opacity;
+                if (fill.src) {
+                    fill.color = "none";
+                }
+            }
+            node.appendChild(fill);
+            var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),
+            newstroke = false;
+            !stroke && (newstroke = stroke = createNode("stroke"));
+            if ((params.stroke && params.stroke != "none") ||
+                params["stroke-width"] ||
+                params["stroke-opacity"] != null ||
+                params["stroke-dasharray"] ||
+                params["stroke-miterlimit"] ||
+                params["stroke-linejoin"] ||
+                params["stroke-linecap"]) {
+                stroke.on = true;
+            }
+            (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);
+            var strokeColor = R.getRGB(params.stroke);
+            stroke.on && params.stroke && (stroke.color = strokeColor.hex);
+            opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);
+            var width = (toFloat(params["stroke-width"]) || 1) * .75;
+            opacity = mmin(mmax(opacity, 0), 1);
+            params["stroke-width"] == null && (width = a["stroke-width"]);
+            params["stroke-width"] && (stroke.weight = width);
+            width && width < 1 && (opacity *= width) && (stroke.weight = 1);
+            stroke.opacity = opacity;
+        
+            params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");
+            stroke.miterlimit = params["stroke-miterlimit"] || 8;
+            params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");
+            if (params["stroke-dasharray"]) {
+                var dasharray = {
+                    "-": "shortdash",
+                    ".": "shortdot",
+                    "-.": "shortdashdot",
+                    "-..": "shortdashdotdot",
+                    ". ": "dot",
+                    "- ": "dash",
+                    "--": "longdash",
+                    "- .": "dashdot",
+                    "--.": "longdashdot",
+                    "--..": "longdashdotdot"
+                };
+                stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;
+            }
+            newstroke && node.appendChild(stroke);
+        }
+        if (res.type == "text") {
+            res.paper.canvas.style.display = E;
+            var span = res.paper.span,
+                m = 100,
+                fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/);
+            s = span.style;
+            a.font && (s.font = a.font);
+            a["font-family"] && (s.fontFamily = a["font-family"]);
+            a["font-weight"] && (s.fontWeight = a["font-weight"]);
+            a["font-style"] && (s.fontStyle = a["font-style"]);
+            fontSize = toFloat(fontSize ? fontSize[0] : a["font-size"]);
+            s.fontSize = fontSize * m + "px";
+            res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>"));
+            var brect = span.getBoundingClientRect();
+            res.W = a.w = (brect.right - brect.left) / m;
+            res.H = a.h = (brect.bottom - brect.top) / m;
+            // res.paper.canvas.style.display = "none";
+            res.X = a.x;
+            res.Y = a.y + res.H / 2;
+
+            ("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));
+            var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"];
+            for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {
+                res._.dirty = 1;
+                break;
+            }
+        
+            // text-anchor emulation
+            switch (a["text-anchor"]) {
+                case "start":
+                    res.textpath.style["v-text-align"] = "left";
+                    res.bbx = res.W / 2;
+                break;
+                case "end":
+                    res.textpath.style["v-text-align"] = "right";
+                    res.bbx = -res.W / 2;
+                break;
+                default:
+                    res.textpath.style["v-text-align"] = "center";
+                    res.bbx = 0;
+                break;
+            }
+            res.textpath.style["v-text-kern"] = true;
+        }
+        // res.paper.canvas.style.display = E;
+    };
+    addGradientFill = function (o, gradient, fill) {
+        o.attrs = o.attrs || {};
+        var attrs = o.attrs,
+            pow = Math.pow,
+            opacity,
+            oindex,
+            type = "linear",
+            fxfy = ".5 .5";
+        o.attrs.gradient = gradient;
+        gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {
+            type = "radial";
+            if (fx && fy) {
+                fx = toFloat(fx);
+                fy = toFloat(fy);
+                pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);
+                fxfy = fx + S + fy;
+            }
+            return E;
+        });
+        gradient = gradient.split(/\s*\-\s*/);
+        if (type == "linear") {
+            var angle = gradient.shift();
+            angle = -toFloat(angle);
+            if (isNaN(angle)) {
+                return null;
+            }
+        }
+        var dots = R._parseDots(gradient);
+        if (!dots) {
+            return null;
+        }
+        o = o.shape || o.node;
+        if (dots.length) {
+            o.removeChild(fill);
+            fill.on = true;
+            fill.method = "none";
+            fill.color = dots[0].color;
+            fill.color2 = dots[dots.length - 1].color;
+            var clrs = [];
+            for (var i = 0, ii = dots.length; i < ii; i++) {
+                dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);
+            }
+            fill.colors = clrs.length ? clrs.join() : "0% " + fill.color;
+            if (type == "radial") {
+                fill.type = "gradientTitle";
+                fill.focus = "100%";
+                fill.focussize = "0 0";
+                fill.focusposition = fxfy;
+                fill.angle = 0;
+            } else {
+                // fill.rotate= true;
+                fill.type = "gradient";
+                fill.angle = (270 - angle) % 360;
+            }
+            o.appendChild(fill);
+        }
+        return 1;
+    };
+    Element = function (node, vml) {
+        this[0] = this.node = node;
+        node.raphael = true;
+        this.id = R._oid++;
+        node.raphaelid = this.id;
+        this.X = 0;
+        this.Y = 0;
+        this.attrs = {};
+        this.paper = vml;
+        this.matrix = R.matrix();
+        this._ = {
+            transform: [],
+            sx: 1,
+            sy: 1,
+            dx: 0,
+            dy: 0,
+            deg: 0,
+            dirty: 1,
+            dirtyT: 1
+        };
+        !vml.bottom && (vml.bottom = this);
+        this.prev = vml.top;
+        vml.top && (vml.top.next = this);
+        vml.top = this;
+        this.next = null;
+    };
+    var elproto = R.el;
+
+    Element.prototype = elproto;
+    elproto.constructor = Element;
+    elproto.transform = function (tstr) {
+        if (tstr == null) {
+            return this._.transform;
+        }
+        var vbs = this.paper._viewBoxShift,
+            vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E,
+            oldt;
+        if (vbs) {
+            oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E);
+        }
+        R._extractTransform(this, vbt + tstr);
+        var matrix = this.matrix.clone(),
+            skew = this.skew,
+            o = this.node,
+            split,
+            isGrad = ~Str(this.attrs.fill).indexOf("-"),
+            isPatt = !Str(this.attrs.fill).indexOf("url(");
+        matrix.translate(-.5, -.5);
+        if (isPatt || isGrad || this.type == "image") {
+            skew.matrix = "1 0 0 1";
+            skew.offset = "0 0";
+            split = matrix.split();
+            if ((isGrad && split.noRotation) || !split.isSimple) {
+                o.style.filter = matrix.toFilter();
+                var bb = this.getBBox(),
+                    bbt = this.getBBox(1),
+                    dx = bb.x - bbt.x,
+                    dy = bb.y - bbt.y;
+                o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
+                setCoords(this, 1, 1, dx, dy, 0);
+            } else {
+                o.style.filter = E;
+                setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);
+            }
+        } else {
+            o.style.filter = E;
+            skew.matrix = Str(matrix);
+            skew.offset = matrix.offset();
+        }
+        oldt && (this._.transform = oldt);
+        return this;
+    };
+    elproto.rotate = function (deg, cx, cy) {
+        if (this.removed) {
+            return this;
+        }
+        if (deg == null) {
+            return;
+        }
+        deg = Str(deg).split(separator);
+        if (deg.length - 1) {
+            cx = toFloat(deg[1]);
+            cy = toFloat(deg[2]);
+        }
+        deg = toFloat(deg[0]);
+        (cy == null) && (cx = cy);
+        if (cx == null || cy == null) {
+            var bbox = this.getBBox(1);
+            cx = bbox.x + bbox.width / 2;
+            cy = bbox.y + bbox.height / 2;
+        }
+        this._.dirtyT = 1;
+        this.transform(this._.transform.concat([["r", deg, cx, cy]]));
+        return this;
+    };
+    elproto.translate = function (dx, dy) {
+        if (this.removed) {
+            return this;
+        }
+        dx = Str(dx).split(separator);
+        if (dx.length - 1) {
+            dy = toFloat(dx[1]);
+        }
+        dx = toFloat(dx[0]) || 0;
+        dy = +dy || 0;
+        if (this._.bbox) {
+            this._.bbox.x += dx;
+            this._.bbox.y += dy;
+        }
+        this.transform(this._.transform.concat([["t", dx, dy]]));
+        return this;
+    };
+    elproto.scale = function (sx, sy, cx, cy) {
+        if (this.removed) {
+            return this;
+        }
+        sx = Str(sx).split(separator);
+        if (sx.length - 1) {
+            sy = toFloat(sx[1]);
+            cx = toFloat(sx[2]);
+            cy = toFloat(sx[3]);
+            isNaN(cx) && (cx = null);
+            isNaN(cy) && (cy = null);
+        }
+        sx = toFloat(sx[0]);
+        (sy == null) && (sy = sx);
+        (cy == null) && (cx = cy);
+        if (cx == null || cy == null) {
+            var bbox = this.getBBox(1);
+        }
+        cx = cx == null ? bbox.x + bbox.width / 2 : cx;
+        cy = cy == null ? bbox.y + bbox.height / 2 : cy;
+    
+        this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
+        this._.dirtyT = 1;
+        return this;
+    };
+    elproto.hide = function () {
+        !this.removed && (this.node.style.display = "none");
+        return this;
+    };
+    elproto.show = function () {
+        !this.removed && (this.node.style.display = E);
+        return this;
+    };
+    elproto._getBBox = function () {
+        if (this.removed) {
+            return {};
+        }
+        if (this.type == "text") {
+            return {
+                x: this.X + (this.bbx || 0) - this.W / 2,
+                y: this.Y - this.H,
+                width: this.W,
+                height: this.H
+            };
+        } else {
+            return pathDimensions(this.attrs.path);
+        }
+    };
+    elproto.remove = function () {
+        if (this.removed) {
+            return;
+        }
+        this.paper.__set__ && this.paper.__set__.exclude(this);
+        R.eve.unbind("*.*." + this.id);
+        R._tear(this, this.paper);
+        this.node.parentNode.removeChild(this.node);
+        this.shape && this.shape.parentNode.removeChild(this.shape);
+        for (var i in this) {
+            delete this[i];
+        }
+        this.removed = true;
+    };
+    elproto.attr = function (name, value) {
+        if (this.removed) {
+            return this;
+        }
+        if (name == null) {
+            var res = {};
+            for (var a in this.attrs) if (this.attrs[has](a)) {
+                res[a] = this.attrs[a];
+            }
+            res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
+            res.transform = this._.transform;
+            return res;
+        }
+        if (value == null && R.is(name, "string")) {
+            if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
+                return this.attrs.gradient;
+            }
+            var names = name.split(separator),
+                out = {};
+            for (var i = 0, ii = names.length; i < ii; i++) {
+                name = names[i];
+                if (name in this.attrs) {
+                    out[name] = this.attrs[name];
+                } else if (R.is(this.paper.customAttributes[name], "function")) {
+                    out[name] = this.paper.customAttributes[name].def;
+                } else {
+                    out[name] = R._availableAttrs[name];
+                }
+            }
+            return ii - 1 ? out : out[names[0]];
+        }
+        if (this.attrs && value == null && R.is(name, "array")) {
+            out = {};
+            for (i = 0, ii = name.length; i < ii; i++) {
+                out[name[i]] = this.attr(name[i]);
+            }
+            return out;
+        }
+        var params;
+        if (value != null) {
+            params = {};
+            params[name] = value;
+        }
+        value == null && R.is(name, "object") && (params = name);
+        for (var key in params) {
+            eve("attr." + key + "." + this.id, this, params[key]);
+        }
+        if (params) {
+            for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
+                var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
+                this.attrs[key] = params[key];
+                for (var subkey in par) if (par[has](subkey)) {
+                    params[subkey] = par[subkey];
+                }
+            }
+            // this.paper.canvas.style.display = "none";
+            if (params.text && this.type == "text") {
+                this.textpath.string = params.text;
+            }
+            setFillAndStroke(this, params);
+            // this.paper.canvas.style.display = E;
+        }
+        return this;
+    };
+    elproto.toFront = function () {
+        !this.removed && this.node.parentNode.appendChild(this.node);
+        this.paper && this.paper.top != this && R._tofront(this, this.paper);
+        return this;
+    };
+    elproto.toBack = function () {
+        if (this.removed) {
+            return this;
+        }
+        if (this.node.parentNode.firstChild != this.node) {
+            this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
+            R._toback(this, this.paper);
+        }
+        return this;
+    };
+    elproto.insertAfter = function (element) {
+        if (this.removed) {
+            return this;
+        }
+        if (element.constructor == R.st.constructor) {
+            element = element[element.length - 1];
+        }
+        if (element.node.nextSibling) {
+            element.node.parentNode.insertBefore(this.node, element.node.nextSibling);
+        } else {
+            element.node.parentNode.appendChild(this.node);
+        }
+        R._insertafter(this, element, this.paper);
+        return this;
+    };
+    elproto.insertBefore = function (element) {
+        if (this.removed) {
+            return this;
+        }
+        if (element.constructor == R.st.constructor) {
+            element = element[0];
+        }
+        element.node.parentNode.insertBefore(this.node, element.node);
+        R._insertbefore(this, element, this.paper);
+        return this;
+    };
+    elproto.blur = function (size) {
+        var s = this.node.runtimeStyle,
+            f = s.filter;
+        f = f.replace(blurregexp, E);
+        if (+size !== 0) {
+            this.attrs.blur = size;
+            s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";
+            s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));
+        } else {
+            s.filter = f;
+            s.margin = 0;
+            delete this.attrs.blur;
+        }
+    };
+
+    R._engine.path = function (pathString, vml) {
+        var el = createNode("shape");
+        el.style.cssText = cssDot;
+        el.coordsize = zoom + S + zoom;
+        el.coordorigin = vml.coordorigin;
+        var p = new Element(el, vml),
+            attr = {fill: "none", stroke: "#000"};
+        pathString && (attr.path = pathString);
+        p.type = "path";
+        p.path = [];
+        p.Path = E;
+        setFillAndStroke(p, attr);
+        vml.canvas.appendChild(el);
+        var skew = createNode("skew");
+        skew.on = true;
+        el.appendChild(skew);
+        p.skew = skew;
+        p.transform(E);
+        return p;
+    };
+    R._engine.rect = function (vml, x, y, w, h, r) {
+        var path = R._rectPath(x, y, w, h, r),
+            res = vml.path(path),
+            a = res.attrs;
+        res.X = a.x = x;
+        res.Y = a.y = y;
+        res.W = a.width = w;
+        res.H = a.height = h;
+        a.r = r;
+        a.path = path;
+        res.type = "rect";
+        return res;
+    };
+    R._engine.ellipse = function (vml, x, y, rx, ry) {
+        var res = vml.path(),
+            a = res.attrs;
+        res.X = x - rx;
+        res.Y = y - ry;
+        res.W = rx * 2;
+        res.H = ry * 2;
+        res.type = "ellipse";
+        setFillAndStroke(res, {
+            cx: x,
+            cy: y,
+            rx: rx,
+            ry: ry
+        });
+        return res;
+    };
+    R._engine.circle = function (vml, x, y, r) {
+        var res = vml.path(),
+            a = res.attrs;
+        res.X = x - r;
+        res.Y = y - r;
+        res.W = res.H = r * 2;
+        res.type = "circle";
+        setFillAndStroke(res, {
+            cx: x,
+            cy: y,
+            r: r
+        });
+        return res;
+    };
+    R._engine.image = function (vml, src, x, y, w, h) {
+        var path = R._rectPath(x, y, w, h),
+            res = vml.path(path).attr({stroke: "none"}),
+            a = res.attrs,
+            node = res.node,
+            fill = node.getElementsByTagName(fillString)[0];
+        a.src = src;
+        res.X = a.x = x;
+        res.Y = a.y = y;
+        res.W = a.width = w;
+        res.H = a.height = h;
+        a.path = path;
+        res.type = "image";
+        fill.parentNode == node && node.removeChild(fill);
+        fill.rotate = true;
+        fill.src = src;
+        fill.type = "tile";
+        res._.fillpos = [x, y];
+        res._.fillsize = [w, h];
+        node.appendChild(fill);
+        setCoords(res, 1, 1, 0, 0, 0);
+        return res;
+    };
+    R._engine.text = function (vml, x, y, text) {
+        var el = createNode("shape"),
+            path = createNode("path"),
+            o = createNode("textpath");
+        x = x || 0;
+        y = y || 0;
+        text = text || "";
+        path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1);
+        path.textpathok = true;
+        o.string = Str(text);
+        o.on = true;
+        el.style.cssText = cssDot;
+        el.coordsize = zoom + S + zoom;
+        el.coordorigin = "0 0";
+        var p = new Element(el, vml),
+            attr = {
+                fill: "#000",
+                stroke: "none",
+                font: R._availableAttrs.font,
+                text: text
+            };
+        p.shape = el;
+        p.path = path;
+        p.textpath = o;
+        p.type = "text";
+        p.attrs.text = Str(text);
+        p.attrs.x = x;
+        p.attrs.y = y;
+        p.attrs.w = 1;
+        p.attrs.h = 1;
+        setFillAndStroke(p, attr);
+        el.appendChild(o);
+        el.appendChild(path);
+        vml.canvas.appendChild(el);
+        var skew = createNode("skew");
+        skew.on = true;
+        el.appendChild(skew);
+        p.skew = skew;
+        p.transform(E);
+        return p;
+    };
+    R._engine.setSize = function (width, height) {
+        var cs = this.canvas.style;
+        this.width = width;
+        this.height = height;
+        width == +width && (width += "px");
+        height == +height && (height += "px");
+        cs.width = width;
+        cs.height = height;
+        cs.clip = "rect(0 " + width + " " + height + " 0)";
+        if (this._viewBox) {
+            setViewBox.apply(this, this._viewBox);
+        }
+        return this;
+    };
+    R._engine.setViewBox = function (x, y, w, h, fit) {
+        R.eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]);
+        var width = this.width,
+            height = this.height,
+            size = 1 / mmax(w / width, h / height),
+            H, W;
+        if (fit) {
+            H = height / h;
+            W = width / w;
+            if (w * H < width) {
+                x -= (width - w * H) / 2 / H;
+            }
+            if (h * W < height) {
+                y -= (height - h * W) / 2 / W;
+            }
+        }
+        this._viewBox = [x, y, w, h, !!fit];
+        this._viewBoxShift = {
+            dx: -x,
+            dy: -y,
+            scale: size
+        };
+        this.forEach(function (el) {
+            el.transform("...");
+        });
+        return this;
+    };
+    var createNode,
+        initWin = function (win) {
+            var doc = win.document;
+            doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
+            try {
+                !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
+                createNode = function (tagName) {
+                    return doc.createElement('<rvml:' + tagName + ' class="rvml">');
+                };
+            } catch (e) {
+                createNode = function (tagName) {
+                    return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
+                };
+            }
+        };
+    initWin(R._g.win);
+    R._engine.create = function () {
+        var con = R._getContainer.apply(0, arguments),
+            container = con.container,
+            height = con.height,
+            s,
+            width = con.width,
+            x = con.x,
+            y = con.y;
+        if (!container) {
+            throw new Error("VML container not found.");
+        }
+        var res = new R._Paper,
+            c = res.canvas = R._g.doc.createElement("div"),
+            cs = c.style;
+        x = x || 0;
+        y = y || 0;
+        width = width || 512;
+        height = height || 342;
+        res.width = width;
+        res.height = height;
+        width == +width && (width += "px");
+        height == +height && (height += "px");
+        res.coordsize = zoom * 1e3 + S + zoom * 1e3;
+        res.coordorigin = "0 0";
+        res.span = R._g.doc.createElement("span");
+        res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";
+        c.appendChild(res.span);
+        cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
+        if (container == 1) {
+            R._g.doc.body.appendChild(c);
+            cs.left = x + "px";
+            cs.top = y + "px";
+            cs.position = "absolute";
+        } else {
+            if (container.firstChild) {
+                container.insertBefore(c, container.firstChild);
+            } else {
+                container.appendChild(c);
+            }
+        }
+        // plugins.call(res, res, R.fn);
+        res.renderfix = function () {};
+        return res;
+    };
+    R.prototype.clear = function () {
+        R.eve("clear", this);
+        this.canvas.innerHTML = E;
+        this.span = R._g.doc.createElement("span");
+        this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
+        this.canvas.appendChild(this.span);
+        this.bottom = this.top = null;
+    };
+    R.prototype.remove = function () {
+        R.eve("remove", this);
+        this.canvas.parentNode.removeChild(this.canvas);
+        for (var i in this) {
+            this[i] = removed(i);
+        }
+        return true;
+    };
+
+    var setproto = R.st;
+    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
+        setproto[method] = (function (methodname) {
+            return function () {
+                var arg = arguments;
+                return this.forEach(function (el) {
+                    el[methodname].apply(el, arg);
+                });
+            };
+        })(method);
+    }
+}(window.Raphael);
\ No newline at end of file