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").val('');
82    $("#search").prop("disabled", false);
83    $("#reset").prop("disabled", false);
84    $("#search").val(watermark).addClass('watermark');
85    $("#search").blur(function() {
86        if ($(this).val().length == 0) {
87            $(this).val(watermark).addClass('watermark');
88        }
89    });
90    $("#search").on('click keydown', function() {
91        if ($(this).val() == watermark) {
92            $(this).val('').removeClass('watermark');
93        }
94    });
95    $("#reset").click(function() {
96        $("#search").val('');
97        $("#search").focus();
98    });
99    $("#search").focus();
100    $("#search")[0].setSelectionRange(0, 0);
101});
102$.widget("custom.catcomplete", $.ui.autocomplete, {
103    _create: function() {
104        this._super();
105        this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)");
106    },
107    _renderMenu: function(ul, items) {
108        var rMenu = this,
109                currentCategory = "";
110        $.each(items, function(index, item) {
111            var li;
112            if (item.l !== noResult.l && item.category !== currentCategory) {
113                ul.append("<li class=\"ui-autocomplete-category\">" + item.category + "</li>");
114                currentCategory = item.category;
115            }
116            li = rMenu._renderItemData(ul, item);
117            if (item.category) {
118                li.attr("aria-label", item.category + " : " + item.l);
119                li.attr("class", "resultItem");
120            } else {
121                li.attr("aria-label", item.l);
122                li.attr("class", "resultItem");
123            }
124        });
125    },
126    _renderItem: function(ul, item) {
127        var label = "";
128        if (item.category === catModules) {
129            label = getHighlightedText(item.l);
130        } else if (item.category === catPackages) {
131            label = (item.m)
132                    ? getHighlightedText(item.m + "/" + item.l)
133                    : getHighlightedText(item.l);
134        } else if (item.category === catTypes) {
135            label = getHighlightedText(item.p + "." + item.l);
136        } else if (item.category === catMembers) {
137            label = getHighlightedText(item.p + "." + (item.c + "." + item.l));
138        } else if (item.category === catSearchTags) {
139            label = getHighlightedText(item.l);
140        } else {
141            label = item.l;
142        }
143        $li = $("<li/>").appendTo(ul);
144        if (item.category === catSearchTags) {
145            if (item.d) {
146                $("<a/>").attr("href", "#")
147                        .html(label + "<span class=\"searchTagHolderResult\"> (" + item.h + ")</span><br><span class=\"searchTagDescResult\">"
148                                + item.d + "</span><br>")
149                        .appendTo($li);
150            } else {
151                $("<a/>").attr("href", "#")
152                        .html(label + "<span class=\"searchTagHolderResult\"> (" + item.h + ")</span>")
153                        .appendTo($li);
154            }
155        } else {
156            $("<a/>").attr("href", "#")
157                    .html(label)
158                    .appendTo($li);
159        }
160        return $li;
161    }
162});
163$(function() {
164    $("#search").catcomplete({
165        minLength: 1,
166        delay: 100,
167        source: function(request, response) {
168            var result = new Array();
169            var presult = new Array();
170            var tresult = new Array();
171            var mresult = new Array();
172            var tgresult = new Array();
173            var secondaryresult = new Array();
174            var displayCount = 0;
175            var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i");
176            camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)");
177            var camelCaseMatcher = new RegExp("^" + camelCaseRegexp);
178            secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
179
180            // Return the nested innermost name from the specified object
181            function nestedName(e) {
182                return e.l.substring(e.l.lastIndexOf(".") + 1);
183            }
184
185            // Sort array items by short name (as opposed to fully qualified name).
186            // Additionally, sort by the nested type name, when present,
187            // as opposed to top level short name.
188            function sortAndConcatResults(a1, a2) {
189                var sortingKey;
190                var sortArray = function(e1, e2) {
191                    var l = sortingKey(e1);
192                    var m = sortingKey(e2);
193                    if (l < m)
194                        return -1;
195                    if (l > m)
196                        return 1;
197                    return 0;
198                };
199                sortingKey = function(e) {
200                    return nestedName(e).toUpperCase();
201                };
202                a1.sort(sortArray);
203                a2.sort(sortArray);
204                a1 = a1.concat(a2);
205                a2.length = 0;
206                return a1;
207            }
208
209            if (moduleSearchIndex) {
210                var mdleCount = 0;
211                $.each(moduleSearchIndex, function(index, item) {
212                    item[category] = catModules;
213                    if (exactMatcher.test(item.l)) {
214                        result.unshift(item);
215                        mdleCount++;
216                    } else if (camelCaseMatcher.test(item.l)) {
217                        result.unshift(item);
218                    } else if (secondaryMatcher.test(item.l)) {
219                        secondaryresult.push(item);
220                    }
221                });
222                displayCount = mdleCount;
223                result = sortAndConcatResults(result, secondaryresult);
224            }
225            if (packageSearchIndex) {
226                var pCount = 0;
227                var pkg = "";
228                $.each(packageSearchIndex, function(index, item) {
229                    item[category] = catPackages;
230                    pkg = (item.m)
231                            ? (item.m + "/" + item.l)
232                            : item.l;
233                    if (exactMatcher.test(item.l)) {
234                        presult.unshift(item);
235                        pCount++;
236                    } else if (camelCaseMatcher.test(pkg)) {
237                        presult.unshift(item);
238                    } else if (secondaryMatcher.test(pkg)) {
239                        secondaryresult.push(item);
240                    }
241                });
242                result = result.concat(sortAndConcatResults(presult, secondaryresult));
243                displayCount = (pCount > displayCount) ? pCount : displayCount;
244            }
245            if (typeSearchIndex) {
246                var tCount = 0;
247                $.each(typeSearchIndex, function(index, item) {
248                    item[category] = catTypes;
249                    var s = nestedName(item);
250                    if (exactMatcher.test(s)) {
251                        tresult.unshift(item);
252                        tCount++;
253                    } else if (camelCaseMatcher.test(s)) {
254                        tresult.unshift(item);
255                    } else if (secondaryMatcher.test(item.p + "." + item.l)) {
256                        secondaryresult.push(item);
257                    }
258                });
259                result = result.concat(sortAndConcatResults(tresult, secondaryresult));
260                displayCount = (tCount > displayCount) ? tCount : displayCount;
261            }
262            if (memberSearchIndex) {
263                var mCount = 0;
264                $.each(memberSearchIndex, function(index, item) {
265                    item[category] = catMembers;
266                    var s = nestedName(item);
267                    if (exactMatcher.test(s)) {
268                        mresult.unshift(item);
269                        mCount++;
270                    } else if (camelCaseMatcher.test(s)) {
271                        mresult.unshift(item);
272                    } else if (secondaryMatcher.test(item.c + "." + item.l)) {
273                        secondaryresult.push(item);
274                    }
275                });
276                result = result.concat(sortAndConcatResults(mresult, secondaryresult));
277                displayCount = (mCount > displayCount) ? mCount : displayCount;
278            }
279            if (tagSearchIndex) {
280                var tgCount = 0;
281                $.each(tagSearchIndex, function(index, item) {
282                    item[category] = catSearchTags;
283                    if (exactMatcher.test(item.l)) {
284                        tgresult.unshift(item);
285                        tgCount++;
286                    } else if (secondaryMatcher.test(item.l)) {
287                        secondaryresult.push(item);
288                    }
289                });
290                result = result.concat(sortAndConcatResults(tgresult, secondaryresult));
291                displayCount = (tgCount > displayCount) ? tgCount : displayCount;
292            }
293            displayCount = (displayCount > 500) ? displayCount : 500;
294            var counter = function() {
295                var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0};
296                var f = function(item) {
297                    count[item.category] += 1;
298                    return (count[item.category] <= displayCount);
299                };
300                return f;
301            }();
302            response(result.filter(counter));
303        },
304        response: function(event, ui) {
305            if (!ui.content.length) {
306                ui.content.push(noResult);
307            } else {
308                $("#search").empty();
309            }
310        },
311        autoFocus: true,
312        position: {
313            collision: "flip"
314        },
315        select: function(event, ui) {
316            if (ui.item.l !== noResult.l) {
317                var url = "";
318                if (ui.item.category === catModules) {
319                    url = ui.item.l + "-summary.html";
320                } else if (ui.item.category === catPackages) {
321                    url = ui.item.l.replace(/\./g, '/') + "/package-summary.html";
322                } else if (ui.item.category === catTypes) {
323                    if (ui.item.p === "<Unnamed>") {
324                        url = ui.item.l + ".html";
325                    } else {
326                        url = ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html";
327                    }
328                } else if (ui.item.category === catMembers) {
329                    if (ui.item.p === "<Unnamed>") {
330                        url = ui.item.c + ".html" + "#";
331                    } else {
332                        url = ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#";
333                    }
334                    if (ui.item.url) {
335                        url += ui.item.url;
336                    } else {
337                        url += getName(ui.item.l);
338                    }
339                } else if (ui.item.category === catSearchTags) {
340                    url += ui.item.u;
341                }
342                if (top !== window) {
343                    parent.classFrame.location = pathtoroot + url;
344                } else {
345                    window.location.href = pathtoroot + url;
346                }
347            }
348        }
349    });
350});
351