xref: /dokuwiki/lib/scripts/media.js (revision c3fd081f18988b471ced03bd73455eebb4f1efc6)
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
8var 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].replace(/[^\w-]/g, '') : 'wiki__text';
273        cb = String.prototype.match.call(document.location, /[?&]onselect=([^&]+)/);
274        cb = cb ? cb[1].replace(/[^\w]/g, '') : 'dw_mediamanager_item_select';
275
276        // The callback name comes from a URL parameter and is called on the
277        // opener. Only accept functions defined in page script, never a
278        // browser/JS built-in (eval, Function, setTimeout, open, ...) which all
279        // report "[native code]" when stringified.
280        var fn = opener[cb];
281        if (typeof fn !== 'function' || /\[native code\]/.test(Function.prototype.toString.call(fn))) {
282            cb = 'dw_mediamanager_item_select';
283        }
284
285        // arguments here only match the dw_mediamanager_item_select function, these will need to change if you override cb with onselect GET param
286        opener[cb](edid, id, opts, dw_mediamanager.align, dw_mediamanager.keepopen);
287        if (!dw_mediamanager.keepopen) {
288            window.close();
289        }
290        opener.focus();
291        return false;
292    },
293
294
295    /**
296     * Prefills the wikiname.
297     *
298     * @author Andreas Gohr <andi@splitbrain.org>
299     */
300    suggest: function () {
301        var $file, $name, text;
302
303        $file = jQuery(this);
304        $name = jQuery('#upload__name');
305
306        if ($name.val() != '') return;
307
308        if (!$file.length || !$name.length) {
309            return;
310        }
311
312        text = $file.val();
313        text = text.substr(text.lastIndexOf('/') + 1);
314        text = text.substr(text.lastIndexOf('\\') + 1);
315        $name.val(text);
316    },
317
318    /**
319     * list the content of a namespace using AJAX
320     *
321     * @author Andreas Gohr <andi@splitbrain.org>
322     * @author Pierre Spring <pierre.spring@caillou.ch>
323     */
324    list: function (event) {
325        var $link, $content, params;
326
327        if (event) {
328            event.preventDefault();
329        }
330
331        jQuery('div.success, div.info, div.error, div.notify').remove();
332
333        $link = jQuery(this);
334
335        //popup
336        $content = jQuery('#media__content');
337
338        if ($content.length === 0) {
339            //fullscreen media manager
340            $content = jQuery('div.filelist');
341
342            if ($link.hasClass('idx_dir')) {
343                //changing namespace
344                jQuery('div.file').empty();
345                jQuery('div.namespaces .selected').removeClass('selected');
346                $link.addClass('selected');
347            }
348        }
349
350        params = 'call=medialist&';
351
352        if ($link[0].search) {
353            params += $link[0].search.substr(1);
354        } else if ($link.is('form')) {
355            params += dw_mediamanager.form_params($link);
356        } else if ($link.closest('form').length > 0) {
357            params += dw_mediamanager.form_params($link.closest('form'));
358        }
359
360        // fetch the subtree
361        dw_mediamanager.update_content($content, params);
362    },
363
364    /**
365     * Returns form parameters
366     *
367     * @author Kate Arzamastseva <pshns@ukr.net>
368     */
369    form_params: function ($form) {
370        if (!$form.length) return;
371
372        var action = '';
373        var i = $form[0].action.indexOf('?');
374        if (i >= 0) {
375            action = $form[0].action.substr(i + 1);
376        }
377        return action + '&' + $form.serialize();
378    },
379
380    set_fileview_list: function (new_type) {
381        dw_mediamanager.set_fileview_opt(['list', 'listType', function (new_type) {
382            jQuery('div.filelist div.panelContent ul')
383                .toggleClass('rows', new_type === 'rows')
384                .toggleClass('thumbs', new_type === 'thumbs');
385        }], new_type);
386    },
387
388    set_fileview_sort: function (new_sort) {
389        dw_mediamanager.set_fileview_opt(['sort', 'sortBy', function (new_sort) {
390            // FIXME
391        }], new_sort);
392    },
393
394    set_fileview_opt: function (opt, new_val) {
395        if (typeof new_val === 'undefined') {
396            new_val = jQuery('form.options li.' + opt[1] + ' input')
397                .filter(':checked').val();
398            // if new_val is still undefined (because form.options is not in active tab), set to most spacious option
399            if (typeof new_val === 'undefined') {
400                new_val = 'thumbs';
401            }
402        }
403
404        if (new_val !== dw_mediamanager.view_opts[opt[0]]) {
405            opt[2](new_val);
406
407            DokuCookie.setValue(opt[0], new_val);
408
409            dw_mediamanager.view_opts[opt[0]] = new_val;
410        }
411    },
412
413    /**
414     * Lists the content of the right column (image details) using AJAX
415     *
416     * @author Kate Arzamastseva <pshns@ukr.net>
417     */
418    details: function (event) {
419        var $link, $content, params, update_list;
420        $link = jQuery(this);
421        event.preventDefault();
422
423        jQuery('div.success, div.info, div.error, div.notify').remove();
424
425        if ($link[0].id == 'mediamanager__btn_delete' && !confirm(LANG.del_confirm)) {
426            return false;
427        }
428        if ($link[0].id == 'mediamanager__btn_restore' && !confirm(LANG.restore_confirm)) {
429            return false;
430        }
431
432        $content = jQuery('div.file');
433        params = 'call=mediadetails&';
434
435        if ($link[0].search) {
436            params += $link[0].search.substr(1);
437        } else if ($link.is('form')) {
438            params += dw_mediamanager.form_params($link);
439        } else if ($link.closest('form').length > 0) {
440            params += dw_mediamanager.form_params($link.closest('form'));
441        }
442
443        update_list = ($link[0].id == 'mediamanager__btn_delete' ||
444        $link[0].id == 'mediamanager__btn_restore');
445
446        dw_mediamanager.update_content($content, params, update_list);
447    },
448
449    update_content: function ($content, params, update_list) {
450        var $container;
451
452        jQuery.post(
453            DOKU_BASE + 'lib/exe/ajax.php',
454            params,
455            function (data) {
456                dw_mediamanager.$resizables().resizable('destroy');
457
458                if (update_list) {
459                    dw_mediamanager.list.call(jQuery('#mediamanager__page').find('form.options button[type="submit"]')[0]);
460                }
461
462                $content.html(data);
463
464                dw_mediamanager.prepare_content($content);
465                dw_mediamanager.updatehide();
466
467                dw_mediamanager.update_resizable();
468                dw_behaviour.revisionBoxHandler();
469
470                // Make sure that the list view style stays the same
471                dw_mediamanager.set_fileview_list(dw_mediamanager.view_opts.list);
472
473                dw_mediamanager.image_diff();
474                dw_mediamanager.init_ajax_uploader();
475                dw_mediamanager.init_options();
476
477            },
478            'html'
479        );
480        $container = $content.find('div.panelContent');
481        if ($container.length === 0) {
482            $container = $content;
483        }
484        $container.html('<img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="..." class="load" />');
485    },
486
487    window_resize: function () {
488        dw_mediamanager.opacity_slider();
489        dw_mediamanager.portions_slider();
490    },
491
492    $resizables: function () {
493        return jQuery('#mediamanager__page').find('div.namespaces, div.filelist');
494    },
495
496    /**
497     * Updates mediamanager layout
498     *
499     * @author Kate Arzamastseva <pshns@ukr.net>
500     */
501    update_resizable: function () {
502        var $resizables = dw_mediamanager.$resizables();
503
504        $resizables.resizable({
505            handles: (jQuery('html[dir=rtl]').length ? 'w' : 'e'),
506            resize: function (event, ui) {
507                var $page = jQuery('#mediamanager__page');
508                var widthFull = $page.width();
509                var widthResizables = 0;
510                $resizables.each(function () {
511                    widthResizables += jQuery(this).width();
512                });
513                var $filePanel = $page.find('div.panel.file');
514
515                // set max width of resizable column
516                var widthOtherResizable = widthResizables - jQuery(this).width();
517                var minWidthNonResizable = parseFloat($filePanel.css("min-width"));
518                var maxWidth = widthFull - (widthOtherResizable + minWidthNonResizable) - 1;
519                $resizables.resizable("option", "maxWidth", maxWidth);
520
521                // width of file panel in % = 100% - width of resizables in %
522                // this calculates with 99.9 and not 100 to overcome rounding errors
523                var relWidthNonResizable = 99.9 - (100 * widthResizables / widthFull);
524                // set width of file panel
525                $filePanel.width(relWidthNonResizable + '%');
526
527                dw_mediamanager.opacity_slider();
528                dw_mediamanager.portions_slider();
529            }
530        });
531    },
532
533    resize: function () {
534        jQuery('#mediamanager__page').find('div.panelContent').css('height', '60vh');
535    },
536
537    /**
538     * Prints 'select' for image difference representation type
539     *
540     * @author Kate Arzamastseva <pshns@ukr.net>
541     */
542    image_diff: function () {
543        if (jQuery('#mediamanager__difftype').length) return;
544
545        var $form = jQuery('#mediamanager__form_diffview');
546        if (!$form.length) return;
547
548        var $label = jQuery(document.createElement('label'));
549        $label.append('<span>' + LANG.media_diff + '</span> ');
550        var $select = jQuery(document.createElement('select'))
551            .attr('id', 'mediamanager__difftype')
552            .attr('name', 'difftype')
553            .change(dw_mediamanager.change_diff_type);
554        $select.append(new Option(LANG.media_diff_both, "both"));
555        $select.append(new Option(LANG.media_diff_opacity, "opacity"));
556        $select.append(new Option(LANG.media_diff_portions, "portions"));
557        $label.append($select);
558        $form.append($label);
559
560        // for IE
561        var select = document.getElementById('mediamanager__difftype');
562        select.options[0].text = LANG.media_diff_both;
563        select.options[1].text = LANG.media_diff_opacity;
564        select.options[2].text = LANG.media_diff_portions;
565    },
566
567    /**
568     * Handles selection of image difference representation type
569     *
570     * @author Kate Arzamastseva <pshns@ukr.net>
571     */
572    change_diff_type: function () {
573        var $select = jQuery('#mediamanager__difftype');
574        var $content = jQuery('#mediamanager__diff');
575
576        var params = dw_mediamanager.form_params($select.closest('form')) + '&call=mediadiff';
577        jQuery.post(
578            DOKU_BASE + 'lib/exe/ajax.php',
579            params,
580            function (data) {
581                $content.html(data);
582                dw_mediamanager.portions_slider();
583                dw_mediamanager.opacity_slider();
584            },
585            'html'
586        );
587    },
588
589    /**
590     * Sets options for opacity diff slider
591     *
592     * @author Kate Arzamastseva <pshns@ukr.net>
593     */
594    opacity_slider: function () {
595        var $diff = jQuery("#mediamanager__diff");
596        var $slider = $diff.find("div.slider");
597        if (!$slider.length) return;
598
599        var $image = $diff.find('div.imageDiff.opacity div.image1 img');
600        if (!$image.length) return;
601        $slider.width($image.width() - 20);
602
603        $slider.slider();
604        $slider.slider("option", "min", 0);
605        $slider.slider("option", "max", 0.999);
606        $slider.slider("option", "step", 0.001);
607        $slider.slider("option", "value", 0.5);
608        $slider.on("slide", function (event, ui) {
609            jQuery('#mediamanager__diff').find('div.imageDiff.opacity div.image2 img').css({opacity: $slider.slider("option", "value")});
610        });
611    },
612
613    /**
614     * Sets options for red line diff slider
615     *
616     * @author Kate Arzamastseva <pshns@ukr.net>
617     */
618    portions_slider: function () {
619        var $diff = jQuery("#mediamanager__diff");
620        if (!$diff.length) return;
621
622        var $image1 = $diff.find('div.imageDiff.portions div.image1 img');
623        var $image2 = $diff.find('div.imageDiff.portions div.image2 img');
624        if (!$image1.length || !$image2.length) return;
625
626        $diff.width('100%');
627        $image2.parent().width('97%');
628        $image1.width('100%');
629        $image2.width('100%');
630
631        if ($image1.width() < $diff.width()) {
632            $diff.width($image1.width());
633        }
634
635        $image2.parent().width('50%');
636        $image2.width($image1.width());
637        $image1.width($image1.width());
638
639        var $slider = $diff.find("div.slider");
640        if (!$slider.length) return;
641        $slider.width($image1.width() - 20);
642
643        $slider.slider();
644        $slider.slider("option", "min", 0);
645        $slider.slider("option", "max", 97);
646        $slider.slider("option", "step", 1);
647        $slider.slider("option", "value", 50);
648        $slider.on("slide", function (event, ui) {
649            jQuery('#mediamanager__diff').find('div.imageDiff.portions div.image2').css({width: $slider.slider("option", "value") + '%'});
650        });
651    },
652
653    /**
654     * Parse a URI query string to an associative array
655     *
656     * @author Kate Arzamastseva <pshns@ukr.net>
657     */
658    params_toarray: function (str) {
659        var vars = [], hash;
660        var hashes = str.split('&');
661        for (var i = 0; i < hashes.length; i++) {
662            hash = hashes[i].split('=');
663            vars[decodeURIComponent(hash[0])] = decodeURIComponent(hash[1]);
664        }
665        return vars;
666    },
667
668    init_ajax_uploader: function () {
669        if (!jQuery('#mediamanager__uploader').length) return;
670        if (jQuery('.qq-upload-list').length) return;
671
672        var params = dw_mediamanager.form_params(jQuery('#dw__upload')) + '&call=mediaupload';
673        params = dw_mediamanager.params_toarray(params);
674
675        var uploader = new qq.FileUploaderExtended({
676            element: document.getElementById('mediamanager__uploader'),
677            action: DOKU_BASE + 'lib/exe/ajax.php',
678            params: params
679        });
680    },
681
682    prepare_content: function ($content) {
683        // hide syntax example
684        $content.find('div.example:visible').hide();
685        // toggle list of allowed mime types
686        $content.find('a.allowedmime').on('click', function (event) {
687            event.preventDefault();
688            $toggle = jQuery(this);
689            $list = $toggle.next('span');
690            $list.toggle();
691        }).next('span').hide();
692
693    },
694
695    /**
696     * shows the popup for a image link
697     */
698    select: function (event) {
699        var $link, id, dot, ext;
700
701        event.preventDefault();
702
703        $link = jQuery(this);
704        id = $link.attr('id').substr(2);
705
706        if (!opener) {
707            // if we don't run in popup display example
708            // the id's are a bit wierd and jQuery('#ex_wiki_dokuwiki-128.png')
709            // will not be found by Sizzle (the CSS Selector Engine
710            // used by jQuery), hence the document.getElementById() call
711            jQuery(document.getElementById('ex_' + id.replace(/:/g, '_').replace(/^_/, ''))).dw_toggle();
712            return;
713        }
714
715        dw_mediamanager.ext = false;
716        dot = id.lastIndexOf(".");
717
718        if (-1 === dot) {
719            dw_mediamanager.insert(id);
720            return;
721        }
722
723        ext = id.substr(dot);
724
725        if ({'.jpg': 1, '.jpeg': 1, '.png': 1, '.gif': 1, '.swf': 1}[ext] !== 1) {
726            dw_mediamanager.insert(id);
727            return;
728        }
729
730        // remove old callback from the insert button and set the new one.
731        var $sendbtn = jQuery('#media__sendbtn');
732        $sendbtn.off().on('click', bind(dw_mediamanager.insert, id));
733
734        dw_mediamanager.unforbid('ext');
735        if (ext === '.swf') {
736            dw_mediamanager.ext = 'swf';
737            dw_mediamanager.forbid('ext', {
738                link: ['1', '2'],
739                size: ['4']
740            });
741        } else {
742            dw_mediamanager.ext = 'img';
743        }
744
745        // Set to defaults
746        dw_mediamanager.setOpt('link');
747        dw_mediamanager.setOpt('align');
748        dw_mediamanager.setOpt('size');
749
750        // toggle buttons for detail and linked image, original size
751        jQuery('#media__linkbtn1, #media__linkbtn2, #media__sizebtn4')
752            .toggle(dw_mediamanager.ext === 'img');
753
754        dw_mediamanager.$popup.dialog('open');
755
756        $sendbtn.focus();
757    },
758
759    /**
760     * Deletion confirmation dialog to the delete buttons.
761     *
762     * @author Michael Klier <chi@chimeric.de>
763     * @author Pierre Spring <pierre.spring@caillou.ch>
764     */
765    confirmattach: function (e) {
766        if (!confirm(LANG.del_confirm + "\n" + jQuery(this).attr('title'))) {
767            e.preventDefault();
768        }
769    },
770
771    /**
772     * Creates checkboxes for additional options
773     *
774     * @author Andreas Gohr <andi@splitbrain.org>
775     * @author Pierre Spring <pierre.spring@caillou.ch>
776     */
777    attachoptions: function () {
778        var $obj, opts;
779
780        $obj = jQuery('#media__opts');
781        if ($obj.length === 0) {
782            return;
783        }
784
785        opts = [];
786        // keep open
787        if (opener) {
788            opts.push(['keepopen', 'keepopen']);
789        }
790        opts.push(['hide', 'hidedetails']);
791
792        jQuery.each(opts,
793            function (_, opt) {
794                var $box, $lbl;
795                $box = jQuery(document.createElement('input'))
796                    .attr('type', 'checkbox')
797                    .attr('id', 'media__' + opt[0])
798                    .on('click', bind(dw_mediamanager.toggleOption, opt[0]));
799
800                if (DokuCookie.getValue(opt[0])) {
801                    $box.prop('checked', true);
802                    dw_mediamanager[opt[0]] = true;
803                }
804
805                $lbl = jQuery(document.createElement('label'))
806                    .attr('for', 'media__' + opt[0])
807                    .text(LANG[opt[1]]);
808
809                $obj.append($box, $lbl, document.createElement('br'));
810            });
811
812        dw_mediamanager.updatehide();
813    },
814
815    /**
816     * Generalized toggler
817     *
818     * @author Pierre Spring <pierre.spring@caillou.ch>
819     */
820    toggleOption: function (variable) {
821        if (jQuery(this).prop('checked')) {
822            DokuCookie.setValue(variable, 1);
823            dw_mediamanager[variable] = true;
824        } else {
825            DokuCookie.setValue(variable, '');
826            dw_mediamanager[variable] = false;
827        }
828        if (variable === 'hide') {
829            dw_mediamanager.updatehide();
830        }
831    },
832
833    /**
834     * Sets the visibility of the image details accordingly to the
835     * chosen hide state
836     *
837     * @author Andreas Gohr <andi@splitbrain.org>
838     */
839    updatehide: function () {
840        jQuery('#media__content').find('div.detail').dw_toggle(!dw_mediamanager.hide);
841    },
842
843    /**
844     * set media insertion option
845     *
846     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
847     */
848    setOpt: function (opt, e) {
849        var val, i;
850        if (typeof e !== 'undefined') {
851            val = this.id.substring(this.id.length - 1);
852        } else {
853            val = dw_mediamanager.getOpt(opt);
854        }
855
856        if (val === false) {
857            DokuCookie.setValue(opt, '');
858            dw_mediamanager[opt] = false;
859            return;
860        }
861
862        if (opt === 'link') {
863            if (val !== '4' && dw_mediamanager.link === '4') {
864                dw_mediamanager.unforbid('linkonly');
865                dw_mediamanager.setOpt('align');
866                dw_mediamanager.setOpt('size');
867            } else if (val === '4') {
868                dw_mediamanager.forbid('linkonly', {align: false, size: false});
869            }
870
871            jQuery("#media__size, #media__align").dw_toggle(val !== '4');
872        }
873
874        DokuCookie.setValue(opt, val);
875        dw_mediamanager[opt] = val;
876
877        for (i = 1; i <= 4; i++) {
878            jQuery("#media__" + opt + "btn" + i).removeClass('selected');
879        }
880        jQuery('#media__' + opt + 'btn' + val).addClass('selected');
881    },
882
883    unforbid: function (group) {
884        delete dw_mediamanager.forbidden_opts[group];
885    },
886
887    forbid: function (group, forbids) {
888        dw_mediamanager.forbidden_opts[group] = forbids;
889    },
890
891    allowedOpt: function (opt, val) {
892        var ret = true;
893        jQuery.each(dw_mediamanager.forbidden_opts,
894            function (_, forbids) {
895                ret = forbids[opt] !== false &&
896                    jQuery.inArray(val, forbids[opt]) === -1;
897                return ret;
898            });
899        return ret;
900    },
901
902    getOpt: function (opt) {
903        var allowed = bind(dw_mediamanager.allowedOpt, opt);
904
905        // Current value
906        if (dw_mediamanager[opt] !== false && allowed(dw_mediamanager[opt])) {
907            return dw_mediamanager[opt];
908        }
909
910        // From cookie
911        if (DokuCookie.getValue(opt) && allowed(DokuCookie.getValue(opt))) {
912            return DokuCookie.getValue(opt);
913        }
914
915        // size default
916        if (opt === 'size' && allowed('2')) {
917            return '2';
918        }
919
920        // Whatever is allowed, and be it false
921        return jQuery.grep(['1', '2', '3', '4'], allowed)[0] || false;
922    }
923};
924
925/**
926 * Default implementation for the media manager's select action
927 *
928 * Can be overriden with the onselect URL parameter. Is called on the opener context
929 *
930 * @param {string} edid
931 * @param {string} mediaid
932 * @param {string} opts
933 * @param {string} align [none, left, center, right]
934 */
935function dw_mediamanager_item_select(edid, mediaid, opts, align, keepopen) {
936    var alignleft = '';
937    var alignright = '';
938
939    // Get the 2 characters after the cursor to check if we're currently inside an image tag
940    var cursorInImageTag = false;
941    var textArea = jQuery('#' + edid)[0];
942    var selection = DWgetSelection(textArea);
943    selection.end = selection.end + 2;
944    var charsAfterCursor = selection.getText();
945    if (charsAfterCursor === '}}') {
946        cursorInImageTag = true;
947    }
948
949    if (align !== '1') {
950        alignleft = align === '2' ? '' : ' ';
951        alignright = align === '4' ? '' : ' ';
952    }
953    if (keepopen && cursorInImageTag) {
954        selection.start = selection.start + 2;
955        DWsetSelection(selection);
956    }
957    insertTags(edid, '{{' + alignleft + mediaid + opts + alignright + '|', '}}', '');
958}
959
960jQuery(dw_mediamanager.init);
961