xref: /plugin/tagging/script/search.js (revision a7b8524b96cced091b8c443f9f8af39caf48f2f4)
1jQuery(function () {
2    /**
3     * Add tag search parameter to all links in the advanced search tools
4     *
5     * This duplicates the solution from the watchcycle plugin, and should also be replaced
6     * with a DokuWiki event, which does not exist yet, but should handle extending search tools.
7     */
8    const $advancedOptions = jQuery('.search-results-form .advancedOptions');
9    if (!$advancedOptions.length) {
10        return;
11    }
12
13    /**
14     * Extracts the value of a given parameter from the URL querystring
15     *
16     * taken via watchcycle from https://stackoverflow.com/a/31412050/3293343
17     * @param param
18     * @returns {*}
19     */
20    function getQueryParam(param) {
21        location.search.substr(1)
22            .split("&")
23            .some(function(item) { // returns first occurence and stops
24                return item.split("=")[0] === param && (param = item.split("=")[1])
25            });
26        return param
27    }
28
29    if (getQueryParam('tagging-logic') === 'and') {
30        $advancedOptions.find('a').each(function (index, element) {
31            const $link = jQuery(element);
32            // do not override parameters in our own links
33            if ($link.attr('href').indexOf('tagging-logic') === -1) {
34                $link.attr('href', $link.attr('href') + '&tagging-logic=and');
35            }
36        });
37    }
38
39
40    /* **************************************************************************
41     * Search filter
42     * ************************************************************************ */
43
44    const $filterContainer = jQuery('#plugin__tagging-tags');
45    const $resultLinks = jQuery('div.search_fullpage_result dt a:not([class])');
46
47    /**
48     * Returns the filter ul
49     *
50     * @param tags
51     * @param [filters]
52     * @returns {jQuery}
53     */
54    function buildFilter(tags, filters) {
55        const lis = [];
56        i = 0;
57
58        // when tag search has no results, build the filter dropdown anyway but from tags in query
59        if (Object.keys(tags).length === 0 && filters.length > 0) {
60            for (const key of filters) {
61                tags[key] = 0;
62            }
63        }
64
65        for (const tag in tags) {
66            let checked = filters.includes(tag) ? 'checked="checked"' : '';
67
68            lis.push(` <li>
69                <input name="tagging[]" type="checkbox" value="${tag}" id="__tagging-${i}" ${checked}>
70                <label for="__tagging-${i}" title="${tag}">
71                    ${tag} (${tags[tag]})
72                </label>
73            </li>`);
74            i++;
75        }
76
77        $filterContainer.find('div.current').addClass('changed');
78
79        return jQuery('<ul aria-expanded="false">' + lis.join('') + '</ul>');
80    }
81
82    /**
83     * Collects the available tags from results list
84     *
85     * @returns {[]}
86     */
87    function getTagsFromResults() {
88        const tags = [];
89        $resultLinks.toArray().forEach(function(link) {
90            const text = jQuery(link).text();
91            if (text.charAt(0) === '#') {
92                const tag = text.replace('#', '');
93                tags.push(tag);
94            }
95        });
96
97        return tags.sort().reduce(function (allTags, tag) {
98            if (tag in allTags) {
99                allTags[tag]++;
100            }
101            else {
102                allTags[tag] = 1;
103            }
104            return allTags;
105        }, {});
106    }
107
108    /**
109     * @returns {*}
110     */
111    function getFiltersFromQuery() {
112        $q = jQuery('#dokuwiki__content input[name="q"]');
113
114        const terms = $q.val().split(' ');
115        let filters = terms.filter(function (term) {
116            return term.charAt(0) === '#';
117        });
118
119        return filters.map(function (tag) {
120            return tag.replace('#', '');
121        });
122    }
123
124    $ul = buildFilter(getTagsFromResults(), getFiltersFromQuery());
125    $filterContainer.append($ul);
126
127});
128