OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 * THE POSSIBILITY OF SUCH DAMAGE. | 23 * THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 var base = base || {}; | 26 var base = base || {}; |
27 | 27 |
28 (function(){ | 28 (function(){ |
29 | 29 |
30 base.endsWith = function(string, suffix) | |
31 { | |
32 if (suffix.length > string.length) | |
33 return false; | |
34 var expectedIndex = string.length - suffix.length; | |
35 return string.lastIndexOf(suffix) == expectedIndex; | |
36 }; | |
37 | |
38 base.joinPath = function(parent, child) | |
39 { | |
40 if (parent.length == 0) | |
41 return child; | |
42 return parent + '/' + child; | |
43 }; | |
44 | |
45 base.trimExtension = function(url) | |
46 { | |
47 var index = url.lastIndexOf('.'); | |
48 if (index == -1) | |
49 return url; | |
50 return url.substr(0, index); | |
51 } | |
52 | |
53 base.uniquifyArray = function(array) | |
54 { | |
55 var seen = {}; | |
56 var result = []; | |
57 array.forEach(function(value) { | |
58 if (seen[value]) | |
59 return; | |
60 seen[value] = true; | |
61 result.push(value); | |
62 }); | |
63 return result; | |
64 }; | |
65 | |
66 base.filterTree = function(tree, isLeaf, predicate) | |
67 { | |
68 var filteredTree = {}; | |
69 | |
70 function walkSubtree(subtree, directory) | |
71 { | |
72 for (var childName in subtree) { | |
73 var child = subtree[childName]; | |
74 var childPath = base.joinPath(directory, childName); | |
75 if (isLeaf(child)) { | |
76 if (predicate(child)) | |
77 filteredTree[childPath] = child; | |
78 continue; | |
79 } | |
80 walkSubtree(child, childPath); | |
81 } | |
82 } | |
83 | |
84 walkSubtree(tree, ''); | |
85 return filteredTree; | |
86 }; | |
87 | |
88 base.parseJSONP = function(jsonp) | |
89 { | |
90 if (!jsonp) | |
91 return {}; | |
92 | |
93 if (!jsonp.match(/^[^{[]*\(/)) | |
94 return JSON.parse(jsonp); | |
95 | |
96 var startIndex = jsonp.indexOf('(') + 1; | |
97 var endIndex = jsonp.lastIndexOf(')'); | |
98 if (startIndex == 0 || endIndex == -1) | |
99 return {}; | |
100 return JSON.parse(jsonp.substr(startIndex, endIndex - startIndex)); | |
101 }; | |
102 | |
103 // This is effectively a cache of possibly-resolved promises. | 30 // This is effectively a cache of possibly-resolved promises. |
104 base.AsynchronousCache = function(fetch) | 31 base.AsynchronousCache = function(fetch) |
105 { | 32 { |
106 this._fetch = fetch; | 33 this._fetch = fetch; |
107 this._promiseCache = {}; | 34 this._promiseCache = {}; |
108 }; | 35 }; |
109 | 36 |
110 base.AsynchronousCache._sentinel = new Object(); | 37 base.AsynchronousCache._sentinel = new Object(); |
111 base.AsynchronousCache.prototype.get = function(key) | 38 base.AsynchronousCache.prototype.get = function(key) |
112 { | 39 { |
113 if (!(key in this._promiseCache)) { | 40 if (!(key in this._promiseCache)) { |
114 this._promiseCache[key] = base.AsynchronousCache._sentinel; | 41 this._promiseCache[key] = base.AsynchronousCache._sentinel; |
115 this._promiseCache[key] = this._fetch.call(null, key); | 42 this._promiseCache[key] = this._fetch.call(null, key); |
116 } | 43 } |
117 if (this._promiseCache[key] === base.AsynchronousCache._sentinel) | 44 if (this._promiseCache[key] === base.AsynchronousCache._sentinel) |
118 return Promise.reject(Error("Reentrant request for ", key)); | 45 return Promise.reject(Error("Reentrant request for ", key)); |
119 | 46 |
120 return this._promiseCache[key]; | 47 return this._promiseCache[key]; |
121 }; | 48 }; |
122 | 49 |
123 base.AsynchronousCache.prototype.clear = function() | 50 base.AsynchronousCache.prototype.clear = function() |
124 { | 51 { |
125 this._promiseCache = {}; | 52 this._promiseCache = {}; |
126 }; | 53 }; |
127 | 54 |
128 // Based on http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/resou
rces/shared/js/cr/ui.js | |
129 base.extends = function(base, prototype) | |
130 { | |
131 var extended = function() { | |
132 var element = typeof base == 'string' ? document.createElement(base) : b
ase.call(this); | |
133 extended.prototype.__proto__ = element.__proto__; | |
134 element.__proto__ = extended.prototype; | |
135 var singleton = element.init && element.init.apply(element, arguments); | |
136 if (singleton) | |
137 return singleton; | |
138 return element; | |
139 } | |
140 | |
141 extended.prototype = prototype; | |
142 return extended; | |
143 } | |
144 | |
145 base.underscoredBuilderName = function(builderName) | |
146 { | |
147 return builderName.replace(/[ .()]/g, '_'); | |
148 } | |
149 | |
150 base.queryParam = function(params) | |
151 { | |
152 var result = [] | |
153 Object.keys(params, function(key, value) { | |
154 result.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); | |
155 }); | |
156 // FIXME: Remove the conversion of space to plus. This is just here | |
157 // to remain compatible with jQuery.param, but there's no reason to | |
158 // deviate from the built-in encodeURIComponent behavior. | |
159 return result.join('&').replace(/%20/g, '+'); | |
160 } | |
161 | |
162 })(); | 55 })(); |
OLD | NEW |