r67524 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r67523‎ | r67524 | r67525 >
Date:10:14, 7 June 2010
Author:dale
Status:deferred
Tags:
Comment:
* improved smilPlayer, moved tests into smilPlayer module.
* basic smilText support
* re-factored smil hooks into mw.SmilHooks.js
* added commons and en.wikipedia to api white list
* minor code cleanup
* added mw.setConfig and mw.ready support to mediaWiki gadget remote
Modified paths:
  • /branches/MwEmbedStandAlone/languages/mw.Language.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/archiveOrgSearch.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/baseRemoteSearch.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/flickrSearch.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/kalturaSearch.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/mediaWikiSearch.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerHtml.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerNative.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/SmilPlayer.i8n.php (added) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/loader.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/mw.EmbedPlayerSmil.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/mw.Smil.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBody.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilHooks.js (added) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilLayout.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/tests (added) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/tests/PanZoom.html (added) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/tests/panzoom (added) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/tests/panzoom/Fruits-4s.smil.xml (modified) (history)
  • /branches/MwEmbedStandAlone/modules/SwarmTransport/mw.SwarmTransport.js (modified) (history)
  • /branches/MwEmbedStandAlone/mwEmbed.js (modified) (history)
  • /branches/MwEmbedStandAlone/remotes/apiProxyPage.js (modified) (history)
  • /branches/MwEmbedStandAlone/remotes/mediaWiki.js (modified) (history)
  • /branches/MwEmbedStandAlone/tests/Playlist_Render.html (replaced) (history)
  • /branches/MwEmbedStandAlone/tests/Sequence_Editor.html (replaced) (history)
  • /branches/MwEmbedStandAlone/tests/Sequence_PanZoom.html (deleted) (history)
  • /branches/MwEmbedStandAlone/tests/media/panzoom (deleted) (history)
  • /branches/MwEmbedStandAlone/tests/testApiProxy.html (modified) (history)

Diff [purge]

Index: branches/MwEmbedStandAlone/remotes/mediaWiki.js
@@ -83,6 +83,7 @@
8484 ], function() {
8585 mw.load( mwEmbedHostPath + '/remotes/AddMediaWizardEditPage.js?' + mwGetReqArgs() );
8686 } );
 87+ return ;
8788 }
8889
8990 // Timed text display:
@@ -104,6 +105,7 @@
105106 myRemote.updateUI();
106107 } );
107108 } );
 109+ return ;
108110 }
109111 }
110112
@@ -130,6 +132,7 @@
131133 } );
132134 */
133135 } );
 136+ return ;
134137 }
135138
136139
@@ -149,7 +152,10 @@
150153 '$j.ui.draggable'
151154 ];
152155 var scriptUrl = mwEmbedHostPath + '/remotes/' + scriptName + '?' + mwGetReqArgs();
153 - loadMwEmbed(libraries, function() { mw.load( scriptUrl ) } );
 156+ loadMwEmbed(libraries, function() {
 157+ mw.load( scriptUrl )
 158+ } );
 159+ return ;
154160 }
155161
156162 // Special api proxy page
@@ -158,13 +164,15 @@
159165 loadMwEmbed( [ 'mw.ApiProxy' ], function() {
160166 mw.load( mwEmbedHostPath + '/remotes/apiProxyPage.js?' + mwGetReqArgs() );
161167 } );
 168+ return ;
162169 }
163170
164171 // Special api proxy page for nested callback of hash url
165172 // Can be replaced with:
166173 if ( wgPageName == 'MediaWiki:ApiProxyNestedCb' ) {
167174 // Note top.mw.ApiProxy.nested frame needs to be on the same domain
168 - top.mw.ApiProxy.nested( window.location.href.split("#")[1] || false );
 175+ top.mw.ApiProxy.nested( window.location.href.split("#")[1] || false );
 176+ return ;
169177 }
170178
171179 // OggHandler rewrite for view pages:
@@ -186,8 +194,16 @@
187195 // Do utility rewrite of OggHandler content:
188196 rewrite_for_OggHandler( vidIdList );
189197 } );
190 - } );
 198+ } );
 199+ return ;
191200 }
 201+
 202+ // IF we did not match any rewrite ( but we do have a ready function ) load mwEmbed
 203+ if( preMwEmbedReady.length ){
 204+ loadMwEmbed( function(){
 205+ // mwEmbed loaded
 206+ });
 207+ }
192208 }
193209 /*
194210 * Sets the mediaWiki content to "loading"
@@ -463,7 +479,7 @@
464480 }
465481
466482
467 - scripts = document.getElementsByTagName( 'script' );
 483+ var scripts = document.getElementsByTagName( 'script' );
468484
469485 // Check for document paramater withJS and ignore found gadget
470486 if( typeof getParamValue == 'undefined' && typeof getURLParamValue == 'undefined'){
@@ -546,7 +562,7 @@
547563 'value' : gadget_id
548564 } );
549565
550 - // Submit the prefrences
 566+ // Submit the preferences
551567 $j.post( form.url, form.data, function( pageHTML ){
552568 var form = mwGetFormFromPage ( pageHTML );
553569 if(!form){
Index: branches/MwEmbedStandAlone/remotes/apiProxyPage.js
@@ -15,9 +15,15 @@
1616 }
1717
1818 // The default mwApiProxyConfig config
19 -// (presently hard coded but should read from user and site config)
 19+// xxx todo whitelist all inter-wiki actions
2020 var mwApiProxyDefaultConfig = {
21 - 'master_whitelist' : [ 'en.wikipedia.org', 'prototype.wikimedia.org', 'localhost', '127.1.1.100' ],
 21+ 'master_whitelist' : [
 22+ 'en.wikipedia.org',
 23+ 'commons.wikimedia.org',
 24+ 'prototype.wikimedia.org',
 25+ 'localhost',
 26+ '127.1.1.100'
 27+ ],
2228 'master_blacklist' : []
2329 };
2430
Index: branches/MwEmbedStandAlone/tests/Sequence_PanZoom.html
@@ -1,35 +0,0 @@
2 -<!doctype html>
3 -<html>
4 -<head>
5 - <title>panzoom Example</title>
6 - <script type="text/javascript" src="../mwEmbed.js?debug=true"></script>
7 - <!-- <script type="text/javascript" src="../jsScriptLoader.php?class=window.jQuery,mwEmbed&debug=true"></script> -->
8 - <script type="text/javascript">
9 - mw.setConfig( 'overlayControls', false );
10 - </script>
11 -</head>
12 -<body>
13 -<h3>Sample playlist pan-zoom animation</h3>
14 -<table>
15 -<tr>
16 -<td>
17 -
18 -<video id="panzoom" type="application/smil" src="media/panzoom/Fruits-4s.smil.xml" width="400" height="400"></video>
19 -
20 -</td>
21 -<td valign="top">
22 -Sample playlist code:
23 -<div style="clear:both"></div>
24 -<textarea style="width:500px;">
25 -<video id="panzoom" type="application/smil" src="media/panzoom/Fruits-4s.smil.xml" width="400" height="300"></video>
26 -</textarea>
27 -<div style="clear:both"></div>
28 -
29 -SMIL Source:
30 -<div style="clear:both"></div>
31 -<iframe style="width:500px;height:300px" src="media/panzoom/Fruits-4s.smil.xml"></iframe>
32 -</td>
33 -</tr>
34 -</table>
35 -</body>
36 -</html>
Index: branches/MwEmbedStandAlone/tests/testApiProxy.html
@@ -158,9 +158,10 @@
159159 <body>
160160 <h3> Simple API proxy testing system </h3>
161161
162 -<div id="setupProxy">Proxy for: <span id="hostName"></span> <br><span style="font-size:small">( be sure to enable the mwEmbed gadget or add importScriptURI( 'path_to_local_mw_install' + /js/remoteMwEmbed.js ) to your User skin .js page </span></div>
 162+<div id="setupProxy">Proxy for: <span id="hostName"></span> <br>
 163+<span style="font-size:small"> this proxy will only work on a limited set of domains that the gadget allows proxy request from </span></div>
163164 <div id="setupDone" style="display:none;">
164 - <br> <a href="#" id="doHello" >Hello User:</a> <span id="helloTarget"></span>
 165+ <br> <a href="#" id="doHello" >Hello User:</a> <span style="width:200px" id="helloTarget"></span>
165166
166167 <br><br><br> <a href="#" id="doAppend">Append Msg to Talk page:</a>
167168 <div id="appendTarget"></div>
Index: branches/MwEmbedStandAlone/tests/Sequence_Editor.html
@@ -3,7 +3,7 @@
44 <html>
55 <head>
66 <title>SMIL Sequence Editor example</title>
7 - <script type="text/javascript" src="../mwEmbed.js?debug=true"></script>
 7+ <script type="text/javascript" src="../../mwEmbed.js?debug=true"></script>
88 <script type="text/javascript">
99 mw.ready(function(){
1010 mw.load( 'Sequencer', function(){
Index: branches/MwEmbedStandAlone/tests/Playlist_Render.html
@@ -2,7 +2,7 @@
33 <html>
44 <head>
55 <title>Seeking Render Example</title>
6 - <script type="text/javascript" src="../mwEmbed.js?debug=true"></script>
 6+ <script type="text/javascript" src="../../mwEmbed.js?debug=true"></script>
77 <style>
88 #render_box {
99 position:absolute;
Index: branches/MwEmbedStandAlone/languages/mw.Language.js
@@ -28,7 +28,7 @@
2929 messageCache[ i ] = msgSet[i];
3030 }
3131 }
32 -
 32+ // By default set the current class missing messages flag to default.
3333 mw.currentClassMissingMessages = false;
3434
3535 /**
@@ -62,8 +62,10 @@
6363 }
6464
6565 /**
66 - * NOTE: this is somewhat of a hack. But its only used in debug mode since
67 - * normal msg loading happens via script-loader
 66+ * Load messages for a given named javascript class.
 67+ * This worked in concunktion with the scriptLoader
 68+ * @param {string} className Name of class file to be loaded
 69+ * @param {function} callback Function to be called once class messages are loaded.
6870 */
6971 mw.loadClassMessages = function( className, callback ) {
7072 // Check if wgScriptLoaderPath is set ( else guess the path relative to mwEmbed)
@@ -136,7 +138,7 @@
137139 */
138140
139141 mw.Language.messageSwapObject = function( message, arguments ){
140 - return this.init( message, arguments );
 142+ this.init( message, arguments );
141143 }
142144
143145 mw.Language.messageSwapObject.prototype= {
Index: branches/MwEmbedStandAlone/modules/SwarmTransport/mw.SwarmTransport.js
@@ -67,7 +67,7 @@
6868
6969 var source = embedPlayer.mediaElement.getSources( 'video/ogg' )[0];
7070 if( ! source ){
71 - mw.log("Error: addSwarmSource: could not find video/ogg source to gennerate torrent from");
 71+ mw.log("Warning: addSwarmSource: could not find video/ogg source to gennerate torrent from");
7272 callback();
7373 return ;
7474 }
Index: branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/kalturaSearch.js
@@ -10,7 +10,7 @@
1111 } );
1212
1313 var kalturaFilters = function ( options ) {
14 - return this.init( options );
 14+ this.init( options );
1515 }
1616
1717 kalturaFilters.prototype = {
@@ -28,8 +28,7 @@
2929 * @param Object options Set of options for the search
3030 */
3131 init: function( options ) {
32 - this.resetFilters();
33 - return this;
 32+ this.resetFilters();
3433 },
3534
3635 resetFilters: function() {
Index: branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/mediaWikiSearch.js
@@ -2,7 +2,7 @@
33 * mediaWiki search implementation
44 */
55 var mediaWikiSearch = function( options ) {
6 - return this.init( options );
 6+ this.init( options );
77 };
88 mediaWikiSearch.prototype = {
99
Index: branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/baseRemoteSearch.js
@@ -35,8 +35,8 @@
3636 'category' : '.media:category@label|url'
3737 };
3838
39 -var baseRemoteSearch = function( iObj ) {
40 - return this.init( iObj );
 39+var baseRemoteSearch = function( options ) {
 40+ this.init( options );
4141 };
4242 baseRemoteSearch.prototype = {
4343
Index: branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/archiveOrgSearch.js
@@ -6,8 +6,8 @@
77 * http://lucene.apache.org/solr/
88 */
99
10 -var archiveOrgSearch = function ( iObj ) {
11 - return this.init( iObj );
 10+var archiveOrgSearch = function ( options ) {
 11+ this.init( options );
1212 }
1313 archiveOrgSearch.prototype = {
1414
Index: branches/MwEmbedStandAlone/modules/AddMedia/searchLibs/flickrSearch.js
@@ -13,7 +13,7 @@
1414 */
1515
1616 var flickrSearch = function ( options ) {
17 - return this.init( options );
 17+ this.init( options );
1818 }
1919 flickrSearch.prototype = {
2020 dtUrl : 'http://www.flickr.com/photos/',
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerHtml.js
@@ -22,10 +22,7 @@
2323 'timeDisplay':true,
2424 'volumeControl':true,
2525
26 - 'overlays':true,
27 -
28 - // if the object supports playlist functions
29 - 'playlist_swap_loader':true
 26+ 'overlays':true,
3027 },
3128
3229 // If the player is "ready to play"
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerNative.js
@@ -37,11 +37,8 @@
3838 'pause' : true,
3939 'fullscreen' : true,
4040 'timeDisplay' : true,
41 - 'volumeControl' : true,
42 -
43 - 'overlays' : true,
44 - // if the object supports playlist functions
45 - 'playlist_swap_loader' : true
 41+ 'volumeControl' : true,
 42+ 'overlays' : true
4643 },
4744 /**
4845 * updates the supported features given the "type of player"
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js
@@ -1495,16 +1495,10 @@
14961496
14971497 // Scope the end of check for player sources so it can be called in a callback
14981498 var finishCheckPlayerSources = function(){
1499 - // Run embedPlayer sources hook
1500 - if ( $j( _this ).data('events') ){
1501 - mw.log(" checkPlayerSources:: trigger checkPlayerSourcesEvent" );
1502 - $j( _this ).trigger ( 'checkPlayerSourcesEvent', function() {
1503 - // Continue application flow and check for Timed Text
1504 - _this.checkForTimedText();
1505 - } );
1506 - } else {
 1499+ // Run embedPlayer sources hook
 1500+ mw.runTriggersCallback( _this, 'checkPlayerSourcesEvent', function(){
15071501 _this.checkForTimedText();
1508 - }
 1502+ })
15091503 }
15101504
15111505 // NOTE: Should could be moved to mediaWiki Api support module
@@ -1863,8 +1857,7 @@
18641858 'color' : 'black',
18651859 'width' : _this.width + 'px',
18661860 'height' : _this.height + 'px'
1867 - })
1868 - .loadingSpinner()
 1861+ })
18691862 );
18701863 }
18711864
@@ -1887,7 +1880,6 @@
18881881 });
18891882 }
18901883
1891 -
18921884 // mw.log('should embed:' + embed_code);
18931885 _this.doEmbedHTML()
18941886 },
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBody.js
@@ -7,99 +7,241 @@
88 }
99
1010 mw.SmilBody.prototype = {
 11+
 12+ // Used to store elements for getElementForTime method
 13+ elementsInRange: [],
1114
12 - init: function( $body ){
13 - this.$dom = $body;
 15+ // Constructor:
 16+ init: function( smilObject ){
 17+ this.smil = smilObject;
 18+ this.$dom = this.smil.getDom().find( 'body' );
 19+ },
 20+
 21+ /**
 22+ * Gets all the elements for a given time.
 23+ *
 24+ */
 25+ getElementForTime: function ( time ) {
 26+ var startOffset = 0;
 27+ if( !time )
 28+ time =0;
 29+ // Empty out the requested element set:
 30+ this.elementsInRange = [];
 31+ this.getElementForTimeRecurse( this.$dom, time, startOffset);
 32+ return this.elementsInRange;
1433 },
1534
16 - // maybe "build" layout ?
17 - updateLayout: function ( $layoutDom , time ) {
 35+ /**
 36+ * getElementForTimeRecurse
 37+ * @param {Object} $node NOde to recursively search for elements in the given time range
 38+ */
 39+ getElementForTimeRecurse: function( $node, time, startOffset){
 40+ // Setup local pointers:
 41+ var nodeDuration = this.getNodeDuration( $node );
 42+ var nodeType = this.getNodeSmilType( $node );
 43+ var nodeParentType = this.getNodeSmilType( $node.parent() );
1844 var _this = this;
1945
20 - // Set up the top level "seq" container:
21 - // ( by default "body" is treated like a seq tag per smil spec )
22 - // http://www.w3.org/TR/2008/REC-SMIL3-20081201/smil-structure.html#edef-body
23 -
24 - this.rootBlock = new mw.SmilPar( this.$dom );
25 - this.rootBlock.smilBlocks = [] ;
26 - mw.log( 'updateLayout:: about to recurse smil blocks');
27 - // Recurse out the rest of the structure:
28 - this.recurseSmilBlocks( this.$dom, this.rootBlock.blockStore );
29 - var cat = this.rootBlock;
30 - debugger;
 46+ mw.log( "getElementForTimeRecurse::" +
 47+ ' time: ' + time +
 48+ ' nodeName: ' + $j( $node ).get(0).nodeName +
 49+ ' nodeType: ' + nodeType +
 50+ ' nodeDur: ' + nodeDuration +
 51+ ' offset: ' + startOffset
 52+ );
3153
32 - return $layoutDom;
33 - },
 54+ // If startOffset is > time skip node and all its children
 55+ if( startOffset > time ){
 56+ mw.log(" Reached end, startOffset is:" + startOffset + ' > ' + time );
 57+ return ;
 58+ }
 59+
 60+ // Means we need to seek ahead
 61+ if( startOffset < time ){
 62+ mw.log("Seek ahead: startOffset is" + startOffset + ' < ' + time );
 63+ return ;
 64+ }
 65+
 66+ // If 'par' or 'seq' recurse to get elements for layout
 67+ if( nodeType == 'par'|| nodeType == 'seq' ) {
 68+ if( $node.children().length ) {
 69+ $node.children().each( function( inx, childNode ){
 70+ mw.log(" recurse:: startOffset:" + nodeType + ' start offset:' + startOffset );
 71+ var childDur = _this.getElementForTimeRecurse( $j( childNode ), time, startOffset);
 72+ // If element parent is a 'seq' increment startOffset:
 73+ if( nodeType == 'seq' ) {
 74+ mw.log(" Parent Seq:: add child dur: " + childDur );
 75+ startOffset += childDur;
 76+ }
 77+ });
 78+ }
 79+ }
 80+
 81+ // If the nodeType is "ref" find the its associated transformations
 82+ // add to this.elementsInRange array
 83+ if( nodeType == 'ref' || nodeType == 'smilText' ) {
 84+ // Ref type get the
 85+ this.elementsInRange.push( $node );
 86+ mw.log("Add ref to elementsInRange:: " + nodeType + " length:" + this.elementsInRange.length);
 87+ }
 88+ // Return the node Duration for startOffset updates
 89+ return this.getNodeDuration( $node );
 90+ },
3491
3592 /**
 93+ * Returns the smil body duration
 94+ * ( wraps getDurationRecurse to get top level duration )
 95+ */
 96+ getDuration: function(){
 97+ this.duration = this.getNodeDuration( this.$dom );
 98+ mw.log("smilBody:: getDuration: " + this.duration );
 99+ return this.duration;
 100+ },
 101+
 102+ /**
 103+ * Gets the duration recursing from a supplied $node
 104+ * @param {jQueryObject} $node
 105+ * @param {boolean} forceRefresh If a fresh duration should be calculated
 106+ */
 107+ getNodeDuration: function( $node, forceRefresh ){
 108+ if( !forceRefresh &&
 109+ $node.data('computedDuration') != null
 110+ ) {
 111+ return $node.data('computedDuration');
 112+ }
 113+ var _this = this;
 114+ var duration = 0;
 115+ // Set the block type to
 116+ var blockType = this.getNodeSmilType( $node );
 117+
 118+ // recurse on children
 119+ if( $node.children().length ){
 120+ $node.children().each( function( inx, childNode ){
 121+ // If in a sequence add to duration
 122+ var childDuration = _this.getNodeDuration( $j( childNode ) );
 123+ if( blockType == 'seq' ){
 124+ $node.data( 'implictDuration', $node.data('implictDuration') + childDuration );
 125+ }
 126+ // with par blocks ImplictDuration is longest child
 127+ if( blockType == 'par' ){
 128+ if( childDuration > $node.data( 'implictDuration' ) ){
 129+ $node.data( 'implictDuration', childDuration);
 130+ }
 131+ }
 132+ });
 133+ }
 134+ // Check the explicit duration attribute:
 135+ if( $node.attr('dur') ) {
 136+ //mw.log(" return dur: " + mw.SmilParseTime( $node.attr('dur') ) );
 137+ $node.data('computedDuration', mw.SmilParseTime( $node.attr('dur') ) );
 138+ } else {
 139+ // Else return the implictDuration ( built from its children )
 140+ if( $node.data( 'implictDuration' ) ){
 141+ //mw.log(" implictDuration:: " + $node.data( 'implictDuration' ) );
 142+ $node.data('computedDuration', $node.data( 'implictDuration' ) );
 143+ } else {
 144+ $node.data('computedDuration', 0 );
 145+ }
 146+ }
 147+ return $node.data('computedDuration');
 148+ },
 149+
 150+ /**
 151+ * Maps a few smil tags to smil types
 152+ *
 153+ * http://www.w3.org/TR/2008/REC-SMIL3-20081201/smil-structure.html#edef-body
 154+ * 'body' -> 'seq'
 155+ *
 156+ * http://www.w3.org/TR/2008/REC-SMIL3-20081201/smil-extended-media-object.html#edef-ref
 157+ * animation, audio, img, text, textstream and video -> 'ref',
 158+ */
 159+ getNodeSmilType: function( $node ){
 160+ var blockType = $j( $node ).get(0).nodeName;
 161+ blockMap = {
 162+ 'body':'seq',
 163+ 'animation':'ref',
 164+ 'audio' : 'ref',
 165+ 'img' : 'ref',
 166+ 'textstream' : 'ref',
 167+ 'video' : 'ref'
 168+ }
 169+ if( blockMap[ blockType ] ){
 170+ blockType = blockMap[ blockType ];
 171+ }
 172+ return blockType;
 173+ }
 174+
 175+
 176+ /**
36177 * Recurse parse out smil elements
37 - */
 178+
38179 recurseSmilBlocks: function( $node, blockStore ){
39180 var _this = this;
40181
41182 // Recursively parse the body for "<par>" and <seq>"
42 - $node.children().each( function( inx, bodyChild ){
43 - mw.log( 'on node: ' + bodyChild.nodeName);
 183+ $node.children().each( function( inx, childNode ){
 184+ debugger;
 185+ mw.log( 'on node: ' + childNode.nodeName);
44186 var smilBlock = {
45 - 'name' : bodyChild.nodeName
 187+ 'name' : childNode.nodeName
46188 };
47 - switch( bodyChild.nodeName ) {
 189+ switch( childNode.nodeName ) {
48190 case 'par':
49 - smilBlock = new mw.SmilPar( bodyChild );
 191+ smilBlock = new mw.SmilPar( childNode );
50192 break;
51193 case 'seq':
52 - smilBlock = new mw.SmilSeq( bodyChild );
 194+ smilBlock = new mw.SmilSeq( childNode );
53195 break;
54196 default:
55 - mw.log(' Skiped ' + bodyChild.nodeName + ' ( not recognized tag )');
 197+ mw.log(childNode.nodeName + ' ( not recognized tag )');
 198+ smilBlock = new mw.SmilElement( childNode );
56199 break;
57 - }
58 - // Add a blockStore the smilBlock
 200+ }
 201+
 202+ // Add smilBlock to the current smilBlock
59203 blockStore.push( smilBlock );
60204
61205 // If children have children add a block store and recurse
62 - if( $j( bodyChild ).children().length ) {
63 - smilBlock.blockStore = [];
64 - _this.recurseSmilBlocks( $j( bodyChild ), smilBlock.smilBlocks );
 206+ if( $j( childNode ).children().length ) {
 207+ _this.recurseSmilBlocks( $j( childNode ), smilBlock.smilBlocks );
65208 }
66209 });
67210 },
 211+ */
68212
69 -
70 - // Updates the layout and adds a css animation to the next frame
71 - updateLayoutCssAnimation: function(){
72 -
73 - }
74213 }
75214
76215 /**
 216+ * Base smil element
 217+
 218+mw.SmilElement = function( parElement ){
 219+ this.init( parElement );
 220+}
 221+mw.SmilElement.prototype = {
 222+ init: function( element ){
 223+ this.tag = element.nodeName;
 224+ this.$dom = $j( element );
 225+ this.blockStore = [];
 226+ }
 227+} */
 228+
 229+/**
77230 * Par Block
78 -*/
 231+* http://www.w3.org/TR/2008/REC-SMIL3-20081201/smil-timing.html#edef-par
 232+
79233 mw.SmilPar = function( parElement ){
80 - return this.init( parElement );
 234+ this.init( parElement );
81235 }
82 -mw.SmilPar.prototype = {
83 - tag: 'par',
84 - init: function( parElement ) {
85 - var _this = this;
86 - this.$dom = parElement;
87 -
88 - // Go though all its children recursing on mw.SmilSeq where needed
89 -
90 - }
91 -}
92 -
 236+// Inhert the SmilElement prototype
 237+mw.SmilPar.prototype = mw.SmilElement.prototype
 238+*/
93239 /**
94240 * Seq Block
95 -*/
 241+* http://www.w3.org/TR/2008/REC-SMIL3-20081201/smil-timing.html#edef-seq
 242+
96243 mw.SmilSeq = function( seqElement ){
97 - return this.init( seqElement );
 244+ this.init( seqElement );
98245 }
99 -mw.SmilSeq.prototype = {
100 - tag: 'seq',
101 - init: function( seqElement ) {
102 - var _this = this;
103 - this.$dom = seqElement;
104 - // Go though all its children recursing on mw.SmilSeq where needed
105 - }
106 -}
 246+//Inhert the SmilElement prototype
 247+mw.SmilSeq.prototype = mw.SmilElement.prototype;
 248+*/
\ No newline at end of file
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilLayout.js
@@ -6,38 +6,227 @@
77 }
88
99 mw.SmilLayout.prototype = {
10 - init: function( $layout ){
11 - this.$dom = $layout;
12 - },
 10+ // Constructor:
 11+ init: function( smilObject ){
 12+ // Setup a pointer to parent smil Object
 13+ this.smil = smilObject;
 14+
 15+ // Set the smil layout dom:
 16+ this.$dom = this.smil.getDom().find( 'layout' );
 17+
 18+ // Reset the htmlDOM cache
 19+ this.$rootLayout = null;
 20+ },
1321
14 - getHtmlDOM: function( size ){
15 - mw.log("SmilLayout:: getHtmlDOM:: " );
 22+ getHtmlDOM: function( size , time ){
 23+ var _this = this;
 24+ mw.log("SmilLayout:: getHtmlDOM:: " + size.width + ' time: ' + time );
 25+ // Setup target Size:
1626 this.targetWidth = size.width;
1727 this.targetHeight = size.height;
1828
19 - //Setup the root layout
20 - $rootLayout = this.getRootLayout();
 29+ if( !time )
 30+ time = 0;
2131
22 - // Add all the other layout items to the root
23 - this.appendRegions( $rootLayout );
 32+ // Get the root layout HTML and append the html regions
 33+ this
 34+ .getRootLayoutHtml()
 35+ .appendHtmlRegions()
 36+
 37+ // Get all the draw elements from the body this time:
 38+ var drawElements = this.smil.getBody().getElementForTime( time );
2439
25 - return $rootLayout
 40+ mw.log(" got " + drawElements.length + " drawElements" );
 41+
 42+ // Draw layout
 43+ $j.each( drawElements , function(inx, smilElement ) {
 44+ _this.drawElement( smilElement, time );
 45+ } )
 46+ return this.$rootLayout;
2647 },
 48+
 49+ // Draw the element
 50+ drawElement: function( smilElement, time ) {
 51+ var _this = this;
 52+ var regionId = $j( smilElement ).attr( 'region');
 53+ var nodeName = $j( smilElement ).get(0).nodeName ;
 54+ mw.log("Draw: " + nodeName + ' into ' + regionId );
 55+ // Check for region target in $rootLayout
 56+ if( this.$rootLayout.find( '#' + regionId ).length == 0 ) {
 57+ mw.log( "Error Could not find region:" + regionId + " for " + nodeName);
 58+ return ;
 59+ }
 60+
 61+ // Append the transformed Smil to its target region
 62+ this.$rootLayout.find( '#' + regionId ).append(
 63+ this.getSmilElementHtml( smilElement, time)
 64+ )
 65+ },
2766
2867 /**
29 - * Add all the regiions to the root layout
 68+ * Get the transformed smil element in html format
 69+ */
 70+ getSmilElementHtml: function ( smilElement, time ) {
 71+ var nodeName = $j( smilElement ).get(0).nodeName ;
 72+ mw.log("Get Smil Element Html: " + nodeName );
 73+ switch( nodeName.toLowerCase() ){
 74+ case 'smiltext':
 75+ return this.getSmilTextHtml( smilElement, time);
 76+ break;
 77+ case 'img':
 78+ return this.getSmilImgHtml( smilElement, time);
 79+ break;
 80+ }
 81+ mw.log( "Error: Could not find smil layout transform for element type: " + nodeName );
 82+ return $j('<span />')
 83+ .text( 'Error: unkown type:' + nodeName );
 84+ },
 85+
 86+ /**
 87+ * Get a text element per given time
 88+ * xxx we need to use "relativeTime"
 89+ */
 90+ getSmilTextHtml: function( smilElement, relativeTime ) {
 91+ var _this = this;
 92+ mw.log( " Get TEXT Html ");
 93+
 94+ // Empty initial text value
 95+ var textValue = '';
 96+
 97+ // Check if we have child transforms and select the transform that is in range
 98+ if( $j( smilElement ).children().length ){
 99+ var bucketText = '';
 100+ var textBuckets = [];
 101+ var clearInx = 0;
 102+ var el = $j( smilElement ).get(0);
 103+ for ( var i=0; i < el.childNodes.length; i++ ) {
 104+ var node = el.childNodes[i];
 105+ // Check for text Node type:
 106+ if( node.nodeType == 3 ) {
 107+ bucketText += node.nodeValue;
 108+ } else if( node.nodeName == 'clear'){
 109+ var clearTime = mw.SmilParseTime( $j( node ).attr( 'begin') );
 110+ // append bucket
 111+ textBuckets.push( {
 112+ 'text' : bucketText,
 113+ 'clearTime' : clearTime
 114+ } );
 115+ }
 116+ }
 117+ // Get the text node in range given time:
 118+ for( var i =0; i < textBuckets.length ; i++){
 119+ var bucket = textBuckets[i];
 120+ if( relativeTime < bucket.clearTime ){
 121+ textValue = bucket.text;
 122+ break;
 123+ }
 124+ }
 125+ } else {
 126+ textValue = $j( smilElement ).text();
 127+ mw.log( 'Direct text value to: ' + textValue);
 128+ }
 129+
 130+ var textCss = _this.transformSmilCss( smilElement );
 131+
 132+ // Make the font size fixed so it can be scaled
 133+ // based on: http://style.cleverchimp.com/font_size_intervals/altintervals.html
 134+ var sizeMap = {
 135+ 'xx-small' : '.57em',
 136+ 'x-small' : '.69em',
 137+ 'small' : '.83em',
 138+ 'medium' : '1em',
 139+ 'large' : '1.2em',
 140+ 'x-large' : '1.43em',
 141+ 'xx-large' : '1.72em'
 142+ }
 143+ if( sizeMap[ textCss['font-size'] ] ){
 144+ textCss['font-size'] = sizeMap[ textCss['font-size'] ];
 145+ }
 146+
 147+ // If the font size is pixel based parent span will have no effect,
 148+ // directly resize the pixels
 149+ if( textCss['font-size'] && textCss['font-size'].indexOf('px') != -1 ){
 150+ textCss['font-size'] = ( parseFloat( textCss['font-size'] )
 151+ * ( this.targetWidth / this.virtualWidth ) ) + 'px';
 152+ }
 153+
 154+ // Return the htmlElement
 155+ return $j('<span />')
 156+ // Wrap in font-size percentage relative to virtual size
 157+ .css( 'font-size', ( ( this.targetWidth / this.virtualWidth )*100 ) + '%' )
 158+ .append(
 159+ $j('<span />')
 160+ // Transform smil css into html css:
 161+ .css( textCss )
 162+ // Add the text value
 163+ .text( textValue )
 164+ );
 165+ },
 166+
 167+ /**
 168+ * Get Image html per given smil element and requested time
 169+ */
 170+ getSmilImgHtml: function( smilElement, relativeTime ) {
 171+ // Check if we have child transforms and select the transform that is in range
 172+
 173+ var panZoom = null;
 174+ if( $j( smilElement ).children().length ){
 175+ $j( smilElement ).children().each(function(inx, childNode ){
 176+ if( childNode.nodeName == 'animate' ){
 177+ // add begin / duration to animation bucket
 178+
 179+ // get panZoom value
 180+
 181+ // calculate animation position
 182+ }
 183+ })
 184+ } else {
 185+ // just set pan zoom from smilElement ( if set )
 186+ if( $j( smilElement ).attr('panZoom') ){
 187+ panZoom = this.parsePanZoom( $j( smilElement ).attr('panZoom') );
 188+ }
 189+ }
 190+ // XXX get context of smil document for relative or absolute paths:
 191+ return $j('<img />')
 192+ .attr( {
 193+ 'src' : 'panzoom/' + $j( smilElement ).attr( 'src' )
 194+ } )
 195+ .css( {
 196+ 'width': '100%',
 197+ 'height' : '100%'
 198+ })
 199+ },
 200+
 201+ /**
 202+ * Parse pan attribute zoom strings
 203+ */
 204+ parsePanZoom: function( panZoomString ){
 205+ var pz = panZoomString.split(',');
 206+ if( pz.length != 4){
 207+ mw.log("Error Could not parse panZoom Attribute: " + panZoomString);
 208+ return {};
 209+ }
 210+ return {
 211+ 'left' : pz[0],
 212+ 'top' : pz[1],
 213+ 'width' : pz[2],
 214+ 'height': pz[3]
 215+ }
 216+ },
 217+
 218+ /**
 219+ * Add all the regions to the root layout
30220 */
31 - appendRegions: function( $rootLayout ){
 221+ appendHtmlRegions: function(){
32222 var _this = this;
33 - this.$dom.find( 'region' ).each( function( inx, regionElement ) {
34 -
35 - $rootLayout.append(
 223+ this.$dom.find( 'region' ).each( function( inx, regionElement ) {
 224+ _this.$rootLayout.append(
36225 $j( '<div />' )
37 - .attr('rel', 'region')
38 - .css( 'position', 'absolute')
39 - // transofrm the smil attributes into html attributes
 226+ .attr('rel', 'region' )
 227+ .css( 'position', 'absolute' )
 228+ // Transform the smil attributes into html attributes
40229 .attr( _this.transformSmilAttributes( regionElement ) )
41 - // transform the css attributes into percentages
 230+ // Transform the css attributes into percentages
42231 .css(
43232 _this.transformVirtualPixleToPercent(
44233 _this.transformSmilCss( regionElement )
@@ -45,13 +234,15 @@
46235 )
47236 );
48237 });
 238+ return this;
49239 },
50240
51241 /**
52 - * get the root layout object with updated html properties
 242+ * Get the root layout object with updated html properties
53243 */
54 - getRootLayout: function(){
55 - var $rootLayout = $j('<div />' )
 244+ getRootLayoutHtml: function(){
 245+ // Set the in
 246+ this.$rootLayout = $j('<div />' )
56247 .attr('rel', 'root-layout' )
57248 .css( {
58249 'position': 'absolute',
@@ -80,10 +271,10 @@
81272 $j.extend( rootLayoutCss, this.transformSizeToTarget() );
82273
83274 // Update the layout css
84 - $rootLayout.css( rootLayoutCss );
 275+ this.$rootLayout.css( rootLayoutCss );
85276 }
86277
87 - return $rootLayout;
 278+ return this;
88279 },
89280
90281 /**
@@ -91,7 +282,7 @@
92283 * using all percentages instead of pixels lets us scale internal
93284 * layout browser side transforms ( instead of a lot javascript css updates )
94285 *
95 - * @param {object} smilLayout css layout to be translated from virtualWidth & virtualHeight
 286+ * @param {object} layout Css layout to be translated from virtualWidth & virtualHeight
96287 */
97288 transformVirtualPixleToPercent: function( layout ){
98289 var percent = { };
@@ -141,6 +332,7 @@
142333 };
143334
144335 },
 336+
145337 /**
146338 * Transform smil attributes into html attributes
147339 */
@@ -157,6 +349,8 @@
158350 attributes[ smilAttributes[ attr ] ] = $smilElement.attr( attr );
159351 }
160352 }
 353+ // XXX TODO Locally scope all ids into embedPlayer.id + _id
 354+
161355 // Translate rootLayout properties into div
162356 return attributes;
163357 },
@@ -167,6 +361,7 @@
168362 */
169363 transformSmilCss: function( smilElement ){
170364 $smilElement = $j( smilElement );
 365+
171366 var smilAttributeToCss = {
172367 'backgroundColor' : 'background-color',
173368 'backgroundOpacity' : 'opacity',
@@ -175,15 +370,20 @@
176371 'height' : 'height',
177372 'top' : 'top',
178373 'right' : 'right',
179 - 'left' : 'left'
180 - }
 374+ 'left' : 'left',
 375+
 376+ 'textColor' : 'color',
 377+ 'textFontSize' : 'font-size',
 378+ 'textFontStyle' : 'font-style'
 379+ }
 380+
181381 var cssAttributes = {};
182 - // Map all the "smil" properties to css
183 - for( var attr in smilAttributeToCss ){
184 - if( $smilElement.attr( attr ) ){
185 - cssAttributes[ smilAttributeToCss[ attr ] ] = $smilElement.attr( attr );
 382+ for(var i =0; i < $smilElement[0].attributes.length; i++ ){
 383+ var attr = $smilElement[0].attributes[i];
 384+ if( smilAttributeToCss[ attr.nodeName ] ){
 385+ cssAttributes[ smilAttributeToCss[ attr.nodeName ]] = attr.nodeValue;
186386 }
187 - }
 387+ }
188388 // Translate rootLayout properties into div
189389 return cssAttributes;
190390 }
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/loader.js
@@ -3,7 +3,7 @@
44 */
55
66 mw.addClassFilePaths( {
7 - "mw.SmilHooks.js" : "mw.SmilHooks",
 7+ "mw.SmilHooks" : "mw.SmilHooks.js",
88
99 "mw.Smil" : "mw.Smil.js",
1010 "mw.SmilLayout" : "mw.SmilLayout.js",
@@ -12,18 +12,11 @@
1313 "mw.EmbedPlayerSmil" : "mw.EmbedPlayerSmil.js"
1414 } );
1515
16 -$j( mw ).bind( 'addElementWaitForMetaEvent', function( event, waitForMetaObject ) {
17 - // Tell embedPlayer ~not~ to wait for metadata in cases of smil documents
18 - if( mw.CheckElementForSMIL( waitForMetaObject[ 'playerElement' ] ) ){
19 - waitForMetaObject[ 'waitForMeta' ] = false;
20 - return false;
21 - }
22 -});
23 -
2416 // Add the mw.SmilPlayer to the embedPlayer loader:
2517 $j( mw ).bind( 'LoaderEmbedPlayerUpdateRequest', function( event, playerElement, classRequest ) {
2618
2719 var smilPlayerLibrarySet = [
 20+ "mw.SmilHooks",
2821 "mw.Smil",
2922 "mw.SmilLayout",
3023 "mw.SmilBody",
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.Smil.js
@@ -71,7 +71,10 @@
7272 this.layout = null;
7373
7474 // Clear out the body
75 - this.body = null;
 75+ this.body = null;
 76+
 77+ // Clear out the top level duration
 78+ this.duration = null;
7679 },
7780
7881 /**
@@ -81,30 +84,119 @@
8285 if( this.$dom ) {
8386 return this.$dom;
8487 }
85 - mw.log( "Error SMIL Dom not available " ) ;
 88+ mw.log( "Error SMIL Dom not available" ) ;
8689 return ;
8790 },
8891
8992 /**
90 - * Get the smil html at a given time
 93+ * Get the smil html at a given time
9194 * @param {object} size The target size width, height
9295 * @param {float} time The target time to be displayed
9396 */
9497 getHtmlDOM: function ( size, time ){
95 - if( !this.layout ){
96 - this.layout = new mw.SmilLayout( this.getDom().find( 'layout' ) );
97 - }
 98+ mw.log("getHtmlDOM:: " + size.width + ' time: ' + time);
 99+
 100+ // Have the layout object return the layout HTML DOM
 101+ return this.getLayout().getHtmlDOM( size, time );
 102+ },
 103+
 104+ /**
 105+ * Get the smil layout object, with reference to the body
 106+ */
 107+ getLayout: function() {
 108+ if( !this.layout ) {
 109+ this.layout = new mw.SmilLayout( this );
 110+ }
 111+ return this.layout;
 112+ },
 113+
 114+ /**
 115+ * Get the smil body object
 116+ */
 117+ getBody: function(){
98118 if( !this.body ){
99 - this.body = new mw.SmilBody( this.getDom().find( 'body' ) );
 119+ this.body = new mw.SmilBody( this );
100120 }
101 - // Get the layout DOM
102 - $layoutDOM = this.layout.getHtmlDOM( { 'width': size.width, 'height': size.height });
 121+ return this.body;
 122+ },
 123+
 124+ /**
 125+ * Get the duration form the
 126+ */
 127+ getDuration: function(){
 128+ // return 0 while we don't have the $dom loaded
 129+ if( !this.$dom ){
 130+ return 0;
 131+ }
103132
104 - mw.log( "mw.Smil :: getHtmlDOM :: " );
105 - // Have the body object update the layoutDOM for its given time.
106 - return this.body.updateLayout( $layoutDOM );
 133+ if( !this.duration ){
 134+ this.duration = this.getBody().getDuration();
 135+ }
 136+ return this.duration;
107137 }
108138 }
 139+/**
 140+ * Some Utility functions
 141+ */
109142
 143+/**
 144+ * Parse smil time function
 145+ * http://www.w3.org/TR/SMIL3/smil-timing.html#Timing-ClockValueSyntax
 146+ *
 147+ * Smil time has the following structure:
 148+ *
 149+ * Clock-value ::= ( Full-clock-value | Partial-clock-value | Timecount-value )
 150+ * Full-clock-value ::= Hours ":" Minutes ":" Seconds ("." Fraction)?
 151+ * Partial-clock-value ::= Minutes ":" Seconds ("." Fraction)?
 152+ * Timecount-value ::= Timecount ("." Fraction)? (Metric)?
 153+ * Metric ::= "h" | "min" | "s" | "ms"
 154+ * Hours ::= DIGIT+ // any positive number
 155+ * Minutes ::= 2DIGIT // range from 00 to 59
 156+ * Seconds ::= 2DIGIT // range from 00 to 59
 157+ * Fraction ::= DIGIT+
 158+ * Timecount ::= DIGIT+
 159+ * 2DIGIT ::= DIGIT DIGIT
 160+ * DIGIT ::= [0-9]
 161+ *
 162+ * @param {mixed} timeValue time value of smil structure
 163+ * @ return {float} Seconds from time value
 164+ */
 165+mw.SmilParseTime = function( timeValue ){
 166+ // If timeValue is already a number return seconds:
 167+ if( ! isNaN( timeValue ) ){
 168+ return parseFloat( timeValue );
 169+ }
 170+ // Trim whitespace
 171+ timeValue = $j.trim( timeValue );
110172
 173+ // First check for hh:mm:ss time:
 174+ if ( timeValue.split( ':' ).length == 3 || timeValue.split( ':' ).length == 2 ) {
 175+ return mw.npt2seconds( timeValue );
 176+ }
 177+
 178+ var timeFactor = null
 179+ // Check for metric hours
 180+ if( timeValue.substr( -1 ) == 'h' ){
 181+ timeFactor = 3600 ;
 182+ }
 183+ // Min metric
 184+ if( timeValue.substr( -3 ) == 'min' ){
 185+ timeFactor = 60;
 186+ }
 187+ // Seconds
 188+ if( timeValue.substr( -1 ) == 's'){
 189+ timeFactor = 1;
 190+ }
 191+ // Millaseconds
 192+ if( timeValue.substr( -2 ) == 'ms'){
 193+ timeFactor = .001;
 194+ }
 195+
 196+ if( timeFactor){
 197+ return parseFloat( parseFloat( timeValue ) * timeFactor );
 198+ }
 199+ mw.log("Error could not parse time: " + timeValue);
 200+}
 201+
 202+
111203
\ No newline at end of file
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/panzoom/Fruits-4s.smil.xml
@@ -0,0 +1,59 @@
 2+<?xml version="1.0" encoding="UTF-8"?>
 3+<smil baseProfile="Language" version="3.0" xmlns="http://www.w3.org/ns/SMIL">
 4+ <head>
 5+ <meta content="Pan and Zoom" name="title"/>
 6+ <meta content="dcab" name="author"/>
 7+ <meta content="Fri Sep 26 09:58:15 CEST 2008" name="date"/>
 8+ <layout>
 9+ <root-layout backgroundColor="green" height="800" width="500"/>
 10+ <region backgroundColor="green" height="700" top="50" left="50" width="400" xml:id="image_region"/>
 11+ <region xml:id="Title" height="25" width="300" left="100" top="10"/>
 12+ <region xml:id="Captions" height="70" width="300" left="100" top="510"/>
 13+ <region id="audio_region" soundLevel="100%"/>
 14+ </layout>
 15+ </head>
 16+ <body>
 17+ <par>
 18+
 19+ <smilText dur="25s" textFontSize="x-large" textFontWeight="normal" textColor="white" region="Title">
 20+ Tante Chris' Fruits
 21+ </smilText>
 22+
 23+ <img dur="25s" fill="freeze" fit="meet" id="image"
 24+ panZoom="0,0,100%,100%" region="image_region" src="fruitStand.jpg">
 25+
 26+ <animate attributeName="panZoom" begin="2.0"
 27+ dur="1.5s" fill="freeze" values="-1,4,99%,99%;511,509,47%,14%"/>
 28+ <animate attributeName="panZoom" begin="5.0"
 29+ dur="1.5s" fill="freeze" values="511,509,47%,14%;418,-3,34%,13%"/>
 30+ <animate attributeName="panZoom" begin="9.0"
 31+ dur="1.5s" fill="freeze" values="418,-3,34%,13%;9,1115,41%,20%"/>
 32+ <animate attributeName="panZoom" begin="13.0"
 33+ dur="1.5s" fill="freeze" values="9,1115,41%,20%;573,2073,64%,17%"/>
 34+ <animate attributeName="panZoom" begin="16.0"
 35+ dur="1.5s" fill="freeze" values="573,2073,64%,17%;1118,1365,14%,8%"/>
 36+ <animate attributeName="panZoom" begin="18.0"
 37+ dur="1.5s" fill="freeze" values="1118,1365,14%,8%;0,0,100%,100%"/>
 38+ </img>
 39+
 40+ <smilText dur="25s" textFontSize="large" textFontWeight="normal" textColor="white" region="Captions">
 41+ Clear Text Test
 42+ <clear begin="3s"/>
 43+ Today, we've got grapes....
 44+ <clear begin="6s"/>
 45+ and we have lemons....
 46+ <clear begin="10s"/>
 47+ and juicy, red ripe tomatos....
 48+ <clear begin="14s"/>
 49+ and tart mandrins ....
 50+ <tev begin="16s"/>
 51+ as well as squeeze-ready organges.
 52+ <clear begin="19s"/>
 53+<!-- The screen does not clear if there is no additional character text.... -->
 54+ .
 55+
 56+ </smilText>
 57+
 58+ </par>
 59+ </body>
 60+</smil>
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/panzoom/fruitStand.jpg
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/panzoom/fruitStand.jpg
___________________________________________________________________
Added: svn:mime-type
161 + application/octet-stream
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/PanZoom.html
@@ -0,0 +1,35 @@
 2+<!doctype html>
 3+<html>
 4+<head>
 5+ <title>Pan Zoom Example</title>
 6+ <script type="text/javascript" src="../../../mwEmbed.js?debug=true"></script>
 7+ <!-- <script type="text/javascript" src="../../jsScriptLoader.php?class=window.jQuery,mwEmbed&debug=true"></script> -->
 8+ <script type="text/javascript">
 9+ mw.setConfig( 'overlayControls', false );
 10+ </script>
 11+</head>
 12+<body>
 13+<h3>Sample playlist pan-zoom animation</h3>
 14+<table>
 15+<tr>
 16+<td>
 17+
 18+<video id="panzoom" type="application/smil" src="panzoom/Fruits-4s.smil.xml" width="400" height="400"></video>
 19+
 20+</td>
 21+<td valign="top">
 22+Sample playlist code:
 23+<div style="clear:both"></div>
 24+<textarea style="width:500px;">
 25+<video id="panzoom" type="application/smil" src="panzoom/Fruits-4s.smil.xml" width="400" height="300"></video>
 26+</textarea>
 27+<div style="clear:both"></div>
 28+
 29+SMIL Source:
 30+<div style="clear:both"></div>
 31+<iframe style="width:500px;height:300px" src="panzoom/Fruits-4s.smil.xml"></iframe>
 32+</td>
 33+</tr>
 34+</table>
 35+</body>
 36+</html>
Property changes on: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/PanZoom.html
___________________________________________________________________
Added: svn:mergeinfo
137 Merged /branches/REL1_15/phase3/js2/mwEmbed/tests/Playlist_Player.html:r51646
238 Merged /branches/sqlite/js2/mwEmbed/tests/Playlist_Player.html:r58211-58321
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/SmilPlayer.i8n.php
@@ -0,0 +1,12 @@
 2+<?php
 3+/**
 4+ * Internationalisation for EmbedPlayer
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+$messages['en'] = array(
 12+ "mwe-embedplayer-ogg-player-smilPlayer" => "Smil javascript player",
 13+);
Property changes on: branches/MwEmbedStandAlone/modules/SmilPlayer/SmilPlayer.i8n.php
___________________________________________________________________
Added: svn:executable
114 + *
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilHooks.js
@@ -0,0 +1,46 @@
 2+
 3+// Define the SmilHooks object
 4+mw.SmilHooks = {};
 5+
 6+// Add the smil player to available player types:
 7+$j( mw ).bind( 'EmbedPlayerManagerReady', function( event ) {
 8+
 9+ // Add the swarmTransport playerType
 10+ mw.EmbedTypes.players.defaultPlayers[ 'application/smil' ] = [ 'Smil' ];
 11+
 12+ // Build the swarm Transport "player"
 13+ var smilMediaPlayer = new mediaPlayer( 'smilPlayer', [ 'application/smil' ], 'Smil' );
 14+
 15+ // Add the swarmTransport "player"
 16+ mw.EmbedTypes.players.addPlayer( smilMediaPlayer );
 17+
 18+} );
 19+
 20+// Tell embedPlayer not to wait for height / width metadata in cases of smil documents
 21+$j( mw ).bind( 'addElementWaitForMetaEvent', function( event, waitForMetaObject ) {
 22+ if( mw.CheckElementForSMIL( waitForMetaObject[ 'playerElement' ] ) ){
 23+ waitForMetaObject[ 'waitForMeta' ] = false;
 24+ return false;
 25+ }
 26+});
 27+
 28+// Bind the smil check for sources
 29+$j( mw ).bind( 'newEmbedPlayerEvent', function( event, swapedPlayerId ) {
 30+ // Setup local reference to embedPlayer interface
 31+ var embedPlayer = $j( '#' + swapedPlayerId ).get(0);
 32+
 33+ // Setup the "embedCode" binding to swap in an updated url
 34+ $j( embedPlayer ).bind( 'checkPlayerSourcesEvent', function( event, callback ) {
 35+ mw.log(" smil enter checkPlayerSources");
 36+ // Get the first smil source:
 37+ mw.log(" SOURCE IS: " + embedPlayer.mediaElement.getSources( 'application/smil' )[0].getSrc() );
 38+ embedPlayer.smil = new mw.Smil();
 39+
 40+ // Load the smil url as part of "source check"
 41+ embedPlayer.smil.loadFromUrl( embedPlayer.mediaElement.getSources( 'application/smil' )[0].getSrc(), function(){
 42+ mw.log(" DONE LOAING SMIL FROM UDL");
 43+ callback();
 44+ });
 45+ } );
 46+});
 47+
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.EmbedPlayerSmil.js
@@ -2,6 +2,11 @@
33 /**
44 * Extends EmbedPlayer to wrap smil playback in the html5 video tag abstraction.
55 */
 6+
 7+//Get all our message text
 8+mw.includeAllModuleMessages();
 9+
 10+// Setup the EmbedPlayerSmil object:
611 mw.EmbedPlayerSmil = {
712
813 // Instance Name
@@ -9,13 +14,14 @@
1015
1116 // Player supported feature set
1217 supports: {
13 - 'play_head': true,
14 - 'pause': true,
15 - 'fullscreen': true,
16 - 'time_display': true,
17 - 'volume_control': true,
18 - 'overlays': true
19 - },
 18+ 'playHead' : true,
 19+ 'pause' : true,
 20+ 'fullscreen' : true,
 21+ 'timeDisplay' : true,
 22+ 'volumeControl' : true,
 23+
 24+ 'overlays' : true
 25+ },
2026
2127 /**
2228 * Put the embed player into the container
@@ -30,26 +36,46 @@
3137 'width' : '100%',
3238 'height' : '100%',
3339 'position' : 'relative'
34 - })
35 - .loadingSpinner()
36 - );
 40+ })
 41+ );
 42+ // Add a loading spinner if we don't already have one
 43+ /*if( $j('#loadingSpinner_' + this.id ).length ){
 44+ $j('#smilCanvas_' + this.id ).loadingSpinner();
 45+ }*/
3746
38 - // Create the smilPlayer
39 - this.smil = new mw.Smil();
40 -
41 - // Load the smil
42 - this.smil.loadFromUrl( this.getSrc(), function(){
 47+ // Update the embed player
 48+ this.getSmil( function( smil ){
4349 // XXX might want to move this into mw.SMIL
4450 $j( _this ).html(
45 - _this.smil.getHtmlDOM( {
 51+ smil.getHtmlDOM( {
4652 'width': _this.getWidth(),
4753 'height': _this.getHeight()
4854 } )
4955 )
50 - } );
 56+ });
5157
5258 },
5359
 60+ getSmil: function( callback ){
 61+ if( !this.smil ) {
 62+ // Create the Smil engine object
 63+ this.smil = new mw.Smil();
 64+
 65+ // Load the smil
 66+ this.smil.loadFromUrl( this.getSrc(), function(){
 67+ callback( this.smil );
 68+ });
 69+ } else {
 70+ callback( this.smil );
 71+ }
 72+ },
 73+
 74+ getDuration: function(){
 75+ if( this.smil ){
 76+ return this.smil.getDuration();
 77+ }
 78+ },
 79+
5480 /**
5581 * Return the virtual canvas element
5682 */
@@ -67,7 +93,7 @@
6894 this.parent_updateThumbnailHTML();
6995 return ;
7096 }
71 - // If no thumb could be gennerated use the first frame of smil:
 97+ // If no thumb could be generated use the first frame of smil:
7298 this.doEmbedPlayer();
7399 },
74100
Index: branches/MwEmbedStandAlone/mwEmbed.js
@@ -281,12 +281,12 @@
282282 * Using defined class names avoids loading the same class
283283 * twice by first checking if the "class variable" is defined
284284 *
285 - * {String} Absolute or relative to mwEmbed file path.
 285+ * {String} Absolute or relative to url path
286286 * The same file won't be loaded twice
287287 *
288288 * {Array} can be an array of any combination of the above strings.
289 - * Will be loaded in-order or in a single
290 - * script-loader request if scriptLoader is enabled
 289+ * Will be loaded in-order or in a single script-loader request
 290+ * if scriptLoader is available.
291291 *
292292 * {Array} {Array} Can be a set of Arrays for loading.
293293 * Some browsers execute included scripts out of order.
@@ -989,7 +989,7 @@
990990 * @param {String} [apiUrl] Optional target API URL (uses default local api if unset)
991991 * @param {String} title The wiki page title you want to edit
992992 * @param {callback} callback Function to pass the token to.
993 - * issues callback with "false" if token not retrived
 993+ * issues callback with "false" if token not retrieved
994994 */
995995 mw.getToken = function( apiUrl, title, callback ) {
996996 // Make the apiUrl be optional:
@@ -999,7 +999,7 @@
10001000 apiUrl = mw.getLocalApiUrl();
10011001 }
10021002
1003 - mw.log( 'mw:getToken' );
 1003+ mw.log( 'mw:getToken' );
10041004
10051005 var request = {
10061006 'prop': 'info',
@@ -1082,12 +1082,15 @@
10831083 * addLoaderDialog
10841084 * small helper for displaying a loading dialog
10851085 *
1086 - * @param {String} msg_txt text text of the loader msg
 1086+ * @param {String} dialogHtml text Html of the loader msg
10871087 */
1088 - mw.addLoaderDialog = function( msg_txt ) {
1089 - mw.addDialog( msg_txt, msg_txt + '<br>' +
1090 - $j('<div />').loadingSpinner().html()
 1088+ mw.addLoaderDialog = function( dialogHtml ) {
 1089+ $dialog = mw.addDialog( dialogHtml, dialogHtml + '<br>' +
 1090+ $j('<div />')
 1091+ .loadingSpinner()
 1092+ .html()
10911093 );
 1094+ return $dialog;
10921095 }
10931096
10941097 /**
@@ -1106,32 +1109,32 @@
11071110 return true;
11081111 }
11091112 return false;
1110 - },
 1113+ }
11111114
11121115 /**
11131116 * Add a (temporary) dialog window:
11141117 * @param {String} title Title string for the dialog
1115 - * @param {String} msg_html String to be inserted in msg box
 1118+ * @param {String} dialogHtml String to be inserted in msg box
11161119 * @param {Mixed} buttons A button object for the dialog
11171120 * Can be 'ok' for oky button.
11181121 */
1119 - mw.addDialog = function ( title, msg_html, buttons ) {
1120 - $j( '#mwe_tmp_loader' ).remove();
 1122+ mw.addDialog = function ( title, dialogHtml, buttons ) {
 1123+ $j( '#mwTempLoaderDialog' ).remove();
11211124 // Append the style free loader ontop:
11221125 $j( 'body' ).append(
11231126 $j('<div />')
11241127 .attr( {
1125 - 'id' : "mwe_tmp_loader",
 1128+ 'id' : "mwTempLoaderDialog",
11261129 'title' : title
11271130 })
11281131 .css('display', 'none')
1129 - .html( msg_html )
 1132+ .html( dialogHtml )
11301133 );
11311134 // Special buttons == ok gives empty give a single "oky" -> "close"
11321135 if ( buttons == 'ok' ) {
11331136 buttons = { };
11341137 buttons[ gM( 'mwe-ok' ) ] = function() {
1135 - $j( '#mwe_tmp_loader' ).close();
 1138+ $j( '#mwTempLoaderDialog' ).close();
11361139 }
11371140 }
11381141 // Load the dialog classes
@@ -1143,7 +1146,7 @@
11441147 '$j.ui.dialog'
11451148 ]
11461149 ], function() {
1147 - $j( '#mwe_tmp_loader' ).dialog( {
 1150+ $j( '#mwTempLoaderDialog' ).dialog( {
11481151 'bgiframe': true,
11491152 'draggable': false,
11501153 'resizable': false,
@@ -1152,6 +1155,7 @@
11531156 'buttons': buttons
11541157 } );
11551158 } );
 1159+ return $j( '#mwTempLoaderDialog' );
11561160 }
11571161
11581162 /**
@@ -1162,7 +1166,7 @@
11631167 if( !mw.isset( '$j.ui.dialog' ) ) {
11641168 return false;
11651169 }
1166 - $j( '#mwe_tmp_loader' ).dialog( 'destroy' ).remove();
 1170+ $j( '#mwTempLoaderDialog' ).dialog( 'destroy' ).remove();
11671171 }
11681172
11691173
@@ -1626,7 +1630,7 @@
16271631
16281632 /**
16291633 * Given seconds return array with 'days', 'hours', 'min', 'seconds'
1630 - * @param {float} sec Seconds to be converted into time mesurements
 1634+ * @param {float} sec Seconds to be converted into time measurements
16311635 */
16321636 mw.seconds2Measurements = function ( sec ){
16331637 var tm = {};
@@ -2261,6 +2265,37 @@
22622266 }
22632267
22642268 /**
 2269+ * Runs all the triggers on a given object with a single "callback"
 2270+ *
 2271+ * Normal tirgger calls will run the callback directly multiple times
 2272+ * for every binded function.
 2273+ *
 2274+ * With runTriggersCallback() callback is not called until all the
 2275+ * binded events have been run.
 2276+ *
 2277+ * @param {object} targetObject Target object to run triggers on
 2278+ * @param {string} triggerName Name of trigger to be run
 2279+ * @param {function} callback Function called once all triggers have been run
 2280+ *
 2281+ */
 2282+ mw.runTriggersCallback = function( targetObject, triggerName, callback ){
 2283+ // on trigger calls with many binded functions.
 2284+ if( ! $j( targetObject ).data( 'events' )[ triggerName ] ) {
 2285+ callback();
 2286+ }
 2287+ var callbackCount = $j( targetObject ).data( 'events' )[ triggerName ].length;
 2288+
 2289+ mw.log(" runTriggersCallback:: " + callbackCount );
 2290+ var callInx = 0;
 2291+ $j( targetObject ).trigger( 'checkPlayerSourcesEvent', function() {
 2292+ callInx++;
 2293+ if( callInx == callbackCount ){
 2294+ // Run callback
 2295+ callback();
 2296+ }
 2297+ } );
 2298+ }
 2299+ /**
22652300 * Utility jQuery bindings
22662301 * Setup after jQuery is available ).
22672302 */
@@ -2321,7 +2356,7 @@
23222357 // The text of the button link
23232358 'text' : '',
23242359
2325 - // The icon id that precceeds the button link:
 2360+ // The icon id that precedes the button link:
23262361 'icon_id' : 'carat-1-n'
23272362 };
23282363

Status & tagging log