1 /**
2  * JavaScript functionality for the media management popup
3  *
4  * @author Andreas Gohr <andi@splitbrain.org>
5  * @author Pierre Spring <pierre.spring@caillou.ch>
6  */
7 
8 var dw_mediamanager = {
9     keepopen: false,
10     hide: false,
11     popup: false,
12     display: false,
13     ext: false,
14     $popup: null,
15 
16     // Image insertion opts
17     align: false,
18     link: false,
19     size: false,
20     forbidden_opts: {},
21 
22     // File list options
23     view_opts: {list: false, sort: false},
24 
25     layout_width: 0,
26 
27     // The minimum height of the full-screen mediamanager in px
28     minHeights: {thumbs: 200, rows: 100},
29 
30     init: function () {
31         var $content, $tree;
32         $content = jQuery('#media__content');
33         $tree = jQuery('#media__tree');
34         if (!$tree.length) return;
35 
36         dw_mediamanager.prepare_content($content);
37 
38         dw_mediamanager.attachoptions();
39         dw_mediamanager.initpopup();
40 
41         // add the action to autofill the "upload as" field
42         $content
43             .on('change', '#upload__file', dw_mediamanager.suggest)
44             // Attach the image selector action to all links
45             .on('click', 'a.select', dw_mediamanager.select)
46             // Attach deletion confirmation dialog to the delete buttons
47             .on('click', '#media__content a.btn_media_delete', dw_mediamanager.confirmattach)
48             .on('submit', '#mediamanager__done_form', dw_mediamanager.list);
49 
50         $tree.dw_tree({
51             toggle_selector: 'img',
52             load_data: function (show_sublist, $clicky) {
53                 // get the enclosed link (is always the first one)
54                 var $link = $clicky.parent().find('div.li a.idx_dir');
55 
56                 jQuery.post(
57                     DOKU_BASE + 'lib/exe/ajax.php',
58                     $link[0].search.substr(1) + '&call=medians',
59                     show_sublist,
60                     'html'
61                 );
62             },
63 
64             toggle_display: function ($clicky, opening) {
65                 $clicky.attr('src', DOKU_BASE + 'lib/images/' + (opening ? 'minus' : 'plus') + '.gif');
66             }
67         });
68         $tree.on('click', 'a', dw_mediamanager.list);
69 
70         // Init view property
71         dw_mediamanager.set_fileview_list();
72 
73         dw_mediamanager.init_options();
74 
75         dw_mediamanager.image_diff();
76         dw_mediamanager.init_ajax_uploader();
77 
78         // changing opened tab in the file list panel
79         var $page = jQuery('#mediamanager__page');
80         $page.find('div.filelist')
81             .on('click', 'ul.tabs a', dw_mediamanager.list)
82             // loading file details
83             .on('click', 'div.panelContent a', dw_mediamanager.details)
84             // search form
85             .on('submit', '#dw__mediasearch', dw_mediamanager.list)
86             // "upload as" field autofill
87             .on('change', '#upload__file', dw_mediamanager.suggest)
88             // uploaded images
89             .on('click', '.qq-upload-file a', dw_mediamanager.details);
90 
91         // changing opened tab in the file details panel
92         $page.find('div.file')
93             .on('click', 'ul.tabs a', dw_mediamanager.details)
94             // "update new version" button
95             .on('submit', '#mediamanager__btn_update', dw_mediamanager.list)
96             // revisions form
97             .on('submit', '#page__revisions', dw_mediamanager.details)
98             .on('click', '#page__revisions a', dw_mediamanager.details)
99             // meta edit form
100             .on('submit', '#mediamanager__save_meta', dw_mediamanager.details)
101             // delete button
102             .on('submit', '#mediamanager__btn_delete', dw_mediamanager.details)
103             // "restore this version" button
104             .on('submit', '#mediamanager__btn_restore', dw_mediamanager.details)
105             // less/more recent buttons in media revisions form
106             .on('submit', '.btn_newer, .btn_older', dw_mediamanager.details);
107 
108         dw_mediamanager.resize();
109         dw_mediamanager.update_resizable();
110         dw_mediamanager.layout_width = $page.width();
111         jQuery(window).on('resize', dw_mediamanager.window_resize);
112     },
113 
114     init_options: function () {
115         var $options = jQuery('div.filelist div.panelHeader form.options'),
116             $listType, $sortBy, $both;
117         if ($options.length === 0) {
118             return;
119         }
120 
121         $listType = $options.find('li.listType');
122         $sortBy = $options.find('li.sortBy');
123         $both = $listType.add($sortBy);
124 
125         // Remove the submit button
126         $options.find('button[type=submit]').parent().hide();
127 
128         // Prepare HTML for jQuery UI buttonset
129         $both.find('label').each(function () {
130             var $this = jQuery(this);
131             $this.children('input').appendTo($this.parent());
132         });
133 
134         // Init buttonset
135         $both.find("input[type='radio']").checkboxradio({icon: false});
136         $both.controlgroup();
137 
138         // Change handlers
139         $listType.children('input').change(function () {
140             dw_mediamanager.set_fileview_list();
141         });
142         $sortBy.children('input').change(function (event) {
143             dw_mediamanager.set_fileview_sort();
144             dw_mediamanager.list.call(jQuery('#dw__mediasearch')[0] || this, event);
145         });
146     },
147 
148     /**
149      * build the popup window
150      *
151      * @author Dominik Eckelmann <eckelmann@cosmocode.de>
152      */
153     initpopup: function () {
154         var opts, $insp, $insbtn;
155 
156         dw_mediamanager.$popup = jQuery(document.createElement('div'))
157             .attr('id', 'media__popup_content')
158             .dialog({
159                 autoOpen: false, width: 280, modal: true,
160                 draggable: true, title: LANG.mediatitle,
161                 resizable: false
162             });
163 
164         opts = [
165             {
166                 id: 'link', label: LANG.mediatarget,
167                 btns: ['lnk', 'direct', 'nolnk', 'displaylnk']
168             },
169             {
170                 id: 'align', label: LANG.mediaalign,
171                 btns: ['noalign', 'left', 'center', 'right']
172             },
173             {
174                 id: 'size', label: LANG.mediasize,
175                 btns: ['small', 'medium', 'large', 'original']
176             }
177         ];
178 
179         jQuery.each(opts, function (_, opt) {
180             var $p, $l;
181             $p = jQuery(document.createElement('p'))
182                 .attr('id', 'media__' + opt.id);
183 
184             if (dw_mediamanager.display === "2") {
185                 $p.hide();
186             }
187 
188             $l = jQuery(document.createElement('label'))
189                 .text(opt.label);
190             $p.append($l);
191 
192             jQuery.each(opt.btns, function (i, text) {
193                 var $btn, $img;
194                 $btn = jQuery(document.createElement('button'))
195                     .addClass('button')
196                     .attr('id', "media__" + opt.id + "btn" + (i + 1))
197                     .attr('title', LANG['media' + text])
198                     .on('click', bind(dw_mediamanager.setOpt, opt.id));
199 
200                 $img = jQuery(document.createElement('img'))
201                     .attr('src', DOKU_BASE + 'lib/images/media_' + opt.id + '_' + text + '.png');
202 
203                 $btn.append($img);
204                 $p.append($btn);
205             });
206 
207             dw_mediamanager.$popup.append($p);
208         });
209 
210         // insert button
211         $insp = jQuery(document.createElement('p'));
212         dw_mediamanager.$popup.append($insp);
213 
214         $insbtn = jQuery(document.createElement('input'))
215             .attr('id', 'media__sendbtn')
216             .attr('type', 'button')
217             .addClass('button')
218             .val(LANG.mediainsert);
219         $insp.append($insbtn);
220     },
221 
222     /**
223      * Insert the clicked image into the opener's textarea
224      *
225      * @author Andreas Gohr <andi@splitbrain.org>
226      * @author Dominik Eckelmann <eckelmann@cosmocode.de>
227      * @author Pierre Spring <pierre.spring@caillou.ch>
228      */
229     insert: function (id) {
230         var opts, cb, edid, s;
231 
232         // set syntax options
233         dw_mediamanager.$popup.dialog('close');
234 
235         opts = '';
236 
237         if ({img: 1, swf: 1}[dw_mediamanager.ext] === 1) {
238 
239             if (dw_mediamanager.link === '4') {
240                 opts = '?linkonly';
241             } else {
242 
243                 if (dw_mediamanager.link === "3" && dw_mediamanager.ext === 'img') {
244                     opts = '?nolink';
245                 } else if (dw_mediamanager.link === "2" && dw_mediamanager.ext === 'img') {
246                     opts = '?direct';
247                 }
248 
249                 s = parseInt(dw_mediamanager.size, 10);
250                 var size = s * 200;
251 
252                 if (s && s >= 1 && s < 4) {
253                     opts += (opts.length) ? '&' : '?';
254                     opts += size;
255                     if (dw_mediamanager.ext === 'swf') {
256                         switch (s) {
257                             case 1:
258                                 opts += 'x62';
259                                 break;
260                             case 2:
261                                 opts += 'x123';
262                                 break;
263                             case 3:
264                                 opts += 'x185';
265                                 break;
266                         }
267                     }
268                 }
269             }
270         }
271         edid = String.prototype.match.call(document.location, /&edid=([^&]+)/);
272         edid = edid ? edid[1] : 'wiki__text';
273         cb = String.prototype.match.call(document.location, /&onselect=([^&]+)/);
274         cb = cb ? cb[1].replace(/[^\w]+/, '') : 'dw_mediamanager_item_select';
275 
276         // arguments here only match the dw_mediamanager_item_select function, these will need to change if you override cb with onselect GET param
277         opener[cb](edid, id, opts, dw_mediamanager.align, dw_mediamanager.keepopen);
278         if (!dw_mediamanager.keepopen) {
279             window.close();
280         }
281         opener.focus();
282         return false;
283     },
284 
285 
286     /**
287      * Prefills the wikiname.
288      *
289      * @author Andreas Gohr <andi@splitbrain.org>
290      */
291     suggest: function () {
292         var $file, $name, text;
293 
294         $file = jQuery(this);
295         $name = jQuery('#upload__name');
296 
297         if ($name.val() != '') return;
298 
299         if (!$file.length || !$name.length) {
300             return;
301         }
302 
303         text = $file.val();
304         text = text.substr(text.lastIndexOf('/') + 1);
305         text = text.substr(text.lastIndexOf('\\') + 1);
306         $name.val(text);
307     },
308 
309     /**
310      * list the content of a namespace using AJAX
311      *
312      * @author Andreas Gohr <andi@splitbrain.org>
313      * @author Pierre Spring <pierre.spring@caillou.ch>
314      */
315     list: function (event) {
316         var $link, $content, params;
317 
318         if (event) {
319             event.preventDefault();
320         }
321 
322         jQuery('div.success, div.info, div.error, div.notify').remove();
323 
324         $link = jQuery(this);
325 
326         //popup
327         $content = jQuery('#media__content');
328 
329         if ($content.length === 0) {
330             //fullscreen media manager
331             $content = jQuery('div.filelist');
332 
333             if ($link.hasClass('idx_dir')) {
334                 //changing namespace
335                 jQuery('div.file').empty();
336                 jQuery('div.namespaces .selected').removeClass('selected');
337                 $link.addClass('selected');
338             }
339         }
340 
341         params = 'call=medialist&';
342 
343         if ($link[0].search) {
344             params += $link[0].search.substr(1);
345         } else if ($link.is('form')) {
346             params += dw_mediamanager.form_params($link);
347         } else if ($link.closest('form').length > 0) {
348             params += dw_mediamanager.form_params($link.closest('form'));
349         }
350 
351         // fetch the subtree
352         dw_mediamanager.update_content($content, params);
353     },
354 
355     /**
356      * Returns form parameters
357      *
358      * @author Kate Arzamastseva <pshns@ukr.net>
359      */
360     form_params: function ($form) {
361         if (!$form.length) return;
362 
363         var action = '';
364         var i = $form[0].action.indexOf('?');
365         if (i >= 0) {
366             action = $form[0].action.substr(i + 1);
367         }
368         return action + '&' + $form.serialize();
369     },
370 
371     set_fileview_list: function (new_type) {
372         dw_mediamanager.set_fileview_opt(['list', 'listType', function (new_type) {
373             jQuery('div.filelist div.panelContent ul')
374                 .toggleClass('rows', new_type === 'rows')
375                 .toggleClass('thumbs', new_type === 'thumbs');
376         }], new_type);
377     },
378 
379     set_fileview_sort: function (new_sort) {
380         dw_mediamanager.set_fileview_opt(['sort', 'sortBy', function (new_sort) {
381             // FIXME
382         }], new_sort);
383     },
384 
385     set_fileview_opt: function (opt, new_val) {
386         if (typeof new_val === 'undefined') {
387             new_val = jQuery('form.options li.' + opt[1] + ' input')
388                 .filter(':checked').val();
389             // if new_val is still undefined (because form.options is not in active tab), set to most spacious option
390             if (typeof new_val === 'undefined') {
391                 new_val = 'thumbs';
392             }
393         }
394 
395         if (new_val !== dw_mediamanager.view_opts[opt[0]]) {
396             opt[2](new_val);
397 
398             DokuCookie.setValue(opt[0], new_val);
399 
400             dw_mediamanager.view_opts[opt[0]] = new_val;
401         }
402     },
403 
404     /**
405      * Lists the content of the right column (image details) using AJAX
406      *
407      * @author Kate Arzamastseva <pshns@ukr.net>
408      */
409     details: function (event) {
410         var $link, $content, params, update_list;
411         $link = jQuery(this);
412         event.preventDefault();
413 
414         jQuery('div.success, div.info, div.error, div.notify').remove();
415 
416         if ($link[0].id == 'mediamanager__btn_delete' && !confirm(LANG.del_confirm)) {
417             return false;
418         }
419         if ($link[0].id == 'mediamanager__btn_restore' && !confirm(LANG.restore_confirm)) {
420             return false;
421         }
422 
423         $content = jQuery('div.file');
424         params = 'call=mediadetails&';
425 
426         if ($link[0].search) {
427             params += $link[0].search.substr(1);
428         } else if ($link.is('form')) {
429             params += dw_mediamanager.form_params($link);
430         } else if ($link.closest('form').length > 0) {
431             params += dw_mediamanager.form_params($link.closest('form'));
432         }
433 
434         update_list = ($link[0].id == 'mediamanager__btn_delete' ||
435         $link[0].id == 'mediamanager__btn_restore');
436 
437         dw_mediamanager.update_content($content, params, update_list);
438     },
439 
440     update_content: function ($content, params, update_list) {
441         var $container;
442 
443         jQuery.post(
444             DOKU_BASE + 'lib/exe/ajax.php',
445             params,
446             function (data) {
447                 dw_mediamanager.$resizables().resizable('destroy');
448 
449                 if (update_list) {
450                     dw_mediamanager.list.call(jQuery('#mediamanager__page').find('form.options button[type="submit"]')[0]);
451                 }
452 
453                 $content.html(data);
454 
455                 dw_mediamanager.prepare_content($content);
456                 dw_mediamanager.updatehide();
457 
458                 dw_mediamanager.update_resizable();
459                 dw_behaviour.revisionBoxHandler();
460 
461                 // Make sure that the list view style stays the same
462                 dw_mediamanager.set_fileview_list(dw_mediamanager.view_opts.list);
463 
464                 dw_mediamanager.image_diff();
465                 dw_mediamanager.init_ajax_uploader();
466                 dw_mediamanager.init_options();
467 
468             },
469             'html'
470         );
471         $container = $content.find('div.panelContent');
472         if ($container.length === 0) {
473             $container = $content;
474         }
475         $container.html('<img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="..." class="load" />');
476     },
477 
478     window_resize: function () {
479         dw_mediamanager.opacity_slider();
480         dw_mediamanager.portions_slider();
481     },
482 
483     $resizables: function () {
484         return jQuery('#mediamanager__page').find('div.namespaces, div.filelist');
485     },
486 
487     /**
488      * Updates mediamanager layout
489      *
490      * @author Kate Arzamastseva <pshns@ukr.net>
491      */
492     update_resizable: function () {
493         var $resizables = dw_mediamanager.$resizables();
494 
495         $resizables.resizable({
496             handles: (jQuery('html[dir=rtl]').length ? 'w' : 'e'),
497             resize: function (event, ui) {
498                 var $page = jQuery('#mediamanager__page');
499                 var widthFull = $page.width();
500                 var widthResizables = 0;
501                 $resizables.each(function () {
502                     widthResizables += jQuery(this).width();
503                 });
504                 var $filePanel = $page.find('div.panel.file');
505 
506                 // set max width of resizable column
507                 var widthOtherResizable = widthResizables - jQuery(this).width();
508                 var minWidthNonResizable = parseFloat($filePanel.css("min-width"));
509                 var maxWidth = widthFull - (widthOtherResizable + minWidthNonResizable) - 1;
510                 $resizables.resizable("option", "maxWidth", maxWidth);
511 
512                 // width of file panel in % = 100% - width of resizables in %
513                 // this calculates with 99.9 and not 100 to overcome rounding errors
514                 var relWidthNonResizable = 99.9 - (100 * widthResizables / widthFull);
515                 // set width of file panel
516                 $filePanel.width(relWidthNonResizable + '%');
517 
518                 dw_mediamanager.opacity_slider();
519                 dw_mediamanager.portions_slider();
520             }
521         });
522     },
523 
524     resize: function () {
525         jQuery('#mediamanager__page').find('div.panelContent').css('height', '60vh');
526     },
527 
528     /**
529      * Prints 'select' for image difference representation type
530      *
531      * @author Kate Arzamastseva <pshns@ukr.net>
532      */
533     image_diff: function () {
534         if (jQuery('#mediamanager__difftype').length) return;
535 
536         var $form = jQuery('#mediamanager__form_diffview');
537         if (!$form.length) return;
538 
539         var $label = jQuery(document.createElement('label'));
540         $label.append('<span>' + LANG.media_diff + '</span> ');
541         var $select = jQuery(document.createElement('select'))
542             .attr('id', 'mediamanager__difftype')
543             .attr('name', 'difftype')
544             .change(dw_mediamanager.change_diff_type);
545         $select.append(new Option(LANG.media_diff_both, "both"));
546         $select.append(new Option(LANG.media_diff_opacity, "opacity"));
547         $select.append(new Option(LANG.media_diff_portions, "portions"));
548         $label.append($select);
549         $form.append($label);
550 
551         // for IE
552         var select = document.getElementById('mediamanager__difftype');
553         select.options[0].text = LANG.media_diff_both;
554         select.options[1].text = LANG.media_diff_opacity;
555         select.options[2].text = LANG.media_diff_portions;
556     },
557 
558     /**
559      * Handles selection of image difference representation type
560      *
561      * @author Kate Arzamastseva <pshns@ukr.net>
562      */
563     change_diff_type: function () {
564         var $select = jQuery('#mediamanager__difftype');
565         var $content = jQuery('#mediamanager__diff');
566 
567         var params = dw_mediamanager.form_params($select.closest('form')) + '&call=mediadiff';
568         jQuery.post(
569             DOKU_BASE + 'lib/exe/ajax.php',
570             params,
571             function (data) {
572                 $content.html(data);
573                 dw_mediamanager.portions_slider();
574                 dw_mediamanager.opacity_slider();
575             },
576             'html'
577         );
578     },
579 
580     /**
581      * Sets options for opacity diff slider
582      *
583      * @author Kate Arzamastseva <pshns@ukr.net>
584      */
585     opacity_slider: function () {
586         var $diff = jQuery("#mediamanager__diff");
587         var $slider = $diff.find("div.slider");
588         if (!$slider.length) return;
589 
590         var $image = $diff.find('div.imageDiff.opacity div.image1 img');
591         if (!$image.length) return;
592         $slider.width($image.width() - 20);
593 
594         $slider.slider();
595         $slider.slider("option", "min", 0);
596         $slider.slider("option", "max", 0.999);
597         $slider.slider("option", "step", 0.001);
598         $slider.slider("option", "value", 0.5);
599         $slider.on("slide", function (event, ui) {
600             jQuery('#mediamanager__diff').find('div.imageDiff.opacity div.image2 img').css({opacity: $slider.slider("option", "value")});
601         });
602     },
603 
604     /**
605      * Sets options for red line diff slider
606      *
607      * @author Kate Arzamastseva <pshns@ukr.net>
608      */
609     portions_slider: function () {
610         var $diff = jQuery("#mediamanager__diff");
611         if (!$diff.length) return;
612 
613         var $image1 = $diff.find('div.imageDiff.portions div.image1 img');
614         var $image2 = $diff.find('div.imageDiff.portions div.image2 img');
615         if (!$image1.length || !$image2.length) return;
616 
617         $diff.width('100%');
618         $image2.parent().width('97%');
619         $image1.width('100%');
620         $image2.width('100%');
621 
622         if ($image1.width() < $diff.width()) {
623             $diff.width($image1.width());
624         }
625 
626         $image2.parent().width('50%');
627         $image2.width($image1.width());
628         $image1.width($image1.width());
629 
630         var $slider = $diff.find("div.slider");
631         if (!$slider.length) return;
632         $slider.width($image1.width() - 20);
633 
634         $slider.slider();
635         $slider.slider("option", "min", 0);
636         $slider.slider("option", "max", 97);
637         $slider.slider("option", "step", 1);
638         $slider.slider("option", "value", 50);
639         $slider.on("slide", function (event, ui) {
640             jQuery('#mediamanager__diff').find('div.imageDiff.portions div.image2').css({width: $slider.slider("option", "value") + '%'});
641         });
642     },
643 
644     /**
645      * Parse a URI query string to an associative array
646      *
647      * @author Kate Arzamastseva <pshns@ukr.net>
648      */
649     params_toarray: function (str) {
650         var vars = [], hash;
651         var hashes = str.split('&');
652         for (var i = 0; i < hashes.length; i++) {
653             hash = hashes[i].split('=');
654             vars[decodeURIComponent(hash[0])] = decodeURIComponent(hash[1]);
655         }
656         return vars;
657     },
658 
659     init_ajax_uploader: function () {
660         if (!jQuery('#mediamanager__uploader').length) return;
661         if (jQuery('.qq-upload-list').length) return;
662 
663         var params = dw_mediamanager.form_params(jQuery('#dw__upload')) + '&call=mediaupload';
664         params = dw_mediamanager.params_toarray(params);
665 
666         var uploader = new qq.FileUploaderExtended({
667             element: document.getElementById('mediamanager__uploader'),
668             action: DOKU_BASE + 'lib/exe/ajax.php',
669             params: params
670         });
671     },
672 
673     prepare_content: function ($content) {
674         // hide syntax example
675         $content.find('div.example:visible').hide();
676         // toggle list of allowed mime types
677         $content.find('a.allowedmime').on('click', function (event) {
678             event.preventDefault();
679             $toggle = jQuery(this);
680             $list = $toggle.next('span');
681             $list.toggle();
682         }).next('span').hide();
683 
684     },
685 
686     /**
687      * shows the popup for a image link
688      */
689     select: function (event) {
690         var $link, id, dot, ext;
691 
692         event.preventDefault();
693 
694         $link = jQuery(this);
695         id = $link.attr('id').substr(2);
696 
697         if (!opener) {
698             // if we don't run in popup display example
699             // the id's are a bit wierd and jQuery('#ex_wiki_dokuwiki-128.png')
700             // will not be found by Sizzle (the CSS Selector Engine
701             // used by jQuery), hence the document.getElementById() call
702             jQuery(document.getElementById('ex_' + id.replace(/:/g, '_').replace(/^_/, ''))).dw_toggle();
703             return;
704         }
705 
706         dw_mediamanager.ext = false;
707         dot = id.lastIndexOf(".");
708 
709         if (-1 === dot) {
710             dw_mediamanager.insert(id);
711             return;
712         }
713 
714         ext = id.substr(dot);
715 
716         if ({'.jpg': 1, '.jpeg': 1, '.png': 1, '.gif': 1, '.swf': 1}[ext] !== 1) {
717             dw_mediamanager.insert(id);
718             return;
719         }
720 
721         // remove old callback from the insert button and set the new one.
722         var $sendbtn = jQuery('#media__sendbtn');
723         $sendbtn.off().on('click', bind(dw_mediamanager.insert, id));
724 
725         dw_mediamanager.unforbid('ext');
726         if (ext === '.swf') {
727             dw_mediamanager.ext = 'swf';
728             dw_mediamanager.forbid('ext', {
729                 link: ['1', '2'],
730                 size: ['4']
731             });
732         } else {
733             dw_mediamanager.ext = 'img';
734         }
735 
736         // Set to defaults
737         dw_mediamanager.setOpt('link');
738         dw_mediamanager.setOpt('align');
739         dw_mediamanager.setOpt('size');
740 
741         // toggle buttons for detail and linked image, original size
742         jQuery('#media__linkbtn1, #media__linkbtn2, #media__sizebtn4')
743             .toggle(dw_mediamanager.ext === 'img');
744 
745         dw_mediamanager.$popup.dialog('open');
746 
747         $sendbtn.focus();
748     },
749 
750     /**
751      * Deletion confirmation dialog to the delete buttons.
752      *
753      * @author Michael Klier <chi@chimeric.de>
754      * @author Pierre Spring <pierre.spring@caillou.ch>
755      */
756     confirmattach: function (e) {
757         if (!confirm(LANG.del_confirm + "\n" + jQuery(this).attr('title'))) {
758             e.preventDefault();
759         }
760     },
761 
762     /**
763      * Creates checkboxes for additional options
764      *
765      * @author Andreas Gohr <andi@splitbrain.org>
766      * @author Pierre Spring <pierre.spring@caillou.ch>
767      */
768     attachoptions: function () {
769         var $obj, opts;
770 
771         $obj = jQuery('#media__opts');
772         if ($obj.length === 0) {
773             return;
774         }
775 
776         opts = [];
777         // keep open
778         if (opener) {
779             opts.push(['keepopen', 'keepopen']);
780         }
781         opts.push(['hide', 'hidedetails']);
782 
783         jQuery.each(opts,
784             function (_, opt) {
785                 var $box, $lbl;
786                 $box = jQuery(document.createElement('input'))
787                     .attr('type', 'checkbox')
788                     .attr('id', 'media__' + opt[0])
789                     .on('click', bind(dw_mediamanager.toggleOption, opt[0]));
790 
791                 if (DokuCookie.getValue(opt[0])) {
792                     $box.prop('checked', true);
793                     dw_mediamanager[opt[0]] = true;
794                 }
795 
796                 $lbl = jQuery(document.createElement('label'))
797                     .attr('for', 'media__' + opt[0])
798                     .text(LANG[opt[1]]);
799 
800                 $obj.append($box, $lbl, document.createElement('br'));
801             });
802 
803         dw_mediamanager.updatehide();
804     },
805 
806     /**
807      * Generalized toggler
808      *
809      * @author Pierre Spring <pierre.spring@caillou.ch>
810      */
811     toggleOption: function (variable) {
812         if (jQuery(this).prop('checked')) {
813             DokuCookie.setValue(variable, 1);
814             dw_mediamanager[variable] = true;
815         } else {
816             DokuCookie.setValue(variable, '');
817             dw_mediamanager[variable] = false;
818         }
819         if (variable === 'hide') {
820             dw_mediamanager.updatehide();
821         }
822     },
823 
824     /**
825      * Sets the visibility of the image details accordingly to the
826      * chosen hide state
827      *
828      * @author Andreas Gohr <andi@splitbrain.org>
829      */
830     updatehide: function () {
831         jQuery('#media__content').find('div.detail').dw_toggle(!dw_mediamanager.hide);
832     },
833 
834     /**
835      * set media insertion option
836      *
837      * @author Dominik Eckelmann <eckelmann@cosmocode.de>
838      */
839     setOpt: function (opt, e) {
840         var val, i;
841         if (typeof e !== 'undefined') {
842             val = this.id.substring(this.id.length - 1);
843         } else {
844             val = dw_mediamanager.getOpt(opt);
845         }
846 
847         if (val === false) {
848             DokuCookie.setValue(opt, '');
849             dw_mediamanager[opt] = false;
850             return;
851         }
852 
853         if (opt === 'link') {
854             if (val !== '4' && dw_mediamanager.link === '4') {
855                 dw_mediamanager.unforbid('linkonly');
856                 dw_mediamanager.setOpt('align');
857                 dw_mediamanager.setOpt('size');
858             } else if (val === '4') {
859                 dw_mediamanager.forbid('linkonly', {align: false, size: false});
860             }
861 
862             jQuery("#media__size, #media__align").dw_toggle(val !== '4');
863         }
864 
865         DokuCookie.setValue(opt, val);
866         dw_mediamanager[opt] = val;
867 
868         for (i = 1; i <= 4; i++) {
869             jQuery("#media__" + opt + "btn" + i).removeClass('selected');
870         }
871         jQuery('#media__' + opt + 'btn' + val).addClass('selected');
872     },
873 
874     unforbid: function (group) {
875         delete dw_mediamanager.forbidden_opts[group];
876     },
877 
878     forbid: function (group, forbids) {
879         dw_mediamanager.forbidden_opts[group] = forbids;
880     },
881 
882     allowedOpt: function (opt, val) {
883         var ret = true;
884         jQuery.each(dw_mediamanager.forbidden_opts,
885             function (_, forbids) {
886                 ret = forbids[opt] !== false &&
887                     jQuery.inArray(val, forbids[opt]) === -1;
888                 return ret;
889             });
890         return ret;
891     },
892 
893     getOpt: function (opt) {
894         var allowed = bind(dw_mediamanager.allowedOpt, opt);
895 
896         // Current value
897         if (dw_mediamanager[opt] !== false && allowed(dw_mediamanager[opt])) {
898             return dw_mediamanager[opt];
899         }
900 
901         // From cookie
902         if (DokuCookie.getValue(opt) && allowed(DokuCookie.getValue(opt))) {
903             return DokuCookie.getValue(opt);
904         }
905 
906         // size default
907         if (opt === 'size' && allowed('2')) {
908             return '2';
909         }
910 
911         // Whatever is allowed, and be it false
912         return jQuery.grep(['1', '2', '3', '4'], allowed)[0] || false;
913     }
914 };
915 
916 /**
917  * Default implementation for the media manager's select action
918  *
919  * Can be overriden with the onselect URL parameter. Is called on the opener context
920  *
921  * @param {string} edid
922  * @param {string} mediaid
923  * @param {string} opts
924  * @param {string} align [none, left, center, right]
925  */
926 function dw_mediamanager_item_select(edid, mediaid, opts, align, keepopen) {
927     var alignleft = '';
928     var alignright = '';
929 
930     // Get the 2 characters after the cursor to check if we're currently inside an image tag
931     var cursorInImageTag = false;
932     var textArea = jQuery('#' + edid)[0];
933     var selection = DWgetSelection(textArea);
934     selection.end = selection.end + 2;
935     var charsAfterCursor = selection.getText();
936     if (charsAfterCursor === '}}') {
937         cursorInImageTag = true;
938     }
939 
940     if (align !== '1') {
941         alignleft = align === '2' ? '' : ' ';
942         alignright = align === '4' ? '' : ' ';
943     }
944     if (keepopen && cursorInImageTag) {
945         selection.start = selection.start + 2;
946         DWsetSelection(selection);
947     }
948     insertTags(edid, '{{' + alignleft + mediaid + opts + alignright + '|', '}}', '');
949 }
950 
951 jQuery(dw_mediamanager.init);
952