1/**
2 * Attaches the mechanics on our plugin's button
3 *
4 * @param {jQuery} $btn the button itself
5 * @param {object} props unused
6 * @param {string} edid the editor's ID
7 * @return {string}
8 */
9function addBtnActionPlugin_watchcycle($btn, props, edid) {
10    'use strict';
11
12    const pickerid = 'picker' + window.pickercounter;
13    const $picker = jQuery(createPicker(pickerid, [], edid))
14        .attr('aria-hidden', 'true')
15        .addClass('plugin-watchcycle')
16    ;
17    window.pickercounter += 1;
18    const l10n = LANG.plugins.watchcycle;
19
20    /**
21     * AJAX request for users and groups
22     * Adapted from Struct plugin
23     *
24     * @param {function} fn Callback on success
25     * @param {string} id Call identifier
26     * @param {string} param Pass the parameter to backend
27     */
28    const ajax_watchcycle = function(fn, id, param) {
29        let data = {};
30
31        data['call'] = 'plugin_watchcycle_' + id;
32        data['param'] = param;
33
34        jQuery.post(DOKU_BASE + 'lib/exe/ajax.php', data, fn, 'json')
35            .fail(function (result) {
36                if (result.responseJSON) {
37                    if (result.responseJSON.stacktrace) {
38                        console.error(result.responseJSON.error + "\n" + result.responseJSON.stacktrace);
39                    }
40                    alert(result.responseJSON.error);
41                }
42            });
43    };
44
45    /**
46     * Autocomplete split helper
47     * @param {string} val
48     * @returns {string}
49     */
50    const autcmpl_split = function(val) {
51        return val.split(/,\s*/);
52    };
53
54    /**
55     * Autocomplete helper returns last part of comma separated string
56     * @param {string} term
57     * @returns {string}
58     */
59    const autcmpl_extractLast = function(term) {
60        return autcmpl_split(term).pop();
61    };
62
63    const $watchCycleForm = jQuery('<form>');
64    const usernameHTML =
65        '<div>' +
66        '<label for="plugin__watchcycle_user_input">' + l10n.label_username + '</label>' +
67        '<input id="plugin__watchcycle_user_input" name="watchcycle_user" type="text" required/>' +
68        '</div>';
69    $watchCycleForm.append(jQuery(usernameHTML));
70    const cycleHTML =
71        '<div>' +
72        '<label for="plugin__watchcycle_cycle_input">' + l10n.label_cycle_length + '</label>' +
73        '<input id="plugin__watchcycle_cycle_input" name="watchcycle_cycle" type="number" required min="1"/>' +
74        '</div>';
75
76    $watchCycleForm.append(cycleHTML);
77    $watchCycleForm.append(jQuery('<button type="submit">' + l10n.button_insert + '</button>'));
78    const $cancelButton = jQuery('<button type="button">' + l10n.button_cancel + '</button>');
79    $cancelButton.on('click', function () {
80        $watchCycleForm.get(0).reset();
81        pickerClose();
82    });
83    $watchCycleForm.append($cancelButton);
84
85    // multi-value autocompletion
86    $watchCycleForm.find('input#plugin__watchcycle_user_input').autocomplete({
87        source: function (request, cb) {
88            ajax_watchcycle(cb, 'get', autcmpl_extractLast(request.term));
89        },
90        focus: function() {
91            // prevent value inserted on focus
92            return false;
93        },
94        select: function(event, ui) {
95            const terms = autcmpl_split(this.value);
96            // remove the current input
97            terms.pop();
98            // add the selected item
99            terms.push(ui.item.value);
100            // add placeholder to get the comma-and-space at the end
101            terms.push("");
102            this.value = terms.join(", ");
103            return false;
104        }
105    });
106
107    $watchCycleForm.on('submit', function (event) {
108        event.preventDefault();
109        $picker.find(".error").remove();
110        const maintainers = $picker.find('[name="watchcycle_user"]').val().replace(new RegExp("[, ]+?$"), "");
111
112
113        const cycle = $picker.find('[name="watchcycle_cycle"]').val();
114
115        // validate maintainers
116        ajax_watchcycle(function (result) {
117            if (result === true) {
118                pickerInsert('~~WATCHCYCLE:' + maintainers + ':' + cycle + '~~', edid);
119                $watchCycleForm.get(0).reset();
120            } else {
121                $picker.find("form").append('<div class="error">' + l10n.invalid_maintainers + '</div>');
122            }
123        }, 'validate', maintainers);
124
125    });
126
127    $picker.append($watchCycleForm).append($watchCycleForm);
128
129    // when the toolbar button is clicked
130    $btn.on('click', function (event) {
131        // open/close the picker
132        pickerToggle(pickerid, $btn);
133        event.preventDefault();
134    });
135}
136
137/**
138 * Add watchcycle_only parameter to search tool links if it is in the search query
139 *
140 * This should ideally be done in the backend, but this is currently (Greebo) not possible. Future DokuWiki release
141 * might include "unknown" search parameter, e.g. those from plugins like this one, by default. Then this can be
142 * removed.
143 */
144jQuery(function () {
145    const $advancedOptions = jQuery('.search-results-form .advancedOptions');
146    if (!$advancedOptions.length) {
147        return;
148    }
149
150    /**\
151     * taken from https://stackoverflow.com/a/31412050/3293343
152     * @param param
153     * @return {*}
154     */
155    function getQueryParam(param) {
156        location.search.substr(1)
157            .split("&")
158            .some(function(item) { // returns first occurence and stops
159                return item.split("=")[0] === param && (param = item.split("=")[1])
160            });
161        return param
162    }
163
164    if (getQueryParam('watchcycle_only') === '1') {
165        $advancedOptions.find('a').each(function (index, element) {
166            const $link = jQuery(element);
167            $link.attr('href', $link.attr('href') + '&watchcycle_only=1');
168        });
169    }
170});
171