1/**
2 * AJAX functions for the pagename quicksearch
3 *
4 * @license  GPL2 (http://www.gnu.org/licenses/gpl.html)
5 * @author   Andreas Gohr <andi@splitbrain.org>
6 * @author   Adrian Lang <lang@cosmocode.de>
7 * @author   Michal Rezler <m.rezler@centrum.cz>
8 */
9jQuery.fn.dw_qsearch = function (overrides) {
10
11    var dw_qsearch = {
12
13        output: '#qsearch__out',
14
15        $inObj: this,
16        $outObj: null,
17        timer: null,
18        curRequest: null,
19
20        /**
21         * initialize the quick search
22         *
23         * Attaches the event handlers
24         *
25         */
26        init: function () {
27            var do_qsearch;
28
29            dw_qsearch.$outObj = jQuery(dw_qsearch.output);
30
31            // objects found?
32            if (dw_qsearch.$inObj.length === 0 ||
33                dw_qsearch.$outObj.length === 0) {
34                return;
35            }
36
37            // attach eventhandler to search field
38            do_qsearch = function () {
39                // abort any previous request
40                if (dw_qsearch.curRequest != null) {
41                    dw_qsearch.curRequest.abort();
42                }
43                var value = dw_qsearch.getSearchterm();
44                if (value === '') {
45                    dw_qsearch.clear_results();
46                    return;
47                }
48                dw_qsearch.$inObj.parents('form').addClass('searching');
49                dw_qsearch.curRequest = jQuery.post(
50                    DOKU_BASE + 'lib/exe/ajax.php',
51                    {
52                        call: 'qsearch',
53                        q: encodeURI(value)
54                    },
55                    dw_qsearch.onCompletion,
56                    'html'
57                );
58            };
59
60            dw_qsearch.$inObj.on('keyup',
61                function () {
62                    if (dw_qsearch.timer) {
63                        window.clearTimeout(dw_qsearch.timer);
64                        dw_qsearch.timer = null;
65                    }
66                    dw_qsearch.timer = window.setTimeout(do_qsearch, 500);
67                }
68            );
69
70            // attach eventhandler to output field
71            dw_qsearch.$outObj.on('click', dw_qsearch.clear_results);
72        },
73
74        /**
75         * Read search term from input
76         */
77        getSearchterm: function() {
78            return dw_qsearch.$inObj.val();
79        },
80
81        /**
82         * Empty and hide the output div
83         */
84        clear_results: function () {
85            dw_qsearch.$inObj.parents('form').removeClass('searching');
86            dw_qsearch.$outObj.hide();
87            dw_qsearch.$outObj.text('');
88        },
89
90        /**
91         * Callback. Reformat and display the results.
92         *
93         * Namespaces are shortened here to keep the results from overflowing
94         * or wrapping
95         *
96         * @param data The result HTML
97         */
98        onCompletion: function (data) {
99            var max, $links, too_big;
100            dw_qsearch.$inObj.parents('form').removeClass('searching');
101
102            dw_qsearch.curRequest = null;
103
104            if (data === '') {
105                dw_qsearch.clear_results();
106                return;
107            }
108
109            dw_qsearch.$outObj
110                .html(data)
111                .show()
112                .css('white-space', 'nowrap');
113
114            // disable overflow during shortening
115            dw_qsearch.$outObj.find('li').css('overflow', 'visible');
116
117            $links = dw_qsearch.$outObj.find('a');
118            max = dw_qsearch.$outObj[0].clientWidth; // maximum width allowed (but take away paddings below)
119            if (document.documentElement.dir === 'rtl') {
120                max -= parseInt(dw_qsearch.$outObj.css('padding-left'));
121                too_big = function (l) {
122                    return l.offsetLeft < 0;
123                };
124            } else {
125                max -= parseInt(dw_qsearch.$outObj.css('padding-right'));
126                too_big = function (l) {
127                    return l.offsetWidth + l.offsetLeft > max;
128                };
129            }
130
131            $links.each(function () {
132                var start, length, replace, nsL, nsR, eli, runaway;
133
134                if (!too_big(this)) {
135                    return;
136                }
137
138                nsL = this.textContent.indexOf('(');
139                nsR = this.textContent.indexOf(')');
140                eli = 0;
141                runaway = 0;
142
143                while ((nsR - nsL > 3) && too_big(this) && runaway++ < 500) {
144                    if (eli !== 0) {
145                        // elipsis already inserted
146                        if ((eli - nsL) > (nsR - eli)) {
147                            // cut left
148                            start = eli - 2;
149                            length = 2;
150                        } else {
151                            // cut right
152                            start = eli + 1;
153                            length = 1;
154                        }
155                        replace = '';
156                    } else {
157                        // replace middle with ellipsis
158                        start = Math.floor(nsL + ((nsR - nsL) / 2));
159                        length = 1;
160                        replace = '…';
161                    }
162                    this.textContent = substr_replace(this.textContent,
163                        replace, start, length);
164
165                    eli = this.textContent.indexOf('…');
166                    nsL = this.textContent.indexOf('(');
167                    nsR = this.textContent.indexOf(')');
168                }
169            });
170
171            // reenable overflow
172            dw_qsearch.$outObj.find('li').css('overflow', 'hidden').css('text-overflow', 'ellipsis');
173        }
174
175
176    };
177
178    jQuery.extend(dw_qsearch, overrides);
179
180    if (!overrides.deferInit) {
181        dw_qsearch.init();
182    }
183
184    return dw_qsearch;
185};
186
187jQuery(function () {
188    jQuery('#qsearch__in').dw_qsearch({
189        output: '#qsearch__out'
190    });
191});
192