r71153 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r71152‎ | r71153 | r71154 >
Date:07:38, 16 August 2010
Author:dale
Status:deferred
Tags:
Comment:
* ensure jquery.ui draggable data options exist before being called
* improved addMedia insert smilClip support
* refactored default config to separate file.
* improved timeline resize layout support
* fixed multi select bug for ctrlDown subselection
Modified paths:
  • /branches/MwEmbedStandAlone/libraries/jquery/jquery.ui/ui/ui.draggable.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/Sequencer.i18n.php (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/css/mw.style.Sequencer.css (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/loader.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.Sequencer.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerAddMedia.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerConfig.js (added) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerTimeline.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerTools.js (modified) (history)
  • /branches/MwEmbedStandAlone/mwEmbed.js (modified) (history)

Diff [purge]

Index: branches/MwEmbedStandAlone/mwEmbed.js
@@ -1038,22 +1038,15 @@
10391039 }
10401040
10411041 /**
1042 - * Mobile Safari has special properties for html5 video::
1043 - *
1044 - * NOTE: should be moved to browser detection script
 1042+ * Close the loader dialog created with addLoaderDialog
10451043 */
1046 - mw.isMobileSafari = function() {
1047 - // check mobile safari foce ( for debug )
1048 - if( mw.getConfig( 'forceMobileSafari' ) ){
1049 - return true;
 1044+ mw.closeLoaderDialog = function() {
 1045+ // Make sure the dialog resource is present
 1046+ if( !mw.isset( '$j.ui.dialog' ) ) {
 1047+ return false;
10501048 }
1051 - if ((navigator.userAgent.indexOf('iPhone') != -1) ||
1052 - (navigator.userAgent.indexOf('iPod') != -1) ||
1053 - (navigator.userAgent.indexOf('iPad') != -1)) {
1054 - return true;
1055 - }
1056 - return false;
1057 - }
 1049+ $j( '#mwTempLoaderDialog' ).dialog( 'destroy' ).remove();
 1050+ }
10581051
10591052 /**
10601053 * Add a (temporary) dialog window:
@@ -1127,20 +1120,26 @@
11281121 $j( '#mwTempLoaderDialog' ).dialog( options );
11291122 } );
11301123 return $j( '#mwTempLoaderDialog' );
1131 - }
 1124+ }
11321125
11331126 /**
1134 - * Close the loader dialog created with addLoaderDialog
 1127+ * Mobile Safari has special properties for html5 video::
 1128+ *
 1129+ * NOTE: should be moved to browser detection script
11351130 */
1136 - mw.closeLoaderDialog = function() {
1137 - // Make sure the dialog resource is present
1138 - if( !mw.isset( '$j.ui.dialog' ) ) {
1139 - return false;
 1131+ mw.isMobileSafari = function() {
 1132+ // check mobile safari foce ( for debug )
 1133+ if( mw.getConfig( 'forceMobileSafari' ) ){
 1134+ return true;
11401135 }
1141 - $j( '#mwTempLoaderDialog' ).dialog( 'destroy' ).remove();
 1136+ if ((navigator.userAgent.indexOf('iPhone') != -1) ||
 1137+ (navigator.userAgent.indexOf('iPod') != -1) ||
 1138+ (navigator.userAgent.indexOf('iPad') != -1)) {
 1139+ return true;
 1140+ }
 1141+ return false;
11421142 }
11431143
1144 -
11451144 /**
11461145 * Similar to php isset function checks if the variable exists. Does a safe
11471146 * check of a descendant method or variable
@@ -1796,13 +1795,15 @@
17971796
17981797 /**
17991798 * getAbsoluteUrl takes a src and returns the absolute location given the
1800 - * document.URL
 1799+ * document.URL or a contextUrl param
18011800 *
1802 - * @param {String}
1803 - * src path or url
 1801+ * @param {String} src path or url
 1802+ * @param {String} contextUrl The domain / context for creating an absolute url
 1803+ * from a relative path
18041804 * @return {String} absolute url
18051805 */
18061806 mw.absoluteUrl = function( src, contextUrl ) {
 1807+
18071808 var parsedSrc = mw.parseUri( src );
18081809 // Source is already absolute return:
18091810 if( parsedSrc.protocol != '') {
@@ -1810,7 +1811,7 @@
18111812 }
18121813
18131814 // Get parent Url location the context URL
1814 - if( contextUrl) {
 1815+ if( contextUrl ) {
18151816 var parsedUrl = mw.parseUri( contextUrl );
18161817 } else {
18171818 var parsedUrl = mw.parseUri( document.URL );
Index: branches/MwEmbedStandAlone/modules/Sequencer/loader.js
@@ -5,12 +5,12 @@
66 // Wrap in mw to not pollute global namespace
77 ( function( mw ) {
88
9 - mw.addResourcePaths( {
10 - "mw.Sequencer" : "mw.Sequencer.js",
11 -
 9+ mw.addResourcePaths( {
1210 "mw.Sequencer" : "mw.Sequencer.js",
1311 "mw.style.Sequencer" : "mw.style.Sequencer.css",
1412
 13+ "mw.SequencerConfig" : "mw.SequencerConfig.js",
 14+
1515 "mw.SequencerAddMedia" : "mw.SequencerAddMedia.js",
1616 "mw.SequencerPlayer" : "mw.SequencerPlayer.js",
1717 "mw.SequencerTimeline" : "mw.SequencerTimeline.js",
@@ -32,15 +32,6 @@
3333
3434 } );
3535
36 - mw.setDefaultConfig({
37 - // If the sequencer should attribute kaltura
38 - "Sequencer.KalturaAttribution" : true,
39 -
40 - // The size of the undo stack
41 - "Sequencer.numberOfUndos" : 100
42 - })
43 -
44 -
4536 /**
4637 * The FirefoggRender sub module
4738 */
@@ -57,8 +48,9 @@
5849 // Make sure we have the required mwEmbed libs:
5950 return [
6051 [ // Load the EmbedPlayer Module ( includes lots of dependent classes )
61 - 'EmbedPlayer',
62 - 'mw.Sequencer'
 52+ 'EmbedPlayer',
 53+ 'mw.Sequencer',
 54+ 'mw.SequencerConfig'
6355 ],
6456 [
6557 '$j.contextMenu',
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.Sequencer.js
@@ -228,7 +228,7 @@
229229
230230 /* timeline container */
231231 'south__minSize' : 160,
232 - 'south__size' : 150,
 232+ 'south__size' : 200,
233233 'south__onresize' : function(){
234234 _this.getTimeline().resizeTimeline();
235235 }
Index: branches/MwEmbedStandAlone/modules/Sequencer/css/mw.style.Sequencer.css
@@ -6,7 +6,7 @@
77 top: 4px;
88 left:4px;
99 right: 4px;
10 - bottom: 4px;
 10+
1111 }
1212
1313 .mwe-sequencer .trackNameContainer{
@@ -28,7 +28,6 @@
2929 }
3030
3131 .mwe-sequencer .trackNames{
32 - height: 100px;
3332 background-color: #EEE;
3433 border: solid thin #999;
3534 padding:4px
@@ -56,14 +55,18 @@
5756 background-color:#6F6;
5857 border:2px dashed #000;
5958 }
60 -.mwe-sequencer .timelineClip:hover{
 59+.mwe-sequencer .timelineClip:hover{
6160 border: 2px solid #66F;
6261 }
6362 .mwe-sequencer .selectedClip{
64 - border: 2px solid #F66;
 63+ margin-top: 1px;
 64+ margin-left: 1px;
 65+ border: 4px solid #F66;
6566 }
6667 .mwe-sequencer .selectedClip:hover{
67 - border: 2px solid #F22;
 68+ margin-top: 1px;
 69+ margin-left: 1px;
 70+ border: 4px solid #F22;
6871 }
6972
7073 .mwe-sequencer .trimStartThumb, .trimEndThumb {
Index: branches/MwEmbedStandAlone/modules/Sequencer/Sequencer.i18n.php
@@ -11,6 +11,7 @@
1212 'mwe-sequencer-loading-timeline' => 'Loading timeline ...',
1313 'mwe-sequencer-loading-player' => 'Loading player ...',
1414 'mwe-sequencer-loading-menu' => 'Loading menu ...',
 15+ 'mwe-sequencer-loading-asset' => 'Loading asset ...',
1516
1617 'mwe-sequencer-no_selected_resource' => '<h3>No resource selected</h3> Select a clip to enable editing.',
1718 'mwe-sequencer-no-sequence-start-new' => 'Empty sequence, [$1 browser for assets] to create a new sequence',
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerAddMedia.js
@@ -10,10 +10,12 @@
1111 };
1212
1313 // Set up the mvSequencer object
14 -mw.SequencerAddMedia.prototype = {
 14+mw.SequencerAddMedia.prototype = {
 15+
1516 init: function( sequencer ){
1617 this.sequencer = sequencer;
1718 },
 19+
1820 // Get the menu widget that drives the search and upload tab selection
1921 getMenuWidget: function(){
2022 var _this = this;
@@ -48,7 +50,7 @@
4951 return false;
5052 }),
5153
52 - //input button
 54+ // Input button
5355 $j.button({
5456 // The text of the button link
5557 'text' : gM('mwe-sequencer-get-media'),
@@ -74,7 +76,7 @@
7577 .empty()
7678 .loadingSpinner();
7779
78 - if( ! this.remoteSearchDriver ){
 80+ if( ! _this.remoteSearchDriver ){
7981 // set the tool target to loading
8082 mw.load( 'AddMedia.addMediaWizard', function(){
8183 _this.remoteSearchDriver = new mw.RemoteSearchDriver({
@@ -83,19 +85,26 @@
8486 'displaySearchInput': false,
8587 'default_query' : inputValue,
8688 'displayResourceInfoIcons' : false,
87 - 'resourceSelectionCallback' : function( resource ){
88 - _this.insertResourceDialog( resource )
 89+ 'resourceSelectionCallback' : function( resource ){
 90+ mw.addLoaderDialog( gM( 'mwe-sequencer-loading-asset' ) );
 91+ // Get convert resource to smilClip and insert into the timeline
 92+ _this.getSmilClipFromResource( resource, function( smilClip ) {
 93+ _this.sequencer.getTimeline().insertSmilClipEdit( smilClip );
 94+ mw.closeLoaderDialog();
 95+ });
8996 return false;
9097 },
9198 'displaySearchResultsCallback' : function(){
9299 _this.addSearchResultsDrag();
93100 }
94 - })
95 - .createUI()
 101+ });
 102+ // Create the search user interface:
 103+ _this.remoteSearchDriver.createUI();
96104 });
97105 } else {
98106 this.remoteSearchDriver.createUI()
99107 }
 108+
100109 },
101110 /**
102111 * Get the resource object from a provided asset
@@ -136,77 +145,82 @@
137146 revert: 'invalid'
138147 });
139148 },
140 - insertAssetDialog: function( assetElement, sequenceTrack, order ){
141 - this.insertResourceDialog(
142 - this.getResourceFromAsset( assetElement ),
143 - sequenceTrack,
144 - order
145 - );
 149+
 150+ /**
 151+ * Take a dom element asset from search results and
 152+ * convert to a smil ref node that can be inserted into
 153+ * a smil xml tree
 154+ */
 155+ getSmilClipFromAsset: function( assetElement, callback ){
 156+ var resource = this.getResourceFromAsset( assetElement )
 157+ this.getSmilClipFromResource ( resource, callback );
146158 },
147159 /**
148 - * Create an insert resource dialog, expose basic in-out points or / duration
149 - * xxx todo if resource needs to be imported run import dialog from remoteResourceDrive
150 - * buttons include insert at end or insert after current
 160+ * Take an addMedia 'resource' and convert to a smil
 161+ * ref node that can be inserted into a smil xml tree
151162 */
152 - insertResourceDialog: function( resource, sequenceTrack, order ){
153 - var buttons = {};
154 - var cat = resource;
155 - debugger;
156 - // Get an xml smil ref pointer: ( per the supplied content type )
157 - var smilRef = this.getSmilRefFromResource( resource );
158 -
159 - // Build out the resource dialog content:
160 - var $content =
161 - $j('<div />').append(
162 - $j('<div />')
163 - .addClass( 'sequencerEditTools' )
164 - .css({
165 - 'width' : '50%',
166 - 'height' : '100%',
167 - 'overflow': 'auto',
168 - 'position' : 'absolute',
169 - 'top' : '0px',
170 - 'left': '0px'
171 - }),
172 -
173 - $j('<div />')
174 - .css({
175 - 'position' : 'absolute'
176 - 'top' : '0px',
177 - 'right': '0px',
178 - 'width' : '50%',
179 - 'height' : '100%'
180 - })
181 - .append(
182 - // the div
183 - )
184 - )
185 - // Build out the edit tools
186 - $content.find( '.sequencerEditTools' )
 163+ getSmilClipFromResource: function( resource, callback ){
 164+ var tagType = 'ref';
 165+ if( resource.mime.indexOf( 'image/' ) != -1 ){
 166+ tagType = 'img';
 167+ }
 168+ if( resource.mime.indexOf( 'video/') != -1 ){
 169+ tagType = 'video';
 170+ }
 171+ if( resource.mime.indexOf( 'audio/') != -1 ){
 172+ tagType = 'audio';
 173+ }
 174+ var $smilRef = $j( '<' + tagType + ' />')
187175
188 - // Insert after last selected clip ( or at end )
189 - buttons[ gM('mwe-sequencer-insert') ] = function() {
190 - // call a function that inserts into smil and timeline ( getTimeline() )
191 - alert(' insert resource')
 176+ // Set the default duration
 177+ if( tagType == 'img' ){
 178+ $smilRef.attr( 'dur', mw.getConfig( 'Sequencer.AddMediaImageDuration' ) );
192179 }
193 - // cancel
194 - buttons[ gM('mwe-cancel') ] = function(){
195 - $j( this ).dialog( 'close' );
196 - };
197 -
198 - mw.addDialog({
199 - 'title' : gM('mwe-sequencer-insert-resource'),
200 - 'dragable' : true,
201 - 'height' : 480,
202 - 'width' : 800,
203 - 'resizable' : true,
204 - 'content' : resourceEdit.getUi()
205 - 'buttons' : buttons
206 - });
207 - },
208 -
209 - getSmilRefFromResource: function( resource ){
210 -
 180+
 181+ // Set all available params
 182+ var resourceAttributeMap = {
 183+ 'type' : 'mime',
 184+ 'title' : 'title',
 185+ 'src' : 'src',
 186+ 'poster' : 'poster'
 187+ }
 188+ for( var i in resourceAttributeMap ){
 189+ if( resource[i] ){
 190+ $smilRef.attr( resourceAttributeMap[i], resource[i] );
 191+ }
 192+ }
 193+ var resourceParamMap = {
 194+ 'content_provider_id' : 'apiProvider',
 195+ 'id' : 'apiTitleKey'
 196+ }
 197+ for( var i in resourceParamMap ){
 198+ if( resource[i] ){
 199+ $smilRef.append(
 200+ $j( '<param />')
 201+ .attr({
 202+ 'name' : resourceParamMap[i],
 203+ 'value' : resource[i]
 204+ })
 205+ )
 206+ }
 207+ }
 208+ // Make sure we have source for the asset.
 209+ if( $smilRef.attr('src') ){
 210+ callback( $smilRef.get(0) )
 211+ } else {
 212+ // the resource includes a pointer to its parent search object
 213+ // from the search object grab the image object for the target resolution
 214+ resource.pSobj.getImageObj(
 215+ resource,
 216+ {
 217+ 'width' : mw.getConfig( 'Sequencer.AddMediaImageWidth' )
 218+ },
 219+ function( imageObj ){
 220+ $smilRef.attr('src', imageObj.url )
 221+ callback( $smilRef.get(0) );
 222+ }
 223+ )
 224+ }
211225 }
212226 }
213227
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerTools.js
@@ -68,6 +68,7 @@
6969 'title' : gM('mwe-sequencer-preview'),
7070 'action': function( _this, smilClip, toolId ){
7171 _this.sequencer.getPlayer().previewClip( smilClip );
 72+ // xxx todo update preview button to "pause" / "play"
7273 }
7374 },
7475 'cancel':{
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerConfig.js
@@ -0,0 +1,32 @@
 2+/**
 3+ * Master default configuration for sequencer
 4+ *
 5+ * Do not modify this file rather after including mwEmbed
 6+ * set any of these configuration values via
 7+ * the mw.setConfig() method
 8+ *
 9+ */
 10+
 11+// Define the class name
 12+mw.SequencerConfig = true;
 13+
 14+mw.setDefaultConfig({
 15+ // If the sequencer should attribute kaltura
 16+ "Sequencer.KalturaAttribution" : true,
 17+
 18+ // The size of the undo stack
 19+ "Sequencer.numberOfUndos" : 100,
 20+
 21+ // Default image duration
 22+ "Sequencer.AddMediaImageDuration" : 2,
 23+
 24+ // Default image source width
 25+ "Sequencer.AddMediaImageWidth" : 640,
 26+
 27+ // Default timeline "video / image" clip thumb size
 28+ "Sequencer.TimelineVideoThumbSize" : 100,
 29+
 30+ // Default timeline "audio / collapsed" size
 31+ "Sequencer.TimelineVideoThumbSize" : 30
 32+})
 33+
\ No newline at end of file
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerTimeline.js
@@ -1,5 +1,5 @@
22
3 -//Wrap in mw closure to avoid global leakage
 3+// Wrap in mw closure to avoid global leakage
44 ( function( mw ) {
55
66 mw.SequencerTimeline = function( sequencer ) {
@@ -11,7 +11,7 @@
1212 // Lazy init $timelineTracksContainer
1313 $timelineTracksContainer : null,
1414
15 - // store a pointer to the track layout
 15+ // Pointer to the track layout
1616 trackLayout: null,
1717
1818 //Default height width of timeline clip:
@@ -27,6 +27,7 @@
2828 getTimelineContainer: function(){
2929 return this.sequencer.getContainer().find('.mwseq-timeline');
3030 },
 31+
3132 /**
3233 * xxx needs to support multiple tracks
3334 */
@@ -43,9 +44,10 @@
4445 $j('<div />')
4546 .addClass( 'ui-layout-center clipTrackSetContainer')
4647 )
 48+ .css( 'height', this.getTimelineContainerHeight() )
4749 )
4850 // Apply layout control to track name / clipTrackSet division
49 - this.getTimelineContainer().find( '.timelineTrackContainer')
 51+ this.trackLayout = this.getTimelineContainer().find( '.timelineTrackContainer')
5052 .layout( {
5153 'applyDefaultStyles': true,
5254 'west__size' : 150,
@@ -56,61 +58,82 @@
5759 return this.getTimelineContainer().find( '.timelineTrackContainer');
5860 },
5961 resizeTimeline: function(){
60 - this.getTimelineContainer().find( '.timelineTrackContainer').resizeAll();
 62+ this.trackLayout.resizeAll();
6163 },
 64+ getTimelineContainerHeight: function(){
 65+ var timelineHeight = 0;
 66+ var smilSequenceTracks = this.sequencer.getSmil().getBody().getSeqElements();
 67+ $j.each(smilSequenceTracks, function( trackIndex, smilSequenceTrack ){
 68+ _this.drawSequenceTrack( trackIndex, smilSequenceTrack );
 69+ })
 70+ },
 71+ // Get the selected sequence track index ( for now its always zero )
 72+ getSelectedTrackIndex: function(){
 73+ return 0;
 74+ },
6275
6376 // Draw the timeline
64 - drawTimeline: function(){
 77+ drawTimeline: function(){
 78+ var _this = this;
6579 // xxx TODO support multiple tracks :::
66 - var seqTracks = this.sequencer.getSmil().getBody().getSeqElements();
67 - // For now just one video track:
68 - this.drawSequenceTrack( 0, seqTracks[ 0 ], 'video');
 80+ var smilSequenceTracks = this.sequencer.getSmil().getBody().getSeqElements();
 81+
 82+ // Draw all the tracks
 83+ $j.each(smilSequenceTracks, function( trackIndex, smilSequenceTrack ){
 84+ _this.drawSequenceTrack( trackIndex, smilSequenceTrack );
 85+ })
6986 },
7087
71 - drawSequenceTrack: function( trackIndex, sequenceNode, trackType ){
 88+ drawSequenceTrack: function( trackIndex, smilSequenceTrack ){
7289 var _this = this;
 90+ // Tracks by default are video tracks
 91+ var trackType = ( $j( smilSequenceTrack ).attr('tracktype') ) ? $j ( smilSequenceTrack ).attr('tracktype') : 'video'
7392 mw.log("SequenceTimeline::drawSequenceTrack: Track inx: " + trackIndex + ' trackType:' + trackType );
7493 // Check if we already have a container for this track set
7594
76 - // Add / update the sequence track name if not present
77 - // xxx check for specific sequenceTrack updates that require interface update
78 - if( this.getTracksContainer().find('.trackNamesContainer').children().length == 0 ){
79 - this.getTracksContainer().find('.trackNamesContainer').append(
80 - this.getTrackNameInterface( trackIndex, sequenceNode, trackType )
 95+ // Add sequence track name if not present
 96+ var $clipTrackName = $j( '#' + this.getTrackNameInterfaceId( trackIndex ) );
 97+ if( $clipTrackName.length == 0 ) {
 98+ $clipTrackName = this.getTracksContainer().find('.trackNamesContainer').append(
 99+ this.getTrackNameInterface( trackIndex, smilSequenceTrack, trackType )
81100 )
82 - };
83 - // Add Sequence track clips
84 - // xxx check for specific sequenceTrack updates that require interface update
85 - this.drawTrackClipsInterface( trackIndex ,sequenceNode , trackType );
 101+ }
 102+ // xxx check for specific smilSequenceTrack updates that require TrackNameInterface update
 103+
 104+
 105+ // Add Sequence track container if not present
 106+ var $clipTrackSet = $j( '#' + this.getTrackSetId( trackIndex ))
 107+ if( $clipTrackSet.length == 0 ) {
 108+ $clipTrackSet = this.getTracksContainer().find('.clipTrackSetContainer').append(
 109+ this.getClipTrackSet( trackIndex )
 110+ ).find( '.clipTrackSet');
 111+ }
 112+ // Draw sequence track clips ( checks for dom updates to smilSequenceTrack )
 113+ this.drawTrackClipsInterface( $clipTrackSet, smilSequenceTrack , trackType );
86114 },
87115
88116 /**
89117 * add Track Clips and Interface binding
90118 */
91 - drawTrackClipsInterface: function( trackIndex, sequenceNode, trackType ){
 119+ drawTrackClipsInterface: function( $clipTrackSet, smilSequenceTrack, trackType ){
92120 var _this = this;
 121+ mw.log( '')
93122 // Setup a local pointer to the smil engine:
94123 var smil = this.sequencer.getSmil();
95 -
96 - var $clipTrackSet = this.getTracksContainer().find('.clipTrackSetContainer').find( '.clipTrackSet' );
97 - // Add the $clipTrackSet if not already in dom:
98 - if( $clipTrackSet.length == 0 ){
99 - $clipTrackSet = this.getTracksContainer().find('.clipTrackSetContainer').append(
100 - this.getClipTrackSet( trackIndex )
101 - ).find( '.clipTrackSet');
102 - }
 124+
103125 var $previusClip = null;
104126
105127 var seqOrder = 0;
106128 var reOrderTimelineFlag = false;
107129
108 - // Get all the refs that are children of the sequenceNode with associated offsets and durations
 130+ // Get all the refs that are children of the smilSequenceTrack with associated offsets and durations
109131 // for now assume all tracks start at zero time:
110132 var startOffset = 0;
111 - smil.getBody().getRefElementsRecurse( sequenceNode, startOffset, function( $node ){
 133+ smil.getBody().getRefElementsRecurse( smilSequenceTrack, startOffset, function( $node ){
112134 var reRenderThumbFlag = false;
 135+ mw.log("ADD: " + _this.getTimelineClipId( $node ) + ' to ' + $clipTrackSet.attr('id') );
113136 // Draw the node onto the timeline if the clip is not already there:
114 - var $timelineClip = $clipTrackSet.find('#' + _this.getTimelineClipId( $node ) )
 137+ var $timelineClip = $clipTrackSet.find( '#' + _this.getTimelineClipId( $node ) )
115138 if( $timelineClip.length == 0 ){
116139 $timelineClip = _this.getTimelineClip( $clipTrackSet, $node );
117140 if( $previusClip ){
@@ -152,7 +175,7 @@
153176 // Check if we need to re-sort the list
154177 if( reOrderTimelineFlag ){
155178 // move every node in-order to the end.
156 - smil.getBody().getRefElementsRecurse( sequenceNode, startOffset, function( $node ){
 179+ smil.getBody().getRefElementsRecurse( smilSequenceTrack, startOffset, function( $node ){
157180 var $timelineClip = $clipTrackSet.find('#' + _this.getTimelineClipId( $node ) )
158181 $timelineClip.appendTo( $clipTrackSet );
159182 });
@@ -160,9 +183,8 @@
161184 $clipTrackSet.children().each(function (inx, clip){
162185 $j( clip ).data('indexOrder', inx);
163186 });
164 - }
 187+ }
165188
166 -
167189 // Give the track set a width relative to the number of clips
168190 $clipTrackSet.css('width', ($clipTrackSet.find( '.timelineClip' ).length + 1) *
169191 ( this.timelineThumbSize.width + 12 )
@@ -258,9 +280,9 @@
259281 editClip: function( selectedClip ){
260282 var smil = this.sequencer.getSmil();
261283 // get the smil element for the edit tool:
262 - var smilClip = smil.$dom.find('#' + $j( selectedClip ).data('smilId') );
 284+ var smilClip = smil.$dom.find( '#' + $j( selectedClip ).data('smilId') );
263285 var toolTarget = this.sequencer.getEditToolTarget();
264 - this.sequencer.getEditTools().drawClipEditTools( toolTarget, previewTarget, smilClip );
 286+ this.sequencer.getEditTools().drawClipEditTools( toolTarget, smilClip );
265287 },
266288
267289 /**
@@ -285,15 +307,79 @@
286308 },
287309
288310 /**
289 - * handles assets dropped into the timeline
 311+ * Handles assets dropped into the timeline
 312+ * xxx TODO right now hard coded to "AddMedia" but eventually we
 313+ * want to support desktop drag and drop
290314 */
291315 handleDropAsset: function( asset ){
 316+ var _this = this;
292317 // Get the newAsset resource object
293318 var clipIndex = $j( asset ).index();
294 - var trackIndex = $j( asset ).parent().data('trackIndex);
295 - this.sequencer.getAddMedia().insertAssetDialog( asset, trackIndex, clipIndex );
 319+ // Get the trackIndex for target track
 320+ var trackIndex = $j( asset ).parent().data( 'trackIndex' );
 321+
 322+ mw.addLoaderDialog( gM( 'mwe-sequencer-loading-asset' ) );
 323+
 324+ this.sequencer.getAddMedia().getSmilClipFromAsset( asset, function( smilClip ){
 325+ $j( asset ).remove();
 326+ _this.insertSmilClipEdit( smilClip, trackIndex, clipIndex );
 327+ mw.closeLoaderDialog();
 328+ });
296329 },
297330
 331+ /**
 332+ * Insert a smilClip to the smil dom and sequencer and display the edit
 333+ * interface with a 'cancel' insert button
 334+ */
 335+ insertSmilClipEdit: function( smilClip, trackIndex, clipIndex ){
 336+ // Handle optional arguments
 337+ if( typeof trackIndex != 'undefined' ){
 338+ trackIndex = this.getSelectedTrackIndex();
 339+ }
 340+ var $clipTrackSet = $j( '#' + this.getTrackSetId( trackIndex ) );
 341+ if( $clipTrackSet.length == 0 ){
 342+ mw.log( "Error: insertSmilClipEdit could not find track " + trackIndex + " in inteface" );
 343+ return ;
 344+ }
 345+
 346+ // Before insert ensure the smilClip has an id:
 347+ this.sequencer.getSmil().getBody().assignIds( $j( smilClip ) );
 348+
 349+ // Add the smil resource to the smil track
 350+ var $smilSequenceTrack = $j( this.sequencer.getSmil().getBody().getSeqElements()[ trackIndex ] );
 351+ if( typeof clipIndex == 'undefined' || clipIndex >= $smilSequenceTrack.children().length ){
 352+ $smilSequenceTrack.append(
 353+ $j( smilClip ).get(0)
 354+ )
 355+ } else {
 356+ $smilSequenceTrack.children().eq( clipIndex ).before(
 357+ $j( smilClip ).get(0)
 358+ )
 359+ }
 360+
 361+ // Update the dom timeline
 362+ this.drawTimeline();
 363+
 364+ // Invalidate / update embedPlayer duration / clip offsets
 365+ this.sequencer.getEmbedPlayer().getDuration( true );
 366+
 367+ // Register the insert edit action
 368+ _this.sequencer.getActionsEdit().registerEdit();
 369+
 370+ // Select the current clip
 371+ var $timelineClip = $clipTrackSet.find('#' + this.getTimelineClipId( smilClip ) )
 372+ if( $timelineClip.length == 0 ){
 373+ mw.log("Error: insertSmilClipEdit: could not find clip: " + this.getTimelineClipId( smilClip ) );
 374+ }
 375+ this.getTimelineContainer().find( '.selectedClip' ).removeClass( 'selectedClip' );
 376+ $timelineClip.addClass( 'selectedClip' );
 377+ // Seek to the added clip
 378+ this.seekToStartOfClip( $timelineClip );
 379+
 380+ // Display the edit interface with 'special' cancel button
 381+ this.editClip( $timelineClip );
 382+ },
 383+
298384 handleReorder: function ( movedClip ){
299385 var _this = this;
300386 var smil = this.sequencer.getSmil();
@@ -340,6 +426,7 @@
341427 // Register the edit state for undo / redo
342428 _this.sequencer.getActionsEdit().registerEdit();
343429 },
 430+
344431 /**
345432 * Handle multiple selections based on what clips was just "cliked"
346433 */
@@ -351,7 +438,13 @@
352439
353440
354441 // Add the selectedClip class to the clickClip
355 - if( $j( clickClip ).hasClass( 'selectedClip') && $target.find( '.selectedClip' ).length == 1 ){
 442+ if( $j( clickClip ).hasClass( 'selectedClip') &&
 443+ (
 444+ $target.find( '.selectedClip' ).length == 1
 445+ ||
 446+ keyBindings.ctrlDown
 447+ )
 448+ ){
356449 $j( clickClip ).removeClass( 'selectedClip' );
357450 }else {
358451 $j( clickClip ).addClass( 'selectedClip' );
@@ -367,11 +460,9 @@
368461 }
369462 } );
370463 }
 464+
371465 // Seek to the current clip time ( startOffset of current )
372 - var seekTime = smil.$dom.find('#' + $j( clickClip ).data('smilId') ).data( 'startOffset' )
373 - embedPlayer.setCurrentTime( seekTime, function(){
374 - mw.log("handleMultiSelect::seek done")
375 - });
 466+ this.seekToStartOfClip( clickClip );
376467
377468 // if shift select is down select the in-between clips
378469 if( keyBindings.shiftDown ){
@@ -400,6 +491,20 @@
401492 // xxx check if selected clip has changed hide tool edit interface
402493 },
403494
 495+ /**
 496+ * Seek to the start of a given timelineClip
 497+ */
 498+ seekToStartOfClip: function( timelineClip ){
 499+ var seekTime = this.sequencer
 500+ .getSmil()
 501+ .$dom.find( '#' + $j( timelineClip ).data('smilId') )
 502+ .data( 'startOffset' );
 503+
 504+ this.sequencer.getEmbedPlayer().setCurrentTime( seekTime, function(){
 505+ mw.log("handleMultiSelect::seek done")
 506+ });
 507+ },
 508+
404509 getTimelineClipId: function( $node ){
405510 return this.sequencer.getSmil().getPageDomId( $node ) + '_timelineClip';
406511 },
@@ -429,7 +534,7 @@
430535 .addClass( 'clipEditLink ui-state-default ui-corner-all' )
431536 .append(
432537 $j('<span />')
433 - .addClass( 'ui-icon ui-icon-scissors' )
 538+ .addClass( 'ui-icon ui-icon-wrench' )
434539 )
435540 .hide()
436541 .buttonHover()
@@ -453,10 +558,9 @@
454559 )
455560 .hide()
456561 .buttonHover()
457 - .click( function(){
458 - // de-select any other selected clips
459 - _this.getTimelineContainer().removeClass( 'selectedClip' );
460 - // add the selected clip class to the current:
 562+ .click( function(){
 563+ // Remove the associated clip:
 564+ _this.getTimelineContainer().removeClass( 'selectedClip' );
461565 $timelineClip.addClass( 'selectedClip' );
462566 _this.removeSelectedClips();
463567 })
@@ -512,44 +616,47 @@
513617 * features to add :: expand collapse, hide, mute etc.
514618 * for now just audio or video with icon
515619 */
516 - getTrackNameInterface: function( trackIndex, sequenceNode, trackType ){
517 - var $trackNameInterface =
 620+ getTrackNameInterface: function( trackIndex, smilSequenceTrack ){
 621+ var $trackNameContainer = $j('<div />')
 622+ .attr('id', this.getTrackNameInterfaceId( trackIndex ) )
 623+ .addClass('trackNames ui-corner-all')
 624+
 625+ var $trackNameTitle =
518626 $j('<a />')
519627 .attr('href','#')
520 - .addClass( "ui-icon_link" );
521 - if( trackType == 'video'){
522 - $trackNameInterface.append(
523 - $j('<span />').addClass( 'ui-icon ui-icon-video'),
524 - $j('<span />').text( gM( 'mwe-sequencer-video-track' ) )
525 - )
 628+ .addClass( "ui-icon_link" );
 629+ if( $j( smilSequenceTrack).attr('tracktype') == 'audio' ){
 630+ $trackNameTitle.append(
 631+ $j('<span />').addClass( 'ui-icon ui-icon-volume-on'),
 632+ $j('<span />').text( gM( 'mwe-sequencer-audio-track' ) )
 633+ )
 634+ $trackNameContainer.css( 'height' , '30px' );
526635 } else {
527 - $trackNameInterface.append(
528 - $j('<span />').addClass( 'ui-icon ui-icon-volume-on'),
529 - $j('<span />').text( gM( 'mwe-sequencer-audio-track' ) )
530 - )
 636+ // for now default to "video" tracktype
 637+ $trackNameTitle.append(
 638+ $j('<span />').addClass( 'ui-icon ui-icon-video'),
 639+ $j('<span />').text( gM( 'mwe-sequencer-video-track' ) )
 640+ )
 641+ $trackNameContainer.css( 'height' , '100px' );
531642 }
 643+ // Add the track title as a tool tip
 644+ if ( $j( smilSequenceTrack ).attr('title') ){
 645+ $trackNameTitle.find('span').attr('title', $j( smilSequenceTrack ).attr('title') );
 646+ }
 647+
 648+ $trackNameContainer.append( $trackNameTitle )
532649 // Wrap the track name in a box that matches the trackNames
533 - return $j('<div />')
534 - .attr('id', this.sequencer.getId() + '_trackName_' + trackIndex)
535 - .addClass('trackNames ui-corner-all')
536 - .append(
537 - $trackNameInterface
538 - )
 650+ return
539651 },
540 -
541 - getSequenceTrackTitle: function( sequenceNode ){
542 - if( $j( sequenceNode).attr('title') ){
543 - return $j( sequenceNode).attr('title');
544 - }
545 - // Else return an empty string ( for now )
546 - return ''
 652+ getTrackNameInterfaceId: function(trackIndex ){
 653+ return this.sequencer.getId() + '_trackName_' + trackIndex;
547654 },
548655
549 - getSequenceTrackId: function( index, sequenceNode ){
550 - if( ! $j( sequenceNode ).data('id') ){
551 - $j( sequenceNode ).data('id', this.sequencer.getId() + '_sequenceTrack_' + index );
 656+ getSequenceTrackId: function( index, smilSequenceTrack ){
 657+ if( ! $j( smilSequenceTrack ).data('id') ){
 658+ $j( smilSequenceTrack ).data('id', this.sequencer.getId() + '_sequenceTrack_' + index );
552659 }
553 - return $j( sequenceNode ).data('id');
 660+ return $j( smilSequenceTrack ).data('id');
554661 }
555662 }
556663
Index: branches/MwEmbedStandAlone/libraries/jquery/jquery.ui/ui/ui.draggable.js
@@ -580,8 +580,11 @@
581581 t.css("cursor", o.cursor);
582582 },
583583 stop: function(event, ui) {
584 - var o = $(this).data('draggable').options;
585 - if (o._cursor) $('body').css("cursor", o._cursor);
 584+ // ensure draggable data options exist
 585+ if( $(this).data('draggable') ){
 586+ var o = $(this).data('draggable').options;
 587+ if (o._cursor) $('body').css("cursor", o._cursor);
 588+ }
586589 }
587590 });
588591

Status & tagging log