• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2010 Nikita Vasilyev. All rights reserved.
3 * Copyright (C) 2010 Joseph Pecoraro. All rights reserved.
4 * Copyright (C) 2010 Google Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *     * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *     * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 *     * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33WebInspector.CSSCompletions = function(values, acceptEmptyPrefix)
34{
35    this._values = values.slice();
36    this._values.sort();
37    this._acceptEmptyPrefix = acceptEmptyPrefix;
38}
39
40WebInspector.CSSCompletions.prototype = {
41    startsWith: function(prefix)
42    {
43        var firstIndex = this._firstIndexOfPrefix(prefix);
44        if (firstIndex === -1)
45            return [];
46
47        var results = [];
48        while (firstIndex < this._values.length && this._values[firstIndex].indexOf(prefix) === 0)
49            results.push(this._values[firstIndex++]);
50        return results;
51    },
52
53    firstStartsWith: function(prefix)
54    {
55        var foundIndex = this._firstIndexOfPrefix(prefix);
56        return (foundIndex === -1 ? "" : this._values[foundIndex]);
57    },
58
59    _firstIndexOfPrefix: function(prefix)
60    {
61        if (!this._values.length)
62            return -1;
63        if (!prefix)
64            return this._acceptEmptyPrefix ? 0 : -1;
65
66        var maxIndex = this._values.length - 1;
67        var minIndex = 0;
68        var foundIndex;
69
70        do {
71            var middleIndex = (maxIndex + minIndex) >> 1;
72            if (this._values[middleIndex].indexOf(prefix) === 0) {
73                foundIndex = middleIndex;
74                break;
75            }
76            if (this._values[middleIndex] < prefix)
77                minIndex = middleIndex + 1;
78            else
79                maxIndex = middleIndex - 1;
80        } while (minIndex <= maxIndex);
81
82        if (foundIndex === undefined)
83            return -1;
84
85        while (foundIndex && this._values[foundIndex - 1].indexOf(prefix) === 0)
86            foundIndex--;
87
88        return foundIndex;
89    },
90
91    keySet: function()
92    {
93        return this._values.keySet();
94    },
95
96    next: function(str, prefix)
97    {
98        return this._closest(str, prefix, 1);
99    },
100
101    previous: function(str, prefix)
102    {
103        return this._closest(str, prefix, -1);
104    },
105
106    _closest: function(str, prefix, shift)
107    {
108        if (!str)
109            return "";
110
111        var index = this._values.indexOf(str);
112        if (index === -1)
113            return "";
114
115        if (!prefix) {
116            index = (index + this._values.length + shift) % this._values.length;
117            return this._values[index];
118        }
119
120        var propertiesWithPrefix = this.startsWith(prefix);
121        var j = propertiesWithPrefix.indexOf(str);
122        j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length;
123        return propertiesWithPrefix[j];
124    }
125}
126