# HG changeset patch # User Raphael Velt # Date 1336060327 -7200 # Node ID d366aa22bd79044abc207c4bc75142390fc245de # Parent 07ab28bca4828f6f6a7f855e2078a17f9bbaebfe New Metadataplayer version diff -r 07ab28bca482 -r d366aa22bd79 web/common.php --- a/web/common.php Wed May 02 19:19:51 2012 +0200 +++ b/web/common.php Thu May 03 17:52:07 2012 +0200 @@ -177,7 +177,7 @@ 'local' => array( 'libdir' => URL_ROOT.'res/js/', 'jquery' => URL_ROOT.'res/js/jquery-1.4.3.min.js', - 'raphael' => URL_ROOT.'res/js/raphael.js', + 'raphael' => URL_ROOT.'res/js/raphael-min.js', 'jquery-ui' => URL_ROOT.'res/js/jquery-ui-1.8.13.min.js', 'niceforms' => URL_ROOT.'res/js/niceforms.js', 'jquery-url' => URL_ROOT.'res/js/jquery.url.js', @@ -192,12 +192,13 @@ 'jquery-scrollto'=>URL_ROOT.'res/js/jquery.scrollTo-1.4.2-min.js' , 'twcx-main' => URL_ROOT.'res/js/live-polemic.js' , 'semanticboard' => URL_ROOT.'res/js/semanticboard.js' , - 'metadataplayer'=> URL_ROOT.'res/js/LdtPlayer-release.js' , + 'metadataplayer'=> URL_ROOT.'res/metadataplayer/LdtPlayer-core.js' , + 'ldtwidgets' => URL_ROOT.'res/metadataplayer/' , ), 'cdn' => array( 'libdir' => URL_ROOT.'res/js/', 'jquery' => 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js', - 'raphael' => URL_ROOT.'res/js/raphael.js', + 'raphael' => URL_ROOT.'res/js/raphael-min.js', 'jquery-ui' => 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js', 'niceforms' => URL_ROOT.'res/js/niceforms.js', 'jquery-url' => URL_ROOT.'res/js/jquery.url.js', @@ -212,7 +213,8 @@ 'jquery-scrollto'=>URL_ROOT.'res/js/jquery.scrollTo-1.4.2-min.js' , 'twcx-main' => URL_ROOT.'res/js/live-polemic.js' , 'semanticboard' => URL_ROOT.'res/js/semanticboard.js' , - 'metadataplayer'=> URL_ROOT.'res/js/LdtPlayer-release.js' , + 'metadataplayer'=> URL_ROOT.'res/metadataplayer/LdtPlayer-core.js' , + 'ldtwidgets' => URL_ROOT.'res/metadataplayer/' , ) ); @@ -242,7 +244,7 @@ 'tweetcast' => URL_ROOT.'res/css/tweetcast.css', 'semanticboard' => URL_ROOT.'res/css/semanticboard.css', 'archives-iframe' => URL_ROOT.'res/css/archives-iframe.css', - 'metadataplayer' => URL_ROOT.'res/css/metadataplayer/LdtPlayer.css', + 'metadataplayer' => URL_ROOT.'res/metadataplayer/LdtPlayer-core.css', ), 'cdn' => array( 'blueprint-screen' => URL_ROOT.'res/css/blueprint-screen.css', @@ -256,7 +258,7 @@ 'tweetcast' => URL_ROOT.'res/css/tweetcast.css', 'semanticboard' => URL_ROOT.'res/css/semanticboard.css', 'archives-iframe' => URL_ROOT.'res/css/archives-iframe.css', - 'metadataplayer' => URL_ROOT.'res/css/metadataplayer/LdtPlayer.css', + 'metadataplayer' => URL_ROOT.'res/metadataplayer/LdtPlayer-core.css', ) ); diff -r 07ab28bca482 -r d366aa22bd79 web/polemicaltimeline.php --- a/web/polemicaltimeline.php Wed May 02 19:19:51 2012 +0200 +++ b/web/polemicaltimeline.php Thu May 03 17:52:07 2012 +0200 @@ -60,102 +60,78 @@ diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/black.png Binary file web/res/css/imgs/black.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/black_arrow.png Binary file web/res/css/imgs/black_arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/black_arrow_big.png Binary file web/res/css/imgs/black_arrow_big.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/black_big.png Binary file web/res/css/imgs/black_big.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/delicious.png Binary file web/res/css/imgs/delicious.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/facebook.png Binary file web/res/css/imgs/facebook.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/grey_arrow_Show.png Binary file web/res/css/imgs/grey_arrow_Show.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/linkedin.png Binary file web/res/css/imgs/linkedin.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/loader.gif Binary file web/res/css/imgs/loader.gif has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/loader_fc.gif Binary file web/res/css/imgs/loader_fc.gif has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/loader_fc2.gif Binary file web/res/css/imgs/loader_fc2.gif has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/purple_arrow_Show.png Binary file web/res/css/imgs/purple_arrow_Show.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/transBlack.png Binary file web/res/css/imgs/transBlack.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/twitter.png Binary file web/res/css/imgs/twitter.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/white.png Binary file web/res/css/imgs/white.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/white_arrow.png Binary file web/res/css/imgs/white_arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/white_arrow_big.png Binary file web/res/css/imgs/white_arrow_big.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/white_arrow_mini.png Binary file web/res/css/imgs/white_arrow_mini.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/white_big.png Binary file web/res/css/imgs/white_big.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/imgs/widget20.png Binary file web/res/css/imgs/widget20.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/LdtPlayer.css --- a/web/res/css/metadataplayer/LdtPlayer.css Wed May 02 19:19:51 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,968 +0,0 @@ -/* Some general styling classes */ - -.Ldt-floatClear { - display: block; width: 100%; height: 0; clear: both; -} - -ul.Ldt-floatList { - padding: 0; margin: 0; list-style: none; -} - -.Ldt-floatList li { - float: left; -} - - -/* */ - -#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) center no-repeat; - text-indent: -9999px; - position: absolute; -} - -/* 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-fbShare { - display: block; - float: left; - width: 24px; - height: 24px; - background:url('imgs/facebook.png'); -} - -.Ldt-TwShare { - display: block; - float: left; - width: 24px; - height: 24px; - background:url('imgs/twitter.png'); -} - -.Ldt-GplusShare { - display: block; - float: left; - width: 24px; - height: 24px; - background:url('imgs/google.png'); -} - -.Ldt-SaTitle{ - padding-top:2px; - padding-bottom:3px; - font-size: 12pt; - color : #0068c4; -} - -.Ldt-SaDescription{ - font-size:12px; -} - -.Ldt-SaKeywords { - font-weight:bold; - 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: 10px; - font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif"; - background:url('imgs/player_gradient.png') repeat-x transparent ; - height: 25px; - border: 1px solid #b6b8b8; - position: relative; -} - - -.Ldt-LeftPlayerControls { - float:left; -} - -.Ldt-RightPlayerControls { - float: right; -} - -.Ldt-Ctrl-button { - float: left; - width: 30px; height: 25px; - background: url('imgs/player-sprites.png'); - cursor: pointer; -} - -.Ldt-Ctrl-spacer { - float: left; width: 1px; height: 25px; background: #b6b8b8; -} - -.Ldt-CtrlPlay { - margin: 0 15px; -} - -.Ldt-CtrlPlay-PlayState { - background-position: 0 0; -} - -.Ldt-CtrlPlay-PlayState:hover { - background-position: 0 -25px; -} - -.Ldt-CtrlPlay-PlayState:active { - background-position: 0 -50px; -} - -.Ldt-CtrlPlay-PauseState { - background-position: -30px 0; -} - -.Ldt-CtrlPlay-PauseState:hover { - background-position: -30px -25px; -} - -.Ldt-CtrlPlay-PauseState:active { - background-position: -30px -50px; -} - - -.Ldt-CtrlAnnotate { - margin: 0 2px; - background-position: -60px 0; -} - -.Ldt-CtrlAnnotate:hover { - background-position: -60px -25px; -} - -.Ldt-CtrlAnnotate:active { - background-position: -60px -50px; -} - -.Ldt-CtrlSearch { - margin: 0 2px; - background-position: -90px 0; -} - -.Ldt-CtrlSearch:hover { - background-position: -90px -25px; -} - -.Ldt-CtrlSearch:active { - background-position: -90px -50px; -} - -.LdtSearch { - display: none; - width: 165px; - height: 25px; - border: 1px; - border-color: #CFCFCF; - float: left; - text-align: center; -} - -.Ldt-Time { - float: left; - margin: 5px; - font-size: 12px; - font-family: Arial, Verdana, sans-serif; -} - -.Ldt-ElapsedTime { - float: left; - color: #4a4a4a; -} - -.Ldt-TimeSeparator { - margin: 0 4px; - float: left; -} - -.Ldt-TotalTime { - float: left; - color: #b2b2b2; -} - -.Ldt-CtrlSound { - margin: 0 2px; -} - -.Ldt-CtrlSound-Full { - background-position: -120px 0; -} - -.Ldt-CtrlSound-Full:hover { - background-position: -120px -25px; -} - -.Ldt-CtrlSound-Full:active { - background-position: -120px -50px; -} - -.Ldt-CtrlSound-Mute { - background-position: -150px 0; -} - -.Ldt-CtrlSound-Mute:hover { - background-position: -150px -25px; -} - -.Ldt-CtrlSound-Mute:active { - background-position: -150px -50px; -} - -.Ldt-CtrlSound-Half { - background-position: -180px 0; -} - -.Ldt-CtrlSound-Half:hover { - background-position: -180px -25px; -} - -.Ldt-CtrlSound-Half:active { - background-position: -180px -50px; -} - -.Ldt-Ctrl-Volume-Control { - display: none; - position: absolute; - background:url('imgs/player_gradient.png') repeat-x transparent ; - height: 25px; - width: 100px; top: 25px; right: -1px; z-index: 100; - padding: 0 2px; - border: 1px solid #b6b8b8; -} - -.Ldt-Ctrl-Volume-Bar { - height: 5px; margin: 9px 3px 0; background: #cccccc; border: 1px solid #999999; border-radius: 2px; -} - -.Ldt-Ctrl-Volume-Cursor { - position: absolute; top: 2px; width: 6px; height: 19px; background: #a8a8a8; border: 1px solid #999999; border-radius: 2px; - cursor: pointer; -} - -.Ldt-Ctrl-Volume-Control:hover .Ldt-Ctrl-Volume-Cursor { - background: #F7268E; -} - -.Ldt-cleaner { - clear:both; -} - -/* Arrow Widget */ -.Ldt-arrowWidget { - position: relative; - - height:16px; - width:27px; - margin-bottom: -3px; - z-index: 4; - left: 0%; -} - -.Ldt-arrowLeftEdge { - background:url('imgs/left_edge_arrow.png') no-repeat scroll 0 0 transparent ; -} - -.Ldt-arrowCenter { - background:url('imgs/arrow.png') no-repeat scroll 0 0 transparent ; -} - -.Ldt-arrowRightEdge { - background:url('imgs/right_edge_arrow.png') no-repeat scroll 0 0 transparent ; -} - -.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: 115px; - width: 180px; - padding: 15px 15px 20px; - color: black; - font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif"; - overflow:hidden; -} - -.tipcolor { - float: left; margin: 2px 4px 2px 0; -} - -.tip img { - max-width: 140px; max-height: 70px; margin: 0 20px; -} - -/* 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-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; - background:url('imgs/profile_arrow.png'); - background-position: 7 10px; -} - -.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; - background:url('imgs/minimize.png'); -} - -.Ldt-tweetWidgetMinimize { - position: relative; - float: right; - height: 17px; - width: 17px; - right: 9px; - background:url('imgs/minimize.png'); -} - -.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 { - float: left; width: 100%; clear: both; -} - -.Ldt-createAnnotation-userAvatar { - float: right; - width: 48px; - height: 48px; - margin: 7px 0; - border: 1px solid #babcbc; -} - -.Ldt-createAnnotation-userAvatar img { - float: right; - display: block; - max-width: 100%; - max-height: 100%; -} - -.Ldt-createAnnotation-profileArrow { - float: right; - vertical-align: top; - height: 48px; - width: 15px; - margin: 7px 5px; - background:url('imgs/profile_arrow.png') center no-repeat; -} - -.Ldt-createAnnotation-Description { - float: left; - width: 520px; - height: 56px; padding: 2px; - resize: none; -} - -.Ldt-createAnnotation-btnblock { - float: left; width: 450px; margin: 5px 0; -} - -.Ldt-createAnnotation-btnblock label { - float: left; margin-left: 12px; margin: 2px 8px 2px 0; font-size: 12px; -} - -.Ldt-createAnnotation-keyword-button { - border: 1px solid #ffffff; - background-color: #217bcb; - color: #ffffff; - padding: 3px 4px; - cursor: pointer; -} - -.Ldt-createAnnotation-active-button .Ldt-createAnnotation-keyword-button { - background-color: #d93c71; -} - -.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; - position: relative; - margin-top: 3px; - padding: 28px 0 0; - font-size: 13px; - border: none; - text-align: center; -} - -.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; -} - -.Ldt-createAnnotation-Minimize { - position: relative; - float: right; - height: 17px; - width: 17px; - right: 0px; - background:url('imgs/minimize.png'); -} - -/* polemic tweet annotation buttons */ - -.Ldt-createAnnotation-polemic-button { - margin: 0; - border: 0; - padding: 0; - margin-right: 2px; - width: 38px; - height: 26px; - text-indent: -999px; - background: url(imgs/polemic_buttons_sprite.png); - cursor: pointer; -} - -.Ldt-createAnnotation-polemic-positive:hover { - background-position: 0 -26px; -} -.Ldt-createAnnotation-active-button .Ldt-createAnnotation-polemic-positive { - background-position: 0 -52px; -} - -.Ldt-createAnnotation-polemic-negative { - background-position: -38px 0; -} -.Ldt-createAnnotation-polemic-negative:hover { - background-position: -38px -26px; -} -.Ldt-createAnnotation-active-button .Ldt-createAnnotation-polemic-negative { - background-position: -38px -52px; -} - -.Ldt-createAnnotation-polemic-reference { - background-position: -76px 0; -} -.Ldt-createAnnotation-polemic-reference:hover { - background-position: -76px -26px; -} -.Ldt-createAnnotation-active-button .Ldt-createAnnotation-polemic-reference { - background-position: -76px -52px; -} - -.Ldt-createAnnotation-polemic-question { - background-position: -114px 0; -} -.Ldt-createAnnotation-polemic-question:hover { - background-position: -114px -26px; -} -.Ldt-createAnnotation-active-button .Ldt-createAnnotation-polemic-question { - background-position: -114px -52px; -} - -.Ldt-createAnnotation-spinner { - display: inline; - width: 16px; - height: 16px; - background-image('imgs/spinner.gif'); -} - -.Ldt-createAnnotation-endScreen-TweetLink { - width: 54px; - height: 20px; - background-image('imgs/tweet_button.png'); -} - -.Ldt-createAnnotation-endScreen-FbLink { - width: 55px; - height: 20px; - background-image('imgs/facebook_button.png'); -} - -.Ldt-createAnnotation-endScreen-GplusLink { - width: 50px; - height: 20px; - background-image('imgs/gplus_button.png'); -} -/* AnnotationsListWidget */ - -.Ldt-AnnotationsListWidget { - font-size: 12px; - font-family: "Arial", "Verdana", "sans-serif"; - border: 1px solid #b6b8b8; - overflow: auto; - max-height: 480px; -} - -ul.Ldt-AnnotationsList-ul { - list-style: none; - padding: 0 3px; -} - -li.Ldt-AnnotationsList-li { - cursor: pointer; - float: left; width: 100%; clear: both; - margin: 2px 0; padding: 2px 0; -} - -.Ldt-AnnotationsList-li:hover { - background-color: #e9e9e9; -} - -.Ldt-AnnotationsList-highlight { - background: #F7268E; color: #ffffff; -} - -.Ldt-AnnotationsListWidget a { - text-decoration: none; -} - -.Ldt-AnnotationsList-Thumb-Placeholder { - float: left; - height: 64px; - width: 64px; - background-image: url('imgs/video_sequence.png'); -} - -.Ldt-AnnotationsList-Thumbnail { - border: none; - float: left; - max-width: 64px; - max-height: 64px; -} - -.Ldt-AnnotationsList-Duration { - color : #f7268e; - float: right; text-align: right; -} - -.Ldt-AnnotationsList-Title { - color: #0068c4; - font-size: 13px; - margin: 0 0 2px 64px; -} - -.Ldt-AnnotationsList-Description { - clear: both; - margin: 2px 0; -} - -ul.Ldt-AnnotationsList-Tags { - width: 100%; list-style: none; clear: both; padding: 0; margin: 2px 0; -} - -li.Ldt-AnnotationsList-Tag-Li { - float: left; margin: 2px; background: #0068c4; color: #fff; padding: 4px; -} - -li.Ldt-AnnotationsList-Tag-Li:hover { - background: #F7268E; -} - -/* Tagcloud */ - -.Ldt-TagCloud { - font-family: "PT Sans", Arial, Helvetica, sans-serif; -} - -.Ldt-TagCloud ul { - list-style: none; padding: 0; margin: 5px; text-align: center; -} - -.Ldt-TagCloud li { - display: inline-block; margin: 2px; cursor:pointer; cursor:hand; -} - -.Ldt-TagCloud li:hover { - color: #0099ff; -} - -.Ldt-TagCloud-actif { - color: #c000c0; -} diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/annotate_arrow.png Binary file web/res/css/metadataplayer/imgs/annotate_arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/arrow.png Binary file web/res/css/metadataplayer/imgs/arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/black.png Binary file web/res/css/metadataplayer/imgs/black.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/black_arrow.png Binary file web/res/css/metadataplayer/imgs/black_arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/black_arrow_big.png Binary file web/res/css/metadataplayer/imgs/black_arrow_big.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/black_big.png Binary file web/res/css/metadataplayer/imgs/black_big.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/delicious.png Binary file web/res/css/metadataplayer/imgs/delicious.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/facebook.png Binary file web/res/css/metadataplayer/imgs/facebook.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/facebook_button.png Binary file web/res/css/metadataplayer/imgs/facebook_button.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/google.png Binary file web/res/css/metadataplayer/imgs/google.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/gplus_button.png Binary file web/res/css/metadataplayer/imgs/gplus_button.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/grey_arrow_Show.png Binary file web/res/css/metadataplayer/imgs/grey_arrow_Show.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/left_edge_arrow.png Binary file web/res/css/metadataplayer/imgs/left_edge_arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/left_handle.gif Binary file web/res/css/metadataplayer/imgs/left_handle.gif has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/linkedin.png Binary file web/res/css/metadataplayer/imgs/linkedin.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/loader.gif Binary file web/res/css/metadataplayer/imgs/loader.gif has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/minimize.png Binary file web/res/css/metadataplayer/imgs/minimize.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/player-sprites.png Binary file web/res/css/metadataplayer/imgs/player-sprites.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/player_gradient.png Binary file web/res/css/metadataplayer/imgs/player_gradient.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/polemic_buttons_sprite.png Binary file web/res/css/metadataplayer/imgs/polemic_buttons_sprite.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/profile_arrow.png Binary file web/res/css/metadataplayer/imgs/profile_arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/purple_arrow_Show.png Binary file web/res/css/metadataplayer/imgs/purple_arrow_Show.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/reply_sprite.png Binary file web/res/css/metadataplayer/imgs/reply_sprite.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/retweet_sprite.png Binary file web/res/css/metadataplayer/imgs/retweet_sprite.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/right_edge_arrow.png Binary file web/res/css/metadataplayer/imgs/right_edge_arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/right_handle.gif Binary file web/res/css/metadataplayer/imgs/right_handle.gif has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/spinner.gif Binary file web/res/css/metadataplayer/imgs/spinner.gif has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/submit_annotation.png Binary file web/res/css/metadataplayer/imgs/submit_annotation.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/transBlack.png Binary file web/res/css/metadataplayer/imgs/transBlack.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/tweet_button.png Binary file web/res/css/metadataplayer/imgs/tweet_button.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/twitter.png Binary file web/res/css/metadataplayer/imgs/twitter.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/user_default_icon.png Binary file web/res/css/metadataplayer/imgs/user_default_icon.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/video_sequence.png Binary file web/res/css/metadataplayer/imgs/video_sequence.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/white.png Binary file web/res/css/metadataplayer/imgs/white.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/white_arrow.png Binary file web/res/css/metadataplayer/imgs/white_arrow.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/white_arrow_big.png Binary file web/res/css/metadataplayer/imgs/white_arrow_big.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/white_arrow_long.png Binary file web/res/css/metadataplayer/imgs/white_arrow_long.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/white_arrow_mini.png Binary file web/res/css/metadataplayer/imgs/white_arrow_mini.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/white_big.png Binary file web/res/css/metadataplayer/imgs/white_big.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/widget20.png Binary file web/res/css/metadataplayer/imgs/widget20.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/metadataplayer/imgs/wire_pattern.png Binary file web/res/css/metadataplayer/imgs/wire_pattern.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/css/tweetcast.css --- a/web/res/css/tweetcast.css Wed May 02 19:19:51 2012 +0200 +++ b/web/res/css/tweetcast.css Thu May 03 17:52:07 2012 +0200 @@ -86,11 +86,11 @@ #mdpgauche { - float: left; width: 300px; margin-right: 10px; + float: left; width: 350px; margin-right: 10px; } #mdpdroite { - float: left; width: 650px; margin-top: 10px; position: relative; + float: left; width: 600px; margin-top: 10px; position: relative; } #colgauche { @@ -571,7 +571,7 @@ } #mdpgauche #accordeon { - width: 300px; + width: 350px; } #accordeon h3 { diff -r 07ab28bca482 -r d366aa22bd79 web/res/js/LdtPlayer-release.js --- a/web/res/js/LdtPlayer-release.js Wed May 02 19:19:51 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6268 +0,0 @@ -/* - * - * Copyright 2010-2012 Institut de recherche et d'innovation - * contributor(s) : Karim Hamidou, Samuel Huron, Raphael Velt, Thibaut Cavalie - * - * 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 0) { - for (var i=0; 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 = { - "&": "&", - "<": "<", - ">": ">", - '"': '"', - "'": ''' - }; - - 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;e2;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;bd?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>1;d(a[g])=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=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/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};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 */ -// Why is it called main ? It only loads the libs ! - -if ( window.IriSP === undefined && window.__IriSP === undefined ) { - /** - @class - the object under which everything goes. - */ - IriSP = {}; - - /** Alias to IriSP for backward compatibility */ - __IriSP = IriSP; -} - -/* underscore comes bundled with the player and we need - it ASAP, so load it that way -*/ - -IriSP._ = window._.noConflict(); -IriSP.underscore = IriSP._; - -IriSP.getLib = function(lib) { - return ( - IriSP.libFiles.useCdn && typeof IriSP.libFiles.cdn[lib] == "string" - ? IriSP.libFiles.cdn[lib] - : ( - typeof IriSP.libFiles.locations[lib] == "string" - ? IriSP.libFiles.locations[lib] - : ( - typeof IriSP.libFiles.inDefaultDir[lib] == "string" - ? IriSP.libFiles.defaultDir + IriSP.libFiles.inDefaultDir[lib] - : null - ) - ) - ) -} - -IriSP.loadLibs = function( config, metadata_url, callback ) { - // Localize jQuery variable - IriSP.jQuery = null; - var $L = $LAB.script(IriSP.getLib("jQuery")).script(IriSP.getLib("swfObject")).wait() - .script(IriSP.getLib("jQueryUI")); - - if (config.player.type === "jwplayer" || config.player.type === "allocine") { - // load our popcorn.js lookalike - $L.script(IriSP.getLib("jwplayer")); - } else { - // load the real popcorn - $L.script(IriSP.getLib("popcorn")).script(IriSP.getLib("popcorn.code")); - if (config.player.type === "youtube") { - $L.script(IriSP.getLib("popcorn.youtube")); - } - if (config.player.type === "vimeo") - $L.script(IriSP.getLib("popcorn.vimeo")); - - /* do nothing for html5 */ - } - - /* widget specific requirements */ - for (var idx in config.gui.widgets) { - if (config.gui.widgets[idx].type === "PolemicWidget" || - config.gui.widgets[idx].type === "StackGraphWidget" || - config.gui.widgets[idx].type === "SparklineWidget") { - $L.script(IriSP.getLib("raphael")); - } - if (config.gui.widgets[idx].type === "TraceWidget") { - $L.script(IriSP.getLib("tracemanager")) - } - } - - // same for modules - /* - for (var idx in config.modules) { - if (config.modules[idx].type === "PolemicWidget") - $L.script(IriSP.getLib("raphaelJs")); - } - */ - - $L.wait(function() { - IriSP.jQuery = window.jQuery.noConflict( true ); - - var css_link_jquery = IriSP.jQuery( "", { - rel: "stylesheet", - type: "text/css", - href: IriSP.getLib("cssjQueryUI"), - 'class': "dynamic_css" - } ); - var css_link_custom = IriSP.jQuery( "", { - 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.annotation_template = "{{! template for an annotation displayed in a segmentWidget }}
"; -IriSP.annotationWidget_template = "{{! template for the annotation widget }}
"; -IriSP.annotation_loading_template = "{{! template shown while the annotation widget is loading }}
 
Chargement...
"; -IriSP.annotationsListWidget_template = "{{! template for the annotation list widget }}
"; -IriSP.arrowWidget_template = "
"; -IriSP.createAnnotationWidget_template = "{{! template for the annotation creation widget }}
{{^cinecast_version}}
{{/cinecast_version}}
{{#show_from_field}} {{/show_from_field}}
{{^user_avatar}} {{/user_avatar}} {{#user_avatar}} {{/user_avatar}}
{{#tags.length}}
    {{#tags}}
  • {{/tags}}
{{#random_tags}} {{/random_tags}} {{/tags.length}} {{#polemic_mode}} {{#polemics.length}}
    {{#polemics}}
  • {{/polemics}}
{{/polemics.length}} {{/polemic_mode}}
"; -IriSP.createAnnotation_errorMessage_template = "

{{l10n.empty_annotation}}

"; -IriSP.loading_template = "
{{l10n.loading_wait}}
"; -IriSP.overlay_marker_template = "{{! the template for the small bars which is z-indexed over our segment widget }}
"; -IriSP.player_template = "{{! template for the radio player }}
{{^disable_annotate_btn}}
{{/disable_annotate_btn}} {{^disable_search_btn}}
{{/disable_search_btn}}
00:00
/
00:00
"; -IriSP.search_template = "{{! template for the search container }}
"; -IriSP.share_template = "{{! social network sharing template }} "; -IriSP.sliceWidget_template = "{{! template for the slice widget }}
{{! the whole bar }}
{{! the zone which represents our slice }}
"; -IriSP.sliderWidget_template = "{{! template for the slider widget - it's composed of two divs we one overlayed on top of the other }}
"; -IriSP.tooltip_template = "{{! template used by the jquery ui tooltip }}
{{title}}
{{begin}} : {{end}}
{{description}}
"; -IriSP.tooltipWidget_template = "{{! template for the tooltip widget }}
"; -IriSP.tweetWidget_template = "{{! template for the tweet widget }}";/* 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( "
"+IriSP.traceNum+" - "+msg+" : "+value+"
" ).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, "$1"], - [/@(\w+)/gi, "@$1"], // matches a @handle - [/#(\w+)/gi, "#$1"],// matches a hashtag - [/(\+\+)/gi, "$1"], - [/(--)/gi, "$1"], - [/(==)/gi, "$1"], - [/(\?\?)/gi, "$1"] - ]; - - 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 val = +dec; - var str = val.toString(16); - var zeroes = ""; - if (str.length < 6) { - for (var i = 0; i < 6 - str.length; i++) - zeroes += "0"; - } - return zeroes + str; -}; - -/* shortcut to have global variables in templates */ -IriSP.templToHTML = function(template, values) { - var params = IriSP.underscore.extend( - { "defaults" : IriSP.default_templates_vars, - "l10n" : IriSP.i18n.getMessages() - }, - 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.jqEscape = function(text) { - return text.replace(/(:|\.)/g,'\\$1') -} - -IriSP.jqId = function (text) { - return IriSP.jQuery('#' + IriSP.jqEscape(text)); - } - -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, text) { - if (typeof(text) === "undefined") - text = "I'm watching "; - - return "http://www.facebook.com/share.php?u=" + IriSP.encodeURI(text) + IriSP.shorten_url(url); -}; - -/** returns an url to share on twitter */ -IriSP.mkTweetUrl = function(url, text) { - if (typeof(text) === "undefined") - text = "I'm watching "; - - return "http://twitter.com/home?status=" + IriSP.encodeURI(text) + IriSP.shorten_url(url); -}; - -/** returns an url to share on google + */ -IriSP.mkGplusUrl = function(url, text) { - return "https://plusone.google.com/_/+1/confirm?hl=en&url=" + IriSP.shorten_url(url); -}; - -/** test if a value is null or undefined */ -IriSP.null_or_undefined = function(val) { - return (typeof(val) === "undefined" || val === null); -}; - -/** get a property that can have multiple names **/ - -IriSP.get_aliased = function(_obj, _aliases) { - for (var _i = 0; _i < _aliases.length; _i++) { - if (typeof _obj[_aliases[_i]] !== "undefined") { - return _obj[_aliases[_i]]; - } - } - return null; -} - -/** issue a call to an url shortener and return the shortened url */ -IriSP.shorten_url = function(url) { - return encodeURIComponent(url); -}; - - -/* 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); - } -} -*/ - -/* Creates regexps from text */ -IriSP.regexpFromText = function(_text) { - return new RegExp('(' + _text.replace(/(\W)/gim,'\\$1') + ')','gim'); -} -/* wrapper that simulates popcorn.js because - popcorn is a bit unstable at the time */ - -IriSP.PopcornReplacement = { -}; - -/** base class for our popcorn-compatible players. - */ -IriSP.PopcornReplacement.player = function(container, options) { - /* the jwplayer calls the callbacks in the global space so we need to - preserve them using IriSP.wrap */ - this.callbacks = { - onReady: IriSP.wrap(this, this.__initApi), - onTime: IriSP.wrap(this, this.__timeHandler), - onPlay: IriSP.wrap(this, this.__playHandler), - onPause: IriSP.wrap(this, this.__pauseHandler), - onSeek: IriSP.wrap(this, this.__seekHandler) - }; - - this.media = { - "paused": true, - "muted": false - }; - - this.container = container.slice(1); //eschew the '#' - - this.msgPump = {}; /* dictionnary used to receive and send messages */ - this.__codes = []; /* used to schedule the execution of a piece of code in - a segment (similar to the popcorn.code plugin). */ - - this._options = options; - -}; - -IriSP.PopcornReplacement.player.prototype.listen = function(msg, callback) { - if (!this.msgPump.hasOwnProperty(msg)) - this.msgPump[msg] = []; - - this.msgPump[msg].push(callback); -}; - -IriSP.PopcornReplacement.player.prototype.trigger = function(msg, params) { - if (!this.msgPump.hasOwnProperty(msg)) - return; - - var d = this.msgPump[msg]; - - for(var i = 0; i < d.length; i++) { - d[i].call(window, params); - } - -}; - -IriSP.PopcornReplacement.player.prototype.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; -}; - -/** init the api after that flash player has been setup - called by the callback - defined by the embedded flash player -*/ -IriSP.PopcornReplacement.player.prototype.__initApi = function() { - this.trigger("loadedmetadata"); // we've done more than loading metadata of course, - // but popcorn doesn't need to know more. - this.media.muted = this.playerFns.getMute(); - /* some programmed segments are supposed to be run at the beginning */ - var i = 0; - for(i = 0; i < this.__codes.length; i++) { - var c = this.__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.player.prototype.currentTime = function(time) { - if (typeof(time) === "undefined") { - return this.playerFns.getPosition(); - } else { - var currentTime = +time; - this.playerFns.seek(currentTime); - return currentTime; - } -}; - -IriSP.PopcornReplacement.player.prototype.play = function() { - this.media.paused = false; - this.trigger("play"); - //IriSP.PopcornReplacement.trigger("playing"); - this.playerFns.play(); -}; - -IriSP.PopcornReplacement.player.prototype.pause = function() { -// if ( !this.media.paused ) { - this.media.paused = true; - this.trigger( "pause" ); - this.playerFns.pause(); -// } -}; - -IriSP.PopcornReplacement.player.prototype.muted = function(val) { - if (typeof(val) !== "undefined") { - - if (this.playerFns.getMute() !== val) { - if (val) { - this.playerFns.setMute(true); - this.media.muted = true; - } else { - this.playerFns.setMute(false); - this.media.muted = false; - } - - this.trigger( "volumechange" ); - } - - return this.playerFns.getMute(); - } else { - return this.playerFns.getMute(); - } -}; - -IriSP.PopcornReplacement.player.prototype.volume = function(val) { - if (typeof this.playerFns.getVolume == "undefined" || typeof this.playerFns.setVolume == "undefined") { - return false; - } - var _vol = this.playerFns.getVolume(); - if (typeof(val) !== "undefined" && parseFloat(val) !== NaN) { - val = Math.max(0, Math.min(1, val)); - if (parseFloat(val) != parseFloat(_vol)) { - this.playerFns.setVolume(val); - this.trigger("volumechange"); - _vol = this.playerFns.getVolume(); - } - } - return _vol; -}; - -IriSP.PopcornReplacement.player.prototype.mute = IriSP.PopcornReplacement.player.prototype.muted; - -IriSP.PopcornReplacement.player.prototype.code = function(options) { - this.__codes.push(options); - return this; -}; - -/* called everytime the player updates itself - (onTime event) - */ - -IriSP.PopcornReplacement.player.prototype.__timeHandler = function(event) { - var pos = event.position; - - var i = 0; - for(i = 0; i < this.__codes.length; i++) { - var c = this.__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(); - } - - } - - this.trigger("timeupdate"); -}; - -IriSP.PopcornReplacement.player.prototype.__seekHandler = function(event) { - var i = 0; - - for(i = 0; i < this.__codes.length; i++) { - var c = this.__codes[i]; - - if (event.position >= c.start && event.position < c.end) { - c.onEnd(); - } - } - - for(i = 0; i < this.__codes.length; i++) { - var c = this.__codes[i]; - - if (typeof(event.offset) === "undefined") - event.offset = 0; - - if (event.offset >= c.start && event.offset < c.end) { - c.onStart(); - } - - } - - /* this signal sends as an extra argument the position in the video. - As far as I know, this argument is not provided by popcorn */ - this.trigger("seeked", event.offset); -}; - -IriSP.PopcornReplacement.player.prototype.__playHandler = function(event) { - this.media.paused = false; - this.trigger("play"); -}; - -IriSP.PopcornReplacement.player.prototype.__pauseHandler = function(event) { - this.media.paused = true; - this.trigger("pause"); -}; - -IriSP.PopcornReplacement.player.prototype.roundTime = function() { - var currentTime = this.currentTime(); - return Math.round(currentTime); -};/* 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, force_reload) { - var base_url = url.split("&")[0]; - if (typeof force_reload != "undefined" && force_reload && this._cache.hasOwnProperty(base_url)) { - delete this._cache[base_url] - } - if (this._cache.hasOwnProperty(base_url)) { - callback(this._cache[base_url]); - } else { - if (!this._callbacks.hasOwnProperty(base_url)) { - this._callbacks[base_url] = [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]); - } - delete this._callbacks[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.getDuration = 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; - } -}; -IriSP.language = 'en'; - -IriSP.libFiles = { - defaultDir : "js/libs/", - inDefaultDir : { - jQuery : "jquery.min.js", - jQueryUI : "jquery-ui.min.js", - jQueryToolTip : "jquery.tools.min.js", - swfObject : "swfobject.js", - cssjQueryUI : "jquery-ui.css", - popcorn : "popcorn.js", - jwplayer : "jwplayer.js", - raphael : "raphael.js", - "popcorn.mediafragment" : "popcorn.mediafragment.js", - "popcorn.code" : "popcorn.code.js", - "popcorn.jwplayer" : "popcorn.jwplayer.js", - "popcorn.youtube" : "popcorn.youtube.js", - "tracemanager" : "tracemanager.js" - }, - locations : { - // use to define locations outside defautl_dir - }, - cdn : { - jQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.js", - jQueryToolTip : "http://cdn.jquerytools.org/1.2.4/all/jquery.tools.min.js", - swfObject : "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js", - cssjQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css" - }, - useCdn : false -} - -IriSP.widgetsDefaults = { - "LayoutManager" : { - spacer_div_height : 0 - }, - "PlayerWidget" : { - - }, - "AnnotationsWidget" : { - "share_text" : "I'm watching " - }, - "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 ? - }, - "SegmentsWidget" : { - cinecast_version : false - }, - "createAnnotationWidget" : { - tags : [ - { - "id" : "digitalstudies", - "meta" : { - "description" : "#digital-studies" - } - }, - { - "id" : "amateur", - "meta" : { - "description" : "#amateur" - }, - } - ], - remote_tags : false, - random_tags : false, - show_from_field : false, - disable_share : false, - polemic_mode : true, /* enable polemics ? */ - polemics : [{ - "className" : "positive", - "keyword" : "++" - }, { - "className" : "negative", - "keyword" : "--" - }, { - "className" : "reference", - "keyword" : "==" - }, { - "className" : "question", - "keyword" : "??" - }], - cinecast_version : false, /* put to false to enable the platform version, true for the festival cinecast one. */ - - /* where does the widget PUT the annotations - this is a mustache template. id refers to the id of the media ans is filled - by the widget. - */ - api_endpoint_template : "", // platform_url + "/ldtplatform/api/ldt/annotations/{{id}}.json", - api_method : "PUT" - }, - "SparklineWidget" : { - lineColor : "#7492b4", - fillColor : "#aeaeb8", - lineWidth : 2, - cinecast_version : false - }, - "AnnotationsListWidget" : { - ajax_mode : true, /* use ajax to get information about the annotations. - if set to false, only search in the annotations for the - current project. */ - /* the platform generates some funky urls. We replace them afterwards to point to the - correct place - this setting will probably be overwritten by the platform - implementers. - Note that the player has to replace the variables between {{ and }} by its own values. - */ - ajax_url : "", //platform_url + "/ldtplatform/api/ldt/segments/{{media}}/{{begin}}/{{end}}", - ajax_granularity : 10000, /* how much ms should we look before and after the current timecode */ - default_thumbnail : "http://ldt.iri.centrepompidou.fr/static/site/ldt/css/imgs/video_sequence.png", - project_url : "", //platform_url + "/ldtplatform/ldt/front/player/" - /* the beginning of a link to the new front */ - cinecast_version : false, - refresh_interval : 10000 - }, - "StackGraphWidget" : { - defaultcolor : "#585858", - tags : [ - { - "keywords" : [ "++" ], - "description" : "positif", - "color" : "#1D973D" - }, - { - "keywords" : [ "--" ], - "description" : "negatif", - "color" : "#CE0A15" - }, - { - "keywords" : [ "==" ], - "description" : "reference", - "color" : "#C5A62D" - }, - { - "keywords" : [ "??" ], - "description" : "question", - "color" : "#036AAE" - } - ], - streamgraph : false - } -}/* 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; - } - if (typeof this.selector != "undefined") { - this.selector.addClass("Ldt-TraceMe").addClass("Ldt-Widget"); - this.selector.attr("widget-type", this._config.type); - } - - // Parsing Widget Defaults - var _this = this; - - if (typeof config.type == "string" && typeof IriSP.widgetsDefaults[config.type] == "object") { - IriSP._(IriSP.widgetsDefaults[config.type]).each(function(_v, _k) { - if (typeof config[_k] != "undefined") { - _this[_k] = config[_k]; - } else { - _this[_k] = _v; - } - }); - } - -}; - - -IriSP.Widget.prototype.currentMedia = function() { - return this._serializer.currentMedia(); -} - -IriSP.Widget.prototype.getDuration = function() { - return this._serializer.getDuration(); -} - -/** - * 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, - "clear": "both" - }); - - 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 = "
"); - - 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; - - - /* Try to guess options.file and options.streamer only if file and streamer - are not already defined in the configuration */ - if (options.provider === "rtmp" && !opts.hasOwnProperty("file") && !opts.hasOwnProperty("streamer")) { - /* 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); - - /* sometimes we get served a file with a wrong path and streamer. - as a streamer is of the form rtmp://domain/path/ and the media is - the rest, we uglily do this : - */ - opts.file = ""; - opts.streamer = ""; - var fullPath = IriSP.get_aliased(IriSP.__jsonMetadata["medias"][0], ["href","url"]); - - if (fullPath === null) { - console.log("no url or href field defined in the metadata."); - } - - var pathSplit = fullPath.split('/'); - - for (var i = 0; i < pathSplit.length; i++) { - if (i < 4) { - opts.streamer += pathSplit[i] + "/"; - } else { - opts.file += pathSplit[i]; - /* omit the last slash if we're on the last element */ - if (i < pathSplit.length - 1) - 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 = new 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; - - case "dailymotion": - pop = new IriSP.PopcornReplacement.dailymotion("#" + containerDiv, options); - break; - - case "allocine": - /* pass the options as-is to the allocine player and let it handle everything */ - pop = new IriSP.PopcornReplacement.allocine("#" + containerDiv, options); - 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 default_options = guiOptions.default_options; - if (IriSP.null_or_undefined(default_options)) - default_options = {}; - - var ret_widgets = []; - var index; - - for (index = 0; index < guiOptions.widgets.length; index++) { - var widget = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, guiOptions.widgets[index], default_options); - - ret_widgets.push(widget); - }; - - return ret_widgets; -}; - -/** configure modules. @see configureWidgets */ -IriSP.configureModules = function (popcornInstance, modulesList) { - if (IriSP.null_or_undefined(modulesList)) - return; - - 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 - @param defaultOptions a dictionnary with some options defined for every widget. - */ -IriSP.instantiateWidget = function(popcornInstance, serialFactory, layoutManager, widgetConfig, defaultOptions) { - - if (IriSP.null_or_undefined(defaultOptions)) - defaultOptions = {}; - - widgetConfig = IriSP.underscore.defaults(widgetConfig, defaultOptions); - - 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"], - _configobj = IriSP.jQuery.extend({}, widgetConfig.requires[i]), - _div = document.createElement('div'), - _container = IriSP.guid(arr.container + '_' + widgetName + '_'); - _configobj.container = _container; - _div.id = _container; - widget.selector.append(_div); - widget[widgetName] = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, _configobj, defaultOptions); - } - } - - serializer.sync(IriSP.wrap(widget, function() { this.draw(); })); - return widget; -}; - -/** single point of entry for the metadataplayer */ -IriSP.initPlayer = function(config, metadata_url) { - document.getElementById(config.gui.container).innerHTML = IriSP.templToHTML(IriSP.loading_template, config.gui); - IriSP.loadLibs(config, metadata_url, - function() { - - var layoutManager = new IriSP.LayoutManager(config.gui); - - var pop = IriSP.configurePopcorn(layoutManager, config.player); - - IriSP._widgets = IriSP.configureWidgets(pop, layoutManager, config.gui); - IriSP._modules = IriSP.configureModules(pop, config.modules); - IriSP.jQuery('#Ldt-loader').detach(); - }); -};IriSP.I18n = function() { - this.messages = {}; - this.base_lang = 'en'; -} - -IriSP.I18n.prototype.getLanguage = function(lang) { - var _lang = ( - typeof lang != "undefined" - ? lang - : ( - typeof IriSP.language != "undefined" - ? IriSP.language - : this.base_lang - ) - ); - return ( - typeof this.messages[_lang] == "object" - ? _lang - : ( - typeof this.messages[this.base_lang] == "object" - ? this.base_lang - : null - ) - ) -} - -IriSP.I18n.prototype.getMessages = function(lang) { - var _lang = this.getLanguage(lang); - return ( - _lang != null - ? this.messages[_lang] - : {} - ); -} - -IriSP.I18n.prototype.getMessage = function(message, lang) { - var _msgs = this.getMessages(lang); - return ( - typeof _msgs[message] != "undefined" - ? _msgs[message] - : message - ) -} - -IriSP.I18n.prototype.addMessage = function(lang, messagekey, messagevalue) { - if (typeof this.messages[lang] == "undefined") { - this.messages[lang] = {}; - } - this.messages[lang][messagekey] = messagevalue; -} - -IriSP.I18n.prototype.addMessages = function(messagesObj) { - var _this = this; - IriSP.underscore(messagesObj).each(function(_messages, _lang) { - IriSP.underscore(_messages).each(function(_value, _key) { - _this.addMessage(_lang, _key, _value); - }) - }); -} - -IriSP.i18n = new IriSP.I18n(); - -IriSP.i18n.addMessages({ - "fr": { - "loading_wait": "Chargement en cours, veuillez patienter…" - }, - "en": { - "loading_wait": "Loading, please wait…" - } -}) -/* To wrap a player the develop should create a new class derived from -the IriSP.PopcornReplacement.player and defining the correct functions */ - -/** allocine player wrapper */ -IriSP.PopcornReplacement.allocine = function(container, options) { -// console.log("Calling allocine player"); - /* appel du parent pour initialiser les structures communes à tous les players */ - IriSP.PopcornReplacement.player.call(this, container, options); - - var _this = this; - - /* Définition des fonctions de l'API - */ - - this.playerFns = { - play : function() { - return _this.apiCall("play"); - }, - pause : function() { - return _this.apiCall("pause"); - }, - getPosition : function() { - return _this.apiCall("getSeek","return") || 0; - }, - seek : function(pos) { - return _this.apiCall("seek",pos); - }, - getMute : function() { - return _this.apiCall("getMute","return"); - }, - setMute : function(p) { - return _this.apiCall("setMute", p); - } - } - - window.onReady = IriSP.wrap(this, this.ready); - window.onAllocineStateChange = IriSP.wrap(this, this.stateHandler); - window.onTime = IriSP.wrap(this, this.progressHandler); - - var _videoUrl = ( - typeof options.directVideoPath == "string" - ? options.directVideoPath - : IriSP.get_aliased(IriSP.__jsonMetadata["medias"][0], ["href","url"]) - ); - var _flashVars = { - "streamFMS" : true, - "adVast" : false, - "lg" : "fr_cinecast", - "autoPlay" : options.autoPlay, - "directVideoTitle" : "", - "urlAcData" : options.urlAcData, - "directVideoPath" : _videoUrl, - "host" : "http://allocine.fr" - } - - if (typeof IriSP.__jsonMetadata["medias"][0].meta == "object" && typeof IriSP.__jsonMetadata["medias"][0].meta.subtitles == "string") { - _flashVars.subTitlePath = IriSP.__jsonMetadata["medias"][0].meta.subtitles; - } - - - var params = { - "allowScriptAccess" : "always", - "wmode": "opaque", - "flashvars" : IriSP.jQuery.param(_flashVars), - "allowfullscreen" : true - }; - var atts = { - id : this.container - }; - swfobject.embedSWF(options.acPlayerUrl, this.container, options.width, options.height, "10", null, null, params, atts); - -}; - -IriSP.PopcornReplacement.allocine.prototype = new IriSP.PopcornReplacement.player("", {}); - -IriSP.PopcornReplacement.allocine.prototype.ready = function() { - this.player = document.getElementById(this.container); - this.player.addEventListener("onStateChange", "onAllocineStateChange"); - this.player.cueVideoByUrl(this._options.video); - this.callbacks.onReady(); -}; - -IriSP.PopcornReplacement.allocine.prototype.progressHandler = function(progressInfo) { - this.callbacks.onTime({ - position: progressInfo.mediaTime - }); -} - - -IriSP.PopcornReplacement.allocine.prototype.apiCall = function(_method, _arg) { - if (this.player) { - try { - if (typeof _arg == "undefined") { - return this.player.sendToActionScript(_method); - } else { - return this.player.sendToActionScript(_method, _arg); - } - } catch(e) { - console.error('Exception while requesting AcPlayer for "' + _method + (typeof _arg == "undefined" ? '' : '" with argument "' + _arg ) + '"\n', e); - return false; - } - } else { - return false; - } -} - -IriSP.PopcornReplacement.allocine.prototype.stateHandler = function(state) { - console.log("stateHandler"); - switch(state) { - case 1: - this.callbacks.onPlay(); - break; - - case 2: - this.callbacks.onPause(); - break; - - case 3: - this.callbacks.onSeek({ - position: this.player.getCurrentTime() - }); - break; - - /* - case 5: - this.callbacks.onReady(); - break; - */ - } - -};/* To wrap a player the develop should create a new class derived from -the IriSP.PopcornReplacement.player and defining the correct functions */ - -/** jwplayer player wrapper */ -IriSP.PopcornReplacement.dailymotion = function(container, options) { - console.log("Calling"); - /* appel du parent pour initialiser les structures communes à tous les players */ - IriSP.PopcornReplacement.player.call(this, container, options); - - var _this = this; - - /* Définition des fonctions de l'API - */ - - this.playerFns = { - play : function() { - if (_this.player) { - return _this.player.playVideo(); - } else { - return false; - } - }, - pause : function() { - if (_this.player) { - return _this.player.pauseVideo(); - } else { - return false; - } - }, - getPosition : function() { - if (_this.player) { - return _this.player.getCurrentTime(); - } else { - return 0; - } - }, - seek : function(pos) { - if (_this.player) { - return _this.player.seekTo(pos); - } else { - return false; - } - }, - getMute : function() { - if (_this.player) { - return _this.player.isMuted(); - } else { - return false; - } - }, - setMute : function(p) { - if (_this.player) { - if (p) { - _this.player.mute(); - } - else { - _this.player.unMute(); - } - } - }, - getVolume : function() { - if (_this.player) { - return _this.player.getVolume() / 100; - } else { - return false; - } - }, - setVolume : function(p) { - if (_this.player) { - _this.player.setVolume(Math.floor(100 * p)); - } - }, - } - - window.onDailymotionPlayerReady = IriSP.wrap(this, this.ready); - window.onDailymotionStateChange = IriSP.wrap(this, this.stateHandler); - window.onDailymotionVideoProgress = IriSP.wrap(this, this.progressHandler); - - var params = { - "allowScriptAccess" : "always", - "wmode": "opaque" - }; - var atts = { - id : this.container - }; - swfobject.embedSWF("http://www.dailymotion.com/swf?chromeless=1&enableApi=1", this.container, options.width, options.height, "8", null, null, params, atts); - -}; - -IriSP.PopcornReplacement.dailymotion.prototype = new IriSP.PopcornReplacement.player("", {}); - -IriSP.PopcornReplacement.dailymotion.prototype.ready = function() { - - this.player = document.getElementById(this.container); - - this.player.addEventListener("onStateChange", "onDailymotionStateChange"); - this.player.addEventListener("onVideoProgress", "onDailymotionVideoProgress"); - this.player.cueVideoByUrl(this._options.video); - - this.callbacks.onReady(); -}; - -IriSP.PopcornReplacement.dailymotion.prototype.progressHandler = function(progressInfo) { - - this.callbacks.onTime({ - position: progressInfo.mediaTime - }); -} - -IriSP.PopcornReplacement.dailymotion.prototype.stateHandler = function(state) { - - switch(state) { - case 1: - this.callbacks.onPlay(); - break; - - case 2: - this.callbacks.onPause(); - break; - - case 3: - this.callbacks.onSeek({ - position: this.player.getCurrentTime() - }); - break; - - /* - case 5: - this.callbacks.onReady(); - break; - */ - } - -};/* To wrap a player the develop should create a new class derived from - the IriSP.PopcornReplacement.player and defining the correct functions */ - -/** jwplayer player wrapper */ -IriSP.PopcornReplacement.jwplayer = function(container, options) { - /* appel du parent pour initialiser les structures communes à tous les players */ - IriSP.PopcornReplacement.player.call(this, container, options); - - this.media.duration = options.duration; /* optional */ - - /* Définition des fonctions de l'API - */ - this.playerFns = { - play: function() { return jwplayer(this.container).play(); }, - pause: function() { return jwplayer(this.container).pause(); }, - getPosition: function() { return jwplayer(this.container).getPosition(); }, - seek: function(pos) { return jwplayer(this.container).seek(pos); }, - getMute: function() { return jwplayer(this.container).getMute() }, - setMute: function(p) { return jwplayer(this.container).setMute(p); }, - getVolume: function() { return jwplayer(this.container).getVolume() / 100; }, - setVolume: function(p) { return jwplayer(this.container).setVolume(Math.floor(100*p)); } - } - - options.events = this.callbacks; - - jwplayer(this.container).setup(options); -}; - -IriSP.PopcornReplacement.jwplayer.prototype = new IriSP.PopcornReplacement.player("", {}); -/* embed module - listens and relay hash changes to a parent window. */ - -IriSP.EmbedModule = function(Popcorn, config, Serializer) { - IriSP.Module.call(this, Popcorn, config, Serializer); - - window.addEventListener('message', IriSP.wrap(this, this.handleMessages), false); - this._Popcorn.listen("IriSP.Mediafragment.hashchange", IriSP.wrap(this, this.relayChanges)); -}; - -IriSP.EmbedModule.prototype = new IriSP.Module(); - -IriSP.EmbedModule.prototype.handleMessages = function(e) { - if (e.data.type === "hashchange") { - window.location.hash = e.data.value; - } -}; - -IriSP.EmbedModule.prototype.relayChanges = function(newHash) { - window.parent.postMessage({type: "hashchange", value: newHash}, "*"); - return; -};/* 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) ); - - /* we have to trigger this signal manually because of a - bug in the jwplayer */ - this._Popcorn.trigger("seeked", parseFloat(offsettime)); - } - } else if ( pageoffset.substring(0, 3) === "id=") { - // annotation - var annotationId = pageoffset.substring( 3 ); - // there's no better way than that because - // of possible race conditions - this._serializer.sync(IriSP.wrap(this, function() { - this.lookupAnnotation.call(this, annotationId); - })); - } - } -}; - -/** handler for the seeked signal. It may have or may have not an argument. - @param time if not undefined, the time we're seeking to -*/ -IriSP.MediaFragment.prototype.updateTime = function(time) { - if (this.mutex === true) { - return; - } - - var history = window.history; - if ( !history.pushState ) { - return false; - } - - if (IriSP.null_or_undefined(time) || typeof(time) != "number") { - var ntime = this._Popcorn.currentTime().toFixed(2) - } else { - var ntime = time.toFixed(2); - } - - // used to relay the new hash to the embedder - this._Popcorn.trigger("IriSP.Mediafragment.hashchange", "#t=" + ntime); - - splitArr = window.location.href.split( "#" ) - history.replaceState( {}, "", splitArr[0] + "#t=" + ntime ); -}; - - -IriSP.MediaFragment.prototype.updateAnnotation = function(annotationId) { - var _this = this; - this.mutex = true; - - var history = window.history; - if ( !history.pushState ) { - return false; - } - - - // used to relay the new hash to the embedder - this._Popcorn.trigger("IriSP.Mediafragment.hashchange", "#id=" + annotationId); - - splitArr = window.location.href.split( "#" ) - history.replaceState( {}, "", splitArr[0] + "#id=" + annotationId); - - - // reset the mutex afterwards to prevent the module from reacting to his own changes. - 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); - - /* we have to trigger this signal manually because of a - bug in the jwplayer */ - this._Popcorn.trigger("seeked", annotation.begin / 1000); - this._Popcorn.trigger("IriSP.Mediafragment.showAnnotation", annotationId); - } - - 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 = []; - this.searchRe = null; - this._ajax_cache = []; - var _this = this; - - this._Popcorn.listen("IriSP.search", function(searchString) { - _this.searchHandler(searchString); - }); - this._Popcorn.listen("IriSP.search.closed", function() { - _this.searchHandler(false); - }); - this._Popcorn.listen("IriSP.search.cleared", function() { - _this.searchHandler(false); - }); -}; - - -IriSP.AnnotationsListWidget.prototype = new IriSP.Widget(); - -IriSP.AnnotationsListWidget.prototype.clear = function() { -}; - -IriSP.AnnotationsListWidget.prototype.clearWidget = function() { -}; - -IriSP.AnnotationsListWidget.prototype.searchHandler = function(searchString) { - this.searchRe = (searchString && searchString.length) ? IriSP.regexpFromText(searchString) : null; - if (this.ajax_mode && !this.cinecast_version) { - var _this = this, - _annotations = ( - this.searchRe === null - ? this._ajax_cache - : IriSP.underscore.filter(this._ajax_cache, function(_a) { - return (_this.searchRe.test(_a.desc) || _this.searchRe.test(_a.title)); - }) - ); - this.do_redraw(_annotations); - if (_annotations.length) { - this._Popcorn.trigger("IriSP.search.matchFound"); - } else { - this._Popcorn.trigger("IriSP.search.noMatchFound"); - } - } else { - this.drawList(); - } -} - -/** effectively redraw the widget - called by drawList */ -IriSP.AnnotationsListWidget.prototype.do_redraw = function(list) { - var _html = IriSP.templToHTML( - IriSP.annotationsListWidget_template, { - annotations: list - }), - _this = this; - - this.selector.html(_html); - - this.selector.find('.Ldt-AnnotationsList-Tag-Li').click(function() { - _this._Popcorn.trigger("IriSP.search.triggeredSearch", IriSP.jQuery(this).text().trim()); - }) - - if (this.searchRe !== null) { - this.selector.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description") - .each(function() { - var _$ = IriSP.jQuery(this); - _$.html(_$.text().trim().replace(_this.searchRe, '$1')) - }) - } -}; - -IriSP.AnnotationsListWidget.prototype.transformAnnotation = function(a) { - var _this = this; - return { - "id" : a.id, - "title": this.cinecast_version ? IriSP.get_aliased(a.meta, ['creator_name', 'creator']) : a.content.title, - "desc" : this.cinecast_version ? a.content.data : a.content.description, - "begin": IriSP.msToTime(a.begin), - "end" : IriSP.msToTime(a.end), - "thumbnail" : (typeof a.meta == "object" && typeof a.meta.thumbnail == "string") ? a.meta.thumbnail : this.default_thumbnail, - "url" : (typeof a.meta == "object" && typeof a.meta.url == "string") ? a.meta.url : null, - "created_at" :(typeof a.meta == "object" && typeof a.meta.created == "string") ? Date.parse(a.meta.created.replace(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}\:\d{2}\:\d{2}).*$/,"$2/$3/$1 $4 UTC+0000")) : null, - "tags": typeof a.tags == "object" - ? IriSP.underscore(a.tags) - .chain() - .map(function(_t) { - if (typeof _t == "string") { - return _t.replace(/^.*:/,'#'); - } else { - if (typeof _t['id-ref'] != "undefined") { - var _f = IriSP.underscore.find(_this._serializer._data.tags, function(_tag) { - return _tag.id == _t['id-ref']; - }); - if (typeof _f != "undefined") { - return IriSP.get_aliased(_f.meta, ['dc:title', 'title']); - } - } - } - return null; - }) - .filter(function(_t) { - return _t !== null && _t !== "" - }) - .value() - : [] - } -} - -/** 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") { - return; -} */ - for (i = 0; i < annotations.length; i++) { - var obj = this.transformAnnotation(annotations[i]); - obj.iterator = i; - obj.distance = Math.abs((annotations[i].end + annotations[i].begin) / 2000 - currentTime); - if (!this.cinecast_version || annotations[i].type == "cinecast:UserAnnotation") { - list.push(obj); - } - - } - - if (this.searchRe !== null) { - list = list.filter(function(_a) { - return (_this.searchRe.test(_a.desc) || _this.searchRe.test(_a.title)); - }); - if (list.length) { - this._Popcorn.trigger("IriSP.search.matchFound"); - } else { - this._Popcorn.trigger("IriSP.search.noMatchFound"); - } - } - list = IriSP.underscore(list) - .chain() - .sortBy(function(_o) { - return _o.distance; - }) - .first(10) - .sortBy(function(_o) { - return (_this.cinecast_version ? - _o.created_at : _o.iterator); - }) - .value(); - var idList = IriSP.underscore.pluck(list, "id").sort(); - - if (!IriSP.underscore.isEqual(this.__oldList, idList) || this.lastSearch !== this.searchRe || typeof(force_redraw) !== "undefined") { - this.do_redraw(list); - this.__oldList = idList; - this.lastSearch = this.searchRe; - } - /* save for next call */ - - -}; - -IriSP.AnnotationsListWidget.prototype.ajaxRedraw = function(timecode) { - - /* the seeked signal sometimes passes an argument - depending on if we're using - our popcorn lookalike or the real thing - if it's the case, use it as it's - more precise than currentTime which sometimes contains the place we where at */ - if (IriSP.null_or_undefined(timecode) || typeof(timecode) != "number") { - var tcode = this._Popcorn.currentTime(); - } else { - var tcode = timecode; - } - - - /* the platform gives us a special url - of the type : http://path/{{media}}/{{begin}}/{{end}} - we double the braces using regexps and we feed it to mustache to build the correct url - we have to do that because the platform only knows at run time what view it's displaying. - */ - - var media_id = this.currentMedia()["id"]; - var duration = this.getDuration(); - - var begin_timecode = (Math.floor(tcode) - 300) * 1000; - if (begin_timecode < 0) - begin_timecode = 0; - - var end_timecode = (Math.floor(tcode) + 300) * 1000; - if (end_timecode > duration) - end_timecode = duration; - - var templ = Mustache.to_html(this.ajax_url, {media: media_id, begin: begin_timecode, - end: end_timecode}); - - /* we create on the fly a serializer to get the ajax */ - var serializer = new IriSP.JSONSerializer(IriSP.__dataloader, templ); - serializer.sync(IriSP.wrap(this, function(json) { this.processJson(json, serializer) })); -}; - -/** process the received json - it's a bit hackish */ -IriSP.AnnotationsListWidget.prototype.processJson = function(json, serializer) { - /* FIXME: DRY the whole thing */ - var annotations = serializer._data.annotations; - if (IriSP.null_or_undefined(annotations)) - return; - - /* - commented in case we wanted to discriminate against some annotation types. - var view_types = serializer.getIds("Contributions"); - */ - var l = []; - - var media = this.currentMedia()["id"]; - - for (i = 0; i < annotations.length; i++) { - var obj = this.transformAnnotation(annotations[i]) - if (typeof obj.url == "undefined" || !obj.url) { - /* only if the annotation isn't present in the document create an - external link */ - if (this.annotations_ids.indexOf(obj.id.toLowerCase()) == -1) { - // braindead url; jacques didn't want to create a new one in the platform, - // so we append the cutting id to the url. - obj.url = this.project_url + "/" + media + "/" + - annotations[i].meta.project + "/" + - annotations[i].meta["id-ref"] + '#id=' + annotations[i].id; - - // obj.url = document.location.href.split("#")[0] + "/" + annotation.meta.project; - } - } - l.push(obj); - } - this._ajax_cache = l; - this.do_redraw(l); -}; -IriSP.AnnotationsListWidget.prototype.draw = function() { - - /* build a table of the annotations present in the document for faster - lookup - */ - this.annotations_ids = IriSP.underscore(this._serializer._data.annotations).map(function(_a) { - return _a.id.toLowerCase(); - }); - - var _this = this; - - if (!this.ajax_mode || this.cinecast_version) { - var _throttled = IriSP.underscore.throttle(function() { - _this.drawList(); - }, 1500); - _throttled(); - this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation", _throttled); - this._Popcorn.listen("timeupdate", _throttled); - if (this.cinecast_version) { - window.setInterval(function() { - var _tmpSerializer = new IriSP.JSONSerializer(IriSP.__dataloader, _this._config.metadata.src, true); - _tmpSerializer.sync(function(json) { - _this.annotations_ids = IriSP.underscore(_this._serializer._data.annotations).map(function(_a) { - return _a.id.toLowerCase(); - }); - IriSP.underscore(json.annotations).each(function(_a) { - var _j = _this.annotations_ids.indexOf(_a.id); - if (_j == -1) { - _this._serializer._data.annotations.push(_a); - _this.annotations_ids.push(_a.id); - } else { - _this._serializer._data.annotations[_j] = _a; - } - _throttled(); - }); - }, true); // true is for force_refresh - },this.refresh_interval); - } - } else { - /* update the widget when the video has finished loading and when it's seeked and paused */ - this._Popcorn.listen("seeked", IriSP.wrap(this, this.ajaxRedraw)); - this._Popcorn.listen("loadedmetadata", IriSP.wrap(this, this.ajaxRedraw)); - this._Popcorn.listen("paused", IriSP.wrap(this, this.ajaxRedraw)); - - this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation", IriSP.wrap(this, this.ajaxRedraw)); - } - -};/* Internationalization for this widget */ - -IriSP.i18n.addMessages( - { - "fr": { - "keywords": "Mots-clés" - }, - "en": { - "keywords": "Keywords" - } - } -); - -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 = ""; - var begin = +annotation.begin / 1000; - var end = +annotation.end / 1000; - var duration = this.getDuration(); - var tags = ""; - - 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); - - - if (!IriSP.null_or_undefined(annotation.tags) && !IriSP.null_or_undefined(this._serializer._data.tags)) { - /* save the tag id and keywords in a unique structure */ - var tag_list = {}; - for (var i = 0; i < this._serializer._data.tags.length; i++) { - var id = this._serializer._data.tags[i]["id"]; - var keyword = IriSP.get_aliased(this._serializer._data.tags[i]["meta"], ["dc:title", "title"]); - - tag_list[id] = keyword; - } - - /* then browse the list of defined tags for the current annotation */ - for (var i = 0; i < annotation.tags.length; i++) { - if (tag_list.hasOwnProperty(annotation.tags[i]["id-ref"])) - tags += tag_list[annotation.tags[i]["id-ref"]] + ", "; - } - } - - tags = IriSP.i18n.getMessage("keywords") + ": " + tags.slice(0, tags.length - 2); - - this.selector.find(".Ldt-SaKeywords").text(tags); - - // update sharing buttons - var url = document.location.href + "#id=" + annotation.id; - this.selector.find(".Ldt-fbShare").attr("href", IriSP.mkFbUrl(url, this.share_text)); - this.selector.find(".Ldt-TwShare").attr("href", IriSP.mkTweetUrl(url, this.share_text)); - this.selector.find(".Ldt-GplusShare").attr("href", IriSP.mkGplusUrl(url, this.share_text)); -}; - -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.AnnotationsWidget.show", - IriSP.wrap(this, this.show)); - this._Popcorn.listen("IriSP.AnnotationsWidget.hide", - IriSP.wrap(this, this.hide)); - - 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.hide = function() { - if (this._hidden == false) { - this.selector.hide(); - this._hidden = true; - } -}; - -IriSP.AnnotationsWidget.prototype.show = function() { - if (this._hidden == true) { - 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.currentChapitre(currentTime); - if (IriSP.null_or_undefined(currentAnnotation)) { - var c_annots = this._serializer.currentAnnotation(currentTime) - if (c_annots.length != 0) - var currentAnnotation = c_annots[0]; // FIXME : use the others ? - else - return; - } - - /* 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.getDuration() / 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) { - this.selector.children(".Ldt-arrowWidget").removeClass("Ldt-arrowLeftEdge Ldt-arrowCenter Ldt-arrowRightEdge") - .addClass("Ldt-arrowLeftEdge"); - } else if (corrected_pixels >= totalWidth - 25) { - this.selector.children(".Ldt-arrowWidget").removeClass("Ldt-arrowLeftEdge Ldt-arrowCenter Ldt-arrowRightEdge") - .addClass("Ldt-arrowRightEdge"); - } else { - this.selector.children(".Ldt-arrowWidget").removeClass("Ldt-arrowLeftEdge Ldt-arrowCenter Ldt-arrowRightEdge") - .addClass("Ldt-arrowCenter"); - } - - 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; -}; -/* Internationalization for this widget */ - -IriSP.i18n.addMessages( - { - "en": { - "submit": "Submit", - "add_keywords": "Add keywords", - "add_polemic_keywords": "Add polemic keywords", - "your_name": "Your name", - "type_here": "Type your annotation here.", - "wait_while_processed": "Please wait while your request is being processed...", - "error_while_contacting": "An error happened while contacting the server. Your annotation has not been saved.", - "empty_annotation": "Your annotation is empty. Please write something before submitting.", - "annotation_saved": "Thank you, your annotation has been saved.", - "share_annotation": "Would you like to share it on social networks ?", - "share_on": "Share on", - "more_tags": "More tags" - }, - "fr": { - "submit": "Envoyer", - "add_keywords": "Ajouter des mots-clés", - "add_polemic_keywords": "Ajouter des mots-clés polémiques", - "your_name": "Votre nom", - "type_here": "Rédigez votre annotation ici.", - "wait_while_processed": "Veuillez patienter pendant le traitement de votre requête...", - "error_while_contacting": "Une erreur s'est produite en contactant le serveur. Votre annotation n'a pas été enregistrée", - "empty_annotation": "Votre annotation est vide. Merci de rédiger un texte avant de l'envoyer.", - "annotation_saved": "Merci, votre annotation a été enregistrée.", - "share_annotation": "Souhaitez-vous la partager sur les réseaux sociaux ?", - "share_on": "Partager sur", - "more_tags": "Plus de mots-clés" - } - } -); - -IriSP.createAnnotationWidget = function(Popcorn, config, Serializer) { - IriSP.Widget.call(this, Popcorn, config, Serializer); - this._hidden = true; - - if (!IriSP.null_or_undefined(IriSP.user)) { - if (!IriSP.null_or_undefined(IriSP.user.avatar)) { - this.user_avatar = IriSP.user.avatar; - } - if (!IriSP.null_or_undefined(IriSP.user.name)) { - this.user_name = IriSP.user.name; - } - } - - /* variables to save the current position of the slicer */ - if (this.cinecast_version) { - this.sliceLeft = 0; - this.sliceWidth = 0; - } -}; - - -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 (typeof this.remote_tags == "object") { - IriSP.jQuery.getJSON((typeof this.remote_tags.alias == "string" ? this.remote_tags.alias : this.remote_tags.url), function(_json) { - _this.tags = _json.tags; - _this.drawCallback(); - }); - } else { - this.drawCallback(); - } -} - -IriSP.createAnnotationWidget.prototype.drawCallback = function() { - var _this = this; - - var annotationMarkup = IriSP.templToHTML(IriSP.createAnnotationWidget_template, - this); - - this.selector.append(annotationMarkup); - - if (!this.cinecast_version) - this.selector.hide(); - else { - this.showStartScreen(); - } - - if (this.random_tags) { - this.selector.find(".Ldt-createAnnotation-keywords li").hide(); - this.showMoreTags(); - this.selector.find('.Ldt-createAnnotation-moar-keywordz').click(function() { - _this.showMoreTags(); - }) - } - // Add onclick event to both polemic and keywords buttons - - this.selector.find(".Ldt-createAnnotation-keyword-button, .Ldt-createAnnotation-polemic-button").click(function() { - _this.addKeyword(IriSP.jQuery(this).text()); - return false; - }); - - // js_mod is a custom event because there's no simple way to test for a js - // change in a textfield. - this.selector.find(".Ldt-createAnnotation-Description") - .bind("propertychange keyup input paste click js_mod", IriSP.wrap(this, this.handleTextChanges)); - - /* the cinecast version of the player is supposed to pause when the user clicks on the button */ - - /* the cinecast version expects the user to comment on a defined segment. - As the widget is always shown, we need a way to update it's content as - time passes. We do this like we did with the annotationsWidget : we schedule - a .code start function which will be called at the right time. - */ - if (this.cinecast_version) { - var legal_ids; - if (typeof(this._serializer.getChapitrage()) !== "undefined") - legal_id = this._serializer.getChapitrage(); - else - legal_id = this._serializer.getNonTweetIds()[0]; - - var annotations = this._serializer._data.annotations; - var i; - - for (i in annotations) { - var annotation = annotations[i]; - if (typeof(annotation.meta) !== "undefined" && typeof(annotation.meta["id-ref"]) !== "undefined" - && legal_id !== annotation.meta["id-ref"]) { - continue; - } - - code = {start: annotation.begin / 1000, end: annotation.end / 1000, - onStart: function(annotation) { return function() { - if (typeof(annotation.content) !== "undefined") - _this.selector.find(".Ldt-createAnnotation-Title").html(annotation.content.title); - - _this._currentAnnotation = annotation; - var beginTime = IriSP.msToTime(annotation.begin); - var endTime = IriSP.msToTime(annotation.end); - var timeTemplate = IriSP.templToHTML("- ({{begin}} - {{ end }})", {begin: beginTime, end: endTime }); - _this.selector.find(".Ldt-createAnnotation-TimeFrame").html(timeTemplate); - } }(annotation) - }; - - this._Popcorn.code(code); - } - } - - this.selector.find(".Ldt-createAnnotation-submitButton").click(IriSP.wrap(this, this.handleButtonClick)); - - if (!this.cinecast_version) { - this._Popcorn.listen("IriSP.PlayerWidget.AnnotateButton.clicked", - IriSP.wrap(this, this.handleAnnotateSignal)); - - // handle clicks on the cancel button too. - this.selector.find(".Ldt-createAnnotation-Minimize").click(IriSP.wrap(this, - function() { - // we've got to simulate the pressing of the button because there's no - // other way to minimize the widget and show the widgets that were hidden - // same time - this._Popcorn.trigger("IriSP.PlayerWidget.AnnotateButton.clicked"); - } - )); - } -}; - -IriSP.createAnnotationWidget.prototype.showMoreTags = function() { - for (var j=0; j < this.random_tags; j++) { - var _jq = this.selector.find(".Ldt-createAnnotation-keywords li:hidden"); - if (_jq.length > 1) { - IriSP.jQuery(_jq[Math.floor(_jq.length*Math.random())]).show(); - } else { - _jq.show(); - break; - } - } - if (this.selector.find(".Ldt-createAnnotation-keywords li:hidden").length == 0) { - this.selector.find('.Ldt-createAnnotation-moar-keywordz').hide(); - } -} - -/* Handles adding keywords and polemics */ -IriSP.createAnnotationWidget.prototype.addKeyword = function(_keyword) { - var _field = this.selector.find(".Ldt-createAnnotation-Description"), - _rx = IriSP.regexpFromText(_keyword), - _contents = _field.val(); - _contents = ( _rx.test(_contents) - ? _contents.replace(_rx,"").replace(" "," ").trim() - : _contents.trim() + " " + _keyword - ); - _field.val(_contents.trim()).trigger("js_mod"); -} - -/** handles clicks on the annotate button. Works only for the non-cinecast version */ -IriSP.createAnnotationWidget.prototype.handleAnnotateSignal = function() { - - if (this._hidden == false && this._state == 'startScreen') { - this.selector.hide(); - this._hidden = true; - - // free the arrow. - this._Popcorn.trigger("IriSP.ArrowWidget.releaseArrow"); - this._Popcorn.trigger("IriSP.SliceWidget.hide"); - this._Popcorn.trigger("IriSP.AnnotationsWidget.show"); - - } else { - this._Popcorn.trigger("IriSP.AnnotationsWidget.hide"); - this.showStartScreen(); - this.selector.show(); - this._hidden = false; - var currentTime = this._Popcorn.currentTime(); - - // block the arrow. - this._Popcorn.trigger("IriSP.ArrowWidget.blockArrow"); - - var duration = this.getDuration(); - - var currentChapter = this._serializer.currentChapitre(currentTime); - - if (IriSP.null_or_undefined(currentChapter)) { - var left = this.selector.width() / 2; - var width = this.selector.width() / 10; - } else { - var left = (currentChapter.begin / duration) * this.selector.width(); - var width = (currentChapter.end / duration) * this.selector.width() - left; - } - - // slider position and length is kept in percents. - this.sliceLeft = (left / this.selector.width()) * 100; - this.sliceWidth = (width / this.selector.width()) * 100; - - this._Popcorn.trigger("IriSP.SliceWidget.position", [left, width]); - this._Popcorn.listen("IriSP.SliceWidget.zoneChange", IriSP.wrap(this, this.handleSliderChanges)); - this._Popcorn.trigger("IriSP.SliceWidget.show"); - - if (!IriSP.null_or_undefined(currentChapter)) { - this.selector.find(".Ldt-createAnnotation-Title").html(currentChapter.content.title); - - this._currentcurrentChapter = currentChapter; - var beginTime = IriSP.msToTime(currentChapter.begin); - var endTime = IriSP.msToTime(currentChapter.end); - var timeTemplate = IriSP.templToHTML("- ({{begin}} - {{ end }})", {begin: beginTime, end: endTime }); - this.selector.find(".Ldt-createAnnotation-TimeFrame").html(timeTemplate); - } - } -}; - - -/** 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(); - if (this.cinecast_version) { - this._Popcorn.pause(); - } - this.selector.find(".Ldt-createAnnotation-btnblock button").each(function() { - var _rx = IriSP.regexpFromText(IriSP.jQuery(this).text()); - if (_rx.test(contents)) { - IriSP.jQuery(this).parent().addClass("Ldt-createAnnotation-active-button"); - } else { - IriSP.jQuery(this).parent().removeClass("Ldt-createAnnotation-active-button"); - } - }); - -}; - -IriSP.createAnnotationWidget.prototype.showStartScreen = function() { - this.selector.find(".Ldt-createAnnotation-screen").hide(); - this.selector.find(".Ldt-createAnnotation-startScreen").show(); - - var jqTextfield = this.selector.find(".Ldt-createAnnotation-Description"); // handle on the textfield. used for the closure - - /* test if the browser supports the placeholder attribute */ - if (!IriSP.null_or_undefined(jqTextfield.get(0).placeholder)) { - jqTextfield.attr("placeholder", IriSP.i18n.getMessage('type_here')); - } else { - jqTextfield.val(IriSP.i18n.getMessage('type_here')); - jqTextfield.one("click", IriSP.wrap(this, function() { jqTextfield.val(""); })); - } - - - - this._state = "startScreen"; -}; - -IriSP.createAnnotationWidget.prototype.showWaitScreen = function() { - this.selector.find(".Ldt-createAnnotation-screen").hide(); - this.selector.find(".Ldt-createAnnotation-waitScreen").show(); - this._state = "waitScreen"; -}; - -IriSP.createAnnotationWidget.prototype.showErrorScreen = function() { - this.selector.find(".Ldt-createAnnotation-screen").hide(); - this.selector.find(".Ldt-createAnnotation-errorScreen").show(); - this._state = "errorScreen"; - var _this = this; - window.setTimeout(function() { _this.showStartScreen(); }, 2000); -}; - -/** update show the final screen with links to share the created annotation */ -IriSP.createAnnotationWidget.prototype.showEndScreen = function(annotation) { - this.selector.find(".Ldt-createAnnotation-screen").hide(); - - if (this.cinecast_version) { - this.selector.find(".Ldt-createAnnotation-Title").parent().show(); - } - - var url = ( (typeof annotation.meta == "object" && typeof annotation.meta.url == "string" && annotation.meta.url.length) - ? annotation.meta.url - : ( document.location.href + "#id=" + annotation.id ) ); - var twStatus = IriSP.mkTweetUrl(url); - var gpStatus = IriSP.mkGplusUrl(url); - var fbStatus = IriSP.mkFbUrl(url); - - 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(); - this._state = "endScreen"; -}; - -/** 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(); - } - - textfield.one("js_mod propertychange keyup input paste", IriSP.wrap(this, function() { - var contents = textfield.val(); - - if (contents !== "") { - this.selector.find(".Ldt-createAnnotation-errorMessage").hide(); - textfield.css("background-color", ""); - } - })); - } else { - this.showWaitScreen(); - - this.sendLdtData(contents, function(annotation) { - if (_this.cinecast_version) { - if (_this._Popcorn.media.paused) - _this._Popcorn.play(); - } - - if (_this._state == "waitScreen") { - _this.showEndScreen(annotation); - if (_this.cinecast_version) { - window.setTimeout(function() { _this.showStartScreen(); }, 5000); - } - } - // hide the slicer widget - if (!_this.cinecast_version) { - _this._Popcorn.trigger("IriSP.SliceWidget.hide"); - } - }); - } -}; - -IriSP.createAnnotationWidget.prototype.handleSliderChanges = function(params) { - this.sliceLeft = params[0]; - this.sliceWidth = params[1]; -}; - -IriSP.createAnnotationWidget.prototype.sendLdtData = function(contents, callback) { - var _this = this; - var apiJson = { - format : "http://advene.org/ns/cinelab/", - annotations : [ - {} - ], - meta: {}}; - var annotation = apiJson.annotations[0]; - - annotation.media = this.currentMedia()["id"]; - - if (this.cinecast_version) { - annotation.begin = Math.round(this._Popcorn.currentTime() * 1000); - annotation.end = annotation.begin; - } else { - var duration = this.getDuration(); - annotation.begin = +((duration * (this.sliceLeft / 100)).toFixed(0)); - annotation.end = +((duration * ((this.sliceWidth + this.sliceLeft) / 100)).toFixed(0)); - } - - // boundary checks - annotation.begin = Math.max(0, annotation.begin); - annotation.end = Math.min(this.getDuration(), annotation.end); - - annotation.type = ( this.cinecast_version ? "cinecast:UserAnnotation" : ( this._serializer.getContributions() || "" )); - if (typeof(annotation.type) === "undefined") - annotation.type = ""; - - annotation.type_title = "Contributions"; - annotation.content = {}; - annotation.content.data = contents; - if (this.cinecast_version) { - var _extract = IriSP.underscore(this._serializer._data.annotations) - .filter(function(_a) { - return (_a.begin <= annotation.begin && _a.end >= annotation.begin && _a.type == "cinecast:MovieExtract"); - }) - if (_extract.length) { - annotation.extract = _extract[0].id; - } - } - - var meta = apiJson.meta; - - - var _username = this.selector.find(".Ldt-createAnnotation-userName").val(); - meta.creator = ( - (_username && _username.length) - ? _username - : ( - (!IriSP.null_or_undefined(IriSP.user) && !IriSP.null_or_undefined(IriSP.user.name)) - ? IriSP.user.name - : "Anonymous user" - ) - ); - - meta.created = Date().toString(); - - var _tags = []; - IriSP._(this.tags).each(function(_v) { - var _rx = IriSP.regexpFromText(_v.meta.description); - if (_rx.test(contents)) { - _tags.push(_v.id); - } - }); - - if (typeof this.remote_tags == "object") { - _tags = IriSP._(_tags).map(function(_t) { - return _this.remote_tags.id + ':' + _t - }); - if (typeof apiJson.imports == "undefined") { - apiJson.imports = []; - } - apiJson.imports.push({ - "id" : this.remote_tags.id, - "url" : this.remote_tags.url - }) - } - annotation.tags = IriSP.underscore.uniq(_tags); - - var jsonString = JSON.stringify(apiJson); - var project_id = this._serializer._data.meta.id; - - //TODO: extract magic url - var url = Mustache.to_html(this.api_endpoint_template, - {id: project_id}); - - IriSP.jQuery.ajax({ - url: url, - type: this.api_method, - contentType: 'application/json', - data: jsonString, - //dataType: 'json', - success: IriSP.wrap(this, function(json, textStatus, XMLHttpRequest) { - /* add the annotation to the annotation and tell the world */ - var annotation = json.annotations[0]; - - if (!this.cinecast_version) { - /* if the media doesn't have a contributions line, we need to add one */ - if (typeof(this._serializer.getContributions()) === "undefined") { - /* set up a basic view */ - var tmp_view = {"dc:contributor": "perso", "dc:creator": "perso", "dc:title": "Contributions", - "id": json.annotations[0].type} - - - IriSP.get_aliased(this._serializer._data, ["annotation_types", "annotation-types"]).push(tmp_view); - } - - delete annotation.tags; - annotation.content.description = annotation.content.data; - annotation.content.title = ""; - delete annotation.content.data; - annotation.id = json.annotations[0].id; - - annotation.meta = meta; - annotation.meta["id-ref"] = json.annotations[0]["type"]; - } else { - annotation.type = "cinecast:UserAnnotation"; - } - // everything is shared so there's no need to propagate the change - var _an_ids = IriSP.underscore(this._serializer._data.annotations).map(function(_a) { - return _a.id.toLowerCase(); - }); - if (_an_ids.indexOf(annotation.id.toLowerCase()) == -1) { - _this._serializer._data.annotations.push(annotation); - } - - _this._Popcorn.trigger("IriSP.createAnnotationWidget.addedAnnotation", annotation); - this.selector.find(".Ldt-createAnnotation-Description").val("").trigger("js_mod"); - callback(annotation); - }), - error: - function(jqXHR, textStatus, errorThrown) { - console.log("an error occured while contacting " - + url + " and sending " + jsonString + textStatus ); - _this.showErrorScreen(); } }); -};IriSP.HelloWorldWidget = function(Popcorn, config, Serializer) { - IriSP.Widget.call(this, Popcorn, config, Serializer); -} - -IriSP.HelloWorldWidget.prototype = new IriSP.Widget(); - -IriSP.HelloWorldWidget.prototype.draw = function() { - this.selector - .html('Hello, world') - .css({ - "text-align" : "center", - "padding": "10px 0", - "font-size" : "14px" - }); - - console.log(this); -} -/* Internationalization for this widget */ - -IriSP.i18n.addMessages( - { - "en": { - "play_pause": "Play/Pause", - "mute_unmute": "Mute/Unmute", - "play": "Play", - "pause": "Pause", - "mute": "Mute", - "unmute": "Unmute", - "annotate": "Annotate", - "search": "Search", - "elapsed_time": "Elapsed time", - "total_time": "Total time", - "volume": "Volume", - "volume_control": "Volume control" - }, - "fr": { - "play_pause": "Lecture/Pause", - "mute_unmute": "Couper/Activer le son", - "play": "Lecture", - "pause": "Pause", - "mute": "Couper le son", - "unmute": "Activer le son", - "annotate": "Annoter", - "search": "Rechercher", - "elapsed_time": "Durée écoulée", - "total_time": "Durée totale", - "volume": "Niveau sonore", - "volume_control": "Réglage du niveau sonore" - } - } -); - - -IriSP.PlayerWidget = function(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, this._config); - 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.volumeUpdater)); - - 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._Popcorn.listen("IriSP.search.triggeredSearch", IriSP.wrap(this, this.triggeredSearch)); - - - 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); }); - - var _volctrl = this.selector.find(".Ldt-Ctrl-Volume-Control"); - this.selector.find('.Ldt-CtrlSound') - .click(function() { self.muteHandler.call(self); } ) - .mouseover(function() { - _volctrl.show(); - }) - .mouseout(function() { - _volctrl.hide(); - }); - _volctrl.mouseover(function() { - _volctrl.show(); - }).mouseout(function() { - _volctrl.hide(); - }); - - /* - 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.selector.find(".Ldt-Ctrl-Volume-Cursor").draggable({ - axis: "x", - drag: function(event, ui) { - var _vol = Math.max(0, Math.min( 1, ui.position.left / (ui.helper.parent().width() - ui.helper.outerWidth()))); - ui.helper.attr("title",IriSP.i18n.getMessage('volume')+': ' + Math.floor(100*_vol) + '%'); - self._Popcorn.volume(_vol); - }, - containment: "parent" - }); - - setTimeout(function() { - self.volumeUpdater(); - }, 1000); /* 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.getDuration() / 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 ){ - /* the background sprite is changed by adding/removing the correct classes */ - this.selector.find(".Ldt-CtrlPlay").attr("title", IriSP.i18n.getMessage('play')); - this.selector.find(".Ldt-CtrlPlay").removeClass("Ldt-CtrlPlay-PauseState").addClass("Ldt-CtrlPlay-PlayState"); - } else { - this.selector.find(".Ldt-CtrlPlay").attr("title", IriSP.i18n.getMessage('pause')); - this.selector.find(".Ldt-CtrlPlay").removeClass("Ldt-CtrlPlay-PlayState").addClass("Ldt-CtrlPlay-PauseState"); - } - - 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() { - this._Popcorn.mute(!this._Popcorn.muted()); -}; - -IriSP.PlayerWidget.prototype.volumeUpdater = function() { - var _muted = this._Popcorn.muted(), - _vol = this._Popcorn.volume(); - if (_vol === false) { - _vol = .5; - } - var _soundCtl = this.selector.find(".Ldt-CtrlSound"); - _soundCtl.removeClass("Ldt-CtrlSound-Mute Ldt-CtrlSound-Half Ldt-CtrlSound-Full"); - if (_muted) { - _soundCtl.attr("title", IriSP.i18n.getMessage('unmute')) - .addClass("Ldt-CtrlSound-Mute"); - } else { - _soundCtl.attr("title", IriSP.i18n.getMessage('mute')) - .addClass(_vol < .5 ? "Ldt-CtrlSound-Half" : "Ldt-CtrlSound-Full" ) - } - var _cursor = this.selector.find(".Ldt-Ctrl-Volume-Cursor"); - _cursor.css({ - "left": ( _muted ? 0 : Math.floor(_vol * (_cursor.parent().width() - _cursor.outerWidth())) ) + "px" - }) -}; - -IriSP.PlayerWidget.prototype.showSearchBlock = function() { - var self = this; - - if (this._searchBlockOpen == false) { - this.selector.find(".LdtSearch").show("blind", { direction: "horizontal"}, 100); - this.selector.find(".LdtSearchInput").css('background-color','#fff'); - - this._searchBlockOpen = true; - this.selector.find(".LdtSearchInput").bind('keyup', null, function() { self.searchHandler.call(self); } ); - this.selector.find(".LdtSearchInput").focus(); - - // we need this variable because some widget can find a match in - // their data while at the same time other's don't. As we want the - // search field to become green when there's a match, we need a - // variable to remember that we had one. - this._positiveMatch = false; - - // tell the world the field is open - this._Popcorn.trigger("IriSP.search.open"); - } -}; - -IriSP.PlayerWidget.prototype.hideSearchBlock = function() { - if (this._searchBlockOpen == true) { - this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value'); - this.selector.find(".LdtSearchInput").attr('value',''); - this.selector.find(".LdtSearch").hide("blind", { direction: "horizontal"}, 75); - - // unbind the watcher event. - this.selector.find(".LdtSearchInput").unbind('keypress set'); - this._searchBlockOpen = false; - - this._positiveMatch = false; - - this._Popcorn.trigger("IriSP.search.closed"); - } -}; - -/** react to clicks on the search button */ -IriSP.PlayerWidget.prototype.searchButtonHandler = function() { - var self = this; - - /* show the search field if it is not shown */ - if ( this._searchBlockOpen == false ) { - this.showSearchBlock(); - this.selector.find(".LdtSearchInput").attr('value', this._searchLastValue); - this._Popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural. - } else { - this.hideSearchBlock(); - } -}; - -/** 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"); -}; - -/** react to an IriSP.Player.triggeredSearch - that is, when - a widget ask the PlayerWidget to do a search on his behalf */ -IriSP.PlayerWidget.prototype.triggeredSearch = function(searchString) { - this.showSearchBlock(); - this.selector.find(".LdtSearchInput").attr('value', searchString); - this._Popcorn.trigger("IriSP.search", searchString); // trigger the search to make it more natural. -}; - - -/* - * - * 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 = []; -}; - -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.getDuration(); // timescale width - var frameLength = lineSize / frameSize; // frame timescale - var timeline; - var colors = new Array("","#1D973D","#036AAE","#CE0A15","#C5A62D","#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); return; }); - - 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. - var view = json.views[0]; - - if(typeof(view.annotation_types) !== "undefined") { - /* we need to be backward compatible with the old files which used to - feature only two lines : Chapitrage and Tweets. We've added a - "Contributions" line so we need to discriminate against that */ - if (view.annotation_types.length === 2 && typeof(this._serializer.getContributions()) === "undefined") { - var view_type = view.annotation_types[1]; - } else { - console.log("PolemicWidget: invalid file - minimizing"); - return; - } - } - } - } - - // Make and define the Raphael area - this.paper = Raphael(document.getElementById(this._id), this._config.width, this._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)); - this.selector.mouseleave(IriSP.wrap(this, function() { self.TooltipWidget.hide.call(self.TooltipWidget); })); - this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater)); - this._Popcorn.listen("IriSP.Mediafragment.showAnnotation", IriSP.wrap(this, this.showAnnotation)); - - 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 = {}, - _source = IriSP.get_aliased(item.meta, ['dc:source', 'source']); - if (_source !== null) { - var MyTJson = JSON.parse(_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 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; - - /* stick a lot of things into e because that's the easiest way - to do it */ - 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 (_e) { - self.TooltipWidget.show.call(self.TooltipWidget, element.title, element.attr("fill"), element.attrs.x + element.attrs.width / 2, element.attrs.y - 2); - element.displayed = true; - self._Popcorn.trigger("IriSP.TraceWidget.MouseEvents", { - "widget" : "StackGraphWidget", - "type": "mousemove", - "x": _e.pageX, - "y": _e.pageY, - "annotation_id": element.id - }); - }}(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(); - } - - -} - -/** update the positionMarker as time passes */ -IriSP.PolemicWidget.prototype.sliderUpdater = function() { - - var time = +this._Popcorn.currentTime(); - var duration = this.getDuration(); - - 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.PolemicWidget.prototype.showAnnotation = function(id) { - if (this.svgElements.hasOwnProperty(id)) { - var e = this.svgElements[id]; - this.TooltipWidget.show(e.title, e.attr("fill"), e.x - 103, e.y - 160); - } -}; -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); }); - - this.defaultColors = ["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"] -}; - -IriSP.SegmentsWidget.prototype = new IriSP.Widget(); - -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)); - - this.positionMarker = this.selector.find(".Ldt-SegmentPositionMarker"); - - this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.positionUpdater)); - var duration = this.getDuration(); - - if (this.cinecast_version) { - var segments_annotations = IriSP.underscore.filter( - this._serializer._data.annotations, - function(_a) { - return _a.type == "cinecast:MovieExtract"; - } - ); - } - else { - - var view_type = this._serializer.getChapitrage(); - if (typeof(view_type) === "undefined") { - view_type = this._serializer.getNonTweetIds()[0]; - } - - - 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 _w = this.selector.width(); - 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 id = annotation.id; - - var startPixel = Math.floor(_w * (begin / duration)); - - var endPixel = Math.floor(_w * (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 = this.cinecast_version - ? annotation.content.data - : annotation.content.title + ( annotation.content.title ? "
" : "" ) + annotation.content.description.replace(/(^.{120,140})[\s].+$/,'$1…'); - - var thumbUrl = annotation.meta.thumbnail || ''; - - var hexa_color = typeof(annotation.content.color) !== "undefined" - ? '#' + IriSP.DEC_HEXA_COLOR(annotation.content.color) - : typeof(annotation.color) !== "undefined" - ? '#' + IriSP.DEC_HEXA_COLOR(annotation.color) - : this.defaultColors[i % this.defaultColors.length]; - - /* - if (hexa_color === "FFCC00") - hexa_color = "333"; - */ - if (hexa_color.length == 5) - 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), "thumbnailUrl": thumbUrl}); - - - this.selector.append(annotationTemplate); - - /* add a special class to the last segment and change its border */ - if (annotation.id === lastSegment.id) { - IriSP.jqId(id).addClass("Ldt-lastSegment").css("border-color", hexa_color); - } - } - // react to mediafragment messages. - this._Popcorn.listen("IriSP.Mediafragment.showAnnotation", - function(id, divTitle) { - - var divObject = IriSP.jqId(id); - if (divObject.length) { - divObject.fadeTo(0,1); - var offset_x = divObject.position().left + divObject.outerWidth() / 2; - self.TooltipWidget.show(divObject.attr("title"), IriSP.jQuery(this).css("background-color"), offset_x, 0); - IriSP.jQuery(document).one("mousemove", function() { divObject.fadeTo(0,.5); - self.TooltipWidget.hide(); }); - } - }); - - this.selector.find(".Ldt-iri-chapter") - .fadeTo(0, .5) - .click(function() { - self._Popcorn.trigger("IriSP.SegmentsWidget.click", this.id); - self._Popcorn.currentTime(IriSP.jQuery(this).attr("data-seek")); - }) - .mouseover( function(event) { - var divObject = IriSP.jQuery(this); - divObject.fadeTo(0,1); - var offset_x = divObject.position().left + divObject.outerWidth() / 2; - var thumb = divObject.attr("thumbnail-url"); - var txt = divObject.attr("title") + (thumb && thumb.length ? '
' : ''); - self.TooltipWidget.show(txt, IriSP.jQuery(this).css("background-color"), offset_x, 0); - }) - .mouseout(function(){ - IriSP.jQuery(this).fadeTo(0,.5); - self.TooltipWidget.hide(); - }); -}; - -/* restores the view after a search */ -IriSP.SegmentsWidget.prototype.clear = function() { - this.selector.children(".Ldt-iri-chapter").fadeTo(0,.5); -}; - -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.getDuration() / 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 + "%"); -}; - -IriSP.SegmentsWidget.prototype.showAnnotation = function() { - -}; -/** 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"); - - var left = this.selector.offset().left; - var top = this.selector.offset().top; - - // a bug in firefox makes it use the wrong format - if (!IriSP.jQuery.browser.mozilla) { - // contain the handles correctly - we cannot set - // containment: parent because it wouldn't allow to select the - // whole slice, so we have to compute a box in which the slice is - // allowed to move. - var containment = [left - 8, top, this.selector.width() + left, top]; - - // var containment = [left - 16, top, this.selector.width() + left - 8, top]; - this.leftHandle.draggable({axis: "x", - drag: IriSP.wrap(this, this.leftHandleDragged), - containment: containment - }); - - containment = [left, top, this.selector.width() + left, top]; - // containment = [left, top, this.selector.width() + left - 8, top]; - this.rightHandle.draggable({axis: "x", - drag: IriSP.wrap(this, this.rightHandleDragged), - containment: containment - }); - - } else { // firefox - // we need to define a containment specific to firefox. - - var containment = [left - 16, top, this.selector.width() + left - 8, top]; - this.leftHandle.draggable({axis: "x", - drag: IriSP.wrap(this, this.leftHandleDragged), - containment: containment - }); - - containment = [left, top, this.selector.width() + left - 8, top]; - this.rightHandle.draggable({axis: "x", - drag: IriSP.wrap(this, this.rightHandleDragged), - containment: containment - }); - } - - this.leftHandle.css("position", "absolute"); - this.rightHandle.css("position", "absolute"); - - this._Popcorn.listen("IriSP.SliceWidget.position", - IriSP.wrap(this, this.positionSliceHandler)); - - this._Popcorn.listen("IriSP.SliceWidget.show", IriSP.wrap(this, this.show)); - this._Popcorn.listen("IriSP.SliceWidget.hide", IriSP.wrap(this, this.hide)); - this.selector.hide(); -}; - -/** responds to an "IriSP.SliceWidget.position" message - @param params an array with the first element being the left distance in - percents and the second element the width of the slice in pixels -*/ -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.offset().left; - var rightHandleX = Math.floor(this.rightHandle.position()["left"]); - - var container_offset = this.selector.offset().left; - - if (Math.floor(ui.position.left) >= rightHandleX - 7) { - /* prevent the handle from moving past the right handle */ - ui.position.left = rightHandleX - 7; - } - - this.zoneWidth = rightHandleX - Math.floor(ui.position.left) - 7; - this.zoneLeft = Math.floor(ui.position.left) + 8; - - this.sliceZone.css("width", this.zoneWidth); - this.sliceZone.css("left", this.zoneLeft + "px"); - - this._leftHandleOldLeft = ui.position.left; - this.broadcastChanges(); - -}; - -/** handle a dragging of the right handle */ -IriSP.SliceWidget.prototype.rightHandleDragged = 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 leftHandleX = Math.floor(this.leftHandle.position()["left"]); - - var container_offset = this.selector.offset().left + this.selector.width(); - - if (Math.floor(ui.position.left) < leftHandleX + 7) { - /* prevent the handle from moving past the left handle */ - ui.position.left = leftHandleX + 7; - } - - this.zoneWidth = Math.floor(ui.position.left) - (leftHandleX + 7); - - this.sliceZone.css("width", this.zoneWidth); - //this.sliceZone.css("left", this.zoneLeft + "px"); - this._rightHandleOldLeft = Math.floor(this._rightHandleOldLeft); - this.broadcastChanges(); -}; - -/** 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.SliceWidget.prototype.show = function() { - this.selector.show(); -}; - -IriSP.SliceWidget.prototype.hide = function() { - this.selector.hide(); -};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.getDuration() / 1000; - var percents = time / duration; - - /* we do these complicated calculations to center exactly - the position Marker */ - - var divWidth = this.selector.width(); - var pixels = Math.floor(this.selector.width() * percents); - var positionMarker_width = this.positionMarker.width(); - var correction = (positionMarker_width / 2); - - /* check that we don't leave the left side */ - var newPos = pixels - correction; - if (newPos <= 0) - newPos = 0; - - /* check that we don't leave the right side */ - var rightEdgePos = pixels + 1 * correction; - - if (rightEdgePos >= divWidth) - newPos = divWidth - 1 * correction - 1; - - this.sliderForeground.css("width", pixels + "px"); - this.positionMarker.css("left", newPos + "px"); - -}; - -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.getDuration() / 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.getDuration() / 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), - this.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.originalEvent.pageX - parentOffset.left; - - var duration = this.getDuration() / 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; - this._results = []; - - this.slices = this._config.slices || Math.floor(this.width/20); - if (!this.width) { - this.width = this.selector.width(); - } - if (!this.height) { - this.height = 40; - } - this.selector.css("height", this.height + "px"); - if (this._config.background) { - this.selector.css("background", this._config.background); - } -}; - - -IriSP.SparklineWidget.prototype = new IriSP.Widget(); - -IriSP.SparklineWidget.prototype.clear = function() { - -}; - -/** draw the sparkline using jquery sparkline */ -IriSP.SparklineWidget.prototype.draw = function() { - this.duration = this.getDuration(); - this.paper = new Raphael(this.selector[0], this.width, this.height); - var _this = this; - - var views = this._serializer._data.views; - var stat_view; - if (!IriSP.null_or_undefined(views)) { - for (var i = 0; i < views.length; i++) { - var view = views[i]; - if (view.id === "stat") { - stat_view = view; - break; - } - } - } - - var _ = IriSP.underscore; - // If we've found the correct view, feed the directly the data from the view - // to jquery sparkline. Otherwise, compute it ourselves. - if (!IriSP.null_or_undefined(stat_view)) { - //console.log("sparklinewidget : using stats embedded in the json"); - var _results = stat_view.meta.stat.split(","); - } else { - var _annotations = this._serializer._data.annotations; - if (this.cinecast_version) { - _annotations = _(_annotations).filter(function(_a) { - return _a.type !== "cinecast:MovieExtract"; - }); - } - var _sliceDuration = Math.floor( this.duration / this.slices), - _results = _(_.range(this.slices)).map(function(_i) { - return _(_annotations).filter(function(_a){ - return (_a.begin <= (1 + _i) * _sliceDuration) && (_a.end >= _i * _sliceDuration) - }).length; - }); - } - var _max = Math.max(1, _(_results).max()), - _h = this.height, - _scale = (_h - this.lineWidth) / _max, - _width = this.width / this.slices, - _y = _(_results).map(function(_v) { - return _h - (_scale * _v); - }), - _d = _(_y).reduce(function(_memo, _v, _k) { - return _memo + ( _k - ? 'C' + (_k * _width) + ' ' + _y[_k - 1] + ' ' + (_k * _width) + ' ' + _v + ' ' + ((_k + .5) * _width) + ' ' + _v - : 'M0 ' + _v + 'L' + (.5*_width) + ' ' + _v ) - },'') + 'L' + this.width + ' ' + _y[_y.length - 1], - _d2 = _d + 'L' + this.width + ' ' + this.height + 'L0 ' + this.height; - this.paper.path(_d2).attr({ - "stroke" : "none", - "fill" : this.fillColor - }); - - this.paper.path(_d).attr({ - "fill" : "none", - "stroke" : this.lineColor, - "stroke-width" : this.lineWidth - }); - - this.rectangleProgress = this.paper.rect(0,0,0,this.height) - .attr({ - "stroke" : "none", - "fill" : "#808080", - "opacity" : .3 - }); - this.ligneProgress = this.paper.path("M0 0L0 "+this.height).attr({"stroke":"#ff00ff", "line-width" : 2}); - // save the results in an array so that we can re-use them when a new annotation - // is added. - this._results = _results; - - this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeUpdateHandler)); -// this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation", IriSP.wrap(this, this.handleNewAnnotation)); - - this.selector.click(IriSP.wrap(this, this.clickHandler)); -}; - -/** react to a timeupdate event */ -IriSP.SparklineWidget.prototype.timeUpdateHandler = function() { - var _currentTime = this._Popcorn.currentTime(), - _x = (1000 * _currentTime / this.duration) * this.width; - this.rectangleProgress.attr({ - "width" : _x - }); - this.ligneProgress.attr({ - "path" : "M" + _x + " 0L" + _x + " " + this.height - }); - -} - -/** handle clicks on the widget */ -IriSP.SparklineWidget.prototype.clickHandler = function(event) { - var relX = event.pageX - this.selector.offset().left; - var newTime = ((relX / this.width) * this.duration/1000).toFixed(2); - - this._Popcorn.trigger("IriSP.SparklineWidget.clicked", newTime); - this._Popcorn.currentTime(newTime); -}; - -/** react when a new annotation is added */ -IriSP.SparklineWidget.prototype.handleNewAnnotation = function(annotation) { -// var num_columns = this._results.length; -// var duration = this._serializer.getDuration(); -// var time_step = Math.round(duration / num_columns); /* the time interval between two columns */ -// var begin = +annotation.begin; -// var end = +annotation.end; -// -// /* increment all the values between the beginning and the end of the annotation */ -// var index_begin = Math.floor(begin / time_step); -// var index_end = Math.floor(end / time_step); -// -// for (var i = index_begin; i < Math.min(index_end, this._results.length); i++) { -// this._results[i]++; -// } -// -// this.selector.find(".Ldt-sparkLine").sparkline(this._results, {lineColor: "#7492b4", fillColor: "#aeaeb8", -// spotColor: "#b70056", -// width: this.width, height: this.height}); -};IriSP.StackGraphWidget = function(Popcorn, config, Serializer) { - IriSP.Widget.call(this, Popcorn, config, Serializer); -} - -IriSP.StackGraphWidget.prototype = new IriSP.Widget(); - -IriSP.StackGraphWidget.prototype.draw = function() { - var _ = IriSP._; - this.height = this._config.height || 50; - this.width = this.selector.width(); - this.slices = this._config.slices || ~~(this.width/(this.streamgraph ? 20 : 5)); - _(this.tags).each(function(_a) { - _a.regexp = new RegExp(_(_a.keywords).map(function(_k) { - return _k.replace(/([\W])/gm,'\\$1'); - }).join("|"),"im") - }); - this.paper = new Raphael(this.selector[0], this.width, this.height); - this.groups = []; - this.duration = this.getDuration(); - - var _annotationType = this._serializer.getTweets(), - _sliceDuration = ~~ ( this.duration / this.slices), - _annotations = this._serializer._data.annotations, - _groupedAnnotations = _(_.range(this.slices)).map(function(_i) { - return _(_annotations).filter(function(_a){ - return (_a.begin <= (1 + _i) * _sliceDuration) && (_a.end >= _i * _sliceDuration) - }); - }), - _max = IriSP._(_groupedAnnotations).max(function(_g) { - return _g.length - }).length, - _scale = this.height / _max, - _width = this.width / this.slices, - _showTitle = !this._config.excludeTitle, - _showDescription = !this._config.excludeDescription; - - - var _paths = _(this.tags).map(function() { - return []; - }); - _paths.push([]); - - for (var i = 0; i < this.slices; i++) { - var _group = _groupedAnnotations[i]; - if (_group) { - var _vol = _(this.tags).map(function() { - return 0; - }); - for (var j = 0; j < _group.length; j++){ - var _txt = (_showTitle ? _group[j].content.title : '') + ' ' + (_showDescription ? _group[j].content.description : '') - var _tags = _(this.tags).map(function(_tag) { - return (_txt.search(_tag.regexp) == -1 ? 0 : 1) - }), - _nbtags = _(_tags).reduce(function(_a,_b) { - return _a + _b; - }, 0); - if (_nbtags) { - IriSP._(_tags).each(function(_v, _k) { - _vol[_k] += (_v / _nbtags); - }); - } - } - var _nbtags = _(_vol).reduce(function(_a,_b) { - return _a + _b; - }, 0), - _nbneutre = _group.length - _nbtags, - _h = _nbneutre * _scale, - _base = this.height - _h; - if (!this.streamgraph) { - this.paper.rect(i * _width, _base, _width - 1, _h ).attr({ - "stroke" : "none", - "fill" : this.defaultcolor - }); - } - _paths[0].push(_base); - for (var j = 0; j < this.tags.length; j++) { - _h = _vol[j] * _scale; - _base = _base - _h; - if (!this.streamgraph) { - this.paper.rect(i * _width, _base, _width - 1, _h ).attr({ - "stroke" : "none", - "fill" : this.tags[j].color - }); - } - _paths[j+1].push(_base); - } - this.groups.push(_(_vol).map(function(_v) { - return _v / _group.length; - })) - } else { - for (var j = 0; j < _paths.length; j++) { - _paths[j].push(this.height); - } - this.groups.push(_(this.tags).map(function() { - return 0; - })); - } - } - - if (this.streamgraph) { - for (var j = _paths.length - 1; j >= 0; j--) { - var _d = _(_paths[j]).reduce(function(_memo, _v, _k) { - return _memo + ( _k - ? 'C' + (_k * _width) + ' ' + _paths[j][_k - 1] + ' ' + (_k * _width) + ' ' + _v + ' ' + ((_k + .5) * _width) + ' ' + _v - : 'M0 ' + _v + 'L' + (.5*_width) + ' ' + _v ) - },'') + 'L' + this.width + ' ' + _paths[j][_paths[j].length - 1] + 'L' + this.width + ' ' + this.height + 'L0 ' + this.height; - this.paper.path(_d).attr({ - "stroke" : "none", - "fill" : (j ? this.tags[j-1].color : this.defaultcolor) - }); - } - } - this.rectangleFocus = this.paper.rect(0,0,_width,this.height) - .attr({ - "stroke" : "none", - "fill" : "#ff00ff", - "opacity" : 0 - }) - this.rectangleProgress = this.paper.rect(0,0,0,this.height) - .attr({ - "stroke" : "none", - "fill" : "#808080", - "opacity" : .3 - }); - this.ligneProgress = this.paper.path("M0 0L0 "+this.height).attr({"stroke":"#ff00ff", "line-width" : 2}) - - this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeUpdateHandler)); - var _this = this; - this.selector - .click(IriSP.wrap(this, this.clickHandler)) - .mousemove(function(_e) { - _this.updateTooltip(_e); - // Trace - var relX = _e.pageX - _this.selector.offset().left; - var _duration = _this.getDuration(); - var _time = parseInt((relX / _this.width) * _duration); - _this._Popcorn.trigger("IriSP.TraceWidget.MouseEvents", { - "widget" : "StackGraphWidget", - "type": "mousemove", - "x": _e.pageX, - "y": _e.pageY, - "time": _time - }); - - }) - .mouseout(function() { - _this.TooltipWidget.hide(); - _this.rectangleFocus.attr({ - "opacity" : 0 - }) - }) -} - -IriSP.StackGraphWidget.prototype.timeUpdateHandler = function() { - var _currentTime = this._Popcorn.currentTime(), - _x = (1000 * _currentTime / this.duration) * this.width; - this.rectangleProgress.attr({ - "width" : _x - }); - this.ligneProgress.attr({ - "path" : "M" + _x + " 0L" + _x + " " + this.height - }) -} - -IriSP.StackGraphWidget.prototype.clickHandler = function(event) { - /* Ctrl-C Ctrl-V'ed from another widget - */ - - var relX = event.pageX - this.selector.offset().left; - var newTime = ((relX / this.width) * this.duration/1000).toFixed(2); - this._Popcorn.trigger("IriSP.StackGraphWidget.clicked", newTime); - this._Popcorn.currentTime(newTime); -}; - -IriSP.StackGraphWidget.prototype.updateTooltip = function(event) { - var _segment = Math.max(0,Math.min(this.groups.length - 1, Math.floor(this.slices * (event.pageX - this.selector.offset().left)/this.width))), - _valeurs = this.groups[_segment], - _width = this.width / this.slices, - _html = '
    ' + IriSP._(this.tags).map(function(_tag, _i) { - return '
  • ' - + ~~(100 * _valeurs[_i]) - + '% de ' - + _tag.description - + '
  • '; - }).join('') + '
'; - this.TooltipWidget._shown = false; // Vraiment, on ne peut pas ouvrir le widget s'il n'est pas encore ouvert ? - this.TooltipWidget.show('','',(_segment + .5)* this.width / this.slices, 0); - this.TooltipWidget.selector.find(".tip").html(_html); - this.rectangleFocus.attr({ - "x" : _segment * _width, - "opacity" : .4 - }) -} - -IriSP.TagCloudWidget = function(Popcorn, config, Serializer) { - IriSP.Widget.call(this, Popcorn, config, Serializer); -} - -IriSP.TagCloudWidget.prototype = new IriSP.Widget(); - -IriSP.TagCloudWidget.prototype.draw = function() { - - var _urlRegExp = /https?:\/\/[0-9a-zA-Z\.%\/-_]+/g, - _stopWords = [ - 'aussi', 'and', 'avec', 'aux', 'bien', 'car', 'cette', 'comme', 'dans', 'donc', 'des', 'elle', 'encore', 'entre', 'est', - 'être', 'eux', 'faire', 'fait', 'http', 'ici', 'ils', 'les', 'leur', 'leurs', 'mais', 'mes', 'même', 'mon', 'notre', - 'non', 'nos', 'nous', 'ont', 'par', 'pas', 'peu', 'peut', 'plus', 'pour', 'que', 'qui', 'sans', 'ses' ,'son', 'sont', 'sur', - 'tes', 'très', 'the', 'ton', 'tous', 'tout', 'une', 'votre', 'vos', 'vous' ], - _regexpword = /[^\s\.&;,'"!\?\d\(\)\+\[\]\\\…\-«»:\/]{3,}/g, - _words = {}, - _showTitle = !this._config.excludeTitle, - _showDescription = !this._config.excludeDescription, - _excludePattern = this._config.excludePattern || null, - _tagCount = this._config.tagCount || 30; - if (typeof this._config.excludeWords !== "undefined" && this._config.excludeWords.length) { - IriSP._(this._config.excludeWords).each(function(_w) { - _stopWords.push(_w.toLowerCase()); - }); - } - - IriSP._(this._serializer._data.annotations).each(function(_annotation) { - if (_annotation.content && _annotation.content.description) { - var _txt = (_showTitle ? _annotation.content.title : '') + ' ' + (_showDescription ? _annotation.content.description : '') - IriSP._(_txt.toLowerCase().replace(_urlRegExp, '').match(_regexpword)).each(function(_mot) { - if (_stopWords.indexOf(_mot) == -1 && (_excludePattern == null || !_excludePattern.test(_mot))) { - _words[_mot] = 1 + (_words[_mot] || 0); - } - }) - } - }); - - _words = IriSP._(_words) - .chain() - .map(function(_v, _k) { - return { - "word" : _k, - "count" : _v - } - }) - .filter(function(_v) { - return _v.count > 2; - }) - .sortBy(function(_v) { - return - _v.count; - }) - .first(_tagCount) - .value(); - var _max = _words[0].count, - _min = Math.min(_words[_words.length - 1].count, _max - 1), - _scale = 16 / Math.sqrt(_max - _min), - _this = this, - _html = '
    ' - + IriSP._(_words) - .chain() - .shuffle() - .map(function(_word) { - var _size = 10 + _scale * Math.sqrt(_word.count - _min); - return '
  • ' - + _word.word - + '
  • ' - }) - .value() - .join("") - + '
'; - this.selector - .addClass("Ldt-TagCloud") - .html(_html); - this.selector.find("li").click(function() { - var _txt = this.textContent.replace(/(^[\s]+|[\s]+$)/g,''); - _this._Popcorn.trigger("IriSP.search.triggeredSearch", _txt); - }); - this._Popcorn.listen("IriSP.search", IriSP.wrap(this, function(searchString) { - var _rgxp = new RegExp("(" + searchString.replace(/(\W)/g,'\\$1') + ")","gi"); - this.selector.find("li").each(function(_i, _e) { - _e.innerHTML = searchString.length ? - _e.textContent.replace(_rgxp,'$1') - : _e.textContent; - }); - })); - this._Popcorn.listen("IriSP.search.closed", IriSP.wrap(this, this.endsearch)); - this._Popcorn.listen("IriSP.search.cleared", IriSP.wrap(this, this.endsearch)); -} - -IriSP.TagCloudWidget.prototype.endsearch = function() { - this.selector.find("li").each(function(_i, _e) { - _e.innerHTML = _e.textContent; - }); -} -/* this widget displays a small tooltip */ -IriSP.TooltipWidget = function(Popcorn, config, Serializer) { - 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. --- NOOOO !!!! - this.selector.css({ - "position": "absolute", - "top": 0, - "left": 0 - }); - this.selector.parent().css({ - "position": "relative" - }); - this.selector.append(templ); - var _this = this; - this.selector.mouseover(function() { - _this.hide(); - }); - this.hide(); - -}; - -IriSP.TooltipWidget.prototype.clear = function() { - this.selector.find(".tiptext").html(""); -}; - -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").html(text); - - var _tip = this.selector.find(".tip"); - _tip.show(); - _tip.css({ - "left": Math.floor(x - _tip.outerWidth() / 2)+"px", - "top": Math.floor(y - _tip.outerHeight())+"px" - }); - this._shown = true; -}; - -IriSP.TooltipWidget.prototype.hide = function() { - this.selector.find(".tip").hide(); - this._shown = false; -};IriSP.TraceWidget = function(Popcorn, config, Serializer) { - IriSP.Widget.call(this, Popcorn, config, Serializer); - this.lastEvent = ""; - var _this = this, - _listeners = { - "IriSP.createAnnotationWidget.addedAnnotation" : 0, - "IriSP.search.open" : 0, - "IriSP.search.closed" : 0, - "IriSP.search" : 0, - "IriSP.search.cleared" : 0, - "IriSP.search.matchFound" : 0, - "IriSP.search.noMatchFound" : 0, - "IriSP.search.triggeredSearch" : 0, - "IriSP.TraceWidget.MouseEvents" : 0, - "play" : 0, - "pause" : 0, - "volumechange" : 0, - "seeked" : 0, - "play" : 0, - "pause" : 0, - "timeupdate" : 2000 - }; - IriSP._(_listeners).each(function(_ms, _listener) { - var _f = function(_arg) { - _this.eventHandler(_listener, _arg); - } - if (_ms) { - _f = IriSP.underscore.throttle(_f, _ms); - } - _this._Popcorn.listen(_listener, _f); - }); - this._Popcorn.listen("timeupdate", IriSP.underscore.throttle(function(_arg) { - _this.eventHandler(_listener, _arg); - })); - - this.tracer = IriSP.TraceManager(IriSP.jQuery).init_trace("test", this._config); - this.tracer.set_default_subject("default_subject"); - this.tracer.trace("StartTracing", { "hello": "world" }); - -} - -IriSP.TraceWidget.prototype = new IriSP.Widget(); - -IriSP.TraceWidget.prototype.draw = function() { - this.mouseLocation = ''; - var _this = this; - IriSP.jQuery(".Ldt-Widget").bind("click mouseover mouseout dragstart dragstop", function(_e) { - var _widget = IriSP.jQuery(this).attr("widget-type"), - _class = _e.target.className; - var _data = { - "type": _e.type, - "x": _e.clientX, - "y": _e.clientY, - "widget": _widget - } - if (typeof _class == "string" && _class.indexOf('Ldt-TraceMe') != -1) { - var _name = _e.target.localName, - _id = _e.target.id, - _text = _e.target.textContent.trim(), - _title = _e.target.title, - _value = _e.target.value; - _data.target = _name + (_id.length ? '#' + IriSP.jqEscape(_id) : '') + (_class.length ? ('.' + IriSP.jqEscape(_class).replace(/\s/g,'.')).replace(/\.Ldt-(Widget|TraceMe)/g,'') : ''); - if (typeof _title == "string" && _title.length && _title.length < 140) { - _data.title = _title; - } - if (typeof _text == "string" && _text.length && _text.length < 140) { - _data.text = _text; - } - if (typeof _value == "string" && _value.length) { - _data.value = _value; - } - _this._Popcorn.trigger('IriSP.TraceWidget.MouseEvents', _data); - } else { - //console.log(_e.type+','+_this.mouseLocation+','+_widget); - if (_e.type == "mouseover") { - if (_this.mouseLocation != _widget) { - _this._Popcorn.trigger('IriSP.TraceWidget.MouseEvents', _data); - } else { - if (typeof _this.moTimeout != "undefined") { - clearTimeout(_this.moTimeout); - delete _this.moTimeout; - } - } - } - if (_e.type == "click") { - _this._Popcorn.trigger('IriSP.TraceWidget.MouseEvents', _data); - } - if (_e.type == "mouseout") { - if (typeof _this.moTimeout != "undefined") { - clearTimeout(_this.moTimeout); - } - _this.moTimeout = setTimeout(function() { - if (_data.widget != _this.mouseLocation) { - _this._Popcorn.trigger('IriSP.TraceWidget.MouseEvents', _data); - } - },100); - } - } - _this.mouseLocation = _widget; - }); -} - -IriSP.TraceWidget.prototype.eventHandler = function(_listener, _arg) { - var _traceName = 'Mdp_'; - if (typeof _arg == "string" || typeof _arg == "number") { - _arg = { "value" : _arg } - } - if (typeof _arg == "undefined") { - _arg = {} - } - switch(_listener) { - case 'IriSP.TraceWidget.MouseEvents': - _traceName += _arg.widget + '_' + _arg.type; - delete _arg.widget; - delete _arg.type; - break; - case 'timeupdate': - case 'play': - case 'pause': - _arg.time = this._Popcorn.currentTime() * 1000; - case 'seeked': - case 'volumechange': - _traceName += 'Popcorn_' + _listener; - break; - default: - _traceName += _listener.replace('IriSP.','').replace('.','_'); - } - this.lastEvent = _traceName; - this.tracer.trace(_traceName, _arg); - if (this._config.js_console) { - console.log("tracer.trace('" + _traceName + "', " + JSON.stringify(_arg) + ");"); - } -} -/* 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 = this.default_profile_picture; - } - - var imageMarkup = IriSP.templToHTML("user image", - {src : img}); - - if (typeof(IriSP.get_aliased(annotation.meta, ["dc:source", "source"]).content) !== "undefined") { - var tweetContents = JSON.parse(IriSP.get_aliased(annotation.meta, ["dc:source", "source"]).content); - var creator = tweetContents.user.screen_name; - var real_name = tweetContents.user.name; - - imageMarkup = IriSP.templToHTML("user image", - {src : img, creator: creator}); - - var formatted_date = new Date(tweetContents.created_at).toLocaleDateString(); - title = IriSP.templToHTML("@{{creator}} - " + - "
{{real_name}}
" + - "
{{{ contents }}}
" + - "
{{ date }}
", - {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), this.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, force_refresh) { - /* we don't have to do much because jQuery handles json for us */ - - var self = this; - - var fn = function(data) { - //TODO: seems taht data can be null here - if (data !== null) { - 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, force_refresh); -}; - -/** @return the metadata about the media being read FIXME: always return the first media. */ -IriSP.JSONSerializer.prototype.currentMedia = function() { - return (typeof this._data.medias == "object" && this._data.medias.length) ? this._data.medias[0] : IriSP.__jsonMetadata.medias[0]; -}; - -IriSP.JSONSerializer.prototype.getDuration = function() { - var _m = this.currentMedia(); - if (_m === null || typeof _m.meta == "undefined") { - return 0; - } - return +(IriSP.get_aliased(_m.meta, ["dc:duration", "duration"]) || 0); -} - - -/** 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 searchViewType = this.getTweets(); - if (typeof(searchViewType) === "undefined") { - var view; - - if (typeof(this._data.views) !== "undefined" && this._data.views !== null) - view = this._data.views[0]; - - 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; -}; - -/** return the current chapitre - @param currentTime the current time, in seconds. -*/ -IriSP.JSONSerializer.prototype.currentChapitre = function(currentTime) { - return this.currentAnnotations(currentTime, this.getChapitrage())[0]; -}; - -/** returns a list of ids of tweet lines (aka: groups in cinelab) */ -IriSP.JSONSerializer.prototype.getTweetIds = function() { - if (IriSP.null_or_undefined(this._data.lists) || IriSP.null_or_undefined(this._data.lists) || - IriSP.null_or_undefined(this._data.views) || IriSP.null_or_undefined(this._data.views[0])) - return []; - - - /* Get the displayable types - We've got to jump through a few hoops because the json sometimes defines - fields with underscores and sometimes with dashes - */ - var annotation_types = IriSP.get_aliased(this._data.views[0], ["annotation_types", "annotation-types"]); - if (annotation_types === null) { - console.log("neither view.annotation_types nor view.annotation-types are defined"); - return; - } - - var available_types = IriSP.get_aliased(this._data, ["annotation_types", "annotation-types"]); - if (available_types === null) { - console.log("neither view.annotation_types nor view.annotation-types are defined"); - return; - } - - var potential_types = []; - - // Get the list of types which contain "Tw" in their content - for (var i = 0; i < available_types.length; i++) { - if (/Tw/i.test(IriSP.get_aliased(available_types[i], ['dc:title', 'title']))) { - potential_types.push(available_types[i].id); - } - } - - // Get the intersection of both. - var tweetsId = IriSP.underscore.intersection(annotation_types, potential_types); - - return tweetsId; -}; - -/** this function returns a list of lines which are not tweet lines */ -IriSP.JSONSerializer.prototype.getNonTweetIds = function() { - if (IriSP.null_or_undefined(this._data.lists) || IriSP.null_or_undefined(this._data.lists) || - IriSP.null_or_undefined(this._data.views) || IriSP.null_or_undefined(this._data.views[0])) - return []; - - /* Get the displayable types - We've got to jump through a few hoops because the json sometimes defines - fields with underscores and sometimes with dashes - */ - var annotation_types = IriSP.get_aliased(this._data.views[0], ["annotation_types", "annotation-types"]); - if (annotation_types === null) { - console.log("neither view.annotation_types nor view.annotation-types are defined"); - return; - } - - var available_types = IriSP.get_aliased(this._data, ["annotation_types", "annotation-types"]); - if (available_types === null) { - console.log("neither view.annotation_types nor view.annotation-types are defined"); - return; - } - - var potential_types = []; - - // Get the list of types which do not contain "Tw" in their content - for (var i = 0; i < available_types.length; i++) { - if (!(/Tw/i.test(IriSP.get_aliased(available_types[i], ['dc:title', 'title'])))) { - potential_types.push(available_types[i].id); - } - } - - // Get the intersection of both. - var nonTweetsId = IriSP.underscore.intersection(annotation_types, potential_types); - - return nonTweetsId; - -}; - -/** return the id of the ligne de temps which contains name - @param name of the ligne de temps -*/ -IriSP.JSONSerializer.prototype.getId = function(name) { - var available_types = IriSP.get_aliased(this._data, ["annotation_types", "annotation-types"]); - - if (available_types == null) - return; - - name = name.toUpperCase(); - var e; - e = IriSP.underscore.find(available_types, - function(entry) { - if (IriSP.get_aliased(entry, ['dc:title', 'title']) === null) - return false; - return (entry["dc:title"].toUpperCase().indexOf(name) !== -1); - }); - - if (typeof(e) === "undefined") - return; - - var id = e.id; - - return id; -}; - -/** return the list of id's of the ligne de temps which contains name - @param name of the ligne de temps -*/ -IriSP.JSONSerializer.prototype.getIds = function(name) { - var available_types = IriSP.get_aliased(this._data, ["annotation_types", "annotation-types"]); - - if (available_types == null) - return; - - name = name.toUpperCase(); - var e = []; - e = IriSP.underscore.filter(available_types, - function(entry) { return (IriSP.get_aliased(entry, ['dc:title', 'title']).toUpperCase().indexOf(name) !== -1) }); - return IriSP.underscore.pluck(e, "id"); -}; - -/** return the id of the ligne de temps named "Chapitrage" */ -IriSP.JSONSerializer.prototype.getChapitrage = function() { - var val = this.getId("Chapitrage"); - if (typeof(val) === "undefined") - val = this.getId("Chapter"); - if (typeof(val) === "undefined") - val = this.getId("Chapit"); - if (typeof(val) === "undefined") - val = this.getId("Chap"); - - return val; -}; - -/** return the id of the ligne de temps named "Tweets" */ -IriSP.JSONSerializer.prototype.getTweets = function() { - var val = this.getId("Tweets"); - if (typeof(val) === "undefined") - val = this.getId("Tweet"); - if (typeof(val) === "undefined") - val = this.getId("Twitter"); - if (typeof(val) === "undefined") - val = this.getId("twit"); - if (typeof(val) === "undefined") - val = this.getId("Polemic"); - - return val; -}; - -/** return the id of the ligne de temps named "Contributions" */ -IriSP.JSONSerializer.prototype.getContributions = function() { - var val = this.getId("Contribution"); - if (typeof(val) === "undefined") - val = this.getId("Particip"); - if (typeof(val) === "undefined") - val = this.getId("Contr"); - if (typeof(val) === "undefined") - val = this.getId("Publ"); - - return val; -}; \ No newline at end of file diff -r 07ab28bca482 -r d366aa22bd79 web/res/js/mustache.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/js/mustache.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,436 @@ +/* + 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 = { + "&": "&", + "<": "<", + ">": ">", + '"': '"', + "'": ''' + }; + + 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"); + } + } + }); +}(); diff -r 07ab28bca482 -r d366aa22bd79 web/res/js/raphael-min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/js/raphael-min.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,7 @@ +/* + * Raphael 1.5.2 - JavaScript Vector Library + * + * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) + * Licensed under the MIT (http://raphaeljs.com/license.html) license. + */ +(function(){function a(){if(a.is(arguments[0],G)){var b=arguments[0],d=bV[m](a,b.splice(0,3+a.is(b[0],E))),e=d.set();for(var g=0,h=b[w];g";bg=bf.firstChild;bg.style.behavior="url(#default#VML)";if(!(bg&&typeof bg.adj=="object"))return a.type=null;bf=null}a.svg=!(a.vml=a.type=="VML");j[e]=a[e];k=j[e];a._id=0;a._oid=0;a.fn={};a.is=function(a,b){b=x.call(b);if(b=="finite")return!O[f](+a);return b=="null"&&a===null||b==typeof a||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||J.call(a).slice(8,-1).toLowerCase()==b};a.angle=function(b,c,d,e,f,g){{if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return((h<0)*180+y.atan(-i/-h)*180/D+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)}};a.rad=function(a){return a%360*D/180};a.deg=function(a){return a*180/D%360};a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,G)){var e=b.length;while(e--)if(B(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(fb-d)return c-f+b}return c};function bh(){var a=[],b=0;for(;b<32;b++)a[b]=(~(~(y.random()*16)))[H](16);a[12]=4;a[16]=(a[16]&3|8)[H](16);return"r-"+a[v]("")}a.setWindow=function(a){h=a;g=h.document};var bi=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write("");e.close();d=e.body}catch(a){d=createPopup().document.body}var f=d.createTextRange();bi=bm(function(a){try{d.style.color=r(a)[Y](c,p);var b=f.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b[H](16)).slice(-6)}catch(a){return"none"}})}else{var h=g.createElement("i");h.title="Raphaël Colour Picker";h.style.display="none";g.body[l](h);bi=bm(function(a){h.style.color=a;return g.defaultView.getComputedStyle(h,p).getPropertyValue("color")})}return bi(b)},bj=function(){return"hsb("+[this.h,this.s,this.b]+")"},bk=function(){return"hsl("+[this.h,this.s,this.l]+")"},bl=function(){return this.hex};a.hsb2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"b"in b){d=b.b;c=b.s;b=b.h;e=b.o}return a.hsl2rgb(b,c,d/2,e)};a.hsl2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"l"in b){d=b.l;c=b.s;b=b.h}if(b>1||c>1||d>1){b/=360;c/=100;d/=100}var f={},g=["r","g","b"],h,i,j,k,l,m;if(c){d<0.5?h=d*(1+c):h=d+c-d*c;i=2*d-h;for(var n=0;n<3;n++){j=b+1/3*-(n-1);j<0&&j++;j>1&&j--;j*6<1?f[g[n]]=i+(h-i)*6*j:j*2<1?f[g[n]]=h:j*3<2?f[g[n]]=i+(h-i)*(2/3-j)*6:f[g[n]]=i}}else f={r:d,g:d,b:d};f.r*=255;f.g*=255;f.b*=255;f.hex="#"+(16777216|f.b|f.g<<8|f.r<<16).toString(16).slice(1);a.is(e,"finite")&&(f.opacity=e);f.toString=bl;return f};a.rgb2hsb=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=f;{if(g==f)return{h:0,s:0,b:f,toString:bj};var k=f-g;i=k/f;b==f?h=(c-d)/k:c==f?h=2+(d-b)/k:h=4+(b-c)/k;h/=6;h<0&&h++;h>1&&h--}return{h:h,s:i,b:j,toString:bj}};a.rgb2hsl=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=(f+g)/2,k;if(g==f)k={h:0,s:0,l:j};else{var l=f-g;i=j<0.5?l/(f+g):l/(2-f-g);b==f?h=(c-d)/l:c==f?h=2+(d-b)/l:h=4+(b-c)/l;h/=6;h<0&&h++;h>1&&h--;k={h:h,s:i,l:j}}k.toString=bk;return k};a._path2string=function(){return this.join(",")[Y](ba,"$1")};function bm(a,b,c){function d(){var g=Array[e].slice.call(arguments,0),h=g[v]("►"),i=d.cache=d.cache||{},j=d.count=d.count||[];if(i[f](h))return c?c(i[h]):i[h];j[w]>=1000&&delete i[j.shift()];j[L](h);i[h]=a[m](b,g);return c?c(i[h]):i[h]}return d}a.getRGB=bm(function(b){if(!b||!(!((b=r(b)).indexOf("-")+1)))return{r:-1,g:-1,b:-1,hex:"none",error:1};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(_[f](b.toLowerCase().substring(0,2))||b.charAt()=="#")&&(b=bi(b));var c,d,e,g,h,i,j,k=b.match(N);if(k){if(k[2]){g=T(k[2].substring(5),16);e=T(k[2].substring(3,5),16);d=T(k[2].substring(1,3),16)}if(k[3]){g=T((i=k[3].charAt(3))+i,16);e=T((i=k[3].charAt(2))+i,16);d=T((i=k[3].charAt(1))+i,16)}if(k[4]){j=k[4][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);k[1].toLowerCase().slice(0,4)=="rgba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100)}if(k[5]){j=k[5][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,g,h)}if(k[6]){j=k[6][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsla"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,g,h)}k={r:d,g:e,b:g};k.hex="#"+(16777216|g|e<<8|d<<16).toString(16).slice(1);a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1}},a);a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=0.075;if(b.h>1){b.h=0;b.s-=0.2;b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b})}return c.hex};a.getColor.reset=function(){delete this.start};a.parsePathString=bm(function(b){if(!b)return null;var c={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},d=[];a.is(b,G)&&a.is(b[0],G)&&(d=bo(b));d[w]||r(b)[Y](bb,function(a,b,e){var f=[],g=x.call(b);e[Y](bc,function(a,b){b&&f[L](+b)});if(g=="m"&&f[w]>2){d[L]([b][n](f.splice(0,2)));g="l";b=b=="m"?"l":"L"}while(f[w]>=c[g]){d[L]([b][n](f.splice(0,c[g])));if(!c[g])break}});d[H]=a._path2string;return d});a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=C(j,3)*a+C(j,2)*3*i*c+j*3*i*i*e+C(i,3)*g,l=C(j,3)*b+C(j,2)*3*i*d+j*3*i*i*f+C(i,3)*h,m=a+2*i*(c-a)+i*i*(e-2*c+a),n=b+2*i*(d-b)+i*i*(f-2*d+b),o=c+2*i*(e-c)+i*i*(g-2*e+c),p=d+2*i*(f-d)+i*i*(h-2*f+d),q=(1-i)*a+i*c,r=(1-i)*b+i*d,s=(1-i)*e+i*g,t=(1-i)*f+i*h,u=90-y.atan((m-o)/(n-p))*180/D;(m>o||n1){x=y.sqrt(x);c=x*c;d=x*d}var z=c*c,A=d*d,C=(f==g?-1:1)*y.sqrt(B((z*A-z*u*u-A*t*t)/(z*u*u+A*t*t))),E=C*c*u/d+(a+h)/2,F=C*-d*t/c+(b+i)/2,G=y.asin(((b-F)/d).toFixed(9)),H=y.asin(((i-F)/d).toFixed(9));G=aH&&(G=G-D*2);!g&&H>G&&(H=H-D*2)}var I=H-G;if(B(I)>k){var J=H,K=h,L=i;H=G+k*(g&&H>G?1:-1);h=E+c*y.cos(H);i=F+d*y.sin(H);m=bt(h,i,c,d,e,0,g,K,L,[H,J,E,F])}I=H-G;var M=y.cos(G),N=y.sin(G),O=y.cos(H),P=y.sin(H),Q=y.tan(I/4),R=4/3*c*Q,S=4/3*d*Q,T=[a,b],U=[a+R*N,b-S*M],V=[h+R*P,i-S*O],W=[h,i];U[0]=2*T[0]-U[0];U[1]=2*T[1]-U[1];{if(j)return[U,V,W][n](m);m=[U,V,W][n](m)[v]()[s](",");var X=[];for(var Y=0,Z=m[w];Y"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}i=f-2*d+b-(h-2*f+d);j=2*(d-b)-2*(f-d);k=b-d;l=(-j+y.sqrt(j*j-4*i*k))/2/i;n=(-j-y.sqrt(j*j-4*i*k))/2/i;B(l)>"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}return{min:{x:A[m](0,p),y:A[m](0,o)},max:{x:z[m](0,p),y:z[m](0,o)}}}),bw=bm(function(a,b){var c=bq(a),d=b&&bq(b),e={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1];b.Y=a[2];break;case"A":a=["C"][n](bt[m](0,[b.x,b.y][n](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x));d=b.y+(b.y-(b.by||b.y));a=["C",c,d][n](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x));b.qy=b.y+(b.y-(b.qy||b.y));a=["C"][n](bs(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1];b.qy=a[2];a=["C"][n](bs(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][n](br(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][n](br(b.x,b.y,a[1],b.y));break;case"V":a=["C"][n](br(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][n](br(b.x,b.y,b.X,b.Y));break}return a},h=function(a,b){if(a[b][w]>7){a[b].shift();var e=a[b];while(e[w])a.splice(b++,0,["C"][n](e.splice(0,6)));a.splice(b,1);k=z(c[w],d&&d[w]||0)}},i=function(a,b,e,f,g){if(a&&b&&a[g][0]=="M"&&b[g][0]!="M"){b.splice(g,0,["M",f.x,f.y]);e.bx=0;e.by=0;e.x=a[g][1];e.y=a[g][2];k=z(c[w],d&&d[w]||0)}};for(var j=0,k=z(c[w],d&&d[w]||0);j0.5)*2-1;C(e-0.5,2)+C(f-0.5,2)>0.25&&(f=y.sqrt(0.25-C(e-0.5,2))*g+0.5)&&f!=0.5&&(f=f.toFixed(5)-0.00001*g)}return p});b=b[s](/\s*\-\s*/);if(d=="linear"){var i=b.shift();i=-S(i);if(isNaN(i))return null;var j=[0,0,y.cos(i*D/180),y.sin(i*D/180)],k=1/(z(B(j[2]),B(j[3]))||1);j[2]*=k;j[3]*=k;if(j[2]<0){j[0]=-j[2];j[2]=0}if(j[3]<0){j[1]=-j[3];j[3]=0}}var m=bx(b);if(!m)return null;var n=a.getAttribute(I);n=n.match(/^url\(#(.*)\)$/);n&&c.defs.removeChild(g.getElementById(n[1]));var o=bG(d+"Gradient");o.id=bh();bG(o,d=="radial"?{fx:e,fy:f}:{x1:j[0],y1:j[1],x2:j[2],y2:j[3]});c.defs[l](o);for(var q=0,t=m[w];q1?G.opacity/100:G.opacity});case"stroke":G=a.getRGB(o);h[R](n,G.hex);n=="stroke"&&G[f]("opacity")&&bG(h,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity});break;case"gradient":(({circle:1,ellipse:1})[f](c.type)||r(o).charAt()!="r")&&bI(h,o,c.paper);break;case"opacity":i.gradient&&!i[f]("stroke-opacity")&&bG(h,{"stroke-opacity":o>1?o/100:o});case"fill-opacity":if(i.gradient){var H=g.getElementById(h.getAttribute(I)[Y](/^url\(#|\)$/g,p));if(H){var J=H.getElementsByTagName("stop");J[J[w]-1][R]("stop-opacity",o)}break}default:n=="font-size"&&(o=T(o,10)+"px");var K=n[Y](/(\-.)/g,function(a){return V.call(a.substring(1))});h.style[K]=o;h[R](n,o);break}}}bM(c,d);m?c.rotate(m.join(q)):S(j)&&c.rotate(j,true)},bL=1.2,bM=function(b,c){if(b.type!="text"||!(c[f]("text")||c[f]("font")||c[f]("font-size")||c[f]("x")||c[f]("y")))return;var d=b.attrs,e=b.node,h=e.firstChild?T(g.defaultView.getComputedStyle(e.firstChild,p).getPropertyValue("font-size"),10):10;if(c[f]("text")){d.text=c.text;while(e.firstChild)e.removeChild(e.firstChild);var i=r(c.text)[s]("\n");for(var j=0,k=i[w];jb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};bN[e].attr=function(b,c){if(this.removed)return this;if(b==null){var d={};for(var e in this.attrs)this.attrs[f](e)&&(d[e]=this.attrs[e]);this._.rt.deg&&(d.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(d.scale=this.scale());d.gradient&&d.fill=="none"&&(d.fill=d.gradient)&&delete d.gradient;return d}if(c==null&&a.is(b,F)){if(b=="translation")return cz.call(this);if(b=="rotation")return this.rotate();if(b=="scale")return this.scale();if(b==I&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[b]}if(c==null&&a.is(b,G)){var g={};for(var h=0,i=b.length;h"));m.W=h.w=m.paper.span.offsetWidth;m.H=h.h=m.paper.span.offsetHeight;m.X=h.x;m.Y=h.y+Q(m.H/2);switch(h["text-anchor"]){case"start":m.node.style["v-text-align"]="left";m.bbx=Q(m.W/2);break;case"end":m.node.style["v-text-align"]="right";m.bbx=-Q(m.W/2);break;default:m.node.style["v-text-align"]="center";break}}};bI=function(a,b){a.attrs=a.attrs||{};var c=a.attrs,d,e="linear",f=".5 .5";a.attrs.gradient=b;b=r(b)[Y](bd,function(a,b,c){e="radial";if(b&&c){b=S(b);c=S(c);C(b-0.5,2)+C(c-0.5,2)>0.25&&(c=y.sqrt(0.25-C(b-0.5,2))*((c>0.5)*2-1)+0.5);f=b+q+c}return p});b=b[s](/\s*\-\s*/);if(e=="linear"){var g=b.shift();g=-S(g);if(isNaN(g))return null}var h=bx(b);if(!h)return null;a=a.shape||a.node;d=a.getElementsByTagName(I)[0]||cd(I);!d.parentNode&&a.appendChild(d);if(h[w]){d.on=true;d.method="none";d.color=h[0].color;d.color2=h[h[w]-1].color;var i=[];for(var j=0,k=h[w];j")}}catch(a){cd=function(a){return g.createElement("<"+a+" xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">")}}bV=function(){var b=by[m](0,arguments),c=b.container,d=b.height,e,f=b.width,h=b.x,i=b.y;if(!c)throw new Error("VML container not found.");var k=new j,n=k.canvas=g.createElement("div"),o=n.style;h=h||0;i=i||0;f=f||512;d=d||342;f==+f&&(f+="px");d==+d&&(d+="px");k.width=1000;k.height=1000;k.coordsize=b_*1000+q+b_*1000;k.coordorigin="0 0";k.span=g.createElement("span");k.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";n[l](k.span);o.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d);if(c==1){g.body[l](n);o.left=h+"px";o.top=i+"px";o.position="absolute"}else c.firstChild?c.insertBefore(n,c.firstChild):c[l](n);bz.call(k,k,a.fn);return k};k.clear=function(){this.canvas.innerHTML=p;this.span=g.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[l](this.span);this.bottom=this.top=null};k.remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=bF(a);return true}}var ce=navigator.userAgent.match(/Version\\x2f(.*?)\s/);navigator.vendor=="Apple Computer, Inc."&&(ce&&ce[1]<4||navigator.platform.slice(0,2)=="iP")?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});h.setTimeout(function(){a.remove()})}:k.safari=function(){};var cf=function(){this.returnValue=false},cg=function(){return this.originalEvent.preventDefault()},ch=function(){this.cancelBubble=true},ci=function(){return this.originalEvent.stopPropagation()},cj=(function(){{if(g.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,g=function(e){if(o&&u[f](b))for(var g=0,h=e.targetTouches&&e.targetTouches.length;g1&&(a=Array[e].splice.call(arguments,0,arguments[w]));return new cC(a)};k.setSize=bU;k.top=k.bottom=null;k.raphael=a;function co(){return this.x+q+this.y}bO.resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};bO.scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:co};b=b||a;!(+b)&&(b=a);var e,f,g,h,i=this.attrs;if(a!=0){var j=this.getBBox(),k=j.x+j.width/2,l=j.y+j.height/2,m=B(a/this._.sx),o=B(b/this._.sy);c=+c||c==0?c:k;d=+d||d==0?d:l;var r=this._.sx>0,s=this._.sy>0,t=~(~(a/B(a))),u=~(~(b/B(b))),x=m*t,y=o*u,z=this.node.style,A=c+B(k-c)*x*(k>c==r?1:-1),C=d+B(l-d)*y*(l>d==s?1:-1),D=a*t>b*u?o:m;switch(this.type){case"rect":case"image":var E=i.width*m,F=i.height*o;this.attr({height:F,r:i.r*D,width:E,x:A-E/2,y:C-F/2});break;case"circle":case"ellipse":this.attr({rx:i.rx*m,ry:i.ry*o,r:i.r*D,cx:A,cy:C});break;case"text":this.attr({x:A,y:C});break;case"path":var G=bp(i.path),H=true,I=r?x:m,J=s?y:o;for(var K=0,L=G[w];Kr)p=n.data[r*l];else{p=a.findDotsAtSegment(b,c,d,e,f,g,h,i,r/l);n.data[r]=p}r&&(k+=C(C(o.x-p.x,2)+C(o.y-p.y,2),0.5));if(j!=null&&k>=j)return p;o=p}if(j==null)return k},cr=function(b,c){return function(d,e,f){d=bw(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;oe){if(c&&!l.start){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);k+=["C",m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k;k=["M",m.x,m.y+"C",m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]][v]();n+=j;g=+i[5];h=+i[6];continue}if(!b&&!c){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j;g=+i[5];h=+i[6]}k+=i}l.end=k;m=b?n:c?l:a.findDotsAtSegment(g,h,i[1],i[2],i[3],i[4],i[5],i[6],1);m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cs=cr(1),ct=cr(),cu=cr(0,1);bO.getTotalLength=function(){if(this.type!="path")return;if(this.node.getTotalLength)return this.node.getTotalLength();return cs(this.attrs.path)};bO.getPointAtLength=function(a){if(this.type!="path")return;return ct(this.attrs.path,a)};bO.getSubpath=function(a,b){if(this.type!="path")return;if(B(this.getTotalLength()-b)<"1e-6")return cu(this.attrs.path,a).end;var c=cu(this.attrs.path,b,1);return a?cu(c,a).end:c};a.easing_formulas={linear:function(a){return a},"<":function(a){return C(a,3)},">":function(a){return C(a-1,3)+1},"<>":function(a){a=a*2;if(a<1)return C(a,3)/2;a-=2;return(C(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==0||a==1)return a;var b=0.3,c=b/4;return C(2,-10*a)*y.sin((a-c)*(2*D)/b)+1},bounce:function(a){var b=7.5625,c=2.75,d;if(a<1/c)d=b*a*a;else if(a<2/c){a-=1.5/c;d=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;d=b*a*a+0.9375}else{a-=2.625/c;d=b*a*a+0.984375}return d}};var cv=[],cw=function(){var b=+(new Date);for(var c=0;cd)return d;while(cf?c=e:d=e;e=(d-c)/2+c}return e}return n(a,1/(200*f))}bO.onAnimation=function(a){this._run=a||0;return this};bO.animate=function(c,d,e,g){var h=this;h.timeouts=h.timeouts||[];if(a.is(e,"function")||!e)g=e||null;if(h.removed){g&&g.call(h);return h}var i={},j={},k=false,l={};for(var m in c)if(c[f](m)){if(X[f](m)||h.paper.customAttributes[f](m)){k=true;i[m]=h.attr(m);i[m]==null&&(i[m]=W[m]);j[m]=c[m];switch(X[m]){case"along":var n=cs(c[m]),o=ct(c[m],n*!(!c.back)),p=h.getBBox();l[m]=n/d;l.tx=p.x;l.ty=p.y;l.sx=o.x;l.sy=o.y;j.rot=c.rot;j.back=c.back;j.len=n;c.rot&&(l.r=S(h.rotate())||0);break;case E:l[m]=(j[m]-i[m])/d;break;case"colour":i[m]=a.getRGB(i[m]);var q=a.getRGB(j[m]);l[m]={r:(q.r-i[m].r)/d,g:(q.g-i[m].g)/d,b:(q.b-i[m].b)/d};break;case"path":var t=bw(i[m],j[m]);i[m]=t[0];var u=t[1];l[m]=[];for(var v=0,x=i[m][w];v";bg=bf.firstChild;bg.style.behavior="url(#default#VML)";if(!(bg&&typeof bg.adj=="object"))return a.type=null;bf=null}a.svg=!(a.vml=a.type=="VML");j[e]=a[e];k=j[e];a._id=0;a._oid=0;a.fn={};a.is=function(a,b){b=x.call(b);if(b=="finite")return!O[f](+a);return b=="null"&&a===null||b==typeof a||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||J.call(a).slice(8,-1).toLowerCase()==b};a.angle=function(b,c,d,e,f,g){{if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return((h<0)*180+y.atan(-i/-h)*180/D+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)}};a.rad=function(a){return a%360*D/180};a.deg=function(a){return a*180/D%360};a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,G)){var e=b.length;while(e--)if(B(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(fb-d)return c-f+b}return c};function bh(){var a=[],b=0;for(;b<32;b++)a[b]=(~(~(y.random()*16)))[H](16);a[12]=4;a[16]=(a[16]&3|8)[H](16);return"r-"+a[v]("")}a.setWindow=function(a){h=a;g=h.document};var bi=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write("");e.close();d=e.body}catch(a){d=createPopup().document.body}var f=d.createTextRange();bi=bm(function(a){try{d.style.color=r(a)[Y](c,p);var b=f.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b[H](16)).slice(-6)}catch(a){return"none"}})}else{var h=g.createElement("i");h.title="Raphaël Colour Picker";h.style.display="none";g.body[l](h);bi=bm(function(a){h.style.color=a;return g.defaultView.getComputedStyle(h,p).getPropertyValue("color")})}return bi(b)},bj=function(){return"hsb("+[this.h,this.s,this.b]+")"},bk=function(){return"hsl("+[this.h,this.s,this.l]+")"},bl=function(){return this.hex};a.hsb2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"b"in b){d=b.b;c=b.s;b=b.h;e=b.o}return a.hsl2rgb(b,c,d/2,e)};a.hsl2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"l"in b){d=b.l;c=b.s;b=b.h}if(b>1||c>1||d>1){b/=360;c/=100;d/=100}var f={},g=["r","g","b"],h,i,j,k,l,m;if(c){d<0.5?h=d*(1+c):h=d+c-d*c;i=2*d-h;for(var n=0;n<3;n++){j=b+1/3*-(n-1);j<0&&j++;j>1&&j--;j*6<1?f[g[n]]=i+(h-i)*6*j:j*2<1?f[g[n]]=h:j*3<2?f[g[n]]=i+(h-i)*(2/3-j)*6:f[g[n]]=i}}else f={r:d,g:d,b:d};f.r*=255;f.g*=255;f.b*=255;f.hex="#"+(16777216|f.b|f.g<<8|f.r<<16).toString(16).slice(1);a.is(e,"finite")&&(f.opacity=e);f.toString=bl;return f};a.rgb2hsb=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=f;{if(g==f)return{h:0,s:0,b:f,toString:bj};var k=f-g;i=k/f;b==f?h=(c-d)/k:c==f?h=2+(d-b)/k:h=4+(b-c)/k;h/=6;h<0&&h++;h>1&&h--}return{h:h,s:i,b:j,toString:bj}};a.rgb2hsl=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=(f+g)/2,k;if(g==f)k={h:0,s:0,l:j};else{var l=f-g;i=j<0.5?l/(f+g):l/(2-f-g);b==f?h=(c-d)/l:c==f?h=2+(d-b)/l:h=4+(b-c)/l;h/=6;h<0&&h++;h>1&&h--;k={h:h,s:i,l:j}}k.toString=bk;return k};a._path2string=function(){return this.join(",")[Y](ba,"$1")};function bm(a,b,c){function d(){var g=Array[e].slice.call(arguments,0),h=g[v]("►"),i=d.cache=d.cache||{},j=d.count=d.count||[];if(i[f](h))return c?c(i[h]):i[h];j[w]>=1000&&delete i[j.shift()];j[L](h);i[h]=a[m](b,g);return c?c(i[h]):i[h]}return d}a.getRGB=bm(function(b){if(!b||!(!((b=r(b)).indexOf("-")+1)))return{r:-1,g:-1,b:-1,hex:"none",error:1};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(_[f](b.toLowerCase().substring(0,2))||b.charAt()=="#")&&(b=bi(b));var c,d,e,g,h,i,j,k=b.match(N);if(k){if(k[2]){g=T(k[2].substring(5),16);e=T(k[2].substring(3,5),16);d=T(k[2].substring(1,3),16)}if(k[3]){g=T((i=k[3].charAt(3))+i,16);e=T((i=k[3].charAt(2))+i,16);d=T((i=k[3].charAt(1))+i,16)}if(k[4]){j=k[4][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);k[1].toLowerCase().slice(0,4)=="rgba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100)}if(k[5]){j=k[5][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,g,h)}if(k[6]){j=k[6][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsla"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,g,h)}k={r:d,g:e,b:g};k.hex="#"+(16777216|g|e<<8|d<<16).toString(16).slice(1);a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1}},a);a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=0.075;if(b.h>1){b.h=0;b.s-=0.2;b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b})}return c.hex};a.getColor.reset=function(){delete this.start};a.parsePathString=bm(function(b){if(!b)return null;var c={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},d=[];a.is(b,G)&&a.is(b[0],G)&&(d=bo(b));d[w]||r(b)[Y](bb,function(a,b,e){var f=[],g=x.call(b);e[Y](bc,function(a,b){b&&f[L](+b)});if(g=="m"&&f[w]>2){d[L]([b][n](f.splice(0,2)));g="l";b=b=="m"?"l":"L"}while(f[w]>=c[g]){d[L]([b][n](f.splice(0,c[g])));if(!c[g])break}});d[H]=a._path2string;return d});a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=C(j,3)*a+C(j,2)*3*i*c+j*3*i*i*e+C(i,3)*g,l=C(j,3)*b+C(j,2)*3*i*d+j*3*i*i*f+C(i,3)*h,m=a+2*i*(c-a)+i*i*(e-2*c+a),n=b+2*i*(d-b)+i*i*(f-2*d+b),o=c+2*i*(e-c)+i*i*(g-2*e+c),p=d+2*i*(f-d)+i*i*(h-2*f+d),q=(1-i)*a+i*c,r=(1-i)*b+i*d,s=(1-i)*e+i*g,t=(1-i)*f+i*h,u=90-y.atan((m-o)/(n-p))*180/D;(m>o||n1){x=y.sqrt(x);c=x*c;d=x*d}var z=c*c,A=d*d,C=(f==g?-1:1)*y.sqrt(B((z*A-z*u*u-A*t*t)/(z*u*u+A*t*t))),E=C*c*u/d+(a+h)/2,F=C*-d*t/c+(b+i)/2,G=y.asin(((b-F)/d).toFixed(9)),H=y.asin(((i-F)/d).toFixed(9));G=aH&&(G=G-D*2);!g&&H>G&&(H=H-D*2)}var I=H-G;if(B(I)>k){var J=H,K=h,L=i;H=G+k*(g&&H>G?1:-1);h=E+c*y.cos(H);i=F+d*y.sin(H);m=bt(h,i,c,d,e,0,g,K,L,[H,J,E,F])}I=H-G;var M=y.cos(G),N=y.sin(G),O=y.cos(H),P=y.sin(H),Q=y.tan(I/4),R=4/3*c*Q,S=4/3*d*Q,T=[a,b],U=[a+R*N,b-S*M],V=[h+R*P,i-S*O],W=[h,i];U[0]=2*T[0]-U[0];U[1]=2*T[1]-U[1];{if(j)return[U,V,W][n](m);m=[U,V,W][n](m)[v]()[s](",");var X=[];for(var Y=0,Z=m[w];Y"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}i=f-2*d+b-(h-2*f+d);j=2*(d-b)-2*(f-d);k=b-d;l=(-j+y.sqrt(j*j-4*i*k))/2/i;n=(-j-y.sqrt(j*j-4*i*k))/2/i;B(l)>"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}return{min:{x:A[m](0,p),y:A[m](0,o)},max:{x:z[m](0,p),y:z[m](0,o)}}}),bw=bm(function(a,b){var c=bq(a),d=b&&bq(b),e={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1];b.Y=a[2];break;case"A":a=["C"][n](bt[m](0,[b.x,b.y][n](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x));d=b.y+(b.y-(b.by||b.y));a=["C",c,d][n](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x));b.qy=b.y+(b.y-(b.qy||b.y));a=["C"][n](bs(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1];b.qy=a[2];a=["C"][n](bs(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][n](br(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][n](br(b.x,b.y,a[1],b.y));break;case"V":a=["C"][n](br(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][n](br(b.x,b.y,b.X,b.Y));break}return a},h=function(a,b){if(a[b][w]>7){a[b].shift();var e=a[b];while(e[w])a.splice(b++,0,["C"][n](e.splice(0,6)));a.splice(b,1);k=z(c[w],d&&d[w]||0)}},i=function(a,b,e,f,g){if(a&&b&&a[g][0]=="M"&&b[g][0]!="M"){b.splice(g,0,["M",f.x,f.y]);e.bx=0;e.by=0;e.x=a[g][1];e.y=a[g][2];k=z(c[w],d&&d[w]||0)}};for(var j=0,k=z(c[w],d&&d[w]||0);j0.5)*2-1;C(e-0.5,2)+C(f-0.5,2)>0.25&&(f=y.sqrt(0.25-C(e-0.5,2))*g+0.5)&&f!=0.5&&(f=f.toFixed(5)-0.00001*g)}return p});b=b[s](/\s*\-\s*/);if(d=="linear"){var i=b.shift();i=-S(i);if(isNaN(i))return null;var j=[0,0,y.cos(i*D/180),y.sin(i*D/180)],k=1/(z(B(j[2]),B(j[3]))||1);j[2]*=k;j[3]*=k;if(j[2]<0){j[0]=-j[2];j[2]=0}if(j[3]<0){j[1]=-j[3];j[3]=0}}var m=bx(b);if(!m)return null;var n=a.getAttribute(I);n=n.match(/^url\(#(.*)\)$/);n&&c.defs.removeChild(g.getElementById(n[1]));var o=bG(d+"Gradient");o.id=bh();bG(o,d=="radial"?{fx:e,fy:f}:{x1:j[0],y1:j[1],x2:j[2],y2:j[3]});c.defs[l](o);for(var q=0,t=m[w];q1?G.opacity/100:G.opacity});case"stroke":G=a.getRGB(o);h[R](n,G.hex);n=="stroke"&&G[f]("opacity")&&bG(h,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity});break;case"gradient":(({circle:1,ellipse:1})[f](c.type)||r(o).charAt()!="r")&&bI(h,o,c.paper);break;case"opacity":i.gradient&&!i[f]("stroke-opacity")&&bG(h,{"stroke-opacity":o>1?o/100:o});case"fill-opacity":if(i.gradient){var H=g.getElementById(h.getAttribute(I)[Y](/^url\(#|\)$/g,p));if(H){var J=H.getElementsByTagName("stop");J[J[w]-1][R]("stop-opacity",o)}break}default:n=="font-size"&&(o=T(o,10)+"px");var K=n[Y](/(\-.)/g,function(a){return V.call(a.substring(1))});h.style[K]=o;h[R](n,o);break}}}bM(c,d);m?c.rotate(m.join(q)):S(j)&&c.rotate(j,true)},bL=1.2,bM=function(b,c){if(b.type!="text"||!(c[f]("text")||c[f]("font")||c[f]("font-size")||c[f]("x")||c[f]("y")))return;var d=b.attrs,e=b.node,h=e.firstChild?T(g.defaultView.getComputedStyle(e.firstChild,p).getPropertyValue("font-size"),10):10;if(c[f]("text")){d.text=c.text;while(e.firstChild)e.removeChild(e.firstChild);var i=r(c.text)[s]("\n");for(var j=0,k=i[w];jb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};bN[e].attr=function(b,c){if(this.removed)return this;if(b==null){var d={};for(var e in this.attrs)this.attrs[f](e)&&(d[e]=this.attrs[e]);this._.rt.deg&&(d.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(d.scale=this.scale());d.gradient&&d.fill=="none"&&(d.fill=d.gradient)&&delete d.gradient;return d}if(c==null&&a.is(b,F)){if(b=="translation")return cz.call(this);if(b=="rotation")return this.rotate();if(b=="scale")return this.scale();if(b==I&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[b]}if(c==null&&a.is(b,G)){var g={};for(var h=0,i=b.length;h"));m.W=h.w=m.paper.span.offsetWidth;m.H=h.h=m.paper.span.offsetHeight;m.X=h.x;m.Y=h.y+Q(m.H/2);switch(h["text-anchor"]){case"start":m.node.style["v-text-align"]="left";m.bbx=Q(m.W/2);break;case"end":m.node.style["v-text-align"]="right";m.bbx=-Q(m.W/2);break;default:m.node.style["v-text-align"]="center";break}}};bI=function(a,b){a.attrs=a.attrs||{};var c=a.attrs,d,e="linear",f=".5 .5";a.attrs.gradient=b;b=r(b)[Y](bd,function(a,b,c){e="radial";if(b&&c){b=S(b);c=S(c);C(b-0.5,2)+C(c-0.5,2)>0.25&&(c=y.sqrt(0.25-C(b-0.5,2))*((c>0.5)*2-1)+0.5);f=b+q+c}return p});b=b[s](/\s*\-\s*/);if(e=="linear"){var g=b.shift();g=-S(g);if(isNaN(g))return null}var h=bx(b);if(!h)return null;a=a.shape||a.node;d=a.getElementsByTagName(I)[0]||cd(I);!d.parentNode&&a.appendChild(d);if(h[w]){d.on=true;d.method="none";d.color=h[0].color;d.color2=h[h[w]-1].color;var i=[];for(var j=0,k=h[w];j")}}catch(a){cd=function(a){return g.createElement("<"+a+" xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">")}}bV=function(){var b=by[m](0,arguments),c=b.container,d=b.height,e,f=b.width,h=b.x,i=b.y;if(!c)throw new Error("VML container not found.");var k=new j,n=k.canvas=g.createElement("div"),o=n.style;h=h||0;i=i||0;f=f||512;d=d||342;f==+f&&(f+="px");d==+d&&(d+="px");k.width=1000;k.height=1000;k.coordsize=b_*1000+q+b_*1000;k.coordorigin="0 0";k.span=g.createElement("span");k.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";n[l](k.span);o.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d);if(c==1){g.body[l](n);o.left=h+"px";o.top=i+"px";o.position="absolute"}else c.firstChild?c.insertBefore(n,c.firstChild):c[l](n);bz.call(k,k,a.fn);return k};k.clear=function(){this.canvas.innerHTML=p;this.span=g.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[l](this.span);this.bottom=this.top=null};k.remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=bF(a);return true}}var ce=navigator.userAgent.match(/Version\\x2f(.*?)\s/);navigator.vendor=="Apple Computer, Inc."&&(ce&&ce[1]<4||navigator.platform.slice(0,2)=="iP")?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});h.setTimeout(function(){a.remove()})}:k.safari=function(){};var cf=function(){this.returnValue=false},cg=function(){return this.originalEvent.preventDefault()},ch=function(){this.cancelBubble=true},ci=function(){return this.originalEvent.stopPropagation()},cj=(function(){{if(g.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,g=function(e){if(o&&u[f](b))for(var g=0,h=e.targetTouches&&e.targetTouches.length;g1&&(a=Array[e].splice.call(arguments,0,arguments[w]));return new cC(a)};k.setSize=bU;k.top=k.bottom=null;k.raphael=a;function co(){return this.x+q+this.y}bO.resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};bO.scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:co};b=b||a;!(+b)&&(b=a);var e,f,g,h,i=this.attrs;if(a!=0){var j=this.getBBox(),k=j.x+j.width/2,l=j.y+j.height/2,m=B(a/this._.sx),o=B(b/this._.sy);c=+c||c==0?c:k;d=+d||d==0?d:l;var r=this._.sx>0,s=this._.sy>0,t=~(~(a/B(a))),u=~(~(b/B(b))),x=m*t,y=o*u,z=this.node.style,A=c+B(k-c)*x*(k>c==r?1:-1),C=d+B(l-d)*y*(l>d==s?1:-1),D=a*t>b*u?o:m;switch(this.type){case"rect":case"image":var E=i.width*m,F=i.height*o;this.attr({height:F,r:i.r*D,width:E,x:A-E/2,y:C-F/2});break;case"circle":case"ellipse":this.attr({rx:i.rx*m,ry:i.ry*o,r:i.r*D,cx:A,cy:C});break;case"text":this.attr({x:A,y:C});break;case"path":var G=bp(i.path),H=true,I=r?x:m,J=s?y:o;for(var K=0,L=G[w];Kr)p=n.data[r*l];else{p=a.findDotsAtSegment(b,c,d,e,f,g,h,i,r/l);n.data[r]=p}r&&(k+=C(C(o.x-p.x,2)+C(o.y-p.y,2),0.5));if(j!=null&&k>=j)return p;o=p}if(j==null)return k},cr=function(b,c){return function(d,e,f){d=bw(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;oe){if(c&&!l.start){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);k+=["C",m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k;k=["M",m.x,m.y+"C",m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]][v]();n+=j;g=+i[5];h=+i[6];continue}if(!b&&!c){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j;g=+i[5];h=+i[6]}k+=i}l.end=k;m=b?n:c?l:a.findDotsAtSegment(g,h,i[1],i[2],i[3],i[4],i[5],i[6],1);m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cs=cr(1),ct=cr(),cu=cr(0,1);bO.getTotalLength=function(){if(this.type!="path")return;if(this.node.getTotalLength)return this.node.getTotalLength();return cs(this.attrs.path)};bO.getPointAtLength=function(a){if(this.type!="path")return;return ct(this.attrs.path,a)};bO.getSubpath=function(a,b){if(this.type!="path")return;if(B(this.getTotalLength()-b)<"1e-6")return cu(this.attrs.path,a).end;var c=cu(this.attrs.path,b,1);return a?cu(c,a).end:c};a.easing_formulas={linear:function(a){return a},"<":function(a){return C(a,3)},">":function(a){return C(a-1,3)+1},"<>":function(a){a=a*2;if(a<1)return C(a,3)/2;a-=2;return(C(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==0||a==1)return a;var b=0.3,c=b/4;return C(2,-10*a)*y.sin((a-c)*(2*D)/b)+1},bounce:function(a){var b=7.5625,c=2.75,d;if(a<1/c)d=b*a*a;else if(a<2/c){a-=1.5/c;d=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;d=b*a*a+0.9375}else{a-=2.625/c;d=b*a*a+0.984375}return d}};var cv=[],cw=function(){var b=+(new Date);for(var c=0;cd)return d;while(cf?c=e:d=e;e=(d-c)/2+c}return e}return n(a,1/(200*f))}bO.onAnimation=function(a){this._run=a||0;return this};bO.animate=function(c,d,e,g){var h=this;h.timeouts=h.timeouts||[];if(a.is(e,"function")||!e)g=e||null;if(h.removed){g&&g.call(h);return h}var i={},j={},k=false,l={};for(var m in c)if(c[f](m)){if(X[f](m)||h.paper.customAttributes[f](m)){k=true;i[m]=h.attr(m);i[m]==null&&(i[m]=W[m]);j[m]=c[m];switch(X[m]){case"along":var n=cs(c[m]),o=ct(c[m],n*!(!c.back)),p=h.getBBox();l[m]=n/d;l.tx=p.x;l.ty=p.y;l.sx=o.x;l.sy=o.y;j.rot=c.rot;j.back=c.back;j.len=n;c.rot&&(l.r=S(h.rotate())||0);break;case E:l[m]=(j[m]-i[m])/d;break;case"colour":i[m]=a.getRGB(i[m]);var q=a.getRGB(j[m]);l[m]={r:(q.r-i[m].r)/d,g:(q.g-i[m].g)/d,b:(q.b-i[m].b)/d};break;case"path":var t=bw(i[m],j[m]);i[m]=t[0];var u=t[1];l[m]=[];for(var v=0,x=i[m][w];v' + + '
' + + '' + + '' + + '' + + '

' + + '( - )

' + + '

' + + '
{{l10n.tags}}
    '; + +IriSP.Widgets.Annotation.prototype.defaults = { + annotation_type : "chap", + show_top_border : false, + site_name : "Lignes de Temps" +} + +IriSP.Widgets.Annotation.prototype.draw = function() { + this.renderTemplate(); + this.bindPopcorn("timeupdate","onTimeupdate"); + this.bindPopcorn("IriSP.Annotation.hide","hide"); + this.bindPopcorn("IriSP.Annotation.show","show"); + this.bindPopcorn("IriSP.Annotation.minimize","minimize"); + this.bindPopcorn("IriSP.Annotation.maximize","maximize"); + this.onTimeupdate(); +} + +IriSP.Widgets.Annotation.prototype.onTimeupdate = function() { + var _time = Math.floor(this.player.popcorn.currentTime() * 1000), + _list = this.getWidgetAnnotations().filter(function(_annotation) { + return _annotation.begin <= _time && _annotation.end > _time; + }); + if (_list.length) { + if (_list[0].id !== this.lastAnnotation) { + this.drawAnnotation(_list[0]); + this.player.popcorn.trigger("IriSP.Annotation.boundsChanged",[ _list[0].begin.valueOf(), _list[0].end.valueOf() ]); + } + this.player.popcorn.trigger("IriSP.Arrow.updatePosition",{widget: this.type, time: ( _list[0].begin + _list[0].end ) / 2}); + } + else { + this.lastAnnotation = false; + this.$.find(".Ldt-Annotation-Inner").addClass("Ldt-Annotation-Empty"); + this.player.popcorn.trigger("IriSP.Arrow.updatePosition",{widget: this.type, time: _time}); + this.player.popcorn.trigger("IriSP.Annotation.boundsChanged",[ _time, _time ]); + } +} + +IriSP.Widgets.Annotation.prototype.drawAnnotation = function(_annotation) { + this.lastAnnotation = _annotation.id; + var _url = (typeof _annotation.url !== "undefined" + ? _annotation.url + : (document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.namespacedId.name)); + var _text = this.l10n.watching + _annotation.title + (this.site_name ? this.l10n.on_site + this.site_name : ''); + var _tags = _annotation.getTagTexts(); + if (_tags.length) { + var _html = IriSP._(_tags).map(function(_tag) { + return '
  • ' + _tag + '
  • '; + }).join(""); + this.$.find(".Ldt-Annotation-Tags").html(_html); + this.$.find(".Ldt-Annotation-Tags-Block").removeClass("Ldt-Annotation-NoTags"); + } else { + this.$.find(".Ldt-Annotation-Tags-Block").addClass("Ldt-Annotation-NoTags"); + } + this.$.find(".Ldt-Annotation-Title").html(_annotation.title); + this.$.find(".Ldt-Annotation-Description").html(_annotation.description); + this.$.find(".Ldt-Annotation-Begin").html(_annotation.begin.toString()); + this.$.find(".Ldt-Annotation-End").html(_annotation.end.toString()); + this.$.find(".Ldt-Annotation-Fb").attr("href", "http://www.facebook.com/share.php?" + IriSP.jQuery.param({ u: _url, t: _text })); + this.$.find(".Ldt-Annotation-Twitter").attr("href", "https://twitter.com/intent/tweet?" + IriSP.jQuery.param({ url: _url, text: _text })); + this.$.find(".Ldt-Annotation-Gplus").attr("href", "https://plusone.google.com/_/+1/confirm?" + IriSP.jQuery.param({ url: _url, title: _text })); + this.$.find(".Ldt-Annotation-Inner").removeClass("Ldt-Annotation-Empty"); +} + +IriSP.Widgets.Annotation.prototype.hide = function() { + this.$.slideUp(); +} + +IriSP.Widgets.Annotation.prototype.show = function() { + this.$.slideDown(); +} + +IriSP.Widgets.Annotation.prototype.minimize = function() { + this.$.find('.Ldt-Annotation-Inner').addClass("Ldt-Annotation-Minimized"); +} + +IriSP.Widgets.Annotation.prototype.maximize = function() { + this.$.find('.Ldt-Annotation-Inner').removeClass("Ldt-Annotation-Minimized"); +} \ No newline at end of file diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/AnnotationsList.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/AnnotationsList.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,78 @@ +/* AnnotationsListWidget */ + +.Ldt-AnnotationsListWidget { +} +.Ldt-AnnotationsListWidget a { + text-decoration: none; +} +ul.Ldt-AnnotationsList-ul { + list-style: none; + padding: 2px; + margin: 0; +} +li.Ldt-AnnotationsList-li { + width: 100%; + clear: both; + margin: 2px 0; + padding: 2px 0; + min-height: 60px; +} +.Ldt-AnnotationsList-li:hover { + background: url(img/pinstripe-grey.png); +} +.Ldt-AnnotationsList-highlight { + background: #F7268E; + color: #ffffff; +} +.Ldt-AnnotationsList-ThumbContainer { + float: left; + width: 80px; + height: 50px; + text-align: center; + margin: 2px 0; +} +.Ldt-AnnotationsList-Thumbnail { + border: none; + max-width: 100%; + max-height: 100%; + margin: 0 auto; +} +.Ldt-AnnotationsList-Duration { + color: #f7268e; + float: right; + text-align: right; + font-size: 12px; + margin: 2px; +} +h3.Ldt-AnnotationsList-Title, #accordeon h3.Ldt-AnnotationsList-Title { + color: #0068c4; + font-size: 14px; + line-height: 1.2em; + margin: 0 2px 0 82px; + font-weight: bold; +} +h3.Ldt-AnnotationsList-Title a, #accordeon h3.Ldt-AnnotationsList-Title a { + color: #0068c4 ; +} +p.Ldt-AnnotationsList-Description, #accordeon p.Ldt-AnnotationsList-Description { + margin: 2px 0 2px 82px; + line-height: 1.2em; + font-size: 12px; + color: #666666; +} +ul.Ldt-AnnotationsList-Tags { + list-style: none; + padding: 0; + margin: 2px 0 8px 82px; +} +li.Ldt-AnnotationsList-Tag-Li { + display: inline-block; + margin: 2px; + background: #0068c4; + color: #fff; + padding: 2px; + font-size: 12px; +} +li.Ldt-AnnotationsList-Tag-Li:hover { + background: #F7268E; +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/AnnotationsList.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/AnnotationsList.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,227 @@ +IriSP.Widgets.AnnotationsList = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); + this.searchString = false; + this.lastIds = []; + var _this = this; + this.throttledRefresh = IriSP._.throttle(function() { + _this.refresh(false); + }, 1500); +}; + +IriSP.Widgets.AnnotationsList.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.AnnotationsList.prototype.defaults = { + /* URL when the annotations are to be reloaded from an LDT-like segment API + * e.g. http://ldt.iri.centrepompidou.fr/ldtplatform/api/ldt/segments/{{media}}/{{begin}}/{{end}}?callback=? + */ + ajax_url : false, + /* how much ms should we look before and after the current timecode in the segment API + */ + ajax_granularity : 300000, + default_thumbnail : "http://ldt.iri.centrepompidou.fr/static/site/ldt/css/imgs/video_sequence.png", + /* URL when the annotation is not in the current project, + * e.g. http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/{{media}}/{{project}}/{{annotationType}}#id={{annotation}} + */ + foreign_url : "", + cinecast_version : false, + annotation_type : false, + refresh_interval : 0, + limit_count : 10, + newest_first : false +}; + +IriSP.Widgets.AnnotationsList.prototype.template = + '
    ' + + '
      ' + + '{{#annotations}}' + + '
    • ' + + '
      ' + + '' + + '' + + '' + + '
      ' + + '
      {{begin}} - {{end}}
      ' + + '

      ' + + '{{title}}' + + '

      ' + + '

      {{description}}

      ' + + '{{#tags.length}}' + + '
        ' + + '{{#tags}}' + + '{{#.}}' + + '
      • ' + + '
        {{.}}
        ' + + '
      • ' + + '{{/.}}' + + '{{/tags}}' + + '
      ' + + '{{/tags.length}}' + + '
    • ' + + '{{/annotations}}' + + '
    ' + + '
    '; + +IriSP.Widgets.AnnotationsList.prototype.clear = function() { +}; + +IriSP.Widgets.AnnotationsList.prototype.clearWidget = function() { +}; + +IriSP.Widgets.AnnotationsList.prototype.onSearch = function(searchString) { + this.searchString = typeof searchString !== "undefined" ? searchString : ''; + var _n = this.refresh(true); + if (this.searchString) { + if (_n) { + this.player.popcorn.trigger("IriSP.search.matchFound"); + } else { + this.player.popcorn.trigger("IriSP.search.noMatchFound"); + } + } +} + +//obj.url = this.project_url + "/" + media + "/" + annotations[i].meta.project + "/" + annotations[i].meta["id-ref"] + '#id=' + annotations[i].id; + +IriSP.Widgets.AnnotationsList.prototype.ajaxSource = function() { + var _currentTime = this.player.popcorn.currentTime(), + _duration = this.source.getDuration(); + if (typeof _currentTime == "undefined") { + _currentTime = 0; + } + this.lastAjaxQuery = _currentTime; + _currentTime = Math.floor(1000 * _currentTime); + var _url = Mustache.to_html(this.ajax_url, { + media : this.source.currentMedia.namespacedId.name, + begin : Math.max(0, _currentTime - this.ajax_granularity), + end : Math.min(_duration.milliseconds, _currentTime + this.ajax_granularity) + }); + this.currentSource = this.player.loadMetadata(IriSP._.defaults({ + "url" : _url + }, this.metadata)); +} + +IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { + _forceRedraw = (typeof _forceRedraw !== "undefined" && _forceRedraw); + if (this.currentSource.status !== IriSP.Model._SOURCE_STATUS_READY) { + return 0; + } + var _this = this, + _currentTime = this.player.popcorn.currentTime(); + if (typeof _currentTime == "undefined") { + _currentTime = 0; + } + var _list = this.annotation_type ? this.currentSource.getAnnotationsByTypeTitle(this.annotation_type, true) : this.currentSource.getAnnotations(); + if (this.searchString) { + _list = _list.searchByTextFields(this.searchString); + } + if (this.limit_count) { + _list = _list.sortBy(function(_annotation) { + return Math.abs(_annotation.begin.getSeconds() - _currentTime); + }).slice(0, this.limit_count) + } + if (this.newest_first) { + _list = _list.sortBy(function(_annotation) { + return -_annotation.created.valueOf(); + }); + } else { + _list = _list.sortBy(function(_annotation) { + return _annotation.begin; + }); + } + + var _ids = _list.idIndex; + + if (_forceRedraw || !IriSP._.isEqual(_ids, this.lastIds)) { + /* This part only gets executed if the list needs updating */ + this.lastIds = _ids; + var _data = _list.map(function(_annotation) { + var _url = ( + ( typeof _annotation.url !== "undefined" && _annotation.url) + ? _annotation.url + : ( + ( typeof _this.source.projectId !== "undefined" && typeof _annotation.project !== "undefined" && _annotation.project && _this.source.projectId !== _annotation.project ) + ? Mustache.to_html( + _this.foreign_url, + { + project : _annotation.project, + media : _annotation.media.id.replace(/^.*:/,''), + annotation : _annotation.namespacedId.name, + annotationType : _annotation.annotationType.id.replace(/^.*:/,'') + } + ) + : '#id=' + _annotation.namespacedId.name + ) + ); + var _res = { + id : _annotation.id, + title : _annotation.title.replace(_annotation.description,''), + description : _annotation.description, + begin : _annotation.begin.toString(), + end : _annotation.end.toString(), + thumbnail : typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail ? _annotation.thumbnail : _this.default_thumbnail, + url : _url, + tags : _annotation.getTagTexts() + } + return _res; + }), + _html = Mustache.to_html( + this.template, + { + annotations : _data + }); + + this.$.html(_html); + + this.$.find('.Ldt-AnnotationsList-Tag-Li').click(function() { + _this.player.popcorn.trigger("IriSP.search.triggeredSearch", IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,'')); + }) + + if(this.searchString) { + var _searchRe = new RegExp('(' + this.searchString.replace(/(\W)/gm,'\\$1') + ')','gim'); + this.$.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description").each(function() { + var _$ = IriSP.jQuery(this); + _$.html(_$.text().replace(/(^\s+|\s+$)/g,'').replace(_searchRe, '$1')) + }) + } + } + + if (this.ajax_url && this.ajax_granularity) { + if (Math.abs(_currentTime - this.lastAjaxQuery) > (this.ajax_granularity / 2000)) { + this.ajaxSource(); + } + } + return _list.length; +} + +IriSP.Widgets.AnnotationsList.prototype.draw = function() { + + this.bindPopcorn("IriSP.search", "onSearch"); + this.bindPopcorn("IriSP.search.closed", "onSearch"); + this.bindPopcorn("IriSP.search.cleared", "onSearch"); + + var _this = this; + + if (this.ajax_url && this.ajax_granularity) { + this.ajaxSource(); + } else { + this.currentSource = this.source; + } + + if (this.refresh_interval) { + window.setInterval(function() { + _this.currentSource.get() + }, this.refresh_interval); + } + + var _events = [ + "IriSP.createAnnotationWidget.addedAnnotation", + "timeupdate", + "seeked", + "loadedmetadata" + ]; + for (var _i = 0; _i < _events.length; _i++) { + this.player.popcorn.listen(_events[_i], this.throttledRefresh); + } + + this.throttledRefresh(); + +}; diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Arrow.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Arrow.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,105 @@ +IriSP.Widgets.Arrow = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); + this.current_pilot_widget = this.pilot_widget +}; + +IriSP.Widgets.Arrow.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Arrow.prototype.defaults = { + arrow_height : 16, + arrow_width : 24, + base_height : 0, + base_curve : 0, + fill_url: IriSP.widgetsDir + '/img/pinstripe.png', + fill_color: "#ffffff", //Gradients can be used, e.g. "90-#000-#fff" for vertical white-to-black + stroke_color: "#b7b7b7", + stroke_width: 1.5, + animation_speed: 20, + pilot_widget: "Annotation" +} + +IriSP.Widgets.Arrow.prototype.draw = function() { + this.height = this.arrow_height + this.base_height; + this.$.addClass("Ldt-Arrow").css({ + height: this.height + "px", + "margin-top": "1px" + }); + this.paper = new Raphael(this.container, this.width, this.height ); + window.myArrow = this; + this.svgArrow = this.paper.path('M0,' + this.height + 'L' + this.width + ',' + this.height); + this.svgArrow.attr({ + stroke: this.stroke_color, + "stroke-width": this.stroke_width, + fill: this.fill_url ? ( 'url(' + this.fill_url + ')' ) : this.fill_color + }); + this.moveTo(0); + this.bindPopcorn("IriSP.Arrow.updatePosition","onUpdatePosition"); + this.bindPopcorn("IriSP.Arrow.takeover","onTakeover"); + this.bindPopcorn("IriSP.Arrow.release","onRelease"); +} + +IriSP.Widgets.Arrow.prototype.drawAt = function(_x) { + _x = Math.floor(Math.max(0, Math.min(_x, this.width))); + var _d = 'M0,' + this.height + + 'L0,' + Math.min( this.height, this.arrow_height + this.base_curve) + + 'Q0,' + this.arrow_height + + ' ' + Math.max(0, Math.min(this.base_curve, _x - this.arrow_width / 2)) + ',' + this.arrow_height + + 'L' + Math.max(0, _x - this.arrow_width / 2) + ',' + this.arrow_height + + 'L' + Math.max(0, _x - this.arrow_width / 2) + ',' + Math.min(this.arrow_height, 2 * this.arrow_height * _x / this.arrow_width) + + 'L' + _x + ',0' + + 'L' + Math.min(this.width, _x + this.arrow_width / 2) + ',' + Math.min(this.arrow_height, 2 * this.arrow_height * ( this.width - _x ) / this.arrow_width) + + 'L' + Math.min(this.width, _x + this.arrow_width / 2) + ',' + this.arrow_height + + 'L' + Math.min(this.width, Math.max(this.width - this.base_curve, _x + this.arrow_width / 2)) + ',' + this.arrow_height + + 'Q' + this.width + ',' + this.arrow_height + + ' ' + this.width + ',' + Math.min( this.height, this.arrow_height + this.base_curve) + + 'L' + this.width + ',' + this.height; + this.svgArrow.attr({ + path: _d + }); +} + +IriSP.Widgets.Arrow.prototype.moveTo = function(_x) { + this.targetX = Math.floor(Math.max(0, Math.min(_x, this.width))); + if (typeof this.animInterval === "undefined") { + this.animInterval = window.setInterval( + this.functionWrapper("increment"), + 40 + ) + } + this.increment(); +} + +IriSP.Widgets.Arrow.prototype.increment = function() { + if (typeof this.currentX === "undefined") { + this.currentX = this.targetX; + } + if (this.currentX < this.targetX) { + this.currentX = Math.min(this.targetX, this.currentX + this.animation_speed); + } + if (this.currentX > this.targetX) { + this.currentX = Math.max(this.targetX, this.currentX - this.animation_speed); + } + if (this.currentX === this.targetX) { + window.clearInterval(this.animInterval); + this.animInterval = undefined; + } + this.drawAt(this.currentX); +} + +IriSP.Widgets.Arrow.prototype.onUpdatePosition = function(_param) { + if (_param.widget === this.current_pilot_widget) { + if (typeof _param.x !== "undefined") { + this.moveTo(_param.x); + } else { + this.moveTo(this.width * _param.time / this.source.getDuration()); + } + } +} + +IriSP.Widgets.Arrow.prototype.onTakeover = function(_widget) { + this.current_pilot_widget = _widget; +} + +IriSP.Widgets.Arrow.prototype.onRelease = function(_widget) { + this.current_pilot_widget = this.pilot_widget; +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Controller.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Controller.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,178 @@ +/* Player Widget */ + +.Ldt-Ctrl { + font-size: 10px; + font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif"; + background:url('img/player_gradient.png') repeat-x transparent ; + height: 25px; + border: 1px solid #b6b8b8; + position: relative; +} + +.Ldt-Ctrl-Left { + float:left; +} + +.Ldt-Ctrl-Right { + float: right; +} + +.Ldt-Ctrl-button { + float: left; + width: 30px; height: 25px; + background: url('img/player-sprites.png'); + cursor: pointer; +} + +.Ldt-Ctrl-spacer { + float: left; width: 1px; height: 25px; background: #b6b8b8; +} + +.Ldt-Ctrl-Play { + margin: 0 15px; +} + +.Ldt-Ctrl-Play-PlayState { + background-position: 0 0; +} + +.Ldt-Ctrl-Play-PlayState:hover { + background-position: 0 -25px; +} + +.Ldt-Ctrl-Play-PlayState:active { + background-position: 0 -50px; +} + +.Ldt-Ctrl-Play-PauseState { + background-position: -30px 0; +} + +.Ldt-Ctrl-Play-PauseState:hover { + background-position: -30px -25px; +} + +.Ldt-Ctrl-Play-PauseState:active { + background-position: -30px -50px; +} + +.Ldt-Ctrl-Annotate { + margin: 0 2px; + background-position: -60px 0; +} + +.Ldt-Ctrl-Annotate:hover { + background-position: -60px -25px; +} + +.Ldt-Ctrl-Annotate:active { + background-position: -60px -50px; +} + +.Ldt-Ctrl-SearchBtn { + margin: 0 2px; + background-position: -90px 0; +} + +.Ldt-Ctrl-SearchBtn:hover { + background-position: -90px -25px; +} + +.Ldt-Ctrl-SearchBtn:active { + background-position: -90px -50px; +} + +.Ldt-Ctrl-Search { + display: none; + width: 165px; + height: 25px; + border: 1px; + border-color: #CFCFCF; + float: left; + text-align: center; +} + +.Ldt-Ctrl-Time { + float: left; + margin: 5px; + font-size: 12px; + font-family: Arial, Verdana, sans-serif; +} + +.Ldt-Ctrl-Time-Elapsed { + float: left; + color: #4a4a4a; +} + +.Ldt-Ctrl-Time-Separator { + margin: 0 4px; + float: left; +} + +.Ldt-Ctrl-Time-Total { + float: left; + color: #b2b2b2; +} + +.Ldt-Ctrl-Sound { + margin: 0 2px; +} + +.Ldt-Ctrl-Sound-Full { + background-position: -120px 0; +} + +.Ldt-Ctrl-Sound-Full:hover { + background-position: -120px -25px; +} + +.Ldt-Ctrl-Sound-Full:active { + background-position: -120px -50px; +} + +.Ldt-Ctrl-Sound-Mute { + background-position: -150px 0; +} + +.Ldt-Ctrl-Sound-Mute:hover { + background-position: -150px -25px; +} + +.Ldt-Ctrl-Sound-Mute:active { + background-position: -150px -50px; +} + +.Ldt-Ctrl-Sound-Half { + background-position: -180px 0; +} + +.Ldt-Ctrl-Sound-Half:hover { + background-position: -180px -25px; +} + +.Ldt-Ctrl-Sound-Half:active { + background-position: -180px -50px; +} + +.Ldt-Ctrl-Volume-Control { + display: none; + position: absolute; + background:url('img/player_gradient.png') repeat-x transparent ; + height: 25px; + width: 100px; top: 25px; right: -1px; z-index: 100; + padding: 0 2px; + border: 1px solid #b6b8b8; +} + +.Ldt-Ctrl-Volume-Bar { + height: 5px; margin: 9px 3px 0; background: #cccccc; border: 1px solid #999999; border-radius: 2px; +} + +.Ldt-Ctrl-Volume-Control .ui-slider-handle { + width: 6px; height: 19px; background: #a8a8a8; border: 1px solid #999999; border-radius: 2px; top: -8px; margin-left: -4px; + cursor: pointer; +} + +.Ldt-Ctrl-Volume-Control:hover .ui-slider-handle { + background: #F7268E; +} \ No newline at end of file diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Controller.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Controller.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,296 @@ +/* Displays Play and Pause buttons, Search Button and Form, Volume Control */ + +IriSP.Widgets.Controller = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); + + this._searchLastValue = ""; +}; + +IriSP.Widgets.Controller.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Controller.prototype.defaults = { + disable_annotate_btn: false, + disable_search_btn: false +} + +IriSP.Widgets.Controller.prototype.template = + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '{{^disable_annotate_btn}}' + + '
    ' + + '
    ' + + '{{/disable_annotate_btn}}' + + '{{^disable_search_btn}}' + + '
    ' + + '
    ' + + '{{/disable_search_btn}}' + + '' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    00:00
    ' + + '
    /
    ' + + '
    00:00
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    '; + +IriSP.Widgets.Controller.prototype.messages = { + en: { + play_pause: "Play/Pause", + mute_unmute: "Mute/Unmute", + play: "Play", + pause: "Pause", + mute: "Mute", + unmute: "Unmute", + annotate: "Annotate", + search: "Search", + elapsed_time: "Elapsed time", + total_time: "Total time", + volume: "Volume", + volume_control: "Volume control" + }, + fr: { + play_pause: "Lecture/Pause", + mute_unmute: "Couper/Activer le son", + play: "Lecture", + pause: "Pause", + mute: "Couper le son", + unmute: "Activer le son", + annotate: "Annoter", + search: "Rechercher", + elapsed_time: "Durée écoulée", + total_time: "Durée totale", + volume: "Niveau sonore", + volume_control: "Réglage du niveau sonore" + } +}; + +IriSP.Widgets.Controller.prototype.draw = function() { + var _this = this; + this.renderTemplate(); + + // Define blocks + this.$playButton = this.$.find(".Ldt-Ctrl-Play"); + this.$searchBlock = this.$.find(".Ldt-Ctrl-Search"); + this.$searchInput = this.$.find(".Ldt-Ctrl-SearchInput"); + this.$volumeBar = this.$.find(".Ldt-Ctrl-Volume-Bar"); + + // handle events + this.bindPopcorn("play","playButtonUpdater"); + this.bindPopcorn("pause","playButtonUpdater"); + this.bindPopcorn("volumechange","volumeUpdater"); + this.bindPopcorn("timeupdate","timeDisplayUpdater"); + this.bindPopcorn("loadedmetadata","timeDisplayUpdater"); + this.bindPopcorn("IriSP.search.matchFound","searchMatch"); + this.bindPopcorn("IriSP.search.noMatchFound","searchNoMatch"); + this.bindPopcorn("IriSP.search.triggeredSearch","triggeredSearch"); + + // handle clicks + this.$playButton.click(this.functionWrapper("playHandler")); + + this.$.find(".Ldt-Ctrl-Annotate").click(function() { + _this.player.popcorn.trigger("IriSP.Player.AnnotateButton.clicked"); + }); + this.$.find(".Ldt-Ctrl-SearchBtn").click(this.functionWrapper("searchButtonHandler")); + + this.$searchInput.keyup(this.functionWrapper("searchHandler") ); + + var _volctrl = this.$.find(".Ldt-Ctrl-Volume-Control"); + this.$.find('.Ldt-Ctrl-Sound') + .click(this.functionWrapper("muteHandler")) + .mouseover(function() { + _volctrl.show(); + }) + .mouseout(function() { + _volctrl.hide(); + }); + _volctrl.mouseover(function() { + _volctrl.show(); + }).mouseout(function() { + _volctrl.hide(); + }); + + + // Allow Volume Cursor Dragging + this.$volumeBar.slider({ + slide: function(event, ui) { + _this.$volumeBar.attr("title",_this.l10n.volume+': ' + ui.value + '%'); + _this.player.popcorn.volume(ui.value / 100); + }, + stop: this.functionWrapper("volumeUpdater") + }); + + // trigger an IriSP.Player.MouseOver to the widgets that are interested (i.e : sliderWidget) + this.$.hover( + function() { + _this.player.popcorn.trigger("IriSP.Player.MouseOver"); + }, + function() { + _this.player.popcorn.trigger("IriSP.Player.MouseOut"); + }); + setTimeout(this.functionWrapper("volumeUpdater"), 1000); + /* some players - including jwplayer - save the state of the mute button between sessions */ +}; + +/* Update the elasped time div */ +IriSP.Widgets.Controller.prototype.timeDisplayUpdater = function() { + var _curTime = this.player.popcorn.roundTime(); + if (typeof this._previousSecond !== "undefined" && _curTime === this._previousSecond) { + return; + } + + // we get it at each call because it may change. + var _totalTime = this.source.getDuration(), + _elapsedTime = new IriSP.Model.Time(); + + _elapsedTime.setSeconds(_curTime); + + this.$.find(".Ldt-Ctrl-Time-Elapsed").html(_elapsedTime.toString()); + this.$.find(".Ldt-Ctrl-Time-Total").html(_totalTime.toString()); + this._previousSecond = _curTime; +}; + +/* update the icon of the button - separate function from playHandler + because in some cases (for instance, when the user directly clicks on + the jwplayer window) we have to change the icon without playing/pausing +*/ +IriSP.Widgets.Controller.prototype.playButtonUpdater = function() { + + var status = this.player.popcorn.media.paused; + + if (status) { + /* the background sprite is changed by adding/removing the correct classes */ + this.$playButton + .attr("title", this.l10n.play) + .removeClass("Ldt-Ctrl-Play-PauseState") + .addClass("Ldt-Ctrl-Play-PlayState"); + } else { + this.$playButton + .attr("title", this.l10n.pause) + .removeClass("Ldt-Ctrl-Play-PlayState") + .addClass("Ldt-Ctrl-Play-PauseState"); + } +}; + + +IriSP.Widgets.Controller.prototype.playHandler = function() { + + var status = this.player.popcorn.media.paused; + + if (status) { + this.player.popcorn.play(); + } else { + this.player.popcorn.pause(); + } +}; + +IriSP.Widgets.Controller.prototype.muteHandler = function() { + this.player.popcorn.mute(!this.player.popcorn.muted()); +}; + +IriSP.Widgets.Controller.prototype.volumeUpdater = function() { + var _muted = this.player.popcorn.muted(), + _vol = this.player.popcorn.volume(); + if (_vol === false) { + _vol = .5; + } + var _soundCtl = this.$.find(".Ldt-Ctrl-Sound"); + _soundCtl.removeClass("Ldt-Ctrl-Sound-Mute Ldt-Ctrl-Sound-Half Ldt-Ctrl-Sound-Full"); + if (_muted) { + _soundCtl.attr("title", this.l10n.unmute) + .addClass("Ldt-Ctrl-Sound-Mute"); + } else { + _soundCtl.attr("title", this.l10n.mute) + .addClass(_vol < .5 ? "Ldt-Ctrl-Sound-Half" : "Ldt-Ctrl-Sound-Full" ) + } + this.$volumeBar.slider("value", _muted ? 0 : 100 * _vol); +}; + +IriSP.Widgets.Controller.prototype.showSearchBlock = function() { + this.$searchBlock.show("blind", { direction: "horizontal"}, 100); + this.$searchInput.css('background-color','#fff'); + + this.$searchInput.focus(); + + // we need this variable because some widgets can find a match in + // their data while at the same time others don't. As we want the + // search field to become green when there's a match, we need a + // variable to remember that we had one. + this._positiveMatch = false; + + // tell the world the field is open + this.player.popcorn.trigger("IriSP.search.open"); +}; + +IriSP.Widgets.Controller.prototype.hideSearchBlock = function() { + this._searchLastValue = this.$searchInput.val(); + this.$searchInput.val(''); + this.$searchBlock.hide("blind", { direction: "horizontal"}, 75); + + this._positiveMatch = false; + + this.player.popcorn.trigger("IriSP.search.closed"); +}; + +/** react to clicks on the search button */ +IriSP.Widgets.Controller.prototype.searchButtonHandler = function() { + if ( this.$searchBlock.is(":hidden") ) { + this.showSearchBlock(); + this.$searchInput.val(this._searchLastValue); + this.player.popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural. + } else { + this.hideSearchBlock(); + } +}; + +/** this handler is called whenever the content of the search + field changes */ +IriSP.Widgets.Controller.prototype.searchHandler = function() { + this._searchLastValue = this.$searchInput.val(); + this._positiveMatch = false; + + // do nothing if the search field is empty, instead of highlighting everything. + if (this._searchLastValue == "") { + this.player.popcorn.trigger("IriSP.search.cleared"); + this.$searchInput.css('background-color',''); + } else { + this.player.popcorn.trigger("IriSP.search", this._searchLastValue); + } +}; + +/** + handler for the IriSP.search.found message, which is sent by some views when they + highlight a match. +*/ +IriSP.Widgets.Controller.prototype.searchMatch = function() { + this._positiveMatch = true; + this.$searchInput.css('background-color','#e1ffe1'); +}; + +/** the same, except that no value could be found */ +IriSP.Widgets.Controller.prototype.searchNoMatch = function() { + if (this._positiveMatch !== true) { + this.$searchInput.css('background-color', "#d62e3a"); + } +}; + +/** react to an IriSP.Player.triggeredSearch - that is, when + a widget ask the.Player to do a search on his behalf */ +IriSP.Widgets.Controller.prototype.triggeredSearch = function(searchString) { + this.showSearchBlock(); + this.$searchInput.attr('value', searchString); + this.player.popcorn.trigger("IriSP.search", searchString); // trigger the search to make it more natural. +}; + + diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/LdtPlayer-core.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/LdtPlayer-core.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,15 @@ +/* Base classes */ + +.Ldt-Loader { + min-height: 128px; + background:url(img/loader.gif) center no-repeat; + text-indent: -9999px; + position: absolute; + width: 100%; +} + +.Ldt-Widget { + font-family: Arial, Helvetica, sans-serif; + color: black; + font-size: 12px; +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/LdtPlayer-core.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/LdtPlayer-core.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,2045 @@ +/* + * + * Copyright 2010-2012 Institut de recherche et d'innovation + * contributor(s) : Karim Hamidou, Samuel Huron, Raphael Velt, Thibaut Cavalie + * + * 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(o){var K=o.$LAB,y="UseLocalXHR",z="AlwaysPreserveOrder",u="AllowDuplicates",A="CacheBust",B="BasePath",C=/^[^?#]*\//.exec(location.href)[0],D=/^\w+\:\/\/\/?[^\/]+/.exec(C)[0],i=document.head||document.getElementsByTagName("head"),L=(o.opera&&Object.prototype.toString.call(o.opera)=="[object Opera]")||("MozAppearance"in document.documentElement.style),q=document.createElement("script"),E=typeof q.preload=="boolean",r=E||(q.readyState&&q.readyState=="uninitialized"),F=!r&&q.async===true,M=!r&&!F&&!L;function G(a){return Object.prototype.toString.call(a)=="[object Function]"}function H(a){return Object.prototype.toString.call(a)=="[object Array]"}function N(a,c){var b=/^\w+\:\/\//;if(/^\/\/\/?/.test(a)){a=location.protocol+a}else if(!b.test(a)&&a.charAt(0)!="/"){a=(c||"")+a}return b.test(a)?a:((a.charAt(0)=="/"?D:C)+a)}function s(a,c){for(var b in a){if(a.hasOwnProperty(b)){c[b]=a[b]}}return c}function O(a){var c=false;for(var b=0;b0){for(var a=0;a=0;){d=n.shift();a=a[d.type].apply(null,d.args)}return a},noConflict:function(){o.$LAB=K;return m},sandbox:function(){return J()}};return m}o.$LAB=J();(function(a,c,b){if(document.readyState==null&&document[a]){document.readyState="loading";document[a](c,b=function(){document.removeEventListener(c,b,false);document.readyState="complete"},false)}})("addEventListener","DOMContentLoaded")})(this);/* init.js - initialization and configuration of Popcorn and the widgets +*/ + +if (typeof window.IriSP === "undefined") { + IriSP = {}; +} + +/* The Metadataplayer Object, single point of entry, replaces IriSP.init_player */ + +IriSP.Metadataplayer = function(config, video_metadata) { + for (var key in IriSP.guiDefaults) { + if (IriSP.guiDefaults.hasOwnProperty(key) && !config.gui.hasOwnProperty(key)) { + config.gui[key] = IriSP.guiDefaults[key] + } + } + var _container = document.getElementById(config.gui.container); + _container.innerHTML = '

    Loading... Chargement...

    '; + this.video_metadata = video_metadata; + this.sourceManager = new IriSP.Model.Directory(); + this.config = config; + this.loadLibs(); +} + +IriSP.Metadataplayer.prototype.toString = function() { + return 'A Metadataplayer in DIV #' + this.config.gui.container; +} + +IriSP.Metadataplayer.prototype.loadLibs = function() { + + var $L = $LAB.script(IriSP.getLib("underscore")).script(IriSP.getLib("Mustache")).script(IriSP.getLib("jQuery")).script(IriSP.getLib("swfObject")).wait().script(IriSP.getLib("jQueryUI")); + + if(this.config.player.type === "jwplayer" || this.config.player.type === "allocine" || this.config.player.type === "dailymotion") { + // load our popcorn.js lookalike + $L.script(IriSP.getLib("jwplayer")); + } else { + // load the real popcorn + $L.script(IriSP.getLib("popcorn")).script(IriSP.getLib("popcorn.code")); + // load plugins if necessary + if(this.config.player.type === "youtube") { + $L.script(IriSP.getLib("popcorn.youtube")); + } + if(this.config.player.type === "vimeo"){ + $L.script(IriSP.getLib("popcorn.vimeo")); + } + } + + /* widget specific requirements */ + for(var _i = 0; _i < this.config.gui.widgets.length; _i++) { + var _t = this.config.gui.widgets[_i].type; + if (typeof IriSP.widgetsRequirements[_t] !== "undefined" && typeof IriSP.widgetsRequirements[_t].requires !== "undefined") { + $L.script(IriSP.getLib(IriSP.widgetsRequirements[_t].requires)); + } + } + + var _this = this; + + $L.wait(function() { + IriSP.jQuery = window.jQuery.noConflict(); + IriSP._ = window._.noConflict(); + + IriSP.loadCss(IriSP.getLib("cssjQueryUI")) + IriSP.loadCss(_this.config.gui.css); + + _this.onLibsLoaded(); + + }); +} + +IriSP.Metadataplayer.prototype.onLibsLoaded = function() { + this.videoData = this.loadMetadata(this.video_metadata); + this.$ = IriSP.jQuery('#' + this.config.gui.container); + this.$.css({ + "width": this.config.gui.width, + "clear": "both" + }); + if (typeof this.config.gui.height !== "undefined") { + this.$.css("height", this.config.gui.height); + } + + var _this = this; + this.videoData.onLoad(function() { + _this.onVideoDataLoaded(); + }); +} + +IriSP.Metadataplayer.prototype.loadMetadata = function(_metadataInfo) { + if (typeof _metadataInfo.serializer === "undefined" && typeof _metadataInfo.format !== "undefined") { + _metadataInfo.serializer = IriSP.serializers[_metadataInfo.format]; + } + if (typeof _metadataInfo.url === "undefined" && typeof _metadataInfo.src !== "undefined") { + _metadataInfo.url = _metadataInfo.src; + } + if (typeof _metadataInfo.url !== "undefined" && typeof _metadataInfo.serializer !== "undefined") { + return this.sourceManager.remoteSource(_metadataInfo); + } else { + return this.sourceManager.newLocalSource(_metadataInfo); + } +} + +IriSP.Metadataplayer.prototype.onVideoDataLoaded = function() { + if (typeof this.videoData !== "undefined" && typeof this.config.player.video === "undefined") { + var _media = this.videoData.currentMedia; + if (typeof _media !== "undefined") { + this.config.player.video = _media.video; + if (typeof _media.streamer !== "undefined") { + this.config.player.streamer = _media.streamer; + this.config.player.video = _media.video.replace(_media.streamer,''); + } + } + + } + this.configurePopcorn(); + this.widgets = []; + var _this = this; + for(var i = 0; i < this.config.gui.widgets.length; i++) { + this.loadWidget(this.config.gui.widgets[i], function(_widget) { + _this.widgets.push(_widget) + }); + }; + this.$.find('.Ldt-Loader').detach(); +} + +IriSP.Metadataplayer.prototype.loadWidget = function(_widgetConfig, _callback) { + /* Creating containers if needed */ + if (typeof _widgetConfig.container === "undefined") { + var _divs = this.layoutDivs(_widgetConfig.type); + _widgetConfig.container = _divs[0]; + } + + var _this = this; + + if (typeof IriSP.Widgets[_widgetConfig.type] !== "undefined") { + IriSP._.defer(function() { + _callback(new IriSP.Widgets[_widgetConfig.type](_this, _widgetConfig)); + }); + } else { + /* Loading Widget CSS */ + if (typeof IriSP.widgetsRequirements[_widgetConfig.type] === "undefined" || typeof IriSP.widgetsRequirements[_widgetConfig.type].noCss === "undefined" || !IriSP.widgetsRequirements[_widgetConfig.type].noCss) { + IriSP.loadCss(IriSP.widgetsDir + '/' + _widgetConfig.type + '.css'); + } + /* Loading Widget JS */ + $LAB.script(IriSP.widgetsDir + '/' + _widgetConfig.type + '.js').wait(function() { + _callback(new IriSP.Widgets[_widgetConfig.type](_this, _widgetConfig)); + }); + } +} + +IriSP.Metadataplayer.prototype.configurePopcorn = function() { + var pop, + ret = this.layoutDivs("video"), + containerDiv = ret[0], + spacerDiv = ret[1]; + + switch(this.config.player.type) { + /* + todo : dynamically create the div/video tag which + will contain the video. + */ + case "html5": + var tmpId = Popcorn.guid("video"); + IriSP.jQuery("#" + containerDiv).append(""); + + if(options.hasOwnProperty("width")) + IriSP.jQuery("#" + containerDiv).css("width", this.config.player.width); + + if(options.hasOwnProperty("height")) + IriSP.jQuery("#" + containerDiv).css("height", this.config.player.height); + pop = Popcorn("#" + tmpId); + break; + + case "jwplayer": + var opts = IriSP.jQuery.extend({}, this.config.player); + delete opts.container; + delete opts.type; + opts.file = opts.video; + delete opts.video; + + if(!opts.hasOwnProperty("flashplayer")) { + opts.flashplayer = IriSP.jwplayer_swf_path; + } + + if(!opts.hasOwnProperty("controlbar.position")) { + opts["controlbar.position"] = "none"; + } + pop = new IriSP.PopcornReplacement.jwplayer("#" + containerDiv, opts); + break; + + case "youtube": + var opts = IriSP.jQuery.extend({}, this.config.player); + delete opts.container; + opts.controls = 0; + opts.autostart = false; + // Popcorn.youtube wants us to specify the size of the player in the style attribute of its container div. + IriSP.jQuery("#" + containerDiv).css({ + width : opts.width + "px", + height : opts.height + "px" + }) + pop = Popcorn.youtube("#" + containerDiv, opts.video, opts); + break; + + case "dailymotion": + pop = new IriSP.PopcornReplacement.dailymotion("#" + containerDiv, this.config.player); + break; + + case "allocine": + /* pass the options as-is to the allocine player and let it handle everything */ + pop = new IriSP.PopcornReplacement.allocine("#" + containerDiv, this.config.player); + break; + + default: + pop = undefined; + }; + + this.popcorn = pop; +} + +/** 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.Metadataplayer.prototype.layoutDivs = function(_name) { + if (typeof(_name) === "undefined") { + _name = ""; + } + var newDiv = IriSP._.uniqueId(this.config.gui.container + "_widget_" + _name + "_"), + spacerDiv = IriSP._.uniqueId("LdtPlayer_spacer_"), + divHtml = IriSP.jQuery('
    ') + .attr("id",newDiv) + .css({ + width: this.config.gui.width + "px", + position: "relative", + clear: "both" + }), + spacerHtml = IriSP.jQuery('
    ') + .attr("id",spacerDiv) + .css({ + width: this.config.gui.width + "px", + height: this.config.gui.spacer_div_height + "px", + position: "relative", + clear: "both" + }); + + this.$.append(divHtml); + this.$.append(spacerHtml); + + return [newDiv, spacerDiv]; +}; +/* utils.js - various utils that don't belong anywhere else */ + +IriSP.jqEscape = function(_text) { + return text.replace(/(:|\.)/g,'\\$1'); +} + +IriSP.getLib = function(lib) { + if (IriSP.libFiles.useCdn && typeof IriSP.libFiles.cdn[lib] == "string") { + return IriSP.libFiles.cdn[lib]; + } + if (typeof IriSP.libFiles.locations[lib] == "string") { + return IriSP.libFiles.locations[lib]; + } + if (typeof IriSP.libFiles.inDefaultDir[lib] == "string") { + return IriSP.libFiles.defaultDir + '/' + IriSP.libFiles.inDefaultDir[lib]; + } +} + +IriSP.loadCss = function(_cssFile) { + IriSP.jQuery("", { + rel : "stylesheet", + type : "text/css", + href : _cssFile + }).appendTo('head'); +}/* wrapper that simulates popcorn.js because + popcorn is a bit unstable at the time */ + +IriSP.PopcornReplacement = { +}; + +/** base class for our popcorn-compatible players. + */ +IriSP.PopcornReplacement.player = function(container, options) { + /* the jwplayer calls the callbacks in the global space so we need to + preserve them this way */ + if (typeof IriSP._ === "undefined") { + return; + } + + this.callbacks = { + onReady: IriSP._.bind(this.__initApi, this), + onTime: IriSP._.bind(this.__timeHandler, this), + onPlay: IriSP._.bind(this.__playHandler, this), + onPause: IriSP._.bind(this.__pauseHandler, this), + onSeek: IriSP._.bind(this.__seekHandler, this) + }; + + this.media = { + "paused": true, + "muted": false + }; + + this.container = container.slice(1); //eschew the '#' + + this.msgPump = {}; /* dictionnary used to receive and send messages */ + this.__codes = []; /* used to schedule the execution of a piece of code in + a segment (similar to the popcorn.code plugin). */ + + this._options = options; + +}; + +IriSP.PopcornReplacement.player.prototype.listen = function(msg, callback) { + if (!this.msgPump.hasOwnProperty(msg)) + this.msgPump[msg] = []; + + this.msgPump[msg].push(callback); +}; + +IriSP.PopcornReplacement.player.prototype.trigger = function(msg, params) { + if (!this.msgPump.hasOwnProperty(msg)) + return; + + var d = this.msgPump[msg]; + + for(var i = 0; i < d.length; i++) { + d[i].call(window, params); + } + +}; + +IriSP.PopcornReplacement.player.prototype.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; +}; + +/** init the api after that flash player has been setup - called by the callback + defined by the embedded flash player +*/ +IriSP.PopcornReplacement.player.prototype.__initApi = function() { + this.trigger("loadedmetadata"); // we've done more than loading metadata of course, + // but popcorn doesn't need to know more. + this.media.muted = this.playerFns.getMute(); + /* some programmed segments are supposed to be run at the beginning */ + var i = 0; + for(i = 0; i < this.__codes.length; i++) { + var c = this.__codes[i]; + if (0 == c.start) { + c.onStart(); + } + + if (0 == c.end) { + c.onEnd(); + } + } +}; + +IriSP.PopcornReplacement.player.prototype.currentTime = function(time) { + if (typeof(time) === "undefined") { + return this.playerFns.getPosition(); + } else { + var currentTime = +time; + this.playerFns.seek(currentTime); + return currentTime; + } +}; + +IriSP.PopcornReplacement.player.prototype.play = function() { + this.media.paused = false; + this.trigger("play"); + //IriSP.PopcornReplacement.trigger("playing"); + this.playerFns.play(); +}; + +IriSP.PopcornReplacement.player.prototype.pause = function() { +// if ( !this.media.paused ) { + this.media.paused = true; + this.trigger( "pause" ); + this.playerFns.pause(); +// } +}; + +IriSP.PopcornReplacement.player.prototype.muted = function(val) { + if (typeof(val) !== "undefined") { + + if (this.playerFns.getMute() !== val) { + if (val) { + this.playerFns.setMute(true); + this.media.muted = true; + } else { + this.playerFns.setMute(false); + this.media.muted = false; + } + + this.trigger( "volumechange" ); + } + + return this.playerFns.getMute(); + } else { + return this.playerFns.getMute(); + } +}; + +IriSP.PopcornReplacement.player.prototype.volume = function(val) { + if (typeof this.playerFns.getVolume == "undefined" || typeof this.playerFns.setVolume == "undefined") { + return false; + } + var _vol = this.playerFns.getVolume(); + if (typeof(val) !== "undefined" && parseFloat(val) !== NaN) { + val = Math.max(0, Math.min(1, val)); + if (parseFloat(val) != parseFloat(_vol)) { + this.playerFns.setVolume(val); + this.trigger("volumechange"); + _vol = this.playerFns.getVolume(); + } + } + return _vol; +}; + +IriSP.PopcornReplacement.player.prototype.mute = IriSP.PopcornReplacement.player.prototype.muted; + +IriSP.PopcornReplacement.player.prototype.code = function(options) { + this.__codes.push(options); + return this; +}; + +/* called everytime the player updates itself + (onTime event) + */ + +IriSP.PopcornReplacement.player.prototype.__timeHandler = function(event) { + var pos = event.position; + + var i = 0; + for(i = 0; i < this.__codes.length; i++) { + var c = this.__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(); + } + + } + + this.trigger("timeupdate"); +}; + +IriSP.PopcornReplacement.player.prototype.__seekHandler = function(event) { + var i = 0; + + for(i = 0; i < this.__codes.length; i++) { + var c = this.__codes[i]; + + if (event.position >= c.start && event.position < c.end) { + c.onEnd(); + } + } + + for(i = 0; i < this.__codes.length; i++) { + var c = this.__codes[i]; + + if (typeof(event.offset) === "undefined") + event.offset = 0; + + if (event.offset >= c.start && event.offset < c.end) { + c.onStart(); + } + + } + + /* this signal sends as an extra argument the position in the video. + As far as I know, this argument is not provided by popcorn */ + this.trigger("seeked", event.offset); +}; + +IriSP.PopcornReplacement.player.prototype.__playHandler = function(event) { + this.media.paused = false; + this.trigger("play"); +}; + +IriSP.PopcornReplacement.player.prototype.__pauseHandler = function(event) { + this.media.paused = true; + this.trigger("pause"); +}; + +IriSP.PopcornReplacement.player.prototype.roundTime = function() { + var currentTime = this.currentTime(); + return Math.round(currentTime); +};/* model.js is where data is stored in a standard form, whatever the serializer */ + +IriSP.Model = { + _SOURCE_STATUS_EMPTY : 0, + _SOURCE_STATUS_WAITING : 1, + _SOURCE_STATUS_READY : 2, + _ID_AUTO_INCREMENT : 0, + getUID : function() { + return "autoid-" + (++this._ID_AUTO_INCREMENT); + }, + regexpFromTextOrArray : function(_textOrArray) { + function escapeText(_text) { + return _text.replace(/([\\\*\+\?\|\{\[\}\]\(\)\^\$\.\#\/])/gm, '\\$1'); + } + return new RegExp( '(' + + ( + typeof _textOrArray === "string" + ? escapeText(_textOrArray) + : IriSP._(_textOrArray).map(escapeText).join("|") + ) + + ')', + 'gim' + ); + }, + isoToDate : function(_str) { + // http://delete.me.uk/2005/03/iso8601.html + var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"; + var d = _str.match(new RegExp(regexp)); + + var offset = 0; + var date = new Date(d[1], 0, 1); + + if (d[3]) { date.setMonth(d[3] - 1); } + if (d[5]) { date.setDate(d[5]); } + if (d[7]) { date.setHours(d[7]); } + if (d[8]) { date.setMinutes(d[8]); } + if (d[10]) { date.setSeconds(d[10]); } + if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); } + if (d[14]) { + offset = (Number(d[16]) * 60) + Number(d[17]); + offset *= ((d[15] == '-') ? 1 : -1); + } + + offset -= date.getTimezoneOffset(); + time = (Number(date) + (offset * 60 * 1000)); + var _res = new Date(); + _res.setTime(Number(time)); + return _res; + }, + dateToIso : function(d) { + function pad(n){return n<10 ? '0'+n : n} + return d.getUTCFullYear()+'-' + + pad(d.getUTCMonth()+1)+'-' + + pad(d.getUTCDate())+'T' + + pad(d.getUTCHours())+':' + + pad(d.getUTCMinutes())+':' + + pad(d.getUTCSeconds())+'Z' + } +} + +/* + * IriSP.Model.List is a class for a list of elements (e.g. annotations, medias, etc. that each have a distinct ID) + */ +IriSP.Model.List = function(_directory) { + Array.call(this); + this.directory = _directory; + this.idIndex = []; + if (typeof _directory == "undefined") { + throw "Error : new IriSP.Model.List(directory): directory is undefined"; + } +} + +IriSP.Model.List.prototype = new Array(); + +IriSP.Model.List.prototype.getElement = function(_id) { + var _index = IriSP._(this.idIndex).indexOf(_id); + if (_index !== -1) { + return this[_index]; + } else { + var _un = _id.replace(/.*:/); + return IriSP._(this.idIndex).find(function(_i) { + return _i.replace(/.*:/) === _un; + }); + } +} + +IriSP.Model.List.prototype.hasId = function(_id) { + return (IriSP._(this.idIndex).indexOf(_id) !== -1); +} + +/* On recent browsers, forEach and map are defined and do what we want. + * Otherwise, we'll use the Underscore.js functions + */ +if (typeof Array.prototype.forEach === "undefined") { + IriSP.Model.List.prototype.forEach = function(_callback) { + var _this = this; + IriSP._(this).forEach(function(_value, _key) { + _callback(_value, _key, _this); + }); + } +} + +if (typeof Array.prototype.map === "undefined") { + IriSP.Model.List.prototype.map = function(_callback) { + var _this = this; + return IriSP._(this).map(function(_value, _key) { + return _callback(_value, _key, _this); + }); + } +} + +/* We override Array's filter function because it doesn't return an IriSP.Model.List + */ +IriSP.Model.List.prototype.filter = function(_callback) { + var _this = this, + _res = new IriSP.Model.List(this.directory); + _res.addElements(IriSP._(this).filter(function(_value, _key) { + return _callback(_value, _key, _this); + })); + return _res; +} + +IriSP.Model.List.prototype.slice = function(_start, _end) { + var _res = new IriSP.Model.List(this.directory); + _res.addElements(Array.prototype.slice.call(this, _start, _end)); + return _res; +} + +IriSP.Model.List.prototype.splice = function(_start, _end) { + var _res = new IriSP.Model.List(this.directory); + _res.addElements(Array.prototype.splice.call(this, _start, _end)); + this.idIndex.splice(_start, _end); + return _res; +} + +/* Array has a sort function, but it's not as interesting as Underscore.js's sortBy + * and won't return a new IriSP.Model.List + */ +IriSP.Model.List.prototype.sortBy = function(_callback) { + var _this = this, + _res = new IriSP.Model.List(this.directory); + _res.addElements(IriSP._(this).sortBy(function(_value, _key) { + return _callback(_value, _key, _this); + })); + return _res; +} + +/* Title and Description are basic information for (almost) all element types, + * here we can search by these criteria + */ +IriSP.Model.List.prototype.searchByTitle = function(_text) { + var _rgxp = IriSP.Model.regexpFromTextOrArray(_text); + return this.filter(function(_element) { + return _rgxp.test(_element.title); + }); +} + +IriSP.Model.List.prototype.searchByDescription = function(_text) { + var _rgxp = IriSP.Model.regexpFromTextOrArray(_text); + return this.filter(function(_element) { + return _rgxp.test(_element.description); + }); +} + +IriSP.Model.List.prototype.searchByTextFields = function(_text) { + var _rgxp = IriSP.Model.regexpFromTextOrArray(_text); + return this.filter(function(_element) { + return _rgxp.test(_element.description) || _rgxp.test(_element.title); + }); +} + +IriSP.Model.List.prototype.getTitles = function() { + return this.map(function(_el) { + return _el.title; + }); +} + +IriSP.Model.List.prototype.addId = function(_id) { + var _el = this.directory.getElement(_id) + if (!this.hasId(_id) && typeof _el !== "undefined") { + this.idIndex.push(_id); + Array.prototype.push.call(this, _el); + } +} + +IriSP.Model.List.prototype.push = function(_el) { + if (typeof _el === "undefined") { + return; + } + var _index = (IriSP._(this.idIndex).indexOf(_el.id)); + if (_index === -1) { + this.idIndex.push(_el.id); + Array.prototype.push.call(this, _el); + } else { + this[_index] = _el; + } +} + +IriSP.Model.List.prototype.addIds = function(_array) { + var _l = _array.length, + _this = this; + IriSP._(_array).forEach(function(_id) { + _this.addId(_id); + }); +} + +IriSP.Model.List.prototype.addElements = function(_array) { + var _this = this; + IriSP._(_array).forEach(function(_el) { + _this.push(_el); + }); +} + +IriSP.Model.List.prototype.removeId = function(_id) { + var _index = (IriSP._(this.idIndex).indexOf(_id)); + if (_index !== -1) { + this.splice(_index,1); + } +} + +IriSP.Model.List.prototype.removeElement = function(_el) { + this.removeId(_el.id); +} + +IriSP.Model.List.prototype.removeIds = function(_list) { + var _this = this; + IriSP._(_list).forEach(function(_id) { + _this.removeId(_id); + }); +} + +IriSP.Model.List.prototype.removeElements = function(_list) { + var _this = this; + IriSP._(_list).forEach(function(_el) { + _this.removeElement(_el); + }); +} + +/* A simple time management object, that helps converting millisecs to seconds and strings, + * without the clumsiness of the original Date object. + */ + +IriSP.Model.Time = function(_milliseconds) { + this.milliseconds = parseInt(typeof _milliseconds !== "undefined" ? _milliseconds : 0); +} + +IriSP.Model.Time.prototype.setSeconds = function(_seconds) { + this.milliseconds = 1000 * _seconds; +} + +IriSP.Model.Time.prototype.getSeconds = function() { + return Math.floor(this.milliseconds / 1000); +} + +IriSP.Model.Time.prototype.getHMS = function() { + var _totalSeconds = Math.abs(this.getSeconds()); + return { + hours : Math.floor(_totalSeconds / 3600), + minutes : (Math.floor(_totalSeconds / 60) % 60), + seconds : _totalSeconds % 60 + } +} + +IriSP.Model.Time.prototype.valueOf = function() { + return this.milliseconds; +} + +IriSP.Model.Time.prototype.toString = function() { + function pad(_n) { + var _res = _n.toString(); + while (_res.length < 2) { + _res = '0' + _res; + } + return _res; + } + var _hms = this.getHMS(), + _res = ''; + if (_hms.hours) { + _res += pad(_hms.hours) + ':' + } + _res += pad(_hms.minutes) + ':' + pad(_hms.seconds); + return _res; +} + +/* IriSP.Model.Reference handles references between elements + */ + +IriSP.Model.Reference = function(_source, _idRef) { + this.source = _source; + if (typeof _idRef === "object") { + this.isList = true; + this.id = IriSP._(_idRef).map(function(_id) { + return _source.getNamespaced(_id).fullname; + }); + } else { + this.isList = false; + this.id = _source.getNamespaced(_idRef).fullname; + } + this.refresh(); +} + +IriSP.Model.Reference.prototype.refresh = function() { + if (this.isList) { + this.contents = new IriSP.Model.List(this.source.directory); + this.contents.addIds(this.id); + } else { + this.contents = this.source.directory.getElement(this.id); + } + +} + +IriSP.Model.Reference.prototype.getContents = function() { + if (typeof this.contents === "undefined" || (this.isList && this.contents.length != this.id.length)) { + this.refresh(); + } + return this.contents; +} + +IriSP.Model.Reference.prototype.isOrHasId = function(_idRef) { + if (this.isList) { + return (IriSP._(this.id).indexOf(_idRef) !== -1) + } else { + return (this.id == _idRef); + } +} + +/* */ + +IriSP.Model.Element = function(_id, _source) { + this.elementType = 'element'; + if (typeof _source === "undefined") { + return; + } + if (typeof _id === "undefined" || !_id) { + _id = IriSP.Model.getUID(); + } + this.source = _source; + this.namespacedId = _source.getNamespaced(_id) + this.id = this.namespacedId.fullname; + this.title = ""; + this.description = ""; + this.source.directory.addElement(this); +} + +IriSP.Model.Element.prototype.toString = function() { + return this.elementType + (this.elementType !== 'element' ? ', id=' + this.id + ', title="' + this.title + '"' : ''); +} + +IriSP.Model.Element.prototype.setReference = function(_elementType, _idRef) { + this[_elementType] = new IriSP.Model.Reference(this.source, _idRef); +} + +IriSP.Model.Element.prototype.getReference = function(_elementType) { + if (typeof this[_elementType] !== "undefined") { + return this[_elementType].getContents(); + } +} + +IriSP.Model.Element.prototype.getRelated = function(_elementType, _global) { + _global = (typeof _global !== "undefined" && _global); + var _this = this; + return this.source.getList(_elementType, _global).filter(function(_el) { + var _ref = _el[_this.elementType]; + return _ref.isOrHasId(_this.id); + }); +} + +/* */ + +IriSP.Model.Media = function(_id, _source) { + IriSP.Model.Element.call(this, _id, _source); + this.elementType = 'media'; + this.duration = new IriSP.Model.Time(); + this.video = ''; +} + +IriSP.Model.Media.prototype = new IriSP.Model.Element(); + +IriSP.Model.Media.prototype.setDuration = function(_durationMs) { + this.duration.milliseconds = _durationMs; +} + +IriSP.Model.Media.prototype.getAnnotations = function() { + return this.getRelated("annotation"); +} + +/* */ + +IriSP.Model.Tag = function(_id, _source) { + IriSP.Model.Element.call(this, _id, _source); + this.elementType = 'tag'; +} + +IriSP.Model.Tag.prototype = new IriSP.Model.Element(); + +IriSP.Model.Tag.prototype.getAnnotations = function() { + return this.getRelated("annotation"); +} + +/* */ + +IriSP.Model.AnnotationType = function(_id, _source) { + IriSP.Model.Element.call(this, _id, _source); + this.elementType = 'annotationType'; +} + +IriSP.Model.AnnotationType.prototype = new IriSP.Model.Element(); + +IriSP.Model.AnnotationType.prototype.getAnnotations = function() { + return this.getRelated("annotation"); +} + +/* Annotation + * */ + +IriSP.Model.Annotation = function(_id, _source) { + IriSP.Model.Element.call(this, _id, _source); + this.elementType = 'annotation'; + this.begin = new IriSP.Model.Time(); + this.end = new IriSP.Model.Time(); +} + +IriSP.Model.Annotation.prototype = new IriSP.Model.Element(null); + +IriSP.Model.Annotation.prototype.setBegin = function(_beginMs) { + this.begin.milliseconds = _beginMs; +} + +IriSP.Model.Annotation.prototype.setEnd = function(_beginMs) { + this.end.milliseconds = _beginMs; +} + +IriSP.Model.Annotation.prototype.setMedia = function(_idRef) { + this.setReference("media", _idRef); +} + +IriSP.Model.Annotation.prototype.getMedia = function() { + return this.getReference("media"); +} + +IriSP.Model.Annotation.prototype.setAnnotationType = function(_idRef) { + this.setReference("annotationType", _idRef); +} + +IriSP.Model.Annotation.prototype.getAnnotationType = function() { + return this.getReference("annotationType"); +} + +IriSP.Model.Annotation.prototype.setTags = function(_idRefs) { + this.setReference("tag", _idRefs); +} + +IriSP.Model.Annotation.prototype.getTags = function() { + return this.getReference("tag"); +} + +IriSP.Model.Annotation.prototype.getTagTexts = function() { + return this.getTags().getTitles(); +} + +/* */ + +IriSP.Model.Source = function(_config) { + this.status = IriSP.Model._SOURCE_STATUS_EMPTY; + if (typeof _config !== "undefined") { + var _this = this; + IriSP._(_config).forEach(function(_v, _k) { + _this[_k] = _v; + }) + this.callbackQueue = []; + this.contents = {}; + if (typeof this.namespace === "undefined") { + this.namespace = "metadataplayer"; + } else { + if (typeof this.namespaceUrl === "undefined" && typeof this.url !== "undefined") { + var _matches = this.url.match(/(^[^?&]+|[^?&][a-zA-Z0-9_%=?]+)/g), + _url = _matches[0]; + if (_matches.length > 1) { + _matches = IriSP._(_matches.slice(1)).reject(function(_txt) { + return /\?$/.test(_txt); + }); + } + if (_matches.length > 0) { + _url += '?' + _matches.join('&'); + } + this.namespaceUrl = _url; + } + } + if (typeof this.namespaceUrl === "undefined") { + this.namespaceUrl = "http://ldt.iri.centrepompidou.fr/"; + } + this.directory.addNamespace(this.namespace, this.namespaceUrl); + this.get(); + } +} + +IriSP.Model.Source.prototype.getNamespaced = function(_id) { + var _tab = _id.split(':'); + if (_tab.length > 1) { + return { + namespace : _tab[0], + name : _tab[1], + fullname : _id + } + } else { + return { + namespace : this.namespace, + name : _id, + fullname : this.namespace + ':' + _id + } + } +} + +IriSP.Model.Source.prototype.unNamespace = function(_id) { + if (typeof _id !== "undefined") { + return _id.replace(this.namespace + ':', ''); + } +} + +IriSP.Model.Source.prototype.addList = function(_listId, _contents) { + if (typeof this.contents[_listId] === "undefined") { + this.contents[_listId] = new IriSP.Model.List(this.directory); + } + this.contents[_listId].addElements(_contents); +} + +IriSP.Model.Source.prototype.getList = function(_listId, _global) { + _global = (typeof _global !== "undefined" && _global); + if (_global || typeof this.contents[_listId] === "undefined") { + return this.directory.getGlobalList().filter(function(_e) { + return (_e.elementType === _listId); + }); + } else { + return this.contents[_listId]; + } +} + +IriSP.Model.Source.prototype.forEach = function(_callback) { + var _this = this; + IriSP._(this.contents).forEach(function(_value, _key) { + _callback.call(_this, _value, _key); + }) +} + +IriSP.Model.Source.prototype.getElement = function(_elId) { + return this.directory.getElement(this.getNamespaced(_elId).fullname); +} + +IriSP.Model.Source.prototype.setCurrentMediaId = function(_idRef) { + if (typeof _idRef !== "undefined") { + this.currentMedia = this.getMedias().getElement(this.getNamespaced(_idRef).fullname); + } +} + +IriSP.Model.Source.prototype.setDefaultCurrentMedia = function() { + if (typeof this.currentMedia === "undefined" && this.getMedias().length) { + this.currentMedia = this.getMedias()[0]; + } +} + +IriSP.Model.Source.prototype.listNamespaces = function(_excludeSelf) { + var _this = this, + _nsls = [], + _excludeSelf = (typeof _excludeSelf !== "undefined" && _excludeSelf); + this.forEach(function(_list) { + IriSP._(_list).forEach(function(_el) { + var _ns = _el.id.replace(/:.*$/,''); + if (IriSP._(_nsls).indexOf(_ns) === -1 && (!_excludeSelf || _ns !== _this.namespace)) { + _nsls.push(_ns); + } + }) + }); + return _nsls; +} + +IriSP.Model.Source.prototype.get = function() { + this.status = IriSP.Model._SOURCE_STATUS_WAITING; + this.handleCallbacks(); +} + +/* We defer the callbacks calls so they execute after the queue is cleared */ +IriSP.Model.Source.prototype.deferCallback = function(_callback) { + var _this = this; + IriSP._.defer(function() { + _callback.call(_this); + }); +} + +IriSP.Model.Source.prototype.handleCallbacks = function() { + this.status = IriSP.Model._SOURCE_STATUS_READY; + while (this.callbackQueue.length) { + this.deferCallback(this.callbackQueue.splice(0,1)[0]); + } +} + +IriSP.Model.Source.prototype.onLoad = function(_callback) { + if (this.status === IriSP.Model._SOURCE_STATUS_READY) { + this.deferCallback(_callback); + } else { + this.callbackQueue.push(_callback); + } +} + +IriSP.Model.Source.prototype.serialize = function() { + return this.serializer.serialize(this); +} + +IriSP.Model.Source.prototype.deSerialize = function(_data) { + this.serializer.deSerialize(_data, this); +} + +IriSP.Model.Source.prototype.getAnnotations = function(_global) { + _global = (typeof _global !== "undefined" && _global); + return this.getList("annotation", _global); +} + +IriSP.Model.Source.prototype.getMedias = function(_global) { + _global = (typeof _global !== "undefined" && _global); + return this.getList("media", _global); +} + +IriSP.Model.Source.prototype.getAnnotationTypes = function(_global) { + _global = (typeof _global !== "undefined" && _global); + return this.getList("annotationType", _global); +} + +IriSP.Model.Source.prototype.getAnnotationsByTypeTitle = function(_title, _global) { + _global = (typeof _global !== "undefined" && _global); + var _res = new IriSP.Model.List(this.directory), + _annTypes = this.getAnnotationTypes(_global).searchByTitle(_title); + _annTypes.forEach(function(_annType) { + _res.addElements(_annType.getAnnotations(_global)); + }) + return _res; +} + +IriSP.Model.Source.prototype.getDuration = function() { + var _m = this.currentMedia; + if (typeof _m !== "undefined") { + return this.currentMedia.duration; + } +} + +/* */ + +IriSP.Model.RemoteSource = function(_config) { + IriSP.Model.Source.call(this, _config); +} + +IriSP.Model.RemoteSource.prototype = new IriSP.Model.Source(); + +IriSP.Model.RemoteSource.prototype.get = function() { + this.status = IriSP.Model._SOURCE_STATUS_WAITING; + var _this = this; + this.serializer.loadData(this.url, function(_result) { + _this.deSerialize(_result); + _this.handleCallbacks(); + }); +} + +/* */ + +IriSP.Model.Directory = function() { + this.remoteSources = {}; + this.elements = {}; + this.namespaces = {}; +} + +IriSP.Model.Directory.prototype.addNamespace = function(_namespace, _url) { + this.namespaces[_namespace] = _url; +} + +IriSP.Model.Directory.prototype.remoteSource = function(_properties) { + var _config = IriSP._({ directory: this }).extend(_properties); + if (typeof this.remoteSources[_properties.url] === "undefined") { + this.remoteSources[_properties.url] = new IriSP.Model.RemoteSource(_config); + } + return this.remoteSources[_properties.url]; +} + +IriSP.Model.Directory.prototype.newLocalSource = function(_properties) { + var _config = IriSP._({ directory: this }).extend(_properties), + _res = new IriSP.Model.Source(_config); + return _res; +} + +IriSP.Model.Directory.prototype.getElement = function(_id) { + var _res = this.elements[_id]; + if (typeof _res === "undefined") { + var _un = _id.replace(/.*:/), + _keys = IriSP._(this.elements).keys(); + _key = IriSP._(_keys).find(function(_i) { + return _i.replace(/.*:/) === _un; + }); + if (typeof _key !== "undefined") { + _res = this.elements[_key]; + } + } + return _res; +} + +IriSP.Model.Directory.prototype.addElement = function(_element) { + this.elements[_element.id] = _element; +} + +IriSP.Model.Directory.prototype.getGlobalList = function() { + var _res = new IriSP.Model.List(this); + _res.addIds(IriSP._(this.elements).keys()); + return _res; +} + +/* */ +IriSP.language = 'en'; + +IriSP.libFiles = { + defaultDir : "js/libs/", + inDefaultDir : { + underscore : "underscore-min.js", + Mustache : "mustache.js", + jQuery : "jquery.min.js", + jQueryUI : "jquery-ui.min.js", + swfObject : "swfobject.js", + cssjQueryUI : "jquery-ui.css", + popcorn : "popcorn.js", + jwplayer : "jwplayer.js", + raphael : "raphael-min.js", + "popcorn.mediafragment" : "popcorn.mediafragment.js", + "popcorn.code" : "popcorn.code.js", + "popcorn.jwplayer" : "popcorn.jwplayer.js", + "popcorn.youtube" : "popcorn.youtube.js", + tracemanager : "tracemanager.js" + }, + locations : { + // use to define locations outside defautl_dir + }, + cdn : { + jQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.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" + }, + useCdn : false +} + +IriSP.widgetsDir = 'widgets'; + +IriSP.widgetsRequirements = { + Sparkline: { + noCss: true, + requires: "raphael" + }, + Arrow: { + noCss: true, + requires: "raphael" + }, + Mediafragment: { + noCss: true + }, + Trace : { + noCss: true, + requires: "tracemanager" + } +} + +IriSP.guiDefaults = { + width : 640, + container : 'LdtPlayer', + spacer_div_height : 0 +} +/* Definition of an ancestor for the Widget classes */ + +if (typeof IriSP.Widgets === "undefined") { + IriSP.Widgets = {} +} + +/** + * @class IriSP.Widget is an "abstract" class. It's mostly used to define some properties common to every widget. + * + * Note that widget constructors are never called directly by the user. Instead, the widgets are instantiated by functions + * defined in init.js + * + * @constructor + * @param player - a reference to the player widget + * @param config - configuration options for the widget + */ + + +IriSP.Widgets.Widget = function(player, config) { + + if( typeof player === "undefined") { + /* Probably an abstract call of the class when + * individual widgets set their prototype */ + return; + } + + /* Setting all the configuration options */ + var _type = config.type, + _config = IriSP._.defaults({}, config, player.config.gui.default_options, this.defaults), + _this = this; + + IriSP._(_config).forEach(function(_value, _key) { + _this[_key] = _value; + }); + + if (typeof this.width === "undefined") { + this.width = player.config.gui.width; + } + + /* Setting this.player at the end in case it's been overriden + * by a configuration option of the same name :-( + */ + this.player = player; + + /* Getting metadata */ + this.source = player.loadMetadata(this.metadata); + + /* Call draw when loaded */ + this.source.onLoad(function() { + _this.draw(); + }); + + /* Adding classes and html attributes */ + this.$ = IriSP.jQuery('#' + this.container); + this.$.addClass("Ldt-TraceMe Ldt-Widget").attr("widget-type", _type); + + /* Does the widget require other widgets ? */ + if (typeof this.requires !== "undefined") { + for (var _i = 0; _i < this.requires.length; _i++) { + var _subconfig = this.requires[_i]; + _subconfig.container = IriSP._.uniqueId(this.container + '_' + _subconfig.type + '_'); + this.$.append(IriSP.jQuery('
    ').attr("id",_subconfig.container)); + this.player.loadWidget(_subconfig, function(_widget) { + _this[_subconfig.type.replace(/^./,function(_s){return _s.toLowerCase();})] = _widget + }); + } + } + + this.l10n = (typeof this.messages[IriSP.language] !== "undefined" ? this.messages[IriSP.language] : this.messages["en"]); + +}; + +IriSP.Widgets.Widget.prototype.defaults = {} + +IriSP.Widgets.Widget.prototype.template = ''; + +IriSP.Widgets.Widget.prototype.messages = {"en":{}}; + +IriSP.Widgets.Widget.prototype.templateToHtml = function(_template) { + return Mustache.to_html(_template, this); +} + +IriSP.Widgets.Widget.prototype.renderTemplate = function() { + this.$.append(this.templateToHtml(this.template)); +} + +IriSP.Widgets.Widget.prototype.functionWrapper = function(_name) { + var _this = this, + _function = this[_name]; + if (typeof _function !== "undefined") { + return function() { + return _function.apply(_this, Array.prototype.slice.call(arguments, 0)); + } + } else { + console.log("Error, Unknown function IriSP." + this.type + "." + _name) + } +} + +IriSP.Widgets.Widget.prototype.bindPopcorn = function(_popcornEvent, _functionName) { + this.player.popcorn.listen(_popcornEvent, this.functionWrapper(_functionName)) +} + +IriSP.Widgets.Widget.prototype.getWidgetAnnotations = function() { + return typeof this.annotation_type !== "undefined" && this.annotation_type ? this.source.getAnnotationsByTypeTitle(this.annotation_type) : this.source.getAnnotations(); +} + +/** + * This method responsible of drawing a widget on screen. + */ +IriSP.Widgets.Widget.prototype.draw = function() { + /* implemented by "sub-classes" */ +}; +/** + * Optional method if you want your widget to support redraws. + */ +IriSP.Widgets.Widget.prototype.redraw = function() { + /* implemented by "sub-classes" */ +}; +/* To wrap a player the develop should create a new class derived from +the IriSP.PopcornReplacement.player and defining the correct functions */ + +/** allocine player wrapper */ +IriSP.PopcornReplacement.allocine = function(container, options) { +// console.log("Calling allocine player"); + /* appel du parent pour initialiser les structures communes à tous les players */ + IriSP.PopcornReplacement.player.call(this, container, options); + + var _this = this; + + /* Définition des fonctions de l'API - */ + + this.playerFns = { + play : function() { + return _this.apiCall("play"); + }, + pause : function() { + return _this.apiCall("pause"); + }, + getPosition : function() { + return _this.apiCall("getSeek","return") || 0; + }, + seek : function(pos) { + return _this.apiCall("seek",pos); + }, + getMute : function() { + return _this.apiCall("getMute","return"); + }, + setMute : function(p) { + return _this.apiCall("setMute", p); + } + } + + window.onReady = IriSP.wrap(this, this.ready); + window.onAllocineStateChange = IriSP.wrap(this, this.stateHandler); + window.onTime = IriSP.wrap(this, this.progressHandler); + + var _flashVars = { + "streamFMS" : true, + "adVast" : false, + "lg" : "fr_cinecast", + "autoPlay" : options.autoPlay, + "directVideoTitle" : "", + "urlAcData" : options.urlAcData, + "directVideoPath" : options.video, + "host" : "http://allocine.fr" + } + + if (typeof IriSP.__jsonMetadata["medias"][0].meta == "object" && typeof IriSP.__jsonMetadata["medias"][0].meta.subtitles == "string") { + _flashVars.subTitlePath = IriSP.__jsonMetadata["medias"][0].meta.subtitles; + } + + + var params = { + "allowScriptAccess" : "always", + "wmode": "opaque", + "flashvars" : IriSP.jQuery.param(_flashVars), + "allowfullscreen" : true + }; + var atts = { + id : this.container + }; + swfobject.embedSWF(options.acPlayerUrl, this.container, options.width, options.height, "10", null, null, params, atts); + +}; + +IriSP.PopcornReplacement.allocine.prototype = new IriSP.PopcornReplacement.player("", {}); + +IriSP.PopcornReplacement.allocine.prototype.ready = function() { + this.player = document.getElementById(this.container); + this.player.addEventListener("onStateChange", "onAllocineStateChange"); + this.player.cueVideoByUrl(this._options.video); + this.callbacks.onReady(); +}; + +IriSP.PopcornReplacement.allocine.prototype.progressHandler = function(progressInfo) { + this.callbacks.onTime({ + position: progressInfo.mediaTime + }); +} + + +IriSP.PopcornReplacement.allocine.prototype.apiCall = function(_method, _arg) { + if (this.player) { + try { + if (typeof _arg == "undefined") { + return this.player.sendToActionScript(_method); + } else { + return this.player.sendToActionScript(_method, _arg); + } + } catch(e) { + console.error('Exception while requesting AcPlayer for "' + _method + (typeof _arg == "undefined" ? '' : '" with argument "' + _arg ) + '"\n', e); + return false; + } + } else { + return false; + } +} + +IriSP.PopcornReplacement.allocine.prototype.stateHandler = function(state) { + console.log("stateHandler"); + switch(state) { + case 1: + this.callbacks.onPlay(); + break; + + case 2: + this.callbacks.onPause(); + break; + + case 3: + this.callbacks.onSeek({ + position: this.player.getCurrentTime() + }); + break; + + /* + case 5: + this.callbacks.onReady(); + break; + */ + } + +};/* To wrap a player the develop should create a new class derived from +the IriSP.PopcornReplacement.player and defining the correct functions */ + +/** jwplayer player wrapper */ +IriSP.PopcornReplacement.dailymotion = function(container, options) { + console.log("Calling"); + /* appel du parent pour initialiser les structures communes à tous les players */ + IriSP.PopcornReplacement.player.call(this, container, options); + + var _this = this; + + /* Définition des fonctions de l'API - */ + + this.playerFns = { + play : function() { + if (_this.player) { + return _this.player.playVideo(); + } else { + return false; + } + }, + pause : function() { + if (_this.player) { + return _this.player.pauseVideo(); + } else { + return false; + } + }, + getPosition : function() { + if (_this.player) { + return _this.player.getCurrentTime(); + } else { + return 0; + } + }, + seek : function(pos) { + if (_this.player) { + return _this.player.seekTo(pos); + } else { + return false; + } + }, + getMute : function() { + if (_this.player) { + return _this.player.isMuted(); + } else { + return false; + } + }, + setMute : function(p) { + if (_this.player) { + if (p) { + _this.player.mute(); + } + else { + _this.player.unMute(); + } + } + }, + getVolume : function() { + if (_this.player) { + return _this.player.getVolume() / 100; + } else { + return false; + } + }, + setVolume : function(p) { + if (_this.player) { + _this.player.setVolume(Math.floor(100 * p)); + } + }, + } + + window.onDailymotionPlayerReady = IriSP.wrap(this, this.ready); + window.onDailymotionStateChange = IriSP.wrap(this, this.stateHandler); + window.onDailymotionVideoProgress = IriSP.wrap(this, this.progressHandler); + + var params = { + "allowScriptAccess" : "always", + "wmode": "opaque" + }; + var atts = { + id : this.container + }; + swfobject.embedSWF("http://www.dailymotion.com/swf?chromeless=1&enableApi=1", this.container, options.width, options.height, "8", null, null, params, atts); + +}; + +IriSP.PopcornReplacement.dailymotion.prototype = new IriSP.PopcornReplacement.player("", {}); + +IriSP.PopcornReplacement.dailymotion.prototype.ready = function() { + + this.player = document.getElementById(this.container); + + this.player.addEventListener("onStateChange", "onDailymotionStateChange"); + this.player.addEventListener("onVideoProgress", "onDailymotionVideoProgress"); + this.player.cueVideoByUrl(this._options.video); + + this.callbacks.onReady(); +}; + +IriSP.PopcornReplacement.dailymotion.prototype.progressHandler = function(progressInfo) { + + this.callbacks.onTime({ + position: progressInfo.mediaTime + }); +} + +IriSP.PopcornReplacement.dailymotion.prototype.stateHandler = function(state) { + + switch(state) { + case 1: + this.callbacks.onPlay(); + break; + + case 2: + this.callbacks.onPause(); + break; + + case 3: + this.callbacks.onSeek({ + position: this.player.getCurrentTime() + }); + break; + + /* + case 5: + this.callbacks.onReady(); + break; + */ + } + +};/* To wrap a player the develop should create a new class derived from + the IriSP.PopcornReplacement.player and defining the correct functions */ + +/** jwplayer player wrapper */ +IriSP.PopcornReplacement.jwplayer = function(container, options) { + /* appel du parent pour initialiser les structures communes à tous les players */ + IriSP.PopcornReplacement.player.call(this, container, options); + + this.media.duration = options.duration; /* optional */ + + /* Définition des fonctions de l'API - */ + this.playerFns = { + play: function() { return jwplayer(this.container).play(); }, + pause: function() { return jwplayer(this.container).pause(); }, + getPosition: function() { return jwplayer(this.container).getPosition(); }, + seek: function(pos) { return jwplayer(this.container).seek(pos); }, + getMute: function() { return jwplayer(this.container).getMute() }, + setMute: function(p) { return jwplayer(this.container).setMute(p); }, + getVolume: function() { return jwplayer(this.container).getVolume() / 100; }, + setVolume: function(p) { return jwplayer(this.container).setVolume(Math.floor(100*p)); } + } + + options.events = this.callbacks; + + jwplayer(this.container).setup(options); +}; + +IriSP.PopcornReplacement.jwplayer.prototype = new IriSP.PopcornReplacement.player("", {}); +/* Cinecast Cinelab Serializer */ + +if (typeof IriSP.serializers === "undefined") { + IriSP.serializers = {} +} + +IriSP.serializers.cinecast = { + types : { + media : { + serialized_name : "medias", + model_name : "media", + deserializer : function(_data, _source) { + var _res = new IriSP.Model.Media(_data.id, _source); + _res.video = _data.url; + _res.title = _data.meta.title; + _res.description = _data.meta.synopsis; + _res.setDuration(_data.meta.duration); + return _res; + }, + serializer : function(_data, _source) { + return { + id : _source.unNamespace(_data.id), + url : _data.video, + meta : { + title : _data.title, + synopsis : _data.description, + duration : _data.duration.milliseconds + } + } + } + }, + tag : { + serialized_name : "tags", + model_name : "tag", + deserializer : function(_data, _source) { + var _res = new IriSP.Model.Tag(_data.id, _source); + _res.title = _data.meta.description; + return _res; + }, + serializer : function(_data, _source) { + return { + id : _source.unNamespace(_data.id), + meta : { + description : _data.title + } + } + } + }, + annotationType : { + serialized_name : "annotation_types", + deserializer : function(_data, _source) { + var _res = new IriSP.Model.AnnotationType(_data.id, _source); + _res.title = _source.getNamespaced(_data.id).name; + _res.description = _data.meta.description; + return _res; + }, + serializer : function(_data, _source) { + return { + id : _source.unNamespace(_data.id), + meta : { + description : _data.description + } + } + } + }, + annotation : { + serialized_name : "annotations", + deserializer : function(_data, _source) { + var _res = new IriSP.Model.Annotation(_data.id, _source); + _res.title = _data.meta.creator_name; + _res.description = _data.content.data; + _res.created = IriSP.Model.isoToDate(_data.meta.created); + _res.setMedia(_data.media, _source); + _res.setAnnotationType(_data.type); + _res.setTags(IriSP._(_data.tags).map(function(_t) { + if (typeof _source.contents.tag === "undefined") { + _source.contents.tag = new IriSP.Model.List(_source.directory); + } + if (_source.contents.tag.hasId(_t)) { + return _t; + } else { + var _id = _t.toLowerCase() + .replace(/#/g,'') + .replace(/^(\d)/,'_$1') + .replace(/[áâäàã]/g,'a') + .replace(/ç/g,'c') + .replace(/[éèêë]/g,'e') + .replace(/[íìîï]/g,'i') + .replace(/ñ/g,'n') + .replace(/[óòôöõ]/g,'o') + .replace(/œ/g,'oe') + .replace(/[úùûü]/g,'u') + .replace(/ÿ/g,'y') + .replace(/[^A-Za-z0-9_]/g,''), + _tag = new IriSP.Model.Tag(_id, _source); + _tag.title = _t; + _source.contents.tag.push(_tag); + return _id; + } + })); + _res.setBegin(_data.begin); + _res.setEnd(_data.end); + _res.creator = _data.meta.creator; + return _res; + }, + serializer : function(_data, _source) { + return { + id : _source.unNamespace(_data.id), + content : { + data : _data.description + }, + begin : _data.begin.milliseconds, + end : _data.begin.milliseconds, + media : _source.unNamespace(_data.media.id), + type : _source.unNamespace(_data.annotationType.id), + meta : { + created : IriSP.Model.dateToIso(_data.created), + creator : _data.creator, + creator_name : _data.title + }, + tags : _data.tag.id.map(function(_id) { + return _source.unNamespace(_id) + }) + } + } + } + }, + serialize : function(_source) { + var _res = { + format : "http://advene.org/ns/cinelab/" + }, + _this = this, + _nsls = _source.listNamespaces(true); + _res.imports = []; + for (var _i = 0; _i < _nsls.length; _i++) { + if (typeof _source.directory.namespaces[_nsls[_i]] !== "undefined") { + _res.imports.push({ + id : _nsls[_i], + url : _source.directory.namespaces[_nsls[_i]] + }) + } + } + _source.forEach(function(_list, _typename) { + if (typeof _this.types[_typename] !== "undefined") { + _res[_this.types[_typename].serialized_name] = _list.map(function(_el) { + return _this.types[_typename].serializer(_el, _source); + }); + } + }); + return _res; + }, + loadData : function(_url, _callback) { + IriSP.jQuery.getJSON(_url, _callback) + }, + deSerialize : function(_data, _source) { + if (typeof _data !== "object" || _data === null) { + return; + } + if (typeof _data.imports !== "undefined") { + IriSP._(_data.imports).forEach(function(_import) { + _source.directory.namespaces[_import.id] = _import.url; + }) + } + IriSP._(this.types).forEach(function(_type, _typename) { + var _listdata = _data[_type.serialized_name]; + if (typeof _listdata !== "undefined" && _listdata !== null) { + var _list = new IriSP.Model.List(_source.directory); + if (_listdata.hasOwnProperty("length")) { + var _l = _listdata.length; + for (var _i = 0; _i < _l; _i++) { + _list.push(_type.deserializer(_listdata[_i], _source)); + } + } else { + _list.push(_type.deserializer(_listdata, _source)); + } + _source.addList(_typename, _list); + } + }); + + if (typeof _data.meta !== "undefined" && typeof _data.meta.main_media !== "undefined" && typeof _data.meta.main_media["id-ref"] !== "undefined") { + _source.setCurrentMediaId(_data.meta.id); + } + _source.setDefaultCurrentMedia(); + } +} + +/* LDT Platform Serializer */ + +if (typeof IriSP.serializers === "undefined") { + IriSP.serializers = {} +} + +IriSP.serializers.ldt = { + types : { + media : { + serialized_name : "medias", + model_name : "media", + deserializer : function(_data, _source) { + var _res = new IriSP.Model.Media(_data.id, _source); + _res.video = ( + typeof _data.url !== "undefined" + ? _data.url + : ( + typeof _data.href !== "undefined" + ? _data.href + : null + ) + ); + if (typeof _data.meta.item !== "undefined" && _data.meta.item.name === "streamer") { + _res.streamer = _data.meta.item.value; + } + _res.title = _data.meta["dc:title"]; + _res.description = _data.meta["dc:description"]; + _res.setDuration(_data.meta["dc:duration"]); + return _res; + }, + serializer : function(_data, _source) { + return { + id : _source.unNamespace(_data.id), + url : _data.video, + meta : { + "dc:title" : _data.title, + "dc:description" : _data.description, + "dc:duration" : _data.duration.milliseconds + } + } + } + }, + tag : { + serialized_name : "tags", + model_name : "tag", + deserializer : function(_data, _source) { + var _res = new IriSP.Model.Tag(_data.id, _source); + _res.title = _data.meta["dc:title"]; + return _res; + }, + serializer : function(_data, _source) { + return { + id : _source.unNamespace(_data.id), + meta : { + "dc:title" : _data.title + } + } + } + }, + annotationType : { + serialized_name : "annotation-types", + deserializer : function(_data, _source) { + var _res = new IriSP.Model.AnnotationType(_data.id, _source); + _res.title = _data["dc:title"]; + _res.description = _data["dc:description"]; + return _res; + }, + serializer : function(_data, _source) { + return { + id : _source.unNamespace(_data.id), + "dc:title" : _data.title, + "dc:description" : _data.description + } + } + }, + annotation : { + serialized_name : "annotations", + deserializer : function(_data, _source) { + var _res = new IriSP.Model.Annotation(_data.id, _source); + _res.title = _data.content.title || ""; + _res.description = _data.content.description || ""; + if (typeof _data.content.img !== "undefined" && _data.content.img.src !== "undefined") { + _res.thumbnail = _data.content.img.src; + } + _res.created = IriSP.Model.isoToDate(_data.meta["dc:created"]); + if (typeof _data.color !== "undefined") { + var _c = parseInt(_data.color).toString(16); + while (_c.length < 6) { + _c = '0' + _c; + } + _res.color = '#' + _c; + } + _res.setMedia(_data.media, _source); + _res.setAnnotationType(_data.meta["id-ref"]); + _res.setTags(IriSP._(_data.tags).pluck("id-ref")); + _res.setBegin(_data.begin); + _res.setEnd(_data.end); + _res.creator = _data.meta["dc:creator"] || ""; + _res.project = _data.meta.project || ""; + if (typeof _data.meta["dc:source"] !== "undefined" && typeof _data.meta["dc:source"].content !== "undefined") { + _res.source = JSON.parse(_data.meta["dc:source"].content); + } + return _res; + }, + serializer : function(_data, _source) { + return { + id : _source.unNamespace(_data.id), + content : { + title : _data.title, + description : _data.description + }, + media : _source.unNamespace(_data.media.id), + meta : { + "id-ref" : _source.unNamespace(_data.annotationType.id), + "dc:created" : IriSP.Model.dateToIso(_data.created), + "dc:creator" : _data.creator, + project : _source.projectId + }, + tags : IriSP._(_data.tag.id).map(function(_d) { + return { + "id-ref" : _source.unNamespace(_id) + } + }) + } + } + } + }, + serialize : function(_source) { + var _res = {}, + _this = this; + _source.forEach(function(_list, _typename) { + if (typeof _this.types[_typename] !== "undefined") { + _res[_this.types[_typename].serialized_name] = _list.map(function(_el) { + return _this.types[_typename].serializer(_el, _source); + }); + } + }); + return _res; + }, + loadData : function(_url, _callback) { + IriSP.jQuery.getJSON(_url, _callback) + }, + deSerialize : function(_data, _source) { + if (typeof _data !== "object" || _data === null) { + return; + } + IriSP._(this.types).forEach(function(_type, _typename) { + var _listdata = _data[_type.serialized_name]; + if (typeof _listdata !== "undefined" && _listdata !== null) { + var _list = new IriSP.Model.List(_source.directory); + if (_listdata.hasOwnProperty("length")) { + var _l = _listdata.length; + for (var _i = 0; _i < _l; _i++) { + _list.push(_type.deserializer(_listdata[_i], _source)); + } + } else { + _list.push(_type.deserializer(_listdata, _source)); + } + _source.addList(_typename, _list); + } + }); + + if (typeof _data.meta !== "undefined") { + _source.projectId = _data.meta.id; + } + + if (typeof _data.meta !== "undefined" && typeof _data.meta.main_media !== "undefined" && typeof _data.meta.main_media["id-ref"] !== "undefined") { + _source.setCurrentMediaId(_data.meta.main_media["id-ref"]); + } + _source.setDefaultCurrentMedia(); + } +} + diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Mediafragment.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Mediafragment.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,77 @@ +IriSP.Widgets.Mediafragment = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); + this.last_hash = ""; + window.onhashchange = this.functionWrapper("goToHash"); + if (typeof window.addEventListener !== "undefined") { + window.addEventListener('message', function(_msg) { + if (_msg.data.type === "hashchange") { + document.location.hash = _msg.data.hash; + } + }) + }; + this.bindPopcorn("pause","setHashToTime"); + this.bindPopcorn("seeked","setHashToTime"); + this.bindPopcorn("IriSP.Mediafragment.setHashToAnnotation","setHashToAnnotation"); + this.blocked = false; +} + +IriSP.Widgets.Mediafragment.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Mediafragment.prototype.draw = function() { + this.goToHash(); +} + +IriSP.Widgets.Mediafragment.prototype.goToHash = function() { + if (document.location.hash !== this.last_hash) { + this.last_hash = document.location.hash; + var _tab = this.last_hash.split("="); + if (_tab[0] === '#id') { + var _annotation = this.source.getElement(_tab[1]); + if (typeof _annotation !== "undefined") { + this.player.popcorn.currentTime(_annotation.begin.getSeconds()); + } + } + if (_tab[0] === '#t') { + this.player.popcorn.currentTime(_tab[1]); + } + } +} + +IriSP.Widgets.Mediafragment.prototype.setHashToAnnotation = function(_annotationId) { + this.setHash( '#id=' + this.source.unNamespace(_annotationId) ); +} + +IriSP.Widgets.Mediafragment.prototype.setHashToTime = function(_time) { + _time = (typeof _time !== "undefined" ? _time : this.player.popcorn.currentTime() ); + this.setHash( '#t=' + _time ); +} + +IriSP.Widgets.Mediafragment.prototype.setHash = function(_hash) { + if (!this.blocked && this.last_hash !== _hash) { + this.last_hash = _hash; + document.location.hash = _hash; + if (window.parent !== window) { + window.parent.postMessage({ + type: "hashchange", + hash: _hash + }) + } + this.block(); + } +} + +IriSP.Widgets.Mediafragment.prototype.unblock = function() { + if (typeof this.blockTimeout !== "undefined") { + window.clearTimeout(this.blockTimeout); + } + this.blockTimeout = undefined; + this.blocked = false; +} + +IriSP.Widgets.Mediafragment.prototype.block = function() { + if (typeof this.blockTimeout !== "undefined") { + window.clearTimeout(this.blockTimeout); + } + this.blocked = true; + this.blockTimeout = window.setTimeout(this.functionWrapper("unblock"), 1000); +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Polemic.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Polemic.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,22 @@ +/* + * Polemic Widget CSS + */ + +.Ldt-Polemic { + border-style: solid none; border-color: #cccccc; border-width: 1px; +} + +.Ldt-Polemic-Position { + background: #fc00ff; + position: absolute; + top: 0; + left: 0; + margin-left: -1px; + width: 2px; + height: 100%; +} + +.Ldt-Polemic-TweetDiv { + position: absolute; +} + diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Polemic.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Polemic.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,304 @@ +IriSP.Widgets.Polemic = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); +}; + +IriSP.Widgets.Polemic.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Polemic.prototype.messages = { + fr: { + from_: "de ", + _to_: " à ", + _annotations: " annotation(s)" + }, + en: { + from_: "from ", + _to_: " to ", + _annotations: " annotation(s)" + } +} +IriSP.Widgets.Polemic.prototype.defaults = { + element_width : 5, + element_height : 5, + max_elements : 15, + annotation_type : "tweet", + defaultcolor : "#585858", + foundcolor : "#fc00ff", + polemics : [ + { + "keywords" : [ "++" ], + "description" : "positif", + "color" : "#1D973D" + }, + { + "keywords" : [ "--" ], + "description" : "negatif", + "color" : "#CE0A15" + }, + { + "keywords" : [ "==" ], + "description" : "reference", + "color" : "#C5A62D" + }, + { + "keywords" : [ "??" ], + "description" : "question", + "color" : "#036AAE" + } + ], + requires : [ + { + type: "Tooltip" + } + ] +}; + +IriSP.Widgets.Polemic.prototype.onSearch = function(searchString) { + this.searchString = typeof searchString !== "undefined" ? searchString : ''; + var _found = 0, + _re = IriSP.Model.regexpFromTextOrArray(searchString), + _this = this; + this.$tweets.each(function() { + var _el = IriSP.jQuery(this); + if (_this.searchString) { + if (_re.test(_el.attr("tweet-title"))) { + _el.css({ + "background" : _this.foundcolor, + "opacity" : 1 + }); + _found++; + } else { + _el.css({ + "background" : _el.attr("polemic-color"), + "opacity" : .5 + }); + } + } else { + _el.css({ + "background" : _el.attr("polemic-color"), + "opacity" : 1 + }); + } + }); + if (this.searchString) { + if (_found) { + this.player.popcorn.trigger("IriSP.search.matchFound"); + } else { + this.player.popcorn.trigger("IriSP.search.noMatchFound"); + } + } +} + +IriSP.Widgets.Polemic.prototype.draw = function() { + + this.bindPopcorn("timeupdate", "onTimeupdate"); + this.$zone = IriSP.jQuery('
    '); + this.$zone.addClass("Ldt-Polemic"); + this.$.append(this.$zone); + + this.$elapsed = IriSP.jQuery('
    ') + .css({ + background: '#cccccc', + position: "absolute", + top: 0, + left: 0, + width: 0, + height: "100%" + }); + + this.$zone.append(this.$elapsed); + + var _slices = [], + _slice_count = Math.floor( this.width / this.element_width ), + _duration = this.source.getDuration(), + _max = 0, + _list = this.getWidgetAnnotations(), + _this = this; + + for (var _i = 0; _i < _slice_count; _i++) { + var _begin = new IriSP.Model.Time( _i * _duration / _slice_count ), + _end = new IriSP.Model.Time( ( _i + 1 ) * _duration / _slice_count ), + _count = 0, + _res = { + begin : _begin.toString(), + end : _end.toString(), + annotations : _list.filter(function(_annotation) { + return _annotation.begin >= _begin && _annotation.end < _end; + }), + polemicStacks : [] + } + + for (var _j = 0; _j < this.polemics.length; _j++) { + var _polemic = _res.annotations.searchByDescription(this.polemics[_j].keywords); + _count += _polemic.length; + _res.polemicStacks.push(_polemic); + } + for (var _j = 0; _j < this.polemics.length; _j++) { + _res.annotations.removeElements(_res.polemicStacks[_j]); + } + _count += _res.annotations.length; + _max = Math.max(_max, _count); + _slices.push(_res); + } + if (_max < this.max_elements) { + this.is_stackgraph = false; + if (_max) { + + this.height = (2 + _max) * this.element_height; + this.$zone.css({ + width: this.width + "px", + height: this.height + "px", + position: "relative" + }); + + var _x = 0, + _html = ''; + + function displayElement(_x, _y, _color, _id, _title) { + _html += Mustache.to_html( + '
    ', + { + id: _id, + title: _title, + posx: Math.floor(_x + (_this.element_width - 1) / 2), + left: _x, + top: _y, + color: _color, + width: (_this.element_width-1), + height: _this.element_height + }); + } + + IriSP._(_slices).forEach(function(_slice) { + var _y = _this.height; + _slice.annotations.forEach(function(_annotation) { + _y -= _this.element_height; + displayElement(_x, _y, _this.defaultcolor, _annotation.id, _annotation.title); + }); + IriSP._(_slice.polemicStacks).forEach(function(_annotations, _j) { + var _color = _this.polemics[_j].color; + _annotations.forEach(function(_annotation) { + _y -= _this.element_height; + displayElement(_x, _y, _color, _annotation.id, _annotation.title); + }); + }); + _x += _this.element_width; + }); + + this.$zone.append(_html); + + this.$tweets = this.$.find(".Ldt-Polemic-TweetDiv"); + + this.$tweets + .mouseover(function() { + var _el = IriSP.jQuery(this); + _this.tooltip.show(_el.attr("pos-x"), _el.attr("pos-y"), _el.attr("tweet-title"), _el.attr("polemic-color")); + }) + .mouseout(function() { + _this.tooltip.hide(); + }) + .click(function() { + var _id = IriSP.jQuery(this).attr("annotation-id"); + _this.player.popcorn.trigger("IriSP.Mediafragment.setHashToAnnotation", _id); + _this.player.popcorn.trigger("IriSP.Tweet.show", _id); + }); + + this.bindPopcorn("IriSP.search", "onSearch"); + this.bindPopcorn("IriSP.search.closed", "onSearch"); + this.bindPopcorn("IriSP.search.cleared", "onSearch"); + + } else { + this.$zone.hide(); + } + } else { + this.is_stackgraph = true; + + this.height = (2 + this.max_elements) * this.element_height; + this.$zone.css({ + width: this.width + "px", + height: this.height + "px", + position: "relative" + }); + + var _x = 0, + _html = '', + _scale = this.max_elements * this.element_height / _max; + + function displayElement(_x, _y, _h, _color, _nums, _begin, _end) { + _html += Mustache.to_html( + '
    ', + { + nums: _nums, + posx: Math.floor(_x + (_this.element_width - 1) / 2), + left: _x, + top: _y, + color: _color, + width: (_this.element_width-1), + height: _h, + begin: _begin, + end: _end + }); + } + + IriSP._(_slices).forEach(function(_slice) { + var _y = _this.height, + _nums = _slice.annotations.length + "," + IriSP._(_slice.polemicStacks).map(function(_annotations) { + return _annotations.length + }).join(","); + if (_slice.annotations.length) { + var _h = Math.ceil(_scale * _slice.annotations.length); + _y -= _h; + displayElement(_x, _y, _h, _this.defaultcolor, _nums, _slice.begin, _slice.end); + } + IriSP._(_slice.polemicStacks).forEach(function(_annotations, _j) { + if (_annotations.length) { + var _color = _this.polemics[_j].color, + _h = Math.ceil(_scale * _annotations.length); + _y -= _h; + displayElement(_x, _y, _h, _color, _nums, _slice.begin, _slice.end); + } + }); + _x += _this.element_width; + }); + + this.$zone.append(_html); + + this.$tweets = this.$.find(".Ldt-Polemic-TweetDiv"); + + this.$tweets + .mouseover(function() { + var _el = IriSP.jQuery(this), + _nums = _el.attr("annotation-counts").split(","), + _html = '

    ' + _this.l10n.from_ + _el.attr("begin-time") + _this.l10n._to_ + _el.attr("end-time") + '

    '; + for (var _i = 0; _i <= _this.polemics.length; _i++) { + var _color = _i ? _this.polemics[_i - 1].color : _this.defaultcolor; + _html += '

    ' + _nums[_i] + _this.l10n._annotations + '

    ' + } + _this.tooltip.show(_el.attr("pos-x"), _el.attr("pos-y"), _html); + }) + .mouseout(function() { + _this.tooltip.hide(); + }) + + } + + this.$position = IriSP.jQuery('
    ').addClass("Ldt-Polemic-Position"); + + this.$zone.append(this.$position); + + this.$zone.click(function(_e) { + var _x = _e.pageX - _this.$zone.offset().left; + _this.player.popcorn.currentTime(_this.source.getDuration().getSeconds() * _x / _this.width); + }); +} + +IriSP.Widgets.Polemic.prototype.onTimeupdate = function() { + var _x = Math.floor( this.width * this.player.popcorn.currentTime() / this.source.getDuration().getSeconds()); + this.$elapsed.css({ + width: _x + "px" + }); + this.$position.css({ + left: _x + "px" + }) +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Segments.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Segments.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,29 @@ +/* + * Segments Widget + */ + +.Ldt-Segments-List { + width: 100%; height: 100%; +} + +.Ldt-Segments-Segment { + position: absolute; height: 100%; opacity: .5; filter:alpha(opacity=50); margin-left: -1px; border-left: 1px solid #ffffff; +} + +.Ldt-Segments-Segment.inactive, .Ldt-Segments-Segment.unfound { + opacity: .2; filter:alpha(opacity=20); +} + +.Ldt-Segments-Segment.active, .Ldt-Segments-Segment.found { + opacity: 1; filter:alpha(opacity=100); +} + +.Ldt-Segments-Position { + background: #fc00ff; + position: absolute; + top: 0; + left: 0; + margin-left: -1px; + width: 2px; + height: 100%; +} \ No newline at end of file diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Segments.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Segments.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,105 @@ +// TODO: Trigger IriSP.SegmentsWidget.click and IriSP.Mediafragment.showAnnotation + +IriSP.Widgets.Segments = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); +}; + +IriSP.Widgets.Segments.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Segments.prototype.defaults = { + annotation_type : "chap", + colors: ["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"], + requires : [ + { + type: "Tooltip" + } + ], + height: 10 +}; + +IriSP.Widgets.Segments.prototype.template = + '
    {{#segments}}' + + '
    ' + + '{{/segments}}
    ' + + '
    '; + +IriSP.Widgets.Segments.prototype.draw = function() { + this.bindPopcorn("IriSP.search", "onSearch"); + this.bindPopcorn("IriSP.search.closed", "onSearch"); + this.bindPopcorn("IriSP.search.cleared", "onSearch"); + this.bindPopcorn("timeupdate", "onTimeupdate"); + + var _list = this.getWidgetAnnotations(), + _this = this, + _scale = this.width / this.source.getDuration(); + this.$.css({ + width : this.width + "px", + height : (this.height - 2) + "px", + margin : "1px 0" + }); + this.$.append(Mustache.to_html(this.template, { + segments : _list.map(function(_annotation, _k) { + var _left = _annotation.begin * _scale, + _width = ( _annotation.end - _annotation.begin ) * _scale, + _center = _left + _width / 2; + return { + text : _annotation.title + ( _annotation.description ? '
    ' + _annotation.description.replace(/(^.{120,140})[\s].+$/,'$1…') : ''), + color : ( typeof _annotation.color !== "undefined" && _annotation.color ? _annotation.color : _this.colors[_k % _this.colors.length] ), + beginseconds : _annotation.begin.getSeconds() , + left : Math.floor( _left ), + width : Math.floor( _width ), + center : Math.floor( _center ), + id : _annotation.namespacedId.name + } + }) + })); + this.$segments = this.$.find('.Ldt-Segments-Segment'); + + this.$segments.mouseover(function() { + var _el = IriSP.jQuery(this); + _this.$segments.removeClass("active").addClass("inactive"); + _this.tooltip.show( _el.attr("center-pos"), 0, _el.attr("segment-text"), _el.attr("segment-color")); + _el.removeClass("inactive").addClass("active"); + }) + .mouseout(function() { + _this.tooltip.hide(); + _this.$segments.removeClass("inactive active"); + }) + .click(function() { + var _el = IriSP.jQuery(this); + _this.player.popcorn.currentTime(_el.attr("begin-seconds")); + _this.player.popcorn.trigger("IriSP.Mediafragment.setHashToAnnotation", _el.attr("segment-id")); + }); +} + +IriSP.Widgets.Segments.prototype.onSearch = function(searchString) { + this.searchString = typeof searchString !== "undefined" ? searchString : ''; + var _found = 0, + _re = IriSP.Model.regexpFromTextOrArray(searchString); + if (this.searchString) { + this.$segments.each(function() { + var _el = IriSP.jQuery(this); + if (_re.test(_el.attr("segment-text"))) { + _el.removeClass("unfound").addClass("found"); + _found++; + } else { + _el.removeClass("found").addClass("unfound"); + } + }); + if (_found) { + this.player.popcorn.trigger("IriSP.search.matchFound"); + } else { + this.player.popcorn.trigger("IriSP.search.noMatchFound"); + } + } else { + this.$segments.removeClass("found unfound"); + } +} + +IriSP.Widgets.Segments.prototype.onTimeupdate = function() { + var _x = Math.floor( this.width * this.player.popcorn.currentTime() / this.source.getDuration().getSeconds()); + this.$.find('.Ldt-Segments-Position').css({ + left: _x + "px" + }) +} \ No newline at end of file diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Slider.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Slider.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,14 @@ +/* Slider Widget */ + +.Ldt-Slider { + border: none; border-radius: 0; padding: 0; margin: 0; background: #B6B8B8; +} + +.Ldt-Slider .ui-slider-handle { + border-radius: 8px; top: -2px; background: #fc00ff; border: 1px solid #ffffff; +} + +.Ldt-Slider .ui-slider-range { + background: #747474; +} + diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Slider.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Slider.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,114 @@ +/* + The Slider Widget fits right under the video + */ + +IriSP.Widgets.Slider = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); + this.bindPopcorn("timeupdate","onTimeupdate"); + this.bindPopcorn("IriSP.PlayerWidget.MouseOver","onMouseover"); + this.bindPopcorn("IriSP.PlayerWidget.MouseOut","onMouseout"); +}; + +IriSP.Widgets.Slider.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Slider.prototype.defaults = { + minimized_height : 4, + maximized_height : 10, + minimize_timeout : 1500 // time before minimizing slider after mouseout +}; + +IriSP.Widgets.Slider.prototype.draw = function() { + + this.$slider = IriSP.jQuery('
    ') + .addClass("Ldt-Slider") + .css(this.calculateSliderCss(this.minimized_height)); + + this.$.append(this.$slider); + + var _this = this; + + this.$slider.slider({ + range: "min", + value: 0, + min: 0, + max: this.source.getDuration().getSeconds(), + slide: function(event, ui) { + _this.player.popcorn.currentTime(ui.value); + _this.player.popcorn.trigger("IriSP.Mediafragment.setHashToTime"); + } + }); + + this.$handle = this.$slider.find('.ui-slider-handle'); + + this.$handle.css(this.calculateHandleCss(this.minimized_height)); + + this.$ + .mouseover(this.functionWrapper("onMouseover")) + .mouseout(this.functionWrapper("onMouseout")); + + this.maximized = false; + this.timeoutId = false; +}; + +IriSP.Widgets.Slider.prototype.onTimeupdate = function() { + var _time = this.player.popcorn.currentTime(); + this.$slider.slider("value",_time); + this.player.popcorn.trigger("IriSP.Arrow.updatePosition",{widget: this.type, time: 1000 * _time}); +} + +IriSP.Widgets.Slider.prototype.onMouseover = function() { + if (this.timeoutId) { + window.clearTimeout(this.timeoutId); + this.timeoutId = false; + } + if (!this.maximized) { + this.animateToHeight(this.maximized_height); + this.maximized = true; + } +} + +IriSP.Widgets.Slider.prototype.onMouseout = function() { + if (this.timeoutId) { + window.clearTimeout(this.timeoutId); + this.timeoutId = false; + } + var _this = this; + this.timeoutId = window.setTimeout(function() { + if (_this.maximized) { + _this.animateToHeight(_this.minimized_height); + _this.maximized = false; + } + _this.timeoutId = false; + }, this.minimize_timeout); + +} + +IriSP.Widgets.Slider.prototype.animateToHeight = function(_height) { + this.$slider.stop().animate( + this.calculateSliderCss(_height), + 500, + function() { + IriSP.jQuery(this).css("overflow","visible"); + }); + this.$handle.stop().animate( + this.calculateHandleCss(_height), + 500, + function() { + IriSP.jQuery(this).css("overflow","visible"); + }); +} + +IriSP.Widgets.Slider.prototype.calculateSliderCss = function(_size) { + return { + height: _size + "px", + "margin-top": (this.minimized_height - _size) + "px" + }; +} + +IriSP.Widgets.Slider.prototype.calculateHandleCss = function(_size) { + return { + height: (2 + _size) + "px", + width: (2 + _size) + "px", + "margin-left": -Math.ceil(2 + _size / 2) + "px" + } +} \ No newline at end of file diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Tagcloud.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Tagcloud.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,28 @@ +/* + * + */ +.Ldt-Tagcloud-Container { + font-family: "Open Sans", Arial, Helvetica, sans-serif; +} + +ul.Ldt-Tagcloud-List { + padding: 5px; + margin: 0; + list-style: none; + text-align: center; +} + +li.Ldt-Tagcloud-item { + display: inline-block; + margin: 2px; + cursor: pointer; +} + +li.Ldt-Tagcloud-item:hover { + color: #0099ff; +} + +.Ldt-Tagcloud-active { + color: #c000c0; + padding: 0; margin: 0; +} \ No newline at end of file diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Tagcloud.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Tagcloud.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,101 @@ +IriSP.Widgets.Tagcloud = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); + this.stopwords = IriSP._.uniq([].concat(this.custom_stopwords).concat(this.stopword_lists[this.stopword_language])); +} + +IriSP.Widgets.Tagcloud.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Tagcloud.prototype.template = + '
      ' + + '{{#words}}
    • {{word}}
    • {{/words}}' + + '
    '; + +IriSP.Widgets.Tagcloud.prototype.defaults = { + include_titles: true, + include_descriptions: true, + tag_count: 30, + stopword_language: "fr", + custom_stopwords: [], + exclude_pattern: false, + annotation_type: false, + min_font_size: 10, + max_font_size: 26 +} + +IriSP.Widgets.Tagcloud.prototype.stopword_lists = { + "fr" : [ + 'aussi', 'avec', 'aux', 'bien', 'car', 'cette', 'comme', 'dans', 'des', 'donc', 'dont', 'elle', 'encore', 'entre', 'est', + 'être', 'eux', 'faire', 'fait', 'http', 'ici', 'ils', 'les', 'leur', 'leurs', 'mais', 'mes', 'même', 'mon', 'notre', + 'non', 'nos', 'nous', 'ont', 'par', 'pas', 'peu', 'peut', 'plus', 'pour', 'quand', 'que', 'qui', 'quoi', 'sans', + 'ses' ,'son', 'sont', 'sur', 'tes', 'très', 'the', 'ton', 'tous', 'tout', 'une', 'votre', 'vos', 'vous' + ], + "en" : [ + 'about', 'again', 'are', 'and', 'because', 'being', 'but', 'can', 'done', 'have', 'for', 'from', + 'get', 'here', 'http', 'like', 'more', 'one', 'our', 'she', 'that', 'the', 'their', 'then', 'there', + 'they', 'this', 'very', 'what', 'when', 'where', 'who', 'why', 'will', 'with', 'www', 'you', 'your' + ] +} + +IriSP.Widgets.Tagcloud.prototype.draw = function() { + + var _urlRegExp = /https?:\/\/[0-9a-zA-Z\.%\/-_]+/g, + _regexpword = /[^\s\.&;,'"!\?\d\(\)\+\[\]\\\…\-«»:\/]{3,}/g, + _words = {}, + _this = this; + this.getWidgetAnnotations().forEach(function(_annotation) { + var _txt = (_this.include_titles ? _annotation.title : '') + ' ' + (_this.include_descriptions ? _annotation.description : ''); + IriSP._(_txt.toLowerCase().replace(_urlRegExp, '').match(_regexpword)).each(function(_word) { + if (IriSP._(_this.stopwords).indexOf(_word) == -1 && (!_this.exclude_pattern || !_this.exclude_pattern.test(_word))) { + _words[_word] = 1 + (_words[_word] || 0); + } + }) + }); + _words = IriSP._(_words) + .chain() + .map(function(_v, _k) { + return { + "word" : _k, + "count" : _v + } + }) + .filter(function(_v) { + return _v.count > 2; + }) + .sortBy(function(_v) { + return - _v.count; + }) + .first(this.tag_count) + .value(); + var _max = _words[0].count, + _min = Math.min(_words[_words.length - 1].count, _max - 1), + _scale = (this.max_font_size - this.min_font_size) / Math.sqrt(_max - _min); + IriSP._(_words).each(function(_word) { + _word.size = Math.floor( _this.min_font_size + _scale * Math.sqrt(_word.count - _min) ); + }); + this.words = _words; + this.renderTemplate(); + this.$words = this.$.find(".Ldt-Tagcloud-item"); + this.$words.click(function() { + var _txt = IriSP.jQuery(this).attr("content"); + _this.player.popcorn.trigger("IriSP.search.triggeredSearch", _txt); + }); + this.bindPopcorn("IriSP.search", "onSearch"); + this.bindPopcorn("IriSP.search.closed", "onSearch"); + this.bindPopcorn("IriSP.search.cleared", "onSearch"); +} + +IriSP.Widgets.Tagcloud.prototype.onSearch = function(searchString) { + searchString = typeof searchString !== "undefined" ? searchString : ''; + if (searchString) { + var _rgxp = IriSP.Model.regexpFromTextOrArray(searchString); + } + this.$words.each(function() { + var _el = IriSP.jQuery(this), + _txt = _el.attr("content"); + if (searchString) { + _el.html(_txt.replace(_rgxp, '$1')); + } else { + _el.html(_txt); + } + }); +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Tooltip.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Tooltip.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,29 @@ +/* ToolTip Widget */ + +.Ldt-Tooltip { + position: absolute; + padding : 3px; + z-index: 10000000000; + max-width: 200px; + background: transparent url("img/white_arrow_long.png"); + font-size: 12px; + height: 115px; + width: 180px; + padding: 15px 15px 20px; + color: black; + font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif"; + overflow:hidden; +} + +.Ldt-Tooltip-Color { + float: left; margin: 2px 4px 2px 0; width: 10px; height: 10px; +} + +.Ldt-Tooltip img { + max-width: 140px; max-height: 70px; margin: 0 20px; +} + +.Ldt-Tooltip p { + margin: 2px 0; + font-size: 12px; +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Tooltip.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Tooltip.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,42 @@ +/* this widget displays a small tooltip */ +IriSP.Widgets.Tooltip = function(Popcorn, config, Serializer) { + IriSP.Widgets.Widget.call(this, Popcorn, config, Serializer); +}; + +IriSP.Widgets.Tooltip.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Tooltip.prototype.template = '
    '; + +IriSP.Widgets.Tooltip.prototype.draw = function() { + _this = this; + this.$.html(this.template); + this.$.parent().css({ + "position" : "relative" + }); + this.$tip = this.$.find(".Ldt-Tooltip"); + this.$.mouseover(function() { + _this.$tip.hide(); + }); + this.hide(); +}; + +IriSP.Widgets.Tooltip.prototype.show = function(x, y, text, color) { + + if (typeof color !== "undefined") { + this.$.find(".Ldt-Tooltip-Color").show().css("background-color", color); + } else { + this.$.find(".Ldt-Tooltip-Color").hide(); + } + + this.$.find(".Ldt-Tooltip-Text").html(text); + + this.$tip.show(); + this.$tip.css({ + "left" : Math.floor(x - this.$tip.outerWidth() / 2) + "px", + "top" : Math.floor(y - this.$tip.outerHeight()) + "px" + }); +}; + +IriSP.Widgets.Tooltip.prototype.hide = function() { + this.$tip.hide(); +}; diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Trace.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Trace.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,148 @@ +IriSP.Widgets.Trace = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); + +} + +IriSP.Widgets.Trace.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Trace.prototype.defaults = { + js_console : false, + url: "http://traces.advene.org:5000/", + requestmode: 'GET', + syncmode: "sync" +} + +IriSP.Widgets.Trace.prototype.draw = function() { + this.lastEvent = ""; + if (typeof window.tracemanager === "undefined") { + console.log("Tracemanager not found"); + return; + } + var _this = this, + _listeners = { + "IriSP.createAnnotationWidget.addedAnnotation" : 0, + "IriSP.search.open" : 0, + "IriSP.search.closed" : 0, + "IriSP.search" : 0, + "IriSP.search.cleared" : 0, + "IriSP.search.matchFound" : 0, + "IriSP.search.noMatchFound" : 0, + "IriSP.search.triggeredSearch" : 0, + "IriSP.TraceWidget.MouseEvents" : 0, + "play" : 0, + "pause" : 0, + "volumechange" : 0, + "seeked" : 0, + "play" : 0, + "pause" : 0, + "timeupdate" : 2000 + }; + IriSP._(_listeners).each(function(_ms, _listener) { + var _f = function(_arg) { + _this.eventHandler(_listener, _arg); + } + if (_ms) { + _f = IriSP._.throttle(_f, _ms); + } + _this.player.popcorn.listen(_listener, _f); + }); + this.player.popcorn.listen("timeupdate", IriSP._.throttle(function(_arg) { + _this.eventHandler(_listener, _arg); + })); + + this.tracer = window.tracemanager.init_trace("test", { + url: this.url, + requestmode: this.requestmode, + syncmode: this.syncmode + }); + this.tracer.set_default_subject("metadataplayer"); + this.tracer.trace("StartTracing", {}); + + this.mouseLocation = ''; + IriSP.jQuery(".Ldt-Widget").bind("click mouseover mouseout dragstart dragstop", function(_e) { + var _widget = IriSP.jQuery(this).attr("widget-type"), + _class = _e.target.className; + var _data = { + "type": _e.type, + "x": _e.clientX, + "y": _e.clientY, + "widget": _widget + } + if (typeof _class == "string" && _class.indexOf('Ldt-TraceMe') != -1) { + var _name = _e.target.localName, + _id = _e.target.id, + _text = _e.target.textContent.trim(), + _title = _e.target.title, + _value = _e.target.value; + _data.target = _name + (_id.length ? '#' + IriSP.jqEscape(_id) : '') + (_class.length ? ('.' + IriSP.jqEscape(_class).replace(/\s/g,'.')).replace(/\.Ldt-(Widget|TraceMe)/g,'') : ''); + if (typeof _title == "string" && _title.length && _title.length < 140) { + _data.title = _title; + } + if (typeof _text == "string" && _text.length && _text.length < 140) { + _data.text = _text; + } + if (typeof _value == "string" && _value.length) { + _data.value = _value; + } + this.player.popcorn.trigger('IriSP.TraceWidget.MouseEvents', _data); + } else { + //console.log(_e.type+','+_this.mouseLocation+','+_widget); + if (_e.type == "mouseover") { + if (_this.mouseLocation != _widget) { + _this.player.popcorn.trigger('IriSP.TraceWidget.MouseEvents', _data); + } else { + if (typeof _this.moTimeout != "undefined") { + clearTimeout(_this.moTimeout); + delete _this.moTimeout; + } + } + } + if (_e.type == "click") { + _this.player.popcorn.trigger('IriSP.TraceWidget.MouseEvents', _data); + } + if (_e.type == "mouseout") { + if (typeof _this.moTimeout != "undefined") { + clearTimeout(_this.moTimeout); + } + _this.moTimeout = setTimeout(function() { + if (_data.widget != _this.mouseLocation) { + _this.player.popcorn.trigger('IriSP.TraceWidget.MouseEvents', _data); + } + },100); + } + } + _this.mouseLocation = _widget; + }); +} + +IriSP.Widgets.Trace.prototype.eventHandler = function(_listener, _arg) { + var _traceName = 'Mdp_'; + if (typeof _arg == "string" || typeof _arg == "number") { + _arg = { "value" : _arg } + } + if (typeof _arg == "undefined") { + _arg = {} + } + switch(_listener) { + case 'IriSP.TraceWidget.MouseEvents': + _traceName += _arg.widget + '_' + _arg.type; + delete _arg.widget; + delete _arg.type; + break; + case 'timeupdate': + case 'play': + case 'pause': + _arg.time = this.player.popcorn.currentTime() * 1000; + case 'seeked': + case 'volumechange': + _traceName += 'Popcorn_' + _listener; + break; + default: + _traceName += _listener.replace('IriSP.','').replace('.','_'); + } + this.lastEvent = _traceName; + this.tracer.trace(_traceName, _arg); + if (this.js_console) { + console.log("tracer.trace('" + _traceName + "', " + JSON.stringify(_arg) + ");"); + } +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Tweet.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Tweet.css Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,105 @@ +.Ldt-Tweet-Widget { + border: 1px solid #b7b7b7; + padding: 1px; + margin: 0; + font-family: Helvetica, Arial, sans-serif; +} + +.Ldt-Tweet-Inner { + background: url(img/pinstripe.png); + padding: 5px; + margin: 0; + min-height: 50px; +} + +.Ldt-Tweet-PinClose-Buttons { + float: right; +} + +.Ldt-Tweet-PinClose-Buttons a { + display: inline-block; width: 17px; height: 17px; margin: 2px; + background: url(img/widget-control.png); +} + +a.Ldt-Tweet-Pin { + background-position: 0 -17px; +} + +a.Ldt-Tweet-Pin:hover, a.Ldt-Tweet-Pin.active { + background-position: -17px -17px; +} + +a.Ldt-Tweet-Pin.active:hover { + background-position: 0 -17px; +} + +a.Ldt-Tweet-Close:hover { + background-position: -17px 0; +} + +.Ldt-Tweet-AvatarContainer { + float: left; width: 48px; height: 48px; margin: 2px 4px 2px 0; +} + +.Ldt-Tweet-Avatar { + border: none; width: 48px; height: 48px; +} + +.Ldt-Tweet-Inner h3 { + margin: 2px 0 5px 52px; + font-size: 14px; +} + +a.Ldt-Tweet-ScreenName { + color: #0068c4; + text-decoration: none; +} + +a.Ldt-Tweet-ScreenName:hover { + color: #000000; + text-decoration: underline; +} + +p.Ldt-Tweet-Contents { + margin: 5px 0 5px 52px; + font-size: 12px; +} + +.Ldt-Tweet-Bottom { + margin: 5px 0 0; + font-size: 12px; + text-align: right; +} + +.Ldt-Tweet-Time { + display: inline-block; +} + +.Ldt-Tweet-Bottom a { + display: inline-block; + margin-left: 12px; + color: #000000; + text-decoration: none; +} + +.Ldt-Tweet-Bottom a:hover { + text-decoration: underline; +} + +.Ldt-Tweet-Icon { + display: inline-block; width: 16px; height: 16px; + margin: 0 2px -2px; + background: url(img/twitter_sprites.png); +} + +.Ldt-Tweet-Retweet .Ldt-Tweet-Icon { + background-position: -80px 0; +} + +.Ldt-Tweet-Retweet:hover .Ldt-Tweet-Icon { + background-position: -96px 0; +} + +.Ldt-Tweet-Reply:hover .Ldt-Tweet-Icon { + background-position: -16px 0; +} \ No newline at end of file diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/Tweet.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/res/metadataplayer/Tweet.js Thu May 03 17:52:07 2012 +0200 @@ -0,0 +1,196 @@ +IriSP.Widgets.Tweet = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); + this.lastAnnotation = false; +}; + +IriSP.Widgets.Tweet.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Tweet.prototype.defaults = { + hide_timeout: 5000, + polemics : [ + { + "keywords" : [ "++" ], + "description" : "positif", + "color" : "#30d765" + }, + { + "keywords" : [ "--" ], + "description" : "negatif", + "color" : "#f51123" + }, + { + "keywords" : [ "==" ], + "description" : "reference", + "color" : "#f1e24a" + }, + { + "keywords" : [ "??" ], + "description" : "question", + "color" : "#05aae6" + } + ] +} + +IriSP.Widgets.Tweet.prototype.messages = { + "fr": { + retweet: "Retweeter", + reply: "Répondre", + keep_visible: "Garder visible", + dont_keep_visible: "Permettre la fermeture automatique", + close_widget: "Fermer l'affichage du tweet", + original_time: "Heure d'envoi  ", + video_time: "Temps de la vidéo : " + }, + "en": { + retweet: "Retweet", + reply: "Reply", + keep_visible: "Keep visible", + dont_keep_visible: "Don't keep visible", + close_widget: "Close tweet display", + original_time: "Tweet sent at: ", + video_time: "Video time: " + } +} + +IriSP.Widgets.Tweet.prototype.template = + '
    ' + + '' + + '' + + '

    ' + + ' ()

    '; + + +IriSP.Widgets.Tweet.prototype.draw = function() { + this.renderTemplate(); + this.bindPopcorn("IriSP.Tweet.show","show"); + this.pinned = false; + var _this = this; + this.$.find(".Ldt-Tweet-Pin").click(function() { + _this.pinned = !_this.pinned; + var _el = IriSP.jQuery(this) + if (_this.pinned) { + _el.addClass("active").attr("title",_this.l10n.dont_keep_visible); + _this.cancelTimeout(); + } else { + _el.removeClass("active").attr("title",_this.l10n.keep_visible); + _this.hideTimeout(); + } + }); + this.$.find(".Ldt-Tweet-Close").click(function() { + _this.hide(); + }); + this.$.hide(); +} + +IriSP.Widgets.Tweet.prototype.show = function(_id) { + var _tweet = this.source.getElement(_id); + if (typeof _tweet !== "undefined" && typeof _tweet.source !== "undefined") { + var _entities = []; + for (var _i = 0; _i < _tweet.source.entities.hashtags.length; _i++) { + var _hash = _tweet.source.entities.hashtags[_i]; + _entities.push({ + is_link: true, + text: '#' + _hash.text, + url: 'http://twitter.com/search?q=%23' + encodeURIComponent(_hash.text), + indices: _hash.indices + }); + } + for (var _i = 0; _i < _tweet.source.entities.urls.length; _i++) { + var _url = _tweet.source.entities.urls[_i], + _displayurl = (typeof _url.display_url !== "undefined" && _url.display_url !== null ? _url.display_url : _url.url), + _linkurl = (typeof _url.expanded_url !== "undefined" && _url.expanded_url !== null ? _url.expanded_url : _url.url); + _displayurl = _displayurl.replace(/^\w+:\/\//,''); + if (!/^\w+:\/\//.test(_linkurl)) { + _linkurl = 'http://' + _linkurl; + } + _entities.push({ + is_link: true, + text: _displayurl, + url: _linkurl, + indices: _url.indices + }); + } + for (var _i = 0; _i < _tweet.source.entities.user_mentions.length; _i++) { + var _user = _tweet.source.entities.user_mentions[_i]; + _entities.push({ + is_link: true, + text: '@' + _user.screen_name, + url: 'http://twitter.com/' + encodeURIComponent(_user.screen_name), + indices: _user.indices + }); + } + for (var _i = 0; _i < this.polemics.length; _i++) { + for (var _j = 0; _j < this.polemics[_i].keywords.length; _j++) { + var _p = _tweet.source.text.indexOf(this.polemics[_i].keywords[_j]); + while (_p !== -1) { + var _end = (_p + this.polemics[_i].keywords[_j].length); + _entities.push({ + is_link: false, + text: this.polemics[_i].keywords[_j], + color: this.polemics[_i].color, + indices: [_p, _end] + }); + _p = _tweet.source.text.indexOf(this.polemics[_i].keywords[_j], _end); + } + } + } + _entities = IriSP._(_entities).sortBy(function(_entity) { + return _entity.indices[0]; + }); + var _currentPos = 0, + _txt = ''; + for (var _i = 0; _i < _entities.length; _i++) { + if (_entities[_i].indices[0] >= _currentPos) { + _txt += _tweet.source.text.substring(_currentPos, _entities[_i].indices[0]); + _currentPos = _entities[_i].indices[1]; + if (_entities[_i].is_link) { + _txt += ''; + } else { + _txt += ''; + } + _txt += _entities[_i].text; + if (_entities[_i].is_link) { + _txt += ''; + } else { + _txt += ''; + } + } + } + _txt += _tweet.source.text.substring(_currentPos); + this.$.find(".Ldt-Tweet-Avatar").attr("src",_tweet.source.user.profile_image_url); + this.$.find(".Ldt-Tweet-ScreenName").html('@'+_tweet.source.user.screen_name); + this.$.find(".Ldt-Tweet-ProfileLink").attr("href", "http://twitter.com/" + _tweet.source.user.screen_name); + this.$.find(".Ldt-Tweet-FullName").html(_tweet.source.user.name); + this.$.find(".Ldt-Tweet-Contents").html(_txt); + this.$.find(".Ldt-Tweet-Time").html(this.l10n.original_time + new Date(_tweet.source.created_at).toLocaleTimeString() + " / " + this.l10n.video_time + _tweet.begin.toString()); + this.player.popcorn.trigger("IriSP.Annotation.minimize"); + this.$.slideDown(); + this.cancelTimeout(); + if (!this.pinned) { + this.hideTimeout(); + } + } else { + this.hide(); + } +} + +IriSP.Widgets.Tweet.prototype.hide = function() { + this.player.popcorn.trigger("IriSP.Annotation.maximize"); + this.$.slideUp(); + this.cancelTimeout(); +} + +IriSP.Widgets.Tweet.prototype.cancelTimeout = function() { + if (typeof this.hide_timer !== "undefined") { + window.clearTimeout(this.hide_timer); + this.hide_timer = undefined; + } +} + +IriSP.Widgets.Tweet.prototype.hideTimeout = function() { + this.cancelTimeout(); + this.hide_timer = window.setTimeout(this.functionWrapper("hide"), this.hide_timeout); +} diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/loader.gif Binary file web/res/metadataplayer/img/loader.gif has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/pinstripe-grey.png Binary file web/res/metadataplayer/img/pinstripe-grey.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/pinstripe.png Binary file web/res/metadataplayer/img/pinstripe.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/player-sprites.png Binary file web/res/metadataplayer/img/player-sprites.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/player_gradient.png Binary file web/res/metadataplayer/img/player_gradient.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/slice-handles.png Binary file web/res/metadataplayer/img/slice-handles.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/socialbuttons.png Binary file web/res/metadataplayer/img/socialbuttons.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/twitter_sprites.png Binary file web/res/metadataplayer/img/twitter_sprites.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/white_arrow_long.png Binary file web/res/metadataplayer/img/white_arrow_long.png has changed diff -r 07ab28bca482 -r d366aa22bd79 web/res/metadataplayer/img/widget-control.png Binary file web/res/metadataplayer/img/widget-control.png has changed