2 handles clip edit controls
3 'inoutpoints':0, //should let you set the in and out points of clip
4 'panzoom':0, //should allow setting keyframes and tweening modes
5 'overlays':0, //should allow setting "locked to clip" overlay tracks
6 'audio':0 //should allow controlling the audio volume (with keyframes)
10 "mwe-crop" : "Crop image",
11 "mwe-apply_crop" : "Apply crop to image",
12 "mwe-reset_crop" : "Reset crop",
13 "mwe-insert_image_page" : "Insert into page",
14 "mwe-insert_into_sequence" : "Insert into sequence",
15 "mwe-preview_insert" : "Preview insert",
16 "mwe-cancel_image_insert" : "Cancel insert",
17 "mwe-sc_fileopts" : "Clip detail edit",
18 "mwe-sc_inoutpoints" : "Set in-out points",
19 "mwe-sc_overlays" : "Overlays",
20 "mwe-sc_audio" : "Audio control",
21 "mwe-sc_duration" : "Duration",
22 "mwe-template_properties" : "Template properties",
23 "mwe-custom_title" : "Custom title",
24 "mwe-edit_properties" : "Edit properties",
25 "mwe-other_properties" : "Other properties",
26 "mwe-resource_page" : "Resource page:",
27 "mwe-set_in_out_points" : "Set in-out points",
28 "mwe-start_time" : "Start time",
29 "mwe-end_time" : "End time",
30 "mwe-preview_inout" : "Preview in-out points",
31 "mwe-edit-tools" : "Edit tools",
32 "mwe-inline-description" : "Caption",
33 "mwe-edit-video-tools" : "Edit video tools:",
34 "mwe-duration" : "Duration:"
37 var default_clipedit_values
= {
38 'rObj': null, // the resource object
39 'clip_disp_ct':null,// target clip disp
40 'control_ct':null, // control container
41 'media_type': null, // media type
42 'parent_ct': null, // parent container
44 'p_rsdObj': null, // parent remote search object
45 'p_seqObj': null, // parent sequence Object
47 'controlActionsCb' : null, // the object that configures control Action callbacks
49 // The set of tools to enable (by default 'all' else an array of tools from mvClipEdit.toolset list below:
50 'enabled_tools': 'all',
51 'edit_action': null, // the requested edit action
52 'profile': 'inpage' // the given profile either "inpage" or "sequence"
54 var mvClipEdit = function( iObj
) {
55 return this.init( iObj
);
57 mvClipEdit
.prototype = {
59 selTool
:null, // selected tool
60 crop
: null, // the crop values
62 toolset
: ['crop', 'layout'],
64 init:function( iObj
) {
66 for ( var i
in default_clipedit_values
) {
72 // if media type was not supplied detect for resource if possible:
73 // @@todo more advanced detection.
74 if ( !this.media_type
&& this.rObj
&& this.rObj
.type
) {
75 if ( this.rObj
.type
.indexOf( "image/" ) === 0 ) {
76 this.media_type
= 'image';
77 } else if ( this.rObj
.type
.indexOf( "video/" ) === 0 ) {
78 this.media_type
= 'video';
79 } else if ( this.rObj
.type
.indexOf( "text/" ) === 0 ) {
80 this.media_type
= 'template';
84 if ( this.profile
== 'sequence' ) {
85 this.doEditTypesMenu();
88 // check the media_type:
89 // js_log('mvClipEdit:: media type:' + this.media_type + ' base width: ' + this.rObj.width + ' bh: ' + this.rObj.height);
90 // could seperate out into media Types objects for now just call method
91 if ( this.media_type
== 'image' ) {
92 this.setUpImageCtrl();
93 } else if ( this.media_type
== 'video' ) {
94 this.setUpVideoCtrl();
99 // master edit types object:
100 // maybe we should refactor these into their own classes
101 // more refactor each media type should be its own class inheriting the shared baseEditType object
104 'media':['image', 'template'],
105 'doEdit':function( _this
, target
) {
106 function doUpdateDur( inputElm
) {
107 js_log( "update duration:" + $j( inputElm
).val() );
108 // update the parent sequence object:
109 _this
.rObj
.dur
= smilParseTime( $j( inputElm
).val() );
110 // update the playlist:
111 _this
.p_seqObj
.do_refresh_timeline( true );
115 '<label for="ce_dur">' + gM( 'mwe-duration' ) + '</label>' +
116 '<input name="ce_dur" tabindex="1" maxlength="11" value="' +
117 seconds2npt( _this
.rObj
.getDuration() ) +
120 ).children( "input[name='ce_dur']" ).change( function() {
123 // Strange can't chain this binding for some reason...
124 $j( target
).find( "input[name='ce_dur']" ).upDownTimeInputBind( doUpdateDur
);
129 'doEdit':function( _this
, target
) {
130 // do clock mouse scroll duration editor
131 var end_ntp
= ( _this
.rObj
.embed
.end_ntp
) ? _this
.rObj
.embed
.end_ntp
: _this
.rObj
.embed
.getDuration();
133 end_ntp
= seconds2npt( _this
.rObj
.dur
);
135 var start_ntp
= ( _this
.rObj
.embed
.start_ntp
) ? _this
.rObj
.embed
.start_ntp
: seconds2npt( 0 );
138 // make sure we have an end time
141 _this
.getSetInOutHtml( {
142 'start_ntp' : start_ntp
,
146 _this
.setInOutBindings();
151 'media':['image', 'video', 'template'],
152 'doEdit':function( _this
, target
) {
153 // if media type is template we have to query to get its URI to get its parameters
154 if ( _this
.media_type
== 'template' && !_this
.rObj
.tVars
) {
155 mv_set_loading( '#sub_cliplib_ic' );
159 'titles': _this
.rObj
.uri
,
162 // get the interface uri from the plObject
163 var api_url
= _this
.p_seqObj
.plObj
.interface_url
;
168 }, function( data
) {
169 if ( typeof data
.query
.pages
== 'undefined' )
170 return _this
.doEditOpts( target
);
171 for ( var i
in data
.query
.pages
) {
172 var page
= data
.query
.pages
[i
];
173 if ( !page
['revisions'] || !page
['revisions'][0]['*'] ) {
174 return _this
.doEditOpts( target
);
176 var template_rev
= page
['revisions'][0]['*'];
179 var pObj
= mw
.parser
.pNew( template_rev
);
180 _this
.rObj
.tVars
= pObj
.getTemplateVars();
181 // run the editor now that we have updated the tVars:
182 _this
.doEditOpts( target
);
186 _this
.doEditOpts( target
);
191 'media':['image', 'video'],
192 'doEdit':function( _this
, target
) {
193 // do clock mouse scroll duration editor
194 $j( target
).html( '<h3>Current Overlays:</h3>Add,Remove,Modify' );
198 'media':['image', 'video', 'template'],
199 'doEdit':function( _this
, target
) {
200 // do clock mouse scroll duration editor
201 $j( target
).html( '<h3>Audio Volume:</h3>' );
205 doEditOpts:function( target
) {
207 // add html for rObj resource:
210 '<td colspan="2"><b>' + gM( 'mwe-edit_properties' ) + '</b></td>' +
214 gM( 'mwe-custom_title' ) +
216 '<td><input type="text" size="15" maxwidth="255" value="';
217 if ( _this
.rObj
.title
!= null )
218 o
+= _this
.rObj
.title
;
222 if ( _this
.rObj
.tVars
) {
223 var existing_p
= _this
.rObj
.params
;
224 var testing_a
= _this
.rObj
.tVars
;
227 '<td colspan="2"><b>' + gM( 'mwe-template_properties' ) + '</b></td>' +
229 for ( var i
= 0; i
< _this
.rObj
.tVars
.length
; i
++ ) {
232 _this
.rObj
.tVars
[i
] +
234 '<td><input name="' + _this
.rObj
.tVars
[i
] + '" class="ic_tparam" type="text" size="15" maxwidth="255" value="';
235 if ( _this
.rObj
.params
[ _this
.rObj
.tVars
[i
] ] ) {
236 o
+= _this
.rObj
.params
[ _this
.rObj
.tVars
[i
] ];
243 if ( typeof wgArticlePath
!= 'undefined' ) {
244 var res_src
= wgArticlePath
.replace( /\$1/, _this
.rObj
.uri
);
245 var res_title
= _this
.rObj
.uri
;
248 var res_src
= _this
.rObj
.src
;
249 var res_title
= mw
.parseUri( _this
.rObj
.src
).file
;
252 '<td colspan="2"><b>' + gM( 'mwe-other_properties' ) + '</b></td>' +
256 gM( 'mwe-resource_page' ) +
258 '<td><a href="' + res_src
+ '" ' +
265 $j( target
).html ( o
);
267 // add update bindings
268 $j( target
+ ' .ic_tparam' ).change( function() {
269 js_log( "updated tparam::" + $j( this ).attr( "name" ) );
270 // update param value:
271 _this
.rObj
.params
[ $j( this ).attr( "name" ) ] = $j( this ).val();
272 // re-parse & update template
273 var template_wiki_text
= '{{' + _this
.rObj
.uri
;
274 for ( var i
= 0; i
< _this
.rObj
.tVars
.length
; i
++ ) {
276 template_wiki_text
+= "\n|" + _this
.rObj
.tVars
[i
] + ' = ' + _this
.rObj
.params
[ _this
.rObj
.tVars
[i
] ] ;
278 template_wiki_text
+= "\n}}";
281 'title' : _this
.p_seqObj
.plObj
.mTitle
,
282 'text' : template_wiki_text
284 $j( _this
.rObj
.embed
).html( mv_get_loading_img() );
286 var api_url
= _this
.p_seqObj
.plObj
.interface_url
;
290 }, function( data
) {
291 if ( data
.parse
.text
['*'] ) {
293 $j( _this
.rObj
.embed
).html( data
.parse
.text
['*'] );
298 // update doFocusBindings
299 if ( _this
.p_seqObj
)
300 _this
.p_seqObj
.doFocusBindings();
302 doEditTypesMenu:function() {
304 // add in subMenus if set
305 // check for submenu and add to item container
308 o
+= '<div id="mv_submenu_clipedit">';
310 var first_tab
= false;
311 $j
.each( this.edit_types
, function( sInx
, editType
) {
312 // check if the given editType is valid for our given media type
314 for ( var i
= 0; i
< editType
.media
.length
; i
++ ) {
315 if ( editType
.media
[i
] == _this
.media_type
) {
323 '<a id="mv_smi_' + sInx
+ '" href="#sc_' + sInx
+ '">' + gM( 'mwe-sc_' + sInx
) + '</a>' +
325 tabc
+= '<div id="sc_' + sInx
+ '" style="overflow:auto;" ></div>';
330 // add sub menu container with menu html:
331 $j( '#' + this.control_ct
).html( o
) ;
333 $j( '#mv_submenu_clipedit' ).tabs( {
335 select: function( event
, ui
) {
336 _this
.doDisplayEdit( $j( ui
.tab
).attr( 'id' ).replace( 'mv_smi_', '' ) );
338 } ).addClass( 'ui-tabs-vertical ui-helper-clearfix' );
340 $j( "#mv_submenu_clipedit li" ).removeClass( 'ui-corner-top' ).addClass( 'ui-corner-left' );
341 // update the default edit display:
342 _this
.doDisplayEdit( first_tab
);
344 doDisplayEdit:function( edit_type
) {
347 js_log( 'doDisplayEdit: ' + edit_type
);
349 // do edit interface for that edit type:
350 if ( this.edit_types
[ edit_type
].doEdit
)
351 this.edit_types
[ edit_type
].doEdit( this, '#sc_' + edit_type
);
353 setUpVideoCtrl:function() {
354 js_log( 'setUpVideoCtrl:f' );
356 var eb
= $j( '#embed_vid' ).get( 0 );
357 // turn on preview to avoid onDone actions
358 eb
.preview_mode
= true;
359 $j( '#' + this.control_ct
).html( '<h3>' + gM( 'mwe-edit-video-tools' ) + '</h3>' );
360 if ( eb
.supportsURLTimeEncoding() ) {
362 $j( '#' + this.control_ct
).append(
363 _this
.getSetInOutHtml( {
364 'start_ntp' : eb
.start_ntp
,
365 'end_ntp' : eb
.end_ntp
368 _this
.setInOutBindings();
371 // if in a sequence we have no need for insertDesc
372 if ( !_this
.p_seqObj
) {
373 $j( '#' + this.control_ct
).append( _this
.getInsertDescHtml() );
375 // update control actions
376 this.updateInsertControlActions();
378 setInOutBindings:function() {
380 // setup a top level shortcut:
381 var $tp
= $j( '#' + this.control_ct
);
383 var start_sec
= npt2seconds( $tp
.find( '.startInOut' ).val() );
384 var end_sec
= npt2seconds( $tp
.find( '.endInOut' ).val() );
386 // if we don't have 0 as start then assume we are in a range request and give some buffer area:
387 var min_slider
= ( start_sec
- 60 < 0 ) ? 0 : start_sec
- 60;
388 if ( min_slider
!= 0 ) {
389 var max_slider
= end_sec
+ 60;
391 max_slider
= end_sec
;
394 $tp
.find( '.inOutSlider' ).slider( {
399 values
: [start_sec
, end_sec
],
400 slide: function( event
, ui
) {
401 // js_log(" vals:"+ seconds2npt( ui.values[0] ) + ' : ' + seconds2npt( ui.values[1]) );
402 $tp
.find( '.startInOut' ).val( seconds2npt( ui
.values
[0] ) );
403 $tp
.find( '.endInOut' ).val( seconds2npt( ui
.values
[1] ) );
405 change:function( event
, ui
) {
406 do_video_time_update( seconds2npt( ui
.values
[0] ), seconds2npt( ui
.values
[1] ) );
410 // bind up and down press when focus on start or end
411 $tp
.find( '.startInOut' ).upDownTimeInputBind( function( inputElm
) {
412 var s_sec
= npt2seconds( $j( inputElm
).val() );
413 var e_sec
= npt2seconds( $tp
.find( '.endInOut' ).val() )
415 $j( inputElm
).val( seconds2npt( e_sec
- 1 ) );
416 // update the slider:
417 var values
= $tp
.find( '.inOutSlider' ).slider( 'option', 'values' );
418 js_log( 'in slider len: ' + $tp
.find( '.inOutSlider' ).length
);
420 $tp
.find( '.inOutSlider' ).slider( 'value', 10 );
422 $tp
.find( '.inOutSlider' ).slider( 'option', 'values', [s_sec
, e_sec
] );
423 var values
= $tp
.find( '.inOutSlider' ).slider( 'option', 'values' );
424 js_log( 'values (after update):' + values
);
426 $tp
.find( '.endInOut' ).upDownTimeInputBind( function( inputElm
) {
427 var s_sec
= npt2seconds( $tp
.find( '.startInOut' ).val() );
428 var e_sec
= npt2seconds( $j( inputElm
).val() );
430 $j( inputElm
).val( seconds2npt( s_sec
+ 1 ) );
431 // update the slider:
432 $tp
.find( '.inOutSlider' ).slider( 'option', 'values', [ s_sec
, e_sec
] );
436 $j( '#' + this.control_ct
+ ' .inOutPreviewClip' ).btnBind().click( function() {
437 $j( '#embed_vid' ).get( 0 ).stop();
438 $j( '#embed_vid' ).get( 0 ).play();
442 getSetInOutHtml:function( setInt
) {
443 return '<strong>' + gM( 'mwe-set_in_out_points' ) + '</strong>' +
444 '<table border="0" style="background: transparent; width:94%;height:50px;">' +
446 '<td style="width:90px">' +
447 gM( 'mwe-start_time' ) +
448 '<input class="ui-widget-content ui-corner-all startInOut" size="9" value="' + setInt
.start_ntp
+ '">' +
451 '<div class="inOutSlider"></div>' +
453 '<td style="width:90px;text-align:right;">' +
454 gM( 'mwe-end_time' ) +
455 '<input class="ui-widget-content ui-corner-all endInOut" size="9" value="' + setInt
.end_ntp
+ '">' +
459 $j
.btnHtml( gM( 'mwe-preview_inout' ), 'inOutPreviewClip', 'video' );
461 getInsertDescHtml:function() {
462 var o
= '<h3>' + gM( 'mwe-inline-description' ) + '</h3>' +
463 '<textarea style="width:95%" id="mv_inline_img_desc" rows="5" cols="30">';
464 if ( this.p_rsdObj
) {
465 // if we have a parent remote search driver let it parse the inline description
466 o
+= this.rObj
.pSobj
.getInlineDescWiki( this.rObj
);
468 o
+= '</textarea><br>';
469 // js_log('getInsertDescHtml: ' + o );
472 updateInsertControlActions:function() {
474 var b_target
= _this
.p_rsdObj
.target_container
+ '~ .ui-dialog-buttonpane';
475 // empty the ui-dialog-buttonpane bar:
476 $j( b_target
).empty();
477 for ( var cbType
in _this
.controlActionsCb
) {
480 $j( b_target
).append( $j
.btnHtml( gM( 'mwe-insert_into_sequence' ), 'mv_insert_sequence', 'check' ) + ' ' )
481 .children( '.mv_insert_sequence' )
485 _this
.controlActionsCb
['insert_seq']( _this
.rObj
);
489 $j( b_target
).append( $j
.btnHtml( gM( 'mwe-insert_image_page' ), 'mv_insert_image_page', 'check' ) + ' ' )
490 .children( '.mv_insert_image_page' )
494 _this
.controlActionsCb
['insert']( _this
.rObj
);
498 $j( b_target
).append( $j
.btnHtml( gM( 'mwe-preview_insert' ), 'mv_preview_insert', 'refresh' ) + ' ' )
499 .children( '.mv_preview_insert' )
503 _this
.controlActionsCb
['preview']( _this
.rObj
);
507 $j( b_target
).append( $j
.btnHtml( gM( 'mwe-cancel_image_insert' ), 'mv_cancel_img_edit', 'close' ) + ' ' )
508 .children( '.mv_cancel_img_edit' )
512 _this
.controlActionsCb
['cancel']( _this
.rObj
);
518 applyEdit:function() {
520 js_log( 'applyEdit::' + this.media_type
);
521 if ( this.media_type
== 'image' ) {
523 } else if ( this.media_type
== 'video' ) {
524 this.applyVideoAdj();
526 // copy over the desc text to the resource object
527 _this
.rObj
['inlineDesc'] = $j( '#mv_inline_img_desc' ).val();
529 appendTool: function( $target
, tool_id
) {
534 '<span style="float:left;">Layout:</span>' +
535 '<input type="radio" name="mv_layout" id="mv_layout_left" style="float:left"></input>'+
536 '<div id="mv_layout_left_img" title="' + gM( 'mwe-layout_left' ) + '"></div>' +
537 '<input type="radio" name="mv_layout" id="mv_layout_right" style="float:left"></input>'+
538 '<div id="mv_layout_right_img" title="' + gM( 'mwe-layout_left' ) + '"></div>' +
539 '<hr style="clear:both" /><br/>'
541 // make sure the default is reflected:
542 if ( ! _this
.rObj
.layout
)
543 _this
.rObj
.layout
= 'right';
544 $j( '#mv_layout_' + _this
.rObj
.layout
)[0].checked
= true;
547 $j( '#mv_layout_left,#mv_layout_left_img' ).click( function() {
548 $j( '#mv_layout_right' )[0].checked
= false;
549 $j( '#mv_layout_left' )[0].checked
= true;
550 _this
.rObj
.layout
= 'left';
553 $j( '#mv_layout_right,#mv_layout_right_img' ).click( function() {
554 $j( '#mv_layout_left' )[0].checked
= false;
555 $j( '#mv_layout_right' )[0].checked
= true;
556 _this
.rObj
.layout
= 'right';
561 '<div class="mv_edit_button mv_crop_button_base" id="mv_crop_button" alt="crop" title="' + gM( 'mwe-crop' ) + '"/>' +
562 '<a href="#" class="mv_crop_msg">' + gM( 'mwe-crop' ) + '</a> ' +
563 '<span style="display:none" class="mv_crop_msg_load">' + gM( 'mwe-loading_txt' ) + '</span> ' +
564 '<a href="#" style="display:none" class="mv_apply_crop">' + gM( 'mwe-apply_crop' ) + '</a> ' +
565 '<a href="#" style="display:none" class="mv_reset_crop">' + gM( 'mwe-reset_crop' ) + '</a> ' +
566 '<hr style="clear:both"/><br>'
569 $j( '#mv_crop_button,.mv_crop_msg,.mv_apply_crop' ).click( function() {
570 js_log( 'click:mv_crop_button: base width: ' + _this
.rObj
.width
+ ' bh: ' + _this
.rObj
.height
);
571 if ( $j( '#mv_crop_button' ).hasClass( 'mv_crop_button_selected' ) ) {
574 js_log( 'click:turn on' );
578 $j( '.mv_reset_crop' ).click( function() {
579 $j( '.mv_apply_crop,.mv_reset_crop' ).hide();
580 $j( '.mv_crop_msg' ).show();
581 $j( '#mv_crop_button' ).removeClass( 'mv_crop_button_selected' ).addClass( 'mv_crop_button_base' ).attr( 'title', gM( 'mwe-crop' ) );
582 _this
.rObj
.crop
= null;
583 $j( '#' + _this
.clip_disp_ct
).empty().html(
584 '<img src="' + _this
.rObj
.edit_url
+ '" id="rsd_edit_img">'
590 '<div class="mv_edit_button mv_scale_button_base" id="mv_scale_button" alt="crop" title="'+gM('mwe-scale')+'"></div>'+
591 '<a href="#" class="mv_scale_msg">' + gM('mwe-scale') + '</a><br>'+
592 '<a href="#" style="display:none" class="mv_apply_scale">' + gM('mwe-apply_scale') + '</a> '+
593 '<a href="#" style="display:none" class="mv_reset_scale">' + gM('mwe-reset_scale') + '</a><br> '+
599 setUpImageCtrl:function() {
601 var $tool_target
= $j( '#' + this.control_ct
);
602 // by default apply Crop tool
603 if ( _this
.enabled_tools
== 'all' || _this
.enabled_tools
.length
> 0 ) {
604 $tool_target
.append( '<h3>' + gM( 'mwe-edit-tools' ) + '</h3>' );
605 for ( var i
in _this
.toolset
) {
606 var toolid
= _this
.toolset
[i
];
607 if ( $j
.inArray( toolid
, _this
.enabled_tools
) != -1 || _this
.enabled_tools
== 'all' )
608 _this
.appendTool( $tool_target
, toolid
);
611 // add the insert description text field:
612 $tool_target
.append( _this
.getInsertDescHtml() );
613 // add the actions to the 'button bar'
614 _this
.updateInsertControlActions();
616 applyVideoAdj:function() {
617 js_log( 'applyVideoAdj::' );
618 $tp
= $j( '#' + this.control_ct
);
620 // be sure to "stop the video (some plugins can't have DOM elements on top of them)
621 $j( '#embed_vid' ).get( 0 ).stop();
623 // update video related keys
624 this.rObj
['start_time'] = $tp
.find( '.startInOut' ).val();
625 this.rObj
['end_time'] = $tp
.find( '.endInOut' ).val() ;
627 // do the local video adjust
628 if ( typeof this.rObj
.pSobj
['applyVideoAdj'] != 'undefined' ) {
629 this.rObj
.pSobj
.applyVideoAdj( this.rObj
);
632 applyCrop:function() {
634 $j( '.mv_apply_crop' ).hide();
635 $j( '.mv_crop_msg' ).show();
636 $j( '#mv_crop_button' ).removeClass( 'mv_crop_button_selected' ).addClass( 'mv_crop_button_base' ).attr( 'title', gM( 'mwe-crop' ) );
637 js_log( 'click:turn off' );
638 var cat
= _this
.rObj
;
639 if ( _this
.rObj
.crop
) {
640 // empty out and display cropped:
641 $j( '#' + _this
.clip_disp_ct
).empty().html(
642 '<div id="mv_cropcotainer" style="overflow:hidden;position:absolute;' +
643 'width:' + _this
.rObj
.crop
.w
+ 'px;' +
644 'height:' + _this
.rObj
.crop
.h
+ 'px;">' +
645 '<div id="mv_crop_img" style="position:absolute;' +
646 'top:-' + _this
.rObj
.crop
.y
+ 'px;' +
647 'left:-' + _this
.rObj
.crop
.x
+ 'px;">' +
648 '<img src="' + _this
.rObj
.edit_url
+ '">' +
655 // right now enableCrop loads "just in time"
656 // @@todo we really need an "auto loader" type system.
657 enableCrop:function() {
659 $j( '.mv_crop_msg' ).hide();
660 $j( '.mv_crop_msg_load' ).show();
661 var doEnableCrop = function() {
662 $j( '.mv_crop_msg_load' ).hide();
663 $j( '.mv_reset_crop,.mv_apply_crop' ).show();
664 $j( '#mv_crop_button' ).removeClass( 'mv_crop_button_base' ).addClass( 'mv_crop_button_selected' ).attr( 'title', gM( 'mwe-crop_done' ) );
665 $j( '#' + _this
.clip_disp_ct
+ ' img' ).Jcrop( {
666 onSelect: function( c
) {
667 js_log( 'on select:' + c
.x
+ ',' + c
.y
+ ',' + c
.x2
+ ',' + c
.y2
+ ',' + c
.w
+ ',' + c
.h
);
670 onChange: function( c
) {
673 // temporary hack (@@todo need to debug why rsd_res_item gets moved )
674 $j( '#clip_edit_disp .rsd_res_item' ).css( {
679 // load the jcrop library if needed:
688 // mv_lock_vid_updates defined in mv_stream.js (we need to do some more refactoring )
689 if ( typeof mv_lock_vid_updates
== 'undefined' )
690 mv_lock_vid_updates
= false;
692 function add_adjust_hooks( mvd_id
, adj_callback
) {
694 var start_sec
= npt2seconds( $j( '#mv_start_hr_' + mvd_id
).val() );
695 var end_sec
= npt2seconds( $j( '#mv_end_hr_' + mvd_id
).val() );
697 // if we don't have 0 as start then assume we are in a range request and give some buffer area:
698 var min_slider
= ( start_sec
- 60 < 0 ) ? 0 : start_sec
- 60;
699 if ( min_slider
!= 0 ) {
700 var max_slider
= end_sec
+ 60;
702 max_slider
= end_sec
;
704 // pre-destroy just in case:
705 $j( '#mvd_form_' + mvd_id
+ ' .inOutSlider' ).slider( 'destroy' ).slider( {
709 values
: [start_sec
, end_sec
],
710 slide: function( event
, ui
) {
711 js_log( " vals:" + seconds2npt( ui
.values
[0] ) + ' : ' + seconds2npt( ui
.values
[1] ) );
712 $j( '#mv_start_hr_' + mvd_id
).val( seconds2npt( ui
.values
[0] ) );
713 $j( '#mv_end_hr_' + mvd_id
).val( seconds2npt( ui
.values
[1] ) );
715 change:function( event
, ui
) {
716 do_video_time_update( seconds2npt( ui
.values
[0] ), seconds2npt( ui
.values
[1] ) );
719 $j( '.mv_adj_hr' ).change( function() {
720 // preserve track duration for nav and seq:
721 // ie seems to crash so no interface updates for IE for the time being
722 if ( !$j
.browser
.msie
) {
723 if ( mvd_id
== 'nav' || mvd_id
== 'seq' ) {
724 add_adjust_hooks( mvd_id
); // (no adj_callback)
726 add_adjust_hooks( mvd_id
)
729 // update the video time for onChange
730 do_video_time_update( $j( '#mv_start_hr_' + mvd_id
).val(), $j( '#mv_end_hr_' + mvd_id
).val() );
734 function do_video_time_update( start_time
, end_time
, mvd_id
) {
735 js_log( 'do_video_time_update: ' + start_time
+ ' ' + end_time
);
736 if ( mv_lock_vid_updates
== false ) {
737 // update the vid title:
738 $j( '#mv_videoPlayerTime' ).html( start_time
+ ' to ' + end_time
);
739 var ebvid
= $j( '#embed_vid' ).get( 0 );
741 if ( ebvid
.isPaused() )
743 ebvid
.updateVideoTime( start_time
, end_time
);
744 js_log( 'update thumb: ' + start_time
);
745 ebvid
.updateThumbTimeNTP( start_time
);
750 // some custom jquery bindings:
752 $.fn
.upDownTimeInputBind = function( inputCB
) {
753 $( this.selector
).unbind( 'focus' ).focus( function() {
754 var doDelayCall
= true;
755 $( this ).addClass( 'ui-state-focus' );
757 $( this ).unbind( 'keydown' ).keydown( function ( e
) {
758 var sec
= npt2seconds( $j( this ).val() );
760 if ( k
== 38 ) {// up
761 $( this ).val( seconds2npt( sec
+ 1 ) );
762 } else if ( k
== 40 ) { // down
763 var sval
= ( ( sec
- 1 ) < 0 ) ? 0 : ( sec
- 1 )
764 $( this ).val( seconds2npt( sval
) );
766 // set the delay updates:
767 if ( k
== 38 || k
== 40 ) {
768 var _inputElm
= this;
770 setTimeout( function() {
771 inputCB( _inputElm
);
778 } ).unbind( 'blur' ).blur( function() {
779 $( this ).removeClass( 'ui-state-focus' );