| /* |
| * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| JSON.LoadError = "JSONLoadError"; |
| JSON.ParseError = "JSONParseError"; |
| |
| // JSON.load() may be called using the following forms: |
| // |
| // JSON.load("http://www.apple.com", function() {/* success */}) |
| // OR |
| // JSON.load("http://www.apple.com", function() {/* success */}, {withCredentials: true, ...}) |
| // OR |
| // JSON.load("http://www.apple.com", function() {/* success */}, function() {/* failure */}) |
| // OR |
| // JSON.load("http://www.apple.com", function() {/* success */}, function() {/* failure */}, {withCredentials: true, ...}) |
| JSON.load = function(url, successCallback, failureCallback, options) |
| { |
| console.assert(url); |
| |
| if (!(successCallback instanceof Function)) |
| return; |
| |
| if (failureCallback && typeof failureCallback === "object") |
| options = failureCallback; |
| |
| if (!(failureCallback instanceof Function)) |
| failureCallback = function() { }; |
| |
| if (typeof options !== "object") |
| options = {}; |
| |
| var request = new XMLHttpRequest; |
| request.onreadystatechange = function() { |
| if (this.readyState !== 4) |
| return; |
| |
| // Don't consider a status of 0 to be a load error for easier testing with local files. |
| var loadErrorOccurred = this.status !== 0 && this.status !== 200; |
| if (loadErrorOccurred) { |
| failureCallback({errorType: JSON.LoadError, error: this.statusText, errorHTTPCode: this.status}); |
| return; |
| } |
| |
| try { |
| var responseText = request.responseText; |
| if (options.hasOwnProperty("jsonpCallbackName")) |
| responseText = responseText.replace(new RegExp("^" + options.jsonpCallbackName + "\\((.*)\\);?$"), "$1"); |
| var data = JSON.parse(responseText); |
| } catch (e) { |
| var data = {errorType: JSON.ParseError, error: e.message}; |
| failureCallback(data); |
| return; |
| } |
| |
| successCallback(data); |
| }; |
| |
| request.open("GET", url); |
| if (options.hasOwnProperty("withCredentials")) |
| request.withCredentials = options.withCredentials; |
| request.send(); |
| }; |
| |
| function loadXML(url, callback, options) { |
| console.assert(url); |
| |
| if (!(callback instanceof Function)) |
| return; |
| |
| var request = new XMLHttpRequest; |
| request.onreadystatechange = function() { |
| if (this.readyState !== 4) |
| return; |
| |
| // Allow a status of 0 for easier testing with local files. |
| if (!this.status || this.status === 200) |
| callback(request.responseXML); |
| }; |
| |
| request.open("GET", url); |
| if ((typeof options === "object") && options.hasOwnProperty("withCredentials")) |
| request.withCredentials = options.withCredentials; |
| request.send(); |
| }; |
| |
| Node.prototype.isAncestor = function(node) |
| { |
| if (!node) |
| return false; |
| |
| var currentNode = node.parentNode; |
| while (currentNode) { |
| if (this === currentNode) |
| return true; |
| currentNode = currentNode.parentNode; |
| } |
| |
| return false; |
| } |
| |
| Node.prototype.isDescendant = function(descendant) |
| { |
| return !!descendant && descendant.isAncestor(this); |
| } |
| |
| Node.prototype.isSelfOrAncestor = function(node) |
| { |
| return !!node && (node === this || this.isAncestor(node)); |
| } |
| |
| Node.prototype.isSelfOrDescendant = function(node) |
| { |
| return !!node && (node === this || this.isDescendant(node)); |
| } |
| |
| Element.prototype.removeChildren = function() |
| { |
| // This has been tested to be the fastest removal method. |
| if (this.firstChild) |
| this.textContent = ""; |
| }; |
| |
| DOMTokenList.prototype.contains = function(string) |
| { |
| for (var i = 0, end = this.length; i < end; ++i) { |
| if (this.item(i) === string) |
| return true; |
| } |
| return false; |
| } |
| |
| Array.prototype.contains = function(value) |
| { |
| return this.indexOf(value) >= 0; |
| }; |
| |
| Array.prototype.findFirst = function(predicate) |
| { |
| for (var i = 0; i < this.length; ++i) { |
| if (predicate(this[i])) |
| return this[i]; |
| } |
| |
| return null; |
| }; |
| |
| Array.prototype.average = function() |
| { |
| var sum = 0; |
| var count = this.length; |
| for (var i = 0; i < count; ++i) |
| sum += this[i]; |
| return sum / count; |
| }; |
| |
| Array.prototype.median = function() |
| { |
| var array = this.slice(); // Make a copy to avoid modifying the object. |
| array.sort(function(a, b) { return a - b; }); |
| |
| var half = Math.floor(array.length / 2); |
| |
| if (array.length % 2) |
| return array[half]; |
| else |
| return (array[half - 1] + array[half]) / 2; |
| }; |
| |
| String.prototype.contains = function(substring) |
| { |
| return this.indexOf(substring) >= 0; |
| }; |
| |
| String.prototype.startsWith = function(substring) |
| { |
| return this.lastIndexOf(substring, 0) === 0; |
| }; |
| |
| function sortDictionariesByOrder(unsorted) |
| { |
| var sorted = []; |
| |
| for (var key in unsorted) |
| sorted.push(unsorted[key]); |
| |
| sorted.sort(function(a, b) { |
| return a.order - b.order; |
| }); |
| |
| return sorted; |
| }; |