xref: /dokuwiki/lib/scripts/media.js (revision ba6c070edd92ca0fc8a6ee85d51769d64a19ee7c)
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    init: function () {
23        var $content, $tree;
24        $content = jQuery('#media__content');
25        $tree    = jQuery('#media__tree');
26
27        dw_mediamanager.prepare_content($content);
28
29        dw_mediamanager.attachoptions();
30        dw_mediamanager.initpopup();
31
32        // add the action to autofill the "upload as" field
33        $content.delegate('#upload__file', 'change', dw_mediamanager.suggest)
34                // Attach the image selector action to all links
35                .delegate('a.select', 'click', dw_mediamanager.select)
36                // Attach deletion confirmation dialog to the delete buttons
37                .delegate('#media__content a.btn_media_delete', 'click',
38                          dw_mediamanager.confirmattach);
39
40        $tree.dw_tree({toggle_selector: 'img',
41                       load_data: function (show_sublist, $clicky) {
42                           // get the enclosed link (is always the first one)
43                           var $link = $clicky.parent().find('div.li a.idx_dir');
44
45                           jQuery.post(
46                               DOKU_BASE + 'lib/exe/ajax.php',
47                               $link[0].search.substr(1) + '&call=medians',
48                               show_sublist,
49                               'html'
50                           );
51                       },
52
53                       toggle_display: function ($clicky, opening) {
54                           $clicky.attr('src',
55                                        DOKU_BASE + 'lib/images/' +
56                                        (opening ? 'minus' : 'plus') + '.gif');
57                       }});
58        $tree.delegate('a', 'click', dw_mediamanager.list);
59    },
60
61    /**
62     * build the popup window
63     *
64     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
65     */
66    initpopup: function () {
67        var opts, $insp, $insbtn;
68
69        dw_mediamanager.$popup = jQuery(document.createElement('div'))
70                 .attr('id', 'media__popup_content')
71                 .dialog({autoOpen: false, width: 280, modal: true,
72                          draggable: true, title: LANG.mediatitle,
73                          resizable: false});
74
75        opts = [{id: 'link', label: LANG.mediatarget,
76                 btns: ['lnk', 'direct', 'nolnk', 'displaylnk']},
77                {id: 'align', label: LANG.mediaalign,
78                 btns: ['noalign', 'left', 'center', 'right']},
79                {id: 'size', label: LANG.mediasize,
80                 btns: ['small', 'medium', 'large', 'original']}
81               ];
82
83        jQuery.each(opts, function (_, opt) {
84            var $p, $l;
85            $p = jQuery(document.createElement('p'))
86                 .attr('id', 'media__' + opt.id);
87
88            if (dw_mediamanager.display === "2") {
89                $p.hide();
90            }
91
92            $l = jQuery(document.createElement('label'))
93                 .text(opt.label);
94            $p.append($l);
95
96            jQuery.each(opt.btns, function (i, text) {
97                var $btn, $img;
98                $btn = jQuery(document.createElement('button'))
99                       .addClass('button')
100                       .attr('id', "media__" + opt.id + "btn" + (i + 1))
101                       .attr('title', LANG['media' + text])
102                       .click(bind(dw_mediamanager.setOpt, opt.id));
103
104                $img = jQuery(document.createElement('img'))
105                       .attr('src', DOKU_BASE + 'lib/images/media_' +
106                                    opt.id + '_' + text + '.png');
107
108                $btn.append($img);
109                $p.append($btn);
110            });
111
112            dw_mediamanager.$popup.append($p);
113        });
114
115        // insert button
116        $insp = jQuery(document.createElement('p'))
117                .addClass('btnlbl');
118        dw_mediamanager.$popup.append($insp);
119
120        $insbtn = jQuery(document.createElement('input'))
121                  .attr('id', 'media__sendbtn')
122                  .attr('type', 'button')
123                  .addClass('button')
124                  .val(LANG.mediainsert);
125        $insp.append($insbtn);
126    },
127
128    /**
129     * Insert the clicked image into the opener's textarea
130     *
131     * @author Andreas Gohr <andi@splitbrain.org>
132     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
133     * @author Pierre Spring <pierre.spring@caillou.ch>
134     */
135    insert: function (id) {
136        var opts, alignleft, alignright, edid, s;
137
138        // set syntax options
139        dw_mediamanager.$popup.dialog('close');
140
141        opts = '';
142        alignleft = '';
143        alignright = '';
144
145        if ({img: 1, swf: 1}[dw_mediamanager.ext] === 1) {
146
147            if (dw_mediamanager.link === '4') {
148                    opts = '?linkonly';
149            } else {
150
151                if (dw_mediamanager.link === "3" && dw_mediamanager.ext === 'img') {
152                    opts = '?nolink';
153                } else if (dw_mediamanager.link === "2" && dw_mediamanager.ext === 'img') {
154                    opts = '?direct';
155                }
156
157                s = parseInt(dw_mediamanager.size, 10);
158
159                if (s && s >= 1 && s < 4) {
160                    opts += (opts.length)?'&':'?';
161                    opts += dw_mediamanager.size + '00';
162                    if (dw_mediamanager.ext === 'swf') {
163                        switch (s) {
164                        case 1:
165                            opts += 'x62';
166                            break;
167                        case 2:
168                            opts += 'x123';
169                            break;
170                        case 3:
171                            opts += 'x185';
172                            break;
173                        }
174                    }
175                }
176                alignleft = dw_mediamanager.align === '2' ? '' : ' ';
177                alignright = dw_mediamanager.align === '4' ? '' : ' ';
178            }
179        }
180        edid = String.prototype.match.call(document.location, /&edid=([^&]+)/);
181        opener.insertTags(edid ? edid[1] : 'wiki__text',
182                          '{{'+alignleft+id+opts+alignright+'|','}}','');
183
184        if(!dw_mediamanager.keepopen) {
185            window.close();
186        }
187        opener.focus();
188        return false;
189    },
190
191    /**
192     * Prefills the wikiname.
193     *
194     * @author Andreas Gohr <andi@splitbrain.org>
195     */
196    suggest: function(){
197        var $file, $name, text;
198
199        $file = jQuery(this);
200        $name = jQuery('#upload__name');
201        if(!$file.length || !$name.length) {
202            return;
203        }
204
205        text = $file.val();
206        text = text.substr(text.lastIndexOf('/')+1);
207        text = text.substr(text.lastIndexOf('\\')+1);
208        $name.val(text);
209    },
210
211    /**
212     * list the content of a namespace using AJAX
213     *
214     * @author Andreas Gohr <andi@splitbrain.org>
215     * @author Pierre Spring <pierre.spring@caillou.ch>
216     */
217    list: function (event) {
218        var $link, $content;
219
220        event.preventDefault();
221
222        jQuery('div.success, div.info, div.error, div.notify').remove();
223
224        $link = jQuery(this);
225        $content = jQuery('#media__content');
226        $content.html('<img src="' + DOKU_BASE + 'lib/images/loading.gif" alt="..." class="load" />');
227
228        // fetch the subtree
229        jQuery.post(
230            DOKU_BASE + 'lib/exe/ajax.php',
231            $link[0].search.substr(1)+'&call=medialist',
232            function (data) {
233                $content.html(data);
234                dw_mediamanager.prepare_content($content);
235                dw_mediamanager.updatehide();
236            },
237            'html'
238        );
239    },
240
241    prepare_content: function ($content) {
242        // hide syntax example
243        $content.find('div.example:visible').hide();
244        dw_mediamanager.initFlashUpload();
245    },
246
247    /**
248     * shows the popup for a image link
249     */
250    select: function(event){
251        var $link, id, dot, ext;
252
253        event.preventDefault();
254
255        $link = jQuery(this);
256        id = $link.attr('name').substr(2);
257
258        if(!opener){
259            // if we don't run in popup display example
260            // the id's are a bit wierd and jQuery('#ex_wiki_dokuwiki-128.png')
261            // will not be found by Sizzle (the CSS Selector Engine
262            // used by jQuery), hence the document.getElementById() call
263            jQuery(document.getElementById('ex_'+id.replace(/:/g,'_').replace(/^_/,''))).dw_toggle();
264            return;
265        }
266
267        dw_mediamanager.ext = false;
268        dot = id.lastIndexOf(".");
269
270        if (-1 === dot) {
271            dw_mediamanager.insert(id);
272            return;
273        }
274
275        ext = id.substr(dot);
276
277        if ({'.jpg':1, '.jpeg':1, '.png':1, '.gif':1, '.swf':1}[ext] !== 1) {
278            dw_mediamanager.insert(id);
279            return;
280        }
281
282        // remove old callback from the insert button and set the new one.
283        jQuery('#media__sendbtn').unbind().click(bind(dw_mediamanager.insert, id));
284
285        dw_mediamanager.unforbid('ext');
286        if (ext === '.swf') {
287            dw_mediamanager.ext = 'swf';
288            dw_mediamanager.forbid('ext', {link: ['1', '2'],
289                                           size: ['4']});
290        } else {
291            dw_mediamanager.ext = 'img';
292        }
293
294        // Set to defaults
295        dw_mediamanager.setOpt('link');
296        dw_mediamanager.setOpt('align');
297        dw_mediamanager.setOpt('size');
298
299        // toggle buttons for detail and linked image, original size
300        jQuery('#media__linkbtn1, #media__linkbtn2, #media__sizebtn4')
301            .toggle(dw_mediamanager.ext === 'img');
302
303        dw_mediamanager.$popup.dialog('open');
304
305        jQuery('#media__sendbtn').focus();
306    },
307
308    /**
309     * Deletion confirmation dialog to the delete buttons.
310     *
311     * @author Michael Klier <chi@chimeric.de>
312     * @author Pierre Spring <pierre.spring@caillou.ch>
313     */
314    confirmattach: function(e){
315        if(!confirm(LANG.del_confirm + "\n" + jQuery(this).attr('title'))) {
316            e.preventDefault();
317        }
318    },
319
320    /**
321     * Creates checkboxes for additional options
322     *
323     * @author Andreas Gohr <andi@splitbrain.org>
324     * @author Pierre Spring <pierre.spring@caillou.ch>
325     */
326    attachoptions: function(){
327        var $obj, opts;
328
329        $obj = jQuery('#media__opts');
330        if($obj.length === 0) {
331            return;
332        }
333
334        opts = [];
335        // keep open
336        if(opener){
337            opts.push(['keepopen', 'keepopen']);
338        }
339        opts.push(['hide', 'hidedetails']);
340
341        jQuery.each(opts,
342                    function(_, opt) {
343                        var $box, $lbl;
344                        $box = jQuery(document.createElement('input'))
345                                 .attr('type', 'checkbox')
346                                 .attr('id', 'media__' + opt[0])
347                                 .click(bind(dw_mediamanager.toggleOption,
348                                             opt[0]));
349
350                        if(DokuCookie.getValue(opt[0])){
351                            $box.prop('checked', true);
352                            dw_mediamanager[opt[0]] = true;
353                        }
354
355                        $lbl = jQuery(document.createElement('label'))
356                                 .attr('for', 'media__' + opt[0])
357                                 .text(LANG[opt[1]]);
358
359                        $obj.append($box, $lbl, document.createElement('br'));
360                    });
361
362        dw_mediamanager.updatehide();
363    },
364
365    /**
366     * Generalized toggler
367     *
368     * @author Pierre Spring <pierre.spring@caillou.ch>
369     */
370    toggleOption: function (variable) {
371        if (jQuery(this).prop('checked')) {
372            DokuCookie.setValue(variable, 1);
373            dw_mediamanager[variable] = true;
374        } else {
375            DokuCookie.setValue(variable, '');
376            dw_mediamanager[variable] = false;
377        }
378        if (variable === 'hide') {
379            dw_mediamanager.updatehide();
380        }
381    },
382
383    initFlashUpload: function () {
384        var $oform, $oflash;
385        if(!hasFlash(8)) {
386            return;
387        }
388
389        $oform  = jQuery('#dw__upload');
390        $oflash = jQuery('#dw__flashupload');
391
392        if(!$oform.length || !$oflash.length) {
393            return;
394        }
395
396        jQuery(document.createElement('img'))
397            .attr('src', DOKU_BASE+'lib/images/multiupload.png')
398            .attr('title', LANG.mu_btn)
399            .attr('alt', LANG.mu_btn)
400            .css('cursor', 'pointer')
401            .click(
402                function () {
403                    $oform.hide();
404                    $oflash.show();
405                }
406            )
407            .appendTo($oform);
408    },
409
410    /**
411     * Sets the visibility of the image details accordingly to the
412     * chosen hide state
413     *
414     * @author Andreas Gohr <andi@splitbrain.org>
415     */
416    updatehide: function(){
417        jQuery('#media__content div.detail').dw_toggle(!dw_mediamanager.hide);
418    },
419
420    /**
421     * set media insertion option
422     *
423     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
424     */
425    setOpt: function(opt, e){
426        var val, i;
427        if (typeof e !== 'undefined') {
428            val = this.id.substring(this.id.length - 1);
429        } else {
430            val = dw_mediamanager.getOpt(opt);
431        }
432
433        if (val === false) {
434            DokuCookie.setValue(opt,'');
435            dw_mediamanager[opt] = false;
436            return;
437        }
438
439        if (opt === 'link') {
440            if (val !== '4' && dw_mediamanager.link === '4') {
441                dw_mediamanager.unforbid('linkonly');
442                dw_mediamanager.setOpt('align');
443                dw_mediamanager.setOpt('size');
444            } else if (val === '4') {
445                dw_mediamanager.forbid('linkonly', {align: false, size: false});
446            }
447
448            jQuery("#media__size, #media__align").dw_toggle(val !== '4');
449        }
450
451        DokuCookie.setValue(opt, val);
452        dw_mediamanager[opt] = val;
453
454        for (i = 1; i <= 4; i++) {
455            jQuery("#media__" + opt + "btn" + i).removeClass('selected');
456        }
457        jQuery('#media__' + opt + 'btn' + val).addClass('selected');
458    },
459
460    unforbid: function (group) {
461        delete dw_mediamanager.forbidden_opts[group];
462    },
463
464    forbid: function (group, forbids) {
465        dw_mediamanager.forbidden_opts[group] = forbids;
466    },
467
468    allowedOpt: function (opt, val) {
469        var ret = true;
470        jQuery.each(dw_mediamanager.forbidden_opts,
471                    function (_, forbids) {
472                        ret = forbids[opt] !== false &&
473                              jQuery.inArray(val, forbids[opt]) === -1;
474                        return ret;
475                    });
476        return ret;
477    },
478
479    getOpt: function (opt) {
480        var allowed = bind(dw_mediamanager.allowedOpt, opt);
481
482        // Current value
483        if (dw_mediamanager[opt] !== false && allowed(dw_mediamanager[opt])) {
484            return dw_mediamanager[opt];
485        }
486
487        // From cookie
488        if (DokuCookie.getValue(opt) && allowed(DokuCookie.getValue(opt))) {
489            return DokuCookie.getValue(opt);
490        }
491
492        // size default
493        if (opt === 'size' && allowed('2')) {
494            return '2';
495        }
496
497        // Whatever is allowed, and be it false
498        return jQuery.grep(['1', '2', '3', '4'], allowed)[0] || false;
499    }
500};
501
502// moved from helpers.js temporarily here
503/**
504 * Very simplistic Flash plugin check, probably works for Flash 8 and higher only
505 *
506 */
507function hasFlash(version){
508    var ver = 0, axo;
509    try{
510        if(navigator.plugins !== null && navigator.plugins.length > 0){
511           ver = navigator.plugins["Shockwave Flash"].description.split(' ')[2].split('.')[0];
512        }else{
513           axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
514           ver = axo.GetVariable("$version").split(' ')[1].split(',')[0];
515        }
516    }catch(e){ }
517
518    return ver >= version;
519}
520
521jQuery(dw_mediamanager.init);
522