| 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 |