xref: /dokuwiki/lib/scripts/media.js (revision 67a0ce7861f65736f36a8dd392c70c9c2d235977)
1/*jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: false, strict: true, newcap: true, immed: true */
2/*global jQuery, window, DOKU_BASE*/
3"use strict";
4
5// TODO
6// * fix the css to have pointers on the +/- images in the tree when JS is enabled
7// * fix the css to have pointers on a.select when JS is enabled
8// * refactor once the jQuery port is over ;)
9
10/**
11 * JavaScript functionality for the media management popup
12 *
13 * @author Andreas Gohr <andi@splitbrain.org>
14 * @author Pierre Spring <pierre.spring@caillou.ch>
15 */
16(function ($) {
17    var toggle, list, prepare_content, insert, confirmattach, attachoptions, initpopup, updatehide, setalign, setsize, inSet, outSet, media_manager;
18
19    var media_manager = {
20        keepopen: false,
21        hide: false,
22        align: false,
23        popup: false,
24        display: false,
25        link: false,
26        size: false,
27        ext: false,
28    };
29
30    /**
31     * build the popup window
32     *
33     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
34     */
35    initpopup = function() {
36        var popup;
37
38        popup = document.createElement('div');
39        popup.setAttribute('id','media__popup');
40
41        var root = document.getElementById('media__manager');
42        if (root == null) return;
43        root.appendChild(popup);
44
45        var headline    = document.createElement('h1');
46        headline.innerHTML = LANG.mediatitle;
47        var headlineimg = document.createElement('img');
48        headlineimg.src = DOKU_BASE + 'lib/images/close.png';
49        headlineimg.id  = 'media__closeimg';
50        $(headlineimg).click(function () {$(popup).hide()});
51        headline.insertBefore(headlineimg, headline.firstChild);
52        popup.appendChild(headline);
53        drag.attach(popup,headline); // Pierre: TODO
54
55        // link
56
57        var linkp = document.createElement('p');
58
59        linkp.id = "media__linkstyle";
60        if (media_manager.display == "2") {
61            linkp.style.display = "none";
62        }
63
64        var linkl = document.createElement('label');
65        linkl.innerHTML = LANG.mediatarget;
66        linkp.appendChild(linkl);
67
68        var linkbtns = ['lnk', 'direct', 'nolnk', 'displaylnk'];
69        for (var i = 0 ; i < linkbtns.length ; ++i) {
70            var linkbtn = document.createElement('button');
71            linkbtn.className = 'button';
72            linkbtn.value = i + 1;
73            linkbtn.id    = "media__linkbtn" + (i + 1);
74            linkbtn.title = LANG['media' + linkbtns[i]];
75            linkbtn.style.borderStyle = 'outset';
76            $(linkbtn).click(function (event) { return setlink(event,this); });
77
78            var linkimg = document.createElement('img');
79            linkimg.src = DOKU_BASE + 'lib/images/media_link_' + linkbtns[i] + '.png';
80
81            linkbtn.appendChild(linkimg);
82            linkp.appendChild(linkbtn);
83        }
84
85        popup.appendChild(linkp);
86
87        // align
88
89        var alignp    = document.createElement('p');
90        var alignl    = document.createElement('label');
91
92        alignp.appendChild(alignl);
93        alignp.id = 'media__align';
94        if (media_manager.display == "2") {
95            alignp.style.display = "none";
96        }
97        alignl.innerHTML = LANG['mediaalign'];
98
99        var alignbtns = ['noalign', 'left', 'center', 'right'];
100        for (var n = 0 ; n < alignbtns.length ; ++n) {
101            var alignbtn = document.createElement('button');
102            var alignimg = document.createElement('img');
103            alignimg.src = DOKU_BASE + 'lib/images/media_align_' + alignbtns[n] + '.png';
104
105            alignbtn.id    = "media__alignbtn" + n;
106            alignbtn.value = n;
107            alignbtn.title = LANG['media' + alignbtns[n]];
108            alignbtn.className = 'button';
109            alignbtn.appendChild(alignimg);
110            alignbtn.style.borderStyle = 'outset';
111            $(alignbtn).click(function (event) { return setalign(event,this); });
112
113            alignp.appendChild(alignbtn);
114        }
115
116        popup.appendChild(alignp);
117
118        // size
119
120        var sizep    = document.createElement('p');
121        var sizel    = document.createElement('label');
122
123        sizep.id = 'media__size';
124        if (media_manager.display == "2") {
125            sizep.style.display = "none";
126        }
127        sizep.appendChild(sizel);
128        sizel.innerHTML = LANG['mediasize'];
129
130        var sizebtns = ['small', 'medium', 'large', 'original'];
131        for (var size = 0 ; size < sizebtns.length ; ++size) {
132            var sizebtn = document.createElement('button');
133            var sizeimg = document.createElement('img');
134
135            sizep.appendChild(sizebtn);
136            sizeimg.src = DOKU_BASE + 'lib/images/media_size_' + sizebtns[size] + '.png';
137
138            sizebtn.className = 'button';
139            sizebtn.appendChild(sizeimg);
140            sizebtn.value = size + 1;
141            sizebtn.id    = 'media__sizebtn' + (size + 1);
142            sizebtn.title = LANG['media' + sizebtns[size]];
143            sizebtn.style.borderStyle = 'outset';
144            $(sizebtn).click(function (event) { return setsize(event,this); });
145        }
146
147        popup.appendChild(sizep);
148
149        // send and close button
150
151        var btnp = document.createElement('p');
152        popup.appendChild(btnp);
153        btnp.setAttribute('class','btnlbl');
154
155        var btn  = document.createElement('input');
156        btn.type = 'button';
157        btn.id   = 'media__sendbtn';
158        btn.setAttribute('class','button');
159        btn.value = LANG['mediainsert'];
160        btnp.appendChild(btn);
161    };
162
163    /**
164     * Insert the clicked image into the opener's textarea
165     *
166     * @author Andreas Gohr <andi@splitbrain.org>
167     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
168     * @author Pierre Spring <pierre.spring@caillou.ch>
169     */
170    insert = function (id) {
171        var opts, optsstart, alignleft, alignright;
172
173        // set syntax options
174        $('#media__popup').hide();
175
176        opts = '';
177        optsstart = '';
178        alignleft = '';
179        alignright = '';
180
181        if (media_manager.ext == 'img' || media_manager.ext == 'swf') {
182
183            if (media_manager.link == '4') {
184                    opts = '?linkonly';
185            } else {
186
187                if (media_manager.link == "3" && media_manager.ext == 'img') {
188                    opts = '?nolink';
189                    optsstart = true;
190                } else if (media_manager.link == "2" && media_manager.ext == 'img') {
191                    opts = '?direct';
192                    optsstart = true;
193                }
194
195                var s = parseInt(media_manager.size);
196
197                if (s && s >= 1) {
198                    opts += (optsstart)?'&':'?';
199                    if (s=="1") {
200                        opts += '100';
201                        if (media_manager.ext == 'swf') {
202                            opts += 'x62';
203                        }
204                    } else if (s=="2") {
205                        opts += '200';
206                        if (media_manager.ext == 'swf') {
207                            opts += 'x123';
208                        }
209                    } else if (s=="3"){
210                        opts += '300';
211                        if (media_manager.ext == 'swf') {
212                            opts += 'x185';
213                        }
214                    }
215                }
216                if (media_manager.align == '1') {
217                    alignleft = '';
218                    alignright = ' ';
219                }
220                if (media_manager.align == '2') {
221                    alignleft = ' ';
222                    alignright = ' ';
223                }
224                if (media_manager.align == '3') {
225                    alignleft = ' ';
226                    alignright = '';
227                }
228            }
229        }
230        opener.insertTags('wiki__text','{{'+alignleft+id+opts+alignright+'|','}}','');
231
232        if(!media_manager.keepopen) window.close();
233        opener.focus();
234        return false;
235    };
236
237    /**
238     * Prefills the wikiname.
239     *
240     * @author Andreas Gohr <andi@splitbrain.org>
241     */
242    suggest = function(){
243        var file, name, text;
244
245        file = $(this);
246        name = $('#upload__name');
247        if(!file.size() || !name.size()) return;
248
249        text = file.val();
250        text = text.substr(text.lastIndexOf('/')+1);
251        text = text.substr(text.lastIndexOf('\\')+1);
252        name.val(text);
253    };
254
255    /**
256     * Open or close a subtree using AJAX
257     *
258     * @author Andreas Gohr <andi@splitbrain.org>
259     * @author Pierre Spring <pierre.spring@caillou.ch>
260     */
261    toggle = function (event) {
262        var clicky, listitem, sublist, link, ul;
263
264        event.preventDefault(); // TODO: really here?
265
266        var clicky = $(this);
267        var listitem = clicky.parent();
268
269        // if already open, close by removing the sublist
270        sublist = listitem.find('ul').first();
271        if(sublist.size()){
272            sublist.remove(); // TODO: really? we could just hide it, right?
273            clicky.attr('src', DOKU_BASE + 'lib/images/plus.gif');
274            return;
275        }
276
277        // get the enclosed link (is always the first one)
278        link = listitem.find('a').first();
279
280        //prepare the new ul
281        ul = $('<ul/>');
282
283        //fixme add classname here
284
285        $.post(
286            DOKU_BASE + 'lib/exe/ajax.php',
287            link.attr('search').substr(1) + '&call=medians',
288            function (data) {
289                ul.html(data)
290                listitem.append(ul);
291            },
292            'html'
293        );
294
295        clicky.attr('src', DOKU_BASE + 'lib/images/minus.gif');
296    };
297
298    /**
299     * list the content of a namespace using AJAX
300     *
301     * @author Andreas Gohr <andi@splitbrain.org>
302     * @author Pierre Spring <pierre.spring@caillou.ch>
303     */
304    list = function (event) {
305        var link, content;
306        link = $(this);
307
308        event.preventDefault();
309
310        cleanMsgArea();
311        content = $('#media__content');
312        content.html('<img src="' + DOKU_BASE + 'lib/images/loading.gif" alt="..." class="load" />');
313
314        // fetch the subtree
315        $.post(
316            DOKU_BASE + 'lib/exe/ajax.php',
317            link.attr('search').substr(1)+'&call=medialist',
318            function (data) {
319                content.html(data);
320                prepare_content(content);
321                updatehide();
322            },
323            'html'
324        );
325
326    };
327
328    prepare_content = function (content) {
329        // hide syntax example
330        content.find('div.example:visible').hide();
331        initFlashUpload();
332    };
333
334    /**
335         * shows the popup for a image link
336         */
337        select = function(event){
338            var link, id, dot, ext;
339
340            event.preventDefault();
341
342            link = $(this);
343            id = link.attr('name').substr(2);
344
345            if(!opener){
346                // if we don't run in popup display example
347                // the id's are a bit wired and $('#ex_wiki_dokuwiki-128.png') will not be found
348                // by Sizzle (the CSS Selector Engine used by jQuery),
349                // hence the document.getElementById() call
350                $(document.getElementById('ex_'+id.replace(/:/g,'_').replace(/^_/,''))).toggle();
351                return;
352            }
353
354            link = link[0];
355
356            media_manager.ext = false;
357            dot = id.lastIndexOf(".");
358
359            if (-1 === dot) {
360                insert(id);
361                return;
362            }
363
364            ext = id.substr(dot);
365
366            if (ext != '.jpg' && ext != '.jpeg' && ext != '.png' && ext != '.gif' && ext != '.swf') {
367                insert(id);
368                return;
369            }
370
371            // remove old callback from the insert button and set the new one.
372            $('#media__sendbtn').unbind().click(function () {insert(id)});
373
374            $('#media__popup').show()
375                .css('left', event.pageX + 'px')
376                .css('top', event.pageY + 'px');
377
378            $('#media__popup button.button').each(function (index, element) { outSet(element) } );
379
380
381            if (ext == '.swf') {
382                media_manager.ext = 'swf';
383
384                // disable display buttons for detail and linked image
385                $('#media__linkbtn1').hide();
386                $('#media__linkbtn2').hide();
387
388                // set the link button to default
389                if (media_manager.link != false) {
390                    if ( media_manager.link == '2' || media_manager.link == '1')  {
391                        inSet('media__linkbtn3');
392                        media_manager.link = '3';
393                        DokuCookie.setValue('link','3');
394                    } else {
395                        inSet('media__linkbtn'+media_manager.link);
396                    }
397                } else if (DokuCookie.getValue('link')) {
398                    if ( DokuCookie.getValue('link') == '2' ||  DokuCookie.getValue('link') == '1')  {
399                        // this options are not availible
400                        inSet('media__linkbtn3');
401                        media_manager.link = '3';
402                        DokuCookie.setValue('link','3');
403                    } else {
404                        inSet('media__linkbtn'+DokuCookie.getValue('link'));
405                        media_manager.link = DokuCookie.getValue('link');
406                    }
407                } else {
408                    // default case
409                    media_manager.link = '3';
410                    inSet('media__linkbtn3');
411                    DokuCookie.setValue('link','3');
412                }
413
414                // disable button for original size
415                $('#media__sizebtn4').hide();
416
417            } else {
418                media_manager.ext = 'img';
419
420                // ensure that the display buttons are there
421                $('#media__linkbtn1').show();
422                $('#media__linkbtn2').show();
423                $('#media__sizebtn4').show();
424
425                // set the link button to default
426                if (DokuCookie.getValue('link')) {
427                    media_manager.link = DokuCookie.getValue('link');
428                }
429                if (media_manager.link == false) {
430                    // default case
431                    media_manager.link = '1';
432                    DokuCookie.setValue('link','1');
433                }
434                inSet('media__linkbtn'+media_manager.link);
435            }
436
437            if (media_manager.link == '4') {
438                media_manager.align = false;
439                media_manager.size = false;
440                $('#media__align').hide();
441                $('#media__size').hide();
442            } else {
443                $('#media__align').show();
444                $('#media__size').show();
445
446                // set the align button to default
447                if (media_manager.align != false) {
448                    inSet('media__alignbtn'+media_manager.align);
449                } else if (DokuCookie.getValue('align')) {
450                    inSet('media__alignbtn'+DokuCookie.getValue('align'));
451                    media_manager.align = DokuCookie.getValue('align');
452                } else {
453                    // default case
454                    media_manager.align = '0';
455                    inSet('media__alignbtn0');
456                    DokuCookie.setValue('align','0');
457                }
458
459                // set the size button to default
460                if (DokuCookie.getValue('size')) {
461                    media_manager.size = DokuCookie.getValue('size');
462                }
463                if (media_manager.size == false || (media_manager.size === '4' && ext === '.swf')) {
464                    // default case
465                    media_manager.size = '2';
466                    DokuCookie.setValue('size','2');
467                }
468                inSet('media__sizebtn'+media_manager.size);
469
470                $('#media__sendbtn').focus();
471            }
472
473           return;
474        };
475
476    /**
477     * Deletion confirmation dialog to the delete buttons.
478     *
479     * @author Michael Klier <chi@chimeric.de>
480     * @author Pierre Spring <pierre.spring@caillou.ch>
481     */
482    confirmattach = function(e){
483        if(!confirm(LANG['del_confirm'] + "\n" + jQuery(this).attr('title'))) {
484            e.preventDefault();
485        }
486    };
487
488    /**
489     * Creates checkboxes for additional options
490     *
491     * @author Andreas Gohr <andi@splitbrain.org>
492     * @author Pierre Spring <pierre.spring@caillou.ch>
493     */
494    attachoptions = function(){
495        obj = $('#media__opts')[0]
496        if(!obj) return;
497
498        // keep open
499        if(opener){
500            var kobox  = document.createElement('input');
501            kobox.type = 'checkbox';
502            kobox.id   = 'media__keepopen';
503            if(DokuCookie.getValue('keepopen')){
504                kobox.checked  = true;
505                kobox.defaultChecked = true; //IE wants this
506                media_manager.keepopen = true;
507            }
508
509            $(kobox).click(
510                function () {
511                    toggleOption(this, 'keepopen');
512                }
513            );
514
515            var kolbl  = document.createElement('label');
516            kolbl.htmlFor   = 'media__keepopen';
517            kolbl.innerHTML = LANG['keepopen'];
518
519            var kobr = document.createElement('br');
520
521            obj.appendChild(kobox);
522            obj.appendChild(kolbl);
523            obj.appendChild(kobr);
524        }
525
526        // hide details
527        var hdbox  = document.createElement('input');
528        hdbox.type = 'checkbox';
529        hdbox.id   = 'media__hide';
530        if(DokuCookie.getValue('hide')){
531            hdbox.checked = true;
532            hdbox.defaultChecked = true; //IE wants this
533            media_manager.hide    = true;
534        }
535        $(hdbox).click(
536            function () {
537                toggleOption(this, 'hide');
538                updatehide();
539            }
540        );
541
542        var hdlbl  = document.createElement('label');
543        hdlbl.htmlFor   = 'media__hide';
544        hdlbl.innerHTML = LANG['hidedetails'];
545
546        var hdbr = document.createElement('br');
547
548        obj.appendChild(hdbox);
549        obj.appendChild(hdlbl);
550        obj.appendChild(hdbr);
551        updatehide();
552    },
553
554    /**
555     * Generalized toggler
556     *
557     * @author Pierre Spring <pierre.spring@caillou.ch>
558     */
559    toggleOption = function (checkbox, variable) {
560        if (checkbox.checked) {
561            DokuCookie.setValue(variable, 1);
562            media_manager[variable] = true;
563        } else {
564            DokuCookie.setValue(variable, '');
565            media_manager[variable] = false;
566        }
567    }
568
569    initFlashUpload = function () {
570        var oform, oflash, title;
571        if(!hasFlash(8)) return;
572
573        oform  = $('#dw__upload');
574        oflash = $('#dw__flashupload');
575
576        if(!oform.size() || !oflash.size()) return;
577
578        title = LANG['mu_btn'];
579
580        $('<img/>').attr('src', DOKU_BASE+'lib/images/multiupload.png')
581            .attr('title', title)
582            .attr('alt', title)
583            .css('cursor', 'pointer')
584            .click(
585                function () {
586                    oform.hide();
587                    oflash.show();
588                }
589            )
590            .appendTo(oform);
591    };
592
593    /**
594     * Sets the visibility of the image details accordingly to the
595     * chosen hide state
596     *
597     * @author Andreas Gohr <andi@splitbrain.org>
598     */
599    updatehide = function(){
600        var content = $('#media__content');
601        if(0 === content.size()) {
602            return;
603        }
604        content.find('div.detail').each(
605            function (index, element) {
606                if(media_manager.hide){
607                    element.style.display = 'none';
608                }else{
609                    element.style.display = '';
610                }
611            }
612
613        );
614    };
615
616    /**
617     * set the align
618     *
619     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
620     */
621    setalign = function(event,cb){
622        if(cb.value){
623            DokuCookie.setValue('align',cb.value);
624            media_manager.align = cb.value;
625            outSet("media__alignbtn0");
626            outSet("media__alignbtn1");
627            outSet("media__alignbtn2");
628            outSet("media__alignbtn3");
629            inSet("media__alignbtn"+cb.value);
630        }else{
631            DokuCookie.setValue('align','');
632            media_manager.align = false;
633        }
634    };
635
636    /**
637     * set the link type
638     *
639     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
640     */
641    setlink = function(event,cb){
642        if(cb.value){
643            DokuCookie.setValue('link',cb.value);
644            media_manager.link = cb.value;
645            outSet("media__linkbtn1");
646            outSet("media__linkbtn2");
647            outSet("media__linkbtn3");
648            outSet("media__linkbtn4");
649            inSet("media__linkbtn"+cb.value);
650            var size = $("#media__size");
651            var align = $("#media__align");
652            if (cb.value != '4') {
653                size.show();
654                align.show();
655            } else {
656                size.hide();
657                align.hide();
658            }
659        }else{
660            DokuCookie.setValue('link','');
661            media_manager.link = false;
662        }
663    };
664
665    /**
666     * set the image size
667     *
668     * @author Dominik Eckelmann <eckelmann@cosmocode.de>
669     */
670    setsize = function(event,cb){
671        if (cb.value) {
672            DokuCookie.setValue('size',cb.value);
673            media_manager.size = cb.value;
674            for (var i = 1 ; i <= 4 ; ++i) {
675                outSet("media__sizebtn" + i);
676            }
677            inSet("media__sizebtn"+cb.value);
678        } else {
679            DokuCookie.setValue('size','');
680            media_manager.width = false;
681        }
682    };
683
684    /**
685     * sets the border to inset
686     */
687    inSet = function(id) {
688        var ele = $('#' + id).css('border-style', 'inset');
689    };
690
691    /**
692     * sets the border to outset
693     */
694    outSet = function(element) {
695        if ('string' === typeof element) {
696            element = '#' + element;
697        }
698        $(element).css('border-style', 'outset');
699    };
700
701    $(function () {
702        var content = $('#media__content');
703        prepare_content(content);
704
705        attachoptions();
706        initpopup();
707
708        // add the action to autofill the "upload as" field
709        content.delegate('#upload__file', 'change', suggest)
710            // Attach the image selector action to all links
711            .delegate('a.select', 'click', select)
712            // Attach deletion confirmation dialog to the delete buttons
713            .delegate('#media__content a.btn_media_delete', 'click', confirmattach);
714
715
716        $('#media__tree').delegate('img', 'click', toggle)
717            .delegate('a', 'click', list);
718    });
719}(jQuery));