1/*jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: false, strict: true, newcap: true, immed: true, sloppy: true, browser: true */ 2/*global jQuery, DOKU_BASE, LANG, bind, DokuCookie, opener, confirm*/ 3 4/** 5 * JavaScript functionality for the media management popup 6 * 7 * @author Andreas Gohr <andi@splitbrain.org> 8 * @author Pierre Spring <pierre.spring@caillou.ch> 9 */ 10 11var dw_mediamanager = { 12 keepopen: false, 13 hide: false, 14 popup: false, 15 display: false, 16 ext: false, 17 $popup: null, 18 19 // Image insertion opts 20 align: false, 21 link: false, 22 size: false, 23 forbidden_opts: {}, 24 25 init: function () { 26 var $content, $tree; 27 $content = jQuery('#media__content'); 28 $tree = jQuery('#media__tree'); 29 30 dw_mediamanager.prepare_content($content); 31 32 dw_mediamanager.attachoptions(); 33 dw_mediamanager.initpopup(); 34 35 // add the action to autofill the "upload as" field 36 $content.delegate('#upload__file', 'change', dw_mediamanager.suggest) 37 // Attach the image selector action to all links 38 .delegate('a.select', 'click', dw_mediamanager.select) 39 // Attach deletion confirmation dialog to the delete buttons 40 .delegate('#media__content a.btn_media_delete', 'click', 41 dw_mediamanager.confirmattach); 42 43 $tree.dw_tree({toggle_selector: 'img', 44 load_data: function (show_sublist, $clicky) { 45 // get the enclosed link (is always the first one) 46 var $link = $clicky.parent().find('div.li a.idx_dir'); 47 48 jQuery.post( 49 DOKU_BASE + 'lib/exe/ajax.php', 50 $link[0].search.substr(1) + '&call=medians', 51 show_sublist, 52 'html' 53 ); 54 }, 55 56 toggle_display: function ($clicky, opening) { 57 $clicky.attr('src', 58 DOKU_BASE + 'lib/images/' + 59 (opening ? 'minus' : 'plus') + '.gif'); 60 }}); 61 $tree.delegate('a', 'click', dw_mediamanager.list); 62 63 jQuery('#mediamanager__layout_list').delegate('#mediamanager__tabs_files a', 'click', dw_mediamanager.list) 64 .delegate('#mediamanager__tabs_list a', 'click', dw_mediamanager.list_view) 65 .delegate('#mediamanager__file_list a', 'click', dw_mediamanager.details) 66 .delegate('#dw__mediasearch', 'submit', dw_mediamanager.list) 67 .delegate('#upload__file', 'change', dw_mediamanager.suggest); 68 69 jQuery('#mediamanager__layout_detail').delegate('#mediamanager__tabs_details a', 'click', dw_mediamanager.details) 70 .delegate('#mediamanager__btn_update', 'submit', dw_mediamanager.list) 71 .delegate('#page__revisions', 'submit', dw_mediamanager.details) 72 .delegate('#page__revisions a', 'click', dw_mediamanager.details) 73 .delegate('#mediamanager__save_meta', 'submit', dw_mediamanager.details) 74 .delegate('#mediamanager__btn_delete', 'submit', dw_mediamanager.details) 75 .delegate('#mediamanager__btn_restore', 'submit', dw_mediamanager.details); 76 77 }, 78 79 /** 80 * build the popup window 81 * 82 * @author Dominik Eckelmann <eckelmann@cosmocode.de> 83 */ 84 initpopup: function () { 85 var opts, $insp, $insbtn; 86 87 dw_mediamanager.$popup = jQuery(document.createElement('div')) 88 .attr('id', 'media__popup_content') 89 .dialog({autoOpen: false, width: 280, modal: true, 90 draggable: true, title: LANG.mediatitle, 91 resizable: false}); 92 93 opts = [{id: 'link', label: LANG.mediatarget, 94 btns: ['lnk', 'direct', 'nolnk', 'displaylnk']}, 95 {id: 'align', label: LANG.mediaalign, 96 btns: ['noalign', 'left', 'center', 'right']}, 97 {id: 'size', label: LANG.mediasize, 98 btns: ['small', 'medium', 'large', 'original']} 99 ]; 100 101 jQuery.each(opts, function (_, opt) { 102 var $p, $l; 103 $p = jQuery(document.createElement('p')) 104 .attr('id', 'media__' + opt.id); 105 106 if (dw_mediamanager.display === "2") { 107 $p.hide(); 108 } 109 110 $l = jQuery(document.createElement('label')) 111 .text(opt.label); 112 $p.append($l); 113 114 jQuery.each(opt.btns, function (i, text) { 115 var $btn, $img; 116 $btn = jQuery(document.createElement('button')) 117 .addClass('button') 118 .attr('id', "media__" + opt.id + "btn" + (i + 1)) 119 .attr('title', LANG['media' + text]) 120 .click(bind(dw_mediamanager.setOpt, opt.id)); 121 122 $img = jQuery(document.createElement('img')) 123 .attr('src', DOKU_BASE + 'lib/images/media_' + 124 opt.id + '_' + text + '.png'); 125 126 $btn.append($img); 127 $p.append($btn); 128 }); 129 130 dw_mediamanager.$popup.append($p); 131 }); 132 133 // insert button 134 $insp = jQuery(document.createElement('p')) 135 .addClass('btnlbl'); 136 dw_mediamanager.$popup.append($insp); 137 138 $insbtn = jQuery(document.createElement('input')) 139 .attr('id', 'media__sendbtn') 140 .attr('type', 'button') 141 .addClass('button') 142 .val(LANG.mediainsert); 143 $insp.append($insbtn); 144 }, 145 146 /** 147 * Insert the clicked image into the opener's textarea 148 * 149 * @author Andreas Gohr <andi@splitbrain.org> 150 * @author Dominik Eckelmann <eckelmann@cosmocode.de> 151 * @author Pierre Spring <pierre.spring@caillou.ch> 152 */ 153 insert: function () { 154 var opts, alignleft, alignright, edid, s; 155 156 // set syntax options 157 dw_mediamanager.$popup.dialog('close'); 158 159 opts = ''; 160 alignleft = ''; 161 alignright = ''; 162 163 if ({img: 1, swf: 1}[dw_mediamanager.ext] === 1) { 164 165 if (dw_mediamanager.link === '4') { 166 opts = '?linkonly'; 167 } else { 168 169 if (dw_mediamanager.link === "3" && dw_mediamanager.ext === 'img') { 170 opts = '?nolink'; 171 } else if (dw_mediamanager.link === "2" && dw_mediamanager.ext === 'img') { 172 opts = '?direct'; 173 } 174 175 s = parseInt(dw_mediamanager.size, 10); 176 177 if (s && s >= 1 && s < 4) { 178 opts += (opts.length)?'&':'?'; 179 opts += dw_mediamanager.size + '00'; 180 if (dw_mediamanager.ext === 'swf') { 181 switch (s) { 182 case 1: 183 opts += 'x62'; 184 break; 185 case 2: 186 opts += 'x123'; 187 break; 188 case 3: 189 opts += 'x185'; 190 break; 191 } 192 } 193 } 194 alignleft = dw_mediamanager.align === '2' ? '' : ' '; 195 alignright = dw_mediamanager.align === '4' ? '' : ' '; 196 } 197 } 198 edid = String.prototype.match.call(document.location, /&edid=([^&]+)/); 199 opener.insertTags(edid ? edid[1] : 'wiki__text', 200 '{{'+alignleft+id+opts+alignright+'|','}}',''); 201 202 if(!dw_mediamanager.keepopen) { 203 window.close(); 204 } 205 opener.focus(); 206 return false; 207 }, 208 209 /** 210 * Prefills the wikiname. 211 * 212 * @author Andreas Gohr <andi@splitbrain.org> 213 */ 214 suggest: function(){ 215 var $file, $name, text; 216 217 $file = jQuery(this); 218 $name = jQuery('#upload__name'); 219 220 if ($name.val() != '') return; 221 222 if(!$file.length || !$name.length) { 223 return; 224 } 225 226 text = $file.val(); 227 text = text.substr(text.lastIndexOf('/')+1); 228 text = text.substr(text.lastIndexOf('\\')+1); 229 $name.val(text); 230 }, 231 232 /** 233 * list the content of a namespace using AJAX 234 * 235 * @author Andreas Gohr <andi@splitbrain.org> 236 * @author Pierre Spring <pierre.spring@caillou.ch> 237 */ 238 list: function (event) { 239 var $link, $content, params; 240 $link = jQuery(this); 241 242 event.preventDefault(); 243 244 jQuery('div.success, div.info, div.error, div.notify').remove(); 245 246 if (document.getElementById('media__content')) { 247 //popup 248 $content = jQuery('#media__content'); 249 $content.html('<img src="' + DOKU_BASE + 'lib/images/loading.gif" alt="..." class="load" />'); 250 251 } else { 252 //fullscreen media manager 253 $content = jQuery('#mediamanager__layout_list'); 254 255 if ($link.hasClass('idx_dir')) { 256 //changing namespace 257 jQuery('#mediamanager__layout_detail').empty(); 258 jQuery('#media__tree .selected').each(function(){ 259 jQuery(this).removeClass('selected'); 260 }); 261 $link.addClass('selected'); 262 } 263 264 jQuery('.scroll-container', $content).html('<img src="' + DOKU_BASE + 'lib/images/loading.gif" alt="..." class="load" />'); 265 } 266 267 params = ''; 268 269 if ($link[0].search) { 270 params = $link[0].search.substr(1)+'&call=medialist'; 271 } else if ($link[0].action) { 272 params = dw_mediamanager.form_params($link)+'&call=medialist'; 273 } 274 275 // fetch the subtree 276 dw_mediamanager.update_content($content, params); 277 278 }, 279 280 /** 281 * Returns form parameters 282 * 283 * @author Kate Arzamastseva <pshns@ukr.net> 284 */ 285 form_params: function ($form) { 286 var elements = $form.serialize(); 287 var action = ''; 288 var i = $form[0].action.indexOf('?'); 289 if (i >= 0) action = $form[0].action.substr(i+1); 290 return elements+'&'+action; 291 }, 292 293 /** 294 * Changes view of media files list 295 * 296 * @author Kate Arzamastseva <pshns@ukr.net> 297 */ 298 list_view: function (event) { 299 var $link, $content; 300 $link = jQuery(this); 301 302 event.preventDefault(); 303 304 $content = jQuery('#mediamanager__file_list'); 305 306 if ($link[0].id == 'mediamanager__link_thumbs') { 307 $content.removeClass('mediamanager-list'); 308 $content.addClass('mediamanager-thumbs'); 309 310 } else if ($link[0].id == 'mediamanager__link_list') { 311 $content.removeClass('mediamanager-thumbs'); 312 $content.addClass('mediamanager-list'); 313 } 314 }, 315 316 /** 317 * Lists the content of the right column (image details) using AJAX 318 * 319 * @author Kate Arzamastseva <pshns@ukr.net> 320 */ 321 details: function (event) { 322 var $link, $content, params, update_list; 323 $link = jQuery(this); 324 325 event.preventDefault(); 326 327 jQuery('div.success, div.info, div.error, div.notify').remove(); 328 329 if ($link[0].id == 'mediamanager__btn_delete' && !confirm(LANG['del_confirm'])) return false; 330 if ($link[0].id == 'mediamanager__btn_restore' && !confirm(LANG['restore_confirm'])) return false; 331 332 $content = jQuery('#mediamanager__layout_detail'); 333 if (jQuery('.scroll-container', $content).length) { 334 jQuery('.scroll-container', $content).html('<img src="' + DOKU_BASE + 'lib/images/loading.gif" alt="..." class="load" />'); 335 } else { 336 jQuery($content).html('<img src="' + DOKU_BASE + 'lib/images/loading.gif" alt="..." class="load" />'); 337 } 338 339 params = ''; 340 341 if ($link[0].search) { 342 params = $link[0].search.substr(1)+'&call=mediadetails'; 343 } else { 344 params = dw_mediamanager.form_params($link)+'&call=mediadetails'; 345 } 346 347 dw_mediamanager.update_content($content, params); 348 349 update_list = ($link[0].id == 'mediamanager__btn_delete' || $link[0].id == 'mediamanager__btn_restore'); 350 if (update_list) { 351 var $link1, $content1, params1; 352 $link1 = jQuery('a.files'); 353 params1 = $link1[0].search.substr(1)+'&call=medialist'; 354 $content1 = jQuery('#mediamanager__layout_list'); 355 jQuery('.scroll-container', $content1).html('<img src="' + DOKU_BASE + 'lib/images/loading.gif" alt="..." class="load" />'); 356 357 dw_mediamanager.update_content($content1, params1); 358 } 359 }, 360 361 update_content: function ($content, params) { 362 jQuery.post( 363 DOKU_BASE + 'lib/exe/ajax.php', 364 params, 365 function (data) { 366 jQuery('.ui-resizable').each(function(){ 367 jQuery(this).resizable('destroy'); 368 }); 369 370 $content.html(data); 371 dw_mediamanager.prepare_content($content); 372 dw_mediamanager.updatehide(); 373 dw_mediamanager.update_resizable(0); 374 dw_mediamanager.opacity_slider(); 375 dw_mediamanager.portions_slider(); 376 377 }, 378 'html' 379 ); 380 }, 381 382 update_resizable: function (count_width) { 383 jQuery(".layout").resizable({ handles: 'e' }); 384 jQuery(".layout").bind("resize", function(event, ui) { 385 var w = 0; 386 jQuery(".layout").each(function() { 387 w += jQuery(this).width(); 388 }); 389 jQuery('#id-mediamanager-layout').width(w+30); 390 }); 391 392 var w = 0; 393 jQuery(".layout").each(function() { 394 if (count_width) jQuery(this).width(jQuery(this).width()); 395 w += jQuery(this).width(); 396 }); 397 jQuery('#id-mediamanager-layout').width(w+30); 398 399 var windowHeight = jQuery(window).height(); 400 var height = windowHeight - 300; 401 jQuery('.scroll-container').each(function (i) { 402 jQuery(this).height(height); 403 }); 404 }, 405 406 opacity_slider: function () { 407 var $slider = jQuery( "#mediamanager__opacity_slider" ); 408 $slider.slider(); 409 $slider.slider("option", "min", 0); 410 $slider.slider("option", "max", 0.999); 411 $slider.slider("option", "step", 0.001); 412 $slider.slider("option", "value", 0.5); 413 $slider.bind("slide", function(event, ui) { 414 jQuery('#mediamanager__diff_opacity_image2').css({ opacity: $slider.slider("option", "value")}); 415 }); 416 }, 417 418 portions_slider: function () { 419 var $slider = jQuery( "#mediamanager__portions_slider" ); 420 $slider.slider(); 421 $slider.slider("option", "min", 0); 422 $slider.slider("option", "max", 100); 423 $slider.slider("option", "step", 1); 424 $slider.slider("option", "value", 50); 425 $slider.bind("slide", function(event, ui) { 426 jQuery('#mediamanager__diff_portions_image2').css({ width: $slider.slider("option", "value")+'%'}); 427 }); 428 }, 429 430 prepare_content: function ($content) { 431 // hide syntax example 432 $content.find('div.example:visible').hide(); 433 dw_mediamanager.initFlashUpload(); 434 }, 435 436 /** 437 * shows the popup for a image link 438 */ 439 select: function(event){ 440 var $link, id, dot, ext; 441 442 event.preventDefault(); 443 444 $link = jQuery(this); 445 id = $link.attr('name').substr(2); 446 447 if(!opener){ 448 // if we don't run in popup display example 449 // the id's are a bit wierd and jQuery('#ex_wiki_dokuwiki-128.png') 450 // will not be found by Sizzle (the CSS Selector Engine 451 // used by jQuery), hence the document.getElementById() call 452 jQuery(document.getElementById('ex_'+id.replace(/:/g,'_').replace(/^_/,''))).dw_toggle(); 453 return; 454 } 455 456 dw_mediamanager.ext = false; 457 dot = id.lastIndexOf("."); 458 459 if (-1 === dot) { 460 dw_mediamanager.insert(id); 461 return; 462 } 463 464 ext = id.substr(dot); 465 466 if ({'.jpg':1, '.jpeg':1, '.png':1, '.gif':1, '.swf':1}[ext] !== 1) { 467 dw_mediamanager.insert(id); 468 return; 469 } 470 471 // remove old callback from the insert button and set the new one. 472 jQuery('#media__sendbtn').unbind().click(bind(dw_mediamanager.insert, id)); 473 474 dw_mediamanager.unforbid('ext'); 475 if (ext === '.swf') { 476 dw_mediamanager.ext = 'swf'; 477 dw_mediamanager.forbid('ext', {link: ['1', '2'], 478 size: ['4']}); 479 } else { 480 dw_mediamanager.ext = 'img'; 481 } 482 483 // Set to defaults 484 dw_mediamanager.setOpt('link'); 485 dw_mediamanager.setOpt('align'); 486 dw_mediamanager.setOpt('size'); 487 488 // toggle buttons for detail and linked image, original size 489 jQuery('#media__linkbtn1, #media__linkbtn2, #media__sizebtn4') 490 .toggle(dw_mediamanager.ext === 'img'); 491 492 dw_mediamanager.$popup.dialog('open'); 493 494 jQuery('#media__sendbtn').focus(); 495 }, 496 497 /** 498 * Deletion confirmation dialog to the delete buttons. 499 * 500 * @author Michael Klier <chi@chimeric.de> 501 * @author Pierre Spring <pierre.spring@caillou.ch> 502 */ 503 confirmattach: function(e){ 504 if(!confirm(LANG.del_confirm + "\n" + jQuery(this).attr('title'))) { 505 e.preventDefault(); 506 } 507 }, 508 509 /** 510 * Creates checkboxes for additional options 511 * 512 * @author Andreas Gohr <andi@splitbrain.org> 513 * @author Pierre Spring <pierre.spring@caillou.ch> 514 */ 515 attachoptions: function(){ 516 var $obj, opts; 517 518 $obj = jQuery('#media__opts'); 519 if($obj.length === 0) { 520 return; 521 } 522 523 opts = []; 524 // keep open 525 if(opener){ 526 opts.push(['keepopen', 'keepopen']); 527 } 528 opts.push(['hide', 'hidedetails']); 529 530 jQuery.each(opts, 531 function(_, opt) { 532 var $box, $lbl; 533 $box = jQuery(document.createElement('input')) 534 .attr('type', 'checkbox') 535 .attr('id', 'media__' + opt[0]) 536 .click(bind(dw_mediamanager.toggleOption, 537 opt[0])); 538 539 if(DokuCookie.getValue(opt[0])){ 540 $box.prop('checked', true); 541 dw_mediamanager[opt[0]] = true; 542 } 543 544 $lbl = jQuery(document.createElement('label')) 545 .attr('for', 'media__' + opt[0]) 546 .text(LANG[opt[1]]); 547 548 $obj.append($box, $lbl, document.createElement('br')); 549 }); 550 551 dw_mediamanager.updatehide(); 552 }, 553 554 /** 555 * Generalized toggler 556 * 557 * @author Pierre Spring <pierre.spring@caillou.ch> 558 */ 559 toggleOption: function (variable) { 560 if (jQuery(this).prop('checked')) { 561 DokuCookie.setValue(variable, 1); 562 dw_mediamanager[variable] = true; 563 } else { 564 DokuCookie.setValue(variable, ''); 565 dw_mediamanager[variable] = false; 566 } 567 if (variable === 'hide') { 568 dw_mediamanager.updatehide(); 569 } 570 }, 571 572 initFlashUpload: function () { 573 var $oform, $oflash; 574 if(!hasFlash(8)) { 575 return; 576 } 577 578 $oform = jQuery('#dw__upload'); 579 $oflash = jQuery('#dw__flashupload'); 580 581 if(!$oform.length || !$oflash.length) { 582 return; 583 } 584 585 jQuery(document.createElement('img')) 586 .attr('src', DOKU_BASE+'lib/images/multiupload.png') 587 .attr('title', LANG.mu_btn) 588 .attr('alt', LANG.mu_btn) 589 .css('cursor', 'pointer') 590 .click( 591 function () { 592 $oform.hide(); 593 $oflash.show(); 594 } 595 ) 596 .appendTo($oform); 597 }, 598 599 /** 600 * Sets the visibility of the image details accordingly to the 601 * chosen hide state 602 * 603 * @author Andreas Gohr <andi@splitbrain.org> 604 */ 605 updatehide: function(){ 606 jQuery('#media__content div.detail').dw_toggle(!dw_mediamanager.hide); 607 }, 608 609 /** 610 * set media insertion option 611 * 612 * @author Dominik Eckelmann <eckelmann@cosmocode.de> 613 */ 614 setOpt: function(opt, e){ 615 var val, i; 616 if (typeof e !== 'undefined') { 617 val = this.id.substring(this.id.length - 1); 618 } else { 619 val = dw_mediamanager.getOpt(opt); 620 } 621 622 if (val === false) { 623 DokuCookie.setValue(opt,''); 624 dw_mediamanager[opt] = false; 625 return; 626 } 627 628 if (opt === 'link') { 629 if (val !== '4' && dw_mediamanager.link === '4') { 630 dw_mediamanager.unforbid('linkonly'); 631 dw_mediamanager.setOpt('align'); 632 dw_mediamanager.setOpt('size'); 633 } else if (val === '4') { 634 dw_mediamanager.forbid('linkonly', {align: false, size: false}); 635 } 636 637 jQuery("#media__size, #media__align").dw_toggle(val !== '4'); 638 } 639 640 DokuCookie.setValue(opt, val); 641 dw_mediamanager[opt] = val; 642 643 for (i = 1; i <= 4; i++) { 644 jQuery("#media__" + opt + "btn" + i).removeClass('selected'); 645 } 646 jQuery('#media__' + opt + 'btn' + val).addClass('selected'); 647 }, 648 649 unforbid: function (group) { 650 delete dw_mediamanager.forbidden_opts[group]; 651 }, 652 653 forbid: function (group, forbids) { 654 dw_mediamanager.forbidden_opts[group] = forbids; 655 }, 656 657 allowedOpt: function (opt, val) { 658 var ret = true; 659 jQuery.each(dw_mediamanager.forbidden_opts, 660 function (_, forbids) { 661 ret = forbids[opt] !== false && 662 jQuery.inArray(val, forbids[opt]) === -1; 663 return ret; 664 }); 665 return ret; 666 }, 667 668 getOpt: function (opt) { 669 var allowed = bind(dw_mediamanager.allowedOpt, opt); 670 671 // Current value 672 if (dw_mediamanager[opt] !== false && allowed(dw_mediamanager[opt])) { 673 return dw_mediamanager[opt]; 674 } 675 676 // From cookie 677 if (DokuCookie.getValue(opt) && allowed(DokuCookie.getValue(opt))) { 678 return DokuCookie.getValue(opt); 679 } 680 681 // size default 682 if (opt === 'size' && allowed('2')) { 683 return '2'; 684 } 685 686 // Whatever is allowed, and be it false 687 return jQuery.grep(['1', '2', '3', '4'], allowed)[0] || false; 688 } 689}; 690 691// moved from helpers.js temporarily here 692/** 693 * Very simplistic Flash plugin check, probably works for Flash 8 and higher only 694 * 695 */ 696function hasFlash(version){ 697 var ver = 0, axo; 698 try{ 699 if(navigator.plugins !== null && navigator.plugins.length > 0){ 700 ver = navigator.plugins["Shockwave Flash"].description.split(' ')[2].split('.')[0]; 701 }else{ 702 axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); 703 ver = axo.GetVariable("$version").split(' ')[1].split(',')[0]; 704 } 705 }catch(e){ } 706 707 return ver >= version; 708} 709 710jQuery(document).ready(function() { 711 dw_mediamanager.update_resizable(1); 712 dw_mediamanager.opacity_slider(); 713 dw_mediamanager.portions_slider(); 714}); 715 716jQuery(dw_mediamanager.init); 717