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