1/*
2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26var noResult = {l: "No results found"};
27var category = "category";
28var catModules = "Modules";
29var catPackages = "Packages";
30var catTypes = "Types";
31var catMembers = "Members";
32var catSearchTags = "SearchTags";
33var highlight = "<span class=\"resultHighlight\">$&</span>";
34var camelCaseRegexp = "";
35var secondaryMatcher = "";
36function getName(name) {
37    var anchor = "";
38    var ch = '';
39    for (i = 0; i < name.length; i++) {
40        ch = name.charAt(i);
41        switch (ch) {
42            case '(':
43            case ')':
44            case '<':
45            case '>':
46            case ',':
47                anchor += "-";
48                break;
49            case ' ':
50            case '[':
51                break;
52            case ']':
53                anchor += ":A";
54                break;
55            case '$':
56                if (i == 0)
57                    anchor += "Z:Z";
58                anchor += ":D";
59                break;
60            case '_':
61                if (i == 0)
62                    anchor += "Z:Z";
63                anchor += ch;
64                break;
65            default:
66                anchor += ch;
67        }
68    }
69    return anchor;
70}
71function getHighlightedText(item) {
72    var ccMatcher = new RegExp(camelCaseRegexp);
73    var label = item.replace(ccMatcher, highlight);
74    if (label === item) {
75        label = item.replace(secondaryMatcher, highlight);
76    }
77    return label;
78}
79var watermark = 'Search';
80$(function() {
81    $("#search").prop("disabled", false);
82    $("#reset").prop("disabled", false);
83    $("#search").val(watermark).addClass('watermark');
84    $("#search").blur(function() {
85        if ($(this).val().length == 0) {
86            $(this).val(watermark).addClass('watermark');
87        }
88    });
89    $("#search").keydown(function() {
90        if ($(this).val() == watermark) {
91            $(this).val('').removeClass('watermark');
92        }
93    });
94    $("#reset").click(function() {
95        $("#search").val('');
96        $("#search").focus();
97    });
98    $("#search").focus();
99    $("#search")[0].setSelectionRange(0, 0);
100});
101$.widget("custom.catcomplete", $.ui.autocomplete, {
102    _create: function() {
103        this._super();
104        this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)");
105    },
106    _renderMenu: function(ul, items) {
107        var rMenu = this,
108                currentCategory = "";
109        $.each(items, function(index, item) {
110            var li;
111            if (item.l !== noResult.l && item.category !== currentCategory) {
112                ul.append("<li class=\"ui-autocomplete-category\">" + item.category + "</li>");
113                currentCategory = item.category;
114            }
115            li = rMenu._renderItemData(ul, item);
116            if (item.category) {
117                li.attr("aria-label", item.category + " : " + item.l);
118                li.attr("class", "resultItem");
119            } else {
120                li.attr("aria-label", item.l);
121                li.attr("class", "resultItem");
122            }
123        });
124    },
125    _renderItem: function(ul, item) {
126        var label = "";
127        if (item.category === catModules) {
128            label = getHighlightedText(item.l);
129        } else if (item.category === catPackages) {
130            label = (item.m)
131                    ? getHighlightedText(item.m + "/" + item.l)
132                    : getHighlightedText(item.l);
133        } else if (item.category === catTypes) {
134            label = getHighlightedText(item.p + "." + item.l);
135        } else if (item.category === catMembers) {
136            label = getHighlightedText(item.p + "." + (item.c + "." + item.l));
137        } else if (item.category === catSearchTags) {
138            label = getHighlightedText(item.l);
139        } else {
140            label = item.l;
141        }
142        $li = $("<li/>").appendTo(ul);
143        if (item.category === catSearchTags) {
144            if (item.d) {
145                $("<a/>").attr("href", "#")
146                        .html(label + "<span class=\"searchTagHolderResult\"> (" + item.h + ")</span><br><span class=\"searchTagDescResult\">"
147                                + item.d + "</span><br>")
148                        .appendTo($li);
149            } else {
150                $("<a/>").attr("href", "#")
151                        .html(label + "<span class=\"searchTagHolderResult\"> (" + item.h + ")</span>")
152                        .appendTo($li);
153            }
154        } else {
155            $("<a/>").attr("href", "#")
156                    .html(label)
157                    .appendTo($li);
158        }
159        return $li;
160    }
161});
162$(function() {
163    $("#search").catcomplete({
164        minLength: 1,
165        delay: 100,
166        source: function(request, response) {
167            var result = new Array();
168            var presult = new Array();
169            var tresult = new Array();
170            var mresult = new Array();
171            var tgresult = new Array();
172            var secondaryresult = new Array();
173            var displayCount = 0;
174            var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i");
175            camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)");
176            var camelCaseMatcher = new RegExp("^" + camelCaseRegexp);
177            secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
178
179            // Return the nested innermost name from the specified object
180            function nestedName(e) {
181                return e.l.substring(e.l.lastIndexOf(".") + 1);
182            }
183
184            // Sort array items by short name (as opposed to fully qualified name).
185            // Additionally, sort by the nested type name, when present,
186            // as opposed to top level short name.
187            function sortAndConcatResults(a1, a2) {
188                var sortingKey;
189                var sortArray = function(e1, e2) {
190                    var l = sortingKey(e1);
191                    var m = sortingKey(e2);
192                    if (l < m)
193                        return -1;
194                    if (l > m)
195                        return 1;
196                    return 0;
197                };
198                sortingKey = function(e) {
199                    return nestedName(e).toUpperCase();
200                };
201                a1.sort(sortArray);
202                a2.sort(sortArray);
203                a1 = a1.concat(a2);
204                a2.length = 0;
205                return a1;
206            }
207
208            if (moduleSearchIndex) {
209                var mdleCount = 0;
210                $.each(moduleSearchIndex, function(index, item) {
211                    item[category] = catModules;
212                    if (exactMatcher.test(item.l)) {
213                        result.unshift(item);
214                        mdleCount++;
215                    } else if (camelCaseMatcher.test(item.l)) {
216                        result.unshift(item);
217                    } else if (secondaryMatcher.test(item.l)) {
218                        secondaryresult.push(item);
219                    }
220                });
221                displayCount = mdleCount;
222                result = sortAndConcatResults(result, secondaryresult);
223            }
224            if (packageSearchIndex) {
225                var pCount = 0;
226                var pkg = "";
227                $.each(packageSearchIndex, function(index, item) {
228                    item[category] = catPackages;
229                    pkg = (item.m)
230                            ? (item.m + "/" + item.l)
231                            : item.l;
232                    if (exactMatcher.test(item.l)) {
233                        presult.unshift(item);
234                        pCount++;
235                    } else if (camelCaseMatcher.test(pkg)) {
236                        presult.unshift(item);
237                    } else if (secondaryMatcher.test(pkg)) {
238                        secondaryresult.push(item);
239                    }
240                });
241                result = result.concat(sortAndConcatResults(presult, secondaryresult));
242                displayCount = (pCount > displayCount) ? pCount : displayCount;
243            }
244            if (typeSearchIndex) {
245                var tCount = 0;
246                $.each(typeSearchIndex, function(index, item) {
247                    item[category] = catTypes;
248                    var s = nestedName(item);
249                    if (exactMatcher.test(s)) {
250                        tresult.unshift(item);
251                        tCount++;
252                    } else if (camelCaseMatcher.test(s)) {
253                        tresult.unshift(item);
254                    } else if (secondaryMatcher.test(item.p + "." + item.l)) {
255                        secondaryresult.push(item);
256                    }
257                });
258                result = result.concat(sortAndConcatResults(tresult, secondaryresult));
259                displayCount = (tCount > displayCount) ? tCount : displayCount;
260            }
261            if (memberSearchIndex) {
262                var mCount = 0;
263                $.each(memberSearchIndex, function(index, item) {
264                    item[category] = catMembers;
265                    var s = nestedName(item);
266                    if (exactMatcher.test(s)) {
267                        mresult.unshift(item);
268                        mCount++;
269                    } else if (camelCaseMatcher.test(s)) {
270                        mresult.unshift(item);
271                    } else if (secondaryMatcher.test(item.c + "." + item.l)) {
272                        secondaryresult.push(item);
273                    }
274                });
275                result = result.concat(sortAndConcatResults(mresult, secondaryresult));
276                displayCount = (mCount > displayCount) ? mCount : displayCount;
277            }
278            if (tagSearchIndex) {
279                var tgCount = 0;
280                $.each(tagSearchIndex, function(index, item) {
281                    item[category] = catSearchTags;
282                    if (exactMatcher.test(item.l)) {
283                        tgresult.unshift(item);
284                        tgCount++;
285                    } else if (secondaryMatcher.test(item.l)) {
286                        secondaryresult.push(item);
287                    }
288                });
289                result = result.concat(sortAndConcatResults(tgresult, secondaryresult));
290                displayCount = (tgCount > displayCount) ? tgCount : displayCount;
291            }
292            displayCount = (displayCount > 500) ? displayCount : 500;
293            var counter = function() {
294                var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0};
295                var f = function(item) {
296                    count[item.category] += 1;
297                    return (count[item.category] <= displayCount);
298                };
299                return f;
300            }();
301            response(result.filter(counter));
302        },
303        response: function(event, ui) {
304            if (!ui.content.length) {
305                ui.content.push(noResult);
306            } else {
307                $("#search").empty();
308            }
309        },
310        autoFocus: true,
311        position: {
312            collision: "flip"
313        },
314        select: function(event, ui) {
315            if (ui.item.l !== noResult.l) {
316                var url = "";
317                if (ui.item.category === catModules) {
318                    url = ui.item.l + "-summary.html";
319                } else if (ui.item.category === catPackages) {
320                    url = ui.item.l.replace(/\./g, '/') + "/package-summary.html";
321                } else if (ui.item.category === catTypes) {
322                    if (ui.item.p === "<Unnamed>") {
323                        url = ui.item.l + ".html";
324                    } else {
325                        url = ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html";
326                    }
327                } else if (ui.item.category === catMembers) {
328                    if (ui.item.p === "<Unnamed>") {
329                        url = ui.item.c + ".html" + "#";
330                    } else {
331                        url = ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#";
332                    }
333                    if (ui.item.url) {
334                        url += ui.item.url;
335                    } else {
336                        url += getName(ui.item.l);
337                    }
338                } else if (ui.item.category === catSearchTags) {
339                    url += ui.item.u;
340                }
341                if (top !== window) {
342                    parent.classFrame.location = pathtoroot + url;
343                } else {
344                    window.location.href = pathtoroot + url;
345                }
346            }
347        }
348    });
349});
350