xref: /plugin/visualindex/script/toolbar.js (revision 3c9c7f3beeea1dce712c368cb507b309c63f5d06)
1if (typeof window.toolbar !== 'undefined') {
2    function shouldShowInEditorMenu() {
3        const raw = window.JSINFO &&
4            JSINFO.plugins &&
5            JSINFO.plugins.visualindex
6            ? JSINFO.plugins.visualindex.show_in_editor_menu
7            : true;
8
9        if (typeof raw === 'boolean') return raw;
10        const normalized = String(raw).trim().toLowerCase();
11        return !(normalized === '0' || normalized === 'false' || normalized === 'off' || normalized === 'no');
12    }
13
14    function buildVisualIndexSyntax(values) {
15        let syntax = '{{visualindex>' + (values.namespace || '.');
16        if (values.filter) syntax += ';filter=' + values.filter;
17        if (values.desc) syntax += ';desc=1';
18        if (values.medias) syntax += ';medias=1';
19        syntax += '}}';
20        return syntax;
21    }
22
23    function insertAtSelection(area, text) {
24        const selection = DWgetSelection(area);
25        const before = area.value.substring(0, selection.start);
26        const after = area.value.substring(selection.end);
27        area.value = before + text + after;
28
29        const pos = before.length + text.length;
30        area.focus();
31        area.setSelectionRange(pos, pos);
32    }
33
34    function openVisualIndexDialog(onSubmit) {
35        const i18n = (window.LANG && LANG.plugins && LANG.plugins.visualindex) ? LANG.plugins.visualindex : {};
36        const title = i18n.toolbar_popup_title || 'Visualindex';
37        const insertLabel = i18n.toolbar_insert || 'Inserer';
38        const cancelLabel = i18n.toolbar_cancel || 'Annuler';
39        const namespaceLabel = i18n.toolbar_namespace || 'Namespace';
40        const namespaceHelp = i18n.toolbar_namespace_help || 'Dossier. "." = dossier courant.';
41        const namespacePickerLabel = i18n.toolbar_namespace_picker || 'Selectionner un dossier';
42        const filterLabel = i18n.toolbar_filter || 'Filtre';
43        const descLabel = i18n.toolbar_desc || 'Ordre descendant';
44        const mediasLabel = i18n.toolbar_medias || 'Afficher les medias';
45
46        const $dialog = jQuery('<div class="plugin_visualindex_form" title="' + title + '"></div>');
47
48        $dialog.append('<label>' + namespaceLabel + '</label>');
49        const $namespace = jQuery('<input type="text" class="edit" style="width:100%;" />').val('.');
50        $dialog.append($namespace);
51        $dialog.append('<div style="font-size:.9em;color:#555;margin-top:4px;">' + namespaceHelp + '</div>');
52
53        const $pickerWrap = jQuery('<div style="margin-top:8px;"></div>');
54        const $pickerBtn = jQuery('<button type="button" class="btn btn-default"></button>').text(namespacePickerLabel);
55        const $nsList = jQuery('<select size="6" style="width:100%;margin-top:6px;display:none;"></select>');
56        $pickerWrap.append($pickerBtn).append($nsList);
57        $dialog.append($pickerWrap);
58
59        $dialog.append('<label style="display:block;margin-top:8px;">' + filterLabel + '</label>');
60        const $filter = jQuery('<input type="text" class="edit" style="width:100%;" />');
61        $dialog.append($filter);
62
63        const $descWrap = jQuery('<label style="display:block;margin-top:10px;"></label>');
64        const $desc = jQuery('<input type="checkbox" />').prop('checked', false);
65        $descWrap.append($desc).append(' ' + descLabel);
66        $dialog.append($descWrap);
67
68        const $mediasWrap = jQuery('<label style="display:block;margin-top:6px;"></label>');
69        const $medias = jQuery('<input type="checkbox" />').prop('checked', false);
70        $mediasWrap.append($medias).append(' ' + mediasLabel);
71        $dialog.append($mediasWrap);
72
73        const normalizeNamespace = function (value) {
74            const val = String(value || '').trim();
75            if (!val || val === '.') return '.';
76            return val.replace(/:+$/, '');
77        };
78
79        const loadNamespaces = function () {
80            const q = normalizeNamespace($namespace.val());
81            jQuery.get(DOKU_BASE + 'lib/exe/ajax.php', {
82                call: 'linkwiz',
83                q: q === '.' ? '' : (q + ':')
84            }).done(function (html) {
85                const $root = jQuery('<div></div>').html(String(html || ''));
86                const set = new Set();
87                set.add('.');
88
89                $root.find('a[title]').each(function () {
90                    const titleVal = String(jQuery(this).attr('title') || '');
91                    if (!titleVal.endsWith(':')) return;
92                    const ns = normalizeNamespace(titleVal);
93                    if (ns) set.add(ns);
94                });
95
96                $nsList.empty();
97                Array.from(set).sort().forEach(function (ns) {
98                    const opt = document.createElement('option');
99                    opt.value = ns;
100                    opt.textContent = ns;
101                    $nsList.append(opt);
102                });
103                $nsList.show();
104            });
105        };
106
107        $pickerBtn.on('click', function () {
108            loadNamespaces();
109        });
110
111        $nsList.on('change dblclick', function () {
112            const ns = String($nsList.val() || '.');
113            $namespace.val(ns).trigger('focus');
114        });
115
116        $dialog.dialog({
117            modal: true,
118            width: 460,
119            close: function () {
120                jQuery(this).dialog('destroy').remove();
121            },
122            buttons: [
123                {
124                    text: insertLabel,
125                    click: function () {
126                        onSubmit({
127                            namespace: String($namespace.val() || '.').trim() || '.',
128                            filter: String($filter.val() || '').trim(),
129                            desc: $desc.is(':checked'),
130                            medias: $medias.is(':checked')
131                        });
132                        jQuery(this).dialog('close');
133                    }
134                },
135                {
136                    text: cancelLabel,
137                    click: function () {
138                        jQuery(this).dialog('close');
139                    }
140                }
141            ]
142        });
143    }
144
145    function addBtnActionVisualIndexPlugin($btn, props, edid) {
146        $btn.on('click', function (e) {
147            e.preventDefault();
148
149            const area = document.getElementById(edid);
150            if (!area) return;
151
152            const submit = function (values) {
153                insertAtSelection(area, buildVisualIndexSyntax(values));
154            };
155
156            if (typeof jQuery !== 'undefined' && jQuery.fn && typeof jQuery.fn.dialog === 'function') {
157                openVisualIndexDialog(submit);
158                return;
159            }
160
161            const ns = window.prompt('Namespace', '.') || '.';
162            submit({namespace: ns, filter: '', desc: false, medias: false});
163        });
164    }
165
166    if (shouldShowInEditorMenu()) {
167        toolbar[toolbar.length] = {
168            type: 'VisualIndexPlugin',
169            title: (window.LANG && LANG.plugins && LANG.plugins.visualindex && LANG.plugins.visualindex.toolbar_button) || 'Visualindex',
170            icon: '../../plugins/visualindex/images/folder.svg'
171        };
172    }
173}
174