Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.Sequencer.js |
— | — | @@ -97,7 +97,7 @@ |
98 | 98 | * Update the smil xml and then update the interface |
99 | 99 | */ |
100 | 100 | updateSmilXML: function( smilXML ){ |
101 | | - mw.log("Sequencer::updateSmilXML" + smilXML); |
| 101 | + mw.log( "Sequencer::updateSmilXML" ); |
102 | 102 | var _this = this; |
103 | 103 | // Update the embedPlayer smil: |
104 | 104 | this.getSmil().updateFromString( smilXML ); |
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerMenu.js |
— | — | @@ -97,46 +97,33 @@ |
98 | 98 | var $menuTarget = this.sequencer.getMenuTarget(); |
99 | 99 | $menuTarget.empty(); |
100 | 100 | |
101 | | - for( var topMenuKey in this.menuConfig ){ |
102 | | - // Create a function to preserve topMenuKey binding scope |
103 | | - function drawTopMenu( topMenuKey ){ |
| 101 | + for( var menuKey in this.menuConfig ){ |
| 102 | + // Create a function to preserve menuKey binding scope |
| 103 | + function drawTopMenu( menuKey ){ |
104 | 104 | // Add the menu target |
105 | 105 | $menuTarget |
106 | 106 | .append( |
107 | 107 | $j('<span />') |
108 | | - .html( gM('mwe-sequencer-menu-' + topMenuKey ) ) |
| 108 | + .html( gM('mwe-sequencer-menu-' + menuKey ) ) |
109 | 109 | .css({ |
110 | 110 | 'padding': '7px', |
111 | 111 | 'cursor' : 'default' |
112 | 112 | }) |
113 | | - .attr( 'id', _this.sequencer.id + '_' + topMenuKey + '_topMenuItem') |
| 113 | + .attr( 'id', _this.sequencer.id + '_' + menuKey + '_topMenuItem') |
114 | 114 | .addClass( 'ui-state-default' ) |
115 | 115 | .buttonHover() |
116 | 116 | // Add menu binding: |
117 | 117 | .menu({ |
118 | | - content: _this.getMenuSet( _this.menuConfig, topMenuKey ), |
119 | | - showSpeed: 100 |
120 | | - }) |
121 | | - // should fire post jquery.fn.menu() mousedown binding :: |
122 | | - .mousedown(function(){ |
123 | | - // sync the disabled enabled state to menu |
124 | | - for( var menuItemKey in _this.menuConfig[ topMenuKey ] ){ |
125 | | - var $menuItem = $j( '#' + _this.getMenuItemId( topMenuKey, menuItemKey ) ); |
126 | | - var isDisabled = _this.menuConfig[ topMenuKey ][menuItemKey].disabled; |
127 | | - if( $menuItem.hasClass( 'disabled') ){ |
128 | | - if( ! isDisabled ){ |
129 | | - $menuItem.removeClass( 'disabled' ) |
130 | | - } |
131 | | - } else { |
132 | | - if( isDisabled ){ |
133 | | - $menuItem.addClass( 'disabled' ); |
134 | | - } |
135 | | - } |
136 | | - } |
137 | | - }) |
| 118 | + content: _this.getMenuSet( menuKey ), |
| 119 | + showSpeed: 100, |
| 120 | + createMenuCallback: function(){ |
| 121 | + // Sync the disabled enabled state to menu |
| 122 | + _this.syncMenuState( menuKey ) |
| 123 | + } |
| 124 | + }) |
138 | 125 | ) |
139 | 126 | } |
140 | | - drawTopMenu( topMenuKey ); |
| 127 | + drawTopMenu( menuKey ); |
141 | 128 | } |
142 | 129 | |
143 | 130 | // Check if we should include kaltura credits |
— | — | @@ -156,9 +143,31 @@ |
157 | 144 | ) |
158 | 145 | } |
159 | 146 | }, |
| 147 | + /** |
| 148 | + * Sync an in-dom menu with the menuConfig state |
| 149 | + */ |
| 150 | + syncMenuState: function( menuKey ){ |
| 151 | + var _this = this; |
| 152 | + var menuConfig = this.menuConfig; |
| 153 | + for( var menuItemKey in _this.menuConfig[ menuKey ] ){ |
| 154 | + var $menuItem = $j( '#' + _this.getMenuItemId( menuKey, menuItemKey ) ); |
| 155 | + var isDisabled = _this.menuConfig[ menuKey ][ menuItemKey ].disabled; |
| 156 | + mw.log('sync: ' + menuItemKey + ' in-dom:' + $menuItem.length + ' isd:' + isDisabled); |
| 157 | + if( $menuItem.hasClass( 'disabled') ){ |
| 158 | + if( ! isDisabled ){ |
| 159 | + $menuItem.removeClass( 'disabled' ) |
| 160 | + } |
| 161 | + } else { |
| 162 | + if( isDisabled ){ |
| 163 | + $menuItem.addClass( 'disabled' ); |
| 164 | + } |
| 165 | + } |
| 166 | + } |
| 167 | + }, |
160 | 168 | /* return a top menuItem with all its associated menuItems */ |
161 | | - getMenuSet: function( menuConfig, menuKey ){ |
| 169 | + getMenuSet: function( menuKey ){ |
162 | 170 | var _this = this; |
| 171 | + var menuConfig = this.menuConfig; |
163 | 172 | // Build out the ul for the given menu |
164 | 173 | var $menu = $j( '<ul />' ) |
165 | 174 | .attr({ |
— | — | @@ -199,6 +208,10 @@ |
200 | 209 | } |
201 | 210 | ); |
202 | 211 | |
| 212 | + if( menuItem.disabled === true ){ |
| 213 | + $li.addClass( 'disabled' ); |
| 214 | + } |
| 215 | + |
203 | 216 | // Set the ID for easy reference |
204 | 217 | $li.attr( 'id', _this.getMenuItemId( menuKey, menuItemKey ) ) |
205 | 218 | |
— | — | @@ -210,42 +223,24 @@ |
211 | 224 | return $li; |
212 | 225 | }, |
213 | 226 | |
214 | | - disableMenuItem: function( menuKey, menuItemKey ){ |
215 | | - |
| 227 | + disableMenuItem: function( menuKey, menuItemKey ){ |
216 | 228 | this.menuConfig[ menuKey ][ menuItemKey ].disabled = true; |
217 | | - $menuItemTarget = $j('#' + this.getMenuItemId(menuKey, menuItemKey ) ); |
| 229 | + $menuItemTarget = $j('#' + this.getMenuItemId( menuKey, menuItemKey ) ); |
| 230 | + |
| 231 | + mw.log("SequencerMenu::disable:" + ' ' + menuKey + ' ' + menuItemKey + ' in-dom:' + $menuItemTarget.length ); |
218 | 232 | if( $menuItemTarget.length && ! $menuItemTarget.hasClass( 'disabled' ) ){ |
219 | 233 | $menuItemTarget.addClass( 'disabled' ); |
220 | 234 | } |
221 | | - |
222 | | - /*this.menuConfig[ menuKey ][ menuItemKey ].enabled = false; |
223 | | - |
224 | | - $j('#' + this.getMenuItemId(menuKey, menuItemKey ) ) |
225 | | - // remove menu role |
226 | | - .attr( 'role', '') |
227 | | - // Set to faded out |
228 | | - .css({ |
229 | | - 'opacity' : .5 |
230 | | - })*/ |
231 | | - |
232 | 235 | }, |
233 | 236 | |
234 | | - enableMenuItem: function( menuKey, menuItemKey ){ |
235 | | - this.menuConfig[ menuKey ][ menuItemKey ].disabled = false; |
236 | | - alert( 'EnableMenuItem' + menuKey + ' key:' + menuItemKey ); |
| 237 | + enableMenuItem: function( menuKey, menuItemKey ){ |
| 238 | + this.menuConfig[ menuKey ][ menuItemKey ].disabled = false; |
237 | 239 | $menuItemTarget = $j('#' + this.getMenuItemId( menuKey, menuItemKey ) ); |
238 | | - if( $menuItemTarget.hasClass( 'disabled' ) ){ |
239 | | - $menuItemTarget.removeClass( 'disabled' ); |
240 | | - } |
241 | 240 | |
242 | | - /* |
243 | | - $j('#' + this.getMenuItemId(menuKey, menuItemKey ) ) |
244 | | - // remove menu role |
245 | | - .attr( 'role', 'menuitem') |
246 | | - // Set to faded out |
247 | | - .css({ |
248 | | - 'opacity' : 1 |
249 | | - })*/ |
| 241 | + mw.log("SequencerMenu::enable:" + menuKey + ' ' + menuItemKey + ' in-dom:' + $menuItemTarget.length ); |
| 242 | + if( $menuItemTarget.length && $menuItemTarget.hasClass( 'disabled' ) ){ |
| 243 | + $menuItemTarget.removeClass( 'disabled' ); |
| 244 | + } |
250 | 245 | }, |
251 | 246 | |
252 | 247 | getMenuItemId: function( menuKey, menuItemKey ){ |
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerTimeline.js |
— | — | @@ -60,7 +60,7 @@ |
61 | 61 | }, |
62 | 62 | |
63 | 63 | // Draw the timeline |
64 | | - drawTimeline: function(){ |
| 64 | + drawTimeline: function(){ |
65 | 65 | // xxx TODO support multiple tracks ::: |
66 | 66 | var seqTracks = this.sequencer.getSmil().getBody().getSeqElements(); |
67 | 67 | // For now just one video track: |
— | — | @@ -91,9 +91,7 @@ |
92 | 92 | var _this = this; |
93 | 93 | // Setup a local pointer to the smil engine: |
94 | 94 | var smil = this.sequencer.getSmil(); |
95 | | - |
96 | | - |
97 | | - |
| 95 | + |
98 | 96 | var $clipTrackSet = this.getTracksContainer().find('.clipTrackSetContainer').find( '.clipTrackSet' ); |
99 | 97 | // Add the $clipTrackSet if not already in dom: |
100 | 98 | if( $clipTrackSet.length == 0 ){ |
— | — | @@ -113,8 +111,7 @@ |
114 | 112 | var reRenderThumbFlag = false; |
115 | 113 | // Draw the node onto the timeline if the clip is not already there: |
116 | 114 | var $timelineClip = $clipTrackSet.find('#' + _this.getTimelineClipId( $node ) ) |
117 | | - if( $timelineClip.length == 0 ){ |
118 | | - |
| 115 | + if( $timelineClip.length == 0 ){ |
119 | 116 | $timelineClip = _this.getTimelineClip( $clipTrackSet, $node ); |
120 | 117 | if( $previusClip ){ |
121 | 118 | $previusClip.after( |
— | — | @@ -125,17 +122,19 @@ |
126 | 123 | $clipTrackSet.prepend( |
127 | 124 | $timelineClip |
128 | 125 | ); |
129 | | - } |
| 126 | + } |
130 | 127 | reRenderThumbFlag = true; |
131 | 128 | } else { |
132 | | - // confirm order |
133 | | - mw.log( $timelineClip.attr('id') + ' found '); |
134 | | - if( $timelineClip.data('prevIndex') != seqOrder ){ |
| 129 | + // Confirm clip is in the correct indexOrder |
| 130 | + //mw.log( 'indexOrder::' + $timelineClip.attr('id') + ' '+ $timelineClip.data('indexOrder') + ' == ' + $node.data('indexOrder')); |
| 131 | + if( $timelineClip.data('indexOrder') != $node.data('indexOrder') ){ |
135 | 132 | reOrderTimelineFlag = true; |
136 | | - } |
| 133 | + } |
137 | 134 | } |
138 | | - // xxx Check if the start time was changed |
139 | 135 | |
| 136 | + // xxx Check if the start time was changed to set reRenderThumbFlag |
| 137 | + |
| 138 | + |
140 | 139 | if ( reRenderThumbFlag ){ |
141 | 140 | // issue a draw Thumb request ( since we reinserted into the dom ) |
142 | 141 | // Check Buffer for when the first frame of the smilNode can be grabbed: |
— | — | @@ -152,12 +151,15 @@ |
153 | 152 | |
154 | 153 | // Check if we need to re-sort the list |
155 | 154 | if( reOrderTimelineFlag ){ |
156 | | - alert(" reorder clips!"); |
157 | 155 | // move every node in-order to the end. |
158 | 156 | smil.getBody().getRefElementsRecurse( sequenceNode, startOffset, function( $node ){ |
159 | 157 | var $timelineClip = $clipTrackSet.find('#' + _this.getTimelineClipId( $node ) ) |
160 | 158 | $timelineClip.appendTo( $clipTrackSet ); |
161 | 159 | }); |
| 160 | + // Update the order for all clips |
| 161 | + $clipTrackSet.children().each(function (inx, clip){ |
| 162 | + $j( clip ).data('indexOrder', inx); |
| 163 | + }); |
162 | 164 | } |
163 | 165 | |
164 | 166 | |
— | — | @@ -218,7 +220,7 @@ |
219 | 221 | .attr('id', _this.getTimelineClipId( $node ) ) |
220 | 222 | .data( { |
221 | 223 | 'smilId': $node.attr('id'), |
222 | | - 'prevIndex' : $clipTrackSet.children().length |
| 224 | + 'indexOrder' : $clipTrackSet.children().length |
223 | 225 | }) |
224 | 226 | .addClass('timelineClip ui-corner-all') |
225 | 227 | .loadingSpinner() |
— | — | @@ -269,7 +271,7 @@ |
270 | 272 | $seqParent.append( $movedSmileNode.get(0) ); |
271 | 273 | } else { |
272 | 274 | // see if the index was affected by our move position |
273 | | - if( clipIndex >= $movedSmileNode.data('prevIndex') ){ |
| 275 | + if( clipIndex >= $movedSmileNode.data('indexOrder') ){ |
274 | 276 | $seqParent.children().eq( clipIndex ).after( $movedSmileNode.get(0) ); |
275 | 277 | }else{ |
276 | 278 | $seqParent.children().eq( clipIndex ).before( $movedSmileNode.get(0) ); |
— | — | @@ -291,9 +293,9 @@ |
292 | 294 | }); |
293 | 295 | } |
294 | 296 | |
295 | | - // Update the prevIndex for all clips |
| 297 | + // Update the order for all clips |
296 | 298 | $seqParent.children().each(function (inx, clip){ |
297 | | - $j( clip ).data('prevIndex', inx); |
| 299 | + $j( clip ).data('indexOrder', inx); |
298 | 300 | }); |
299 | 301 | |
300 | 302 | // Invalidate / update embedPlayer duration / clip offsets |
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerActionsEdit.js |
— | — | @@ -47,7 +47,7 @@ |
48 | 48 | * Apply a smil xml transform state ( to support undo / redo ) |
49 | 49 | */ |
50 | 50 | registerEdit: function(){ |
51 | | - mw.log( 'ActionsEdit::registerEdit: ' + this.sequencer.getSmil().getXMLString() ); |
| 51 | + mw.log( 'ActionsEdit::registerEdit: stacksize' + this.editStack.length + ' editIndex: ' + this.editIndex ); |
52 | 52 | // Throw away any edit history after the current editIndex: |
53 | 53 | if( this.editStack.length && this.editIndex > this.editStack.length ) { |
54 | 54 | this.editStack = this.editStack.splice(0, this.editIndex); |
— | — | @@ -71,13 +71,15 @@ |
72 | 72 | this.editIndex--; |
73 | 73 | if( this.editStack[ this.editIndex ] ) { |
74 | 74 | this.sequencer.updateSmilXML( this.editStack[ this.editIndex ] ); |
| 75 | + // Enable redo action |
| 76 | + this.sequencer.getMenu().enableMenuItem( 'edit', 'redo' ); |
75 | 77 | } else { |
76 | 78 | // index out of range set to 0 |
77 | 79 | this.editIndex = 0; |
78 | 80 | mw.log("Error: SequenceActionsEdit:: undo Already at oldest index:" + this.editIndex); |
79 | | - } |
| 81 | + } |
80 | 82 | // if at oldest undo disable undo option |
81 | | - if( this.editIndex - 1 == 0 ){ |
| 83 | + if( ( this.editIndex - 1 ) < 0 ){ |
82 | 84 | this.sequencer.getMenu().disableMenuItem( 'edit', 'undo' ); |
83 | 85 | } |
84 | 86 | }, |
— | — | @@ -87,15 +89,19 @@ |
88 | 90 | redo: function(){ |
89 | 91 | this.editIndex ++; |
90 | 92 | if( this.editStack[ this.editIndex ] ) { |
| 93 | + mw.log("DO redo for editIndex::" + this.editIndex + ' xml lenght' + this.editStack[ this.editIndex ].length ); |
91 | 94 | this.sequencer.updateSmilXML( this.editStack[ this.editIndex ] ); |
| 95 | + // Enable undo action |
| 96 | + this.sequencer.getMenu().enableMenuItem( 'edit', 'undo' ); |
92 | 97 | } else { |
93 | | - // index out of redo range set to last edit |
| 98 | + // Index out of redo range set to last edit |
94 | 99 | this.editIndex == this.editStack.length - 1 |
95 | 100 | mw.log( 'Error: SequencerActionsEdit::Redo: Already at most recent edit avaliable'); |
96 | 101 | } |
97 | 102 | |
98 | 103 | // if at newest redo disable redo option |
99 | | - if( this.editIndex == this.editStack.length - 1 ){ |
| 104 | + mw.log( this.editIndex + ' >= ' + ( this.editStack.length -1 ) ); |
| 105 | + if( this.editIndex >= this.editStack.length -1 ){ |
100 | 106 | this.sequencer.getMenu().disableMenuItem( 'edit', 'redo' ); |
101 | 107 | } |
102 | 108 | } |
Index: branches/MwEmbedStandAlone/libraries/jquery/plugins/jquery.menu/jquery.menu.js |
— | — | @@ -126,6 +126,7 @@ |
127 | 127 | linkToFront: false |
128 | 128 | }, |
129 | 129 | showSpeed: 200, // show/hide speed in milliseconds |
| 130 | + createMenuCallback: null, |
130 | 131 | callerOnState: 'ui-state-active', // class to change the appearance of the link/button when the menu is showing |
131 | 132 | loadingState: 'ui-state-loading', // class added to the link/button while the menu is created |
132 | 133 | linkHover: 'ui-state-hover', // class for menu option hover state |
— | — | @@ -277,7 +278,7 @@ |
278 | 279 | }; |
279 | 280 | break; |
280 | 281 | }; |
281 | | - }); |
| 282 | + }); |
282 | 283 | }; |
283 | 284 | |
284 | 285 | this.create = function() { |
— | — | @@ -323,12 +324,12 @@ |
324 | 325 | var menuli = menuitem.parent(); |
325 | 326 | if( !menuli.hasClass('divider') && !menuli.hasClass('disabled') ){ |
326 | 327 | $('.'+options.linkHover).removeClass(options.linkHover).blur().parent().removeAttr('id'); |
327 | | - $(this).addClass(options.linkHover).focus().parent().attr('id','active-menuitem'); |
| 328 | + $(this).addClass(options.linkHover).focus().parent().addClass('active-menuitem'); |
328 | 329 | } |
329 | 330 | }, |
330 | 331 | function() { |
331 | 332 | if( !menuitem.hasClass('divider') && !menuitem.hasClass('disabled') ){ |
332 | | - $(this).removeClass(options.linkHover).blur().parent().removeAttr('id'); |
| 333 | + $(this).removeClass(options.linkHover).blur().parent().removeClass('active-menuitem'); |
333 | 334 | } |
334 | 335 | } |
335 | 336 | ); |
— | — | @@ -347,6 +348,10 @@ |
348 | 349 | |
349 | 350 | menu.setPosition(container, caller, options); |
350 | 351 | menu.menuExists = true; |
| 352 | + |
| 353 | + if( typeof options.createMenuCallback == 'function' ){ |
| 354 | + options.createMenuCallback(); |
| 355 | + } |
351 | 356 | }; |
352 | 357 | |
353 | 358 | this.chooseItem = function(item) { |