xref: /dokuwiki/lib/scripts/qsearch.js (revision d91a4ef556635b5298c47df2856851f0694b2885)
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 */
9
10var dw_qsearch = {
11
12    $inObj: null,
13    $outObj: null,
14    timer: null,
15
16    /**
17     * initialize the quick search
18     *
19     * Attaches the event handlers
20     *
21     * @param input element (jQuery selector/DOM obj)
22     * @param output element (jQuery selector/DOM obj)
23     */
24    init: function (input, output) {
25        var do_qsearch;
26
27        dw_qsearch.$inObj  = jQuery(input);
28        dw_qsearch.$outObj = jQuery(output);
29
30        // objects found?
31        if (dw_qsearch.$inObj.length === 0 ||
32            dw_qsearch.$outObj.length === 0) {
33            return;
34        }
35
36        // attach eventhandler to search field
37        do_qsearch = function () {
38            var value = dw_qsearch.$inObj.val();
39            if (value === '') {
40                return;
41            }
42            jQuery.post(
43                DOKU_BASE + 'lib/exe/ajax.php',
44                {
45                    call: 'qsearch',
46                    q: encodeURI(value)
47                },
48                dw_qsearch.onCompletion,
49                'html'
50            );
51        };
52
53        dw_qsearch.$inObj.keyup(
54            function() {
55                if(dw_qsearch.timer){
56                    window.clearTimeout(dw_qsearch.timer);
57                    dw_qsearch.timer = null;
58                }
59                dw_qsearch.timer = window.setTimeout(do_qsearch, 500);
60            }
61        );
62
63        // attach eventhandler to output field
64        dw_qsearch.$outObj.click(dw_qsearch.clear_results);
65    },
66
67    /**
68     * Empty and hide the output div
69     */
70    clear_results: function(){
71        dw_qsearch.$outObj.hide();
72        dw_qsearch.$outObj.text('');
73    },
74
75    /**
76     * Callback. Reformat and display the results.
77     *
78     * Namespaces are shortened here to keep the results from overflowing
79     * or wrapping
80     *
81     * @param data The result HTML
82     */
83    onCompletion: function(data) {
84        var max, $links, too_big;
85
86        if (data === '') { return; }
87
88        dw_qsearch.$outObj
89            .html(data)
90            .show()
91            .css('white-space', 'nowrap');
92
93        // disable overflow during shortening
94        dw_qsearch.$outObj.find('li').css('overflow', 'visible');
95
96        $links = dw_qsearch.$outObj.find('a');
97        max    = dw_qsearch.$outObj[0].clientWidth; // maximum width allowed (but take away paddings below)
98        if(document.documentElement.dir === 'rtl'){
99            max -= parseInt(dw_qsearch.$outObj.css('padding-left'));
100            too_big = function (l) { return l.offsetLeft < 0; };
101        }else{
102            max -= parseInt(dw_qsearch.$outObj.css('padding-right'));
103            too_big = function (l) { return l.offsetWidth + l.offsetLeft > max; };
104        }
105
106        $links.each(function () {
107            var start, length, replace, nsL, nsR, eli, runaway;
108
109            if (!too_big(this)) {
110                return;
111            }
112
113            // make IE's innerText available to W3C conform browsers
114            if(this.textContent){
115                this.__defineGetter__('innerText', function(){ return this.textContent });
116                this.__defineSetter__('innerText', function(val){ this.textContent = val });
117            }
118
119            nsL = this.innerText.indexOf('(');
120            nsR = this.innerText.indexOf(')');
121            eli = 0;
122            runaway = 0;
123
124            while((nsR - nsL > 3) && too_big(this) && runaway++ < 500) {
125                if(eli !== 0){
126                    // elipsis already inserted
127                    if( (eli - nsL) > (nsR - eli) ){
128                        // cut left
129                        start = eli - 2;
130                        length = 2;
131                    }else{
132                        // cut right
133                        start = eli + 1;
134                        length = 1;
135                    }
136                    replace = '';
137                }else{
138                    // replace middle with ellipsis
139                    start = Math.floor( nsL + ((nsR-nsL)/2) );
140                    length = 1;
141                    replace = '…';
142                }
143                this.innerText = substr_replace(this.innerText,
144                                                replace, start, length);
145
146                eli = this.innerText.indexOf('…');
147                nsL = this.innerText.indexOf('(');
148                nsR = this.innerText.indexOf(')');
149            }
150        });
151
152        // reenable overflow
153        dw_qsearch.$outObj.find('li').css('overflow', 'hidden').css('text-overflow','ellipsis');
154    }
155};
156
157jQuery(function () {
158    dw_qsearch.init('#qsearch__in','#qsearch__out');
159});
160