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