* don't display preview button on passthrough uploads (.tiff images etc)
[lhc/web/wiklou.git] / js2 / mwEmbed / libAddMedia / mvFirefogg.js
1 /* adds firefogg support.
2 * autodetects: new upload api or old http POST.
3 */
4
5 loadGM({
6 "fogg-select_file" : "Select file",
7 "fogg-select_new_file" : "Select new file",
8 "fogg-select_url" : "Select URL",
9 "fogg-save_local_file" : "Save Ogg",
10 "fogg-check_for_fogg" : "Checking for Firefogg <blink>...<\/blink>",
11 "fogg-installed" : "Firefogg is installed",
12 "fogg-for_improved_uplods" : "For improved uploads:",
13 "fogg-please_install" : "<a href=\"$1\">Install Firefogg<\/a>. More <a href=\"http:\/\/commons.wikimedia.org\/wiki\/Commons:Firefogg\">about Firefogg<\/a>",
14 "fogg-use_latest_fox" : "Please first install <a href=\"http:\/\/www.mozilla.com\/en-US\/firefox\/upgrade.html?from=firefogg\">Firefox 3.5<\/a> (or later). <i>Then revisit this page to install the <b>Firefogg<\/b> extension.<\/i>",
15 "fogg-passthrough_mode" : "Your selected file is already Ogg or not a video file",
16 "fogg-transcoding" : "Encoding video to Ogg",
17 "fogg-encoding-done" : "Encoding complete",
18 "fogg-badtoken" : "Token is not valid",
19 "fogg-preview" : "Preview video",
20 "fogg-hidepreview" : "Hide preview"
21 });
22
23 var firefogg_install_links = {
24 'macosx': 'http://firefogg.org/macosx/Firefogg.xpi',
25 'win32': 'http://firefogg.org/win32/Firefogg.xpi',
26 'linux' : 'http://firefogg.org/linux/Firefogg.xpi'
27 };
28
29 var default_firefogg_options = {
30 //what to do when finished uploading
31 'done_upload_cb':false,
32 //if firefoog is enabled
33 'fogg_enabled':false,
34 //the api url to upload to
35 'api_url':null,
36 //the passthrough flag (enables un-modified uploads)
37 'passthrough': false,
38 //if we will be showing the encoder interface
39 'encoder_interface': false,
40 //if we want to limit the library functionality to "only firefoog" (no upload or progress bars)
41 'only_fogg': false,
42
43
44 //callbacks:
45 'new_source_cb': false, //called on source name update passes along source name
46
47 //target control container or form (can't be left null)
48 'selector': '',
49
50 //if not rewriting a form we are encoding local.
51 'form_rewrite': false,
52
53 //taget buttons:
54 'target_btn_select_file': false,
55 'target_btn_select_new_file': false,
56
57 //'target_btn_select_url': false,
58
59 'target_btn_save_local_file': false,
60 'target_input_file_name': false,
61
62
63 //target install descriptions
64 'target_check_for_fogg': false,
65 'target_installed': false,
66 'target_please_install': false,
67 'target_use_latest_fox': false,
68 //status:
69 'target_passthrough_mode':false,
70
71 //if firefogg should take over the form submit action
72 'firefogg_form_action':true,
73
74 //if we should show a preview of encoding progress
75 'show_preview':false,
76 }
77
78
79 var mvFirefogg = function(iObj){
80 return this.init( iObj );
81 }
82 mvFirefogg.prototype = { //extends mvBaseUploadInterface
83
84 min_firefogg_version : '0.9.9.5',
85 fogg_enabled : false, //if firefogg is enabled or not.
86 encoder_settings:{ //@@todo allow server to set this
87 'maxSize' : '400',
88 'videoBitrate' : '544',
89 'audioBitrate' : '96',
90 'noUpscaling' : true
91 },
92 sourceFileInfo: {},
93 ogg_extensions: ['ogg', 'ogv', 'oga'],
94 video_extensions: ['avi', 'mov', 'mp4', 'mp2', 'mpeg', 'mpeg2', 'mpeg4', 'dv', 'wmv'],
95
96 passthrough: false,
97 sourceMode: 'file',
98
99 init: function( iObj ){
100 if(!iObj)
101 iObj = {};
102
103 //if we have no api_url set upload to "post"
104 if(!iObj.api_url)
105 iObj.upload_mode = 'post';
106
107 //inherit iObj properties:
108 for(var i in default_firefogg_options){
109 if(iObj[i]){
110 this[i] = iObj[i];
111 }else{
112 this[i] = default_firefogg_options[i];
113 }
114 }
115 //check if we want to limit the usage:
116 if(!this.only_fogg){
117 var myBUI = new mvBaseUploadInterface( iObj );
118
119 //standard extends code:
120 for(var i in myBUI){
121 if(this[i]){
122 this['pe_'+ i] = myBUI[i];
123 }else{
124 this[i] = myBUI[i];
125 }
126 }
127 }
128
129 if(!this.selector){
130 js_log('firefogg: missing selector ');
131 }
132 },
133 doRewrite:function( callback ){
134 var _this = this;
135 js_log('sel len: ' + this.selector + '::' + $j(this.selector).length + ' tag:'+ $j(this.selector).get(0).tagName);
136 if( $j(this.selector).length >=0 ){
137
138 if( $j(this.selector).get(0).tagName.toLowerCase() == 'input' ){
139 _this.form_rewrite = true;
140 }
141 }
142 //check if we are rewriting an input or a form:
143 if( this.form_rewrite ){
144 this.setupForm();
145 }else{
146 this.doControlHTML();
147 this.doControlBindings();
148 }
149
150 //doRewrite is done:
151 if(callback)
152 callback();
153 },
154 doControlHTML: function( ){
155 var _this = this;
156 var out = '';
157 $j.each(default_firefogg_options, function(target, na){
158 if(target.substring(0, 6)=='target'){
159 //js_log('check for target html: ' + target);
160 //check for the target if missing add to the output:
161 if( _this[target] === false){
162 out += _this.getTargetHtml(target) + ' ';
163 //update the target selector
164 _this[target] = _this.selector + ' .' + target;
165 }
166 }
167 });
168 $j( this.selector ).append( out ).hide();
169 },
170 getTargetHtml:function(target){
171 if( target.substr(7,3)=='btn'){
172 return '<input style="" class="' + target + '" type="button" value="' + gM( 'fogg-' + target.substring(11)) + '"/> ';
173 }else if(target.substr(7,5)=='input'){
174 return '<input style="" class="' + target + '" type="text" value="' + gM( 'fogg-' + target.substring(11)) + '"/> ';
175 }else{
176 return '<div style="" class="' + target + '" >'+ gM('fogg-'+ target.substring(7)) + '</div> ';
177 }
178 },
179 doControlBindings: function(){
180 var _this = this;
181
182 //hide all targets:
183 var hide_target_list='';
184 var coma='';
185 $j.each(default_firefogg_options, function(target, na){
186 if(target.substring(0, 6)=='target'){
187 hide_target_list+=coma + _this[target];
188 coma=',';
189 }
190 });
191 $j( hide_target_list ).hide();
192 //now that the proper set of items has been hiiden show:
193 $j( this.selector ).show();
194
195
196 //hide all but check-for-fogg
197 //check for firefogg
198 if( _this.firefoggCheck() ){
199
200 //if rewriting the form lets keep the text input around:
201 if( _this.form_rewrite )
202 $j(this.target_input_file_name).show();
203
204 //show select file:
205 $j( this.target_btn_select_file ).unbind(
206 ).attr('disabled', false
207 ).css({'display':'inline'}
208 ).click(function(){
209 _this.selectFogg();
210 });
211
212 //also setup the text file display on Click to select file:
213 $j(this.target_input_file_name).unbind().attr('readonly', 'readonly').click(function(){
214 _this.selectFogg();
215 })
216
217 }else{
218 //first check firefox version:
219 if(!( $j.browser.mozilla && $j.browser.version >= '1.9.1' )) {
220 js_log( 'show use latest::' + _this.target_use_latest_fox );
221 if( _this.target_use_latest_fox ){
222 if( _this.form_rewrite )
223 $j( _this.target_use_latest_fox ).prepend( gM('fogg-for_improved_uplods') );
224
225 $j( _this.target_use_latest_fox ).show();
226 }
227 return ;
228 }
229
230 //if rewriting form use upload msg text
231 var upMsg = (_this.form_rewrite) ? gM('fogg-for_improved_uplods') : '';
232 $j( _this.target_please_install ).html( upMsg + gM('fogg-please_install', _this.getOSlink() )).css('padding', '10px').show();
233 }
234 //setup the target save local file bindins:
235 $j( _this.target_btn_save_local_file ).unbind().click(function(){
236 _this.saveLocalFogg();
237 });
238 },
239 /*
240 * returns the firefogg link for your os:
241 */
242 getOSlink:function(){
243 var os_link = false;
244 if(navigator.oscpu){
245 if(navigator.oscpu.search('Linux') >= 0)
246 os_link = firefogg_install_links['linux'];
247 else if(navigator.oscpu.search('Mac') >= 0)
248 os_link = firefogg_install_links['macosx'];
249 else if(navigator.oscpu.search('Win') >= 0)
250 os_link = firefogg_install_links['win32'];
251 }
252 return os_link
253 },
254 firefoggCheck:function(){
255 if(typeof(Firefogg) != 'undefined' && Firefogg().version >= this.min_firefogg_version){
256 this.fogg = new Firefogg();
257 this.fogg_enabled = true;
258 return true;
259 }else{
260 return false;
261 }
262 },
263 //assume input target
264 setupForm: function(){
265 js_log('firefogg::setupForm::');
266 //to parent form setup if we want http updates
267 if( this.form_rewrite ){
268 //do parent form setup:
269 this.pe_setupForm();
270 }
271
272 //check if we have firefogg (if not just add a link and stop proccessing)
273 if( !this.firefoggCheck() ){
274 //add some status indicators if not provided:
275 if(!this.target_please_install){
276 $j(this.selector).after ( this.getTargetHtml('target_please_install') );
277 this.target_please_install = this.selector + ' ~ .target_please_install';
278 }
279 if(!this.target_use_latest_fox){
280 $j(this.selector).after ( this.getTargetHtml('target_use_latest_fox') );
281 this.target_use_latest_fox = this.selector + ' ~ .target_use_latest_fox';
282 }
283 //update download link:
284 this.doControlBindings();
285 return ;
286 }
287
288 //change the file browser to type text: (can't directly change input from "file" to "text" so longer way:
289 var inTag = '<input ';
290 $j.each($j(this.selector).get(0).attributes, function(i, attr){
291 var val = attr.value;
292 if( attr.name == 'type')
293 val = 'text';
294 inTag += attr.name + '="' + val + '" ';
295 });
296 if(!$j(this.selector).attr('style'))
297 inTag += 'style="display:inline" ';
298
299 inTag+= '/><span id="' + $j(this.selector).attr('name') + '_fogg-control"></span>';
300
301 js_log('set input: ' + inTag);
302 $j(this.selector).replaceWith(inTag);
303
304 this.target_input_file_name = 'input[name=' + $j(this.selector).attr('name') + ']';
305 //update the selector to the control target:
306 this.selector = '#' + $j(this.selector).attr('name') + "_fogg-control";
307
308 this.doControlHTML();
309 //check for the other inline status indicator targets:
310
311 //update the bindings:
312 this.doControlBindings();
313 },
314 //do firefogg specific additions:
315 dispProgressOverlay:function(){
316 this.pe_dispProgressOverlay();
317 //if we are uploading video (not in passthrough mode show preview button)
318 if( ! this.encoder_settings['passthrough'] ){
319 this.doPreviewControl();
320 }
321 },
322 doPreviewControl:function(){
323 var _this = this;
324 //prepend preview collapable
325 $j('#upProgressDialog').append(
326 '<div style="clear:both;height:3em"/>'+
327 $j.btnHtml(gM('fogg-preview'), 'fogg_preview', 'triangle-1-e') +
328 '<div style="padding:10px;">' +
329 '<canvas style="margin:auto;" id="fogg_preview_canvas" />' +
330 '</div>'
331 );
332 //set initial state
333 if( _this.show_preview == true){
334 $j('#fogg_preview_canvas').show();
335 }else{
336 $j('#fogg_preview_canvas').hide();
337 }
338 //apply preview binding:
339 $j('#upProgressDialog .fogg_preview').btnBind().click( function(){
340 js_log("click .foog_preview" + $j(this).children('.ui-icon').attr('class') );
341 //check state:
342 if( $j(this).children('.ui-icon').hasClass('ui-icon-triangle-1-e') ){
343 _this.show_preview = true;
344 //update icon:
345 $j(this).children('.ui-icon')
346 .removeClass('ui-icon-triangle-1-e')
347 .addClass('ui-icon-triangle-1-s');
348 //update text
349 $j(this).children('.btnText').text( gM('fogg-hidepreview') );
350
351 //show preview window
352 $j('#fogg_preview_canvas').show('fast');
353 }else{
354 _this.show_preview = false;
355 //update icon:
356 $j(this).children('.ui-icon')
357 .removeClass('ui-icon-triangle-1-s')
358 .addClass('ui-icon-triangle-1-e');
359 //update text:
360 $j(this).children('.btnText').text( gM('fogg-preview') );
361
362 $j('#fogg_preview_canvas').hide('slow');
363 }
364 //don't follow the #
365 return false;
366 });
367 },
368 doRenderPreview:function(){
369 var _this = this;
370 //set up the hidden video to pull frames from:
371 if( $j('#fogg_preview_vid').length == 0 )
372 $j('body').append('<video id="fogg_preview_vid" style="display:none"></video>');
373 var v = $j('#fogg_preview_vid').get(0);
374
375 function seekToEnd(){
376 var v = $j('#fogg_preview_vid').get(0);
377 v.currentTime = v.duration-0.4;
378 }
379 function getFrame() {
380 var v = $j('#fogg_preview_vid').get(0);
381 var canvas = $j('#fogg_preview_canvas').get(0);
382 canvas.width = 160;
383 canvas.height = canvas.width * v.videoHeight/v.videoWidth;
384 var ctx = canvas.getContext("2d");
385 ctx.drawImage(v, 0, 0, canvas.width, canvas.height);
386 }
387 var previewI=null;
388 function preview() {
389 //initialize the video if not setup already:
390 var v = $j('#fogg_preview_vid').get(0);
391 if( v.src != _this.fogg.previewUrl ){
392 js_log('init preview with url:' + _this.fogg.previewUrl);
393 v.src = _this.fogg.previewUrl;
394
395 //set the video to seek to the end of the video
396 v.removeEventListener("loadedmetadata", seekToEnd, true);
397 v.addEventListener("loadedmetadata", seekToEnd, true);
398
399 //render a frame once seek is complete:
400 v.removeEventListener("seeked", getFrame, true);
401 v.addEventListener("seeked", getFrame, true);
402
403 //refresh the video duration/meta:
404 clearInterval(previewI);
405 var previewI = setInterval(function(){
406 if (_this.fogg.status() != "encoding"){
407 clearInterval(previewI);
408 }
409 v.load();
410 }, 1000);
411 }
412 }
413 preview();
414 },
415 getEditForm:function(){
416 if( this.target_edit_from )
417 return this.pe_getEditForm();
418 //else try to get the parent "from" of the file selector:
419 return $j(this.selector).parents('form:first').get(0);
420 },
421 selectFogg:function(){
422 var _this = this;
423 if(_this.fogg.selectVideo() ){
424 this.selectFoggActions();
425 }
426 },
427 selectFoggActions:function(){
428 var _this = this;
429 js_log('videoSelectReady');
430 //if not already hidden hide select file and show "select new":
431 $j(_this.target_btn_select_file).hide();
432
433 //show and setup binding for select new file:
434 $j(_this.target_btn_select_new_file).show().unbind().click(function(){
435 //create new fogg instance:
436 _this.fogg = new Firefogg();
437 _this.selectFogg();
438 });
439
440 //update if we are in passthrough mode or going to encode
441 if( _this.fogg.sourceInfo && _this.fogg.sourceFilename ){
442 //update the source status
443 try{
444 _this.sourceFileInfo = JSON.parse( _this.fogg.sourceInfo ) ;
445 }catch (e){
446 js_error('error could not parse fogg sourceInfo');
447 }
448
449 //now setup encoder settings based source type:
450 _this.autoEncoderSettings();
451
452 //if set to passthough update the interface:
453 if(_this.encoder_settings['passthrough'] == true){
454 $j(_this.target_passthrough_mode).show();
455 }else{
456 $j(_this.target_passthrough_mode).hide();
457 //if set to encoder expose the encode button:
458 if( !_this.form_rewrite ){
459 $j(_this.target_btn_save_local_file).show();
460 }
461 }
462 //~otherwise the encoding will be triggered by the form~
463
464 //do source name update callback:
465 js_log(" should update: " + _this.target_input_file_name + ' to: ' + _this.fogg.sourceFilename );
466 $j(_this.target_input_file_name).val(_this.fogg.sourceFilename).show();
467
468 if(_this.new_source_cb){
469 if(_this.encoder_settings['passthrough']){
470 var fName = _this.fogg.sourceFilename
471 }else{
472 var oggExt = (_this.isSourceAudio())?'oga':'ogg';
473 oggExt = (_this.isSourceVideo())?'ogv':oggExt;
474 oggExt = (_this.isUnknown())?'ogg':oggExt;
475 oggName = _this.fogg.sourceFilename.substr(0,
476 _this.fogg.sourceFilename.lastIndexOf('.'));
477 var fName = oggName +'.'+ oggExt
478 }
479 _this.new_source_cb( _this.fogg.sourceFilename , fName);
480 }
481 }
482 },
483 saveLocalFogg:function(){
484 //request target location:
485 if(this.fogg){
486 if(!this.fogg.saveVideoAs() )
487 return false;
488
489 //we have set a target now call the encode:
490 this.doEncode();
491 }
492 },
493 //simple auto encoder settings just enable passthough if file is not video or > 480 pixles tall
494 autoEncoderSettings:function(){
495 var _this = this;
496 //grab the extension:
497 var sf = _this.fogg.sourceFilename;
498 var ext = '';
499 if( sf.lastIndexOf('.') != -1){
500 ext = sf.substring( sf.lastIndexOf('.')+1 ).toLowerCase();
501 }
502
503 //set to passthrough to true by default (images, arbitrary files that we want to send with http chunks)
504 this.encoder_settings['passthrough'] = true;
505
506 //see if we have video or audio:
507 if( _this.isSourceAudio() || _this.isSourceVideo() ){
508 _this.encoder_settings['passthrough'] = false;
509 }
510
511 //special case see if we already have ogg video:
512 if( _this.isOggFormat() ){
513 _this.encoder_settings['passthrough'] = true;
514 }
515
516 js_log('base autoEncoderSettings::' + _this.sourceFileInfo.contentType + ' passthrough:' + _this.encoder_settings['passthrough']);
517 },
518 isUnknown:function(){
519 return (this.sourceFileInfo.contentType.indexOf("unknown") != -1);
520 },
521 isSourceAudio:function(){
522 return (this.sourceFileInfo.contentType.indexOf("audio/") != -1);
523 },
524 isSourceVideo:function(){
525 return (this.sourceFileInfo.contentType.indexOf("video/") != -1);
526 },
527 isOggFormat:function(){
528 return ( this.sourceFileInfo.contentType.indexOf("video/ogg") != -1 ||
529 this.sourceFileInfo.contentType.indexOf("application/ogg") != -1 );
530 },
531 getProgressTitle:function(){
532 js_log("fogg:getProgressTitle f:" + this.fogg_enabled + ' rw:' + this.form_rewrite);
533 //return the parent if we don't have fogg turned on:
534 if(! this.fogg_enabled || !this.firefogg_form_action )
535 return this.pe_getProgressTitle();
536 if( !this.form_rewrite )
537 return gM('fogg-transcoding');
538 //else return our upload+transcode msg:
539 return gM('mwe-upload-transcode-in-progress');
540 },
541 doUploadSwitch:function(){
542 var _this = this;
543 js_log("firefogg: doUploadSwitch:: " + this.fogg_enabled + ' up mode:' + _this.upload_mode);
544 //make sure firefogg is enabled otherwise do parent UploadSwich:
545 if( !this.fogg_enabled || !this.firefogg_form_action )
546 return _this.pe_doUploadSwitch();
547
548 //check what mode to use firefogg in:
549 if( _this.upload_mode == 'post' ){
550 _this.doEncode();
551 }else if( _this.upload_mode == 'api' ){ //if api mode and chunks supported do chunkUpload
552 _this.doChunkUpload();
553 }else{
554 js_error( 'Error: unrecongized upload mode: ' + _this.upload_mode );
555 }
556 },
557 //doChunkUpload does both uploading and encoding at the same time and uploads one meg chunks as they are ready
558 doChunkUpload : function(){
559 js_log('firefogg::doChunkUpload');
560 var _this = this;
561 _this.action_done = false;
562
563 //extension should already be ogg but since its user editable,
564 //check again
565 //we are transcoding so we know it will be an ogg
566 //(should not be done for passthrough mode)
567 var sf = _this.formData['filename'];
568 var ext = '';
569 if( sf.lastIndexOf('.') != -1){
570 ext = sf.substring( sf.lastIndexOf('.') ).toLowerCase();
571 }
572 if( !_this.encoder_settings['passthrough'] && $j.inArray(ext.substr(1), _this.ogg_extensions) == -1 ){
573 var extreg = new RegExp(ext + '$', 'i');
574 _this.formData['filename'] = sf.replace(extreg, '.ogg');
575 }
576 //add chunk response hook to build the resultURL when uploading chunks
577
578 //check for editToken:
579 if(!this.etoken){
580 js_log('missing token try ' + _this.formData['token']);
581 if( _this.formData['token']){
582 _this.etoken = _this.formData['token'];
583 _this.doChunkWithFormData();
584 }else{
585 get_mw_token(
586 'File:'+ _this.formData['filename'],
587 _this.api_url,
588 function( eToken ){
589 if( !eToken || eToken == '+\\' ){
590 _this.updateProgressWin( gM('fogg-badtoken'), gM('fogg-badtoken') );
591 return false;
592 }
593 _this.etoken = eToken;
594 _this.doChunkWithFormData();
595 }
596 );
597 }
598 }else{
599 js_log('we already have token: ' + this.etoken);
600 _this.doChunkWithFormData();
601 }
602 },
603 doChunkWithFormData:function(){
604 var _this = this;
605 js_log("firefogg::doChunkWithFormData" + _this.etoken);
606 //build the api url:
607 var aReq ={
608 'action': 'upload',
609 'format': 'json',
610 'filename': _this.formData['filename'],
611 'comment': _this.formData['comment'],
612 'enablechunks': 'true'
613 };
614
615 if( _this.etoken )
616 aReq['token'] = this.etoken;
617
618 if( _this.formData['watch'] )
619 aReq['watch'] = _this.formData['watch'];
620
621 if( _this.formData['ignorewarnings'] )
622 aReq['ignorewarnings'] = _this.formData['ignorewarnings'];
623
624 js_log('do fogg upload/encode call: '+ _this.api_url + ' :: ' + JSON.stringify( aReq ) );
625 js_log('foggEncode: '+ JSON.stringify( _this.encoder_settings ) );
626 _this.fogg.upload( JSON.stringify( _this.encoder_settings ), _this.api_url , JSON.stringify( aReq ) );
627
628 //update upload status:
629 _this.doUploadStatus();
630 },
631 //doEncode and monitor progress:
632 doEncode : function(){
633 var _this = this;
634 _this.action_done = false;
635 _this.dispProgressOverlay();
636 js_log('doEncode: with: ' + JSON.stringify( _this.encoder_settings ) );
637 _this.fogg.encode( JSON.stringify( _this.encoder_settings ) );
638
639 //show transcode status:
640 $j('#up-status-state').html( gM('mwe-upload-transcoded-status') );
641
642 //setup a local function for timed callback:
643 var encodingStatus = function() {
644 var status = _this.fogg.status();
645
646 if( _this.show_preview == true ){
647 _this.doRenderPreview();
648 }
649
650 //update progress bar
651 _this.updateProgress( _this.fogg.progress() );
652
653 //loop to get new status if still encoding
654 if( _this.fogg.state == 'encoding' ) {
655 setTimeout(encodingStatus, 500);
656 }else if ( _this.fogg.state == 'encoding done' ) { //encoding done, state can also be 'encoding failed
657 _this.encodeDone();
658 }else if(_this.fogg.state == 'encoding fail'){
659 //@@todo error handling:
660 js_error('encoding failed');
661 }
662 }
663 encodingStatus();
664 },
665 encodeDone:function(){
666 var _this = this;
667 js_log('::encodeDone::');
668 _this.action_done = true;
669 //send to the post url:
670 if( _this.form_rewrite && _this.upload_mode == 'post' ){
671 js_log('done with encoding do POST upload:' + _this.editForm.action);
672 // ignore warnings & set source type
673 //_this.formData[ 'wpIgnoreWarning' ]='true';
674 _this.formData[ 'wpSourceType' ] = 'upload';
675 _this.formData[ 'action' ] = 'submit';
676 //wpUploadFile is set by firefogg
677 delete _this.formData[ 'file' ];
678
679 _this.fogg.post( _this.editForm.action, 'wpUploadFile', JSON.stringify( _this.formData ) );
680 //update upload status:
681 _this.doUploadStatus();
682 }else{
683 js_log("done with encoding (no upload) ");
684 //set stuats to 100% for one second:
685 _this.updateProgress( 1 );
686 setTimeout(function(){
687 _this.updateProgressWin(gM('fogg-encoding-done'),
688 gM('fogg-encoding-done') + '<br>' +
689 //show the video at full resolution upto 720px wide
690 '<video controls="true" style="margin:auto" id="fogg_final_vid" src="' +
691 _this.fogg.previewUrl + '"></video>'
692 );
693 //load the video and set a callback:
694 var v = $j('#fogg_final_vid').get(0);
695 function resizeVid(){
696 var v = $j('#fogg_final_vid').get(0);
697 if( v.videoWidth > 720 ){
698 $j(v).css({
699 'width':720,
700 'height': 720 * (v.videoHeight/v.videoWidth)
701 });
702 }else{
703 $j(v).css({
704 'width': v.videoWidth,
705 'height': v.videoHeight
706 });
707 }
708 }
709
710 //set flag to diplay video at res
711 v.removeEventListener("loadedmetadata", resizeVid, true);
712 v.addEventListener("loadedmetadata", resizeVid, true);
713 v.load();
714
715 }, 1000);
716 }
717 },
718 doUploadStatus:function() {
719 var _this = this;
720 $j( '#up-status-state' ).html( gM('mwe-uploaded-status') );
721
722 _this.oldResponseText = '';
723 //setup a local function for timed callback:
724 var uploadStatus = function(){
725 //get the response text:
726 var response_text = _this.fogg.responseText;
727 if(!response_text){
728 try{
729 var pstatus = JSON.parse( _this.fogg.uploadstatus() );
730 response_text = pstatus["responseText"];
731 }catch(e){
732 js_log("could not parse uploadstatus / could not get responseText");
733 }
734 }
735
736 if( _this.oldResponseText != response_text){
737 js_log('new result text:' + response_text + ' state:' + _this.fogg.state);
738 _this.oldResponseText = response_text;
739 //try and parse the response text and check for errors
740 try{
741 var apiResult = JSON.parse( response_text );
742 }catch(e){
743 js_log("could not parse response_text::" + response_text + ' ...for now try with eval...');
744 try{
745 var apiResult = eval( response_text );
746 }catch(e){
747 var apiResult = null;
748 }
749 }
750 if(apiResult && _this.apiUpdateErrorCheck( apiResult ) === false){
751 //stop status update we have an error
752 _this.action_done = true;
753 _this.fogg.cancel();
754 return false;
755 }
756 }
757 if( _this.show_preview == true ){
758 if( _this.fogg.state == 'encoding' ){
759 _this.doRenderPreview();
760 }
761 }
762
763 //update progress bar
764 _this.updateProgress( _this.fogg.progress() );
765
766 //loop to get new status if still uploading (could also be encoding if we are in chunk upload mode)
767 if( _this.fogg.state == 'encoding' || _this.fogg.state == 'uploading') {
768 setTimeout(uploadStatus, 100);
769 }//check upload state
770 else if( _this.fogg.state == 'upload done' ||
771 _this.fogg.state == 'done' ||
772 _this.fogg.state == 'encoding done' ) {
773 //if in "post" upload mode read the html response (should be depricated):
774 if( _this.upload_mode == 'api' ){
775 if( apiResult && apiResult.resultUrl ){
776 var buttons ={};
777 buttons[gM('mwe-go-to-resource')] = function(){
778 window.location = apiResult.resultUrl;
779 }
780 var go_to_url_txt = gM('mwe-go-to-resource');
781 if( typeof _this.done_upload_cb == 'function' ){
782 //if done action return 'true'
783 if( _this.done_upload_cb( _this.formData ) ){
784 //update status
785 _this.updateProgressWin( gM('mwe-successfulupload'), gM( 'mwe-upload_done', apiResult.resultUrl),buttons);
786 }else{
787 //if done action returns 'false' //close progress window
788 this.action_done = true;
789 $j('#upProgressDialog').empty().dialog('close');
790 }
791 }else{
792 //update status (without done_upload_cb)
793 _this.updateProgressWin( gM('mwe-successfulupload'), gM( 'mwe-upload_done', apiResult.resultUrl),buttons);
794 }
795 }else{
796 //done state with error? ..not really possible given how firefogg works
797 js_log(" Upload done in chunks mode, but no resultUrl!");
798 }
799 }else if( _this.upload_mode == 'post' && _this.api_url ) {
800 _this.procPageResponse( response_text );
801 }
802 }else{
803 //upload error:
804 js_log('Error:firefogg upload error: ' + _this.fogg.state );
805 }
806 }
807 uploadStatus();
808 },
809 cancel_action:function( dlElm ){
810 if(!this.fogg_enabled){
811 return this.pe_cancel_action();
812 }
813 js_log('firefogg:cancel')
814 if( confirm( gM('mwe-cancel-confim') )){
815 if(navigator.oscpu && navigator.oscpu.search('Win') >= 0){
816 alert( 'sorry we do not yet support cancel on windows' );
817 }else{
818 this.action_done = true;
819 this.fogg.cancel();
820 $j(dlElm).empty().dialog('close');
821 }
822 } else{
823 return false;
824 }
825 },
826 /**
827 * procPageResponse should be faded out in favor of the upload api soon..
828 * its all very fragile to read the html output and guess at stuff
829 */
830 procPageResponse:function( result_page ){
831 var _this = this;
832 js_log('f:procPageResponse');
833 var sstring = 'var wgTitle = "' + this.formData['filename'].replace('_',' ');
834
835 if(wgArticlePath){
836 var result_txt = gM('mwe-upload_done', wgArticlePath.replace(/\$1/, 'File:' + _this.formData['filename'] ) );
837 }else{
838 result_txt = 'File has uploaded but api "done" URL was provided. Check the log for result page output';
839 }
840
841 //set the error text in case we dont' get far along in processing the response
842 _this.updateProgressWin( gM('mwe-upload_completed'), result_txt );
843
844 if( result_page && result_page.toLowerCase().indexOf( sstring.toLowerCase() ) != -1){
845 js_log( 'upload done got redirect found: ' + sstring + ' r:' + _this.done_upload_cb );
846 if( _this.done_upload_cb == 'redirect' ){
847 $j( '#dlbox-centered' ).html( '<h3>Upload Completed:</h3>' + result_txt + '<br>' + form_txt);
848 window.location = wgArticlePath.replace( /\$1/, 'File:' + _this.formData['wpDestFile'] );
849 }else{
850 //check if the add_done_action is a callback:
851 if( typeof _this.done_upload_cb == 'function' )
852 _this.done_upload_cb();
853 }
854 }else{
855 //js_log( 'upload page error: did not find: ' +sstring + ' in ' + "\n" + result_page );
856 var form_txt = '';
857 if( !result_page ){
858 //@@todo fix this:
859 //the mediaWiki upload system does not have an API so we can\'t read errors
860 }else{
861 var res = grabWikiFormError( result_page );
862
863 if(res.error_txt)
864 result_txt = res.error_txt;
865
866 if(res.form_txt)
867 form_txt = res.form_txt;
868 }
869 js_log( 'error text is: ' + result_txt );
870 $j( '#dlbox-centered' ).html( '<h3>' + gM('mwe-upload_completed') + '</h3>' + result_txt + '<br>' + form_txt);
871 }
872 }
873 };