ol-cesium
Version:
OpenLayers Cesium integration library
1,680 lines (1,476 loc) • 1.11 MB
JavaScript
/**
* Cesium - https://github.com/AnalyticalGraphicsInc/cesium
*
* Copyright 2011-2017 Cesium Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Columbus View (Pat. Pend.)
*
* Portions licensed separately.
* See https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md for full licensing details.
*/
(function () {
define('Core/defined',[],function() {
'use strict';
/**
* @exports defined
*
* @param {*} value The object.
* @returns {Boolean} Returns true if the object is defined, returns false otherwise.
*
* @example
* if (Cesium.defined(positions)) {
* doSomething();
* } else {
* doSomethingElse();
* }
*/
function defined(value) {
return value !== undefined && value !== null;
}
return defined;
});
define('Core/DeveloperError',[
'./defined'
], function(
defined) {
'use strict';
/**
* Constructs an exception object that is thrown due to a developer error, e.g., invalid argument,
* argument out of range, etc. This exception should only be thrown during development;
* it usually indicates a bug in the calling code. This exception should never be
* caught; instead the calling code should strive not to generate it.
* <br /><br />
* On the other hand, a {@link RuntimeError} indicates an exception that may
* be thrown at runtime, e.g., out of memory, that the calling code should be prepared
* to catch.
*
* @alias DeveloperError
* @constructor
* @extends Error
*
* @param {String} [message] The error message for this exception.
*
* @see RuntimeError
*/
function DeveloperError(message) {
/**
* 'DeveloperError' indicating that this exception was thrown due to a developer error.
* @type {String}
* @readonly
*/
this.name = 'DeveloperError';
/**
* The explanation for why this exception was thrown.
* @type {String}
* @readonly
*/
this.message = message;
//Browsers such as IE don't have a stack property until you actually throw the error.
var stack;
try {
throw new Error();
} catch (e) {
stack = e.stack;
}
/**
* The stack trace of this exception, if available.
* @type {String}
* @readonly
*/
this.stack = stack;
}
if (defined(Object.create)) {
DeveloperError.prototype = Object.create(Error.prototype);
DeveloperError.prototype.constructor = DeveloperError;
}
DeveloperError.prototype.toString = function() {
var str = this.name + ': ' + this.message;
if (defined(this.stack)) {
str += '\n' + this.stack.toString();
}
return str;
};
/**
* @private
*/
DeveloperError.throwInstantiationError = function() {
throw new DeveloperError('This function defines an interface and should not be called directly.');
};
return DeveloperError;
});
/**
* @license
*
* Grauw URI utilities
*
* See: http://hg.grauw.nl/grauw-lib/file/tip/src/uri.js
*
* @author Laurens Holst (http://www.grauw.nl/)
*
* Copyright 2012 Laurens Holst
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
define('ThirdParty/Uri',[],function() {
/**
* Constructs a URI object.
* @constructor
* @class Implementation of URI parsing and base URI resolving algorithm in RFC 3986.
* @param {string|URI} uri A string or URI object to create the object from.
*/
function URI(uri) {
if (uri instanceof URI) { // copy constructor
this.scheme = uri.scheme;
this.authority = uri.authority;
this.path = uri.path;
this.query = uri.query;
this.fragment = uri.fragment;
} else if (uri) { // uri is URI string or cast to string
var c = parseRegex.exec(uri);
this.scheme = c[1];
this.authority = c[2];
this.path = c[3];
this.query = c[4];
this.fragment = c[5];
}
}
// Initial values on the prototype
URI.prototype.scheme = null;
URI.prototype.authority = null;
URI.prototype.path = '';
URI.prototype.query = null;
URI.prototype.fragment = null;
// Regular expression from RFC 3986 appendix B
var parseRegex = new RegExp('^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?$');
/**
* Returns the scheme part of the URI.
* In "http://example.com:80/a/b?x#y" this is "http".
*/
URI.prototype.getScheme = function() {
return this.scheme;
};
/**
* Returns the authority part of the URI.
* In "http://example.com:80/a/b?x#y" this is "example.com:80".
*/
URI.prototype.getAuthority = function() {
return this.authority;
};
/**
* Returns the path part of the URI.
* In "http://example.com:80/a/b?x#y" this is "/a/b".
* In "mailto:mike@example.com" this is "mike@example.com".
*/
URI.prototype.getPath = function() {
return this.path;
};
/**
* Returns the query part of the URI.
* In "http://example.com:80/a/b?x#y" this is "x".
*/
URI.prototype.getQuery = function() {
return this.query;
};
/**
* Returns the fragment part of the URI.
* In "http://example.com:80/a/b?x#y" this is "y".
*/
URI.prototype.getFragment = function() {
return this.fragment;
};
/**
* Tests whether the URI is an absolute URI.
* See RFC 3986 section 4.3.
*/
URI.prototype.isAbsolute = function() {
return !!this.scheme && !this.fragment;
};
///**
//* Extensive validation of the URI against the ABNF in RFC 3986
//*/
//URI.prototype.validate
/**
* Tests whether the URI is a same-document reference.
* See RFC 3986 section 4.4.
*
* To perform more thorough comparison, you can normalise the URI objects.
*/
URI.prototype.isSameDocumentAs = function(uri) {
return uri.scheme == this.scheme &&
uri.authority == this.authority &&
uri.path == this.path &&
uri.query == this.query;
};
/**
* Simple String Comparison of two URIs.
* See RFC 3986 section 6.2.1.
*
* To perform more thorough comparison, you can normalise the URI objects.
*/
URI.prototype.equals = function(uri) {
return this.isSameDocumentAs(uri) && uri.fragment == this.fragment;
};
/**
* Normalizes the URI using syntax-based normalization.
* This includes case normalization, percent-encoding normalization and path segment normalization.
* XXX: Percent-encoding normalization does not escape characters that need to be escaped.
* (Although that would not be a valid URI in the first place. See validate().)
* See RFC 3986 section 6.2.2.
*/
URI.prototype.normalize = function() {
this.removeDotSegments();
if (this.scheme)
this.scheme = this.scheme.toLowerCase();
if (this.authority)
this.authority = this.authority.replace(authorityRegex, replaceAuthority).
replace(caseRegex, replaceCase);
if (this.path)
this.path = this.path.replace(caseRegex, replaceCase);
if (this.query)
this.query = this.query.replace(caseRegex, replaceCase);
if (this.fragment)
this.fragment = this.fragment.replace(caseRegex, replaceCase);
};
var caseRegex = /%[0-9a-z]{2}/gi;
var percentRegex = /[a-zA-Z0-9\-\._~]/;
var authorityRegex = /(.*@)?([^@:]*)(:.*)?/;
function replaceCase(str) {
var dec = unescape(str);
return percentRegex.test(dec) ? dec : str.toUpperCase();
}
function replaceAuthority(str, p1, p2, p3) {
return (p1 || '') + p2.toLowerCase() + (p3 || '');
}
/**
* Resolve a relative URI (this) against a base URI.
* The base URI must be an absolute URI.
* See RFC 3986 section 5.2
*/
URI.prototype.resolve = function(baseURI) {
var uri = new URI();
if (this.scheme) {
uri.scheme = this.scheme;
uri.authority = this.authority;
uri.path = this.path;
uri.query = this.query;
} else {
uri.scheme = baseURI.scheme;
if (this.authority) {
uri.authority = this.authority;
uri.path = this.path;
uri.query = this.query;
} else {
uri.authority = baseURI.authority;
if (this.path == '') {
uri.path = baseURI.path;
uri.query = this.query || baseURI.query;
} else {
if (this.path.charAt(0) == '/') {
uri.path = this.path;
uri.removeDotSegments();
} else {
if (baseURI.authority && baseURI.path == '') {
uri.path = '/' + this.path;
} else {
uri.path = baseURI.path.substring(0, baseURI.path.lastIndexOf('/') + 1) + this.path;
}
uri.removeDotSegments();
}
uri.query = this.query;
}
}
}
uri.fragment = this.fragment;
return uri;
};
/**
* Remove dot segments from path.
* See RFC 3986 section 5.2.4
* @private
*/
URI.prototype.removeDotSegments = function() {
var input = this.path.split('/'),
output = [],
segment,
absPath = input[0] == '';
if (absPath)
input.shift();
var sFirst = input[0] == '' ? input.shift() : null;
while (input.length) {
segment = input.shift();
if (segment == '..') {
output.pop();
} else if (segment != '.') {
output.push(segment);
}
}
if (segment == '.' || segment == '..')
output.push('');
if (absPath)
output.unshift('');
this.path = output.join('/');
};
// We don't like this function because it builds up a cache that is never cleared.
// /**
// * Resolves a relative URI against an absolute base URI.
// * Convenience method.
// * @param {String} uri the relative URI to resolve
// * @param {String} baseURI the base URI (must be absolute) to resolve against
// */
// URI.resolve = function(sURI, sBaseURI) {
// var uri = cache[sURI] || (cache[sURI] = new URI(sURI));
// var baseURI = cache[sBaseURI] || (cache[sBaseURI] = new URI(sBaseURI));
// return uri.resolve(baseURI).toString();
// };
// var cache = {};
/**
* Serialises the URI to a string.
*/
URI.prototype.toString = function() {
var result = '';
if (this.scheme)
result += this.scheme + ':';
if (this.authority)
result += '//' + this.authority;
result += this.path;
if (this.query)
result += '?' + this.query;
if (this.fragment)
result += '#' + this.fragment;
return result;
};
return URI;
});
define('Core/freezeObject',[
'./defined'
], function(
defined) {
'use strict';
/**
* Freezes an object, using Object.freeze if available, otherwise returns
* the object unchanged. This function should be used in setup code to prevent
* errors from completely halting JavaScript execution in legacy browsers.
*
* @private
*
* @exports freezeObject
*/
var freezeObject = Object.freeze;
if (!defined(freezeObject)) {
freezeObject = function(o) {
return o;
};
}
return freezeObject;
});
define('Core/defaultValue',[
'./freezeObject'
], function(
freezeObject) {
'use strict';
/**
* Returns the first parameter if not undefined, otherwise the second parameter.
* Useful for setting a default value for a parameter.
*
* @exports defaultValue
*
* @param {*} a
* @param {*} b
* @returns {*} Returns the first parameter if not undefined, otherwise the second parameter.
*
* @example
* param = Cesium.defaultValue(param, 'default');
*/
function defaultValue(a, b) {
if (a !== undefined && a !== null) {
return a;
}
return b;
}
/**
* A frozen empty object that can be used as the default value for options passed as
* an object literal.
* @type {Object}
*/
defaultValue.EMPTY_OBJECT = freezeObject({});
return defaultValue;
});
define('Core/getAbsoluteUri',[
'../ThirdParty/Uri',
'./defaultValue',
'./defined',
'./DeveloperError'
], function(
Uri,
defaultValue,
defined,
DeveloperError) {
'use strict';
/**
* Given a relative Uri and a base Uri, returns the absolute Uri of the relative Uri.
* @exports getAbsoluteUri
*
* @param {String} relative The relative Uri.
* @param {String} [base] The base Uri.
* @returns {String} The absolute Uri of the given relative Uri.
*
* @example
* //absolute Uri will be "https://test.com/awesome.png";
* var absoluteUri = Cesium.getAbsoluteUri('awesome.png', 'https://test.com');
*/
function getAbsoluteUri(relative, base) {
var documentObject;
if (typeof document !== 'undefined') {
documentObject = document;
}
return getAbsoluteUri._implementation(relative, base, documentObject);
}
getAbsoluteUri._implementation = function(relative, base, documentObject) {
if (!defined(relative)) {
throw new DeveloperError('relative uri is required.');
}
if (!defined(base)) {
if (typeof documentObject === 'undefined') {
return relative;
}
base = defaultValue(documentObject.baseURI, documentObject.location.href);
}
var baseUri = new Uri(base);
var relativeUri = new Uri(relative);
return relativeUri.resolve(baseUri).toString();
};
return getAbsoluteUri;
});
/**
@license
when.js - https://github.com/cujojs/when
MIT License (c) copyright B Cavalier & J Hann
* A lightweight CommonJS Promises/A and when() implementation
* when is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
* @version 1.7.1
*/
(function(define) { 'use strict';
define('ThirdParty/when',[],function () {
var reduceArray, slice, undef;
//
// Public API
//
when.defer = defer; // Create a deferred
when.resolve = resolve; // Create a resolved promise
when.reject = reject; // Create a rejected promise
when.join = join; // Join 2 or more promises
when.all = all; // Resolve a list of promises
when.map = map; // Array.map() for promises
when.reduce = reduce; // Array.reduce() for promises
when.any = any; // One-winner race
when.some = some; // Multi-winner race
when.chain = chain; // Make a promise trigger another resolver
when.isPromise = isPromise; // Determine if a thing is a promise
/**
* Register an observer for a promise or immediate value.
*
* @param {*} promiseOrValue
* @param {function?} [onFulfilled] callback to be called when promiseOrValue is
* successfully fulfilled. If promiseOrValue is an immediate value, callback
* will be invoked immediately.
* @param {function?} [onRejected] callback to be called when promiseOrValue is
* rejected.
* @param {function?} [onProgress] callback to be called when progress updates
* are issued for promiseOrValue.
* @returns {Promise} a new {@link Promise} that will complete with the return
* value of callback or errback or the completion value of promiseOrValue if
* callback and/or errback is not supplied.
*/
function when(promiseOrValue, onFulfilled, onRejected, onProgress) {
// Get a trusted promise for the input promiseOrValue, and then
// register promise handlers
return resolve(promiseOrValue).then(onFulfilled, onRejected, onProgress);
}
/**
* Returns promiseOrValue if promiseOrValue is a {@link Promise}, a new Promise if
* promiseOrValue is a foreign promise, or a new, already-fulfilled {@link Promise}
* whose value is promiseOrValue if promiseOrValue is an immediate value.
*
* @param {*} promiseOrValue
* @returns Guaranteed to return a trusted Promise. If promiseOrValue is a when.js {@link Promise}
* returns promiseOrValue, otherwise, returns a new, already-resolved, when.js {@link Promise}
* whose resolution value is:
* * the resolution value of promiseOrValue if it's a foreign promise, or
* * promiseOrValue if it's a value
*/
function resolve(promiseOrValue) {
var promise, deferred;
if(promiseOrValue instanceof Promise) {
// It's a when.js promise, so we trust it
promise = promiseOrValue;
} else {
// It's not a when.js promise. See if it's a foreign promise or a value.
if(isPromise(promiseOrValue)) {
// It's a thenable, but we don't know where it came from, so don't trust
// its implementation entirely. Introduce a trusted middleman when.js promise
deferred = defer();
// IMPORTANT: This is the only place when.js should ever call .then() on an
// untrusted promise. Don't expose the return value to the untrusted promise
promiseOrValue.then(
function(value) { deferred.resolve(value); },
function(reason) { deferred.reject(reason); },
function(update) { deferred.progress(update); }
);
promise = deferred.promise;
} else {
// It's a value, not a promise. Create a resolved promise for it.
promise = fulfilled(promiseOrValue);
}
}
return promise;
}
/**
* Returns a rejected promise for the supplied promiseOrValue. The returned
* promise will be rejected with:
* - promiseOrValue, if it is a value, or
* - if promiseOrValue is a promise
* - promiseOrValue's value after it is fulfilled
* - promiseOrValue's reason after it is rejected
* @param {*} promiseOrValue the rejected value of the returned {@link Promise}
* @returns {Promise} rejected {@link Promise}
*/
function reject(promiseOrValue) {
return when(promiseOrValue, rejected);
}
/**
* Trusted Promise constructor. A Promise created from this constructor is
* a trusted when.js promise. Any other duck-typed promise is considered
* untrusted.
* @constructor
* @name Promise
*/
function Promise(then) {
this.then = then;
}
Promise.prototype = {
/**
* Register a callback that will be called when a promise is
* fulfilled or rejected. Optionally also register a progress handler.
* Shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress)
* @param {function?} [onFulfilledOrRejected]
* @param {function?} [onProgress]
* @returns {Promise}
*/
always: function(onFulfilledOrRejected, onProgress) {
return this.then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress);
},
/**
* Register a rejection handler. Shortcut for .then(undefined, onRejected)
* @param {function?} onRejected
* @returns {Promise}
*/
otherwise: function(onRejected) {
return this.then(undef, onRejected);
},
/**
* Shortcut for .then(function() { return value; })
* @param {*} value
* @returns {Promise} a promise that:
* - is fulfilled if value is not a promise, or
* - if value is a promise, will fulfill with its value, or reject
* with its reason.
*/
yield: function(value) {
return this.then(function() {
return value;
});
},
/**
* Assumes that this promise will fulfill with an array, and arranges
* for the onFulfilled to be called with the array as its argument list
* i.e. onFulfilled.spread(undefined, array).
* @param {function} onFulfilled function to receive spread arguments
* @returns {Promise}
*/
spread: function(onFulfilled) {
return this.then(function(array) {
// array may contain promises, so resolve its contents.
return all(array, function(array) {
return onFulfilled.apply(undef, array);
});
});
}
};
/**
* Create an already-resolved promise for the supplied value
* @private
*
* @param {*} value
* @returns {Promise} fulfilled promise
*/
function fulfilled(value) {
var p = new Promise(function(onFulfilled) {
// TODO: Promises/A+ check typeof onFulfilled
try {
return resolve(onFulfilled ? onFulfilled(value) : value);
} catch(e) {
return rejected(e);
}
});
return p;
}
/**
* Create an already-rejected {@link Promise} with the supplied
* rejection reason.
* @private
*
* @param {*} reason
* @returns {Promise} rejected promise
*/
function rejected(reason) {
var p = new Promise(function(_, onRejected) {
// TODO: Promises/A+ check typeof onRejected
try {
return onRejected ? resolve(onRejected(reason)) : rejected(reason);
} catch(e) {
return rejected(e);
}
});
return p;
}
/**
* Creates a new, Deferred with fully isolated resolver and promise parts,
* either or both of which may be given out safely to consumers.
* The Deferred itself has the full API: resolve, reject, progress, and
* then. The resolver has resolve, reject, and progress. The promise
* only has then.
*
* @returns {Deferred}
*/
function defer() {
var deferred, promise, handlers, progressHandlers,
_then, _progress, _resolve;
/**
* The promise for the new deferred
* @type {Promise}
*/
promise = new Promise(then);
/**
* The full Deferred object, with {@link Promise} and {@link Resolver} parts
* @class Deferred
* @name Deferred
*/
deferred = {
then: then, // DEPRECATED: use deferred.promise.then
resolve: promiseResolve,
reject: promiseReject,
// TODO: Consider renaming progress() to notify()
progress: promiseProgress,
promise: promise,
resolver: {
resolve: promiseResolve,
reject: promiseReject,
progress: promiseProgress
}
};
handlers = [];
progressHandlers = [];
/**
* Pre-resolution then() that adds the supplied callback, errback, and progback
* functions to the registered listeners
* @private
*
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
*/
_then = function(onFulfilled, onRejected, onProgress) {
// TODO: Promises/A+ check typeof onFulfilled, onRejected, onProgress
var deferred, progressHandler;
deferred = defer();
progressHandler = typeof onProgress === 'function'
? function(update) {
try {
// Allow progress handler to transform progress event
deferred.progress(onProgress(update));
} catch(e) {
// Use caught value as progress
deferred.progress(e);
}
}
: function(update) { deferred.progress(update); };
handlers.push(function(promise) {
promise.then(onFulfilled, onRejected)
.then(deferred.resolve, deferred.reject, progressHandler);
});
progressHandlers.push(progressHandler);
return deferred.promise;
};
/**
* Issue a progress event, notifying all progress listeners
* @private
* @param {*} update progress event payload to pass to all listeners
*/
_progress = function(update) {
processQueue(progressHandlers, update);
return update;
};
/**
* Transition from pre-resolution state to post-resolution state, notifying
* all listeners of the resolution or rejection
* @private
* @param {*} value the value of this deferred
*/
_resolve = function(value) {
value = resolve(value);
// Replace _then with one that directly notifies with the result.
_then = value.then;
// Replace _resolve so that this Deferred can only be resolved once
_resolve = resolve;
// Make _progress a noop, to disallow progress for the resolved promise.
_progress = noop;
// Notify handlers
processQueue(handlers, value);
// Free progressHandlers array since we'll never issue progress events
progressHandlers = handlers = undef;
return value;
};
return deferred;
/**
* Wrapper to allow _then to be replaced safely
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
* @returns {Promise} new promise
*/
function then(onFulfilled, onRejected, onProgress) {
// TODO: Promises/A+ check typeof onFulfilled, onRejected, onProgress
return _then(onFulfilled, onRejected, onProgress);
}
/**
* Wrapper to allow _resolve to be replaced
*/
function promiseResolve(val) {
return _resolve(val);
}
/**
* Wrapper to allow _reject to be replaced
*/
function promiseReject(err) {
return _resolve(rejected(err));
}
/**
* Wrapper to allow _progress to be replaced
*/
function promiseProgress(update) {
return _progress(update);
}
}
/**
* Determines if promiseOrValue is a promise or not. Uses the feature
* test from http://wiki.commonjs.org/wiki/Promises/A to determine if
* promiseOrValue is a promise.
*
* @param {*} promiseOrValue anything
* @returns {boolean} true if promiseOrValue is a {@link Promise}
*/
function isPromise(promiseOrValue) {
return promiseOrValue && typeof promiseOrValue.then === 'function';
}
/**
* Initiates a competitive race, returning a promise that will resolve when
* howMany of the supplied promisesOrValues have resolved, or will reject when
* it becomes impossible for howMany to resolve, for example, when
* (promisesOrValues.length - howMany) + 1 input promises reject.
*
* @param {Array} promisesOrValues array of anything, may contain a mix
* of promises and values
* @param howMany {number} number of promisesOrValues to resolve
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
* @returns {Promise} promise that will resolve to an array of howMany values that
* resolved first, or will reject with an array of (promisesOrValues.length - howMany) + 1
* rejection reasons.
*/
function some(promisesOrValues, howMany, onFulfilled, onRejected, onProgress) {
checkCallbacks(2, arguments);
return when(promisesOrValues, function(promisesOrValues) {
var toResolve, toReject, values, reasons, deferred, fulfillOne, rejectOne, progress, len, i;
len = promisesOrValues.length >>> 0;
toResolve = Math.max(0, Math.min(howMany, len));
values = [];
toReject = (len - toResolve) + 1;
reasons = [];
deferred = defer();
// No items in the input, resolve immediately
if (!toResolve) {
deferred.resolve(values);
} else {
progress = deferred.progress;
rejectOne = function(reason) {
reasons.push(reason);
if(!--toReject) {
fulfillOne = rejectOne = noop;
deferred.reject(reasons);
}
};
fulfillOne = function(val) {
// This orders the values based on promise resolution order
// Another strategy would be to use the original position of
// the corresponding promise.
values.push(val);
if (!--toResolve) {
fulfillOne = rejectOne = noop;
deferred.resolve(values);
}
};
for(i = 0; i < len; ++i) {
if(i in promisesOrValues) {
when(promisesOrValues[i], fulfiller, rejecter, progress);
}
}
}
return deferred.then(onFulfilled, onRejected, onProgress);
function rejecter(reason) {
rejectOne(reason);
}
function fulfiller(val) {
fulfillOne(val);
}
});
}
/**
* Initiates a competitive race, returning a promise that will resolve when
* any one of the supplied promisesOrValues has resolved or will reject when
* *all* promisesOrValues have rejected.
*
* @param {Array|Promise} promisesOrValues array of anything, may contain a mix
* of {@link Promise}s and values
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
* @returns {Promise} promise that will resolve to the value that resolved first, or
* will reject with an array of all rejected inputs.
*/
function any(promisesOrValues, onFulfilled, onRejected, onProgress) {
function unwrapSingleResult(val) {
return onFulfilled ? onFulfilled(val[0]) : val[0];
}
return some(promisesOrValues, 1, unwrapSingleResult, onRejected, onProgress);
}
/**
* Return a promise that will resolve only once all the supplied promisesOrValues
* have resolved. The resolution value of the returned promise will be an array
* containing the resolution values of each of the promisesOrValues.
* @memberOf when
*
* @param {Array|Promise} promisesOrValues array of anything, may contain a mix
* of {@link Promise}s and values
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
* @returns {Promise}
*/
function all(promisesOrValues, onFulfilled, onRejected, onProgress) {
checkCallbacks(1, arguments);
return map(promisesOrValues, identity).then(onFulfilled, onRejected, onProgress);
}
/**
* Joins multiple promises into a single returned promise.
* @returns {Promise} a promise that will fulfill when *all* the input promises
* have fulfilled, or will reject when *any one* of the input promises rejects.
*/
function join(/* ...promises */) {
return map(arguments, identity);
}
/**
* Traditional map function, similar to `Array.prototype.map()`, but allows
* input to contain {@link Promise}s and/or values, and mapFunc may return
* either a value or a {@link Promise}
*
* @param {Array|Promise} promise array of anything, may contain a mix
* of {@link Promise}s and values
* @param {function} mapFunc mapping function mapFunc(value) which may return
* either a {@link Promise} or value
* @returns {Promise} a {@link Promise} that will resolve to an array containing
* the mapped output values.
*/
function map(promise, mapFunc) {
return when(promise, function(array) {
var results, len, toResolve, resolve, i, d;
// Since we know the resulting length, we can preallocate the results
// array to avoid array expansions.
toResolve = len = array.length >>> 0;
results = [];
d = defer();
if(!toResolve) {
d.resolve(results);
} else {
resolve = function resolveOne(item, i) {
when(item, mapFunc).then(function(mapped) {
results[i] = mapped;
if(!--toResolve) {
d.resolve(results);
}
}, d.reject);
};
// Since mapFunc may be async, get all invocations of it into flight
for(i = 0; i < len; i++) {
if(i in array) {
resolve(array[i], i);
} else {
--toResolve;
}
}
}
return d.promise;
});
}
/**
* Traditional reduce function, similar to `Array.prototype.reduce()`, but
* input may contain promises and/or values, and reduceFunc
* may return either a value or a promise, *and* initialValue may
* be a promise for the starting value.
*
* @param {Array|Promise} promise array or promise for an array of anything,
* may contain a mix of promises and values.
* @param {function} reduceFunc reduce function reduce(currentValue, nextValue, index, total),
* where total is the total number of items being reduced, and will be the same
* in each call to reduceFunc.
* @returns {Promise} that will resolve to the final reduced value
*/
function reduce(promise, reduceFunc /*, initialValue */) {
var args = slice.call(arguments, 1);
return when(promise, function(array) {
var total;
total = array.length;
// Wrap the supplied reduceFunc with one that handles promises and then
// delegates to the supplied.
args[0] = function (current, val, i) {
return when(current, function (c) {
return when(val, function (value) {
return reduceFunc(c, value, i, total);
});
});
};
return reduceArray.apply(array, args);
});
}
/**
* Ensure that resolution of promiseOrValue will trigger resolver with the
* value or reason of promiseOrValue, or instead with resolveValue if it is provided.
*
* @param promiseOrValue
* @param {Object} resolver
* @param {function} resolver.resolve
* @param {function} resolver.reject
* @param {*} [resolveValue]
* @returns {Promise}
*/
function chain(promiseOrValue, resolver, resolveValue) {
var useResolveValue = arguments.length > 2;
return when(promiseOrValue,
function(val) {
val = useResolveValue ? resolveValue : val;
resolver.resolve(val);
return val;
},
function(reason) {
resolver.reject(reason);
return rejected(reason);
},
resolver.progress
);
}
//
// Utility functions
//
/**
* Apply all functions in queue to value
* @param {Array} queue array of functions to execute
* @param {*} value argument passed to each function
*/
function processQueue(queue, value) {
var handler, i = 0;
while (handler = queue[i++]) {
handler(value);
}
}
/**
* Helper that checks arrayOfCallbacks to ensure that each element is either
* a function, or null or undefined.
* @private
* @param {number} start index at which to start checking items in arrayOfCallbacks
* @param {Array} arrayOfCallbacks array to check
* @throws {Error} if any element of arrayOfCallbacks is something other than
* a functions, null, or undefined.
*/
function checkCallbacks(start, arrayOfCallbacks) {
// TODO: Promises/A+ update type checking and docs
var arg, i = arrayOfCallbacks.length;
while(i > start) {
arg = arrayOfCallbacks[--i];
if (arg != null && typeof arg != 'function') {
throw new Error('arg '+i+' must be a function');
}
}
}
/**
* No-Op function used in method replacement
* @private
*/
function noop() {}
slice = [].slice;
// ES5 reduce implementation if native not available
// See: http://es5.github.com/#x15.4.4.21 as there are many
// specifics and edge cases.
reduceArray = [].reduce ||
function(reduceFunc /*, initialValue */) {
/*jshint maxcomplexity: 7*/
// ES5 dictates that reduce.length === 1
// This implementation deviates from ES5 spec in the following ways:
// 1. It does not check if reduceFunc is a Callable
var arr, args, reduced, len, i;
i = 0;
// This generates a jshint warning, despite being valid
// "Missing 'new' prefix when invoking a constructor."
// See https://github.com/jshint/jshint/issues/392
arr = Object(this);
len = arr.length >>> 0;
args = arguments;
// If no initialValue, use first item of array (we know length !== 0 here)
// and adjust i to start at second item
if(args.length <= 1) {
// Skip to the first real element in the array
for(;;) {
if(i in arr) {
reduced = arr[i++];
break;
}
// If we reached the end of the array without finding any real
// elements, it's a TypeError
if(++i >= len) {
throw new TypeError();
}
}
} else {
// If initialValue provided, use it
reduced = args[1];
}
// Do the actual reduce
for(;i < len; ++i) {
// Skip holes
if(i in arr) {
reduced = reduceFunc(reduced, arr[i], i, arr);
}
}
return reduced;
};
function identity(x) {
return x;
}
return when;
});
})(typeof define == 'function' && define.amd
? define
: function (factory) { typeof exports === 'object'
? (module.exports = factory())
: (this.when = factory());
}
// Boilerplate for AMD, Node, and browser global
);
define('Core/appendForwardSlash',[],function() {
'use strict';
/**
* @private
*/
function appendForwardSlash(url) {
if (url.length === 0 || url[url.length - 1] !== '/') {
url = url + '/';
}
return url;
}
return appendForwardSlash;
});
define('Core/Check',[
'./defined',
'./DeveloperError'
], function(
defined,
DeveloperError) {
'use strict';
/**
* Contains functions for checking that supplied arguments are of a specified type
* or meet specified conditions
* @private
*/
var Check = {};
/**
* Contains type checking functions, all using the typeof operator
*/
Check.typeOf = {};
function getUndefinedErrorMessage(name) {
return name + ' is required, actual value was undefined';
}
function getFailedTypeErrorMessage(actual, expected, name) {
return 'Expected ' + name + ' to be typeof ' + expected + ', actual typeof was ' + actual;
}
/**
* Throws if test is not defined
*
* @param {String} name The name of the variable being tested
* @param {*} test The value that is to be checked
* @exception {DeveloperError} test must be defined
*/
Check.defined = function (name, test) {
if (!defined(test)) {
throw new DeveloperError(getUndefinedErrorMessage(name));
}
};
/**
* Throws if test is not typeof 'function'
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @exception {DeveloperError} test must be typeof 'function'
*/
Check.typeOf.func = function (name, test) {
if (typeof test !== 'function') {
throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'function', name));
}
};
/**
* Throws if test is not typeof 'string'
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @exception {DeveloperError} test must be typeof 'string'
*/
Check.typeOf.string = function (name, test) {
if (typeof test !== 'string') {
throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'string', name));
}
};
/**
* Throws if test is not typeof 'number'
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @exception {DeveloperError} test must be typeof 'number'
*/
Check.typeOf.number = function (name, test) {
if (typeof test !== 'number') {
throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'number', name));
}
};
/**
* Throws if test is not typeof 'number' and less than limit
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @param {Number} limit The limit value to compare against
* @exception {DeveloperError} test must be typeof 'number' and less than limit
*/
Check.typeOf.number.lessThan = function (name, test, limit) {
Check.typeOf.number(name, test);
if (test >= limit) {
throw new DeveloperError('Expected ' + name + ' to be less than ' + limit + ', actual value was ' + test);
}
};
/**
* Throws if test is not typeof 'number' and less than or equal to limit
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @param {Number} limit The limit value to compare against
* @exception {DeveloperError} test must be typeof 'number' and less than or equal to limit
*/
Check.typeOf.number.lessThanOrEquals = function (name, test, limit) {
Check.typeOf.number(name, test);
if (test > limit) {
throw new DeveloperError('Expected ' + name + ' to be less than or equal to ' + limit + ', actual value was ' + test);
}
};
/**
* Throws if test is not typeof 'number' and greater than limit
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @param {Number} limit The limit value to compare against
* @exception {DeveloperError} test must be typeof 'number' and greater than limit
*/
Check.typeOf.number.greaterThan = function (name, test, limit) {
Check.typeOf.number(name, test);
if (test <= limit) {
throw new DeveloperError('Expected ' + name + ' to be greater than ' + limit + ', actual value was ' + test);
}
};
/**
* Throws if test is not typeof 'number' and greater than or equal to limit
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @param {Number} limit The limit value to compare against
* @exception {DeveloperError} test must be typeof 'number' and greater than or equal to limit
*/
Check.typeOf.number.greaterThanOrEquals = function (name, test, limit) {
Check.typeOf.number(name, test);
if (test < limit) {
throw new DeveloperError('Expected ' + name + ' to be greater than or equal to' + limit + ', actual value was ' + test);
}
};
/**
* Throws if test is not typeof 'object'
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @exception {DeveloperError} test must be typeof 'object'
*/
Check.typeOf.object = function (name, test) {
if (typeof test !== 'object') {
throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'object', name));
}
};
/**
* Throws if test is not typeof 'boolean'
*
* @param {String} name The name of the variable being tested
* @param {*} test The value to test
* @exception {DeveloperError} test must be typeof 'boolean'
*/
Check.typeOf.bool = function (name, test) {
if (typeof test !== 'boolean') {
throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'boolean', name));
}
};
/**
* Throws if test1 and test2 is not typeof 'number' and not equal in value
*
* @param {String} name1 The name of the first variable being tested
* @param {String} name2 The name of the second variable being tested against
* @param {*} test1 The value to test
* @param {*} test2 The value to test against
* @exception {DeveloperError} test1 and test2 should be type of 'number' and be equal in value
*/
Check.typeOf.number.equals = function (name1, name2, test1, test2) {
Check.typeOf.number(name1, test1);
Check.typeOf.number(name2, test2);
if (test1 !== test2) {
throw new DeveloperError(name1 + ' must be equal to ' + name2 + ', the actual values are ' + test1 + ' and ' + test2);
}
};
return Check;
});
define('Core/clone',[
'./defaultValue'
], function(
defaultValue) {
'use strict';
/**
* Clones an object, returning a new object containing the same properties.
*
* @exports clone
*
* @param {Object} object The object to clone.
* @param {Boolean} [deep=false] If true, all properties will be deep cloned recursively.
* @returns {Object} The cloned object.
*/
function clone(object, deep) {
if (object === null || typeof object !== 'object') {
return object;
}
deep = defaultValue(deep, false);
var result = new object.constructor();
for ( var propertyName in object) {
if (object.hasOwnProperty(propertyName)) {
var value = object[propertyName];
if (deep) {
value = clone(value, deep);
}
result[propertyName] = value;
}
}
return result;
}
return clone;
});
define('Core/combine',[
'./defaultValue',
'./defined'
], function(
defaultValue,
defined) {
'use strict';
/**
* Merges two objects, copying their properties onto a new combined object. When two objects have the same
* property, the value of the property on the first object is used. If either object is undefined,
* it will be treated as an empty object.
*
* @example
* var object1 = {
* propOne : 1,
* propTwo : {
* value1 : 10
* }
* }
* var object2 = {
* propTwo : 2
* }
* var final = Cesium.combine(object1, object2);
*
* // final === {
* // propOne : 1,
* // propTwo : {
* // value1 : 10
* // }
* // }
*
* @param {Object} [object1] The first object to merge.
* @param {Object} [object2] The second object to merge.
* @param {Boolean} [deep=false] Perform a recursive merge.
* @returns {Object} The combined object containing all properties from both objects.
*
* @exports combine
*/
function combine(object1, object2, deep) {
deep = defaultValue(deep, false);
var result = {};
var object1Defined = defined(object1);
var object2Defined = defined(object2);
var property;
var object1Value;
var object2Value;
if (object1Defined) {
for (property in object1) {
if (object1.hasOwnProperty(property)) {
object1Value = object1[property];
if (object2Defined && deep && typeof object1Value === 'object' && object2.hasOwnProperty(property)) {
object2Value = object2[property];
if (typeof object2Value === 'object') {
result[property] = combine(object1Value, object2Value, deep);
} else {
result[property] = object1Value;
}
} else {
result[property] = object1Value;
}
}
}
}
if (object2Defined) {
for (property in object2) {
if (object2.hasOwnProperty(property) && !result.hasOwnProperty(property)) {
object2Value = object2[property];
result[property] = object2Value;
}
}
}
return result;
}
return combine;
});
define('Core/defineProperties',[
'./defined'
], function(
defined) {
'use strict';
var definePropertyWorks = (function() {
try {
return 'x' in Object.defineProperty({}, 'x', {});
} catch (e) {
return false;
}
})();
/**
* Defines properties on an object, using Object.defineProperties if available,
* otherwise returns the object unchanged. This function should be used in
* setup code to prevent errors from completely halting JavaScript execution
* in legacy browsers.
*
* @private
*
* @exports defineProperties
*/
var defineProperties = Object.defineProperties;
if (!definePropertyWorks || !defined(defineProperties)) {
defineProperties = function(o) {
return o;
};
}
return defineProperties;
});
define('Core/oneTimeWarning',[
'./defaultValue',
'./defined',
'./DeveloperError'
], function(
defaultValue,
defined,
DeveloperError) {
'use strict';
var warnings = {};
/**
* Logs a one time message to the console. Use this function instead of
* <code>console.log</code> directly since this does not log duplicate messages
* unless it is called from multiple workers.
*
* @exports oneTimeWarning
*
* @param {String} identifier The unique identifier for this warning.
* @param {String} [message=identifier] The message to log to the console.
*
* @example
* for(var i=0;i<foo.length;++i) {
* if (!defined(foo[i].bar)) {
* // Something that can be recovered from but may happen a lot
* oneTimeWarning('foo.bar undefined', 'foo.bar is undefined. Setting to 0.');
* foo[i].bar = 0;
* // ...
* }
* }
*
* @private
*/
function oneTimeWarning(identifier, message) {
if (!defined(identifier)) {
throw new DeveloperError('identifier is required.');
}
if (!defined(warnings[identifier])) {
warnings[identifier] = true;
console.warn(defaultValue(message, identifier));
}
}
oneTimeWarning.geometryOutlines = 'Entity geometry outlines are unsupported on terrain. Outlines will be disabled. To enable outlines, disable geometry terrain clamping by explicitly setting height to 0.';
oneTimeWarning.geometryZIndex = 'Entity geometry with zIndex are unsupported when height or extrudedHeight are defined. zIndex will be ignored';
oneTimeWarning.geometryHeightReference = 'Entity corridor, ellipse, polygon or rectangle with heightReference must also have a defined height. heightReference will be ignored';
oneTimeWarning.geometryExtrudedHeightReference = 'Entity corridor, ellipse, polygon or rectangle with extrudedHeightReference must also have a defined extrudedHeight. extrudedHeightReference will be ignored';
return oneTimeWarning;
});
define('Core/deprecationWarning',[
'./defined',
'./DeveloperError',
'./oneTimeWarning'
], fun