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' );