root/veekun/trunk/root/script/dexsuggest.js @ 445

Revision 445, 7.2 KB (checked in by eevee, 18 months ago)

Fixed dexsuggest boxes that are supposed to only show moves. (#320)

Line 
1var dexsuggest_oldvalue = "";
2var dexsuggest_host_el  = null;
3var dexsuggest_request  = null;
4
5// set a teensy delay on the ajax request so we don't interrupt typing
6var dexsuggest_timeout  = null;
7function dexsuggest_change_wrapper(evt) {
8    if (dexsuggest_timeout)
9        window.clearTimeout(dexsuggest_timeout);
10
11    window.setTimeout(dexsuggest_change, 100, evt);
12}
13
14// handle keypresses
15function dexsuggest_change(evt) {
16    dexsuggest_timeout = null;
17
18    if (evt.keyCode == 9 || evt.keyCode == 13) return;
19
20    var suggestbox = document.getElementById("dexsuggest");
21    var el = evt.target;
22    var suggestvalue = el.value;
23   
24    if (suggestvalue == dexsuggest_oldvalue) return;
25    dexsuggest_oldvalue = suggestvalue;
26   
27    if (!suggestvalue && suggestbox) {
28        suggestbox.style.visibility == "hidden";
29        return;
30    }
31
32    if (dexsuggest_request)
33        dexsuggest_request.abort();
34
35    var url = "/dex/suggest?extended=1;search=" + suggestvalue;
36    var type;
37    if ($(dexsuggest_host_el).is(".js-dexsuggest-pokemon"))
38        type = "pokemon";
39    else if ($(dexsuggest_host_el).is(".js-dexsuggest-move"))
40        type = "move";
41
42    if (type)
43        url += ";type=" + type;
44
45    dexsuggest_request = $.ajax({
46        type: "GET",
47        url: url,
48        dataType: "json",
49        error: function() {
50            dexsuggest_request = null;
51        },
52        success: function(res) {
53            dexsuggest_request = null;
54            if (res[0] != el.value) return;
55
56            while (suggestbox.firstChild)
57                suggestbox.removeChild(suggestbox.firstChild);
58            suggestbox.scrollTop = 0;
59
60            var opt;
61            var len = suggestvalue.length;
62            for (var i = 0; i < res[1].length; i++) {
63                opt = document.createElement('li');
64                var typed_part = document.createElement('span');
65                typed_part.className = 'typed';
66                typed_part.appendChild(
67                    document.createTextNode( res[1][i].label.substr(0, len) )
68                );
69                opt.appendChild(typed_part);
70
71                var untyped_part = res[1][i].label.substr(len);
72                opt.appendChild( document.createTextNode(untyped_part) );
73
74                if (res[1][i].image) {
75                    opt.style.backgroundImage = "url(" + res[1][i].image + ")";
76
77                    if (res[1][i].bottom_align)  // special hack for Pokemon
78                        opt.style.backgroundPosition = "0.33em bottom";
79                    // XXX: any way to just override the vertical position?
80                    else if (res[1][i].left_4px)  // special hack for items
81                        opt.style.backgroundPosition = "0.66em center";
82                    // XXX: THIS IS AWFUL, need better solution STAT
83                }
84
85                $(opt).click(dexsuggest_update_host);
86
87                suggestbox.appendChild(opt);
88            }
89
90            if (res[1].length) {
91                suggestbox.style.visibility = "visible";
92            } else {
93                suggestbox.style.visibility = "hidden";
94            }
95           
96            dexsuggest_resize();
97        }
98    });
99}
100
101function dexsuggest_update_host(evt) {
102    $(dexsuggest_host_el).val(evt.currentTarget.textContent);
103}
104
105function dexsuggest_press(evt) {
106    var suggestbox = document.getElementById('dexsuggest');
107    if (!suggestbox) return;
108
109    var el = evt.target;
110    var suggestvalue = el.value;
111   
112    var old_host_el = dexsuggest_host_el;
113    dexsuggest_host_el = el;
114    if (el != old_host_el) {
115        dexsuggest_resize();
116    }
117
118    if (!evt.charCode) {  // no character generated
119        if (evt.keyCode == 27) {  // esc
120            dexsuggest_hide();
121
122        // These two cases are used for moving the selection highlight up and
123        // down the fake listbox.
124        } else if (evt.keyCode == 38) {  // up
125            if (suggestbox.style.visibility == "hidden")
126                return;
127
128            var selected = $('#dexsuggest > .selected').get(0);
129            var prev;
130            if (selected) {
131                prev = selected.previousSibling;
132            } else {
133                prev = $('#dexsuggest > li:last-child').get(0);
134            }
135            if (prev) {
136                prev.className = 'selected';
137                if (selected)
138                    selected.className = undefined;
139
140                dexsuggest_scrollto(prev);
141                evt.preventDefault();
142            }
143        } else if (evt.keyCode == 40) {  // down
144            if (suggestbox.style.visibility == "hidden")
145                suggestbox.style.visibility = "visible";
146
147            var selected = $('#dexsuggest > .selected').get(0);
148            var next;
149            if (selected) {
150                next = selected.nextSibling;
151            } else {
152                next = $('#dexsuggest > li').get(0);
153            }
154            if (next) {
155                next.className = 'selected';
156                if (selected)
157                    selected.className = undefined;
158
159                dexsuggest_scrollto(next);
160                evt.preventDefault();
161            }
162
163        // Select the highlighted entry if there be one, otherwise submit
164        } else if (evt.keyCode == 13) {  // enter
165            // no suggestbox -> normal submit
166            if (suggestbox.style.visibility == "hidden")
167                return;
168
169            var selected = $('#dexsuggest > .selected').get(0);
170
171            // nothing selected
172            if (!selected)
173                return;
174
175            // otherwise, copy selection to target box...
176            $(evt.target).val( selected.textContent );
177
178            // ...and kill submit
179            evt.preventDefault();
180
181            dexsuggest_hide();
182        }
183    }
184}
185
186function dexsuggest_scrollto(el) {
187    var min_bottom = el.offsetTop + el.offsetHeight;
188    if (el.parentNode.scrollTop < min_bottom - el.parentNode.offsetHeight)
189        el.parentNode.scrollTop = min_bottom - el.parentNode.offsetHeight;
190
191    var max_top = el.offsetTop;
192    if (el.parentNode.scrollTop > max_top)
193        el.parentNode.scrollTop = max_top;
194}
195
196function dexsuggest_resize() {
197    var el = document.getElementById('dexsuggest');
198    if (!el) return;
199    if (!dexsuggest_host_el) return;
200
201    var top_el  = dexsuggest_host_el;
202    var left_el = dexsuggest_host_el;
203   
204    var offset_top = top_el ? top_el.offsetHeight : 0;
205    while (top_el) {
206        offset_top += top_el.offsetTop;
207        top_el = top_el.offsetParent;
208    }
209
210    var offset_left = 0;
211    while (left_el) {
212        offset_left += left_el.offsetLeft;
213        left_el = left_el.offsetParent;
214    }
215
216    el.style.top   = offset_top  + "px";
217    el.style.left  = offset_left + "px";
218    el.style.width = dexsuggest_host_el.offsetWidth + "px";
219}
220
221function dexsuggest_hide() {
222    $('#dexsuggest').css('visibility', 'hidden');
223}
224
225$(document).ready(function(evt) {
226    var suggestbox = document.createElement('ul');
227    suggestbox.id = "dexsuggest";
228    suggestbox.style.visibility = "hidden";
229    document.body.appendChild(suggestbox);
230   
231    $(".js-dexsuggest")
232        .attr("autocomplete", "off")
233        .keyup(dexsuggest_change_wrapper)
234        .keypress(dexsuggest_press)
235        .blur(function(){ window.setTimeout(dexsuggest_hide, 100) });
236    $(document).resize(dexsuggest_resize);
237
238    dexsuggest_resize();
239});
Note: See TracBrowser for help on using the browser.