r76689 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r76688‎ | r76689 | r76690 >
Date:17:33, 15 November 2010
Author:dale
Status:deferred
Tags:
Comment:
sync with kaltura svn. Some whitespace fixes scripts may have to be re-run. ( merge got tricky because I had not keep mwEmbedStandAlone up-to-date )
Modified paths:
  • /branches/MwEmbedStandAlone/DefaultSettings.js (modified) (history)
  • /branches/MwEmbedStandAlone/libraries/jquery/plugins/jquery.postmessage.js (added) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/loader.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerNative.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.IFramePlayerApiClient.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Playlist/mw.Playlist.js (modified) (history)
  • /branches/MwEmbedStandAlone/mwEmbed.js (modified) (history)
  • /branches/MwEmbedStandAlone/mwEmbedFrame.php (modified) (history)

Diff [purge]

Index: branches/MwEmbedStandAlone/DefaultSettings.js
@@ -0,0 +1,4 @@
 2+/**
 3+* Custom Javascript Configuration included on every request.
 4+* In a default svn checkout this file should always be empty.
 5+*/
\ No newline at end of file
Index: branches/MwEmbedStandAlone/mwEmbedFrame.php
@@ -12,8 +12,8 @@
1313 // Setup the mwEmbedFrame
1414 $myMwEmbedFrame = new mwEmbedFrame();
1515
16 -// Do mwEmbedFrame output:
17 -$myMwEmbedFrame->outputFrame();
 16+// Do mwEmbedFrame video output:
 17+$myMwEmbedFrame->outputIFrame();
1818
1919 /**
2020 * mwEmbed iFrame class
@@ -29,11 +29,13 @@
3030 'poster',
3131 'kentryid',
3232 'kwidgetid',
 33+ 'kuiconfid',
 34+ 'kplaylistid',
3335 'skin'
3436 );
3537 var $playerIframeId = 'iframeVid';
3638 var $debug = false;
37 -
 39+
3840 // When used in direct source mode the source asset.
3941 // NOTE: can be an array of sources in cases of "many" sources set
4042 var $sources = array();
@@ -42,39 +44,55 @@
4345 //parse input:
4446 $this->parseRequest();
4547 }
46 - function outputFrame(){
47 - // Presently only video frame supported:
48 - $this->outputEmbedFrame();
49 - }
50 -
 48+
5149 // Parse the embedFrame request and sanitize input
5250 private function parseRequest(){
 51+ // Check for / attribute type request and update "REQUEST" global
 52+ // ( uses kaltura standard entry_id/{entryId} request )
 53+ // normalize to the REQUEST object
 54+ // @@FIXME: this should be moved over to a kaltura specific iframe implementation
 55+ if( $_SERVER['REQUEST_URI'] ){
 56+ $kalturaUrlMap = Array(
 57+ 'entry_id' => 'kentryid',
 58+ 'uiconf_id' => 'kuiconfid',
 59+ 'wid' => 'kwidgetid',
 60+ 'playlist_id' => 'kplaylistid'
 61+ );
 62+ $urlParts = explode( '/', $_SERVER['REQUEST_URI'] );
 63+ foreach( $urlParts as $inx => $urlPart ){
 64+ foreach( $kalturaUrlMap as $urlKey => $reqeustAttribute ){
 65+ if( $urlPart == $reqeustAttribute && isset( $urlParts[$inx+1] ) ){
 66+ $_REQUEST[ $reqeustAttribute ] = $urlParts[$inx+1];
 67+ }
 68+ }
 69+ }
 70+ }
5371 // Check for attributes
5472 foreach( $this->playerAttributes as $attributeKey){
55 - if( isset( $_GET[ $attributeKey ] ) ){
56 - $this->$attributeKey = htmlspecialchars( $_GET[$attributeKey] );
 73+ if( isset( $_REQUEST[ $attributeKey ] ) ){
 74+ $this->$attributeKey = htmlspecialchars( $_REQUEST[$attributeKey] );
5775 }
5876 }
5977
6078 // Check for debug flag
61 - if( isset( $_GET['debug'] ) ){
 79+ if( isset( $_REQUEST['debug'] ) ){
6280 $this->debug = true;
6381 }
64 -
 82+
6583 // Process the special "src" attribute
66 - if( isset( $_GET['src'] ) ){
67 - if( is_array( $_GET['src'] ) ){
68 - foreach($_GET['src'] as $src ){
 84+ if( isset( $_REQUEST['src'] ) ){
 85+ if( is_array( $_REQUEST['src'] ) ){
 86+ foreach($_REQUEST['src'] as $src ){
6987 $this->sources[] = htmlspecialchars( $src );
7088 }
7189 } else {
72 - $this->sources = array( htmlspecialchars( $_GET['src'] ) );
 90+ $this->sources = array( htmlspecialchars( $_REQUEST['src'] ) );
7391 }
7492 }
75 -
 93+
7694 }
7795 private function getVideoTag( ){
78 - // Add default video tag with 100% width / height
 96+ // Add default video tag with 100% width / height
7997 // ( parent embed is responsible for setting the iframe size )
8098 $o = '<video id="' . htmlspecialchars( $this->playerIframeId ) . '" style="width:100%;height:100%"';
8199 foreach( $this->playerAttributes as $attributeKey){
@@ -92,11 +110,12 @@
93111 }
94112 $o.= '</video>';
95113 return $o;
96 - }
97 - private function outputEmbedFrame( ){
 114+ }
 115+
 116+ function outputIFrame( ){
98117 // Setup the embed string based on attribute set:
99118 $embedResourceList = 'window.jQuery,mwEmbed,mw.style.mwCommon,$j.fn.menu,mw.style.jquerymenu,mw.EmbedPlayer,mw.EmbedPlayerNative,mw.EmbedPlayerJava,mw.PlayerControlBuilder,$j.fn.hoverIntent,mw.style.EmbedPlayer,$j.cookie,$j.ui,mw.style.ui_redmond,$j.widget,$j.ui.mouse,mw.PlayerSkinKskin,mw.style.PlayerSkinKskin,mw.TimedText,mw.style.TimedText,$j.ui.slider';
100 -
 119+
101120 if( isset( $this->kentryid ) ){
102121 $embedResourceList.= ',' . implode(',', array(
103122 'KalturaClientBase',
@@ -106,7 +125,7 @@
107126 'KalturaAccessControl',
108127 'MD5',
109128 'mw.KWidgetSupport',
110 - 'mw.KAnalytics',
 129+ 'mw.KAnalytics',
111130 'mw.KDPMapping',
112131 'mw.MobileAdTimeline',
113132 'mw.KAds'
@@ -126,43 +145,52 @@
127146 left:0px;
128147 bottom:0px;
129148 right:0px;
130 -
 149+
131150 }
132151 </style>
133 - <script type="text/javascript" src="ResourceLoader.php?class=<?php
 152+ <script type="text/javascript" src="<?php echo str_replace( 'mwEmbedFrame.php', '', $_SERVER['SCRIPT_NAME'] ); ?>ResourceLoader.php?class=<?php
 153+ // @@TODO we should move this over to using the mwEmbedLoader.js so we don't have to mannage the resource list in two places.
 154+ // ( this will matter less once we migrate to the new mediaWiki resource loader framework)
134155 echo $embedResourceList;
135156 if( $this->debug ){
136157 echo '&debug=true';
137 - }
 158+ }
138159 ?>"></script>
139 -
 160+
140161 <script type="text/javascript">
141162 //Set some iframe embed config:
142 - // We can't support full screen in object context since it requires outter page DOM control
 163+ // We can't support full screen in object context since it requires outer page DOM control
143164 mw.setConfig( 'EmbedPlayer.EnableFullscreen', false );
144165
145166 // Enable the iframe player server:
146 - mw.setConfig( 'EmbedPlayer.EnalbeIFramePlayerServer', true );
147 -
 167+ mw.setConfig( 'EmbedPlayer.EnableIFramePlayerServer', true );
 168+
148169 mw.ready(function(){
149 - // Trigger fullscreen so that iframe resize keeps player size
150 - $j( '#<?php echo htmlspecialchars( $this->playerIframeId )?>' )
151 - .get(0).fullscreen();
 170+ // Bind window resize to reize the player:
 171+ $j(window).resize(function(){
 172+ $j( '#<?php echo htmlspecialchars( $this->playerIframeId )?>' )
 173+ .get(0).resizePlayer({
 174+ 'width' : $j(window).width(),
 175+ 'height' : $j(window).height()
 176+ });
 177+ });
152178 });
153179 </script>
154 - </head>
155 - <body>
156 - <?php
157 - // Check if we have a way to get sources:
158 - if( isset( $this->apiTitleKey ) || isset( $this->kentryid ) || count( $this->sources ) != 0 ) {
 180+
 181+ </head>
 182+ <body>
 183+ <?
 184+ // Check if we have a way to get sources:
 185+ if( isset( $this->apiTitleKey ) || isset( $this->kentryid ) || count( $this->sources ) != 0 ) {
159186 echo $this->getVideoTag();
160 - } else {
161 - echo "Error: mwEmbedFrame missing required parameter for video sources";
162 - }
163 - ?>
164 - </body>
 187+ } else {
 188+ echo "Error: mwEmbedFrame missing required parameter for video sources</body></html>";
 189+ exit(1);
 190+ }
 191+ ?>
 192+ </body>
165193 </html>
166194 <?php
167195 }
168196 }
169 - ?>
 197+?>
Index: branches/MwEmbedStandAlone/mwEmbed.js
@@ -81,21 +81,34 @@
8282 }
8383 return ;
8484 }
 85+ mwConfig[ name ] = value;
 86+ };
 87+ /**
 88+ * Merge in a configuration value:
 89+ */
 90+ mw.mergeConfig = function( name, value ){
 91+ if( typeof name == 'object' ) {
 92+ $j.each( name, function( inx, val) {
 93+ mw.setConfig( inx, val );
 94+ });
 95+ return ;
 96+ }
8597 // Check if we should "merge" the config
8698 if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) {
8799 if ( value.constructor.toString().indexOf("Array") == -1 ){
 100+ // merge in the array
 101+ mwConfig[ name ] = mwConfig[ name ].concat( value );
 102+ } else {
88103 for( var i in value ){
89104 mwConfig[ name ][ i ] = value[ i ];
90105 }
91 - } else {
92 - // merge in the array
93 - mwConfig[ name ] = mwConfig[ name ].concat( value );
94106 }
95 - } else {
96 - mwConfig[ name ] = value;
 107+ return ;
97108 }
 109+ // else do a normal setConfig
 110+ mwConfig[ name ] = value;
98111 };
99 -
 112+
100113 /**
101114 * Set a default config value Will only update configuration if no value is
102115 * present
@@ -120,16 +133,7 @@
121134 }
122135 // Check if we should "merge" the config
123136 if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) {
124 - if ( value.constructor.toString().indexOf("Array") == -1 ){
125 - for( var i in value ){
126 - if( typeof mwConfig[ name ][ i ] == 'undefined' ){
127 - mwConfig[ name ][ i ] = value[ i ];
128 - }
129 - }
130 - } else {
131 - // merge in the array
132 - mwConfig[ name ] = mwConfig[ name ].concat( value);
133 - }
 137+ mw.mergeConfig( name, value);
134138 }
135139 };
136140
@@ -1150,39 +1154,64 @@
11511155 uiRequest
11521156 ], function() {
11531157 var $dialog = $j( '#mwTempLoaderDialog' ).show().dialog( options );
1154 - // center the dialog
1155 - // xxx figure out why jquery ui is messing up here
1156 - /*$j( '#mwTempLoaderDialog' ).parent('.ui-dialog').css({
1157 - 'position' : 'absolute',
1158 - 'left' : '50%',
1159 - 'margin-left': -1 * $dialog.width()/2,
1160 - 'top' : '50%',
1161 - 'margin-top': -1 * $dialog.height()/2
1162 - }); */
11631158 } );
11641159 return $j( '#mwTempLoaderDialog' );
11651160 };
11661161
11671162 /**
1168 - * Mobile HTML5 has special properties for html5 video::
1169 - *
 1163+ * Fallforward system by default prefers flash.
 1164+ *
 1165+ * This is separate from the EmbedPlayer library detection to provide package loading control
11701166 * NOTE: should be phased out in favor of browser feature detection where possible
 1167+ *
11711168 */
1172 - mw.isMobileHTML5 = function() {
1173 - // check mobile safari foce ( for debug )
1174 - if( mw.getConfig( 'forceMobileHTML5' ) || document.URL.indexOf('forceMobileHTML5') != -1 ){
 1169+ mw.isHTML5FallForwardNative = function(){
 1170+ // Check for a mobile html5 user agent:
 1171+ if ( (navigator.userAgent.indexOf('iPhone') != -1) ||
 1172+ (navigator.userAgent.indexOf('iPod') != -1) ||
 1173+ (navigator.userAgent.indexOf('iPad') != -1) ||
 1174+ (navigator.userAgent.indexOf('Android 2.') != -1) ||
 1175+ // to debug in chrome / desktop safari
 1176+ (document.URL.indexOf('forceMobileHTML5') != -1 )
 1177+ ) {
11751178 return true;
11761179 }
1177 - if (( navigator.userAgent.indexOf('iPhone') != -1) ||
1178 - ( navigator.userAgent.indexOf('iPod') != -1) ||
1179 - ( navigator.userAgent.indexOf('iPad') != -1) ||
1180 - ( mw.isAndroid2() )
1181 - ) {
 1180+
 1181+ // Check if the client does not have flash and has the video tag
 1182+ if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) {
 1183+ for ( var i = 0; i < navigator.mimeTypes.length; i++ ) {
 1184+ var type = navigator.mimeTypes[i].type;
 1185+ var semicolonPos = type.indexOf( ';' );
 1186+ if ( semicolonPos > -1 ) {
 1187+ type = type.substr( 0, semicolonPos );
 1188+ }
 1189+ if (type == 'application/x-shockwave-flash' ) {
 1190+ // flash is installed don't use html5
 1191+ return false;
 1192+ }
 1193+ }
 1194+ }
 1195+
 1196+ // For IE:
 1197+ var hasObj = true;
 1198+ try {
 1199+ var obj = new ActiveXObject( 'ShockwaveFlash.ShockwaveFlash' );
 1200+ } catch ( e ) {
 1201+ hasObj = false;
 1202+ }
 1203+ if( hasObj ){
 1204+ return false;
 1205+ }
 1206+ // No flash return true if the browser supports html5 video tag with basic support for canPlayType:
 1207+ var dummyvid = document.createElement( "video" );
 1208+ // temporary hack firefox does not work well with native player:
 1209+ if( dummyvid.canPlayType && !$j.browser.mozilla) {
11821210 return true;
11831211 }
 1212+ // No video tag or flash, return false ( normal "install flash" user flow )
11841213 return false;
1185 - };
1186 - // Android 2 has some restrictions vs other mobile platforms
 1214+ }
 1215+ // Android 2 has some restrictions vs other mobile platforms
11871216 mw.isAndroid2 = function(){
11881217 if ( navigator.userAgent.indexOf('Android 2.') != -1) {
11891218 return true;
@@ -1602,7 +1631,6 @@
16031632 }
16041633 return false;
16051634 };
1606 -
16071635 /**
16081636 * Given a float number of seconds, returns npt format response. ( ignore
16091637 * days for now )
@@ -1646,7 +1674,6 @@
16471675 }
16481676 return hoursStr + tm.minutes + ":" + tm.seconds;
16491677 };
1650 -
16511678 /**
16521679 * Given seconds return array with 'days', 'hours', 'min', 'seconds'
16531680 *
@@ -1663,11 +1690,14 @@
16641691 };
16651692
16661693 /**
1667 - * Take hh:mm:ss,ms or hh:mm:ss.ms input, return the number of seconds
 1694+ * Given a float number of seconds, returns npt format response. ( ignore
 1695+ * days for now )
16681696 *
1669 - * @param {String}
1670 - * npt_str NPT time string
1671 - * @return {Float} Number of seconds
 1697+ * @param {Float}
 1698+ * sec Seconds
 1699+ * @param {Boolean}
 1700+ * verbose If hours and milliseconds should padded be displayed.
 1701+ * @return {Float} String npt format
16721702 */
16731703 mw.npt2seconds = function ( npt_str ) {
16741704 if ( !npt_str ) {
Index: branches/MwEmbedStandAlone/modules/Playlist/mw.Playlist.js
@@ -257,7 +257,7 @@
258258 $videoList.show()
259259 // show the video list and apply the swipe binding
260260 $j( _this.target ).find('.media-rss-video-list-wrapper').fadeIn();
261 - if( mw.isMobileHTML5() ){
 261+ if( mw.isHTML5FallForwardNative() ){
262262 // iScroll is buggy with current version of iPad / iPhone use scroll buttons instead
263263 /*
264264 document.addEventListener('touchmove', function(e){ e.preventDefault(); });
@@ -444,7 +444,7 @@
445445 // see: http://developer.apple.com/iphone/search/search.php?simp=1&num=10&Search=html5+autoplay
446446 var updateVideoPlayerToDom = true;
447447
448 - if( mw.isMobileHTML5() ){
 448+ if( mw.isHTML5FallForwardNative() ){
449449 // Check for a current video:
450450 var $inDomVideo = $j( _this.target + ' .media-rss-video-player video' );
451451 if( $inDomVideo.length == 0 ){
@@ -588,7 +588,7 @@
589589 .click( function(){
590590 mw.log( 'clicked on: ' + $j( this ).data( 'clipIndex') );
591591 // Make sure the existing player is "playing " (safari can't play async with javascript )
592 - /*if( mw.isMobileHTML5() ){
 592+ /*if( mw.isHTML5FallForwardNative() ){
593593 var embedPlayer = $j('#' + _this.getVideoPlayerId() ).get(0);
594594 //embedPlayer.playerElement.play();
595595 }*/
@@ -612,7 +612,7 @@
613613
614614 play: function(){
615615 var embedPlayer = $j('#' + this.getVideoPlayerId() ).get(0);
616 - if( mw.isMobileHTML5() ){
 616+ if( mw.isHTML5FallForwardNative() ){
617617 embedPlayer.playerElement.play();
618618 } else{
619619 embedPlayer.play();
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/loader.js
@@ -82,6 +82,133 @@
8383 'EmbedPLayer.IFramePlayer.DomainWhiteList' : '*'
8484 } );
8585
 86+ /*
 87+ * The default video attributes supported by embedPlayer
 88+ */
 89+ mw.setDefaultConfig('EmbedPlayer.Attributes', {
 90+ /*
 91+ * Base html element attributes:
 92+ */
 93+
 94+ // id: Auto-populated if unset
 95+ "id" : null,
 96+
 97+ // Width: alternate to "style" to set player width
 98+ "width" : null,
 99+
 100+ // Height: alternative to "style" to set player height
 101+ "height" : null,
 102+
 103+ /*
 104+ * Base html5 video element attributes / states also see:
 105+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
 106+ */
 107+
 108+ // Media src URI, can be relative or absolute URI
 109+ "src" : null,
 110+
 111+ // Poster attribute for displaying a place holder image before loading
 112+ // or playing the video
 113+ "poster" : null,
 114+
 115+ // Autoplay if the media should start playing
 116+ "autoplay" : false,
 117+
 118+ // Loop attribute if the media should repeat on complete
 119+ "loop" : false,
 120+
 121+ // If the player controls should be displayed
 122+ "controls" : true,
 123+
 124+ // Video starts "paused"
 125+ "paused" : true,
 126+
 127+ // ReadyState an attribute informs clients of video loading state:
 128+ // see: http://www.whatwg.org/specs/web-apps/current-work/#readystate
 129+ "readyState" : 0,
 130+
 131+ // Loading state of the video element
 132+ "networkState" : 0,
 133+
 134+ // Current playback position
 135+ "currentTime" : 0,
 136+
 137+ // Previous player set time
 138+ // Lets javascript use $j('#videoId').get(0).currentTime = newTime;
 139+ "previousTime" : 0,
 140+
 141+ // Previous player set volume
 142+ // Lets javascript use $j('#videoId').get(0).volume = newVolume;
 143+ "previousVolume" : 1,
 144+
 145+ // Initial player volume:
 146+ "volume" : 0.75,
 147+
 148+ // Caches the volume before a mute toggle
 149+ "preMuteVolume" : 0.75,
 150+
 151+ // Media duration: Value is populated via
 152+ // custom durationHint attribute or via the media file once its played
 153+ "duration" : null,
 154+
 155+ // Mute state
 156+ "muted" : false,
 157+
 158+ /**
 159+ * Custom attributes for embedPlayer player: (not part of the html5
 160+ * video spec)
 161+ */
 162+
 163+ // Default video aspect ratio
 164+ 'videoAspect' : '4:3',
 165+
 166+ // Start time of the clip
 167+ "start" : 0,
 168+
 169+ // End time of the clip
 170+ "end" : null,
 171+
 172+ // A apiTitleKey for looking up subtitles, credits and related videos
 173+ "apiTitleKey" : null,
 174+
 175+ // The apiProvider where to lookup the title key
 176+ "apiProvider" : null,
 177+
 178+ // If the player controls should be overlaid
 179+ // ( Global default via config EmbedPlayer.OverlayControls in module
 180+ // loader.js)
 181+ "overlaycontrols" : true,
 182+
 183+ // Attribute to use 'native' controls
 184+ "usenativecontrols" : false,
 185+
 186+ // If the player should include an attribution button:
 187+ 'attributionbutton' : true,
 188+
 189+ // ROE url ( for xml based metadata )
 190+ // also see: http://wiki.xiph.org/ROE
 191+ "roe" : null,
 192+
 193+ // If serving an ogg_chop segment use this to offset the presentation
 194+ // time
 195+ // ( for some plugins that use ogg page time rather than presentation
 196+ // time )
 197+ "startOffset" : 0,
 198+
 199+ // Thumbnail (same as poster)
 200+ "thumbnail" : null,
 201+
 202+ // Source page for media asset ( used for linkbacks in remote embedding
 203+ // )
 204+ "linkback" : null,
 205+
 206+ // If the download link should be shown
 207+ "download_link" : true,
 208+
 209+ // Content type of the media
 210+ "type" : null
 211+ } );
 212+
86213 // Add class file paths
87214 mw.addResourcePaths( {
88215 "mw.EmbedPlayer" : "mw.EmbedPlayer.js",
@@ -217,6 +344,13 @@
218345 if( !!document.createElement('video').canPlayType && !$j.browser.safari ) {
219346 dependencyRequest[0].push( 'mw.EmbedPlayerNative' )
220347 }
 348+
 349+ // Check if the iFrame player server is enabled:
 350+ if (mw.getConfig('EmbedPlayer.EnableIFramePlayerServer')) {
 351+ dependencyRequest.push('mw.EmbedPlayerNative');
 352+ dependencyRequest.push('$j.postMessage');
 353+ dependencyRequest.push('mw.IFramePlayerApiServer');
 354+ }
221355
222356 // Return the set of libs to be loaded
223357 return dependencyRequest;
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js
@@ -1,306 +1,126 @@
2 -/**
 2+/**
33 * embedPlayer is the base class for html5 video tag javascript abstraction library
44 * embedPlayer include a few subclasses:
5 -*
6 -* mediaPlayer Media player embed system ie: java, vlc or native.
7 -* mediaElement Represents source media elements
8 -* mw.PlayerControlBuilder Handles skinning of the player controls
 5+*
 6+* mediaPlayer Media player embed system ie: java, vlc or native.
 7+* mediaElement Represents source media elements
 8+* mw.PlayerControlBuilder Handles skinning of the player controls
99 */
1010
 11+/**
 12+ * Add the messages text:
 13+ */
 14+
1115 mw.includeAllModuleMessages();
1216
13 -/*
14 -* The default video attributes supported by embedPlayer
15 -*/
16 -mw.setDefaultConfig( 'EmbedPlayer.Attributes', {
17 - /*
18 - * Base html element attributes:
19 - */
2017
21 - // id: Auto-populated if unset
22 - "id" : null,
23 -
24 - // Width: alternate to "style" to set player width
25 - "width" : null,
26 -
27 - // Height: alternative to "style" to set player height
28 - "height" : null,
29 -
30 - /*
31 - * Base html5 video element attributes / states
32 - * also see: http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
33 - */
34 -
35 - // Media src URI, can be relative or absolute URI
36 - "src" : null,
37 -
38 - // Poster attribute for displaying a place holder image before loading or playing the video
39 - "poster": null,
40 -
41 - // Autoplay if the media should start playing
42 - "autoplay" : false,
43 -
44 - // Loop attribute if the media should repeat on complete
45 - "loop" : false,
46 -
47 - // If the player controls should be displayed
48 - "controls" : true,
49 -
50 - // Video starts "paused"
51 - "paused" : true,
52 -
53 - // ReadyState an attribute informs clients of video loading state:
54 - // see: http://www.whatwg.org/specs/web-apps/current-work/#readystate
55 - "readyState" : 0,
56 -
57 - // Loading state of the video element
58 - "networkState" : 0,
59 -
60 - // Current playback position
61 - "currentTime" :0,
62 -
63 - // Previous player set time
64 - // Lets javascript use $j('#videoId').get(0).currentTime = newTime;
65 - "previousTime" :0,
66 -
67 - // Previous player set volume
68 - // Lets javascript use $j('#videoId').get(0).volume = newVolume;
69 - "previousVolume" : 1,
70 -
71 - // Initial player volume:
72 - "volume" : 0.75,
73 -
74 - // Caches the volume before a mute toggle
75 - "preMuteVolume" : 0.75,
76 -
77 - // Media duration: Value is populated via
78 - // custom durationHint attribute or via the media file once its played
79 - "duration" :null,
80 -
81 - // Mute state
82 - "muted" : false,
83 -
84 - /**
85 - * Custom attributes for embedPlayer player:
86 - * (not part of the html5 video spec)
87 - */
88 -
89 - // Default video aspect ratio
90 - 'videoAspect': '4:3',
91 -
92 - // Start time of the clip
93 - "start" : 0,
94 -
95 - // End time of the clip
96 - "end" : null,
97 -
98 - // A apiTitleKey for looking up subtitles, credits and related videos
99 - "apiTitleKey" : null,
100 -
101 - // The apiProvider where to lookup the title key
102 - "apiProvider" : null,
103 -
104 - // If the player controls should be overlaid
105 - //( Global default via config EmbedPlayer.OverlayControls in module loader.js)
106 - "overlaycontrols" : true,
107 -
108 - // Attribute to use 'native' controls
109 - "usenativecontrols" : false,
110 -
111 - // If the player should include an attribution button:
112 - 'attributionbutton' : true,
113 -
114 - // ROE url ( for xml based metadata )
115 - // also see: http://wiki.xiph.org/ROE
116 - "roe" : null,
117 -
118 - // If serving an ogg_chop segment use this to offset the presentation time
119 - // ( for some plugins that use ogg page time rather than presentation time )
120 - "startOffset" : 0,
121 -
122 - // Thumbnail (same as poster)
123 - "thumbnail" : null,
124 -
125 - // Source page for media asset ( used for linkbacks in remote embedding )
126 - "linkback" : null,
127 -
128 - // If the download link should be shown
129 - "download_link" : true,
130 -
131 - // Content type of the media
132 - "type" : null
133 -});
134 -
135 -mw.setDefaultConfig( {
136 - // If the player controls should be overlaid on top of the video ( if supported by playback method)
137 - // can be set to false per embed player via overlayControls attribute
138 - 'EmbedPlayer.OverlayControls' : true,
139 -
140 - 'EmbedPlayer.LibraryPage': 'http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library',
141 -
142 - // A default apiProvider ( ie where to lookup subtitles, video properties etc )
143 - // NOTE: Each player instance can also specify a specific provider
144 - "EmbedPlayer.ApiProvider" : "local",
145 -
146 - // Default video size ( if no size provided )
147 - "EmbedPlayer.DefaultSize" : "400x300",
148 -
149 - // If the video player should attribute kaltura
150 - "EmbedPlayer.KalturaAttribution" : true,
151 -
152 - // The attribution button
153 - 'EmbedPlayer.AttributionButton' :{
154 - 'title' : 'Kaltura html5 video library',
155 - 'href' : 'http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library',
156 - // Style icon to be applied
157 - 'class' : 'kaltura-icon',
158 - // An icon image url ( should be a 12x12 image or data url )
159 - 'iconurl' : false
160 - },
161 -
162 -
163 - // Set the browser player warning flag displays warning for non optimal playback
164 - "EmbedPlayer.ShowNativeWarning" : true,
165 -
166 - // If fullscreen is global enabled.
167 - "EmbedPlayer.EnableFullscreen" : true,
168 -
169 - // If mwEmbed should use the Native player controls
170 - // this will prevent video tag rewriting and skinning
171 - // useful for devices such as iPad / iPod that
172 - // don't fully support DOM overlays or don't expose full-screen
173 - // functionality to javascript
174 - "EmbedPlayer.NativeControls" : false,
175 -
176 - // If mwEmbed should use native controls on mobile safari
177 - "EmbedPlayer.NativeControlsMobileSafari" : true,
178 -
179 -
180 - // The z-index given to the player interface during full screen ( high z-index )
181 - "EmbedPlayer.fullScreenZIndex" : 999998,
182 -
183 - // The default share embed mode ( can be "object" or "videojs" )
184 - //
185 - // "object" will provide a <object tag pointing to mwEmbedFrame.php
186 - // Object embedding should be much more compatible with sites that
187 - // let users embed flash applets
188 - // "videojs" will include the source javascript and video tag to
189 - // rewrite the player on the remote page DOM
190 - // Video tag embedding is much more mash-up friendly but exposes
191 - // the remote site to the mwEmbed javascript and can be a xss issue.
192 - "EmbedPlayer.ShareEmbedMode" : 'object',
193 -
194 - // Default player skin name
195 - "EmbedPlayer.SkinName" : "mvpcf",
196 -
197 - // Number of milliseconds between interface updates
198 - 'EmbedPlayer.MonitorRate' : 250
199 -} );
200 -
20118 /**
202 - * The base source attribute checks
203 - * also see: http://dev.w3.org/html5/spec/Overview.html#the-source-element
 19+ * The base source attribute checks also see:
 20+ * http://dev.w3.org/html5/spec/Overview.html#the-source-element
20421 */
205 -mw.setDefaultConfig( 'embedPlayerSourceAttributes', [
 22+mw.setDefaultConfig( 'EmbedPlayer.SourceAttributes', [
20623 // source id
20724 'id',
208 -
 25+
20926 // media url
21027 'src',
211 -
 28+
21229 // media codecs attribute ( if provided )
21330 'codecs',
214 -
 31+
21532 // Title string for the source asset
21633 'title',
217 -
 34+
21835 // boolean if we support temporal url requests on the source media
21936 'URLTimeEncoding',
220 -
 37+
22138 // Media has a startOffset ( used for plugins that
22239 // display ogg page time rather than presentation time
22340 'startOffset',
224 -
 41+
22542 // A hint to the duration of the media file so that duration
22643 // can be displayed in the player without loading the media file
22744 'durationHint',
228 -
 45+
22946 // Media start time
23047 'start',
231 -
 48+
23249 // Media end time
23350 'end',
234 -
 51+
23552 // If the source is the default source
23653 'default',
237 -
 54+
23855 // Language key used for subtitle tracks
23956 'srclang',
240 -
 57+
24158 // titleKey ( used for api lookups )
24259 'titleKey',
243 -
 60+
24461 // The provider type ( for what type of api query to make )
24562 'provider_type',
246 -
 63+
24764 // The api url for the provider
248 - 'provider_url'
 65+ 'provider_url'
24966 ] );
25067
25168 /**
252 -* Adds jQuery binding for embedPlayer
253 -*/
 69+ * Adds jQuery binding for embedPlayer
 70+ */
25471 ( function( $ ) {
255 -
 72+
25673 /*
257 - * embeds all players that match the rewrite player tags config
258 - * Passes off request to the embedPlayer selector:
259 - *
260 - * @param {Object} attributes Attributes to apply to embed players
261 - * @param {Function} callback Function to call once embedding is done
262 - */
 74+ * embeds all players that match the rewrite player tags config Passes off
 75+ * request to the embedPlayer selector:
 76+ *
 77+ * @param {Object} attributes Attributes to apply to embed players @param
 78+ * {Function} callback Function to call once embedding is done
 79+ */
26380 $.embedPlayers = function( attributes, callback) {
26481 $j( mw.getConfig( 'EmbedPlayer.RewriteTags' ) ).embedPlayer( attributes, callback );
26582 };
266 -
 83+
26784 /**
268 - * Selector based embedPlayer jQuery binding
269 - *
270 - * Rewrites all tags via a given selector
271 - *
272 - * @param {object=} attributes Optional embedPlayer attributes for the given video interface.
273 - * Attributes Object can include any key value pair that would otherwise be
274 - * an attribute in the html element.
275 - *
276 - * also see: mw.getConfig( 'EmbedPlayer.Attributes' )
277 - *
278 - * @param {Function=} callback Optional Function to be called once video interfaces are ready
279 - *
280 - */
 85+ * Selector based embedPlayer jQuery binding
 86+ *
 87+ * Rewrites all tags via a given selector
 88+ *
 89+ * @param {object=}
 90+ * attributes Optional embedPlayer attributes for the given video
 91+ * interface. Attributes Object can include any key value pair
 92+ * that would otherwise be an attribute in the html element.
 93+ *
 94+ * also see: mw.getConfig( 'EmbedPlayer.Attributes' )
 95+ *
 96+ * @param {Function=}
 97+ * callback Optional Function to be called once video interfaces
 98+ * are ready
 99+ *
 100+ */
281101 $.fn.embedPlayer = function( attributes, callback ) {
282102 mw.log( 'EmbedPlayer:: fn.embedPlayer' );
283103 var playerSelect = this.selector;
284 -
 104+
285105 // Define attributes if unset
286106 if( !attributes ) {
287107 attributes = {};
288108 }
289 -
 109+
290110 // Handle optional include of attributes argument:
291111 if( typeof attributes == 'function' ){
292112 callback = attributes;
293113 attributes = {};
294114 }
295 -
 115+
296116 $j( playerSelect ).each( function( index, playerElement) {
297117 // make sure the playerElement has an id:
298118 if( $j( playerElement ).attr('id') =='' ){
299119 $j( playerElement ).attr( "id", 'mwe_v' + ( index ) );
300120 }
301 -
 121+
302122 // If we are dynamically embedding on a "div" check if we can
303123 // add a poster image behind the loader:
304 - if( playerElement.nodeName.toLowerCase() == 'div'
 124+ if( playerElement.nodeName.toLowerCase() == 'div'
305125 && ( attributes.poster || $j(playerElement).attr( 'poster' ) ) ){
306126 var posterSrc = ( attributes.poster ) ? attributes.poster : $j(playerElement).attr( 'poster' );
307127
@@ -313,7 +133,7 @@
314134 if( !height ){
315135 var height = ( attributes.height )? attributes.height : '100%';
316136 }
317 -
 137+
318138 mw.log('EmbedPlayer:: set loading background: ' + posterSrc);
319139 $j( playerElement ).append(
320140 $j( '<img />' )
@@ -326,12 +146,12 @@
327147 );
328148 }
329149 });
330 -
 150+
331151 // If we have not detected browser plugin embed types do that now
332152 if( ! mw.EmbedTypes.players ){
333153 mw.EmbedTypes.init();
334154 }
335 -
 155+
336156 // Create the Global Embed Player Manager ( if not already created )
337157 if( ! mw.playerManager ) {
338158 mw.log( "EmbedPlayer::Create the player manager:" );
@@ -341,7 +161,8 @@
342162 $j( mw ).trigger( 'EmbedPlayerManagerReady' );
343163 }
344164 var addedToPlayerManager = false;
345 - // Make sure we have user preference setup ( for setting preferences on video selection )
 165+ // Make sure we have user preference setup ( for setting preferences on
 166+ // video selection )
346167 mw.setupUserConfig( function() {
347168 mw.log("EmbedPlayer:: found: " + $j( playerSelect ).length + ' players ');
348169 // Add each selected element to the player manager:
@@ -357,132 +178,136 @@
358179 // Add the player
359180 mw.playerManager.addElement( playerElement, attributes);
360181 }
361 -
 182+
362183 } );
363 - // run the callback directly if no players were added to the playerManager
 184+ // run the callback directly if no players were added to the
 185+ // playerManager
364186 if( !addedToPlayerManager && callback ){
365187 callback();
366188 }
367 -
 189+
368190 });
369191 };
370192
371193 } )( jQuery );
372194
373195 /**
374 -* EmbedPlayerManager
375 -*
376 -* Manages calls to embed video interfaces
377 -*/
 196+ * EmbedPlayerManager
 197+ *
 198+ * Manages calls to embed video interfaces
 199+ */
378200 var EmbedPlayerManager = function( ) {
379201 // Create a Player Manage
380202 return this.init( );
381203 };
382204 EmbedPlayerManager.prototype = {
383 -
 205+
384206 // Functions to run after the video interface is ready
385207 callbackFunctions : null,
386 -
 208+
387209 playerElementQueue: [],
388 -
 210+
389211 /**
390 - * Constructor initializes callbackFunctions and playerList
391 - */
 212+ * Constructor initializes callbackFunctions and playerList
 213+ */
392214 init: function( ) {
393215 this.callbackFunctions = [];
394216 this.playerList = [];
395217 },
396 -
 218+
397219 /**
398 - * Adds a callback to the callbackFunctions list
399 - * the callback functions are called once the players are ready.
400 - *
401 - * @param {Function} callback Function to be called once players are ready
402 - */
 220+ * Adds a callback to the callbackFunctions list the callback functions are
 221+ * called once the players are ready.
 222+ *
 223+ * @param {Function}
 224+ * callback Function to be called once players are ready
 225+ */
403226 addCallback: function( callback ) {
404227 if( typeof callback == 'function' ){
405228 this.callbackFunctions.push( callback );
406229 }
407230 },
408 -
 231+
409232 /**
410 - * Get the list of players
411 - */
 233+ * Get the list of players
 234+ */
412235 getPlayerList: function( ) {
413236 return this.playerList;
414237 },
415 -
 238+
416239 /**
417 - * Adds an Element for the embedPlayer to rewrite
418 - *
419 - * uses embedPlayer interface on audio / video elements
420 - * uses mvPlayList interface on playlist elements
421 - *
422 - * Once a player interface is established the following chain of functions are called;
423 - *
424 - * _this.checkPlayerSources()
425 - * _this.checkForTimedText()
426 - * _this.setupSourcePlayer()
427 - * _this.inheritEmbedPlayer()
428 - * _this.selectedPlayer.load()
429 - * _this.showPlayer()
430 - *
431 - * @param {Element} playerElement DOM element to be swapped
432 - * @param {Object} [Optional] attributes Extra attributes to apply to the player interface
433 - */
 240+ * Adds an Element for the embedPlayer to rewrite
 241+ *
 242+ * uses embedPlayer interface on audio / video elements uses mvPlayList
 243+ * interface on playlist elements
 244+ *
 245+ * Once a player interface is established the following chain of functions
 246+ * are called;
 247+ *
 248+ * _this.checkPlayerSources() _this.checkForTimedText()
 249+ * _this.setupSourcePlayer() _this.inheritEmbedPlayer()
 250+ * _this.selectedPlayer.load() _this.showPlayer()
 251+ *
 252+ * @param {Element}
 253+ * playerElement DOM element to be swapped
 254+ * @param {Object}
 255+ * [Optional] attributes Extra attributes to apply to the player
 256+ * interface
 257+ */
434258 addElement: function( playerElement, attributes ) {
435259 var _this = this;
436 -
 260+
437261 if ( !playerElement.id || playerElement.id == '' ) {
438262 // give the playerElement an id:
439 - playerElement.id = 'vid' + ( this.playerList.length + 1 );
 263+ playerElement.id = 'vid' + ( this.playerList.length + 1 );
440264 }
441265 mw.log('EmbedPlayerManager: addElement:: ' + playerElement.id );
442266
443267 // Add the element id to playerList
444268 this.playerList.push( playerElement.id );
445 -
 269+
446270 // Check for player attributes such as skins or plugins attributes
447271 // that add to the request set
448272 var playerDependencyRequest = [];
449 -
 273+
450274 // merge in any custom attributes
451275 $j.extend( playerElement, attributes );
452 -
 276+
453277 // Update the list of dependent libraries for the player
454278 // ( allows extensions to add to the dependency list )
455279 mw.embedPlayerUpdateLibraryRequest( playerElement, playerDependencyRequest );
456 -
 280+
457281 // Load any skins we need then swap in the interface
458282 mw.load( playerDependencyRequest, function() {
459283 var waitForMeta = true;
460 -
461 - // Be sure to "stop" the target ( sometimes firefox keeps playing the video even
 284+
 285+ // Be sure to "stop" the target ( sometimes firefox keeps playing
 286+ // the video even
462287 // though its been removed from the DOM )
463288 if( playerElement.pause ){
464289 playerElement.pause();
465290 }
466 -
467 -
 291+
 292+
468293 // Let extensions determine if its worthwhile to wait for metadata:
469294 // We pass an object to the trigger to preserve reference values
470 - var eventObject = {
471 - 'playerElement' : playerElement,
 295+ var eventObject = {
 296+ 'playerElement' : playerElement,
472297 'waitForMeta' : waitForMeta
473298 };
474299 $j( mw ).trigger( 'addElementWaitForMetaEvent', eventObject );
475 -
 300+
476301 // update the waitForMeta
477302 waitForMeta = eventObject[ 'waitForMeta' ];
478 -
479 -
 303+
 304+
480305 // Set the wait for meta flag if unset by extension
481306 if( waitForMeta ){
482307 waitForMeta = _this.waitForMetaCheck( playerElement );
483308 }
484 -
 309+
485310 var ranPlayerSwapFlag = false;
486 -
 311+
487312 // Local callback to runPlayer swap once playerElement has metadata
488313 function runPlayerSwap() {
489314 if( ranPlayerSwapFlag ){
@@ -490,10 +315,10 @@
491316 }
492317 ranPlayerSwapFlag = true;
493318 mw.log("EmbedPlayer::runPlayerSwap::" + $j( playerElement ).attr('id') );
494 -
 319+
495320 var playerInterface = new mw.EmbedPlayer( playerElement , attributes);
496321 var swapPlayer = _this.swapEmbedPlayerElement( playerElement, playerInterface );
497 -
 322+
498323 // Copy over any data attributes from the playerElement
499324 if( mw.getConfig( 'EmbedPlayer.DataAttributes' ) ) {
500325 var dataAttr = mw.getConfig( 'EmbedPlayer.DataAttributes' );
@@ -503,43 +328,46 @@
504329 }
505330 }
506331 }
507 -
508 - // Pass the id to any hook that needs to interface prior to checkPlayerSources
 332+
 333+ // Pass the id to any hook that needs to interface prior to
 334+ // checkPlayerSources
509335 mw.log("EmbedPlayer::addElement :trigger " + playerInterface.id );
510336 $j( mw ).trigger ( 'newEmbedPlayerEvent', $j( '#' + playerInterface.id ).get(0) );
511 -
512 - // Issue the checkPlayerSources call to the new player interface:
 337+
 338+ // Issue the checkPlayerSources call to the new player
 339+ // interface:
513340 // make sure to use the element that is in the DOM:
514341 $j( '#' + playerInterface.id ).get(0).checkPlayerSources();
515342 }
516 -
 343+
517344 if( waitForMeta ) {
518 - mw.log('EmbedPlayer::WaitForMeta ( video missing height (' +
519 - $j( playerElement ).attr('height') + '), width (' +
 345+ mw.log('EmbedPlayer::WaitForMeta ( video missing height (' +
 346+ $j( playerElement ).attr('height') + '), width (' +
520347 $j( playerElement ).attr('width') + ') or duration: ' +
521 - $j( playerElement ).attr('duration')
 348+ $j( playerElement ).attr('duration')
522349 );
523 -
 350+
524351 playerElement.removeEventListener( "loadedmetadata", runPlayerSwap, true );
525352 playerElement.addEventListener( "loadedmetadata", runPlayerSwap, true );
526 -
527 - // Time-out of 5 seconds ( maybe still playable but no timely metadata )
 353+
 354+ // Time-out of 5 seconds ( maybe still playable but no timely
 355+ // metadata )
528356 setTimeout( runPlayerSwap, 5000 );
529357 return ;
530 - } else {
 358+ } else {
531359 runPlayerSwap();
532360 return ;
533 - }
534 - });
 361+ }
 362+ });
535363 },
536 -
 364+
537365 /**
538 - * Check for bogus resolutions of the media asset that has not loaded.
539 - * @return
540 - * true if the resolution is "likely" to be updated
541 - * by waiting for metadata
542 - * false if the resolution has been set via an attribute or is already loaded
543 - */
 366+ * Check for bogus resolutions of the media asset that has not loaded.
 367+ *
 368+ * @return true if the resolution is "likely" to be updated by waiting for
 369+ * metadata false if the resolution has been set via an attribute or
 370+ * is already loaded
 371+ */
544372 waitForMetaCheck: function( playerElement ){
545373 var waitForMeta = false;
546374 if( !playerElement )
@@ -550,19 +378,19 @@
551379 {
552380 return false;
553381 }
554 -
555 -
 382+
 383+
556384 var width = $j( playerElement ).css( 'width' );
557385 var height = $j( playerElement ).css( 'height' );
558 -
 386+
559387 // Css video defaults
560 - if( $j( playerElement ).css( 'width' ) == '300px' &&
 388+ if( $j( playerElement ).css( 'width' ) == '300px' &&
561389 $j( playerElement ).css( 'height' ) == '150px'
562390 ){
563391 waitForMeta = true;
564392 } else {
565393 // Check if we should wait for duration:
566 - if( $j( playerElement ).attr( 'duration') ||
 394+ if( $j( playerElement ).attr( 'duration') ||
567395 $j( playerElement ).attr('durationHint')
568396 ){
569397 // height, width and duration set; do not wait for meta data:
@@ -571,30 +399,31 @@
572400 waitForMeta = true;
573401 }
574402 }
575 -
576 - //Firefox ~ sometimes ~ gives -1 for unloaded media
 403+
 404+ // Firefox ~ sometimes ~ gives -1 for unloaded media
577405 if ( $j(playerElement).attr( 'width' ) == -1 || $j(playerElement).attr( 'height' ) == -1 ) {
578 - waitForMeta = true;
 406+ waitForMeta = true;
579407 }
580 -
 408+
581409 // Google Chrome / safari gives 0 width height for unloaded media
582 - if( $j(playerElement).attr( 'width' ) === 0 ||
583 - $j(playerElement).attr( 'height' ) === 0
 410+ if( $j(playerElement).attr( 'width' ) === 0 ||
 411+ $j(playerElement).attr( 'height' ) === 0
584412 ) {
585413 waitForMeta = true;
586414 }
587 -
 415+
588416 // Firefox default width height is ~sometimes~ 150 / 300
589417 if( this.height == 150 && this.width == 300 ){
590 - waitForMeta = true;
 418+ waitForMeta = true;
591419 }
592 -
 420+
593421 // Make sure we have a src attribute or source child
594 - // ( i.e not a video tag to be dynamically populated or looked up from xml resource description )
595 - if( waitForMeta &&
 422+ // ( i.e not a video tag to be dynamically populated or looked up from
 423+ // xml resource description )
 424+ if( waitForMeta &&
596425 (
597426 $j( playerElement ).attr('src') ||
598 - $j( playerElement ).find("source[src]").length !== 0
 427+ $j( playerElement ).find("source[src]").length !== 0
599428 )
600429 ) {
601430 // Detect src type ( if no type set )
@@ -602,50 +431,54 @@
603432 } else {
604433 // playerElement is not likely to update its meta data ( no src )
605434 return false;
606 - }
 435+ }
607436 },
608 -
 437+
609438 /**
610 - * swapEmbedPlayerElement
611 - *
612 - * Takes a video element as input and swaps it out with
613 - * an embed player interface
614 - *
615 - * @param {Element} targetElement Element to be swapped
616 - * @param {Object} playerInterface Interface to swap into the target element
617 - */
 439+ * swapEmbedPlayerElement
 440+ *
 441+ * Takes a video element as input and swaps it out with an embed player
 442+ * interface
 443+ *
 444+ * @param {Element}
 445+ * targetElement Element to be swapped
 446+ * @param {Object}
 447+ * playerInterface Interface to swap into the target element
 448+ */
618449 swapEmbedPlayerElement: function( targetElement, playerInterface ) {
619450 mw.log( 'EmbedPlayer::swapEmbedPlayerElement: ' + targetElement.id );
620451 // Create a new element to swap the player interface into
621452 var swapPlayerElement = document.createElement('div');
622 -
 453+
623454 // Get properties / methods from playerInterface
624455 for ( var method in playerInterface ) {
625 - if ( method != 'readyState' ) { // readyState crashes IE ( don't include )
 456+ if ( method != 'readyState' ) { // readyState crashes IE ( don't
 457+ // include )
626458 swapPlayerElement[ method ] = playerInterface[ method ];
627459 }
628460 }
629 -
630 - // Check if we are using native controls ( should keep the video embed around )
 461+
 462+ // Check if we are using native controls ( should keep the video embed
 463+ // around )
631464 if( playerInterface.useNativePlayerControls() ) {
632465 $j( targetElement )
633466 .attr( 'id', playerInterface.pid )
634467 .addClass( 'nativeEmbedPlayerPid' )
635468 .show()
636 - .after(
 469+ .after(
637470 $j( swapPlayerElement ).css( 'display', 'none' )
638471 );
639472 } else {
640473 $j( targetElement ).replaceWith( swapPlayerElement );
641474 }
642 -
643 -
 475+
 476+
644477 // Set swapPlayerElement has height / width set and set to loading:
645478 $j( swapPlayerElement ).css( {
646479 'width' : playerInterface.width,
647480 'height' : playerInterface.height
648481 } );
649 -
 482+
650483 // If we don't already have a loadSpiner add one:
651484 if( $j('#loadingSpinner_' + playerInterface.id ).length == 0 ){
652485 if( playerInterface.useNativePlayerControls() ) {
@@ -653,7 +486,7 @@
654487 .getAbsoluteOverlaySpinner()
655488 .attr('id', 'loadingSpinner_' + playerInterface.id );
656489 }else{
657 - $j( swapPlayerElement ).append(
 490+ $j( swapPlayerElement ).append(
658491 $j('<div />')
659492 .loadingSpinner()
660493 );
@@ -661,29 +494,29 @@
662495 }
663496 return swapPlayerElement;
664497 },
665 -
666 -
 498+
 499+
667500 /**
668 - * Player ready will run the global callbacks
669 - * once players are "ready"
670 - *
671 - * This enables mw.ready event to expose video tag
672 - * elements as if the videotag was supported natively.
673 - *
674 - * @param {Object} player The EmbedPlayer object
675 - */
 501+ * Player ready will run the global callbacks once players are "ready"
 502+ *
 503+ * This enables mw.ready event to expose video tag elements as if the
 504+ * videotag was supported natively.
 505+ *
 506+ * @param {Object}
 507+ * player The EmbedPlayer object
 508+ */
676509 playerReady: function( player ) {
677510 var _this = this;
678511 mw.log( 'EmbedPlayer::ReadyToPlay callback player:' + player.id );
679512 player.readyToPlay = true;
680 -
 513+
681514 // Remove the player loader spinner:
682515 $j('#loadingSpinner_' + player.id ).remove();
683 -
 516+
684517 // Run the player ready trigger
685518 $j( player ).trigger( 'playerReady' );
686 -
687 - var is_ready = true;
 519+
 520+ var is_ready = true;
688521 for ( var i = 0; i < this.playerList.length; i++ ) {
689522 var currentPlayer = $j( '#' + this.playerList[i] ).get( 0 );
690523 if ( player ) {
@@ -694,8 +527,8 @@
695528 if ( is_ready ) {
696529 // Be sure to remove any player loader spinners
697530 $j('.playerLoadingSpinner').remove();
698 -
699 - mw.log( "EmbedPlayer::All on-page players ready run playerManager callbacks" );
 531+
 532+ mw.log( "EmbedPlayer::All on-page players ready run playerMannager callbacks" );
700533 // Run queued functions
701534 if( _this.callbackFunctions ) {
702535 while ( _this.callbackFunctions.length ) {
@@ -707,10 +540,12 @@
708541 };
709542
710543 /**
711 - * mediaSource class represents a source for a media element.
712 - * @param {Element} element: MIME type of the source.
713 - * @constructor
714 - */
 544+ * mediaSource class represents a source for a media element.
 545+ *
 546+ * @param {Element}
 547+ * element: MIME type of the source.
 548+ * @constructor
 549+ */
715550 function mediaSource( element ) {
716551 this.init( element );
717552 }
@@ -718,50 +553,50 @@
719554 mediaSource.prototype = {
720555 // MIME type of the source.
721556 mimeType:null,
722 -
 557+
723558 // URI of the source.
724559 uri:null,
725 -
 560+
726561 // Title of the source.
727562 title: null,
728 -
 563+
729564 // True if the source has been marked as the default.
730565 markedDefault: false,
731 -
 566+
732567 // True if the source supports url specification of offset and duration
733568 URLTimeEncoding:false,
734 -
 569+
735570 // Start offset of the requested segment
736571 startOffset: 0,
737 -
 572+
738573 // Duration of the requested segment (0 if not known)
739574 duration:0,
740 -
 575+
741576 // Is the source playable
742577 is_playable: null,
743 -
 578+
744579 // source id
745580 id: null,
746 -
 581+
747582 // Start time in npt format
748583 start_npt: null,
749 -
 584+
750585 // End time in npt format
751586 end_npt: null,
752 -
 587+
753588 // A provider "id" to identify api request type
754589 provider_type : null,
755590
756591 // The api url for the provider
757 - provider_url : null,
758 -
 592+ provider_url : null,
 593+
759594 /**
760 - * MediaSource constructor:
761 - */
 595+ * MediaSource constructor:
 596+ */
762597 init : function( element ) {
763598 // mw.log('EmbedPlayer::adding mediaSource: ' + element);
764599 this.src = $j( element ).attr( 'src' );
765 -
 600+
766601 // Set default URLTimeEncoding if we have a time url:
767602 // not ideal way to discover if content is on an oggz_chop server.
768603 // should check some other way.
@@ -769,9 +604,9 @@
770605 if ( typeof pUrl[ 'queryKey' ][ 't' ] != 'undefined' ) {
771606 this.URLTimeEncoding = true;
772607 }
773 -
774 - var sourceAttr = mw.getConfig( 'embedPlayerSourceAttributes' );
775 -
 608+
 609+ var sourceAttr = mw.getConfig( 'EmbedPlayer.SourceAttributes' );
 610+
776611 for ( var i = 0; i < sourceAttr.length; i++ ) { // array loop:
777612 var attr = sourceAttr[ i ];
778613 var attr_value = element.getAttribute( attr );
@@ -779,8 +614,8 @@
780615 this[ attr ] = attr_value;
781616 }
782617 }
783 -
784 -
 618+
 619+
785620 // Set the content type:
786621 if ( $j( element ).attr( 'type' ) ) {
787622 this.mimeType = $j( element ).attr( 'type' );
@@ -792,47 +627,53 @@
793628 } else {
794629 this.mimeType = this.detectType( this.src );
795630 }
796 -
 631+
797632 // Conform the mime type to ogg
798633 if( this.mimeType == 'video/theora') {
799634 this.mimeType = 'video/ogg';
800635 }
801 -
 636+
802637 if( this.mimeType == 'audio/vorbis') {
803638 this.mimeType = 'audio/ogg';
804639 }
805 -
 640+
806641 // Check for parent elements ( supplies categories in "track" )
807642 if( $j( element ).parent().attr('category') ) {
808643 this.category = $j( element ).parent().attr('category');
809644 }
810 -
 645+
811646 if( $j( element ).attr( 'default' ) ){
812647 this.markedDefault = true;
813648 }
814 -
 649+
815650 // Get the url duration ( if applicable )
816651 this.getURLDuration();
817652 },
818 -
 653+
819654 /**
820 - * Update Source title via Element
821 - * @param {Element} element Source element to update attributes from
822 - */
 655+ * Update Source title via Element
 656+ *
 657+ * @param {Element}
 658+ * element Source element to update attributes from
 659+ */
823660 updateSource: function( element ) {
824661 // for now just update the title:
825662 if ( $j( element ).attr( "title" ) ) {
826663 this.title = $j( element ).attr( "title" );
827664 }
828665 },
829 -
 666+
830667 /**
831668 * Updates the src time and start & end
832 - * @param {String} start_time: in NPT format
833 - * @param {String} end_time: in NPT format
 669+ *
 670+ * @param {String}
 671+ * start_time: in NPT format
 672+ * @param {String}
 673+ * end_time: in NPT format
834674 */
835675 updateSrcTime: function ( start_npt, end_npt ) {
836 - // mw.log("f:updateSrcTime: "+ start_npt+'/'+ end_npt + ' from org: ' + this.start_npt+ '/'+this.end_npt);
 676+ // mw.log("f:updateSrcTime: "+ start_npt+'/'+ end_npt + ' from org: ' +
 677+ // this.start_npt+ '/'+this.end_npt);
837678 // mw.log("pre uri:" + this.src);
838679 // if we have time we can use:
839680 if ( this.URLTimeEncoding ) {
@@ -840,35 +681,38 @@
841682 if ( !mw.npt2seconds( start_npt ) ) {
842683 start_npt = this.start_npt;
843684 }
844 -
 685+
845686 if ( !mw.npt2seconds( end_npt ) ) {
846687 end_npt = this.end_npt;
847688 }
848 -
849 - this.src = mw.replaceUrlParams( this.src, {
850 - 't': start_npt + '/' + end_npt
 689+
 690+ this.src = mw.replaceUrlParams( this.src, {
 691+ 't': start_npt + '/' + end_npt
851692 });
852 -
 693+
853694 // update the duration
854695 this.getURLDuration();
855696 }
856697 },
857 -
 698+
858699 /**
859 - * Sets the duration and sets the end time if unset
860 - * @param {Float} duration: in seconds
861 - */
 700+ * Sets the duration and sets the end time if unset
 701+ *
 702+ * @param {Float}
 703+ * duration: in seconds
 704+ */
862705 setDuration: function ( duration ) {
863706 this.duration = duration;
864707 if ( !this.end_npt ) {
865708 this.end_npt = mw.seconds2npt( this.startOffset + duration );
866709 }
867710 },
868 -
 711+
869712 /**
870 - * MIME type accessors function.
871 - * @return {String} the MIME type of the source.
872 - */
 713+ * MIME type accessors function.
 714+ *
 715+ * @return {String} the MIME type of the source.
 716+ */
873717 getMIMEType: function() {
874718 if( this.mimeType ) {
875719 return this.mimeType;
@@ -876,11 +720,15 @@
877721 this.mimeType = this.detectType( this.src );
878722 return this.mimeType;
879723 },
880 -
881 - /** URI function.
882 - * @param {Number} serverSeekTime Int: Used to adjust the URI for url based seeks)
883 - * @return {String} the URI of the source.
884 - */
 724+
 725+ /**
 726+ * URI function.
 727+ *
 728+ * @param {Number}
 729+ * serverSeekTime Int: Used to adjust the URI for url based
 730+ * seeks)
 731+ * @return {String} the URI of the source.
 732+ */
885733 getSrc : function( serverSeekTime ) {
886734 if ( !serverSeekTime || !this.URLTimeEncoding ) {
887735 return this.src;
@@ -891,20 +739,21 @@
892740 }
893741 return mw.replaceUrlParams( this.src,
894742 {
895 - 't' : mw.seconds2npt( serverSeekTime ) + endvar
896 - }
897 - );
 743+ 't': mw.seconds2npt( serverSeekTime ) + endvar
 744+ }
 745+ );
898746 },
899 -
 747+
900748 /**
901 - * Title accessor function.
902 - * @return {String} Title of the source.
903 - */
 749+ * Title accessor function.
 750+ *
 751+ * @return {String} Title of the source.
 752+ */
904753 getTitle : function() {
905754 if( this.title ){
906755 return this.title;
907756 }
908 -
 757+
909758 // Return a Title based on mime type:
910759 switch( this.getMIMEType() ) {
911760 case 'video/h264' :
@@ -926,21 +775,21 @@
927776 return 'AVI video'; // FIXME: i18n
928777 break;
929778 }
930 -
931 - // Return Title based on file name:
 779+
 780+ // Return tilte based on file name:
932781 var urlParts = mw.parseUri( this.getSrc() );
933782 if( urlParts.file ){
934783 return urlParts.file;
935784 }
936 -
 785+
937786 // Return the mime type string if not known type.
938787 return this.mimeType;
939788 },
940 -
 789+
941790 /**
942 - *
 791+ *
943792 * Get Duration of the media in milliseconds from the source url.
944 - *
 793+ *
945794 * Supports media_url?t=ntp_start/ntp_end url request format
946795 */
947796 getURLDuration : function() {
@@ -964,57 +813,60 @@
965814 }
966815 }
967816 },
968 -
 817+
969818 /**
970 - * Attempts to detect the type of a media file based on the URI.
971 - * @param {String} uri URI of the media file.
972 - * @return {String} The guessed MIME type of the file.
973 - */
 819+ * Attempts to detect the type of a media file based on the URI.
 820+ *
 821+ * @param {String}
 822+ * uri URI of the media file.
 823+ * @return {String} The guessed MIME type of the file.
 824+ */
974825 detectType: function( uri ) {
975826 // NOTE: if media is on the same server as the javascript
976 - // we can issue a HEAD request and read the mime type of the media...
 827+ // we can issue a HEAD request and read the mime type of the media ...
977828 // ( this will detect media mime type independently of the url name)
978829 // http://www.jibbering.com/2002/4/httprequest.html
979830 var end_inx = ( uri.indexOf( '?' ) != -1 ) ? uri.indexOf( '?' ) : uri.length;
980831 var no_param_uri = uri.substr( 0, end_inx );
981 - switch( no_param_uri.substr( no_param_uri.lastIndexOf( '.' ), 4 ).toLowerCase() ) {
 832+ switch( no_param_uri.substr( no_param_uri.lastIndexOf( '.' )+1 ).toLowerCase() ) {
982833 case 'smil':
983 - case '.sml':
984 - return 'application/smil';
 834+ case 'sml':
 835+ return 'application/smil'
985836 break;
986 - case '.m4v':
987 - case '.mp4':
 837+ case 'm4v':
 838+ case 'mp4':
 839+ case 'mov':
988840 return 'video/h264';
989841 break;
990842 case 'webm':
991843 return 'video/webm';
992844 break;
993 - case '.srt':
 845+ case 'srt':
994846 return 'text/x-srt';
995847 break;
996 - case '.flv':
 848+ case 'flv':
997849 return 'video/x-flv';
998850 break;
999 - case '.ogg':
1000 - case '.ogv':
 851+ case 'ogg':
 852+ case 'ogv':
1001853 return 'video/ogg';
1002854 break;
1003 - case '.oga':
 855+ case 'oga':
1004856 return 'audio/ogg';
1005857 break;
1006 - case '.anx':
 858+ case 'anx':
1007859 return 'video/ogg';
1008860 break;
1009 - case '.xml':
 861+ case 'xml':
1010862 return 'text/xml';
1011863 break;
1012 - case '.avi':
 864+ case 'avi':
1013865 return 'video/x-msvideo';
1014866 break;
1015 - case '.mpg':
 867+ case 'mpg':
1016868 return 'video/mpeg';
1017869 break;
1018 - case '.mpeg':
 870+ case 'mpeg':
1019871 return 'video/mpeg';
1020872 break;
1021873 }
@@ -1022,95 +874,103 @@
1023875 };
1024876
1025877 /**
1026 -* A media element corresponding to a <video> element.
1027 -*
1028 -* It is implemented as a collection of mediaSource objects. The media sources
1029 -* will be initialized from the <video> element, its child <source> elements,
1030 -* and/or the ROE file referenced by the <video> element.
1031 -* @param {element} videoElement <video> element used for initialization.
1032 -* @constructor
1033 -*/
 878+ * A media element corresponding to a <video> element.
 879+ *
 880+ * It is implemented as a collection of mediaSource objects. The media sources
 881+ * will be initialized from the <video> element, its child <source> elements,
 882+ * and/or the ROE file referenced by the <video> element.
 883+ *
 884+ * @param {element}
 885+ * videoElement <video> element used for initialization.
 886+ * @constructor
 887+ */
1034888 function mediaElement( element ) {
1035889 this.init( element );
1036890 }
1037891
1038892 mediaElement.prototype = {
1039 -
 893+
1040894 // The array of mediaSource elements.
1041895 sources: null,
1042 -
 896+
1043897 // flag for ROE data being added.
1044898 addedROEData: false,
1045 -
 899+
1046900 // Selected mediaSource element.
1047901 selectedSource: null,
1048 -
 902+
1049903 // Media element thumbnail
1050904 thumbnail: null,
1051 -
 905+
1052906 // Media element linkback
1053907 linkback: null,
1054908
1055909 /**
1056 - * Media Element constructor
1057 - *
1058 - * Sets up a mediaElement from a provided top level "video" element
1059 - * adds any child sources that are found
1060 - *
1061 - * @param {Element} videoElement Element that has src attribute or has children source elements
1062 - */
 910+ * Media Element constructor
 911+ *
 912+ * Sets up a mediaElement from a provided top level "video" element adds any
 913+ * child sources that are found
 914+ *
 915+ * @param {Element}
 916+ * videoElement Element that has src attribute or has children
 917+ * source elements
 918+ */
1063919 init: function( videoElement ) {
1064920 var _this = this;
1065921 mw.log( "EmbedPlayer::mediaElement:init:" + videoElement.id );
1066922 this.sources = new Array();
1067 -
 923+
1068924 // Process the videoElement as a source element:
1069925 if ( $j( videoElement ).attr( "src" ) ) {
1070926 _this.tryAddSource( videoElement );
1071927 }
1072 -
 928+
1073929 // Process elements source children
1074930 $j( videoElement ).find( 'source,track' ).each( function( ) {
1075931 _this.tryAddSource( this );
1076932 } );
1077933 },
1078 -
 934+
1079935 /**
1080 - * Updates the time request for all sources that have
1081 - * a standard time request argument (ie &t=start_time/end_time)
1082 - *
1083 - * @param {String} start_npt Start time in npt format
1084 - * @param {String} end_npt End time in npt format
1085 - */
 936+ * Updates the time request for all sources that have a standard time
 937+ * request argument (ie &t=start_time/end_time)
 938+ *
 939+ * @param {String}
 940+ * start_npt Start time in npt format
 941+ * @param {String}
 942+ * end_npt End time in npt format
 943+ */
1086944 updateSourceTimes: function( start_npt, end_npt ) {
1087945 var _this = this;
1088946 $j.each( this.sources, function( inx, mediaSource ) {
1089947 mediaSource.updateSrcTime( start_npt, end_npt );
1090948 } );
1091949 },
1092 -
 950+
1093951 /**
1094 - * Check for Timed Text tracks
1095 - * @return {Boolean} True if text tracks exist, false if no text tracks are found
1096 - */
 952+ * Check for Timed Text tracks
 953+ *
 954+ * @return {Boolean} True if text tracks exist, false if no text tracks are
 955+ * found
 956+ */
1097957 textSourceExists: function() {
1098958 for ( var i = 0; i < this.sources.length; i++ ) {
1099 - mw.log('EmbedPlayer::textSourceExists:'+ this.sources[i].mimeType );
1100 - if ( this.sources[i].mimeType == 'text/cmml' ||
1101 - this.sources[i].mimeType == 'text/x-srt' )
 959+ if ( this.sources[i].mimeType == 'text/cmml' ||
 960+ this.sources[i].mimeType == 'text/x-srt' )
1102961 {
1103962 return true;
1104963 }
1105964 };
1106965 return false;
1107966 },
1108 -
 967+
1109968 /**
1110 - * Returns the array of mediaSources of this element.
1111 - *
1112 - * @param {String} [mimeFilter] Filter criteria for set of mediaSources to return
1113 - * @return {Array} mediaSource elements.
1114 - */
 969+ * Returns the array of mediaSources of this element.
 970+ *
 971+ * @param {String}
 972+ * [mimeFilter] Filter criteria for set of mediaSources to return
 973+ * @return {Array} mediaSource elements.
 974+ */
1115975 getSources: function( mimeFilter ) {
1116976 if ( !mimeFilter ) {
1117977 return this.sources;
@@ -1119,19 +979,21 @@
1120980 var source_set = new Array();
1121981 for ( var i = 0; i < this.sources.length ; i++ ) {
1122982 if ( this.sources[i].mimeType &&
1123 - this.sources[i].mimeType.indexOf( mimeFilter ) != -1 )
 983+ this.sources[i].mimeType.indexOf( mimeFilter ) != -1 )
1124984 {
1125985 source_set.push( this.sources[i] );
1126986 }
1127987 }
1128988 return source_set;
1129989 },
1130 -
 990+
1131991 /**
1132 - * Selects a source by id
1133 - * @param {String} source_id Id of the source to select.
1134 - * @return {MediaSource} The selected mediaSource or null if not found
1135 - */
 992+ * Selects a source by id
 993+ *
 994+ * @param {String}
 995+ * source_id Id of the source to select.
 996+ * @return {MediaSource} The selected mediaSource or null if not found
 997+ */
1136998 getSourceById:function( source_id ) {
1137999 for ( var i = 0; i < this.sources.length ; i++ ) {
11381000 if ( this.sources[i].id == source_id ) {
@@ -1140,12 +1002,13 @@
11411003 }
11421004 return null;
11431005 },
1144 -
 1006+
11451007 /**
1146 - * Selects a particular source for playback updating the "selectedSource"
1147 - *
1148 - * @param {Number} index Index of source element to set as selectedSource
1149 - */
 1008+ * Selects a particular source for playback updating the "selectedSource"
 1009+ *
 1010+ * @param {Number}
 1011+ * index Index of source element to set as selectedSource
 1012+ */
11501013 selectSource:function( index ) {
11511014 mw.log( 'EmbedPlayer::mediaElement:selectSource:' + index );
11521015 var playableSources = this.getPlayableSources();
@@ -1158,16 +1021,22 @@
11591022 }
11601023 }
11611024 },
1162 -
 1025+
11631026 /**
1164 - * Selects the default source via cookie preference, default marked, or by id order
1165 - */
1166 - autoSelectSource: function() {
1167 - mw.log( 'EmbedPlayer::mediaElement::autoSelectSource:' + this.id);
 1027+ * Selects the default source via cookie preference, default marked, or by
 1028+ * id order
 1029+ */
 1030+ autoSelectSource: function() {
 1031+ mw.log( 'EmbedPlayer::mediaElement::autoSelectSource' );
11681032 // Select the default source
11691033 var playableSources = this.getPlayableSources();
11701034 var flash_flag = ogg_flag = false;
1171 -
 1035+
 1036+ // Check if there are any playableSources
 1037+ if( playableSources.length == 0 ){
 1038+ return false;
 1039+ }
 1040+
11721041 // Set via user-preference
11731042 for ( var source = 0; source < playableSources.length; source++ ) {
11741043 var mimeType = playableSources[source].mimeType;
@@ -1177,7 +1046,7 @@
11781047 return true;
11791048 }
11801049 }
1181 -
 1050+
11821051 // Set via marked default:
11831052 for ( var source = 0; source < playableSources.length; source++ ) {
11841053 if ( playableSources[ source ].markedDefault ) {
@@ -1186,7 +1055,7 @@
11871056 return true;
11881057 }
11891058 }
1190 -
 1059+
11911060 // Prefer native playback
11921061 for ( var source = 0; source < playableSources.length; source++ ) {
11931062 var mimeType = playableSources[source].mimeType;
@@ -1197,15 +1066,15 @@
11981067 return true;
11991068 }
12001069 }
1201 -
 1070+
12021071 // Set h264 via native or flash fallback
12031072 for ( var source = 0; source < playableSources.length; source++ ) {
12041073 var mimeType = playableSources[source].mimeType;
12051074 var player = mw.EmbedTypes.players.defaultPlayer( mimeType );
1206 - if ( mimeType == 'video/h264'
1207 - && player
1208 - && (
1209 - player.library == 'Native'
 1075+ if ( mimeType == 'video/h264'
 1076+ && player
 1077+ && (
 1078+ player.library == 'Native'
12101079 ||
12111080 player.library == 'Kplayer'
12121081 )
@@ -1215,7 +1084,7 @@
12161085 return true;
12171086 }
12181087 };
1219 -
 1088+
12201089 // Else just select first source
12211090 if ( !this.selectedSource ) {
12221091 mw.log( 'set via first source:' + playableSources[0] );
@@ -1225,34 +1094,37 @@
12261095 // No Source found so no source selected
12271096 return false;
12281097 },
1229 -
 1098+
12301099 /**
1231 - * check if the mime is ogg
1232 - */
 1100+ * check if the mime is ogg
 1101+ */
12331102 isOgg: function( mimeType ){
1234 - if ( mimeType == 'video/ogg'
1235 - || mimeType == 'ogg/video'
1236 - || mimeType == 'video/annodex'
 1103+ if ( mimeType == 'video/ogg'
 1104+ || mimeType == 'ogg/video'
 1105+ || mimeType == 'video/annodex'
12371106 || mimeType == 'application/ogg'
12381107 ) {
12391108 return true;
12401109 }
12411110 return false;
12421111 },
1243 -
 1112+
12441113 /**
1245 - * Returns the thumbnail URL for the media element.
1246 - * @returns {String} thumbnail URL
1247 - */
 1114+ * Returns the thumbnail URL for the media element.
 1115+ *
 1116+ * @returns {String} thumbnail URL
 1117+ */
12481118 getPosterSrc: function( ) {
12491119 return this.poster;
12501120 },
1251 -
 1121+
12521122 /**
1253 - * Checks whether there is a stream of a specified MIME type.
1254 - * @param {String} mimeType MIME type to check.
1255 - * @return {Boolean} true if sources include MIME false if not.
1256 - */
 1123+ * Checks whether there is a stream of a specified MIME type.
 1124+ *
 1125+ * @param {String}
 1126+ * mimeType MIME type to check.
 1127+ * @return {Boolean} true if sources include MIME false if not.
 1128+ */
12571129 hasStreamOfMIMEType: function( mimeType )
12581130 {
12591131 for ( var i = 0; i < this.sources.length; i++ )
@@ -1263,10 +1135,10 @@
12641136 }
12651137 return false;
12661138 },
1267 -
 1139+
12681140 /**
1269 - * Checks if media is a playable type
1270 - */
 1141+ * Checks if media is a playable type
 1142+ */
12711143 isPlayableType: function( mimeType ) {
12721144 if ( mw.EmbedTypes.players.defaultPlayer( mimeType ) ) {
12731145 return true;
@@ -1274,17 +1146,20 @@
12751147 return false;
12761148 }
12771149 },
1278 -
 1150+
12791151 /**
1280 - * Adds a single mediaSource using the provided element if
1281 - * the element has a 'src' attribute.
1282 - * @param {Element} element <video>, <source> or <mediaSource> <text> element.
1283 - */
 1152+ * Adds a single mediaSource using the provided element if the element has a
 1153+ * 'src' attribute.
 1154+ *
 1155+ * @param {Element}
 1156+ * element <video>, <source> or <mediaSource> <text> element.
 1157+ */
12841158 tryAddSource: function( element ) {
1285 - //mw.log( 'f:tryAddSource:' + $j( element ).attr( "src" ) );
 1159+ // mw.log( 'f:tryAddSource:' + $j( element ).attr( "src" ) );
12861160 var newSrc = $j( element ).attr( 'src' );
12871161 if ( newSrc ) {
1288 - // make sure an existing element with the same src does not already exist:
 1162+ // make sure an existing element with the same src does not already
 1163+ // exist:
12891164 for ( var i = 0; i < this.sources.length; i++ ) {
12901165 if ( this.sources[i].src == newSrc ) {
12911166 // Source already exists update any new attr:
@@ -1295,45 +1170,48 @@
12961171 }
12971172 // Create a new source
12981173 var source = new mediaSource( element );
1299 -
 1174+
13001175 this.sources.push( source );
1301 - //mw.log( 'tryAddSource: added source ::' + source + 'sl:' + this.sources.length );
 1176+ // mw.log( 'tryAddSource: added source ::' + source + 'sl:' +
 1177+ // this.sources.length );
13021178 return source;
13031179 },
1304 -
 1180+
13051181 /**
1306 - * Get playable sources
1307 - *
1308 - * @returns {Array} of playable sources
1309 - */
 1182+ * Get playable sources
 1183+ *
 1184+ * @returns {Array} of playable sources
 1185+ */
13101186 getPlayableSources: function() {
1311 - var playableSources = [];
 1187+ var playableSources = [];
13121188 for ( var i = 0; i < this.sources.length; i++ ) {
13131189 if ( this.isPlayableType( this.sources[i].mimeType ) ) {
13141190 playableSources.push( this.sources[i] );
13151191 } else {
1316 - //mw.log( "type " + this.sources[i].mimeType + 'is not playable' );
 1192+ mw.log( "type " + this.sources[i].mimeType + ' is not playable' );
13171193 }
13181194 };
13191195 return playableSources;
13201196 },
1321 -
 1197+
13221198 /**
1323 - * Imports media sources from ROE data.
1324 - * @param roe_data ROE data.
1325 - */
 1199+ * Imports media sources from ROE data.
 1200+ *
 1201+ * @param roe_data
 1202+ * ROE data.
 1203+ */
13261204 addROE: function( roe_data ) {
13271205 mw.log( 'EmbedPlayer::mediaElement:addROE' );
13281206 this.addedROEData = true;
13291207 var _this = this;
13301208 if ( roe_data ) {
13311209 var $roeParsed = $j( roe_data.pay_load );
1332 -
 1210+
13331211 // Add media sources:
13341212 $roeParsed.find("mediaSource").each( function( inx, source ) {
13351213 _this.tryAddSource( source );
13361214 } );
1337 -
 1215+
13381216 // Set the thumbnail:
13391217 $roeParsed.find( 'img' ).each( function( inx, n ) {
13401218 if ( $j( n ).attr( "id" ) == "stream_thumb" ) {
@@ -1341,7 +1219,7 @@
13421220 _this.poster = $j( n ).attr( "src" );
13431221 }
13441222 } );
1345 -
 1223+
13461224 // Set the linkback:
13471225 $roeParsed.find( 'link' ).each( function( inx, n ) {
13481226 if ( $j( n ).attr( 'id' ) == 'html_linkback' ) {
@@ -1357,78 +1235,91 @@
13581236
13591237
13601238 /**
1361 -* Base embedPlayer object
1362 -* @param {Element} element, the element used for initialization.
1363 -* @param {Object} customAttributes Attributes for the video interface
1364 -* that are not already element attributes
1365 -* @constructor
1366 -*/
 1239+ * Base embedPlayer object
 1240+ *
 1241+ * @param {Element}
 1242+ * element, the element used for initialization.
 1243+ * @param {Object}
 1244+ * customAttributes Attributes for the video interface that are not
 1245+ * already element attributes
 1246+ * @constructor
 1247+ */
13671248 mw.EmbedPlayer = function( element, customAttributes ) {
13681249 return this.init( element, customAttributes );
13691250 };
13701251
13711252 mw.EmbedPlayer.prototype = {
1372 -
 1253+
13731254 // The mediaElement object containing all mediaSource objects
13741255 'mediaElement' : null,
1375 -
1376 - // Object that describes the supported feature set of the underling plugin / player
 1256+
 1257+ // Object that describes the supported feature set of the underling plugin /
 1258+ // player
13771259 'supports': { },
1378 -
 1260+
13791261 // Preview mode flag,
13801262 // some plugins don't seek accurately but in preview mode we need
13811263 // accurate seeks so we do tricks like hide the image until its ready
13821264 'preview_mode' : false,
1383 -
 1265+
13841266 // Ready to play
13851267 // NOTE: we should switch over to setting the html5 video ready state
1386 - 'readyToPlay' : false,
1387 -
 1268+ 'readyToPlay' : false,
 1269+
13881270 // Stores the loading errors
1389 - 'loadError' : false,
1390 -
1391 - // Thumbnail updating flag ( to avoid rewriting an thumbnail thats already being updated)
 1271+ 'loadError' : false,
 1272+
 1273+ // Thumbnail updating flag ( to avoid rewriting an thumbnail thats already
 1274+ // being updated)
13921275 'thumbnail_updating' : false,
1393 -
 1276+
13941277 // Thumbnail display flag
13951278 'thumbnail_disp' : true,
1396 -
 1279+
13971280 // Local variable to hold CMML meeta data about the current clip
13981281 // for more on CMML see: http://wiki.xiph.org/CMML
13991282 'cmmlData': null,
1400 -
 1283+
14011284 // Stores the seek time request, Updated by the doSeek function
14021285 'serverSeekTime' : 0,
1403 -
 1286+
14041287 // If the embedPlayer is current 'seeking'
14051288 'seeking' : false,
1406 -
 1289+
14071290 // Percent of the clip buffered:
14081291 'bufferedPercent' : 0,
1409 -
 1292+
14101293 // Holds the timer interval function
14111294 'monitorTimerId' : null,
1412 -
 1295+
14131296 // Buffer flags
14141297 'bufferStartFlag' : false,
14151298 'bufferEndFlag' : false,
1416 -
 1299+
14171300 // On done playing
1418 - 'donePlayingCount' : 0,
1419 -
 1301+ 'donePlayingCount' : 0
 1302+ ,
 1303+ // if player events should be Propagated
 1304+ '_propagateEvents': true,
 1305+
 1306+
14201307 /**
1421 - * embedPlayer constructor
1422 - *
1423 - * @param {Element} element DOM element that we are building the player interface for.
1424 - * @param {Object} customAttributes Attributes supplied via argument (rather than applied to the element)
1425 - */
 1308+ * embedPlayer constructor
 1309+ *
 1310+ * @param {Element}
 1311+ * element DOM element that we are building the player interface
 1312+ * for.
 1313+ * @param {Object}
 1314+ * customAttributes Attributes supplied via argument (rather than
 1315+ * applied to the element)
 1316+ */
14261317 init: function( element, customAttributes ) {
14271318 var _this = this;
14281319 // Set customAttributes if unset:
14291320 if ( !customAttributes ) {
14301321 customAttributes = { };
14311322 }
1432 -
 1323+
14331324 var playerAttributes = mw.getConfig( 'EmbedPlayer.Attributes' );
14341325 // Setup the player Interface from supported attributes:
14351326 for ( var attr in playerAttributes ) {
@@ -1449,17 +1340,17 @@
14501341 if( this[ attr ] == "true" ) this[attr] = true;
14511342 }
14521343 //
1453 -
1454 -
 1344+
 1345+
14551346 if( this.apiTitleKey ){
14561347 this.apiTitleKey = decodeURI( this.apiTitleKey );
14571348 }
1458 -
 1349+
14591350 // Hide "controls" if using native player controls:
14601351 if( this.useNativePlayerControls() ){
14611352 _this.controls = false;
14621353 }
1463 -
 1354+
14641355 // Set the poster:
14651356 if ( $j( element ).attr( 'thumbnail' ) ) {
14661357 _this.poster = $j( element ).attr( 'thumbnail' );
@@ -1467,10 +1358,10 @@
14681359 if ( $j( element ).attr( 'poster' ) ) {
14691360 _this.poster = $j( element ).attr( 'poster' );
14701361 }
1471 -
 1362+
14721363 // Set the skin name from the class
14731364 var sn = $j(element).attr( 'class' );
1474 -
 1365+
14751366 if ( sn && sn != '' ) {
14761367 for ( var n = 0; n < mw.validSkins.length; n++ ) {
14771368 if ( sn.indexOf( mw.validSkins[n].toLowerCase() ) !== -1 ) {
@@ -1478,55 +1369,56 @@
14791370 }
14801371 }
14811372 }
1482 -
 1373+
14831374 // Set the default skin if unset:
14841375 if ( !this.skinName ) {
14851376 this.skinName = mw.getConfig( 'EmbedPlayer.SkinName' );
14861377 }
1487 -
 1378+
14881379 if( !this.monitorRate ){
14891380 this.monitorRate = mw.getConfig( 'EmbedPlayer.MonitorRate' );
14901381 }
1491 -
 1382+
14921383 // Make sure startOffset is cast as an float:
14931384 if ( this.startOffset && this.startOffset.split( ':' ).length >= 2 ) {
14941385 this.startOffset = parseFloat( mw.npt2seconds( this.startOffset ) );
14951386 }
1496 -
 1387+
14971388 // Make sure offset is in float:
14981389 this.startOffset = parseFloat( this.startOffset );
1499 -
1500 - // Set the source duration ( if provided in the element metaData or durationHint )
 1390+
 1391+ // Set the source duration ( if provided in the element metaData or
 1392+ // durationHint )
15011393 if ( $j( element ).attr( 'duration' ) ) {
15021394 _this.duration = $j( element ).attr( 'duration' );
15031395 }
1504 -
 1396+
15051397 if ( !_this.duration && $j( element ).attr( 'durationHint' ) ) {
15061398 _this.durationHint = $j( element ).attr( 'durationHint' );
15071399 // Convert duration hint if needed:
15081400 _this.duration = mw.npt2seconds( _this.durationHint );
1509 - }
1510 -
 1401+ }
 1402+
15111403 // Make sure duration is a float:
15121404 this.duration = parseFloat( this.duration );
15131405 mw.log( 'EmbedPlayer::mediaElement:' + this.id + " duration is: " + this.duration );
1514 -
 1406+
15151407 // Set the player size attributes based loaded video element:
1516 - this.setPlayerSize( element );
1517 -
 1408+ this.setPlayerSize( element );
 1409+
15181410 // Set the plugin id
15191411 this.pid = 'pid_' + this.id;
15201412
15211413 // Grab any innerHTML and set it to missing_plugin_html
15221414 // NOTE: we should strip "source" tags instead of checking and skipping
15231415 if ( element.innerHTML != '' && element.getElementsByTagName( 'source' ).length == 0 ) {
1524 - //mw.log( 'innerHTML: ' + element.innerHTML );
 1416+ // mw.log( 'innerHTML: ' + element.innerHTML );
15251417 this.user_missing_plugin_html = element.innerHTML;
15261418 }
1527 -
 1419+
15281420 // Add the mediaElement object with the elements sources:
15291421 this.mediaElement = new mediaElement( element );
1530 -
 1422+
15311423 // Process attribute "sources" for dynamic embedding
15321424 if( customAttributes.sources && customAttributes.sources.length ){
15331425 for( var i =0; i < customAttributes.sources.length ; i ++ ){
@@ -1534,7 +1426,8 @@
15351427 if( customSource.src ){
15361428 var $source = $j('<source />')
15371429 .attr( 'src', customSource.src );
1538 - // xxx todo pull list of valid source attributes from mediaSource prototype
 1430+ // xxx todo pull list of valid source attributes from
 1431+ // mediaSource prototype
15391432 if( customSource.type ){
15401433 $source.attr('type', customSource.type );
15411434 }
@@ -1546,59 +1439,67 @@
15471440 }
15481441 }
15491442 },
1550 -
 1443+
 1444+ stopEventPropagation: function(){
 1445+ this._propagateEvents = false;
 1446+ },
 1447+ restoreEventPropagation: function(){
 1448+ this._propagateEvents = true;
 1449+ },
15511450 /**
15521451 * for plugin-players to update supported features
15531452 */
15541453 updateFeatureSupport: function(){
15551454 return ;
15561455 },
1557 -
 1456+
15581457 /**
1559 - * Set the width & height from css style attribute, element attribute, or by default value
1560 - * if no css or attribute is provided set a callback to resize.
1561 - *
1562 - * Updates this.width & this.height
1563 - *
1564 - * @param {Element} element Source element to grab size from
1565 - */
 1458+ * Set the width & height from css style attribute, element attribute, or by
 1459+ * default value if no css or attribute is provided set a callback to
 1460+ * resize.
 1461+ *
 1462+ * Updates this.width & this.height
 1463+ *
 1464+ * @param {Element}
 1465+ * element Source element to grab size from
 1466+ */
15661467 setPlayerSize: function( element ) {
1567 -
 1468+
15681469 this.height = $j(element).css( 'height' );
15691470 this.width = $j(element).css( 'width' );
1570 -
 1471+
15711472 // Set to parent size ( resize events will cause player size updates)
15721473 if( this.height.indexOf('100%') != -1 || this.width.indexOf('100%') != -1 ){
1573 - $relativeParent = $j(element).parents().filter(function() {
1574 - // reduce to only relative position or "body" elements
1575 - return $j( this ).is( 'body' ) || $j(this).css( 'position' ) == 'relative';
 1474+ $relativeParent = $j(element).parents().filter(function() {
 1475+ // reduce to only relative position or "body" elements
 1476+ return $j(this).is('body') || $j(this).css('position') == 'relative';
15761477 }).slice(0,1); // grab only the "first"
15771478 this.width = $relativeParent.width();
15781479 this.height = $relativeParent.height();
15791480 }
1580 -
1581 - // Make sure height and width are a number
 1481+ // make sure height and width are a number
15821482 this.height = parseInt( this.height );
15831483 this.width = parseInt( this.width );
15841484
1585 -
1586 -
1587 - // Set via attribute if CSS is zero or NaN and we have an attribute value:
1588 - this.height = ( ( this.height==0 || isNaN( this.height ) )
1589 - && $j(element).attr( 'height' ) ) ?
 1485+ // Set via attribute if CSS is zero or NaN and we have an attribute
 1486+ // value:
 1487+ this.height = ( this.height==0 || isNaN( this.height )
 1488+ && $j(element).attr( 'height' ) ) ?
15901489 parseInt( $j(element).attr( 'height' ) ): this.height;
1591 - this.width = ( ( this.width == 0 || isNaN( this.width ) )
1592 - && $j(element).attr( 'width' ) )?
 1490+ this.width = ( this.width == 0 || isNaN( this.width )
 1491+ && $j(element).attr( 'width' ) )?
15931492 parseInt( $j(element).attr( 'width' ) ): this.width;
1594 -
1595 -
 1493+
 1494+
15961495 // Special case for audio
1597 - // Firefox sets audio height to "0px" while webkit uses 32px .. force zero:
 1496+ // Firefox sets audio height to "0px" while webkit uses 32px .. force
 1497+ // zero:
15981498 if( element.tagName.toLowerCase() == 'audio' && this.height == '32' ) {
15991499 this.height = 0;
16001500 }
1601 -
1602 - // Use default aspect ration to get height or width ( if rewriting a non-audio player )
 1501+
 1502+ // Use default aspect ration to get height or width ( if rewriting a
 1503+ // non-audio player )
16031504 if( element.tagName.toLowerCase() != 'audio' && this.videoAspect ) {
16041505 var aspect = this.videoAspect.split( ':' );
16051506 if( this.height && !this.width ) {
@@ -1609,20 +1510,23 @@
16101511 this.height = parseInt( this.width * ( aspect[1] / aspect[0] ) );
16111512 }
16121513 }
1613 -
1614 - // On load sometimes attr is temporally -1 as we don't have video metadata yet.
 1514+
 1515+ // On load sometimes attr is temporally -1 as we don't have video
 1516+ // metadata yet.
16151517 // or in IE we get NaN for width height
1616 - //
1617 - // NOTE: browsers that do support height width should set "waitForMeta" flag in addElement
 1518+ //
 1519+ // NOTE: browsers that do support height width should set "waitForMeta"
 1520+ // flag in addElement
16181521 if( ( isNaN( this.height ) && isNaN( this.width ) ) ||
1619 - ( this.height == -1 || this.width == -1 ) ||
 1522+ ( this.height == -1 || this.width == -1 ) ||
16201523 // Check for firefox defaults
1621 - // Note: ideally firefox would not do random guesses at css values
 1524+ // Note: ideally firefox would not do random guesses at css
 1525+ // values
16221526 ( (this.height == 150 || this.height == 64 ) && this.width == 300 )
16231527 ) {
16241528 var defaultSize = mw.getConfig( 'EmbedPlayer.DefaultSize' ).split( 'x' );
16251529 this.width = defaultSize[0];
1626 -
 1530+
16271531 // Special height default for audio tag ( if not set )
16281532 if( element.tagName.toLowerCase() == 'audio' ) {
16291533 this.height = 0;
@@ -1630,65 +1534,62 @@
16311535 this.height = defaultSize[1];
16321536 }
16331537 }
 1538+
16341539 },
16351540 /**
1636 - * Resize the player to a new size
1637 - * @param {object} size The width height size of the player
 1541+ * Resize the player to a new size preserving aspect ratio Wraps the
 1542+ * controlBuilder.resizePlayer function
16381543 */
16391544 resizePlayer: function( size , animate){
16401545 mw.log("EmbedPlayer::resizePlayer:" + size.width + ' x ' + size.height );
1641 - this.width = size.width;
1642 - this.height = size.height;
1643 - var playerSize = {'width' : this.width, 'height' : this.height };
1644 - // check if height needs to include interface controls
1645 - if( ! this.controlBuilder.checkOverlayControls() ){
1646 - size.height = size.height + this.controlBuilder.height;
 1546+
 1547+ // Check if we are native display then resize the playerElement directly
 1548+ if( this.useNativePlayerControls() ){
 1549+ if( animate ){
 1550+ $j( this.getPlayerElement() ).animate( size );
 1551+ } else {
 1552+ $j( this.getPlayerElement() ).css( size );
 1553+ }
 1554+ } else {
 1555+ this.controlBuilder.resizePlayer( size, animate);
16471556 }
1648 -
1649 - if( animate ){
1650 - $j(this).animate(playerSize);
1651 - this.$interface.animate( size );
1652 - }else{
1653 - $j(this).css(playerSize);
1654 - this.$interface.css( size );
1655 - }
16561557 },
1657 -
 1558+
16581559 /**
1659 - * Get the player pixel width not including controls
1660 - *
1661 - * @return {Number} pixel height of the video
1662 - */
 1560+ * Get the player pixel width not including controls
 1561+ *
 1562+ * @return {Number} pixel height of the video
 1563+ */
16631564 getPlayerWidth: function() {
16641565 return $j( this ).width();
16651566 },
1666 -
 1567+
16671568 /**
1668 - * Get the player pixel height not including controls
1669 - *
1670 - * @return {Number} pixel height of the video
1671 - */
 1569+ * Get the player pixel height not including controls
 1570+ *
 1571+ * @return {Number} pixel height of the video
 1572+ */
16721573 getPlayerHeight: function() {
16731574 return $j( this ).height();
16741575 },
16751576
16761577 /**
1677 - * Check player for sources.
1678 - * If we need to get media sources form an external file
1679 - * that request is issued here
1680 - */
 1578+ * Check player for sources. If we need to get media sources form an
 1579+ * external file that request is issued here
 1580+ */
16811581 checkPlayerSources: function() {
16821582 mw.log( 'EmbedPlayer::checkPlayerSources: ' + this.id );
16831583 var _this = this;
1684 -
1685 - // Scope the end of check for player sources so it can be called in a callback
 1584+
 1585+ // Scope the end of check for player sources so it can be called in a
 1586+ // callback
16861587 var finishCheckPlayerSources = function(){
16871588 // Run embedPlayer sources hook
16881589 mw.runTriggersCallback( _this, 'checkPlayerSourcesEvent', function(){
16891590 _this.checkForTimedText();
16901591 });
16911592 };
1692 -
 1593+
16931594 // NOTE: Should could be moved to mediaWiki Api support module
16941595 // only load from api if sources are empty:
16951596 if ( _this.apiTitleKey && this.mediaElement.sources.length == 0) {
@@ -1698,38 +1599,40 @@
16991600 finishCheckPlayerSources();
17001601 } );
17011602 return ;
1702 - } else {
 1603+ } else {
17031604 finishCheckPlayerSources();
17041605 }
17051606 },
1706 -
 1607+
17071608 /**
17081609 * Insert and play a video source ( useful for ads or bumper videos )
1709 - *
1710 - * Only works while video is in active play back.
1711 - * Only tested with native playback atm.
 1610+ *
 1611+ * Only works while video is in active play back. Only tested with native
 1612+ * playback atm.
17121613 */
17131614 insertAndPlaySource: function( source ){
17141615 mw.log("Error: only native playback supports insertAndPlaySource right now");
17151616 },
1716 -
 1617+
17171618 /**
1718 - * Load Source video info from mediaWiki Api title key ( this.apiTitleKey )
1719 - * @@todo move this to mediaWiki 'api' module
1720 - * @param {Function} callback Function called once loading is complete
1721 - */
 1619+ * Load Source video info from mediaWiki Api title key ( this.apiTitleKey )
 1620+ *
 1621+ * @@todo move this to mediaWiki 'api' module
 1622+ * @param {Function}
 1623+ * callback Function called once loading is complete
 1624+ */
17221625 loadSourceFromApi: function( callback ){
17231626 var _this = this;
17241627 if( !_this.apiTitleKey ){
17251628 mw.log( 'Error no apiTitleKey');
17261629 return false;
17271630 }
1728 -
 1631+
17291632 // Set local apiProvider via config if not defined
17301633 if( !_this.apiProvider ) {
17311634 _this.apiProvider = mw.getConfig( 'EmbedPlayer.ApiProvider' );
17321635 }
1733 -
 1636+
17341637 // Setup the request
17351638 var request = {
17361639 'prop': 'imageinfo',
@@ -1760,40 +1663,40 @@
17611664 return ;
17621665 }
17631666 var imageinfo = page.imageinfo[0];
1764 -
 1667+
17651668 // Set the poster
17661669 _this.poster = imageinfo.thumburl;
1767 -
 1670+
17681671 // Add the media src
17691672 _this.mediaElement.tryAddSource(
17701673 $j('<source />')
17711674 .attr( 'src', imageinfo.url )
17721675 .get( 0 )
17731676 );
1774 -
 1677+
17751678 // Set the duration
17761679 if( imageinfo.metadata[2]['name'] == 'length' ) {
17771680 _this.duration = imageinfo.metadata[2]['value'];
17781681 }
1779 -
 1682+
17801683 // Set the width height
17811684 // Make sure we have an accurate aspect ratio
17821685 if( imageinfo.height != 0 && imageinfo.width != 0 ) {
17831686 _this.height = parseInt( _this.width * ( imageinfo.height / imageinfo.width ) );
17841687 }
1785 -
 1688+
17861689 // Update the css for the player interface
17871690 $j( _this ).css( 'height', _this.height);
1788 -
 1691+
17891692 callback();
17901693 });
17911694 },
1792 -
 1695+
17931696 /**
1794 - * Check if we should load the timedText interface or not.
1795 - *
1796 - * Note we check for text sources outside of
1797 - */
 1697+ * Check if we should load the timedText interface or not.
 1698+ *
 1699+ * Note we check for text sources outside of
 1700+ */
17981701 isTimedTextSupported: function() {
17991702 // Check for timed text sources or api/ roe url
18001703 if ( ( this.roe || this.apiTitleKey ||
@@ -1803,11 +1706,10 @@
18041707 return false;
18051708 }
18061709 },
1807 -
 1710+
18081711 /**
1809 - * Check for timed Text support
1810 - * and load necessary libraries
1811 - */
 1712+ * Check for timed Text support and load necessary libraries
 1713+ */
18121714 checkForTimedText: function( ) {
18131715 var _this = this;
18141716 mw.log( 'EmbedPlayer::checkForTimedText: ' + _this.id );
@@ -1821,19 +1723,19 @@
18221724 }
18231725 _this.setupSourcePlayer();
18241726 },
1825 -
 1727+
18261728 /**
1827 - * Set up the select source player
1828 - *
1829 - * issues autoSelectSource call
1830 - *
1831 - * Sets load error if no source is playable
1832 - */
 1729+ * Set up the select source player
 1730+ *
 1731+ * issues autoSelectSource call
 1732+ *
 1733+ * Sets load error if no source is playable
 1734+ */
18331735 setupSourcePlayer: function() {
1834 - mw.log("EmbedPlayer::setupSourcePlayer: " + this.id );
 1736+ mw.log("EmbedPlayer::setupSourcePlayer: " + this.id + ' sources: ' + this.mediaElement.sources.length );
18351737 // Autoseletct the media source
18361738 this.mediaElement.autoSelectSource();
1837 -
 1739+
18381740 // Auto select player based on default order
18391741 if ( !this.mediaElement.selectedSource ) {
18401742 // check for parent clip:
@@ -1848,39 +1750,25 @@
18491751 } else {
18501752 this.selectedPlayer = mw.EmbedTypes.players.defaultPlayer( this.mediaElement.selectedSource.mimeType );
18511753 }
1852 -
 1754+
18531755 if ( this.selectedPlayer ) {
18541756 // Inherit the playback system of the selected player:
18551757 this.inheritEmbedPlayer();
18561758 } else {
1857 - // No source's playable
1858 - var missingType = '';
1859 - var or = '';
1860 - for ( var i = 0; i < this.mediaElement.sources.length; i++ ) {
1861 - missingType += or + this.mediaElement.sources[i].mimeType;
1862 - or = ' or ';
1863 - }
1864 - // Get from parent playlist if set:
1865 - if ( this.pc ){
1866 - missingType = this.pc.type;
1867 - }
1868 -
1869 - mw.log( 'No player found for given source type ' + missingType );
1870 - this.showPluginMissingHTML( missingType );
1871 -
1872 - // Call the global player manager to inform this video interface is "ready" for page callback to be proccessed.
1873 - mw.playerManager.playerReady( this );
 1759+ this.showPluginMissingHTML();
18741760 }
18751761 },
1876 -
 1762+
18771763 /**
1878 - * Load and inherit methods from the selected player interface
1879 - *
1880 - * @param {Function} callback Function to be called once playback-system has been inherited
1881 - */
 1764+ * Load and inherit methods from the selected player interface
 1765+ *
 1766+ * @param {Function}
 1767+ * callback Function to be called once playback-system has been
 1768+ * inherited
 1769+ */
18821770 inheritEmbedPlayer: function( callback ) {
18831771 mw.log( "EmbedPlayer::inheritEmbedPlayer:duration is: " + this.getDuration() + ' p: ' + this.id );
1884 -
 1772+
18851773 // Clear out any non-base embedObj methods:
18861774 if ( this.instanceOf ) {
18871775 eval( 'var tmpObj = mw.EmbedPlayer' + this.instanceOf );
@@ -1892,55 +1780,59 @@
18931781 }
18941782 }
18951783 }
1896 -
 1784+
18971785 // Set up the new embedObj
18981786 mw.log( 'EmbedPlayer::inheritEmbedPlayer: embedding with ' + this.selectedPlayer.library );
18991787 var _this = this;
1900 -
 1788+
19011789 // Load the selected player
19021790 this.selectedPlayer.load( function() {
19031791 mw.log( 'EmbedPlayer::inheritEmbedPlayer ' + _this.selectedPlayer.library + " player loaded for " + _this.id );
1904 -
 1792+
19051793 // Get embed library player Interface
19061794 var playerInterface = mw[ 'EmbedPlayer' + _this.selectedPlayer.library ];
1907 -
1908 - for ( var method in playerInterface ) {
 1795+
 1796+ for ( var method in playerInterface ) {
19091797 if ( _this[method] && !_this['parent_' + method] ) {
19101798 _this['parent_' + method] = _this[method];
19111799 }
19121800 _this[ method ] = playerInterface[method];
19131801 }
1914 -
 1802+
19151803 // Update feature support
19161804 _this.updateFeatureSupport();
1917 -
 1805+
19181806 _this.getDuration();
1919 -
 1807+
19201808 _this.showPlayer();
1921 - // Call the global player manager to inform this video interface is ready:
 1809+
 1810+ // Call the global player manager to inform this video interface is
 1811+ // ready:
19221812 mw.playerManager.playerReady( _this );
1923 -
 1813+
19241814 // Run the callback if provided
19251815 if ( typeof callback == 'function' ){
19261816 callback();
19271817 }
19281818 } );
19291819 },
1930 -
 1820+
19311821 /**
1932 - * Select a player playback system
1933 - *
1934 - * @param {Object} player Player playback system to be selected
1935 - * player playback system include vlc, native, java etc.
1936 - */
 1822+ * Select a player playback system
 1823+ *
 1824+ * @param {Object}
 1825+ * player Player playback system to be selected player playback
 1826+ * system include vlc, native, java etc.
 1827+ */
19371828 selectPlayer: function( player ) {
19381829 var _this = this;
19391830 if ( this.selectedPlayer.id != player.id ) {
19401831 this.selectedPlayer = player;
19411832 this.inheritEmbedPlayer( function(){
19421833 // Hide / remove track container
1943 - _this.$interface.find( '.track' ).remove();
1944 - // We have to re-bind hoverIntent ( has to happen in this scope )
 1834+ _this.$interface.find( '.track' ).remove();
 1835+ // We have to re-bind hoverIntent ( has to happen in this scope
 1836+ // )
19451837 if( _this.controls && _this.controlBuilder.checkOverlayControls() ){
19461838 _this.controlBuilder.showControlBar();
19471839 _this.$interface.hoverIntent({
@@ -1952,17 +1844,17 @@
19531845 'out' : function(){
19541846 _this.controlBuilder.hideControlBar();
19551847 }
1956 - });
 1848+ })
19571849 }
19581850 });
19591851 }
19601852 },
1961 -
 1853+
19621854 /**
1963 - * Get a time range from the media start and end time
1964 - *
1965 - * @return start_npt and end_npt time if present
1966 - */
 1855+ * Get a time range from the media start and end time
 1856+ *
 1857+ * @return start_npt and end_npt time if present
 1858+ */
19671859 getTimeRange: function() {
19681860 var end_time = (this.controlBuilder.longTimeDisp)? '/' + mw.seconds2npt( this.getDuration() ) : '';
19691861 var default_time_range = '0:00:00' + end_time;
@@ -1974,53 +1866,55 @@
19751867 return default_time_range;
19761868 return this.mediaElement.selectedSource.start_npt + this.mediaElement.selectedSource.end_npt;
19771869 },
1978 -
 1870+
19791871 /**
1980 - * Get the duration of the embed player
1981 - */
 1872+ * Get the duration of the embed player
 1873+ */
19821874 getDuration: function() {
19831875 return this.duration;
19841876 },
1985 -
 1877+
19861878 /**
1987 - * Get the player height
1988 - */
 1879+ * Get the player height
 1880+ */
19891881 getHeight: function() {
19901882 return this.height;
19911883 },
1992 -
 1884+
19931885 /**
1994 - * Get the player width
1995 - */
 1886+ * Get the player width
 1887+ */
19961888 getWidth: function(){
19971889 return this.width;
19981890 },
1999 -
 1891+
20001892 /**
2001 - * Check if the selected source is an audio element:
2002 - */
 1893+ * Check if the selected source is an audio element:
 1894+ */
20031895 isAudio: function(){
20041896 return ( this.mediaElement.selectedSource.mimeType.indexOf('audio/') !== -1 );
20051897 },
2006 -
 1898+
20071899 /**
2008 - * Get the plugin embed html ( should be implemented by embed player interface )
2009 - */
 1900+ * Get the plugin embed html ( should be implemented by embed player
 1901+ * interface )
 1902+ */
20101903 doEmbedHTML: function() {
20111904 return 'Error: function doEmbedHTML should be implemented by embed player interface ';
20121905 },
2013 -
 1906+
20141907 /**
2015 - * Seek function ( should be implemented by embedPlayer interface playerNative, playerKplayer etc. )
2016 - * embedPlayer doSeek only handles URL time seeks
2017 - */
 1908+ * Seek function ( should be implemented by embedPlayer interface
 1909+ * playerNative, playerKplayer etc. ) embedPlayer doSeek only handles URL
 1910+ * time seeks
 1911+ */
20181912 doSeek: function( percent ) {
20191913 var _this = this;
2020 -
 1914+
20211915 this.seeking = true;
20221916 // Run the seeking hook
20231917 $j( this.embedPlayer ).trigger( 'onSeek' );
2024 -
 1918+
20251919 // See if we should do a server side seek ( player independent )
20261920 if ( this.supportsURLTimeEncoding() ) {
20271921 mw.log( 'EmbedPlayer::doSeek:: updated serverSeekTime: ' + mw.seconds2npt ( this.serverSeekTime ) );
@@ -2031,137 +1925,148 @@
20321926 // Update the slider
20331927 this.updatePlayHead( percent );
20341928 }
2035 -
2036 - // Do play request in 100ms ( give the dom time to swap out the embed player )
 1929+
 1930+ // Do play request in 100ms ( give the dom time to swap out the embed
 1931+ // player )
20371932 setTimeout( function() {
20381933 _this.seeking = false;
2039 - _this.play();
 1934+ _this.play()
20401935 _this.monitor();
20411936 }, 100 );
2042 -
 1937+
20431938 // Run the onSeeking interface update
20441939 // NOTE controlBuilder should really bind to html5 events rather
20451940 // than explicitly calling it or inheriting stuff.
2046 - this.controlBuilder.onSeek();
 1941+ this.controlBuilder.onSeek();
20471942 },
2048 -
 1943+
20491944 /**
2050 - * Seeks to the requested time and issues a callback when ready
2051 - * (should be overwritten by client that supports frame serving)
 1945+ * Seeks to the requested time and issues a callback when ready (should be
 1946+ * overwritten by client that supports frame serving)
20521947 */
20531948 setCurrentTime: function( time, callback ) {
20541949 mw.log( 'Error: base embed setCurrentTime can not frame serve (override via plugin)' );
20551950 },
2056 -
 1951+
20571952 /**
2058 - * On clip done action. Called once a clip is done playing
2059 - */
 1953+ * On clip done action. Called once a clip is done playing
 1954+ */
20601955 onClipDone: function() {
20611956 mw.log( 'EmbedPlayer::onClipDone:' + this.id + ' doneCount:' + this.donePlayingCount + ' stop state:' +this.isStopped() );
20621957 var _this = this;
2063 -
 1958+
20641959 // Only run stopped once:
20651960 if( !this.isStopped() ){
20661961 // Stop the monitor:
20671962 this.stopMonitor();
2068 -
 1963+
20691964 // Show the control bar:
20701965 this.controlBuilder.showControlBar();
2071 -
 1966+
20721967 // Update the clip done playing count:
20731968 this.donePlayingCount ++;
2074 -
 1969+
20751970 // Fire the html5 ended binding
20761971 var onDoneActionObject = {
20771972 'runBaseControlDone' : true
2078 - };
2079 -
2080 - // Run the ended trigger ( allow the ended object to prevent default actions )
 1973+ }
 1974+
 1975+ // Run the ended trigger ( allow the ended object to prevent default
 1976+ // actions )
20811977 mw.log("EmbedPlayer::onClipDone:Trigger ended");
20821978 $j( this ).trigger( 'ended', onDoneActionObject );
2083 -
 1979+
20841980 if( onDoneActionObject.runBaseControlDone ){
2085 -
 1981+
20861982 // Check if we have the "loop" property set
20871983 if( this.loop ) {
20881984 this.stop();
20891985 this.play();
2090 - return;
 1986+ return;
20911987 }
2092 -
 1988+
20931989 // Stop the clip (load the thumbnail etc)
20941990 this.stop();
20951991 this.serverSeekTime = 0;
20961992 this.updatePlayHead( 0 );
2097 -
2098 - // Make sure we are not in preview mode( no end clip actions in preview mode)
 1993+
 1994+ // Make sure we are not in preview mode( no end clip actions in
 1995+ // preview mode)
20991996 if ( this.preview_mode ) {
21001997 return ;
21011998 }
2102 -
 1999+
21032000 // Do the controlBuilder onClip done interface
21042001 this.controlBuilder.onClipDone();
21052002 }
21062003 }
 2004+
21072005 },
2108 -
2109 -
 2006+
 2007+
21102008 /**
2111 - * Shows the video Thumbnail, updates pause state
2112 - */
 2009+ * Shows the video Thumbnail, updates pause state
 2010+ */
21132011 showThumbnail: function() {
21142012 var _this = this;
21152013 mw.log( 'EmbedPlayer::showThumbnail' + this.thumbnail_disp );
2116 -
 2014+
21172015 // Close Menu Overlay:
21182016 this.controlBuilder.closeMenuOverlay();
2119 -
 2017+
21202018 // update the thumbnail html:
21212019 this.updatePosterHTML();
2122 -
 2020+
21232021 this.paused = true;
21242022 this.thumbnail_disp = true;
21252023 // Make sure the controlBuilder bindings are up-to-date
21262024 this.controlBuilder.addControlBindings();
2127 -
2128 - // Once the thumbnail is shown run the mediaReady trigger (if not using native controls)
 2025+
 2026+ // Once the thumbnail is shown run the mediaReady trigger (if not using
 2027+ // native controls)
21292028 if( !this.useNativePlayerControls() ){
21302029 mw.log("mediaLoaded");
21312030 $j( this ).trigger( 'mediaLoaded' );
21322031 }
21332032 },
2134 -
 2033+
21352034 /**
2136 - * Show the player
2137 - */
 2035+ * Show the player
 2036+ */
21382037 showPlayer : function () {
21392038 mw.log( 'EmbedPlayer:: Show player: ' + this.id + ' interace: w:' + this.width + ' h:' + this.height);
21402039 var _this = this;
21412040 // Set-up the local controlBuilder instance:
21422041 this.controlBuilder = new mw.PlayerControlBuilder( this );
21432042 var _this = this;
2144 -
 2043+
21452044 // Make sure we have mwplayer_interface
21462045 if( $j( this ).parent( '.mwplayer_interface' ).length == 0 ) {
21472046 // Select "player"
21482047 $j( this )
2149 - .wrap(
 2048+ .wrap(
21502049 $j('<div>')
21512050 .addClass( 'mwplayer_interface ' + this.controlBuilder.playerClass )
21522051 .css({
2153 - 'width' : this.width + 'px',
2154 - 'height' : this.height + 'px',
2155 - 'position' : 'relative'
 2052+ 'width' : this.width,
 2053+ 'height' : this.height,
 2054+ 'position' : 'relative',
 2055+ 'background' : '#000'
21562056 })
2157 - );
 2057+ )
 2058+ // position the "player" absolute inside the relative interface
 2059+ // parent:
 2060+ .css('position', 'absolute');
21582061 }
21592062
2160 - //Set up local jQuery object reference to "mwplayer_interface"
 2063+
 2064+
 2065+ // Set up local jQuery object reference to "mwplayer_interface"
21612066 this.$interface = $j( this ).parent( '.mwplayer_interface' );
2162 -
 2067+
21632068 // Update Thumbnail for the "player"
21642069 this.updatePosterHTML();
2165 -
 2070+
21662071 // Add controls if enabled:
21672072 if ( this.controls ) {
21682073 this.controlBuilder.addControls();
@@ -2170,35 +2075,44 @@
21712076 // Interface is hidden if controls are "off"
21722077 this.$interface.hide();
21732078 }
2174 -
 2079+
21752080 if ( this.autoplay ) {
21762081 mw.log( 'EmbedPlayer::showPlayer::activating autoplay' );
21772082 // Issue a non-blocking play request
21782083 setTimeout(function(){
21792084 _this.play();
2180 - },0);
 2085+ },0)
21812086 }
2182 -
 2087+
21832088 },
2184 -
 2089+
21852090 /**
2186 - * Get missing plugin html (check for user included code)
2187 - * @param {String} [misssingType] missing type mime
2188 - */
2189 - showPluginMissingHTML: function( misssingType ) {
 2091+ * Get missing plugin html (check for user included code)
 2092+ *
 2093+ * @param {String}
 2094+ * [misssingType] missing type mime
 2095+ */
 2096+ showPluginMissingHTML: function( ) {
 2097+ // Get mime type for unsuported formats:
 2098+ var missingType = '';
 2099+ var or = '';
 2100+ for ( var i = 0; i < this.mediaElement.sources.length; i++ ) {
 2101+ missingType += or + this.mediaElement.sources[i].mimeType;
 2102+ or = ' or ';
 2103+ }
21902104 // Remove the loading spinner if present:
21912105 $j('.playerLoadingSpinner').remove();
2192 -
 2106+
21932107 // If the native video is already displayed hide it:
21942108 if( $j( '#' + this.pid ).length != 0 ){
21952109 $j('#loadingSpinner_' + this.id ).remove();
2196 - $j( '#' + this.pid ).hide();
 2110+ $j( '#' + this.pid ).hide()
21972111 }
21982112 if( this.mediaElement.sources.length == 0 ){
2199 - // Hide the pid if present:
 2113+ // hide the pid if present:
22002114 $j( '#pid_' + this.id ).hide();
22012115 $j( this ).show().html(
2202 - $j('<span />').text(
 2116+ $j('<span />').text(
22032117 gM('mwe-embedplayer-missing-source')
22042118 )
22052119 );
@@ -2207,53 +2121,53 @@
22082122 var source = this.mediaElement.sources[0];
22092123 // Check if we have user defined missing html msg:
22102124 if ( this.user_missing_plugin_html ) {
2211 - $j( this ).html( this.user_missing_plugin_html );
2212 - } else {
2213 - if ( !misssingType ){
2214 - misssingType = '';
2215 - }
2216 - $j( this ).html(
2217 - $j('<div />').append(
2218 - gM( 'mwe-embedplayer-generic_missing_plugin', misssingType ),
2219 - $j( '<br />' ),
2220 - $j( '<a />' )
2221 - .attr( {
2222 - 'title' : gM( 'mwe-embedplayer-download_clip' ),
2223 - 'href' : source.src
2224 - })
2225 - .text( gM( 'mwe-embedplayer-download_clip' ) )
2226 - )
2227 - );
 2125+ $j( this ).html( this.user_missing_plugin_html );
 2126+ } else {
 2127+ $j( this ).html(
 2128+ $j('<div />').append(
 2129+ gM( 'mwe-embedplayer-generic_missing_plugin', missingType ),
 2130+ $j( '<br />' ),
 2131+ $j( '<a />' )
 2132+ .attr( {
 2133+ 'title' : gM( 'mwe-embedplayer-download_clip' ),
 2134+ 'href' : source.src
 2135+ })
 2136+ .text( gM( 'mwe-embedplayer-download_clip' ) )
 2137+ )
 2138+ );
22282139 }
22292140 // hide
22302141 },
2231 -
 2142+
22322143 /**
2233 - * Update the video time request via a time request string
2234 - * @param {String} time_req
2235 - */
 2144+ * Update the video time request via a time request string
 2145+ *
 2146+ * @param {String}
 2147+ * time_req
 2148+ */
22362149 updateVideoTimeReq: function( time_req ) {
22372150 mw.log( 'EmbedPlayer::updateVideoTimeReq:' + time_req );
22382151 var time_parts = time_req.split( '/' );
22392152 this.updateVideoTime( time_parts[0], time_parts[1] );
22402153 },
2241 -
 2154+
22422155 /**
2243 - * Update Video time from provided start_npt and end_npt values
2244 - *
2245 - * @param {String} start_npt the new start time in npt format
2246 - * @pamra {String} end_npt the new end time in npt format
2247 - */
 2156+ * Update Video time from provided start_npt and end_npt values
 2157+ *
 2158+ * @param {String}
 2159+ * start_npt the new start time in npt format
 2160+ * @pamra {String} end_npt the new end time in npt format
 2161+ */
22482162 updateVideoTime: function( start_npt, end_npt ) {
22492163 // update media
22502164 this.mediaElement.updateSourceTimes( start_npt, end_npt );
2251 -
 2165+
22522166 // update mv_time
22532167 this.controlBuilder.setStatus( start_npt + '/' + end_npt );
2254 -
 2168+
22552169 // reset slider
22562170 this.updatePlayHead( 0 );
2257 -
 2171+
22582172 // reset seek_offset:
22592173 if ( this.mediaElement.selectedSource.URLTimeEncoding ) {
22602174 this.serverSeekTime = 0;
@@ -2262,19 +2176,23 @@
22632177 }
22642178 },
22652179
2266 -
 2180+
22672181 /**
2268 - * Update Thumb time with npt formated time
2269 - * @param {String} time NPT formated time to update thumbnail
2270 - */
 2182+ * Update Thumb time with npt formated time
 2183+ *
 2184+ * @param {String}
 2185+ * time NPT formated time to update thumbnail
 2186+ */
22712187 updateThumbTimeNPT: function( time ) {
22722188 this.updateThumbTime( mw.npt2seconds( time ) - parseInt( this.startOffset ) );
22732189 },
2274 -
 2190+
22752191 /**
2276 - * Update the thumb with a new time
2277 - * @param {Float} floatSeconds Time to update the thumb to
2278 - */
 2192+ * Update the thumb with a new time
 2193+ *
 2194+ * @param {Float}
 2195+ * floatSeconds Time to update the thumb to
 2196+ */
22792197 updateThumbTime:function( floatSeconds ) {
22802198 // mw.log('updateThumbTime:'+floatSeconds);
22812199 var _this = this;
@@ -2283,8 +2201,8 @@
22842202 }
22852203 if ( this.org_thum_src.indexOf( 't=' ) !== -1 ) {
22862204 this.last_thumb_url = mw.replaceUrlParams( this.org_thum_src,
2287 - {
2288 - 't' : mw.seconds2npt( floatSeconds + parseInt( this.startOffset ) )
 2205+ {
 2206+ 't' : mw.seconds2npt( floatSeconds + parseInt( this.startOffset ) )
22892207 }
22902208 );
22912209 if ( !this.thumbnail_updating ) {
@@ -2293,23 +2211,26 @@
22942212 }
22952213 }
22962214 },
2297 -
 2215+
22982216 /**
2299 - * Updates the displayed thumbnail via percent of the stream
2300 - * @param {Float} percent Percent of duration to update thumb
2301 - */
 2217+ * Updates the displayed thumbnail via percent of the stream
 2218+ *
 2219+ * @param {Float}
 2220+ * percent Percent of duration to update thumb
 2221+ */
23022222 updateThumbPerc:function( percent ) {
23032223 return this.updateThumbTime( ( this.getDuration() * percent ) );
23042224 },
2305 -
 2225+
23062226 /**
2307 - * Updates the thumbnail if the thumbnail is being displayed
2308 - *
2309 - * @param {String} src New src of thumbnail
2310 - * @param {Boolean} quick_switch
2311 - * true switch happens instantly
2312 - * false / undefined animated cross fade
2313 - */
 2227+ * Updates the thumbnail if the thumbnail is being displayed
 2228+ *
 2229+ * @param {String}
 2230+ * src New src of thumbnail
 2231+ * @param {Boolean}
 2232+ * quick_switch true switch happens instantly false / undefined
 2233+ * animated cross fade
 2234+ */
23142235 updatePosterSrc: function( src, quick_switch ) {
23152236 // make sure we don't go to the same url if we are not already updating:
23162237 if ( !this.thumbnail_updating && $j( '#img_thumb_' + this.id ).attr( 'src' ) == src )
@@ -2317,9 +2238,9 @@
23182239 // if we are already updating don't issue a new update:
23192240 if ( this.thumbnail_updating && $j( '#new_img_thumb_' + this.id ).attr( 'src' ) == src )
23202241 return false;
2321 -
 2242+
23222243 mw.log( 'update thumb: ' + src );
2323 -
 2244+
23242245 if ( quick_switch ) {
23252246 $j( '#img_thumb_' + this.id ).attr( 'src', src );
23262247 } else {
@@ -2327,11 +2248,11 @@
23282249 // if still animating remove new_img_thumb_
23292250 if ( this.thumbnail_updating == true )
23302251 $j( '#new_img_thumb_' + this.id ).stop().remove();
2331 -
 2252+
23322253 if ( this.thumbnail_disp ) {
23332254 mw.log( 'set to thumb:' + src );
23342255 this.thumbnail_updating = true;
2335 - $j( this ).append(
 2256+ $j( this ).append(
23362257 $j('<img />')
23372258 .attr({
23382259 'src' : src,
@@ -2342,7 +2263,7 @@
23432264 .css( {
23442265 'display' : 'none',
23452266 'position' : 'absolute',
2346 - 'z-index' : 2,
 2267+ 'zindex' : 2,
23472268 'top' : '0px',
23482269 'left' : '0px'
23492270 })
@@ -2352,9 +2273,10 @@
23532274 // once faded in remove org and rename new:
23542275 $j( '#img_thumb_' + _this.id ).remove();
23552276 $j( '#new_img_thumb_' + _this.id ).attr( 'id', 'img_thumb_' + _this.id );
2356 - $j( '#img_thumb_' + _this.id ).css( 'z-index', '1' );
 2277+ $j( '#img_thumb_' + _this.id ).css( 'zindex', '1' );
23572278 _this.thumbnail_updating = false;
2358 - // mw.log("done fadding in "+ $j('#img_thumb_'+_this.id).attr("src"));
 2279+ // mw.log("done fadding in "+
 2280+ // $j('#img_thumb_'+_this.id).attr("src"));
23592281
23602282 // if we have a thumb queued update to that
23612283 if ( _this.last_thumb_url ) {
@@ -2366,30 +2288,30 @@
23672289 }
23682290 }
23692291 },
2370 -
 2292+
23712293 /**
2372 - * Returns the HTML code for the video when it is in thumbnail mode.
2373 - * playing, configuring the player, inline cmml display, HTML linkback,
2374 - * download, and embed code.
2375 - */
 2294+ * Returns the HTML code for the video when it is in thumbnail mode.
 2295+ * playing, configuring the player, inline cmml display, HTML linkback,
 2296+ * download, and embed code.
 2297+ */
23762298 updatePosterHTML: function () {
23772299 mw.log( 'EmbedPlayer:updatePosterHTML::' + this.id );
23782300 var thumb_html = '';
23792301 var class_atr = '';
23802302 var style_atr = '';
2381 -
2382 -
 2303+
 2304+
23832305 if( this.useNativePlayerControls() ){
23842306 this.showNativePlayer();
23852307 return ;
23862308 }
2387 -
 2309+
23882310 // Set by default thumb value if not found
2389 - var posterSrc = ( this.poster ) ? this.poster :
 2311+ var posterSrc = ( this.poster ) ? this.poster :
23902312 mw.getConfig( 'imagesPath' ) + 'vid_default_thumb.jpg';
2391 -
 2313+
23922314 // Poster support is not very consistent in browsers
2393 - // use a jpeg poster image:
 2315+ // use a jpg poster image:
23942316 $j( this ).html(
23952317 $j( '<img />' )
23962318 .css({
@@ -2403,59 +2325,60 @@
24042326 })
24052327 .addClass( 'playerPoster' )
24062328 );
2407 -
2408 - if ( this.controls
2409 - && this.height > this.controlBuilder.getComponentHeight( 'playButtonLarge' )
 2329+
 2330+ if ( this.controls
 2331+ && this.height > this.controlBuilder.getComponentHeight( 'playButtonLarge' )
24102332 ) {
24112333 $j( this ).append(
24122334 this.controlBuilder.getComponent( 'playButtonLarge' )
24132335 );
24142336 }
24152337 },
2416 -
 2338+
24172339 /**
24182340 * Checks if native controls should be used
2419 - *
2420 - * @param [player] Object Optional player object to check controls attribute
 2341+ *
 2342+ * @param [player]
 2343+ * Object Optional player object to check controls attribute
24212344 * @returns boolean true if the mwEmbed player interface should be used
2422 - * false if the mwEmbed player interface should not be used
 2345+ * false if the mwEmbed player interface should not be used
24232346 */
24242347 useNativePlayerControls: function() {
24252348 if( this.usenativecontrols === true ){
24262349 return true;
24272350 }
2428 -
 2351+
24292352 if( mw.getConfig('EmbedPlayer.NativeControls') === true ) {
24302353 return true;
24312354 }
24322355 if( mw.getConfig('EmbedPlayer.NativeControlsMobileSafari' ) &&
2433 - mw.isMobileHTML5()
 2356+ mw.isHTML5FallForwardNative()
24342357 ){
24352358 return true;
2436 - }
 2359+ }
24372360 return false;
24382361 },
2439 -
2440 -
 2362+
 2363+
24412364 /**
24422365 * Show the native player embed code
2443 - *
 2366+ *
24442367 * This is for cases where the main library needs to "get out of the way"
2445 - * since the device only supports a limited subset of the html5 and
2446 - * won't work with an html javascirpt interface
 2368+ * since the device only supports a limited subset of the html5 and won't
 2369+ * work with an html javascirpt interface
24472370 */
24482371 showNativePlayer: function(){
24492372 var _this = this;
24502373 // Empty the player
24512374 $j(this).empty();
2452 -
 2375+
24532376 // Remove the player loader spinner if it exists
24542377 $j('#loadingSpinner_' + this.id ).remove();
2455 -
2456 -
 2378+
 2379+
24572380 // Check if we need to refresh mobile safari
24582381 var mobileSafariNeedsRefresh = false;
2459 -
 2382+
24602383 // Unhide the original video element if not part of a playerThemer embed
24612384 if( !$j( '#' + this.pid ).hasClass('PlayerThemer') ){
24622385 $j( '#' + this.pid )
@@ -2464,27 +2387,28 @@
24652388 } )
24662389 .show()
24672390 .attr('controls', 'true');
2468 -
 2391+
24692392 mobileSafariNeedsRefresh = true;
24702393 }
2471 -
 2394+
24722395 // iPad does not handle video tag update for attributes like "controls"
2473 - // so we have to do a full replace ( if controls are not included initially )
2474 - if( mw.isMobileHTML5() && mobileSafariNeedsRefresh ) {
 2396+ // so we have to do a full replace ( if controls are not included
 2397+ // initially )
 2398+ if( mw.isHTML5FallForwardNative() && mobileSafariNeedsRefresh ) {
24752399 var source = this.mediaElement.getSources( 'video/h264' )[0];
24762400 // XXX note this should be updated once mobile supports h.264
24772401 if( !source || !source.src ){
24782402 mw.log( 'Warning: Your probably fakeing the iPhone userAgent ( no h.264 source )' );
24792403 source = this.mediaElement.getSources( 'video/ogg' )[0];
24802404 }
2481 -
 2405+
24822406 var videoAttribues = {
24832407 'id' : _this.pid,
24842408 'poster': _this.poster,
24852409 'src' : source.src,
24862410 'controls' : 'true'
2487 - };
2488 -
 2411+ }
 2412+
24892413 if( this.loop ){
24902414 videoAttribues[ 'loop' ] = 'true';
24912415 }
@@ -2492,17 +2416,18 @@
24932417 'width' : _this.width,
24942418 'height' : _this.height
24952419 };
2496 - $j( '#' + this.pid ).replaceWith(
 2420+ $j( '#' + this.pid ).replaceWith(
24972421 _this.getNativePlayerHtml( videoAttribues, cssStyle )
2498 - );
 2422+ )
24992423 // Bind native events:
25002424 this.applyMediaElementBindings();
25012425 }
2502 - // Android only can play with a special play button ( no native controls in the dom , and no auto-play )
 2426+ // Android only can play with a special play button ( no native controls
 2427+ // in the dom , and no auto-play )
25032428 // and only with 'native display'
25042429 if( mw.isAndroid2() ){
25052430 $j( '#' + _this.pid ).siblings('.play-btn-large').remove();
2506 - $j( '#' + _this.pid ).after(
 2431+ $j( '#' + _this.pid ).after(
25072432 $j('<div />')
25082433 .css({
25092434 'position' : 'relative',
@@ -2515,30 +2440,31 @@
25162441 } )
25172442 .click( function() {
25182443 _this.play();
2519 - // no need to hide the play button since android plays fullscreen
 2444+ // no need to hide the play button since android plays
 2445+ // fullscreen
25202446 } )
2521 - );
 2447+ )
25222448 }
25232449 return ;
25242450 },
25252451 /**
2526 - * Should be set via native embed support
2527 - */
 2452+ * Should be set via native embed support
 2453+ */
25282454 getNativePlayerHtml: function(){
25292455 return $j('<div />' )
25302456 .css( 'width', this.getWidth() )
25312457 .html( 'Error: Trying to get native html5 player without native support for codec' );
25322458 },
25332459 /**
2534 - * Should be set via native embed support
2535 - */
 2460+ * Should be set via native embed support
 2461+ */
25362462 applyMediaElementBindings: function(){
25372463 return ;
25382464 },
2539 -
 2465+
25402466 /**
2541 - * Gets code to embed the player remotely for "share" this player links
2542 - */
 2467+ * Gets code to embed the player remotely for "share" this player links
 2468+ */
25432469 getEmbeddingHTML: function() {
25442470 switch( mw.getConfig( 'EmbedPlayer.ShareEmbedMode' ) ){
25452471 case 'iframe':
@@ -2549,7 +2475,7 @@
25502476 break;
25512477 }
25522478 },
2553 -
 2479+
25542480 /**
25552481 * Get the share embed object code
25562482 *
@@ -2608,50 +2534,50 @@
26092535 // Return the embed code
26102536 return embedCode;
26112537 },
2612 -
 2538+
26132539 /**
2614 - * Get the share embed Video tag code
2615 - */
 2540+ * Get the share embed Video tag code
 2541+ */
26162542 getShareEmbedVideoJs: function(){
2617 -
 2543+
26182544 // Set the embed tag type:
26192545 var embedtag = ( this.isAudio() )? 'audio': 'video';
2620 -
 2546+
26212547 // Set up the mwEmbed js include:
26222548 var embedCode = '&lt;script type=&quot;text/javascript&quot; ' +
2623 - 'src=&quot;' +
2624 - mw.escapeQuotesHTML(
2625 - mw.absoluteUrl(
2626 - mw.getMwEmbedSrc()
 2549+ 'src=&quot;' +
 2550+ mw.escapeQuotesHTML(
 2551+ mw.absoluteUrl(
 2552+ mw.getMwEmbedSrc()
26272553 )
26282554 ) + '&quot;&gt;&lt;/script&gt' +
26292555 '&lt;' + embedtag + ' ';
26302556
26312557 if( this.poster ) {
26322558 embedCode += 'poster=&quot;' +
2633 - mw.escapeQuotesHTML( mw.absoluteUrl( this.poster ) ) +
 2559+ mw.escapeQuotesHTML( mw.absoluteUrl( this.poster ) ) +
26342560 '&quot; ';
26352561 }
2636 -
 2562+
26372563 // Set the skin if set to something other than default
26382564 if( this.skinName ){
26392565 embedCode += 'class=&quot;' +
2640 - mw.escapeQuotesHTML( this.skinName ) +
 2566+ mw.escapeQuotesHTML( this.skinName ) +
26412567 '&quot; ';
26422568 }
2643 -
 2569+
26442570 if( this.duration ) {
26452571 embedCode +='durationHint=&quot;' + parseFloat( this.duration ) + '&quot; ';
26462572 }
2647 -
 2573+
26482574 if( this.width || this.height ){
26492575 embedCode +='style=&quot;';
26502576 embedCode += ( this.width )? 'width:' + this.width +'px;': '';
26512577 embedCode += ( this.height )? 'height:' + this.height +'px;': '';
26522578 embedCode += '&quot; ';
26532579 }
2654 -
2655 -
 2580+
 2581+
26562582 if ( this.roe ) {
26572583 embedCode += 'roe=&quot;' + mw.escapeQuotesHTML( this.roe ) + '&quot; ';
26582584 } else if( this.apiTitleKey ) {
@@ -2661,30 +2587,30 @@
26622588 }
26632589 // close the video tag
26642590 embedCode += '&gt;&lt;/video&gt;';
2665 -
 2591+
26662592 } else {
2667 - //Close the video attr
 2593+ // Close the video attr
26682594 embedCode += '&gt;';
2669 -
 2595+
26702596 // Output all the video sources:
26712597 for( var i=0; i < this.mediaElement.sources.length; i++ ){
26722598 var source = this.mediaElement.sources[i];
26732599 if( source.src ) {
2674 - embedCode +='&lt;source src=&quot;' +
2675 - mw.absoluteUrl( source.src ) +
2676 - '&quot; &lt;&gt;/source&gt;';
 2600+ embedCode +='&lt;source src=&quot;' +
 2601+ mw.absoluteUrl( source.src ) +
 2602+ '&quot; &gt;&lt;/source&gt;';
26772603 }
26782604 }
26792605 // Close the video tag
26802606 embedCode += '&lt;/video&gt;';
26812607 }
2682 -
 2608+
26832609 return embedCode;
26842610 },
2685 -
 2611+
26862612 /**
2687 - * Follows a linkback. Loads the ROE xml if no linkback is found
2688 - */
 2613+ * Follows a linkback. Loads the ROE xml if no linkback is found
 2614+ */
26892615 doLinkBack: function() {
26902616 if ( ! this.linkback && this.roe && this.mediaElement.addedROEData == false ) {
26912617 var _this = this;
@@ -2703,40 +2629,36 @@
27042630 }
27052631 }
27062632 },
2707 -
 2633+
27082634 /**
2709 - * Base Embed Controls
2710 - */
2711 -
 2635+ * Base Embed Controls
 2636+ */
 2637+
27122638 /**
2713 - * The Play Action
2714 - *
2715 - * Handles play requests, updates relevant states:
2716 - * seeking =false
2717 - * paused = false
2718 - * Updates pause button
2719 - * Starts the "monitor"
2720 - */
 2639+ * The Play Action
 2640+ *
 2641+ * Handles play requests, updates relevant states: seeking =false paused =
 2642+ * false Updates pause button Starts the "monitor"
 2643+ */
27212644 play: function() {
27222645 var _this = this;
2723 - // Run play hook (if we we did not bind the native player )
2724 - if( this.paused && this.useNativePlayerControls() ){
 2646+
 2647+ if( this.paused && this.bubbleEventCheck() ){
27252648 this.paused = false;
2726 - mw.log("trigger play event::" + !this.paused);
2727 - $j( this ).trigger( 'play' );
 2649+ mw.log("trigger play event::" + !this.paused);
 2650+ $j( this ).trigger( 'play' );
27282651 }
27292652 this.paused = false;
2730 -
2731 - mw.log( "EmbedPlayer:: play" );
 2653+
 2654+ mw.log( "EmbedPlayer:: play" );
27322655 // Hide any overlay:
27332656 this.controlBuilder.closeMenuOverlay();
2734 -
 2657+
27352658 // Check if thumbnail is being displayed and embed html
27362659 if ( this.thumbnail_disp ) {
27372660 if ( !this.selectedPlayer ) {
2738 - mw.log( 'no selectedPlayer' );
27392661 this.showPluginMissingHTML();
2740 - return;
 2662+ return;
27412663 } else {
27422664 this.thumbnail_disp = false;
27432665 this.doEmbedHTML();
@@ -2745,31 +2667,42 @@
27462668 // the plugin is already being displayed
27472669 this.seeking = false;
27482670 }
2749 -
2750 -
 2671+
 2672+
27512673 this.$interface.find('.play-btn span')
27522674 .removeClass( 'ui-icon-play' )
27532675 .addClass( 'ui-icon-pause' );
2754 -
 2676+
27552677 this.$interface.find( '.play-btn' )
27562678 .unbind()
27572679 .buttonHover()
27582680 .click( function( ) {
27592681 _this.pause();
2760 - } )
2761 - .attr( 'title', gM( 'mwe-embedplayer-pause_clip' ) );
 2682+ } )
 2683+ .attr( 'title', gM( 'mwe-embedplayer-pause_clip' ) );
27622684
27632685 // Start the monitor if not already started
27642686 this.monitor();
2765 -
2766 - // If we previously finished playing this clip run the "replay hook"
2767 - if( this.donePlayingCount > 0 ) {
2768 - mw.log("replayEvent");
2769 - $j( this ).trigger( 'replayEvent' );
 2687+
 2688+ // If we previously finished playing this clip run the "replay hook"
 2689+ if( this.donePlayingCount > 0 ) {
 2690+ mw.log("replayEvent");
 2691+ $j( this ).trigger( 'replayEvent' );
 2692+ }
 2693+ },
 2694+ /**
 2695+ * Returns true if the event should be triggered or false if not
 2696+ *
 2697+ * @@FIXME:: firefox nightlies now Do NOT bubble events. Once release tag
 2698+ * every version after that
 2699+ */
 2700+ bubbleEventCheck: function(){
 2701+ if( $j.browser.webkit ){
 2702+ return true;
27702703 }
 2704+ return false;
27712705 },
2772 -
2773 -
 2706+
27742707 /**
27752708 * Maps the html5 load request. There is no general way to "load" clips so
27762709 * underling plugin-player libs should override.
@@ -2778,29 +2711,29 @@
27792712 // should be done by child (no base way to pre-buffer video)
27802713 mw.log( 'baseEmbed:load call' );
27812714 },
2782 -
 2715+
27832716 /**
2784 - * Base embed pause
2785 - * Updates the play/pause button state.
2786 - *
2787 - * There is no general way to pause the video
2788 - * must be overwritten by embed object to support this functionality.
2789 - */
 2717+ * Base embed pause Updates the play/pause button state.
 2718+ *
 2719+ * There is no general way to pause the video must be overwritten by embed
 2720+ * object to support this functionality.
 2721+ */
27902722 pause: function( event ) {
27912723 var _this = this;
2792 - // Trigger the pause event if not already paused and using native controls:
2793 - if( this.paused === false && this.useNativePlayerControls() ){
 2724+ // Trigger the pause event if not already paused and using native
 2725+ // controls:
 2726+ if( this.paused === false && this.bubbleEventCheck() ){
27942727 this.paused = true;
27952728 mw.log('EmbedPlayer:trigger pause:' + this.paused);
27962729 $j( this ).trigger('pause' );
27972730 }
27982731 this.paused = true;
2799 -
 2732+
28002733 // update the ctrl "paused state"
28012734 this.$interface.find('.play-btn span' )
28022735 .removeClass( 'ui-icon-pause' )
28032736 .addClass( 'ui-icon-play' );
2804 -
 2737+
28052738 this.$interface.find('.play-btn' )
28062739 .unbind()
28072740 .buttonHover()
@@ -2809,26 +2742,23 @@
28102743 } )
28112744 .attr( 'title', gM( 'mwe-embedplayer-play_clip' ) );
28122745 },
2813 -
 2746+
28142747 /**
2815 - * Base embed stop
2816 - *
2817 - * Updates the player to the stop state
2818 - * shows Thumbnail
2819 - * resets Buffer
2820 - * resets Playhead slider
2821 - * resets Status
2822 - */
 2748+ * Base embed stop
 2749+ *
 2750+ * Updates the player to the stop state shows Thumbnail resets Buffer resets
 2751+ * Playhead slider resets Status
 2752+ */
28232753 stop: function() {
28242754 var _this = this;
28252755 mw.log( 'EmbedPlayer::stop:' + this.id );
2826 -
 2756+
28272757 // no longer seeking:
28282758 this.didSeekJump = false;
2829 -
 2759+
28302760 // Reset current time and prev time and seek offset
2831 - this.currentTime = this.previousTime = this.serverSeekTime = 0;
2832 -
 2761+ this.currentTime = this.previousTime = this.serverSeekTime = 0;
 2762+
28332763 // Issue pause to update interface (only call this parent)
28342764 if( !this.paused ){
28352765 this.paused = true;
@@ -2839,30 +2769,30 @@
28402770 this.pause();
28412771 }
28422772 }
2843 -
 2773+
28442774 // Rewrite the html to thumbnail disp
28452775 this.showThumbnail();
28462776 this.bufferedPercent = 0; // reset buffer state
28472777 this.controlBuilder.setStatus( this.getTimeRange() );
2848 -
 2778+
28492779 // Reset the playhead
2850 - mw.log("EmbedPlayer::Stop:: Reset play head");
 2780+ mw.log("EmbedPlayer::Stop:: Reset play head")
28512781 this.updatePlayHead( 0 );
2852 -
2853 - //Bind play-btn-large play
 2782+
 2783+ // Bind play-btn-large play
28542784 this.$interface.find( '.play-btn-large' )
28552785 .unbind( 'click' )
28562786 .click( function() {
28572787 _this.play();
28582788 } );
28592789 },
2860 -
 2790+
28612791 /**
2862 - * Base Embed mute
2863 - *
2864 - * Handles interface updates for toggling mute.
2865 - * Plug-in / player interface must handle the actual media player update
2866 - */
 2792+ * Base Embed mute
 2793+ *
 2794+ * Handles interface updates for toggling mute. Plug-in / player interface
 2795+ * must handle the actual media player update
 2796+ */
28672797 toggleMute: function() {
28682798 mw.log( 'f:toggleMute:: (old state:) ' + this.muted );
28692799 if ( this.muted ) {
@@ -2877,11 +2807,13 @@
28782808 // Update the interface
28792809 this.setInterfaceVolume( percent );
28802810 },
2881 -
 2811+
28822812 /**
2883 - * Update volume function ( called from interface updates )
2884 - * @param {float} percent Percent of full volume
2885 - */
 2813+ * Update volume function ( called from interface updates )
 2814+ *
 2815+ * @param {float}
 2816+ * percent Percent of full volume
 2817+ */
28862818 setVolume: function( percent ) {
28872819 // ignore NaN percent:
28882820 if( isNaN( percent ) ){
@@ -2889,78 +2821,81 @@
28902822 }
28912823 // Set the local volume attribute
28922824 this.previousVolume = this.volume = percent;
2893 -
 2825+
28942826 // Un-mute if setting positive volume
28952827 if( percent != 0 ){
28962828 this.muted = false;
28972829 }
2898 -
 2830+
28992831 // Update the playerElement volume
29002832 this.setPlayerElementVolume( percent );
2901 -
2902 - //mw.log(" setVolume:: " + percent + ' this.volume is: ' + this.volume);
 2833+
 2834+ // mw.log(" setVolume:: " + percent + ' this.volume is: ' +
 2835+ // this.volume);
29032836 $j( this ).trigger('volumeChanged', percent );
29042837 },
2905 -
 2838+
29062839 /**
2907 - * Updates the interface volume
2908 - * TODO should move to controlBuilder
2909 - * @param {float} percent Percentage volume to update interface
2910 - */
 2840+ * Updates the interface volume TODO should move to controlBuilder
 2841+ *
 2842+ * @param {float}
 2843+ * percent Percentage volume to update interface
 2844+ */
29112845 setInterfaceVolume: function( percent ) {
2912 - if( this.supports[ 'volumeControl' ] &&
2913 - this.$interface.find( '.volume-slider' ).length
 2846+ if( this.supports[ 'volumeControl' ] &&
 2847+ this.$interface.find( '.volume-slider' ).length
29142848 ) {
29152849 this.$interface.find( '.volume-slider' ).slider( 'value', percent * 100 );
29162850 }
29172851 },
2918 -
 2852+
29192853 /**
2920 - * Abstract Update volume Method must be override by plug-in / player interface
2921 - */
 2854+ * Abstract Update volume Method must be override by plug-in / player
 2855+ * interface
 2856+ */
29222857 setPlayerElementVolume: function( percent ) {
29232858 mw.log('Error player does not support volume adjustment' );
29242859 },
2925 -
 2860+
29262861 /**
2927 - * Abstract get volume Method must be override by plug-in / player interface
2928 - * (if player does not override we return the abstract player value )
2929 - */
 2862+ * Abstract get volume Method must be override by plug-in / player interface
 2863+ * (if player does not override we return the abstract player value )
 2864+ */
29302865 getPlayerElementVolume: function(){
2931 - //mw.log(' error player does not support getting volume property' );
 2866+ // mw.log(' error player does not support getting volume property' );
29322867 return this.volume;
29332868 },
2934 -
 2869+
29352870 /**
2936 - * Abstract get volume muted property must be overwritten by plug-in / player interface
2937 - * (if player does not override we return the abstract player value )
2938 - */
 2871+ * Abstract get volume muted property must be overwritten by plug-in /
 2872+ * player interface (if player does not override we return the abstract
 2873+ * player value )
 2874+ */
29392875 getPlayerElementMuted: function(){
2940 - //mw.log(' error player does not support getting mute property' );
 2876+ // mw.log(' error player does not support getting mute property' );
29412877 return this.muted;
29422878 },
2943 -
 2879+
29442880 /**
2945 - * Passes a fullscreen request to the controlBuilder interface
2946 - */
 2881+ * Passes a fullscreen request to the controlBuilder interface
 2882+ */
29472883 fullscreen: function() {
29482884 this.controlBuilder.toggleFullscreen();
29492885 },
2950 -
 2886+
29512887 /**
2952 - * Abstract method to be run post embedding the player
2953 - * Generally should be overwritten by the plug-in / player
2954 - */
 2888+ * Abstract method to be run post embedding the player Generally should be
 2889+ * overwritten by the plug-in / player
 2890+ */
29552891 postEmbedJS:function() {
29562892 return ;
29572893 },
2958 -
 2894+
29592895 /**
2960 - * Checks the player state based on thumbnail display & paused state
2961 - * @return {Boolean}
2962 - * true if playing
2963 - * false if not playing
2964 - */
 2896+ * Checks the player state based on thumbnail display & paused state
 2897+ *
 2898+ * @return {Boolean} true if playing false if not playing
 2899+ */
29652900 isPlaying : function() {
29662901 if ( this.thumbnail_disp ) {
29672902 // in stopped state
@@ -2972,35 +2907,33 @@
29732908 return true;
29742909 }
29752910 },
2976 -
 2911+
29772912 /**
2978 - * Get paused state
2979 - * @return {Boolean}
2980 - * true if playing
2981 - * false if not playing
2982 - */
 2913+ * Get paused state
 2914+ *
 2915+ * @return {Boolean} true if playing false if not playing
 2916+ */
29832917 isPaused: function() {
29842918 return this.paused;
29852919 },
2986 -
 2920+
29872921 /**
2988 - * Get Stopped state
2989 - * @return {Boolean}
2990 - * true if stopped
2991 - * false if playing
2992 - */
 2922+ * Get Stopped state
 2923+ *
 2924+ * @return {Boolean} true if stopped false if playing
 2925+ */
29932926 isStopped: function() {
29942927 return this.thumbnail_disp;
29952928 },
2996 -
 2929+
29972930 // xxx temporary hack we need a better stop monitor system
29982931 stopMonitor: function(){
29992932 this.thumbnail_disp = true;
30002933 },
3001 -
 2934+
30022935 /**
3003 - * Checks if the currentTime was updated outside of
3004 - * the getPlayerElementTime function
 2936+ * Checks if the currentTime was updated outside of the getPlayerElementTime
 2937+ * function
30052938 */
30062939 checkForCurrentTimeSeek: function(){
30072940 var _this = this;
@@ -3015,51 +2948,54 @@
30162949 }
30172950 }
30182951 },
3019 -
 2952+
30202953 /**
3021 - * Monitor playback and update interface components.
3022 - * underling plugin objects are responsible for updating currentTime
3023 - */
 2954+ * Monitor playback and update interface components. underling plugin
 2955+ * objects are responsible for updating currentTime
 2956+ */
30242957 monitor: function() {
30252958 var _this = this;
3026 -
 2959+
30272960 // Check for current time update outside of embed player
30282961 this.checkForCurrentTimeSeek();
3029 -
 2962+
30302963 // Update currentTime via embedPlayer
30312964 _this.currentTime = _this.getPlayerElementTime();
3032 -
 2965+
30332966 // Update any offsets from server seek
30342967 if( _this.serverSeekTime && _this.supportsURLTimeEncoding ){
3035 - _this.currentTime = _this.serverSeekTime + _this.getPlayerElementTime();
 2968+ _this.currentTime = _this.serverSeekTime + _this.getPlayerElementTime()
30362969 }
30372970
3038 - // Update the previousTime ( so we can know if the user-javascript changed currentTime )
 2971+ // Update the previousTime ( so we can know if the user-javascript
 2972+ // changed currentTime )
30392973 _this.previousTime = _this.currentTime;
3040 -
3041 -
 2974+
 2975+
30422976 // Check if volume was set outside of embed player function
3043 - //mw.log( ' this.volume: ' + _this.volume + ' prev Volume:: ' + _this.previousVolume );
 2977+ // mw.log( ' this.volume: ' + _this.volume + ' prev Volume:: ' +
 2978+ // _this.previousVolume );
30442979 if( Math.round( _this.volume * 100 ) != Math.round( _this.previousVolume * 100 ) ) {
30452980 _this.setInterfaceVolume( _this.volume );
30462981 $j( this ).trigger('volumeChanged', _this.volume );
30472982 }
3048 -
 2983+
30492984 // Update the previous volume
30502985 _this.previousVolume = _this.volume;
3051 -
 2986+
30522987 // Update the volume from the player element
30532988 _this.volume = this.getPlayerElementVolume();
3054 -
 2989+
30552990 // update the mute state from the player element
30562991 if( _this.muted != _this.getPlayerElementMuted() && ! _this.isStopped() ){
30572992 mw.log( "EmbedPlayer::monitor: muted does not mach embed player" );
30582993 _this.toggleMute();
30592994 // Make sure they match:
3060 - _this.muted = _this.getPlayerElementMuted();
 2995+ _this.muted = _this.getPlayerElementMuted();
30612996 }
3062 -
3063 - //mw.log( 'Monitor:: ' + this.currentTime + ' duration: ' + ( parseInt( this.getDuration() ) + 1 ) + ' is seeking: ' + this.seeking );
 2997+
 2998+ // mw.log( 'Monitor:: ' + this.currentTime + ' duration: ' + ( parseInt(
 2999+ // this.getDuration() ) + 1 ) + ' is seeking: ' + this.seeking );
30643000 if ( this.currentTime >= 0 && this.duration ) {
30653001 if ( !this.userSlide && !this.seeking ) {
30663002 if ( parseInt( this.startOffset ) != 0 ) {
@@ -3095,55 +3031,57 @@
30963032 this.controlBuilder.setStatus( this.getTimeRange() );
30973033 }
30983034 }
3099 -
 3035+
31003036 // Update buffer information
31013037 this.updateBufferStatus();
3102 -
 3038+
31033039 // run the "native" progress event on the virtual html5 object if set
31043040 if( this.progressEventData ) {
3105 - //mw.log("trigger:progress event on html5 proxy");
 3041+ // mw.log("trigger:progress event on html5 proxy");
31063042 $j( this ).trigger( 'progress', this.progressEventData );
31073043 }
3108 -
3109 - // Call monitor at 250ms interval. ( use setInterval to avoid stacking monitor requests )
 3044+
 3045+ // Call monitor at 250ms interval. ( use setInterval to avoid stacking
 3046+ // monitor requests )
31103047 if( ! this.isStopped() ) {
31113048 if( !this.monitorInterval ){
31123049 this.monitorInterval = setInterval( function(){
31133050 if( _this.monitor )
31143051 _this.monitor();
3115 - }, this.monitorRate );
 3052+ }, this.monitorRate )
31163053 }
31173054 } else {
31183055 // If stopped "stop" monitor:
31193056 clearInterval( this.monitorInterval );
31203057 this.monitorInterval = 0;
31213058 }
3122 -
3123 - //mw.log('trigger:monitor:: ' + this.currentTime );
 3059+
 3060+ // mw.log('trigger:monitor:: ' + this.currentTime );
31243061 $j( this ).trigger( 'monitorEvent' );
31253062 },
3126 -
 3063+
31273064 /**
31283065 * Abstract getPlayerElementTime function
31293066 */
31303067 getPlayerElementTime: function(){
31313068 mw.log("Error: getPlayerElementTime should be implemented by embed library");
31323069 },
3133 -
 3070+
31343071 /**
3135 - * Update the Buffer status based on the local bufferedPercent var
3136 - */
 3072+ * Update the Buffer status based on the local bufferedPercent var
 3073+ */
31373074 updateBufferStatus: function() {
3138 -
 3075+
31393076 // Get the buffer target based for playlist vs clip
31403077 $buffer = this.$interface.find( '.mw_buffer' );
31413078 // Update the buffer progress bar (if available )
31423079 if ( this.bufferedPercent != 0 ) {
3143 - //mw.log('Update buffer css: ' + ( this.bufferedPercent * 100 ) + '% ' + $buffer.length );
 3080+ // mw.log('Update buffer css: ' + ( this.bufferedPercent * 100 ) +
 3081+ // '% ' + $buffer.length );
31443082 if ( this.bufferedPercent > 1 ){
31453083 this.bufferedPercent = 1;
31463084 }
3147 -
 3085+
31483086 $buffer.css({
31493087 "width" : ( this.bufferedPercent * 100 ) + '%'
31503088 });
@@ -3151,26 +3089,27 @@
31523090 } else {
31533091 $buffer.css( "width", '0px' );
31543092 }
3155 -
 3093+
31563094 // if we have not already run the buffer start hook
31573095 if( this.bufferedPercent > 0 && !this.bufferStartFlag ) {
31583096 this.bufferStartFlag = true;
31593097 mw.log("bufferStart");
31603098 $j( this ).trigger( 'bufferStartEvent' );
31613099 }
3162 -
 3100+
31633101 // if we have not already run the buffer end hook
31643102 if( this.bufferedPercent == 1 && !this.bufferEndFlag){
31653103 this.bufferEndFlag = true;
31663104 $j( this ).trigger( 'bufferEndEvent' );
31673105 }
31683106 },
3169 -
 3107+
31703108 /**
3171 - * Update the player playhead
3172 - *
3173 - * @param {Float} perc Value between 0 and 1 for position of playhead
3174 - */
 3109+ * Update the player playhead
 3110+ *
 3111+ * @param {Float}
 3112+ * perc Value between 0 and 1 for position of playhead
 3113+ */
31753114 updatePlayHead: function( perc ) {
31763115 $playHead = this.$interface.find( '.play_head' );
31773116 if ( this.controls && $playHead.length != 0 ) {
@@ -3180,12 +3119,13 @@
31813120 // @@todo should have 'progress' trigger the same as html5
31823121 $j( this ).trigger('updatePlayHeadPercent', perc);
31833122 },
3184 -
 3123+
31853124 /**
3186 - * Highlight a section of video on the playhead
3187 - *
3188 - * @param {Object} options Provides "start" time & "end" time to highlight
3189 - */
 3125+ * Highlight a section of video on the playhead
 3126+ *
 3127+ * @param {Object}
 3128+ * options Provides "start" time & "end" time to highlight
 3129+ */
31903130 highlightPlaySection:function( options ) {
31913131 mw.log( 'highlightPlaySection' );
31923132 var eid = ( this.pc ) ? this.pc.pp.id:this.id;
@@ -3194,8 +3134,8 @@
31953135 rel_start_sec = mw.npt2seconds( options['start'] );
31963136 // remove the startOffset if relevent:
31973137 if ( this.startOffset )
3198 - rel_start_sec = rel_start_sec - this.startOffset;
3199 -
 3138+ rel_start_sec = rel_start_sec - this.startOffset
 3139+
32003140 var slider_perc = 0;
32013141 if ( rel_start_sec <= 0 ) {
32023142 left_perc = 0;
@@ -3206,22 +3146,23 @@
32073147 left_perc = parseInt( ( rel_start_sec / dur ) * 100 ) ;
32083148 slider_perc = ( left_perc / 100 );
32093149 }
3210 -
 3150+
32113151 mw.log( "slider perc:" + slider_perc );
32123152 if ( ! this.isPlaying() ) {
32133153 this.updatePlayHead( slider_perc );
32143154 }
3215 -
 3155+
32163156 width_perc = parseInt( ( ( mw.npt2seconds( options['end'] ) - mw.npt2seconds( options['start'] ) ) / dur ) * 100 ) ;
32173157 if ( ( width_perc + left_perc ) > 100 ) {
32183158 width_perc = 100 - left_perc;
32193159 }
3220 - // mw.log('should hl: '+rel_start_sec+ '/' + dur + ' re:' + rel_end_sec+' lp:' + left_perc + ' width: ' + width_perc);
 3160+ // mw.log('should hl: '+rel_start_sec+ '/' + dur + ' re:' +
 3161+ // rel_end_sec+' lp:' + left_perc + ' width: ' + width_perc);
32213162 $j( '#mv_seeker_' + eid + ' .mv_highlight' ).css( {
32223163 'left' : left_perc + '%',
32233164 'width' : width_perc + '%'
32243165 } ).show();
3225 -
 3166+
32263167 this.jump_time = options['start'];
32273168 this.serverSeekTime = mw.npt2seconds( options['start'] );
32283169 // trim output to
@@ -3229,56 +3170,58 @@
32303171 mw.log( 'DO update: ' + this.jump_time );
32313172 this.updateThumbTime( rel_start_sec );
32323173 },
3233 -
 3174+
32343175 /**
3235 - * Hides the playhead highlight
3236 - */
 3176+ * Hides the playhead highlight
 3177+ */
32373178 hideHighlight: function() {
32383179 var eid = ( this.pc ) ? this.pc.pp.id:this.id;
32393180 $j( '#mv_seeker_' + eid + ' .mv_highlight' ).hide();
32403181 this.controlBuilder.setStatus( this.getTimeRange() );
32413182 },
3242 -
3243 -
 3183+
 3184+
32443185 /**
3245 - * Helper Functions for selected source
3246 - */
3247 -
 3186+ * Helper Functions for selected source
 3187+ */
 3188+
32483189 /**
3249 - * Get the current selected media source
3250 - *
3251 - * @return src url
3252 - */
 3190+ * Get the current selected media source
 3191+ *
 3192+ * @return src url
 3193+ */
32533194 getSrc: function() {
32543195 if( this.mediaElement.selectedSource ){
32553196 return this.mediaElement.selectedSource.getSrc( this.serverSeekTime );
32563197 }
32573198 return false;
32583199 },
3259 -
 3200+
32603201 /**
3261 - * If the selected src supports URL time encoding
3262 - *
3263 - * @return {Boolean}
3264 - * ture if the src supports url time requests
3265 - * false if the src does not support url time requests
3266 - */
 3202+ * If the selected src supports URL time encoding
 3203+ *
 3204+ * @return {Boolean} ture if the src supports url time requests false if the
 3205+ * src does not support url time requests
 3206+ */
32673207 supportsURLTimeEncoding: function() {
32683208 // do head request if on the same domain
32693209 return this.mediaElement.selectedSource.URLTimeEncoding;
32703210 }
3271 -};
 3211+}
32723212
32733213
32743214
32753215 /**
3276 - * mediaPlayer represents a media player plugin.
3277 - *
3278 - * @param {String} id id used for the plugin.
3279 - * @param {Array} supported_types an array of supported MIME types.
3280 - * @param {String} library external script containing the plugin interface code.
3281 - * @constructor
3282 - */
 3216+ * mediaPlayer represents a media player plugin.
 3217+ *
 3218+ * @param {String}
 3219+ * id id used for the plugin.
 3220+ * @param {Array}
 3221+ * supported_types an array of supported MIME types.
 3222+ * @param {String}
 3223+ * library external script containing the plugin interface code.
 3224+ * @constructor
 3225+ */
32833226 function mediaPlayer( id, supported_types, library )
32843227 {
32853228 this.id = id;
@@ -3291,24 +3234,24 @@
32923235 mediaPlayer.prototype = {
32933236 // Id of the mediaPlayer
32943237 id:null,
3295 -
 3238+
32963239 // Mime types supported by this player
32973240 supported_types:null,
3298 -
 3241+
32993242 // Player library ie: native, vlc, java etc.
33003243 library:null,
3301 -
 3244+
33023245 // Flag stores the mediaPlayer load state
33033246 loaded:false,
3304 -
 3247+
33053248 /**
3306 - * Checks support for a given MIME type
3307 - *
3308 - * @param {String} type Mime type to check against supported_types
3309 - * @return {Boolean}
3310 - * true if mime type is supported
3311 - * false if mime type is unsupported
3312 - */
 3249+ * Checks support for a given MIME type
 3250+ *
 3251+ * @param {String}
 3252+ * type Mime type to check against supported_types
 3253+ * @return {Boolean} true if mime type is supported false if mime type is
 3254+ * unsupported
 3255+ */
33133256 supportsMIMEType: function( type ) {
33143257 for ( var i = 0; i < this.supported_types.length; i++ ) {
33153258 if ( this.supported_types[i] == type )
@@ -3316,39 +3259,41 @@
33173260 }
33183261 return false;
33193262 },
3320 -
 3263+
33213264 /**
3322 - * Get the "name" of the player from a predictable msg key
3323 - */
 3265+ * Get the "name" of the player from a predictable msg key
 3266+ */
33243267 getName: function() {
33253268 return gM( 'mwe-embedplayer-ogg-player-' + this.id );
33263269 },
3327 -
 3270+
33283271 /**
3329 - * Loads the player library & player skin config ( if needed ) and then calls the callback.
3330 - *
3331 - * @param {Function} callback Function to be called once player library is loaded.
3332 - */
 3272+ * Loads the player library & player skin config ( if needed ) and then
 3273+ * calls the callback.
 3274+ *
 3275+ * @param {Function}
 3276+ * callback Function to be called once player library is loaded.
 3277+ */
33333278 load: function( callback ) {
3334 - //Load player library ( upper case the first letter of the library )
 3279+ // Load player library ( upper case the first letter of the library )
33353280 mw.load( [
33363281 'mw.EmbedPlayer' + this.library.substr(0,1).toUpperCase() + this.library.substr(1)
33373282 ], function() {
33383283 callback();
33393284 } );
33403285 }
3341 -};
 3286+}
33423287
33433288 /**
3344 -* players and supported mime types
3345 -* In an ideal world we would query the plugin to get what mime
3346 -* types it supports in practice not always reliable/available
3347 -*
3348 -* We can't cleanly store these values per library since player library is loaded post player detection
3349 -*
3350 -*/
 3289+ * players and supported mime types In an ideal world we would query the plugin
 3290+ * to get what mime types it supports in practice not always reliable/available
 3291+ *
 3292+ * We can't cleanly store these values per library since player library is
 3293+ * loaded post player detection
 3294+ *
 3295+ */
33513296
3352 -//Flash based players:
 3297+// Flash based players:
33533298
33543299 var kplayer = new mediaPlayer('kplayer', ['video/x-flv', 'video/h264'], 'Kplayer');
33553300
@@ -3373,6 +3318,7 @@
33743319
33753320 /**
33763321 * mediaPlayers is a collection of mediaPlayer objects supported by the client.
 3322+ *
33773323 * @constructor
33783324 */
33793325 function mediaPlayers()
@@ -3384,44 +3330,46 @@
33853331 {
33863332 // The list of players supported
33873333 players : null,
3388 -
 3334+
33893335 // Store per mime-type prefrences for players
33903336 preference : { },
3391 -
 3337+
33923338 // Stores the default set of players for a given mime type
33933339 defaultPlayers : { },
3394 -
 3340+
33953341 /**
3396 - * Initializartion function sets the default order for players for
3397 - * a given mime type
3398 - */
 3342+ * Initializartion function sets the default order for players for a given
 3343+ * mime type
 3344+ */
33993345 init: function() {
34003346 this.players = new Array();
34013347 this.loadPreferences();
3402 -
 3348+
34033349 // set up default players order for each library type
34043350 this.defaultPlayers['video/x-flv'] = ['Kplayer', 'Vlc'];
34053351 this.defaultPlayers['video/h264'] = ['Native', 'Kplayer', 'Vlc'];
3406 -
 3352+
34073353 this.defaultPlayers['video/ogg'] = ['Native', 'Vlc', 'Java', 'Generic'];
 3354+ this.defaultPlayers['video/webm'] = ['Native', 'Vlc'];
34083355 this.defaultPlayers['application/ogg'] = ['Native', 'Vlc', 'Java', 'Generic'];
34093356 this.defaultPlayers['audio/ogg'] = ['Native', 'Vlc', 'Java' ];
34103357 this.defaultPlayers['video/mp4'] = ['Vlc'];
34113358 this.defaultPlayers['video/mpeg'] = ['Vlc'];
34123359 this.defaultPlayers['video/x-msvideo'] = ['Vlc'];
3413 -
 3360+
34143361 this.defaultPlayers['text/html'] = ['Html'];
34153362 this.defaultPlayers['image/jpeg'] = ['Html'];
34163363 this.defaultPlayers['image/png'] = ['Html'];
34173364 this.defaultPlayers['image/svg'] = ['Html'];
3418 -
 3365+
34193366 },
3420 -
 3367+
34213368 /**
3422 - * Adds a Player to the player list
3423 - *
3424 - * @param {Object} player Player object to be added
3425 - */
 3369+ * Adds a Player to the player list
 3370+ *
 3371+ * @param {Object}
 3372+ * player Player object to be added
 3373+ */
34263374 addPlayer: function( player ) {
34273375 for ( var i = 0; i < this.players.length; i++ ) {
34283376 if ( this.players[i].id == player.id ) {
@@ -3429,12 +3377,12 @@
34303378 return ;
34313379 }
34323380 }
3433 -
3434 -
 3381+
 3382+
34353383 // Add the player:
34363384 this.players.push( player );
34373385 },
3438 -
 3386+
34393387 /**
34403388 * Checks if a player is supported by id
34413389 */
@@ -3446,14 +3394,14 @@
34473395 }
34483396 return false;
34493397 },
3450 -
 3398+
34513399 /**
3452 - * get players that support a given mimeType
3453 - *
3454 - * @param {String} mimeType Mime type of player set
3455 - * @return {Array}
3456 - * Array of players that support a the requested mime type
3457 - */
 3400+ * get players that support a given mimeType
 3401+ *
 3402+ * @param {String}
 3403+ * mimeType Mime type of player set
 3404+ * @return {Array} Array of players that support a the requested mime type
 3405+ */
34583406 getMIMETypePlayers: function( mimeType ) {
34593407 var mimePlayers = new Array();
34603408 var _this = this;
@@ -3469,17 +3417,16 @@
34703418 }
34713419 return mimePlayers;
34723420 },
3473 -
 3421+
34743422 /**
3475 - * Default player for a given mime type
3476 - *
3477 - * @param {String} mimeType Mime type of the requested player
3478 - * @return
3479 - * Player for mime type
3480 - * null if no player found
3481 - */
 3423+ * Default player for a given mime type
 3424+ *
 3425+ * @param {String}
 3426+ * mimeType Mime type of the requested player
 3427+ * @return Player for mime type null if no player found
 3428+ */
34823429 defaultPlayer : function( mimeType ) {
3483 - //mw.log( "get defaultPlayer for " + mimeType );
 3430+ // mw.log( "get defaultPlayer for " + mimeType );
34843431 var mimePlayers = this.getMIMETypePlayers( mimeType );
34853432 if ( mimePlayers.length > 0 )
34863433 {
@@ -3492,26 +3439,29 @@
34933440 // (it will be chosen according to the defaultPlayers list
34943441 return mimePlayers[0];
34953442 }
3496 - //mw.log( 'No default player found for ' + mimeType );
 3443+ // mw.log( 'No default player found for ' + mimeType );
34973444 return null;
34983445 },
3499 -
 3446+
35003447 /**
3501 - * Sets the format preference.
3502 - *
3503 - * @param {String} mimeFormat Prefered format
3504 - */
 3448+ * Sets the format preference.
 3449+ *
 3450+ * @param {String}
 3451+ * mimeFormat Prefered format
 3452+ */
35053453 setFormatPreference : function ( mimeFormat ) {
35063454 this.preference['format_preference'] = mimeFormat;
3507 - mw.setUserConfig( 'playerPref', this.preference);
 3455+ mw.setUserConfig( 'playerPref', this.preference);
35083456 },
3509 -
 3457+
35103458 /**
3511 - * Sets the player preference
3512 - *
3513 - * @param {String} playerId Prefered player id
3514 - * @param {String} mimeType Mime type for the associated player stream
3515 - */
 3459+ * Sets the player preference
 3460+ *
 3461+ * @param {String}
 3462+ * playerId Prefered player id
 3463+ * @param {String}
 3464+ * mimeType Mime type for the associated player stream
 3465+ */
35163466 setPlayerPreference : function( playerId, mimeType ) {
35173467 var selectedPlayer = null;
35183468 for ( var i = 0; i < this.players.length; i++ ) {
@@ -3525,7 +3475,7 @@
35263476 }
35273477 // Update All the player instances:
35283478 if ( selectedPlayer ) {
3529 - var playerList = mw.playerManager.getPlayerList();
 3479+ var playerList = mw.playerManager.getPlayerList();
35303480 for ( var i = 0; i < playerList.length; i++ ) {
35313481 var embed = $j( '#' + playerList[i] ).get( 0 );
35323482 if ( embed.mediaElement.selectedSource && ( embed.mediaElement.selectedSource.mimeType == mimeType ) )
@@ -3536,11 +3486,11 @@
35373487 }
35383488 }
35393489 },
3540 -
 3490+
35413491 /**
3542 - * Loads the user preference settings from a cookie
3543 - */
3544 - loadPreferences : function ( ) {
 3492+ * Loads the user preference settings from a cookie
 3493+ */
 3494+ loadPreferences : function ( ) {
35453495 this.preference = { };
35463496 // see if we have a cookie set to a clientSupported type:
35473497 preferenceConfig = mw.getUserConfig( 'playerPref' );
@@ -3559,78 +3509,84 @@
35603510
35613511 // List of players supported
35623512 players: null,
3563 -
 3513+
35643514 // Detect flag for completion
35653515 detect_done:false,
3566 -
 3516+
35673517 /**
3568 - * Runs the detect method and update the detect_done flag
3569 - * @constructor
3570 - */
 3518+ * Runs the detect method and update the detect_done flag
 3519+ *
 3520+ * @constructor
 3521+ */
35713522 init: function() {
35723523 // detect supported types
35733524 this.detect();
35743525 this.detect_done = true;
35753526 },
3576 -
 3527+
35773528 /**
3578 - * If the browsers supports a given mimetype
3579 - *
3580 - * @param {String} mimeType Mime type for browser plug-in check
3581 - */
 3529+ * If the browsers supports a given mimetype
 3530+ *
 3531+ * @param {String}
 3532+ * mimeType Mime type for browser plug-in check
 3533+ */
35823534 supportedMimeType: function( mimeType ) {
35833535 for ( var i =0; i < navigator.plugins.length; i++ ) {
35843536 var plugin = navigator.plugins[i];
35853537 if ( typeof plugin[ mimeType ] != "undefined" )
3586 - return true;
 3538+ return true;
35873539 }
35883540 return false;
35893541 },
3590 -
 3542+
35913543 /**
3592 - * Detects what plug-ins the client supports
3593 - */
 3544+ * Detects what plug-ins the client supports
 3545+ */
35943546 detect: function() {
35953547 mw.log( "embedPlayer: running detect" );
35963548 this.players = new mediaPlayers();
35973549 // every browser supports html rendering:
35983550 this.players.addPlayer( htmlPlayer );
3599 - // In Mozilla, navigator.javaEnabled() only tells us about preferences, we need to
 3551+ // In Mozilla, navigator.javaEnabled() only tells us about preferences,
 3552+ // we need to
36003553 // search navigator.mimeTypes to see if it's installed
36013554 try{
36023555 var javaEnabled = navigator.javaEnabled();
36033556 } catch ( e ){
3604 -
 3557+
36053558 }
36063559 // Some browsers filter out duplicate mime types, hiding some plugins
36073560 var uniqueMimesOnly = $j.browser.opera || $j.browser.safari;
3608 -
3609 - // Opera will switch off javaEnabled in preferences if java can't be found.
3610 - // And it doesn't register an application/x-java-applet mime type like Mozilla does.
 3561+
 3562+ // Opera will switch off javaEnabled in preferences if java can't be
 3563+ // found.
 3564+ // And it doesn't register an application/x-java-applet mime type like
 3565+ // Mozilla does.
36113566 if ( javaEnabled && ( navigator.appName == 'Opera' ) ) {
36123567 this.players.addPlayer( cortadoPlayer );
36133568 }
3614 -
 3569+
36153570 // ActiveX plugins
36163571 if ( $j.browser.msie ) {
36173572 // check for flash
36183573 if ( this.testActiveX( 'ShockwaveFlash.ShockwaveFlash' ) ) {
36193574 this.players.addPlayer( kplayer );
3620 - //this.players.addPlayer( flowPlayer );
 3575+ // this.players.addPlayer( flowPlayer );
36213576 }
36223577 // VLC
36233578 if ( this.testActiveX( 'VideoLAN.VLCPlugin.2' ) ) {
36243579 this.players.addPlayer( vlcPlayer );
36253580 }
3626 -
 3581+
36273582 // Java ActiveX
36283583 if ( this.testActiveX( 'JavaWebStart.isInstalled' ) ) {
36293584 this.players.addPlayer( cortadoPlayer );
36303585 }
3631 -
 3586+
36323587 // quicktime (currently off)
3633 - // if ( this.testActiveX( 'QuickTimeCheckObject.QuickTimeCheck.1' ) )
3634 - // this.players.addPlayer(quicktimeActiveXPlayer);
 3588+ // if ( this.testActiveX(
 3589+ // 'QuickTimeCheckObject.QuickTimeCheck.1' ) )
 3590+ // this.players.addPlayer(quicktimeActiveXPlayer);
36353591 }
36363592 // <video> element
36373593 if ( typeof HTMLVideoElement == 'object' // Firefox, Safari
@@ -3642,23 +3598,24 @@
36433599 if( dummyvid.canPlayType ) {
36443600 // Add the webm player
36453601 if( dummyvid.canPlayType('video/webm; codecs="vp8, vorbis"') ){
3646 - this.players.addPlayer( webmNativePlayer );
 3602+ this.players.addPlayer( webmNativePlayer );
36473603 }
3648 -
 3604+
36493605 // Test for h264:
36503606 if ( dummyvid.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"' ) ) {
36513607 this.players.addPlayer( h264NativePlayer );
36523608 }
3653 - // For now if Android assume we support h264Native (FIXME test on real devices )
 3609+ // For now if Android assume we support h264Native (FIXME
 3610+ // test on real devices )
36543611 if ( mw.isAndroid2() ){
36553612 this.players.addPlayer( h264NativePlayer );
36563613 }
3657 -
3658 - // Test for ogg
 3614+
 3615+ // Test for ogg
36593616 if ( dummyvid.canPlayType( 'video/ogg; codecs="theora,vorbis"' ) ) {
36603617 this.players.addPlayer( oggNativePlayer );
36613618 // older versions of safari do not support canPlayType,
3662 - // but xiph qt registers mimetype via quicktime plugin
 3619+ // but xiph qt registers mimetype via quicktime plugin
36633620 } else if ( this.supportedMimeType( 'video/ogg' ) ) {
36643621 this.players.addPlayer( oggNativePlayer );
36653622 }
@@ -3666,8 +3623,8 @@
36673624 } catch ( e ) {
36683625 mw.log( 'could not run canPlayType ' + e );
36693626 }
3670 - }
3671 -
 3627+ }
 3628+
36723629 // "navigator" plugins
36733630 if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) {
36743631 for ( var i = 0; i < navigator.mimeTypes.length; i++ ) {
@@ -3676,7 +3633,7 @@
36773634 if ( semicolonPos > -1 ) {
36783635 type = type.substr( 0, semicolonPos );
36793636 }
3680 - // mw.log('on type: '+type);
 3637+ // mw.log( 'on type: ' + type );
36813638 var pluginName = navigator.mimeTypes[i].enabledPlugin ? navigator.mimeTypes[i].enabledPlugin.name : '';
36823639 if ( !pluginName ) {
36833640 // In case it is null or undefined
@@ -3686,22 +3643,22 @@
36873644 this.players.addPlayer( vlcPlayer );
36883645 continue;
36893646 }
3690 -
 3647+
36913648 if ( type == 'application/x-java-applet' ) {
36923649 this.players.addPlayer( cortadoPlayer );
36933650 continue;
36943651 }
3695 -
 3652+
36963653 if ( (type == 'video/mpeg' || type=='video/x-msvideo') &&
3697 - pluginName.toLowerCase() == 'vlc multimedia plugin' ) {
3698 - this.players.addPlayer( vlcMozillaPlayer );
3699 - }
3700 -
 3654+ pluginName.toLowerCase() == 'vlc multimedia plugin' ) {
 3655+ this.players.addPlayer( vlcMozillaPlayer );
 3656+ }
 3657+
37013658 if ( type == 'application/ogg' ) {
37023659 if ( pluginName.toLowerCase() == 'vlc multimedia plugin' ) {
37033660 this.players.addPlayer( vlcMozillaPlayer );
37043661 // else if ( pluginName.indexOf( 'QuickTime' ) > -1 )
3705 - // this.players.addPlayer(quicktimeMozillaPlayer);
 3662+ // this.players.addPlayer(quicktimeMozillaPlayer);
37063663 } else {
37073664 this.players.addPlayer( oggPluginPlayer );
37083665 }
@@ -3715,12 +3672,12 @@
37163673 continue;
37173674 }
37183675 }
3719 -
 3676+
37203677 if ( type == 'application/x-shockwave-flash' ) {
3721 -
 3678+
37223679 this.players.addPlayer( kplayer );
3723 - //this.players.addPlayer( flowPlayer );
3724 -
 3680+ // this.players.addPlayer( flowPlayer );
 3681+
37253682 // check version to add omtk:
37263683 if( navigator.plugins["Shockwave Flash"] ){
37273684 var flashDescription = navigator.plugins["Shockwave Flash"].description;
@@ -3733,18 +3690,19 @@
37343691 }
37353692 }
37363693 }
3737 -
 3694+
37383695 // Allow extensions to detect and add their own "players"
37393696 mw.log("trigger::embedPlayerUpdateMediaPlayersEvent");
37403697 $j( mw ).trigger( 'embedPlayerUpdateMediaPlayersEvent' , this.players );
3741 -
 3698+
37423699 },
3743 -
 3700+
37443701 /**
3745 - * Test IE for activeX by name
3746 - *
3747 - * @param {String} name Name of ActiveXObject to look for
3748 - */
 3702+ * Test IE for activeX by name
 3703+ *
 3704+ * @param {String}
 3705+ * name Name of ActiveXObject to look for
 3706+ */
37493707 testActiveX : function ( name ) {
37503708 mw.log("EmbedPlayer::detect: test testActiveX: " + name);
37513709 var hasObj = true;
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.IFramePlayerApiClient.js
@@ -1,53 +1,129 @@
22 /**
3 -* iFrame api mapping support
4 -*
5 -* Client side ( binds a given iFrames to expose the player api )
 3+* iFrame api mapping support
 4+*
 5+* Client side ( binds a given iFrames to expose the player api )
66 */
7 -
8 -// Add the jQuery binding
9 -( function( $ ) {
10 - $.fn.iFramePlayer = function( options ){
11 -
12 - var iframe = $(this.selector).get(0);
13 - var cat = new mw.IFramePlayerApiClient( iframe, options );
14 - };
15 -
16 -} )( jQuery );
17 -
18 -mw.IFramePlayerApiClient = function( iframe, options ){
19 - return this.init( iframe , options);
 7+mw.IFramePlayerApiClient = function( iframe, playerProxy, options ){
 8+ return this.init( iframe , playerProxy, options);
209 }
2110 mw.IFramePlayerApiClient.prototype = {
22 - exportedMethods: [
 11+ 'exportedMethods': [
2312 'play',
2413 'pause'
2514 ],
26 - exportedBindings: [
27 - 'ended'
28 - ],
29 - init: function( iframe , options ){
 15+ // Local store of the post message ( not updated by user js )
 16+ '_prevPlayerProxy': {},
 17+ // Stores the current playerProxy ( can be updated by user js )
 18+ 'init': function( iframe , playerProxy, options ){
3019 this.iframe = iframe;
31 - if( !options.targetOrigin ){
32 - mw.log("Error: IFramePlayerApiClient please supply a target origin");
33 - return ;
34 - } else {
35 - this.targetOrigin = options.targetOrigin;
36 - }
37 - this.addPlayerApi();
 20+ this.playerProxy = playerProxy;
 21+ // Set the iframe server
 22+ var srcParts = mw.parseUri( mw.absoluteUrl( $j(this.iframe).attr('src') ) );
 23+ this.iframeServer = srcParts.protocol + '://' + srcParts.authority;
 24+ this.addPlayerSendApi();
 25+ this.addPlayerReciveApi();
3826 },
39 - addPlayerApi: function(){
 27+ 'addPlayerSendApi': function(){
4028 var _this = this;
4129 $j.each( this.exportedMethods, function(na, method){
42 - _this.iframe[ method ] = function(){
43 - _this.postMethod( method, arguments );
 30+ _this.playerProxy[ method ] = function(){
 31+ _this.postMessage( {
 32+ 'method' : method,
 33+ 'args' : arguments
 34+ } );
4435 };
4536 });
4637 },
47 - postMethod: function( method , args){
48 - mw.log("IFramePlayer:: Post method: '" + method + "' with " + args.length + " arguments");
49 - var methodMsg = {
50 - 'method' : method
 38+ 'addPlayerReciveApi': function(){
 39+ var _this = this;
 40+ $j.receiveMessage( function( event ){
 41+ _this.hanldeReciveMsg( event )
 42+ });
 43+ },
 44+ /**
 45+ * Handle received events
 46+ */
 47+ 'hanldeReciveMsg': function( event ){
 48+ var _this = this;
 49+ //mw.log("IframePlayerApiClient:: hanldeReciveMsg ");
 50+ // Confirm the event is coming for the target host:
 51+ if( event.origin != this.iframeServer){
 52+ mw.log("Skip msg from host does not match iFrame player: " + event.origin +
 53+ ' != iframe Server: ' + this.iframeServer )
 54+ return ;
5155 };
52 - this.iframe.contentWindow.postMessage( JSON.stringify( methodMsg ), this.targetOrigin );
 56+ // Decode the message
 57+ var msgObject = JSON.parse( event.data );
 58+ var playerAttributes = mw.getConfig( 'EmbedPlayer.Attributes' );
 59+ // Before we update local attributes check that the object has not been updated by user js
 60+ for( var attrName in playerAttributes ){
 61+ if( attrName != 'id' ){
 62+ if( _this._prevPlayerProxy[ attrName ] != _this.playerProxy[ attrName ] ){
 63+ mw.log( "IFramePlayerApiClient:: User js update:" + attrName + ' set to: ' + this.playerProxy[ attrName ] + ' != old: ' + _this._prevPlayerProxy[ attrName ] );
 64+ // Send the updated attribute back to the iframe:
 65+ _this.postMessage({
 66+ 'attrName' : attrName,
 67+ 'attrValue' : _this.playerProxy[ attrName ]
 68+ });
 69+ }
 70+ }
 71+ }
 72+ // Update any attributes
 73+ if( msgObject.attributes ){
 74+ for( var i in msgObject.attributes ){
 75+ if( i != 'id' && i != 'class' && i != 'style' ){
 76+ try{
 77+ this.playerProxy[ i ] = msgObject.attributes[i];
 78+ this._prevPlayerProxy[i] = msgObject.attributes[i];
 79+ } catch( e ){
 80+ mw.log("Error could not set:" + i );
 81+ }
 82+ }
 83+ }
 84+ }
 85+ // Trigger any binding events
 86+ if( typeof msgObject.triggerName != 'undefined' && msgObject.triggerArgs != 'undefined') {
 87+ mw.log('IFramePlayerApiClient:: trigger: ' + msgObject.triggerName );
 88+ $j( _this.playerProxy ).trigger( msgObject.triggerName, msgObject.triggerArgs );
 89+ }
 90+ // @@TODO:: Allow extending modules to wrap these api events ( kaltura kdp javascript emulation ? )
 91+ },
 92+ 'postMessage': function( msgObj ){
 93+ mw.log( "IFramePlayerApiClient:: postMessage(): " + JSON.stringify( msgObj ) );
 94+ $j.postMessage(
 95+ JSON.stringify( msgObj ),
 96+ mw.absoluteUrl( $j( this.iframe ).attr('src') ),
 97+ this.iframe.contentWindow
 98+ );
5399 }
54100 };
 101+
 102+//Add the jQuery binding
 103+( function( $ ) {
 104+ $.fn.iFramePlayer = function( options ){
 105+ if( ! this.selector ){
 106+ this.selector = $j( this ).get(0);
 107+ }
 108+ // Append '_ifp' ( iframe player ) to id of real iframe so that 'id', and 'src' attributes don't conflict
 109+ var originalIframeId = ( $( this.selector ).attr( 'id' ) )? $( this.selector ).attr( 'id' ) : Math.floor( 9999999 * Math.random() );
 110+ var iframePlayerId = originalIframeId + '_ifp' ; // here we use random to generate a unique id
 111+ // Append the div element proxy after the iframe
 112+ $j( this.selector )
 113+ .attr('id', iframePlayerId)
 114+ .after(
 115+ $('<div />')
 116+ .attr( 'id', originalIframeId )
 117+ );
 118+ var playerProxy = $j( '#' + originalIframeId ).get(0);
 119+ var iframe = $j('#' + iframePlayerId).get(0);
 120+ if(!iframe){
 121+ mw.log("Error invalide iFramePlayer request");
 122+ return false;
 123+ }
 124+ if( !iframe['playerApi'] ){
 125+ iframe['playerApi'] = new mw.IFramePlayerApiClient( iframe, playerProxy, options );
 126+ }
 127+ // Return the player proxy for chaining player events / attributes
 128+ return $j( playerProxy );
 129+ };
 130+} )( jQuery );
\ No newline at end of file
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js
@@ -796,8 +796,7 @@
797797 'id' : 'ffwarn_' + embedPlayer.id,
798798 'type' : "checkbox",
799799 'name' : 'ffwarn_' + embedPlayer.id
800 - })
801 - .click( function() {
 800+ }).click( function() {
802801 mw.log("WarningBindinng:: set " + preferenceId + ' to hidewarning ' );
803802 // Set up a cookie for 30 days:
804803 $j.cookie( preferenceId, 'hidewarning', { expires: 30 } );
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerNative.js
@@ -1,37 +1,34 @@
22 /**
33 * Native embed library:
4 -*
 4+*
55 * Enables embedPlayer support for native html5 browser playback system
66 */
77 mw.EmbedPlayerNative = {
88
99 //Instance Name
1010 instanceOf: 'Native',
11 -
12 - // Counts the number of times we tried to access the video element
 11+
 12+ // Counts the number of times we tried to access the video element
1313 grab_try_count:0,
14 -
15 - // Flag to only load the video ( not play it )
 14+
 15+ // Flag to only load the video ( not play it )
1616 onlyLoadFlag:false,
17 -
18 - //Callback fired once video is "loaded"
 17+
 18+ //Callback fired once video is "loaded"
1919 onLoadedCallback: null,
20 -
21 - //For retrying a player embed with a distinct url
22 - // NOTE: this bug workaround may no longer be applicable
23 - urlAppend:'',
24 -
25 - // The previous "currentTime" to sniff seek actions
 20+
 21+ // The previous "currentTime" to sniff seek actions
2622 // NOTE the bug where onSeeked does not seem fire consistently may no longer be applicable
2723 prevCurrentTime: -1,
28 -
 24+
2925 // Store the progress event ( updated during monitor )
3026 progressEventData: null,
31 -
32 - // If the media loaded event has been fired
 27+
 28+ // If the media loaded event has been fired
3329 mediaLoadedFlag: null,
34 -
35 - // All the native events per:
 30+
 31+
 32+ // All the native events per:
3633 // http://www.w3.org/TR/html5/video.html#mediaevents
3734 nativeEvents : [
3835 'loadstart',
@@ -68,49 +65,49 @@
6966 'overlays' : true
7067 },
7168
72 - /**
73 - * updates the supported features given the "type of player"
 69+ /**
 70+ * Updates the supported features given the "type of player"
7471 */
7572 updateFeatureSupport: function(){
7673 // iWhatever devices appear to have a broken
7774 // dom overlay implementation of video atm. (hopefully iphone OS 4 fixes this )
78 - if( mw.isMobileHTML5() ) {
 75+ if( mw.isHTML5FallForwardNative() ) {
7976 this.supports.overlays = false;
8077 }
8178 },
82 -
 79+
8380 /**
8481 * Return the embed code
8582 */
8683 doEmbedHTML : function () {
8784 var _this = this;
88 -
89 - // Reset some play state flags:
 85+
 86+ // Reset some play state flags:
9087 _this.bufferStartFlag = false;
9188 _this.bufferEndFlag = false;
92 -
 89+
9390 mw.log( "native play url:" + this.getSrc() + ' startOffset: ' + this.start_ntp + ' end: ' + this.end_ntp );
94 -
 91+
9592 // Check if using native controls and already the "pid" is already in the DOM
9693 if( this.useNativePlayerControls() && $j( '#' + this.pid ).length &&
9794 typeof $j( '#' + this.pid ).get(0).play != 'undefined' ) {
9895 _this.postEmbedJS();
9996 return ;
10097 }
101 -
 98+
10299 $j( this ).html(
103100 _this.getNativePlayerHtml()
104101 );
105 -
106 - // Directly run postEmbedJS ( if playerElement is not available it will retry )
 102+
 103+ // Directly run postEmbedJS ( if playerElement is not available it will retry )
107104 _this.postEmbedJS();
108105 },
109 -
 106+
110107 /**
111108 * Get the native player embed code.
112 - *
 109+ *
113110 * @param {object} playerAttribtues Attributes to be override in function call
114 - * @return {object} cssSet css to apply to the player
 111+ * @return {object} cssSet css to apply to the player
115112 */
116113 getNativePlayerHtml: function( playerAttribtues, cssSet ){
117114 if( !playerAttribtues) {
@@ -119,46 +116,46 @@
120117 // Update required attributes
121118 if( !playerAttribtues[ 'id'] ) playerAttribtues['id'] = this.pid;
122119 if( !playerAttribtues['src'] ) playerAttribtues['src'] = this.getSrc();
123 -
 120+
124121 // If autoplay pass along to attribute ( needed for iPad / iPod no js autoplay support
125122 if( this.autoplay ) {
126123 playerAttribtues['autoplay'] = 'true';
127124 }
128 -
129 -
 125+
 126+
130127 if( !cssSet ){
131128 cssSet = {};
132129 }
133130 // Set default width height to 100% of parent container
134131 if( !cssSet['width'] ) cssSet['width'] = '100%';
135132 if( !cssSet['height'] ) cssSet['height'] = '100%';
136 -
 133+
137134 // Also need to set the loop param directly for iPad / iPod
138135 if( this.loop ) {
139136 playerAttribtues['loop'] = 'true';
140137 }
141 -
 138+
142139 var tagName = ( this.isAudio() ) ? 'audio' : 'video';
143 -
 140+
144141 return $j( '<' + tagName + ' />' )
145 - // Add the special nativeEmbedPlayer to avoid any rewrites of of this video tag.
 142+ // Add the special nativeEmbedPlayer to avoid any rewrites of of this video tag.
146143 .addClass( 'nativeEmbedPlayerPid' )
147144 .attr( playerAttribtues )
148145 .css( cssSet );
149146 },
150 -
 147+
151148 /**
152 - * Post element javascript, binds event listeners and starts monitor
 149+ * Post element javascript, binds event listeners and starts monitor
153150 */
154151 postEmbedJS: function() {
155152 var _this = this;
156153 mw.log( "f:native:postEmbedJS:" );
157154
158 - // Setup local pointer:
 155+ // Setup local pointer:
159156 var vid = this.getPlayerElement();
160157 // Apply media element bindings:
161158 this.applyMediaElementBindings();
162 -
 159+
163160 // Check for load flag
164161 if ( this.onlyLoadFlag ) {
165162 vid.pause();
@@ -167,14 +164,14 @@
168165 // Issue play request
169166 vid.play();
170167 }
171 -
 168+
172169 setTimeout( function() {
173170 _this.monitor();
174171 }, 100 );
175172 },
176 -
 173+
177174 /**
178 - * Apply media element bindings
 175+ * Apply media element bindings
179176 */
180177 applyMediaElementBindings: function(){
181178 var _this = this;
@@ -183,35 +180,36 @@
184181 mw.log( " Error: applyMediaElementBindings without player elemnet");
185182 return ;
186183 }
187 -
188 - // Bind events to local js methods:
189 - vid.addEventListener( 'canplaythrough', function() { $j( _this ).trigger('canplaythrough'); }, true);
190 - vid.addEventListener( 'loadedmetadata', function() { _this.onloadedmetadata() }, true);
191 - vid.addEventListener( 'progress', function( e ) { if( _this.onprogress ) { _this.onprogress( e ); } }, true);
192 - vid.addEventListener( 'ended', function() { _this.onended() }, true);
193 - vid.addEventListener( 'seeking', function() { _this.onSeeking() }, true);
194 - vid.addEventListener( 'seeked', function() { _this.onSeeked() }, true);
195 -
196 - vid.addEventListener( 'pause', function() { if( _this.onPaused ) { _this.onPaused() } }, true );
197 - vid.addEventListener( 'play', function(){ _this.onPlay() }, true );
198 - vid.addEventListener( 'volumechange', function(){ _this.onVolumeChange() } , true );
 184+ $j.each( _this.nativeEvents, function( inx, eventName ){
 185+ $j( vid ).bind( eventName , function(){
 186+ if( _this._propagateEvents ){
 187+ // Check if there is local handler:
 188+ if( _this['on' + eventName ] ){
 189+ _this['on' + eventName ].apply( _this, arguments );
 190+ } else {
 191+ // no local handler directly propagate the event to the abstract object:
 192+ $j( _this ).trigger( eventName, arguments )
 193+ }
 194+ }
 195+ })
 196+ });
199197 },
200 -
 198+
201199 // basic monitor function to update buffer
202200 monitor: function(){
203201 var _this = this;
204202 var vid = _this.getPlayerElement();
205 -
 203+
206204 // Update the bufferedPercent
207205 if( vid && vid.buffered && vid.buffered.end && vid.duration ) {
208206 this.bufferedPercent = (vid.buffered.end(0) / vid.duration);
209207 }
210208 _this.parent_monitor();
211209 },
212 -
213 -
 210+
 211+
214212 /**
215 - * Issue a seeking request.
 213+ * Issue a seeking request.
216214 *
217215 * @param {Float} percentage
218216 */
@@ -220,10 +218,10 @@
221219 this.seeking = true;
222220 // Run the seeking hook
223221 $j( this.embedPlayer ).trigger( 'onSeek' );
224 -
 222+
225223 // Run the onSeeking interface update
226224 this.controlBuilder.onSeek();
227 -
 225+
228226 // @@todo check if the clip is loaded here (if so we can do a local seek)
229227 if ( this.supportsURLTimeEncoding() ) {
230228 // Make sure we could not do a local seek instead:
@@ -231,21 +229,22 @@
232230 mw.log( "do local seek " + percentage + ' is already buffered < ' + this.bufferedPercent );
233231 this.doNativeSeek( percentage );
234232 } else {
235 - // We support URLTimeEncoding call parent seek:
 233+ // We support URLTimeEncoding call parent seek:
236234 this.parent_doSeek( percentage );
237235 }
238236 } else if ( this.playerElement && this.playerElement.duration ) {
239 - // (could also check bufferedPercent > percentage seek (and issue oggz_chop request or not)
 237+ // (could also check bufferedPercent > percentage seek (and issue oggz_chop request or not)
240238 this.doNativeSeek( percentage );
241239 } else {
242 - // try to do a play then seek:
 240+ // try to do a play then seek:
243241 this.doPlayThenSeek( percentage )
244242 }
245243 },
246 -
 244+
247245 /**
248246 * Do a native seek by updating the currentTime
249 - * @param {float} percentage Percent to seek to of full time
 247+ * @param {float} percentage
 248+ * Percent to seek to of full time
250249 */
251250 doNativeSeek: function( percentage ) {
252251 var _this = this;
@@ -257,11 +256,12 @@
258257 _this.monitor();
259258 })
260259 },
261 -
 260+
262261 /**
263262 * Seek in a existing stream
264263 *
265 - * @param {Float} percentage Percentage of the stream to seek to between 0 and 1
 264+ * @param {Float} percentage
 265+ * Percentage of the stream to seek to between 0 and 1
266266 */
267267 doPlayThenSeek: function( percentage ) {
268268 mw.log( 'native::doPlayThenSeek::' );
@@ -274,7 +274,7 @@
275275 if ( _this.playerElement && _this.playerElement.duration ) {
276276 _this.doNativeSeek( percentage );
277277 } else {
278 - // Try to get player for 40 seconds:
 278+ // Try to get player for 40 seconds:
279279 // (it would be nice if the onmetadata type callbacks where fired consistently)
280280 if ( retryCount < 800 ) {
281281 setTimeout( readyForSeek, 50 );
@@ -286,12 +286,14 @@
287287 }
288288 readyForSeek();
289289 },
290 -
 290+
291291 /**
292292 * Set the current time with a callback
293 - *
294 - * @param {Float} position Seconds to set the time to
295 - * @param {Function} callback Function called once time has been set.
 293+ *
 294+ * @param {Float} position
 295+ * Seconds to set the time to
 296+ * @param {Function} callback
 297+ * Function called once time has been set.
296298 */
297299 setCurrentTime: function( time , callback, callbackCount ) {
298300 var _this = this;
@@ -301,7 +303,7 @@
302304 if( _this.playerElement.readyState >= 1 ){
303305 if( _this.playerElement.currentTime == time ){
304306 callback();
305 - return;
 307+ return;
306308 }
307309 var once = function( event ) {
308310 if( callback ){
@@ -311,17 +313,11 @@
312314 };
313315 // Assume we will get to add the Listener before the seek is done
314316 _this.playerElement.addEventListener( 'seeked', once, false );
315 - try {
316 - _this.playerElement.currentTime = time;
317 - } catch (e) {
318 - mw.log("Could not seek to this point. Unbuffered point.");
319 - callback();
320 - return;
321 - }
 317+ _this.playerElement.currentTime = time;
322318 } else {
323319 if( callbackCount >= 300 ){
324320 mw.log("Error with seek request, media never in ready state");
325 - return ;
 321+ return ;
326322 }
327323 setTimeout( function(){
328324 _this.setCurrentTime( time, callback , callbackCount++);
@@ -335,8 +331,8 @@
336332 getPlayerElementTime: function() {
337333 var _this = this;
338334 // Make sure we have .vid obj
339 - this.getPlayerElement();
340 -
 335+ this.getPlayerElement();
 336+
341337 if ( !this.playerElement ) {
342338 mw.log( 'mwEmbedPlayer::getPlayerElementTime: ' + this.id + ' not in dom ( stop monitor)' );
343339 return false;
@@ -344,19 +340,8 @@
345341 // Return the playerElement currentTime
346342 return this.playerElement.currentTime;
347343 },
348 -
 344+
349345 /**
350 - * Get video src URI
351 - * appends this.urlAppend for unique urls for re-requesting src urls on broken playback
352 - */
353 - getSrc: function() {
354 - var src = this.parent_getSrc();
355 - if ( this.urlAppend != '' )
356 - return src + ( ( src.indexOf( '?' ) == -1 ) ? '?':'&' ) + this.urlAppend;
357 - return src;
358 - },
359 -
360 - /**
361346 * Pause the video playback
362347 * calls parent_pause to update the interface
363348 */
@@ -369,13 +354,13 @@
370355 }
371356 }
372357 },
373 -
 358+
374359 /**
375360 * Play back the video stream
376 - * calls parent_play to update the interface
 361+ * calls parent_play to update the interface
377362 */
378363 play: function( ) {
379 -
 364+
380365 this.getPlayerElement();
381366 this.parent_play(); // update interface
382367 if ( this.playerElement && this.playerElement.play ) {
@@ -383,12 +368,12 @@
384369 if( this.playerElement.paused ){
385370 this.playerElement.play();
386371 }
387 - // re-start the monitor:
 372+ // re-start the monitor:
388373 this.monitor();
389374 }
390375 },
391376 /**
392 - * Stop the player ( end all listeners )
 377+ * Stop the player ( end all listeners )
393378 */
394379 stop:function(){
395380 if( this.playerElement ){
@@ -396,10 +381,10 @@
397382 }
398383 this.parent_stop();
399384 },
400 -
 385+
401386 /**
402387 * Toggle the Mute
403 - * calls parent_toggleMute to update the interface
 388+ * calls parent_toggleMute to update the interface
404389 */
405390 toggleMute: function() {
406391 this.parent_toggleMute();
@@ -407,7 +392,7 @@
408393 if ( this.playerElement )
409394 this.playerElement.muted = this.muted;
410395 },
411 -
 396+
412397 /**
413398 * Update Volume
414399 *
@@ -422,37 +407,28 @@
423408 this.playerElement.volume = percentage;
424409 }
425410 },
426 -
 411+
427412 /**
428413 * get Volume
429414 *
430 - * @return {Float}
 415+ * @return {Float}
431416 * Audio volume between 0 and 1.
432417 */
433 - getPlayerElementVolume: function() {
 418+ getPlayerElementVolume: function() {
434419 if ( this.getPlayerElement() ) {
435420 return this.playerElement.volume;
436421 }
437422 },
438423 /**
439424 * get the native muted state
440 - */
 425+ */
441426 getPlayerElementMuted: function(){
442427 if ( this.getPlayerElement() ) {
443428 return this.playerElement.muted;
444429 }
445430 },
446 -
 431+
447432 /**
448 - * Handle volume change are handled via "monitor" as to not do too many binding triggers per seconds.
449 - */
450 - onVolumeChange: function(){
451 - //mw.log( "native::volumechange::trigger" );
452 - //this.volume = this.playerElement.volume;
453 - $j( this ).trigger( 'volumechange' );
454 - },
455 -
456 - /**
457433 * Get the native media duration
458434 */
459435 getNativeDuration: function() {
@@ -460,7 +436,7 @@
461437 return this.playerElement.duration;
462438 }
463439 },
464 -
 440+
465441 /**
466442 * load the video stream with a callback fired once the video is "loaded"
467443 *
@@ -481,80 +457,80 @@
482458 callback();
483459 }
484460 },
485 -
 461+
486462 /**
487 - * Get /update the playerElement value
488 - */
 463+ * Get /update the playerElement value
 464+ */
489465 getPlayerElement: function () {
490466 this.playerElement = $j( '#' + this.pid ).get( 0 );
491467 return this.playerElement;
492468 },
493 -
 469+
494470 /**
495 - * Bindings for the Video Element Events
 471+ * Bindings for the Video Element Events
496472 */
497 -
 473+
498474 /**
499475 * Local method for seeking event
500 - * fired when "seeking"
 476+ * fired when "seeking"
501477 */
502 - onSeeking: function() {
 478+ onseeking: function() {
503479 mw.log( "native:onSeeking");
504 - // Trigger the html5 seeking event
 480+ // Trigger the html5 seeking event
505481 //( if not already set from interface )
506482 if( !this.seeking ) {
507483 this.seeking = true;
508484 // Run the seeking hook (somewhat redundant )
509485 $j( this ).trigger( 'onSeek' );
510 -
 486+
511487 // Run the onSeeking interface update
512488 this.controlBuilder.onSeek();
513 -
 489+
514490 // Trigger the html5 "seeking" trigger
515491 mw.log("native:seeking:trigger:: " + this.seeking);
516492 $j( this ).trigger( 'seeking' );
517493 }
518494 },
519 -
 495+
520496 /**
521497 * Local method for seeked event
522 - * fired when done seeking
 498+ * fired when done seeking
523499 */
524 - onSeeked: function() {
 500+ onseeked: function() {
525501 mw.log("native:onSeeked");
526 -
 502+
527503 mw.log("native:onSeeked:trigger");
528 - // Trigger the html5 action on the parent
 504+ // Trigger the html5 action on the parent
529505 if( this.seeking && this.useNativePlayerControls() ){
530506 this.seeking = false;
531507 $j( this ).trigger( 'seeked' );
532508 }
533509 this.seeking = false;
534510 },
535 -
 511+
536512 /**
537513 * Handle the native paused event
538 - */
539 - onPaused: function(){
 514+ */
 515+ onpause: function(){
540516 mw.log( "EmbedPlayer:native: OnPaused" );
541517 this.parent_pause();
542518 },
543 -
 519+
544520 /**
545 - * Handle the native play event
 521+ * Handle the native play event
546522 */
547 - onPlay: function(){
 523+ onplay: function(){
548524 mw.log("EmbedPlayer:native:: OnPlay");
549525 // Update the interface ( if paused )
550526 this.parent_play();
551527 },
552 -
 528+
553529 /**
554530 * Local method for metadata ready
555 - * fired when metadata becomes available
 531+ * fired when metadata becomes available
556532 *
557 - * Used to update the media duration to
558 - * accurately reflect the src duration
 533+ * Used to update the media duration to
 534+ * accurately reflect the src duration
559535 */
560536 onloadedmetadata: function() {
561537 this.getPlayerElement();
@@ -562,42 +538,45 @@
563539 mw.log( 'f:onloadedmetadata metadata ready Update duration:' + this.playerElement.duration + ' old dur: ' + this.getDuration() );
564540 this.duration = this.playerElement.duration;
565541 }
566 -
 542+
567543 //Fire "onLoaded" flags if set
568544 if( typeof this.onLoadedCallback == 'function' ) {
569545 this.onLoadedCallback();
570546 }
571 -
 547+
572548 // Tigger "media loaded"
573549 if( ! this.mediaLoadedFlag ){
574550 $j( this ).trigger( 'mediaLoaded' );
575551 this.mediaLoadedFlag = true;
576552 }
577553 },
578 -
 554+
579555 /**
580556 * Local method for progress event
581 - * fired as the video is downloaded / buffered
 557+ * fired as the video is downloaded / buffered
582558 *
583 - * Used to update the bufferedPercent
 559+ * Used to update the bufferedPercent
 560+ *
 561+ * Note: this way of updating buffer was only supported in firefox 3.x and
 562+ * not supported in firefox 4.x
584563 */
585564 onprogress: function( e ) {
586565 if( e.loaded && e.total ) {
587 - this.bufferedPercent = e.loaded / e.total;
 566+ this.bufferedPercent = e.loaded / e.total;
588567 this.progressEventData = e.loaded;
589568 }
590569 },
591 -
 570+
592571 /**
593572 * Local method for progress event
594 - * fired as the video is downloaded / buffered
 573+ * fired as the video is downloaded / buffered
595574 *
596 - * Used to update the bufferedPercent
 575+ * Used to update the bufferedPercent
597576 */
598577 onended: function() {
599578 var _this = this;
600579 mw.log( 'EmbedPlayer:native: onended:' + this.playerElement.currentTime + ' real dur:' + this.getDuration() );
601 -
 580+
602581 this.onClipDone();
603582 }
604583 };
Index: branches/MwEmbedStandAlone/libraries/jquery/plugins/jquery.postmessage.js
@@ -0,0 +1,222 @@
 2+/*!
 3+ * jQuery postMessage - v0.5 - 9/11/2009
 4+ * http://benalman.com/projects/jquery-postmessage-plugin/
 5+ *
 6+ * Copyright (c) 2009 "Cowboy" Ben Alman
 7+ * Dual licensed under the MIT and GPL licenses.
 8+ * http://benalman.com/about/license/
 9+ */
 10+
 11+// Script: jQuery postMessage: Cross-domain scripting goodness
 12+//
 13+// *Version: 0.5, Last updated: 9/11/2009*
 14+//
 15+// Project Home - http://benalman.com/projects/jquery-postmessage-plugin/
 16+// GitHub - http://github.com/cowboy/jquery-postmessage/
 17+// Source - http://github.com/cowboy/jquery-postmessage/raw/master/jquery.ba-postmessage.js
 18+// (Minified) - http://github.com/cowboy/jquery-postmessage/raw/master/jquery.ba-postmessage.min.js (0.9kb)
 19+//
 20+// About: License
 21+//
 22+// Copyright (c) 2009 "Cowboy" Ben Alman,
 23+// Dual licensed under the MIT and GPL licenses.
 24+// http://benalman.com/about/license/
 25+//
 26+// About: Examples
 27+//
 28+// This working example, complete with fully commented code, illustrates one
 29+// way in which this plugin can be used.
 30+//
 31+// Iframe resizing - http://benalman.com/code/projects/jquery-postmessage/examples/iframe/
 32+//
 33+// About: Support and Testing
 34+//
 35+// Information about what version or versions of jQuery this plugin has been
 36+// tested with and what browsers it has been tested in.
 37+//
 38+// jQuery Versions - 1.3.2
 39+// Browsers Tested - Internet Explorer 6-8, Firefox 3, Safari 3-4, Chrome, Opera 9.
 40+//
 41+// About: Release History
 42+//
 43+// 0.5 - (9/11/2009) Improved cache-busting
 44+// 0.4 - (8/25/2009) Initial release
 45+
 46+(function($){
 47+ '$:nomunge'; // Used by YUI compressor.
 48+
 49+ // A few vars used in non-awesome browsers.
 50+ var interval_id,
 51+ last_hash,
 52+ cache_bust = 1,
 53+
 54+ // A var used in awesome browsers.
 55+ rm_callback,
 56+
 57+ // A few convenient shortcuts.
 58+ window = this,
 59+ FALSE = !1,
 60+
 61+ // Reused internal strings.
 62+ postMessage = 'postMessage',
 63+ addEventListener = 'addEventListener',
 64+
 65+ p_receiveMessage,
 66+
 67+ // I couldn't get window.postMessage to actually work in Opera 9.64!
 68+ has_postMessage = window[postMessage] && !$.browser.opera;
 69+
 70+ // Method: jQuery.postMessage
 71+ //
 72+ // This method will call window.postMessage if available, setting the
 73+ // targetOrigin parameter to the base of the target_url parameter for maximum
 74+ // security in browsers that support it. If window.postMessage is not available,
 75+ // the target window's location.hash will be used to pass the message. If an
 76+ // object is passed as the message param, it will be serialized into a string
 77+ // using the jQuery.param method.
 78+ //
 79+ // Usage:
 80+ //
 81+ // > jQuery.postMessage( message, target_url [, target ] );
 82+ //
 83+ // Arguments:
 84+ //
 85+ // message - (String) A message to be passed to the other frame.
 86+ // message - (Object) An object to be serialized into a params string, using
 87+ // the jQuery.param method.
 88+ // target_url - (String) The URL of the other frame this window is
 89+ // attempting to communicate with. This must be the exact URL (including
 90+ // any query string) of the other window for this script to work in
 91+ // browsers that don't support window.postMessage.
 92+ // target - (Object) A reference to the other frame this window is
 93+ // attempting to communicate with. If omitted, defaults to `parent`.
 94+ //
 95+ // Returns:
 96+ //
 97+ // Nothing.
 98+
 99+ $[postMessage] = function( message, target_url, target ) {
 100+ if ( !target_url ) { return; }
 101+
 102+ // Serialize the message if not a string. Note that this is the only real
 103+ // jQuery dependency for this script. If removed, this script could be
 104+ // written as very basic JavaScript.
 105+ message = typeof message === 'string' ? message : $.param( message );
 106+
 107+ // Default to parent if unspecified.
 108+ target = target || parent;
 109+
 110+ if ( has_postMessage ) {
 111+ // The browser supports window.postMessage, so call it with a targetOrigin
 112+ // set appropriately, based on the target_url parameter.
 113+ target[postMessage]( message, target_url.replace( /([^:]+:\/\/[^\/]+).*/, '$1' ) );
 114+
 115+ } else if ( target_url ) {
 116+ // The browser does not support window.postMessage, so set the location
 117+ // of the target to target_url#message. A bit ugly, but it works! A cache
 118+ // bust parameter is added to ensure that repeat messages trigger the
 119+ // callback.
 120+ target.location = target_url.replace( /#.*$/, '' ) + '#' + (+new Date) + (cache_bust++) + '&' + message;
 121+ }
 122+ };
 123+
 124+ // Method: jQuery.receiveMessage
 125+ //
 126+ // Register a single callback for either a window.postMessage call, if
 127+ // supported, or if unsupported, for any change in the current window
 128+ // location.hash. If window.postMessage is supported and source_origin is
 129+ // specified, the source window will be checked against this for maximum
 130+ // security. If window.postMessage is unsupported, a polling loop will be
 131+ // started to watch for changes to the location.hash.
 132+ //
 133+ // Note that for simplicity's sake, only a single callback can be registered
 134+ // at one time. Passing no params will unbind this event (or stop the polling
 135+ // loop), and calling this method a second time with another callback will
 136+ // unbind the event (or stop the polling loop) first, before binding the new
 137+ // callback.
 138+ //
 139+ // Also note that if window.postMessage is available, the optional
 140+ // source_origin param will be used to test the event.origin property. From
 141+ // the MDC window.postMessage docs: This string is the concatenation of the
 142+ // protocol and "://", the host name if one exists, and ":" followed by a port
 143+ // number if a port is present and differs from the default port for the given
 144+ // protocol. Examples of typical origins are https://example.org (implying
 145+ // port 443), http://example.net (implying port 80), and http://example.com:8080.
 146+ //
 147+ // Usage:
 148+ //
 149+ // > jQuery.receiveMessage( callback [, source_origin ] [, delay ] );
 150+ //
 151+ // Arguments:
 152+ //
 153+ // callback - (Function) This callback will execute whenever a <jQuery.postMessage>
 154+ // message is received, provided the source_origin matches. If callback is
 155+ // omitted, any existing receiveMessage event bind or polling loop will be
 156+ // canceled.
 157+ // source_origin - (String) If window.postMessage is available and this value
 158+ // is not equal to the event.origin property, the callback will not be
 159+ // called.
 160+ // source_origin - (Function) If window.postMessage is available and this
 161+ // function returns false when passed the event.origin property, the
 162+ // callback will not be called.
 163+ // delay - (Number) An optional zero-or-greater delay in milliseconds at
 164+ // which the polling loop will execute (for browser that don't support
 165+ // window.postMessage). If omitted, defaults to 100.
 166+ //
 167+ // Returns:
 168+ //
 169+ // Nothing!
 170+
 171+ $.receiveMessage = p_receiveMessage = function( callback, source_origin, delay ) {
 172+ if ( has_postMessage ) {
 173+ // Since the browser supports window.postMessage, the callback will be
 174+ // bound to the actual event associated with window.postMessage.
 175+
 176+ if ( callback ) {
 177+ // Unbind an existing callback if it exists.
 178+ rm_callback && p_receiveMessage();
 179+
 180+ // Bind the callback. A reference to the callback is stored for ease of
 181+ // unbinding.
 182+ rm_callback = function(e) {
 183+ if ( ( typeof source_origin === 'string' && e.origin !== source_origin )
 184+ || ( $.isFunction( source_origin ) && source_origin( e.origin ) === FALSE ) ) {
 185+ return FALSE;
 186+ }
 187+ callback( e );
 188+ };
 189+ }
 190+
 191+ if ( window[addEventListener] ) {
 192+ window[ callback ? addEventListener : 'removeEventListener' ]( 'message', rm_callback, FALSE );
 193+ } else {
 194+ window[ callback ? 'attachEvent' : 'detachEvent' ]( 'onmessage', rm_callback );
 195+ }
 196+
 197+ } else {
 198+ // Since the browser sucks, a polling loop will be started, and the
 199+ // callback will be called whenever the location.hash changes.
 200+
 201+ interval_id && clearInterval( interval_id );
 202+ interval_id = null;
 203+
 204+ if ( callback ) {
 205+ delay = typeof source_origin === 'number'
 206+ ? source_origin
 207+ : typeof delay === 'number'
 208+ ? delay
 209+ : 100;
 210+
 211+ interval_id = setInterval(function(){
 212+ var hash = document.location.hash,
 213+ re = /^#?\d+&/;
 214+ if ( hash !== last_hash && re.test( hash ) ) {
 215+ last_hash = hash;
 216+ callback({ data: hash.replace( re, '' ) });
 217+ }
 218+ }, delay );
 219+ }
 220+ }
 221+ };
 222+
 223+})(jQuery);
\ No newline at end of file

Follow-up revisions

RevisionCommit summaryAuthorDate
r76854Follow up to r76689. This reapplies r75471, r75492 and r75592 which were over...hartman23:40, 16 November 2010
r76860Follow up to r76689. Reapply whitespace cleanup from r75691hartman23:55, 16 November 2010

Status & tagging log