summaryrefslogtreecommitdiff
path: root/chimere/static/ol3/ol-debug.js
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2016-05-29 23:23:16 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2016-05-29 23:23:16 +0200
commit25d2888bc10e782e85e097aac8a0879a3c148cc7 (patch)
treeb47820eac152e7114ca320a742d49c095f2a758a /chimere/static/ol3/ol-debug.js
parentfb7858ee1391861e70586e931c2cfec97b4b6c48 (diff)
downloadChimère-25d2888bc10e782e85e097aac8a0879a3c148cc7.tar.bz2
Chimère-25d2888bc10e782e85e097aac8a0879a3c148cc7.zip
ol3 v3.12 -> v3.16
Diffstat (limited to 'chimere/static/ol3/ol-debug.js')
-rw-r--r--chimere/static/ol3/ol-debug.js57917
1 files changed, 22121 insertions, 35796 deletions
diff --git a/chimere/static/ol3/ol-debug.js b/chimere/static/ol3/ol-debug.js
index 5bf1864..91f7ae3 100644
--- a/chimere/static/ol3/ol-debug.js
+++ b/chimere/static/ol3/ol-debug.js
@@ -1,6 +1,6 @@
// OpenLayers 3. See http://openlayers.org/
// License: https://raw.githubusercontent.com/openlayers/ol3/master/LICENSE.md
-// Version: v3.12.1
+// Version: v3.16.0
(function (root, factory) {
if (typeof exports === "object") {
@@ -177,7 +177,8 @@ goog.define = function(name, defaultValue) {
Object.prototype.hasOwnProperty.call(
goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {
value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];
- } else if (goog.global.CLOSURE_DEFINES &&
+ } else if (
+ goog.global.CLOSURE_DEFINES &&
Object.prototype.hasOwnProperty.call(
goog.global.CLOSURE_DEFINES, name)) {
value = goog.global.CLOSURE_DEFINES[name];
@@ -239,7 +240,7 @@ goog.define('goog.TRUSTED_SITE', true);
*
* This define can be used to trigger alternate implementations compatible with
* running in EcmaScript Strict mode or warn about unavailable functionality.
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
+ * @see https://goo.gl/g5EoHI
*
*/
goog.define('goog.STRICT_MODE_COMPATIBLE', false);
@@ -282,6 +283,9 @@ goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', false);
* "goog.package.part".
*/
goog.provide = function(name) {
+ if (goog.isInModuleLoader_()) {
+ throw Error('goog.provide can not be used within a goog.module.');
+ }
if (!COMPILED) {
// Ensure that the same namespace isn't provided twice.
// A goog.module/goog.provide maps a goog.require to a specific file
@@ -359,8 +363,7 @@ goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;
* "goog.package.part", is expected but not required.
*/
goog.module = function(name) {
- if (!goog.isString(name) ||
- !name ||
+ if (!goog.isString(name) || !name ||
name.search(goog.VALID_MODULE_RE_) == -1) {
throw Error('Invalid module identifier');
}
@@ -408,9 +411,8 @@ goog.module.getInternal_ = function(name) {
if (!COMPILED) {
if (goog.isProvided_(name)) {
// goog.require only return a value with-in goog.module files.
- return name in goog.loadedModules_ ?
- goog.loadedModules_[name] :
- goog.getObjectByName(name);
+ return name in goog.loadedModules_ ? goog.loadedModules_[name] :
+ goog.getObjectByName(name);
} else {
return null;
}
@@ -419,7 +421,7 @@ goog.module.getInternal_ = function(name) {
/**
- * @private {?{moduleName: (string|undefined)}}
+ * @private {?{moduleName: (string|undefined), declareLegacyNamespace:boolean}}
*/
goog.moduleLoaderState_ = null;
@@ -441,11 +443,13 @@ goog.isInModuleLoader_ = function() {
*/
goog.module.declareLegacyNamespace = function() {
if (!COMPILED && !goog.isInModuleLoader_()) {
- throw new Error('goog.module.declareLegacyNamespace must be called from ' +
+ throw new Error(
+ 'goog.module.declareLegacyNamespace must be called from ' +
'within a goog.module');
}
if (!COMPILED && !goog.moduleLoaderState_.moduleName) {
- throw Error('goog.module must be called prior to ' +
+ throw Error(
+ 'goog.module must be called prior to ' +
'goog.module.declareLegacyNamespace.');
}
goog.moduleLoaderState_.declareLegacyNamespace = true;
@@ -466,8 +470,9 @@ goog.module.declareLegacyNamespace = function() {
goog.setTestOnly = function(opt_message) {
if (goog.DISALLOW_TEST_ONLY_CODE) {
opt_message = opt_message || '';
- throw Error('Importing test-only code into non-debug environment' +
- (opt_message ? ': ' + opt_message : '.'));
+ throw Error(
+ 'Importing test-only code into non-debug environment' +
+ (opt_message ? ': ' + opt_message : '.'));
}
};
@@ -497,11 +502,11 @@ goog.forwardDeclare = function(name) {};
* and thus block property disambiguation.
*/
goog.forwardDeclare('Document');
+goog.forwardDeclare('HTMLScriptElement');
goog.forwardDeclare('XMLHttpRequest');
if (!COMPILED) {
-
/**
* Check if the given name has been goog.provided. This will return false for
* names that are available only as implicit namespaces.
@@ -512,7 +517,7 @@ if (!COMPILED) {
goog.isProvided_ = function(name) {
return (name in goog.loadedModules_) ||
(!goog.implicitNamespaces_[name] &&
- goog.isDefAndNotNull(goog.getObjectByName(name)));
+ goog.isDefAndNotNull(goog.getObjectByName(name)));
};
/**
@@ -546,7 +551,7 @@ if (!COMPILED) {
goog.getObjectByName = function(name, opt_obj) {
var parts = name.split('.');
var cur = opt_obj || goog.global;
- for (var part; part = parts.shift(); ) {
+ for (var part; part = parts.shift();) {
if (goog.isDefAndNotNull(cur[part])) {
cur = cur[part];
} else {
@@ -580,17 +585,22 @@ goog.globalize = function(obj, opt_global) {
* the names of the objects this file provides.
* @param {!Array<string>} requires An array of strings with
* the names of the objects this file requires.
- * @param {boolean=} opt_isModule Whether this dependency must be loaded as
- * a module as declared by goog.module.
+ * @param {boolean|!Object<string>=} opt_loadFlags Parameters indicating
+ * how the file must be loaded. The boolean 'true' is equivalent
+ * to {'module': 'goog'} for backwards-compatibility. Valid properties
+ * and values include {'module': 'goog'} and {'lang': 'es6'}.
*/
-goog.addDependency = function(relPath, provides, requires, opt_isModule) {
+goog.addDependency = function(relPath, provides, requires, opt_loadFlags) {
if (goog.DEPENDENCIES_ENABLED) {
var provide, require;
var path = relPath.replace(/\\/g, '/');
var deps = goog.dependencies_;
+ if (!opt_loadFlags || typeof opt_loadFlags === 'boolean') {
+ opt_loadFlags = opt_loadFlags ? {'module': 'goog'} : {};
+ }
for (var i = 0; provide = provides[i]; i++) {
deps.nameToPath[provide] = path;
- deps.pathIsModule[path] = !!opt_isModule;
+ deps.pathIsModule[path] = opt_loadFlags['module'] == 'goog';
}
for (var j = 0; require = requires[j]; j++) {
if (!(path in deps.requires)) {
@@ -612,9 +622,10 @@ goog.addDependency = function(relPath, provides, requires, opt_isModule) {
// will not load until some point after the current script. If a namespace is
// needed at runtime, it needs to be defined in a previous script, or loaded via
// require() with its registered dependencies.
-// User-defined namespaces may need their own deps file. See http://go/js_deps,
-// http://go/genjsdeps, or, externally, DepsWriter.
-// https://developers.google.com/closure/library/docs/depswriter
+//
+// User-defined namespaces may need their own deps file. For a reference on
+// creating a deps file, see:
+// Externally: https://developers.google.com/closure/library/docs/depswriter
//
// Because of legacy clients, the DOM loader can't be easily removed from
// base.js. Work is being done to make it disableable or replaceable for
@@ -810,7 +821,6 @@ goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
if (goog.DEPENDENCIES_ENABLED) {
-
/**
* This object is used to keep track of dependencies and other data that is
* used for loading scripts.
@@ -825,18 +835,18 @@ if (goog.DEPENDENCIES_ENABLED) {
* }}
*/
goog.dependencies_ = {
- pathIsModule: {}, // 1 to 1
+ pathIsModule: {}, // 1 to 1
- nameToPath: {}, // 1 to 1
+ nameToPath: {}, // 1 to 1
- requires: {}, // 1 to many
+ requires: {}, // 1 to many
// Used when resolving dependencies to prevent us from visiting file twice.
visited: {},
- written: {}, // Used to keep track of script files we have written.
+ written: {}, // Used to keep track of script files we have written.
- deferred: {} // Used to track deferred module evaluations in old IEs
+ deferred: {} // Used to track deferred module evaluations in old IEs
};
@@ -848,8 +858,7 @@ if (goog.DEPENDENCIES_ENABLED) {
goog.inHtmlDocument_ = function() {
/** @type {Document} */
var doc = goog.global.document;
- return typeof doc != 'undefined' &&
- 'write' in doc; // XULDocument misses write.
+ return doc != null && 'write' in doc; // XULDocument misses write.
};
@@ -890,8 +899,8 @@ if (goog.DEPENDENCIES_ENABLED) {
* @private
*/
goog.importScript_ = function(src, opt_sourceText) {
- var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
- goog.writeScriptTag_;
+ var importScript =
+ goog.global.CLOSURE_IMPORT_SCRIPT || goog.writeScriptTag_;
if (importScript(src, opt_sourceText)) {
goog.dependencies_.written[src] = true;
}
@@ -899,8 +908,8 @@ if (goog.DEPENDENCIES_ENABLED) {
/** @const @private {boolean} */
- goog.IS_OLD_IE_ = !!(!goog.global.atob && goog.global.document &&
- goog.global.document.all);
+ goog.IS_OLD_IE_ =
+ !!(!goog.global.atob && goog.global.document && goog.global.document.all);
/**
@@ -935,9 +944,8 @@ if (goog.DEPENDENCIES_ENABLED) {
if (!goog.LOAD_MODULE_USING_EVAL || !goog.isDef(goog.global.JSON)) {
return '' +
'goog.loadModule(function(exports) {' +
- '"use strict";' +
- scriptText +
- '\n' + // terminate any trailing single line comment.
+ '"use strict";' + scriptText +
+ '\n' + // terminate any trailing single line comment.
';return exports' +
'});' +
'\n//# sourceURL=' + srcUrl + '\n';
@@ -996,8 +1004,7 @@ if (goog.DEPENDENCIES_ENABLED) {
* @private
*/
goog.maybeProcessDeferredDep_ = function(name) {
- if (goog.isDeferredModule_(name) &&
- goog.allDepsAreAvailable_(name)) {
+ if (goog.isDeferredModule_(name) && goog.allDepsAreAvailable_(name)) {
var path = goog.getPathFromDeps_(name);
goog.maybeProcessDeferredPath_(goog.basePath + path);
}
@@ -1053,6 +1060,33 @@ if (goog.DEPENDENCIES_ENABLED) {
/**
+ * Load a goog.module from the provided URL. This is not a general purpose
+ * code loader and does not support late loading code, that is it should only
+ * be used during page load. This method exists to support unit tests and
+ * "debug" loaders that would otherwise have inserted script tags. Under the
+ * hood this needs to use a synchronous XHR and is not recommeneded for
+ * production code.
+ *
+ * The module's goog.requires must have already been satisified; an exception
+ * will be thrown if this is not the case. This assumption is that no
+ * "deps.js" file exists, so there is no way to discover and locate the
+ * module-to-be-loaded's dependencies and no attempt is made to do so.
+ *
+ * There should only be one attempt to load a module. If
+ * "goog.loadModuleFromUrl" is called for an already loaded module, an
+ * exception will be throw.
+ *
+ * @param {string} url The URL from which to attempt to load the goog.module.
+ */
+ goog.loadModuleFromUrl = function(url) {
+ // Because this executes synchronously, we don't need to do any additional
+ // bookkeeping. When "goog.loadModule" the namespace will be marked as
+ // having been provided which is sufficient.
+ goog.retrieveAndExecModule_(url);
+ };
+
+
+ /**
* @param {function(?):?|string} moduleDef The module definition.
*/
goog.loadModule = function(moduleDef) {
@@ -1063,7 +1097,10 @@ if (goog.DEPENDENCIES_ENABLED) {
// of the module.
var previousState = goog.moduleLoaderState_;
try {
- goog.moduleLoaderState_ = {moduleName: undefined};
+ goog.moduleLoaderState_ = {
+ moduleName: undefined,
+ declareLegacyNamespace: false
+ };
var exports;
if (goog.isFunction(moduleDef)) {
exports = moduleDef.call(goog.global, {});
@@ -1095,6 +1132,10 @@ if (goog.DEPENDENCIES_ENABLED) {
/**
* @private @const {function(string):?}
+ *
+ * The new type inference warns because this function has no formal
+ * parameters, but its jsdoc says that it takes one argument.
+ * (The argument is used via arguments[0], but NTI does not detect this.)
* @suppress {newCheckTypes}
*/
goog.loadModuleFromSource_ = function() {
@@ -1118,7 +1159,8 @@ if (goog.DEPENDENCIES_ENABLED) {
*/
goog.writeScriptSrcNode_ = function(src) {
goog.global.document.write(
- '<script type="text/javascript" src="' + src + '"></' + 'script>');
+ '<script type="text/javascript" src="' + src + '"></' +
+ 'script>');
};
@@ -1143,7 +1185,8 @@ if (goog.DEPENDENCIES_ENABLED) {
goog.appendScriptSrcNode_ = function(src) {
/** @type {Document} */
var doc = goog.global.document;
- var scriptEl = doc.createElement('script');
+ var scriptEl =
+ /** @type {HTMLScriptElement} */ (doc.createElement('script'));
scriptEl.type = 'text/javascript';
scriptEl.src = src;
scriptEl.defer = false;
@@ -1163,7 +1206,7 @@ if (goog.DEPENDENCIES_ENABLED) {
*/
goog.writeScriptTag_ = function(src, opt_sourceText) {
if (goog.inHtmlDocument_()) {
- /** @type {Document} */
+ /** @type {!HTMLDocument} */
var doc = goog.global.document;
// If the user tries to require a new symbol after document load,
@@ -1197,14 +1240,14 @@ if (goog.DEPENDENCIES_ENABLED) {
var state = " onreadystatechange='goog.onScriptLoad_(this, " +
++goog.lastNonModuleScriptIndex_ + ")' ";
doc.write(
- '<script type="text/javascript" src="' +
- src + '"' + state + '></' + 'script>');
+ '<script type="text/javascript" src="' + src + '"' + state +
+ '></' +
+ 'script>');
}
} else {
doc.write(
- '<script type="text/javascript">' +
- opt_sourceText +
- '</' + 'script>');
+ '<script type="text/javascript">' + opt_sourceText + '</' +
+ 'script>');
}
return true;
} else {
@@ -1351,8 +1394,9 @@ goog.normalizePath_ = function(path) {
while (i < components.length) {
if (components[i] == '.') {
components.splice(i, 1);
- } else if (i && components[i] == '..' &&
- components[i - 1] && components[i - 1] != '..') {
+ } else if (
+ i && components[i] == '..' && components[i - 1] &&
+ components[i - 1] != '..') {
components.splice(--i, 2);
} else {
i++;
@@ -1394,8 +1438,8 @@ goog.retrieveAndExecModule_ = function(src) {
// console doesn't auto-canonicalize XHR loads as it does <script> srcs.
src = goog.normalizePath_(src);
- var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
- goog.writeScriptTag_;
+ var importScript =
+ goog.global.CLOSURE_IMPORT_SCRIPT || goog.writeScriptTag_;
var scriptText = goog.loadFileSync_(src);
@@ -1423,7 +1467,7 @@ goog.retrieveAndExecModule_ = function(src) {
/**
* This is a "fixed" version of the typeof operator. It differs from the typeof
* operator in such a way that null returns 'null' and arrays return 'array'.
- * @param {*} value The value to get the type of.
+ * @param {?} value The value to get the type of.
* @return {string} The name of the type.
*/
goog.typeOf = function(value) {
@@ -1433,7 +1477,7 @@ goog.typeOf = function(value) {
// Check these first, so we can avoid calling Object.prototype.toString if
// possible.
//
- // IE improperly marshals tyepof across execution contexts, but a
+ // IE improperly marshals typeof across execution contexts, but a
// cross-context object will still return false for "instanceof Object".
if (value instanceof Array) {
return 'array';
@@ -1445,7 +1489,7 @@ goog.typeOf = function(value) {
// value, the compiler requires the value be cast to type Object,
// even though the ECMA spec explicitly allows it.
var className = Object.prototype.toString.call(
- /** @type {Object} */ (value));
+ /** @type {!Object} */ (value));
// In Firefox 3.6, attempting to access iframe window objects' length
// property throws an NS_ERROR_FAILURE, so we need to special-case it
// here.
@@ -1476,11 +1520,11 @@ goog.typeOf = function(value) {
// boundaries (not iframe though) so we have to do object detection
// for this edge case.
typeof value.length == 'number' &&
- typeof value.splice != 'undefined' &&
- typeof value.propertyIsEnumerable != 'undefined' &&
- !value.propertyIsEnumerable('splice')
+ typeof value.splice != 'undefined' &&
+ typeof value.propertyIsEnumerable != 'undefined' &&
+ !value.propertyIsEnumerable('splice')
- )) {
+ )) {
return 'array';
}
// HACK: There is still an array case that fails.
@@ -1498,9 +1542,9 @@ goog.typeOf = function(value) {
// 'function'. However, if the object has a call property, it is a
// function.
if ((className == '[object Function]' ||
- typeof value.call != 'undefined' &&
- typeof value.propertyIsEnumerable != 'undefined' &&
- !value.propertyIsEnumerable('call'))) {
+ typeof value.call != 'undefined' &&
+ typeof value.propertyIsEnumerable != 'undefined' &&
+ !value.propertyIsEnumerable('call'))) {
return 'function';
}
@@ -1676,7 +1720,7 @@ goog.removeUid = function(obj) {
// In IE, DOM nodes are not instances of Object and throw an exception if we
// try to delete. Instead we try to use removeAttribute.
- if ('removeAttribute' in obj) {
+ if (obj !== null && 'removeAttribute' in obj) {
obj.removeAttribute(goog.UID_PROPERTY_);
}
/** @preserveTry */
@@ -1799,9 +1843,7 @@ goog.bindJs_ = function(fn, selfObj, var_args) {
};
} else {
- return function() {
- return fn.apply(selfObj, arguments);
- };
+ return function() { return fn.apply(selfObj, arguments); };
}
};
@@ -1898,10 +1940,11 @@ goog.mixin = function(target, source) {
* between midnight, January 1, 1970 and the current time.
*/
goog.now = (goog.TRUSTED_SITE && Date.now) || (function() {
- // Unary plus operator converts its operand to a number which in the case of
- // a date is done by calling getTime().
- return +new Date();
-});
+ // Unary plus operator converts its operand to a number which in
+ // the case of
+ // a date is done by calling getTime().
+ return +new Date();
+ });
/**
@@ -1935,7 +1978,8 @@ goog.globalEval = function(script) {
} else {
/** @type {Document} */
var doc = goog.global.document;
- var scriptElt = doc.createElement('SCRIPT');
+ var scriptElt =
+ /** @type {!HTMLScriptElement} */ (doc.createElement('SCRIPT'));
scriptElt.type = 'text/javascript';
scriptElt.defer = false;
// Note(user): can't use .innerHTML since "t('<test>')" will fail and
@@ -1998,7 +2042,7 @@ goog.cssNameMappingStyle_;
* var x = goog.getCssName('foo');
* var y = goog.getCssName(this.baseClass, 'active');
* becomes:
- * var x= 'foo';
+ * var x = 'foo';
* var y = this.baseClass + '-active';
*
* If one argument is passed it will be processed, if two are passed only the
@@ -2027,12 +2071,10 @@ goog.getCssName = function(className, opt_modifier) {
var rename;
if (goog.cssNameMapping_) {
- rename = goog.cssNameMappingStyle_ == 'BY_WHOLE' ?
- getMapping : renameByParts;
+ rename =
+ goog.cssNameMappingStyle_ == 'BY_WHOLE' ? getMapping : renameByParts;
} else {
- rename = function(a) {
- return a;
- };
+ rename = function(a) { return a; };
}
if (opt_modifier) {
@@ -2106,6 +2148,10 @@ if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
* var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});
* </code>
*
+ * This function produces a string which should be treated as plain text. Use
+ * {@link goog.html.SafeHtmlFormatter} in conjunction with goog.getMsg to
+ * produce SafeHtml.
+ *
* @param {string} str Translatable string, places holders in the form {$foo}.
* @param {Object<string, string>=} opt_values Maps place holder name to value.
* @return {string} message with placeholders filled.
@@ -2113,7 +2159,8 @@ if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
goog.getMsg = function(str, opt_values) {
if (opt_values) {
str = str.replace(/\{\$([^}]+)}/g, function(match, key) {
- return key in opt_values ? opt_values[key] : match;
+ return (opt_values != null && key in opt_values) ? opt_values[key] :
+ match;
});
}
return str;
@@ -2201,7 +2248,7 @@ goog.exportProperty = function(object, publicName, symbol) {
*/
goog.inherits = function(childCtor, parentCtor) {
/** @constructor */
- function tempCtor() {};
+ function tempCtor() {}
tempCtor.prototype = parentCtor.prototype;
childCtor.superClass_ = parentCtor.prototype;
childCtor.prototype = new tempCtor();
@@ -2266,9 +2313,10 @@ goog.base = function(me, opt_methodName, var_args) {
var caller = arguments.callee.caller;
if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) {
- throw Error('arguments.caller not defined. goog.base() cannot be used ' +
- 'with strict mode code. See ' +
- 'http://www.ecma-international.org/ecma-262/5.1/#sec-C');
+ throw Error(
+ 'arguments.caller not defined. goog.base() cannot be used ' +
+ 'with strict mode code. See ' +
+ 'http://www.ecma-international.org/ecma-262/5.1/#sec-C');
}
if (caller.superClass_) {
@@ -2289,8 +2337,8 @@ goog.base = function(me, opt_methodName, var_args) {
args[i - 2] = arguments[i];
}
var foundCaller = false;
- for (var ctor = me.constructor;
- ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
+ for (var ctor = me.constructor; ctor;
+ ctor = ctor.superClass_ && ctor.superClass_.constructor) {
if (ctor.prototype[opt_methodName] === caller) {
foundCaller = true;
} else if (foundCaller) {
@@ -2324,6 +2372,9 @@ goog.base = function(me, opt_methodName, var_args) {
* (e.g. "var Timer = goog.Timer").
*/
goog.scope = function(fn) {
+ if (goog.isInModuleLoader_()) {
+ throw Error('goog.scope is not supported within a goog.module.');
+ }
fn.call(goog.global);
};
@@ -2343,7 +2394,6 @@ if (!COMPILED) {
}
-
//==============================================================================
// goog.defineClass implementation
//==============================================================================
@@ -2404,10 +2454,10 @@ goog.defineClass = function(superClass, def) {
/**
- * @typedef {
- * !Object|
- * {constructor:!Function}|
- * {constructor:!Function, statics:(Object|function(Function):void)}}
+ * @typedef {{
+ * constructor: (!Function|undefined),
+ * statics: (Object|undefined|function(Function):void)
+ * }}
* @suppress {missingProvide}
*/
goog.defineClass.ClassDescriptor;
@@ -2466,13 +2516,8 @@ goog.defineClass.createSealingConstructor_ = function(ctr, superClass) {
* @const
*/
goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [
- 'constructor',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'toLocaleString',
- 'toString',
- 'valueOf'
+ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
+ 'toLocaleString', 'toString', 'valueOf'
];
@@ -2565,12 +2610,6 @@ ol.DEFAULT_RASTER_REPROJECTION_ERROR_THRESHOLD = 0.5;
/**
- * @define {number} Default high water mark.
- */
-ol.DEFAULT_TILE_CACHE_HIGH_WATER_MARK = 2048;
-
-
-/**
* @define {number} Default tile size.
*/
ol.DEFAULT_TILE_SIZE = 256;
@@ -2791,14 +2830,6 @@ ol.WEBGL_EXTENSIONS; // value is set in `ol.has`
* var child = new ChildClass('a', 'b', 'see');
* child.foo(); // This works.
*
- * In addition, a superclass' implementation of a method can be invoked as
- * follows:
- *
- * ChildClass.prototype.foo = function(a) {
- * ChildClass.base(this, 'foo', a);
- * // Other code here.
- * };
- *
* @param {!Function} childCtor Child constructor.
* @param {!Function} parentCtor Parent constructor.
* @function
@@ -2816,27 +2847,8 @@ ol.inherits =
*/
ol.nullFunction = function() {};
-// FIXME factor out common code between usedTiles and wantedTiles
-
-goog.provide('ol.PostRenderFunction');
-goog.provide('ol.PreRenderFunction');
-
-/**
- * @typedef {function(ol.Map, ?olx.FrameState): boolean}
- */
-ol.PostRenderFunction;
-
-
-/**
- * Function to perform manipulations before rendering. This function is called
- * with the {@link ol.Map} as first and an optional {@link olx.FrameState} as
- * second argument. Return `true` to keep this function for the next frame,
- * `false` to remove it.
- * @typedef {function(ol.Map, ?olx.FrameState): boolean}
- * @api
- */
-ol.PreRenderFunction;
+ol.global = Function('return this')();
// Copyright 2009 The Closure Library Authors. All Rights Reserved.
//
@@ -3032,7 +3044,7 @@ goog.string.endsWith = function(str, suffix) {
*/
goog.string.caseInsensitiveStartsWith = function(str, prefix) {
return goog.string.caseInsensitiveCompare(
- prefix, str.substr(0, prefix.length)) == 0;
+ prefix, str.substr(0, prefix.length)) == 0;
};
@@ -3045,7 +3057,8 @@ goog.string.caseInsensitiveStartsWith = function(str, prefix) {
*/
goog.string.caseInsensitiveEndsWith = function(str, suffix) {
return goog.string.caseInsensitiveCompare(
- suffix, str.substr(str.length - suffix.length, suffix.length)) == 0;
+ suffix, str.substr(str.length - suffix.length, suffix.length)) ==
+ 0;
};
@@ -3081,7 +3094,7 @@ goog.string.subs = function(str, var_args) {
returnString += splitParts.shift() + subsArguments.shift();
}
- return returnString + splitParts.join('%s'); // Join unused '%s'
+ return returnString + splitParts.join('%s'); // Join unused '%s'
};
@@ -3220,7 +3233,7 @@ goog.string.isSpace = function(ch) {
*/
goog.string.isUnicodeChar = function(ch) {
return ch.length == 1 && ch >= ' ' && ch <= '~' ||
- ch >= '\u0080' && ch <= '\uFFFD';
+ ch >= '\u0080' && ch <= '\uFFFD';
};
@@ -3276,8 +3289,8 @@ goog.string.normalizeSpaces = function(str) {
* @return {string} Copy of the string with normalized breaking spaces.
*/
goog.string.collapseBreakingSpaces = function(str) {
- return str.replace(/[\t\r\n ]+/g, ' ').replace(
- /^[\t\r\n ]+|[\t\r\n ]+$/g, '');
+ return str.replace(/[\t\r\n ]+/g, ' ')
+ .replace(/^[\t\r\n ]+|[\t\r\n ]+$/g, '');
};
@@ -3286,11 +3299,10 @@ goog.string.collapseBreakingSpaces = function(str) {
* @param {string} str The string to trim.
* @return {string} A trimmed copy of {@code str}.
*/
-goog.string.trim = (goog.TRUSTED_SITE && String.prototype.trim) ?
- function(str) {
+goog.string.trim =
+ (goog.TRUSTED_SITE && String.prototype.trim) ? function(str) {
return str.trim();
- } :
- function(str) {
+ } : function(str) {
// Since IE doesn't include non-breaking-space (0xa0) in their \s
// character class (as required by section 7.2 of the ECMAScript spec),
// we explicitly include it in the regexp to enforce consistent
@@ -3350,31 +3362,18 @@ goog.string.caseInsensitiveCompare = function(str1, str2) {
/**
- * Regular expression used for splitting a string into substrings of fractional
- * numbers, integers, and non-numeric characters.
- * @type {RegExp}
- * @private
- */
-goog.string.numerateCompareRegExp_ = /(\.\d+)|(\d+)|(\D+)/g;
-
-
-/**
- * String comparison function that handles numbers in a way humans might expect.
- * Using this function, the string "File 2.jpg" sorts before "File 10.jpg". The
- * comparison is mostly case-insensitive, though strings that are identical
- * except for case are sorted with the upper-case strings before lower-case.
- *
- * This comparison function is significantly slower (about 500x) than either
- * the default or the case-insensitive compare. It should not be used in
- * time-critical code, but should be fast enough to sort several hundred short
- * strings (like filenames) with a reasonable delay.
+ * Compares two strings interpreting their numeric substrings as numbers.
*
- * @param {string} str1 The string to compare in a numerically sensitive way.
- * @param {string} str2 The string to compare {@code str1} to.
- * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than
- * 0 if str1 > str2.
+ * @param {string} str1 First string.
+ * @param {string} str2 Second string.
+ * @param {!RegExp} tokenizerRegExp Splits a string into substrings of
+ * non-negative integers, non-numeric characters and optionally fractional
+ * numbers starting with a decimal point.
+ * @return {number} Negative if str1 < str2, 0 is str1 == str2, positive if
+ * str1 > str2.
+ * @private
*/
-goog.string.numerateCompare = function(str1, str2) {
+goog.string.numberAwareCompare_ = function(str1, str2, tokenizerRegExp) {
if (str1 == str2) {
return 0;
}
@@ -3387,8 +3386,8 @@ goog.string.numerateCompare = function(str1, str2) {
// Using match to split the entire string ahead of time turns out to be faster
// for most inputs than using RegExp.exec or iterating over each character.
- var tokens1 = str1.toLowerCase().match(goog.string.numerateCompareRegExp_);
- var tokens2 = str2.toLowerCase().match(goog.string.numerateCompareRegExp_);
+ var tokens1 = str1.toLowerCase().match(tokenizerRegExp);
+ var tokens2 = str2.toLowerCase().match(tokenizerRegExp);
var count = Math.min(tokens1.length, tokens2.length);
@@ -3398,7 +3397,6 @@ goog.string.numerateCompare = function(str1, str2) {
// Compare pairs of tokens, returning if one token sorts before the other.
if (a != b) {
-
// Only if both tokens are integers is a special comparison required.
// Decimal numbers are sorted as strings (e.g., '.09' < '.1').
var num1 = parseInt(a, 10);
@@ -3418,13 +3416,62 @@ goog.string.numerateCompare = function(str1, str2) {
}
// The two strings must be equivalent except for case (perfect equality is
- // tested at the head of the function.) Revert to default ASCII-betical string
- // comparison to stablize the sort.
+ // tested at the head of the function.) Revert to default ASCII string
+ // comparison to stabilize the sort.
return str1 < str2 ? -1 : 1;
};
/**
+ * String comparison function that handles non-negative integer numbers in a
+ * way humans might expect. Using this function, the string 'File 2.jpg' sorts
+ * before 'File 10.jpg', and 'Version 1.9' before 'Version 1.10'. The comparison
+ * is mostly case-insensitive, though strings that are identical except for case
+ * are sorted with the upper-case strings before lower-case.
+ *
+ * This comparison function is up to 50x slower than either the default or the
+ * case-insensitive compare. It should not be used in time-critical code, but
+ * should be fast enough to sort several hundred short strings (like filenames)
+ * with a reasonable delay.
+ *
+ * @param {string} str1 The string to compare in a numerically sensitive way.
+ * @param {string} str2 The string to compare {@code str1} to.
+ * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than
+ * 0 if str1 > str2.
+ */
+goog.string.intAwareCompare = function(str1, str2) {
+ return goog.string.numberAwareCompare_(str1, str2, /\d+|\D+/g);
+};
+
+
+/**
+ * String comparison function that handles non-negative integer and fractional
+ * numbers in a way humans might expect. Using this function, the string
+ * 'File 2.jpg' sorts before 'File 10.jpg', and '3.14' before '3.2'. Equivalent
+ * to {@link goog.string.intAwareCompare} apart from the way how it interprets
+ * dots.
+ *
+ * @param {string} str1 The string to compare in a numerically sensitive way.
+ * @param {string} str2 The string to compare {@code str1} to.
+ * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than
+ * 0 if str1 > str2.
+ */
+goog.string.floatAwareCompare = function(str1, str2) {
+ return goog.string.numberAwareCompare_(str1, str2, /\d+|\.\d+|\D+/g);
+};
+
+
+/**
+ * Alias for {@link goog.string.floatAwareCompare}.
+ *
+ * @param {string} str1
+ * @param {string} str2
+ * @return {number}
+ */
+goog.string.numerateCompare = goog.string.floatAwareCompare;
+
+
+/**
* URL-encodes a string
* @param {*} str The string to url-encode.
* @return {string} An encoded copy of {@code str} that is safe for urls.
@@ -3506,11 +3553,11 @@ goog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {
if (opt_isLikelyToContainHtmlChars) {
str = str.replace(goog.string.AMP_RE_, '&amp;')
- .replace(goog.string.LT_RE_, '&lt;')
- .replace(goog.string.GT_RE_, '&gt;')
- .replace(goog.string.QUOT_RE_, '&quot;')
- .replace(goog.string.SINGLE_QUOTE_RE_, '&#39;')
- .replace(goog.string.NULL_RE_, '&#0;');
+ .replace(goog.string.LT_RE_, '&lt;')
+ .replace(goog.string.GT_RE_, '&gt;')
+ .replace(goog.string.QUOT_RE_, '&quot;')
+ .replace(goog.string.SINGLE_QUOTE_RE_, '&#39;')
+ .replace(goog.string.NULL_RE_, '&#0;');
if (goog.string.DETECT_DOUBLE_ESCAPING) {
str = str.replace(goog.string.E_RE_, '&#101;');
}
@@ -3609,9 +3656,8 @@ goog.string.E_RE_ = /e/g;
* @const {!RegExp}
* @private
*/
-goog.string.ALL_RE_ = (goog.string.DETECT_DOUBLE_ESCAPING ?
- /[\x00&<>"'e]/ :
- /[\x00&<>"']/);
+goog.string.ALL_RE_ =
+ (goog.string.DETECT_DOUBLE_ESCAPING ? /[\x00&<>"'e]/ : /[\x00&<>"']/);
/**
@@ -3834,8 +3880,8 @@ goog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {
* middle as possible.
* @return {string} A truncated copy of {@code str}.
*/
-goog.string.truncateMiddle = function(str, chars,
- opt_protectEscapedCharacters, opt_trailingChars) {
+goog.string.truncateMiddle = function(
+ str, chars, opt_protectEscapedCharacters, opt_trailingChars) {
if (opt_protectEscapedCharacters) {
str = goog.string.unescapeEntities(str);
}
@@ -3874,9 +3920,15 @@ goog.string.specialEscapeChars_ = {
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
- '\x0B': '\\x0B', // '\v' is not supported in JScript
+ '\x0B': '\\x0B', // '\v' is not supported in JScript
'"': '\\"',
- '\\': '\\\\'
+ '\\': '\\\\',
+ // To support the use case of embedding quoted strings inside of script
+ // tags, we have to make sure HTML comments and opening/closing script tags do
+ // not appear in the resulting string. The specific strings that must be
+ // escaped are documented at:
+ // http://www.w3.org/TR/html51/semantics.html#restrictions-for-contents-of-script-elements
+ '<': '\x3c'
};
@@ -3891,25 +3943,22 @@ goog.string.jsEscapeCache_ = {
/**
* Encloses a string in double quotes and escapes characters so that the
- * string is a valid JS string.
+ * string is a valid JS string. The resulting string is safe to embed in
+ * `<script>` tags as "<" is escaped.
* @param {string} s The string to quote.
* @return {string} A copy of {@code s} surrounded by double quotes.
*/
goog.string.quote = function(s) {
s = String(s);
- if (s.quote) {
- return s.quote();
- } else {
- var sb = ['"'];
- for (var i = 0; i < s.length; i++) {
- var ch = s.charAt(i);
- var cc = ch.charCodeAt(0);
- sb[i + 1] = goog.string.specialEscapeChars_[ch] ||
- ((cc > 31 && cc < 127) ? ch : goog.string.escapeChar(ch));
- }
- sb.push('"');
- return sb.join('');
- }
+ var sb = ['"'];
+ for (var i = 0; i < s.length; i++) {
+ var ch = s.charAt(i);
+ var cc = ch.charCodeAt(0);
+ sb[i + 1] = goog.string.specialEscapeChars_[ch] ||
+ ((cc > 31 && cc < 127) ? ch : goog.string.escapeChar(ch));
+ }
+ sb.push('"');
+ return sb.join('');
};
@@ -3955,7 +4004,7 @@ goog.string.escapeChar = function(c) {
}
} else {
rv = '\\u';
- if (cc < 4096) { // \u1000
+ if (cc < 4096) { // \u1000
rv += '0';
}
}
@@ -4053,8 +4102,9 @@ goog.string.removeAll = function(s, ss) {
* @return {string} A RegExp safe, escaped copy of {@code s}.
*/
goog.string.regExpEscape = function(s) {
- return String(s).replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
- replace(/\x08/g, '\\x08');
+ return String(s)
+ .replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1')
+ .replace(/\x08/g, '\\x08');
};
@@ -4065,14 +4115,12 @@ goog.string.regExpEscape = function(s) {
* @return {string} A string containing {@code length} repetitions of
* {@code string}.
*/
-goog.string.repeat = (String.prototype.repeat) ?
- function(string, length) {
- // The native method is over 100 times faster than the alternative.
- return string.repeat(length);
- } :
- function(string, length) {
- return new Array(length + 1).join(string);
- };
+goog.string.repeat = (String.prototype.repeat) ? function(string, length) {
+ // The native method is over 100 times faster than the alternative.
+ return string.repeat(length);
+} : function(string, length) {
+ return new Array(length + 1).join(string);
+};
/**
@@ -4141,7 +4189,7 @@ goog.string.buildString = function(var_args) {
goog.string.getRandomString = function() {
var x = 2147483648;
return Math.floor(Math.random() * x).toString(36) +
- Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);
+ Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);
};
@@ -4191,8 +4239,8 @@ goog.string.compareVersions = function(version1, version2) {
// qualifier is always higher than a subversion with any qualifier. Next,
// the qualifiers are compared as strings.
order = goog.string.compareElements_(v1CompNum, v2CompNum) ||
- goog.string.compareElements_(v1Comp[2].length == 0,
- v2Comp[2].length == 0) ||
+ goog.string.compareElements_(
+ v1Comp[2].length == 0, v2Comp[2].length == 0) ||
goog.string.compareElements_(v1Comp[2], v2Comp[2]);
// Stop as soon as an inequality is discovered.
} while (order == 0);
@@ -4318,9 +4366,8 @@ goog.string.isUpperCamelCase = function(str) {
* @return {string} The string in camelCase form.
*/
goog.string.toCamelCase = function(str) {
- return String(str).replace(/\-([a-z])/g, function(all, match) {
- return match.toUpperCase();
- });
+ return String(str).replace(
+ /\-([a-z])/g, function(all, match) { return match.toUpperCase(); });
};
@@ -4369,16 +4416,16 @@ goog.string.toSelectorCase = function(str) {
*/
goog.string.toTitleCase = function(str, opt_delimiters) {
var delimiters = goog.isString(opt_delimiters) ?
- goog.string.regExpEscape(opt_delimiters) : '\\s';
+ goog.string.regExpEscape(opt_delimiters) :
+ '\\s';
// For IE8, we need to prevent using an empty character set. Otherwise,
// incorrect matching will occur.
delimiters = delimiters ? '|[' + delimiters + ']+' : '';
var regexp = new RegExp('(^' + delimiters + ')([a-z])', 'g');
- return str.replace(regexp, function(all, p1, p2) {
- return p1 + p2.toUpperCase();
- });
+ return str.replace(
+ regexp, function(all, p1, p2) { return p1 + p2.toUpperCase(); });
};
@@ -4426,8 +4473,7 @@ goog.string.parseInt = function(value) {
if (goog.isString(value)) {
// If the string starts with '0x' or '-0x', parse as hex.
- return /^\s*-?0x/i.test(value) ?
- parseInt(value, 16) : parseInt(value, 10);
+ return /^\s*-?0x/i.test(value) ? parseInt(value, 16) : parseInt(value, 10);
}
return NaN;
@@ -4452,7 +4498,6 @@ goog.string.parseInt = function(value) {
* as zero.
* @return {!Array<string>} The string, split.
*/
-
goog.string.splitLimit = function(str, separator, limit) {
var parts = str.split(separator);
var returnVal = [];
@@ -4474,6 +4519,43 @@ goog.string.splitLimit = function(str, separator, limit) {
/**
+ * Finds the characters to the right of the last instance of any separator
+ *
+ * This function is similar to goog.string.path.baseName, except it can take a
+ * list of characters to split the string on. It will return the rightmost
+ * grouping of characters to the right of any separator as a left-to-right
+ * oriented string.
+ *
+ * @see goog.string.path.baseName
+ * @param {string} str The string
+ * @param {string|!Array<string>} separators A list of separator characters
+ * @return {string} The last part of the string with respect to the separators
+ */
+goog.string.lastComponent = function(str, separators) {
+ if (!separators) {
+ return str;
+ } else if (typeof separators == 'string') {
+ separators = [separators];
+ }
+
+ var lastSeparatorIndex = -1;
+ for (var i = 0; i < separators.length; i++) {
+ if (separators[i] == '') {
+ continue;
+ }
+ var currentSeparatorIndex = str.lastIndexOf(separators[i]);
+ if (currentSeparatorIndex > lastSeparatorIndex) {
+ lastSeparatorIndex = currentSeparatorIndex;
+ }
+ }
+ if (lastSeparatorIndex == -1) {
+ return str;
+ }
+ return str.slice(lastSeparatorIndex + 1);
+};
+
+
+/**
* Computes the Levenshtein edit distance between two strings.
* @param {string} a
* @param {string} b
@@ -4499,7 +4581,7 @@ goog.string.editDistance = function(a, b) {
v1[0] = i + 1;
for (var j = 0; j < b.length; j++) {
- var cost = a[i] != b[j];
+ var cost = Number(a[i] != b[j]);
// Cost for the substring is the minimum of adding one character, removing
// one character, or a swap.
v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);
@@ -4597,7 +4679,9 @@ goog.asserts.AssertionError.prototype.name = 'AssertionError';
* The default error handler.
* @param {!goog.asserts.AssertionError} e The exception to be handled.
*/
-goog.asserts.DEFAULT_ERROR_HANDLER = function(e) { throw e; };
+goog.asserts.DEFAULT_ERROR_HANDLER = function(e) {
+ throw e;
+};
/**
@@ -4617,8 +4701,8 @@ goog.asserts.errorHandler_ = goog.asserts.DEFAULT_ERROR_HANDLER;
* @throws {goog.asserts.AssertionError} When the value is not a number.
* @private
*/
-goog.asserts.doAssertFailure_ =
- function(defaultMessage, defaultArgs, givenMessage, givenArgs) {
+goog.asserts.doAssertFailure_ = function(
+ defaultMessage, defaultArgs, givenMessage, givenArgs) {
var message = 'Assertion failed';
if (givenMessage) {
message += ': ' + givenMessage;
@@ -4661,8 +4745,8 @@ goog.asserts.setErrorHandler = function(errorHandler) {
*/
goog.asserts.assert = function(condition, opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS && !condition) {
- goog.asserts.doAssertFailure_('', null, opt_message,
- Array.prototype.slice.call(arguments, 2));
+ goog.asserts.doAssertFailure_(
+ '', null, opt_message, Array.prototype.slice.call(arguments, 2));
}
return condition;
};
@@ -4688,9 +4772,10 @@ goog.asserts.assert = function(condition, opt_message, var_args) {
*/
goog.asserts.fail = function(opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS) {
- goog.asserts.errorHandler_(new goog.asserts.AssertionError(
- 'Failure' + (opt_message ? ': ' + opt_message : ''),
- Array.prototype.slice.call(arguments, 1)));
+ goog.asserts.errorHandler_(
+ new goog.asserts.AssertionError(
+ 'Failure' + (opt_message ? ': ' + opt_message : ''),
+ Array.prototype.slice.call(arguments, 1)));
}
};
@@ -4705,9 +4790,9 @@ goog.asserts.fail = function(opt_message, var_args) {
*/
goog.asserts.assertNumber = function(value, opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) {
- goog.asserts.doAssertFailure_('Expected number but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
+ goog.asserts.doAssertFailure_(
+ 'Expected number but got %s: %s.', [goog.typeOf(value), value],
+ opt_message, Array.prototype.slice.call(arguments, 2));
}
return /** @type {number} */ (value);
};
@@ -4723,9 +4808,9 @@ goog.asserts.assertNumber = function(value, opt_message, var_args) {
*/
goog.asserts.assertString = function(value, opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) {
- goog.asserts.doAssertFailure_('Expected string but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
+ goog.asserts.doAssertFailure_(
+ 'Expected string but got %s: %s.', [goog.typeOf(value), value],
+ opt_message, Array.prototype.slice.call(arguments, 2));
}
return /** @type {string} */ (value);
};
@@ -4742,9 +4827,9 @@ goog.asserts.assertString = function(value, opt_message, var_args) {
*/
goog.asserts.assertFunction = function(value, opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) {
- goog.asserts.doAssertFailure_('Expected function but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
+ goog.asserts.doAssertFailure_(
+ 'Expected function but got %s: %s.', [goog.typeOf(value), value],
+ opt_message, Array.prototype.slice.call(arguments, 2));
}
return /** @type {!Function} */ (value);
};
@@ -4760,8 +4845,8 @@ goog.asserts.assertFunction = function(value, opt_message, var_args) {
*/
goog.asserts.assertObject = function(value, opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) {
- goog.asserts.doAssertFailure_('Expected object but got %s: %s.',
- [goog.typeOf(value), value],
+ goog.asserts.doAssertFailure_(
+ 'Expected object but got %s: %s.', [goog.typeOf(value), value],
opt_message, Array.prototype.slice.call(arguments, 2));
}
return /** @type {!Object} */ (value);
@@ -4778,9 +4863,9 @@ goog.asserts.assertObject = function(value, opt_message, var_args) {
*/
goog.asserts.assertArray = function(value, opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) {
- goog.asserts.doAssertFailure_('Expected array but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
+ goog.asserts.doAssertFailure_(
+ 'Expected array but got %s: %s.', [goog.typeOf(value), value],
+ opt_message, Array.prototype.slice.call(arguments, 2));
}
return /** @type {!Array<?>} */ (value);
};
@@ -4797,9 +4882,9 @@ goog.asserts.assertArray = function(value, opt_message, var_args) {
*/
goog.asserts.assertBoolean = function(value, opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) {
- goog.asserts.doAssertFailure_('Expected boolean but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
+ goog.asserts.doAssertFailure_(
+ 'Expected boolean but got %s: %s.', [goog.typeOf(value), value],
+ opt_message, Array.prototype.slice.call(arguments, 2));
}
return /** @type {boolean} */ (value);
};
@@ -4815,11 +4900,11 @@ goog.asserts.assertBoolean = function(value, opt_message, var_args) {
* @throws {goog.asserts.AssertionError} When the value is not an Element.
*/
goog.asserts.assertElement = function(value, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && (!goog.isObject(value) ||
- value.nodeType != goog.dom.NodeType.ELEMENT)) {
- goog.asserts.doAssertFailure_('Expected Element but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
+ if (goog.asserts.ENABLE_ASSERTS &&
+ (!goog.isObject(value) || value.nodeType != goog.dom.NodeType.ELEMENT)) {
+ goog.asserts.doAssertFailure_(
+ 'Expected Element but got %s: %s.', [goog.typeOf(value), value],
+ opt_message, Array.prototype.slice.call(arguments, 2));
}
return /** @type {!Element} */ (value);
};
@@ -4831,7 +4916,7 @@ goog.asserts.assertElement = function(value, opt_message, var_args) {
*
* The compiler may tighten the type returned by this function.
*
- * @param {*} value The value to check.
+ * @param {?} value The value to check.
* @param {function(new: T, ...)} type A user-defined constructor.
* @param {string=} opt_message Error message in case of failure.
* @param {...*} var_args The items to substitute into the failure message.
@@ -4842,7 +4927,8 @@ goog.asserts.assertElement = function(value, opt_message, var_args) {
*/
goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) {
if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) {
- goog.asserts.doAssertFailure_('Expected instanceof %s but got %s.',
+ goog.asserts.doAssertFailure_(
+ 'Expected instanceof %s but got %s.',
[goog.asserts.getType_(type), goog.asserts.getType_(value)],
opt_message, Array.prototype.slice.call(arguments, 3));
}
@@ -5061,21 +5147,38 @@ ol.math.toRadians = function(angleInDegrees) {
return angleInDegrees * Math.PI / 180;
};
-goog.provide('ol.CenterConstraint');
-goog.provide('ol.CenterConstraintType');
-
-goog.require('ol.math');
-
+/**
+ * Returns the modulo of a / b, depending on the sign of b.
+ *
+ * @param {number} a Dividend.
+ * @param {number} b Divisor.
+ * @return {number} Modulo.
+ */
+ol.math.modulo = function(a, b) {
+ var r = a % b;
+ return r * b < 0 ? r + b : r;
+};
/**
- * @typedef {function((ol.Coordinate|undefined)): (ol.Coordinate|undefined)}
+ * Calculates the linearly interpolated value of x between a and b.
+ *
+ * @param {number} a Number
+ * @param {number} b Number
+ * @param {number} x Value to be interpolated.
+ * @return {number} Interpolated value.
*/
-ol.CenterConstraintType;
+ol.math.lerp = function(a, b, x) {
+ return a + x * (b - a);
+};
+
+goog.provide('ol.CenterConstraint');
+
+goog.require('ol.math');
/**
* @param {ol.Extent} extent Extent.
- * @return {ol.CenterConstraintType}
+ * @return {ol.CenterConstraintType} The constraint.
*/
ol.CenterConstraint.createExtent = function(extent) {
return (
@@ -5104,2608 +5207,957 @@ ol.CenterConstraint.none = function(center) {
return center;
};
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Utilities for manipulating arrays.
- *
- * @author arv@google.com (Erik Arvidsson)
- */
-
-
-goog.provide('goog.array');
-goog.provide('goog.array.ArrayLike');
-
-goog.require('goog.asserts');
-
-
-/**
- * @define {boolean} NATIVE_ARRAY_PROTOTYPES indicates whether the code should
- * rely on Array.prototype functions, if available.
- *
- * The Array.prototype functions can be defined by external libraries like
- * Prototype and setting this flag to false forces closure to use its own
- * goog.array implementation.
- *
- * If your javascript can be loaded by a third party site and you are wary about
- * relying on the prototype functions, specify
- * "--define goog.NATIVE_ARRAY_PROTOTYPES=false" to the JSCompiler.
- *
- * Setting goog.TRUSTED_SITE to false will automatically set
- * NATIVE_ARRAY_PROTOTYPES to false.
- */
-goog.define('goog.NATIVE_ARRAY_PROTOTYPES', goog.TRUSTED_SITE);
+goog.provide('ol.Constraints');
/**
- * @define {boolean} If true, JSCompiler will use the native implementation of
- * array functions where appropriate (e.g., {@code Array#filter}) and remove the
- * unused pure JS implementation.
+ * @constructor
+ * @param {ol.CenterConstraintType} centerConstraint Center constraint.
+ * @param {ol.ResolutionConstraintType} resolutionConstraint
+ * Resolution constraint.
+ * @param {ol.RotationConstraintType} rotationConstraint
+ * Rotation constraint.
*/
-goog.define('goog.array.ASSUME_NATIVE_FUNCTIONS', false);
+ol.Constraints = function(centerConstraint, resolutionConstraint, rotationConstraint) {
+ /**
+ * @type {ol.CenterConstraintType}
+ */
+ this.center = centerConstraint;
-/**
- * @typedef {Array|NodeList|Arguments|{length: number}}
- */
-goog.array.ArrayLike;
+ /**
+ * @type {ol.ResolutionConstraintType}
+ */
+ this.resolution = resolutionConstraint;
+ /**
+ * @type {ol.RotationConstraintType}
+ */
+ this.rotation = rotationConstraint;
-/**
- * Returns the last element in an array without removing it.
- * Same as goog.array.last.
- * @param {Array<T>|goog.array.ArrayLike} array The array.
- * @return {T} Last item in array.
- * @template T
- */
-goog.array.peek = function(array) {
- return array[array.length - 1];
};
-
-/**
- * Returns the last element in an array without removing it.
- * Same as goog.array.peek.
- * @param {Array<T>|goog.array.ArrayLike} array The array.
- * @return {T} Last item in array.
- * @template T
- */
-goog.array.last = goog.array.peek;
-
-
-/**
- * Reference to the original {@code Array.prototype}.
- * @private
- */
-goog.array.ARRAY_PROTOTYPE_ = Array.prototype;
-
-
-// NOTE(arv): Since most of the array functions are generic it allows you to
-// pass an array-like object. Strings have a length and are considered array-
-// like. However, the 'in' operator does not work on strings so we cannot just
-// use the array path even if the browser supports indexing into strings. We
-// therefore end up splitting the string.
+goog.provide('ol.object');
/**
- * Returns the index of the first element of an array with a specified value, or
- * -1 if the element is not present in the array.
- *
- * See {@link http://tinyurl.com/developer-mozilla-org-array-indexof}
+ * Polyfill for Object.assign(). Assigns enumerable and own properties from
+ * one or more source objects to a target object.
*
- * @param {Array<T>|goog.array.ArrayLike} arr The array to be searched.
- * @param {T} obj The object for which we are searching.
- * @param {number=} opt_fromIndex The index at which to start the search. If
- * omitted the search starts at index 0.
- * @return {number} The index of the first matching array element.
- * @template T
+ * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
+ * @param {!Object} target The target object.
+ * @param {...Object} var_sources The source object(s).
+ * @return {!Object} The modified target object.
*/
-goog.array.indexOf = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.indexOf) ?
- function(arr, obj, opt_fromIndex) {
- goog.asserts.assert(arr.length != null);
-
- return goog.array.ARRAY_PROTOTYPE_.indexOf.call(arr, obj, opt_fromIndex);
- } :
- function(arr, obj, opt_fromIndex) {
- var fromIndex = opt_fromIndex == null ?
- 0 : (opt_fromIndex < 0 ?
- Math.max(0, arr.length + opt_fromIndex) : opt_fromIndex);
-
- if (goog.isString(arr)) {
- // Array.prototype.indexOf uses === so only strings should be found.
- if (!goog.isString(obj) || obj.length != 1) {
- return -1;
- }
- return arr.indexOf(obj, fromIndex);
- }
-
- for (var i = fromIndex; i < arr.length; i++) {
- if (i in arr && arr[i] === obj)
- return i;
- }
- return -1;
- };
-
-
-/**
- * Returns the index of the last element of an array with a specified value, or
- * -1 if the element is not present in the array.
- *
- * See {@link http://tinyurl.com/developer-mozilla-org-array-lastindexof}
- *
- * @param {!Array<T>|!goog.array.ArrayLike} arr The array to be searched.
- * @param {T} obj The object for which we are searching.
- * @param {?number=} opt_fromIndex The index at which to start the search. If
- * omitted the search starts at the end of the array.
- * @return {number} The index of the last matching array element.
- * @template T
- */
-goog.array.lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.lastIndexOf) ?
- function(arr, obj, opt_fromIndex) {
- goog.asserts.assert(arr.length != null);
-
- // Firefox treats undefined and null as 0 in the fromIndex argument which
- // leads it to always return -1
- var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
- return goog.array.ARRAY_PROTOTYPE_.lastIndexOf.call(arr, obj, fromIndex);
- } :
- function(arr, obj, opt_fromIndex) {
- var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
-
- if (fromIndex < 0) {
- fromIndex = Math.max(0, arr.length + fromIndex);
- }
-
- if (goog.isString(arr)) {
- // Array.prototype.lastIndexOf uses === so only strings should be found.
- if (!goog.isString(obj) || obj.length != 1) {
- return -1;
- }
- return arr.lastIndexOf(obj, fromIndex);
- }
-
- for (var i = fromIndex; i >= 0; i--) {
- if (i in arr && arr[i] === obj)
- return i;
- }
- return -1;
- };
-
-
-/**
- * Calls a function for each element in an array. Skips holes in the array.
- * See {@link http://tinyurl.com/developer-mozilla-org-array-foreach}
- *
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array like object over
- * which to iterate.
- * @param {?function(this: S, T, number, ?): ?} f The function to call for every
- * element. This function takes 3 arguments (the element, the index and the
- * array). The return value is ignored.
- * @param {S=} opt_obj The object to be used as the value of 'this' within f.
- * @template T,S
- */
-goog.array.forEach = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.forEach) ?
- function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
-
- goog.array.ARRAY_PROTOTYPE_.forEach.call(arr, f, opt_obj);
- } :
- function(arr, f, opt_obj) {
- var l = arr.length; // must be fixed during loop... see docs
- var arr2 = goog.isString(arr) ? arr.split('') : arr;
- for (var i = 0; i < l; i++) {
- if (i in arr2) {
- f.call(opt_obj, arr2[i], i, arr);
- }
- }
- };
-
-
-/**
- * Calls a function for each element in an array, starting from the last
- * element rather than the first.
- *
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this: S, T, number, ?): ?} f The function to call for every
- * element. This function
- * takes 3 arguments (the element, the index and the array). The return
- * value is ignored.
- * @param {S=} opt_obj The object to be used as the value of 'this'
- * within f.
- * @template T,S
- */
-goog.array.forEachRight = function(arr, f, opt_obj) {
- var l = arr.length; // must be fixed during loop... see docs
- var arr2 = goog.isString(arr) ? arr.split('') : arr;
- for (var i = l - 1; i >= 0; --i) {
- if (i in arr2) {
- f.call(opt_obj, arr2[i], i, arr);
- }
+ol.object.assign = (typeof Object.assign === 'function') ? Object.assign : function(target, var_sources) {
+ if (target === undefined || target === null) {
+ throw new TypeError('Cannot convert undefined or null to object');
}
-};
-
-
-/**
- * Calls a function for each element in an array, and if the function returns
- * true adds the element to a new array.
- *
- * See {@link http://tinyurl.com/developer-mozilla-org-array-filter}
- *
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?):boolean} f The function to call for
- * every element. This function
- * takes 3 arguments (the element, the index and the array) and must
- * return a Boolean. If the return value is true the element is added to the
- * result array. If it is false the element is not included.
- * @param {S=} opt_obj The object to be used as the value of 'this'
- * within f.
- * @return {!Array<T>} a new array in which only elements that passed the test
- * are present.
- * @template T,S
- */
-goog.array.filter = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.filter) ?
- function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
-
- return goog.array.ARRAY_PROTOTYPE_.filter.call(arr, f, opt_obj);
- } :
- function(arr, f, opt_obj) {
- var l = arr.length; // must be fixed during loop... see docs
- var res = [];
- var resLength = 0;
- var arr2 = goog.isString(arr) ? arr.split('') : arr;
- for (var i = 0; i < l; i++) {
- if (i in arr2) {
- var val = arr2[i]; // in case f mutates arr2
- if (f.call(opt_obj, val, i, arr)) {
- res[resLength++] = val;
- }
- }
- }
- return res;
- };
-
-
-/**
- * Calls a function for each element in an array and inserts the result into a
- * new array.
- *
- * See {@link http://tinyurl.com/developer-mozilla-org-array-map}
- *
- * @param {Array<VALUE>|goog.array.ArrayLike} arr Array or array like object
- * over which to iterate.
- * @param {function(this:THIS, VALUE, number, ?): RESULT} f The function to call
- * for every element. This function takes 3 arguments (the element,
- * the index and the array) and should return something. The result will be
- * inserted into a new array.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within f.
- * @return {!Array<RESULT>} a new array with the results from f.
- * @template THIS, VALUE, RESULT
- */
-goog.array.map = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.map) ?
- function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
-
- return goog.array.ARRAY_PROTOTYPE_.map.call(arr, f, opt_obj);
- } :
- function(arr, f, opt_obj) {
- var l = arr.length; // must be fixed during loop... see docs
- var res = new Array(l);
- var arr2 = goog.isString(arr) ? arr.split('') : arr;
- for (var i = 0; i < l; i++) {
- if (i in arr2) {
- res[i] = f.call(opt_obj, arr2[i], i, arr);
- }
- }
- return res;
- };
-
-
-/**
- * Passes every element of an array into a function and accumulates the result.
- *
- * See {@link http://tinyurl.com/developer-mozilla-org-array-reduce}
- *
- * For example:
- * var a = [1, 2, 3, 4];
- * goog.array.reduce(a, function(r, v, i, arr) {return r + v;}, 0);
- * returns 10
- *
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {function(this:S, R, T, number, ?) : R} f The function to call for
- * every element. This function
- * takes 4 arguments (the function's previous result or the initial value,
- * the value of the current array element, the current array index, and the
- * array itself)
- * function(previousValue, currentValue, index, array).
- * @param {?} val The initial value to pass into the function on the first call.
- * @param {S=} opt_obj The object to be used as the value of 'this'
- * within f.
- * @return {R} Result of evaluating f repeatedly across the values of the array.
- * @template T,S,R
- */
-goog.array.reduce = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.reduce) ?
- function(arr, f, val, opt_obj) {
- goog.asserts.assert(arr.length != null);
- if (opt_obj) {
- f = goog.bind(f, opt_obj);
- }
- return goog.array.ARRAY_PROTOTYPE_.reduce.call(arr, f, val);
- } :
- function(arr, f, val, opt_obj) {
- var rval = val;
- goog.array.forEach(arr, function(val, index) {
- rval = f.call(opt_obj, rval, val, index, arr);
- });
- return rval;
- };
-
-
-/**
- * Passes every element of an array into a function and accumulates the result,
- * starting from the last element and working towards the first.
- *
- * See {@link http://tinyurl.com/developer-mozilla-org-array-reduceright}
- *
- * For example:
- * var a = ['a', 'b', 'c'];
- * goog.array.reduceRight(a, function(r, v, i, arr) {return r + v;}, '');
- * returns 'cba'
- *
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, R, T, number, ?) : R} f The function to call for
- * every element. This function
- * takes 4 arguments (the function's previous result or the initial value,
- * the value of the current array element, the current array index, and the
- * array itself)
- * function(previousValue, currentValue, index, array).
- * @param {?} val The initial value to pass into the function on the first call.
- * @param {S=} opt_obj The object to be used as the value of 'this'
- * within f.
- * @return {R} Object returned as a result of evaluating f repeatedly across the
- * values of the array.
- * @template T,S,R
- */
-goog.array.reduceRight = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.reduceRight) ?
- function(arr, f, val, opt_obj) {
- goog.asserts.assert(arr.length != null);
- if (opt_obj) {
- f = goog.bind(f, opt_obj);
- }
- return goog.array.ARRAY_PROTOTYPE_.reduceRight.call(arr, f, val);
- } :
- function(arr, f, val, opt_obj) {
- var rval = val;
- goog.array.forEachRight(arr, function(val, index) {
- rval = f.call(opt_obj, rval, val, index, arr);
- });
- return rval;
- };
-
-
-/**
- * Calls f for each element of an array. If any call returns true, some()
- * returns true (without checking the remaining elements). If all calls
- * return false, some() returns false.
- *
- * See {@link http://tinyurl.com/developer-mozilla-org-array-some}
- *
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
- * for every element. This function takes 3 arguments (the element, the
- * index and the array) and should return a boolean.
- * @param {S=} opt_obj The object to be used as the value of 'this'
- * within f.
- * @return {boolean} true if any element passes the test.
- * @template T,S
- */
-goog.array.some = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.some) ?
- function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
- return goog.array.ARRAY_PROTOTYPE_.some.call(arr, f, opt_obj);
- } :
- function(arr, f, opt_obj) {
- var l = arr.length; // must be fixed during loop... see docs
- var arr2 = goog.isString(arr) ? arr.split('') : arr;
- for (var i = 0; i < l; i++) {
- if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
- return true;
+ var output = Object(target);
+ for (var i = 1, ii = arguments.length; i < ii; ++i) {
+ var source = arguments[i];
+ if (source !== undefined && source !== null) {
+ for (var key in source) {
+ if (source.hasOwnProperty(key)) {
+ output[key] = source[key];
}
}
- return false;
- };
-
-
-/**
- * Call f for each element of an array. If all calls return true, every()
- * returns true. If any call returns false, every() returns false and
- * does not continue to check the remaining elements.
- *
- * See {@link http://tinyurl.com/developer-mozilla-org-array-every}
- *
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
- * for every element. This function takes 3 arguments (the element, the
- * index and the array) and should return a boolean.
- * @param {S=} opt_obj The object to be used as the value of 'this'
- * within f.
- * @return {boolean} false if any element fails the test.
- * @template T,S
- */
-goog.array.every = goog.NATIVE_ARRAY_PROTOTYPES &&
- (goog.array.ASSUME_NATIVE_FUNCTIONS ||
- goog.array.ARRAY_PROTOTYPE_.every) ?
- function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
-
- return goog.array.ARRAY_PROTOTYPE_.every.call(arr, f, opt_obj);
- } :
- function(arr, f, opt_obj) {
- var l = arr.length; // must be fixed during loop... see docs
- var arr2 = goog.isString(arr) ? arr.split('') : arr;
- for (var i = 0; i < l; i++) {
- if (i in arr2 && !f.call(opt_obj, arr2[i], i, arr)) {
- return false;
- }
- }
- return true;
- };
-
-
-/**
- * Counts the array elements that fulfill the predicate, i.e. for which the
- * callback function returns true. Skips holes in the array.
- *
- * @param {!(Array<T>|goog.array.ArrayLike)} arr Array or array like object
- * over which to iterate.
- * @param {function(this: S, T, number, ?): boolean} f The function to call for
- * every element. Takes 3 arguments (the element, the index and the array).
- * @param {S=} opt_obj The object to be used as the value of 'this' within f.
- * @return {number} The number of the matching elements.
- * @template T,S
- */
-goog.array.count = function(arr, f, opt_obj) {
- var count = 0;
- goog.array.forEach(arr, function(element, index, arr) {
- if (f.call(opt_obj, element, index, arr)) {
- ++count;
- }
- }, opt_obj);
- return count;
-};
-
-
-/**
- * Search an array for the first element that satisfies a given condition and
- * return that element.
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?) : boolean} f The function to call
- * for every element. This function takes 3 arguments (the element, the
- * index and the array) and should return a boolean.
- * @param {S=} opt_obj An optional "this" context for the function.
- * @return {T|null} The first array element that passes the test, or null if no
- * element is found.
- * @template T,S
- */
-goog.array.find = function(arr, f, opt_obj) {
- var i = goog.array.findIndex(arr, f, opt_obj);
- return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];
-};
-
-
-/**
- * Search an array for the first element that satisfies a given condition and
- * return its index.
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
- * every element. This function
- * takes 3 arguments (the element, the index and the array) and should
- * return a boolean.
- * @param {S=} opt_obj An optional "this" context for the function.
- * @return {number} The index of the first array element that passes the test,
- * or -1 if no element is found.
- * @template T,S
- */
-goog.array.findIndex = function(arr, f, opt_obj) {
- var l = arr.length; // must be fixed during loop... see docs
- var arr2 = goog.isString(arr) ? arr.split('') : arr;
- for (var i = 0; i < l; i++) {
- if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
- return i;
- }
- }
- return -1;
-};
-
-
-/**
- * Search an array (in reverse order) for the last element that satisfies a
- * given condition and return that element.
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?) : boolean} f The function to call
- * for every element. This function
- * takes 3 arguments (the element, the index and the array) and should
- * return a boolean.
- * @param {S=} opt_obj An optional "this" context for the function.
- * @return {T|null} The last array element that passes the test, or null if no
- * element is found.
- * @template T,S
- */
-goog.array.findRight = function(arr, f, opt_obj) {
- var i = goog.array.findIndexRight(arr, f, opt_obj);
- return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];
-};
-
-
-/**
- * Search an array (in reverse order) for the last element that satisfies a
- * given condition and return its index.
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?) : boolean} f The function to call
- * for every element. This function
- * takes 3 arguments (the element, the index and the array) and should
- * return a boolean.
- * @param {S=} opt_obj An optional "this" context for the function.
- * @return {number} The index of the last array element that passes the test,
- * or -1 if no element is found.
- * @template T,S
- */
-goog.array.findIndexRight = function(arr, f, opt_obj) {
- var l = arr.length; // must be fixed during loop... see docs
- var arr2 = goog.isString(arr) ? arr.split('') : arr;
- for (var i = l - 1; i >= 0; i--) {
- if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
- return i;
- }
- }
- return -1;
-};
-
-
-/**
- * Whether the array contains the given object.
- * @param {goog.array.ArrayLike} arr The array to test for the presence of the
- * element.
- * @param {*} obj The object for which to test.
- * @return {boolean} true if obj is present.
- */
-goog.array.contains = function(arr, obj) {
- return goog.array.indexOf(arr, obj) >= 0;
-};
-
-
-/**
- * Whether the array is empty.
- * @param {goog.array.ArrayLike} arr The array to test.
- * @return {boolean} true if empty.
- */
-goog.array.isEmpty = function(arr) {
- return arr.length == 0;
-};
-
-
-/**
- * Clears the array.
- * @param {goog.array.ArrayLike} arr Array or array like object to clear.
- */
-goog.array.clear = function(arr) {
- // For non real arrays we don't have the magic length so we delete the
- // indices.
- if (!goog.isArray(arr)) {
- for (var i = arr.length - 1; i >= 0; i--) {
- delete arr[i];
}
}
- arr.length = 0;
+ return output;
};
/**
- * Pushes an item into an array, if it's not already in the array.
- * @param {Array<T>} arr Array into which to insert the item.
- * @param {T} obj Value to add.
- * @template T
+ * Removes all properties from an object.
+ * @param {Object} object The object to clear.
*/
-goog.array.insert = function(arr, obj) {
- if (!goog.array.contains(arr, obj)) {
- arr.push(obj);
+ol.object.clear = function(object) {
+ for (var property in object) {
+ delete object[property];
}
};
/**
- * Inserts an object at the given index of the array.
- * @param {goog.array.ArrayLike} arr The array to modify.
- * @param {*} obj The object to insert.
- * @param {number=} opt_i The index at which to insert the object. If omitted,
- * treated as 0. A negative index is counted from the end of the array.
- */
-goog.array.insertAt = function(arr, obj, opt_i) {
- goog.array.splice(arr, opt_i, 0, obj);
-};
-
-
-/**
- * Inserts at the given index of the array, all elements of another array.
- * @param {goog.array.ArrayLike} arr The array to modify.
- * @param {goog.array.ArrayLike} elementsToAdd The array of elements to add.
- * @param {number=} opt_i The index at which to insert the object. If omitted,
- * treated as 0. A negative index is counted from the end of the array.
- */
-goog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) {
- goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd);
-};
-
-
-/**
- * Inserts an object into an array before a specified object.
- * @param {Array<T>} arr The array to modify.
- * @param {T} obj The object to insert.
- * @param {T=} opt_obj2 The object before which obj should be inserted. If obj2
- * is omitted or not found, obj is inserted at the end of the array.
- * @template T
+ * Get an array of property values from an object.
+ * @param {Object<K,V>} object The object from which to get the values.
+ * @return {!Array<V>} The property values.
+ * @template K,V
*/
-goog.array.insertBefore = function(arr, obj, opt_obj2) {
- var i;
- if (arguments.length == 2 || (i = goog.array.indexOf(arr, opt_obj2)) < 0) {
- arr.push(obj);
- } else {
- goog.array.insertAt(arr, obj, i);
+ol.object.getValues = function(object) {
+ var values = [];
+ for (var property in object) {
+ values.push(object[property]);
}
+ return values;
};
/**
- * Removes the first occurrence of a particular value from an array.
- * @param {Array<T>|goog.array.ArrayLike} arr Array from which to remove
- * value.
- * @param {T} obj Object to remove.
- * @return {boolean} True if an element was removed.
- * @template T
+ * Determine if an object has any properties.
+ * @param {Object} object The object to check.
+ * @return {boolean} The object is empty.
*/
-goog.array.remove = function(arr, obj) {
- var i = goog.array.indexOf(arr, obj);
- var rv;
- if ((rv = i >= 0)) {
- goog.array.removeAt(arr, i);
+ol.object.isEmpty = function(object) {
+ var property;
+ for (property in object) {
+ return false;
}
- return rv;
+ return !property;
};
-
/**
- * Removes from an array the element at index i
- * @param {goog.array.ArrayLike} arr Array or array like object from which to
- * remove value.
- * @param {number} i The index to remove.
- * @return {boolean} True if an element was removed.
+ * File for all typedefs used by the compiler, and referenced by JSDoc.
+ *
+ * These look like vars (or var properties), but in fact are simply identifiers
+ * for the Closure compiler. Originally they were included in the appropriate
+ * namespace file, but with the move away from Closure namespaces and towards
+ * self-contained standard modules are now all in this file.
+ * Unlike the other type definitions - enums and constructor functions - they
+ * are not code and so are not imported or exported. They are only referred to
+ * in type-defining comments used by the Closure compiler, and so should not
+ * appear in module code.
+ *
+ * When the code is converted to ES6 modules, the namespace structure will
+ * disappear, and these typedefs will have to be renamed accordingly, but the
+ * namespace structure is maintained for the present for backwards compatibility.
+ *
+ * In principle, typedefs should not have a `goog.provide` nor should files which
+ * refer to a typedef in comments need a `goog.require`. However, goog.provides
+ * are needed for 2 cases, both to prevent compiler errors/warnings:
+ * - the 1st two for specific errors
+ * - each sub-namespace needs at least one so the namespace is created when not
+ * used in the code, as when application code is compiled with the library.
*/
-goog.array.removeAt = function(arr, i) {
- goog.asserts.assert(arr.length != null);
+goog.provide('ol.Extent');
+goog.provide('ol.events.EventTargetLike');
- // use generic form of splice
- // splice returns the removed items and if successful the length of that
- // will be 1
- return goog.array.ARRAY_PROTOTYPE_.splice.call(arr, i, 1).length == 1;
-};
+goog.provide('ol.interaction.DragBoxEndConditionType');
+goog.provide('ol.proj.ProjectionLike');
+goog.provide('ol.raster.Operation');
+goog.provide('ol.style.AtlasBlock');
/**
- * Removes the first value that satisfies the given condition.
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?) : boolean} f The function to call
- * for every element. This function
- * takes 3 arguments (the element, the index and the array) and should
- * return a boolean.
- * @param {S=} opt_obj An optional "this" context for the function.
- * @return {boolean} True if an element was removed.
- * @template T,S
+ * @typedef {string|Array.<string>|ol.Attribution|Array.<ol.Attribution>}
+ * @api
*/
-goog.array.removeIf = function(arr, f, opt_obj) {
- var i = goog.array.findIndex(arr, f, opt_obj);
- if (i >= 0) {
- goog.array.removeAt(arr, i);
- return true;
- }
- return false;
-};
+ol.AttributionLike;
/**
- * Removes all values that satisfy the given condition.
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array
- * like object over which to iterate.
- * @param {?function(this:S, T, number, ?) : boolean} f The function to call
- * for every element. This function
- * takes 3 arguments (the element, the index and the array) and should
- * return a boolean.
- * @param {S=} opt_obj An optional "this" context for the function.
- * @return {number} The number of items removed
- * @template T,S
+ * @typedef {{fillStyle: ol.ColorLike}}
*/
-goog.array.removeAllIf = function(arr, f, opt_obj) {
- var removedCount = 0;
- goog.array.forEachRight(arr, function(val, index) {
- if (f.call(opt_obj, val, index, arr)) {
- if (goog.array.removeAt(arr, index)) {
- removedCount++;
- }
- }
- });
- return removedCount;
-};
+ol.CanvasFillState;
/**
- * Returns a new array that is the result of joining the arguments. If arrays
- * are passed then their items are added, however, if non-arrays are passed they
- * will be added to the return array as is.
- *
- * Note that ArrayLike objects will be added as is, rather than having their
- * items added.
- *
- * goog.array.concat([1, 2], [3, 4]) -> [1, 2, 3, 4]
- * goog.array.concat(0, [1, 2]) -> [0, 1, 2]
- * goog.array.concat([1, 2], null) -> [1, 2, null]
- *
- * There is bug in all current versions of IE (6, 7 and 8) where arrays created
- * in an iframe become corrupted soon (not immediately) after the iframe is
- * destroyed. This is common if loading data via goog.net.IframeIo, for example.
- * This corruption only affects the concat method which will start throwing
- * Catastrophic Errors (#-2147418113).
- *
- * See http://endoflow.com/scratch/corrupted-arrays.html for a test case.
- *
- * Internally goog.array should use this, so that all methods will continue to
- * work on these broken array objects.
+ * A function returning the canvas element (`{HTMLCanvasElement}`)
+ * used by the source as an image. The arguments passed to the function are:
+ * {@link ol.Extent} the image extent, `{number}` the image resolution,
+ * `{number}` the device pixel ratio, {@link ol.Size} the image size, and
+ * {@link ol.proj.Projection} the image projection. The canvas returned by
+ * this function is cached by the source. The this keyword inside the function
+ * references the {@link ol.source.ImageCanvas}.
*
- * @param {...*} var_args Items to concatenate. Arrays will have each item
- * added, while primitives and objects will be added as is.
- * @return {!Array<?>} The new resultant array.
+ * @typedef {function(this:ol.source.ImageCanvas, ol.Extent, number,
+ * number, ol.Size, ol.proj.Projection): HTMLCanvasElement}
+ * @api
*/
-goog.array.concat = function(var_args) {
- return goog.array.ARRAY_PROTOTYPE_.concat.apply(
- goog.array.ARRAY_PROTOTYPE_, arguments);
-};
+ol.CanvasFunctionType;
/**
- * Returns a new array that contains the contents of all the arrays passed.
- * @param {...!Array<T>} var_args
- * @return {!Array<T>}
- * @template T
+ * @typedef {{lineCap: string,
+ * lineDash: Array.<number>,
+ * lineJoin: string,
+ * lineWidth: number,
+ * miterLimit: number,
+ * strokeStyle: string}}
*/
-goog.array.join = function(var_args) {
- return goog.array.ARRAY_PROTOTYPE_.concat.apply(
- goog.array.ARRAY_PROTOTYPE_, arguments);
-};
+ol.CanvasStrokeState;
/**
- * Converts an object to an array.
- * @param {Array<T>|goog.array.ArrayLike} object The object to convert to an
- * array.
- * @return {!Array<T>} The object converted into an array. If object has a
- * length property, every property indexed with a non-negative number
- * less than length will be included in the result. If object does not
- * have a length property, an empty array will be returned.
- * @template T
+ * @typedef {{font: string,
+ * textAlign: string,
+ * textBaseline: string}}
*/
-goog.array.toArray = function(object) {
- var length = object.length;
-
- // If length is not a number the following it false. This case is kept for
- // backwards compatibility since there are callers that pass objects that are
- // not array like.
- if (length > 0) {
- var rv = new Array(length);
- for (var i = 0; i < length; i++) {
- rv[i] = object[i];
- }
- return rv;
- }
- return [];
-};
+ol.CanvasTextState;
/**
- * Does a shallow copy of an array.
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array-like object to
- * clone.
- * @return {!Array<T>} Clone of the input array.
- * @template T
+ * @typedef {function((ol.Coordinate|undefined)): (ol.Coordinate|undefined)}
*/
-goog.array.clone = goog.array.toArray;
+ol.CenterConstraintType;
/**
- * Extends an array with another array, element, or "array like" object.
- * This function operates 'in-place', it does not create a new Array.
- *
- * Example:
- * var a = [];
- * goog.array.extend(a, [0, 1]);
- * a; // [0, 1]
- * goog.array.extend(a, 2);
- * a; // [0, 1, 2]
- *
- * @param {Array<VALUE>} arr1 The array to modify.
- * @param {...(Array<VALUE>|VALUE)} var_args The elements or arrays of elements
- * to add to arr1.
- * @template VALUE
+ * A color represented as a short array [red, green, blue, alpha].
+ * red, green, and blue should be integers in the range 0..255 inclusive.
+ * alpha should be a float in the range 0..1 inclusive. If no alpha value is
+ * given then `1` will be used.
+ * @typedef {Array.<number>}
+ * @api
*/
-goog.array.extend = function(arr1, var_args) {
- for (var i = 1; i < arguments.length; i++) {
- var arr2 = arguments[i];
- if (goog.isArrayLike(arr2)) {
- var len1 = arr1.length || 0;
- var len2 = arr2.length || 0;
- arr1.length = len1 + len2;
- for (var j = 0; j < len2; j++) {
- arr1[len1 + j] = arr2[j];
- }
- } else {
- arr1.push(arr2);
- }
- }
-};
+ol.Color;
/**
- * Adds or removes elements from an array. This is a generic version of Array
- * splice. This means that it might work on other objects similar to arrays,
- * such as the arguments object.
+ * A type accepted by CanvasRenderingContext2D.fillStyle.
+ * Represents a color, pattern, or gradient.
*
- * @param {Array<T>|goog.array.ArrayLike} arr The array to modify.
- * @param {number|undefined} index The index at which to start changing the
- * array. If not defined, treated as 0.
- * @param {number} howMany How many elements to remove (0 means no removal. A
- * value below 0 is treated as zero and so is any other non number. Numbers
- * are floored).
- * @param {...T} var_args Optional, additional elements to insert into the
- * array.
- * @return {!Array<T>} the removed elements.
- * @template T
+ * @typedef {string|CanvasPattern|CanvasGradient}
+ * @api
*/
-goog.array.splice = function(arr, index, howMany, var_args) {
- goog.asserts.assert(arr.length != null);
-
- return goog.array.ARRAY_PROTOTYPE_.splice.apply(
- arr, goog.array.slice(arguments, 1));
-};
+ol.ColorLike;
/**
- * Returns a new array from a segment of an array. This is a generic version of
- * Array slice. This means that it might work on other objects similar to
- * arrays, such as the arguments object.
- *
- * @param {Array<T>|goog.array.ArrayLike} arr The array from
- * which to copy a segment.
- * @param {number} start The index of the first element to copy.
- * @param {number=} opt_end The index after the last element to copy.
- * @return {!Array<T>} A new array containing the specified segment of the
- * original array.
- * @template T
+ * An array of numbers representing an xy coordinate. Example: `[16, 48]`.
+ * @typedef {Array.<number>} ol.Coordinate
+ * @api stable
*/
-goog.array.slice = function(arr, start, opt_end) {
- goog.asserts.assert(arr.length != null);
-
- // passing 1 arg to slice is not the same as passing 2 where the second is
- // null or undefined (in that case the second argument is treated as 0).
- // we could use slice on the arguments object and then use apply instead of
- // testing the length
- if (arguments.length <= 2) {
- return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start);
- } else {
- return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start, opt_end);
- }
-};
+ol.Coordinate;
/**
- * Removes all duplicates from an array (retaining only the first
- * occurrence of each array element). This function modifies the
- * array in place and doesn't change the order of the non-duplicate items.
- *
- * For objects, duplicates are identified as having the same unique ID as
- * defined by {@link goog.getUid}.
- *
- * Alternatively you can specify a custom hash function that returns a unique
- * value for each item in the array it should consider unique.
- *
- * Runtime: N,
- * Worstcase space: 2N (no dupes)
+ * A function that takes a {@link ol.Coordinate} and transforms it into a
+ * `{string}`.
*
- * @param {Array<T>|goog.array.ArrayLike} arr The array from which to remove
- * duplicates.
- * @param {Array=} opt_rv An optional array in which to return the results,
- * instead of performing the removal inplace. If specified, the original
- * array will remain unchanged.
- * @param {function(T):string=} opt_hashFn An optional function to use to
- * apply to every item in the array. This function should return a unique
- * value for each item in the array it should consider unique.
- * @template T
+ * @typedef {function((ol.Coordinate|undefined)): string}
+ * @api stable
*/
-goog.array.removeDuplicates = function(arr, opt_rv, opt_hashFn) {
- var returnArray = opt_rv || arr;
- var defaultHashFn = function(item) {
- // Prefix each type with a single character representing the type to
- // prevent conflicting keys (e.g. true and 'true').
- return goog.isObject(item) ? 'o' + goog.getUid(item) :
- (typeof item).charAt(0) + item;
- };
- var hashFn = opt_hashFn || defaultHashFn;
-
- var seen = {}, cursorInsert = 0, cursorRead = 0;
- while (cursorRead < arr.length) {
- var current = arr[cursorRead++];
- var key = hashFn(current);
- if (!Object.prototype.hasOwnProperty.call(seen, key)) {
- seen[key] = true;
- returnArray[cursorInsert++] = current;
- }
- }
- returnArray.length = cursorInsert;
-};
+ol.CoordinateFormatType;
/**
- * Searches the specified array for the specified target using the binary
- * search algorithm. If no opt_compareFn is specified, elements are compared
- * using <code>goog.array.defaultCompare</code>, which compares the elements
- * using the built in < and > operators. This will produce the expected
- * behavior for homogeneous arrays of String(s) and Number(s). The array
- * specified <b>must</b> be sorted in ascending order (as defined by the
- * comparison function). If the array is not sorted, results are undefined.
- * If the array contains multiple instances of the specified target value, any
- * of these instances may be found.
- *
- * Runtime: O(log n)
- *
- * @param {Array<VALUE>|goog.array.ArrayLike} arr The array to be searched.
- * @param {TARGET} target The sought value.
- * @param {function(TARGET, VALUE): number=} opt_compareFn Optional comparison
- * function by which the array is ordered. Should take 2 arguments to
- * compare, and return a negative number, zero, or a positive number
- * depending on whether the first argument is less than, equal to, or
- * greater than the second.
- * @return {number} Lowest index of the target value if found, otherwise
- * (-(insertion point) - 1). The insertion point is where the value should
- * be inserted into arr to preserve the sorted property. Return value >= 0
- * iff target is found.
- * @template TARGET, VALUE
+ * An array of numbers representing an extent: `[minx, miny, maxx, maxy]`.
+ * @typedef {Array.<number>}
+ * @api stable
*/
-goog.array.binarySearch = function(arr, target, opt_compareFn) {
- return goog.array.binarySearch_(arr,
- opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */,
- target);
-};
+ol.Extent;
/**
- * Selects an index in the specified array using the binary search algorithm.
- * The evaluator receives an element and determines whether the desired index
- * is before, at, or after it. The evaluator must be consistent (formally,
- * goog.array.map(goog.array.map(arr, evaluator, opt_obj), goog.math.sign)
- * must be monotonically non-increasing).
+ * {@link ol.source.Vector} sources use a function of this type to load
+ * features.
*
- * Runtime: O(log n)
+ * This function takes an {@link ol.Extent} representing the area to be loaded,
+ * a `{number}` representing the resolution (map units per pixel) and an
+ * {@link ol.proj.Projection} for the projection as arguments. `this` within
+ * the function is bound to the {@link ol.source.Vector} it's called from.
*
- * @param {Array<VALUE>|goog.array.ArrayLike} arr The array to be searched.
- * @param {function(this:THIS, VALUE, number, ?): number} evaluator
- * Evaluator function that receives 3 arguments (the element, the index and
- * the array). Should return a negative number, zero, or a positive number
- * depending on whether the desired index is before, at, or after the
- * element passed to it.
- * @param {THIS=} opt_obj The object to be used as the value of 'this'
- * within evaluator.
- * @return {number} Index of the leftmost element matched by the evaluator, if
- * such exists; otherwise (-(insertion point) - 1). The insertion point is
- * the index of the first element for which the evaluator returns negative,
- * or arr.length if no such element exists. The return value is non-negative
- * iff a match is found.
- * @template THIS, VALUE
+ * The function is responsible for loading the features and adding them to the
+ * source.
+ * @api
+ * @typedef {function(this:ol.source.Vector, ol.Extent, number,
+ * ol.proj.Projection)}
*/
-goog.array.binarySelect = function(arr, evaluator, opt_obj) {
- return goog.array.binarySearch_(arr, evaluator, true /* isEvaluator */,
- undefined /* opt_target */, opt_obj);
-};
+ol.FeatureLoader;
/**
- * Implementation of a binary search algorithm which knows how to use both
- * comparison functions and evaluators. If an evaluator is provided, will call
- * the evaluator with the given optional data object, conforming to the
- * interface defined in binarySelect. Otherwise, if a comparison function is
- * provided, will call the comparison function against the given data object.
- *
- * This implementation purposefully does not use goog.bind or goog.partial for
- * performance reasons.
- *
- * Runtime: O(log n)
+ * A function that returns an array of {@link ol.style.Style styles} given a
+ * resolution. The `this` keyword inside the function references the
+ * {@link ol.Feature} to be styled.
*
- * @param {Array<VALUE>|goog.array.ArrayLike} arr The array to be searched.
- * @param {function(TARGET, VALUE): number|
- * function(this:THIS, VALUE, number, ?): number} compareFn Either an
- * evaluator or a comparison function, as defined by binarySearch
- * and binarySelect above.
- * @param {boolean} isEvaluator Whether the function is an evaluator or a
- * comparison function.
- * @param {TARGET=} opt_target If the function is a comparison function, then
- * this is the target to binary search for.
- * @param {THIS=} opt_selfObj If the function is an evaluator, this is an
- * optional this object for the evaluator.
- * @return {number} Lowest index of the target value if found, otherwise
- * (-(insertion point) - 1). The insertion point is where the value should
- * be inserted into arr to preserve the sorted property. Return value >= 0
- * iff target is found.
- * @template THIS, VALUE, TARGET
- * @private
+ * @typedef {function(this: ol.Feature, number):
+ * (ol.style.Style|Array.<ol.style.Style>)}
+ * @api stable
*/
-goog.array.binarySearch_ = function(arr, compareFn, isEvaluator, opt_target,
- opt_selfObj) {
- var left = 0; // inclusive
- var right = arr.length; // exclusive
- var found;
- while (left < right) {
- var middle = (left + right) >> 1;
- var compareResult;
- if (isEvaluator) {
- compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr);
- } else {
- compareResult = compareFn(opt_target, arr[middle]);
- }
- if (compareResult > 0) {
- left = middle + 1;
- } else {
- right = middle;
- // We are looking for the lowest index so we can't return immediately.
- found = !compareResult;
- }
- }
- // left is the index if found, or the insertion point otherwise.
- // ~left is a shorthand for -left - 1.
- return found ? left : ~left;
-};
+ol.FeatureStyleFunction;
/**
- * Sorts the specified array into ascending order. If no opt_compareFn is
- * specified, elements are compared using
- * <code>goog.array.defaultCompare</code>, which compares the elements using
- * the built in < and > operators. This will produce the expected behavior
- * for homogeneous arrays of String(s) and Number(s), unlike the native sort,
- * but will give unpredictable results for heterogenous lists of strings and
- * numbers with different numbers of digits.
- *
- * This sort is not guaranteed to be stable.
- *
- * Runtime: Same as <code>Array.prototype.sort</code>
+ * {@link ol.source.Vector} sources use a function of this type to get the url
+ * to load features from.
*
- * @param {Array<T>} arr The array to be sorted.
- * @param {?function(T,T):number=} opt_compareFn Optional comparison
- * function by which the
- * array is to be ordered. Should take 2 arguments to compare, and return a
- * negative number, zero, or a positive number depending on whether the
- * first argument is less than, equal to, or greater than the second.
- * @template T
+ * This function takes an {@link ol.Extent} representing the area to be loaded,
+ * a `{number}` representing the resolution (map units per pixel) and an
+ * {@link ol.proj.Projection} for the projection as arguments and returns a
+ * `{string}` representing the URL.
+ * @api
+ * @typedef {function(ol.Extent, number, ol.proj.Projection) : string}
*/
-goog.array.sort = function(arr, opt_compareFn) {
- // TODO(arv): Update type annotation since null is not accepted.
- arr.sort(opt_compareFn || goog.array.defaultCompare);
-};
+ol.FeatureUrlFunction;
/**
- * Sorts the specified array into ascending order in a stable way. If no
- * opt_compareFn is specified, elements are compared using
- * <code>goog.array.defaultCompare</code>, which compares the elements using
- * the built in < and > operators. This will produce the expected behavior
- * for homogeneous arrays of String(s) and Number(s).
- *
- * Runtime: Same as <code>Array.prototype.sort</code>, plus an additional
- * O(n) overhead of copying the array twice.
+ * A function that is called to trigger asynchronous canvas drawing. It is
+ * called with a "done" callback that should be called when drawing is done.
+ * If any error occurs during drawing, the "done" callback should be called with
+ * that error.
*
- * @param {Array<T>} arr The array to be sorted.
- * @param {?function(T, T): number=} opt_compareFn Optional comparison function
- * by which the array is to be ordered. Should take 2 arguments to compare,
- * and return a negative number, zero, or a positive number depending on
- * whether the first argument is less than, equal to, or greater than the
- * second.
- * @template T
+ * @typedef {function(function(Error))}
*/
-goog.array.stableSort = function(arr, opt_compareFn) {
- for (var i = 0; i < arr.length; i++) {
- arr[i] = {index: i, value: arr[i]};
- }
- var valueCompareFn = opt_compareFn || goog.array.defaultCompare;
- function stableCompareFn(obj1, obj2) {
- return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index;
- };
- goog.array.sort(arr, stableCompareFn);
- for (var i = 0; i < arr.length; i++) {
- arr[i] = arr[i].value;
- }
-};
+ol.ImageCanvasLoader;
/**
- * Sort the specified array into ascending order based on item keys
- * returned by the specified key function.
- * If no opt_compareFn is specified, the keys are compared in ascending order
- * using <code>goog.array.defaultCompare</code>.
+ * A function that takes an {@link ol.Image} for the image and a `{string}` for
+ * the src as arguments. It is supposed to make it so the underlying image
+ * {@link ol.Image#getImage} is assigned the content specified by the src. If
+ * not specified, the default is
*
- * Runtime: O(S(f(n)), where S is runtime of <code>goog.array.sort</code>
- * and f(n) is runtime of the key function.
+ * function(image, src) {
+ * image.getImage().src = src;
+ * }
*
- * @param {Array<T>} arr The array to be sorted.
- * @param {function(T): K} keyFn Function taking array element and returning
- * a key used for sorting this element.
- * @param {?function(K, K): number=} opt_compareFn Optional comparison function
- * by which the keys are to be ordered. Should take 2 arguments to compare,
- * and return a negative number, zero, or a positive number depending on
- * whether the first argument is less than, equal to, or greater than the
- * second.
- * @template T,K
- */
-goog.array.sortByKey = function(arr, keyFn, opt_compareFn) {
- var keyCompareFn = opt_compareFn || goog.array.defaultCompare;
- goog.array.sort(arr, function(a, b) {
- return keyCompareFn(keyFn(a), keyFn(b));
- });
-};
-
-
-/**
- * Sorts an array of objects by the specified object key and compare
- * function. If no compare function is provided, the key values are
- * compared in ascending order using <code>goog.array.defaultCompare</code>.
- * This won't work for keys that get renamed by the compiler. So use
- * {'foo': 1, 'bar': 2} rather than {foo: 1, bar: 2}.
- * @param {Array<Object>} arr An array of objects to sort.
- * @param {string} key The object key to sort by.
- * @param {Function=} opt_compareFn The function to use to compare key
- * values.
- */
-goog.array.sortObjectsByKey = function(arr, key, opt_compareFn) {
- goog.array.sortByKey(arr,
- function(obj) { return obj[key]; },
- opt_compareFn);
-};
-
-
-/**
- * Tells if the array is sorted.
- * @param {!Array<T>} arr The array.
- * @param {?function(T,T):number=} opt_compareFn Function to compare the
- * array elements.
- * Should take 2 arguments to compare, and return a negative number, zero,
- * or a positive number depending on whether the first argument is less
- * than, equal to, or greater than the second.
- * @param {boolean=} opt_strict If true no equal elements are allowed.
- * @return {boolean} Whether the array is sorted.
- * @template T
- */
-goog.array.isSorted = function(arr, opt_compareFn, opt_strict) {
- var compare = opt_compareFn || goog.array.defaultCompare;
- for (var i = 1; i < arr.length; i++) {
- var compareResult = compare(arr[i - 1], arr[i]);
- if (compareResult > 0 || compareResult == 0 && opt_strict) {
- return false;
- }
- }
- return true;
-};
-
-
-/**
- * Compares two arrays for equality. Two arrays are considered equal if they
- * have the same length and their corresponding elements are equal according to
- * the comparison function.
+ * Providing a custom `imageLoadFunction` can be useful to load images with
+ * post requests or - in general - through XHR requests, where the src of the
+ * image element would be set to a data URI when the content is loaded.
*
- * @param {goog.array.ArrayLike} arr1 The first array to compare.
- * @param {goog.array.ArrayLike} arr2 The second array to compare.
- * @param {Function=} opt_equalsFn Optional comparison function.
- * Should take 2 arguments to compare, and return true if the arguments
- * are equal. Defaults to {@link goog.array.defaultCompareEquality} which
- * compares the elements using the built-in '===' operator.
- * @return {boolean} Whether the two arrays are equal.
- */
-goog.array.equals = function(arr1, arr2, opt_equalsFn) {
- if (!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) ||
- arr1.length != arr2.length) {
- return false;
- }
- var l = arr1.length;
- var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
- for (var i = 0; i < l; i++) {
- if (!equalsFn(arr1[i], arr2[i])) {
- return false;
- }
- }
- return true;
-};
-
-
-/**
- * 3-way array compare function.
- * @param {!Array<VALUE>|!goog.array.ArrayLike} arr1 The first array to
- * compare.
- * @param {!Array<VALUE>|!goog.array.ArrayLike} arr2 The second array to
- * compare.
- * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
- * function by which the array is to be ordered. Should take 2 arguments to
- * compare, and return a negative number, zero, or a positive number
- * depending on whether the first argument is less than, equal to, or
- * greater than the second.
- * @return {number} Negative number, zero, or a positive number depending on
- * whether the first argument is less than, equal to, or greater than the
- * second.
- * @template VALUE
- */
-goog.array.compare3 = function(arr1, arr2, opt_compareFn) {
- var compare = opt_compareFn || goog.array.defaultCompare;
- var l = Math.min(arr1.length, arr2.length);
- for (var i = 0; i < l; i++) {
- var result = compare(arr1[i], arr2[i]);
- if (result != 0) {
- return result;
- }
- }
- return goog.array.defaultCompare(arr1.length, arr2.length);
-};
-
-
-/**
- * Compares its two arguments for order, using the built in < and >
- * operators.
- * @param {VALUE} a The first object to be compared.
- * @param {VALUE} b The second object to be compared.
- * @return {number} A negative number, zero, or a positive number as the first
- * argument is less than, equal to, or greater than the second,
- * respectively.
- * @template VALUE
+ * @typedef {function(ol.Image, string)}
+ * @api
*/
-goog.array.defaultCompare = function(a, b) {
- return a > b ? 1 : a < b ? -1 : 0;
-};
+ol.ImageLoadFunctionType;
/**
- * Compares its two arguments for inverse order, using the built in < and >
- * operators.
- * @param {VALUE} a The first object to be compared.
- * @param {VALUE} b The second object to be compared.
- * @return {number} A negative number, zero, or a positive number as the first
- * argument is greater than, equal to, or less than the second,
- * respectively.
- * @template VALUE
+ * @typedef {{x: number, xunits: (ol.style.IconAnchorUnits|undefined),
+ * y: number, yunits: (ol.style.IconAnchorUnits|undefined)}}
*/
-goog.array.inverseDefaultCompare = function(a, b) {
- return -goog.array.defaultCompare(a, b);
-};
+ol.KMLVec2_;
/**
- * Compares its two arguments for equality, using the built in === operator.
- * @param {*} a The first object to compare.
- * @param {*} b The second object to compare.
- * @return {boolean} True if the two arguments are equal, false otherwise.
+ * @typedef {{flatCoordinates: Array.<number>,
+ * whens: Array.<number>}}
*/
-goog.array.defaultCompareEquality = function(a, b) {
- return a === b;
-};
+ol.KMLGxTrackObject_;
/**
- * Inserts a value into a sorted array. The array is not modified if the
- * value is already present.
- * @param {Array<VALUE>|goog.array.ArrayLike} array The array to modify.
- * @param {VALUE} value The object to insert.
- * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
- * function by which the array is ordered. Should take 2 arguments to
- * compare, and return a negative number, zero, or a positive number
- * depending on whether the first argument is less than, equal to, or
- * greater than the second.
- * @return {boolean} True if an element was inserted.
- * @template VALUE
+ * @typedef {{layer: ol.layer.Layer,
+ * opacity: number,
+ * sourceState: ol.source.State,
+ * visible: boolean,
+ * managed: boolean,
+ * extent: (ol.Extent|undefined),
+ * zIndex: number,
+ * maxResolution: number,
+ * minResolution: number}}
*/
-goog.array.binaryInsert = function(array, value, opt_compareFn) {
- var index = goog.array.binarySearch(array, value, opt_compareFn);
- if (index < 0) {
- goog.array.insertAt(array, value, -(index + 1));
- return true;
- }
- return false;
-};
+ol.LayerState;
/**
- * Removes a value from a sorted array.
- * @param {!Array<VALUE>|!goog.array.ArrayLike} array The array to modify.
- * @param {VALUE} value The object to remove.
- * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
- * function by which the array is ordered. Should take 2 arguments to
- * compare, and return a negative number, zero, or a positive number
- * depending on whether the first argument is less than, equal to, or
- * greater than the second.
- * @return {boolean} True if an element was removed.
- * @template VALUE
+ * One of `all`, `bbox`, `tile`.
+ *
+ * @typedef {function(ol.Extent, number): Array.<ol.Extent>}
+ * @api
*/
-goog.array.binaryRemove = function(array, value, opt_compareFn) {
- var index = goog.array.binarySearch(array, value, opt_compareFn);
- return (index >= 0) ? goog.array.removeAt(array, index) : false;
-};
+ol.LoadingStrategy;
/**
- * Splits an array into disjoint buckets according to a splitting function.
- * @param {Array<T>} array The array.
- * @param {function(this:S, T,number,Array<T>):?} sorter Function to call for
- * every element. This takes 3 arguments (the element, the index and the
- * array) and must return a valid object key (a string, number, etc), or
- * undefined, if that object should not be placed in a bucket.
- * @param {S=} opt_obj The object to be used as the value of 'this' within
- * sorter.
- * @return {!Object} An object, with keys being all of the unique return values
- * of sorter, and values being arrays containing the items for
- * which the splitter returned that key.
- * @template T,S
+ * @typedef {{key_: string,
+ * newer: ol.LRUCacheEntry,
+ * older: ol.LRUCacheEntry,
+ * value_: *}}
*/
-goog.array.bucket = function(array, sorter, opt_obj) {
- var buckets = {};
-
- for (var i = 0; i < array.length; i++) {
- var value = array[i];
- var key = sorter.call(opt_obj, value, i, array);
- if (goog.isDef(key)) {
- // Push the value to the right bucket, creating it if necessary.
- var bucket = buckets[key] || (buckets[key] = []);
- bucket.push(value);
- }
- }
-
- return buckets;
-};
+ol.LRUCacheEntry;
/**
- * Creates a new object built from the provided array and the key-generation
- * function.
- * @param {Array<T>|goog.array.ArrayLike} arr Array or array like object over
- * which to iterate whose elements will be the values in the new object.
- * @param {?function(this:S, T, number, ?) : string} keyFunc The function to
- * call for every element. This function takes 3 arguments (the element, the
- * index and the array) and should return a string that will be used as the
- * key for the element in the new object. If the function returns the same
- * key for more than one element, the value for that key is
- * implementation-defined.
- * @param {S=} opt_obj The object to be used as the value of 'this'
- * within keyFunc.
- * @return {!Object<T>} The new object.
- * @template T,S
+ * @typedef {{controls: ol.Collection.<ol.control.Control>,
+ * interactions: ol.Collection.<ol.interaction.Interaction>,
+ * keyboardEventTarget: (Element|Document),
+ * logos: (Object.<string, (string|Element)>),
+ * overlays: ol.Collection.<ol.Overlay>,
+ * rendererConstructor:
+ * function(new: ol.renderer.Map, Element, ol.Map),
+ * values: Object.<string, *>}}
*/
-goog.array.toObject = function(arr, keyFunc, opt_obj) {
- var ret = {};
- goog.array.forEach(arr, function(element, index) {
- ret[keyFunc.call(opt_obj, element, index, arr)] = element;
- });
- return ret;
-};
+ol.MapOptionsInternal;
/**
- * Creates a range of numbers in an arithmetic progression.
- *
- * Range takes 1, 2, or 3 arguments:
- * <pre>
- * range(5) is the same as range(0, 5, 1) and produces [0, 1, 2, 3, 4]
- * range(2, 5) is the same as range(2, 5, 1) and produces [2, 3, 4]
- * range(-2, -5, -1) produces [-2, -3, -4]
- * range(-2, -5, 1) produces [], since stepping by 1 wouldn't ever reach -5.
- * </pre>
- *
- * @param {number} startOrEnd The starting value of the range if an end argument
- * is provided. Otherwise, the start value is 0, and this is the end value.
- * @param {number=} opt_end The optional end value of the range.
- * @param {number=} opt_step The step size between range values. Defaults to 1
- * if opt_step is undefined or 0.
- * @return {!Array<number>} An array of numbers for the requested range. May be
- * an empty array if adding the step would not converge toward the end
- * value.
+ * An array with two elements, representing a pixel. The first element is the
+ * x-coordinate, the second the y-coordinate of the pixel.
+ * @typedef {Array.<number>}
+ * @api stable
*/
-goog.array.range = function(startOrEnd, opt_end, opt_step) {
- var array = [];
- var start = 0;
- var end = startOrEnd;
- var step = opt_step || 1;
- if (opt_end !== undefined) {
- start = startOrEnd;
- end = opt_end;
- }
-
- if (step * (end - start) < 0) {
- // Sign mismatch: start + step will never reach the end value.
- return [];
- }
-
- if (step > 0) {
- for (var i = start; i < end; i += step) {
- array.push(i);
- }
- } else {
- for (var i = start; i > end; i += step) {
- array.push(i);
- }
- }
- return array;
-};
+ol.Pixel;
/**
- * Returns an array consisting of the given value repeated N times.
- *
- * @param {VALUE} value The value to repeat.
- * @param {number} n The repeat count.
- * @return {!Array<VALUE>} An array with the repeated value.
- * @template VALUE
+ * @typedef {function(ol.Map, ?olx.FrameState): boolean}
*/
-goog.array.repeat = function(value, n) {
- var array = [];
- for (var i = 0; i < n; i++) {
- array[i] = value;
- }
- return array;
-};
+ol.PostRenderFunction;
/**
- * Returns an array consisting of every argument with all arrays
- * expanded in-place recursively.
- *
- * @param {...*} var_args The values to flatten.
- * @return {!Array<?>} An array containing the flattened values.
+ * Function to perform manipulations before rendering. This function is called
+ * with the {@link ol.Map} as first and an optional {@link olx.FrameState} as
+ * second argument. Return `true` to keep this function for the next frame,
+ * `false` to remove it.
+ * @typedef {function(ol.Map, ?olx.FrameState): boolean}
+ * @api
*/
-goog.array.flatten = function(var_args) {
- var CHUNK_SIZE = 8192;
-
- var result = [];
- for (var i = 0; i < arguments.length; i++) {
- var element = arguments[i];
- if (goog.isArray(element)) {
- for (var c = 0; c < element.length; c += CHUNK_SIZE) {
- var chunk = goog.array.slice(element, c, c + CHUNK_SIZE);
- var recurseResult = goog.array.flatten.apply(null, chunk);
- for (var r = 0; r < recurseResult.length; r++) {
- result.push(recurseResult[r]);
- }
- }
- } else {
- result.push(element);
- }
- }
- return result;
-};
+ol.PreRenderFunction;
/**
- * Rotates an array in-place. After calling this method, the element at
- * index i will be the element previously at index (i - n) %
- * array.length, for all values of i between 0 and array.length - 1,
- * inclusive.
- *
- * For example, suppose list comprises [t, a, n, k, s]. After invoking
- * rotate(array, 1) (or rotate(array, -4)), array will comprise [s, t, a, n, k].
- *
- * @param {!Array<T>} array The array to rotate.
- * @param {number} n The amount to rotate.
- * @return {!Array<T>} The array.
- * @template T
+ * @typedef {function(ol.Extent, number, number) : ol.ImageBase}
*/
-goog.array.rotate = function(array, n) {
- goog.asserts.assert(array.length != null);
-
- if (array.length) {
- n %= array.length;
- if (n > 0) {
- goog.array.ARRAY_PROTOTYPE_.unshift.apply(array, array.splice(-n, n));
- } else if (n < 0) {
- goog.array.ARRAY_PROTOTYPE_.push.apply(array, array.splice(0, -n));
- }
- }
- return array;
-};
+ol.ReprojImageFunctionType;
/**
- * Moves one item of an array to a new position keeping the order of the rest
- * of the items. Example use case: keeping a list of JavaScript objects
- * synchronized with the corresponding list of DOM elements after one of the
- * elements has been dragged to a new position.
- * @param {!(Array|Arguments|{length:number})} arr The array to modify.
- * @param {number} fromIndex Index of the item to move between 0 and
- * {@code arr.length - 1}.
- * @param {number} toIndex Target index between 0 and {@code arr.length - 1}.
+ * @typedef {function(number, number, number, number) : ol.Tile}
*/
-goog.array.moveItem = function(arr, fromIndex, toIndex) {
- goog.asserts.assert(fromIndex >= 0 && fromIndex < arr.length);
- goog.asserts.assert(toIndex >= 0 && toIndex < arr.length);
- // Remove 1 item at fromIndex.
- var removedItems = goog.array.ARRAY_PROTOTYPE_.splice.call(arr, fromIndex, 1);
- // Insert the removed item at toIndex.
- goog.array.ARRAY_PROTOTYPE_.splice.call(arr, toIndex, 0, removedItems[0]);
- // We don't use goog.array.insertAt and goog.array.removeAt, because they're
- // significantly slower than splice.
-};
+ol.ReprojTileFunctionType;
/**
- * Creates a new array for which the element at position i is an array of the
- * ith element of the provided arrays. The returned array will only be as long
- * as the shortest array provided; additional values are ignored. For example,
- * the result of zipping [1, 2] and [3, 4, 5] is [[1,3], [2, 4]].
- *
- * This is similar to the zip() function in Python. See {@link
- * http://docs.python.org/library/functions.html#zip}
+ * Single triangle; consists of 3 source points and 3 target points.
*
- * @param {...!goog.array.ArrayLike} var_args Arrays to be combined.
- * @return {!Array<!Array<?>>} A new array of arrays created from
- * provided arrays.
+ * @typedef {{source: Array.<ol.Coordinate>,
+ * target: Array.<ol.Coordinate>}}
*/
-goog.array.zip = function(var_args) {
- if (!arguments.length) {
- return [];
- }
- var result = [];
- for (var i = 0; true; i++) {
- var value = [];
- for (var j = 0; j < arguments.length; j++) {
- var arr = arguments[j];
- // If i is larger than the array length, this is the shortest array.
- if (i >= arr.length) {
- return result;
- }
- value.push(arr[i]);
- }
- result.push(value);
- }
-};
+ol.ReprojTriangle;
/**
- * Shuffles the values in the specified array using the Fisher-Yates in-place
- * shuffle (also known as the Knuth Shuffle). By default, calls Math.random()
- * and so resets the state of that random number generator. Similarly, may reset
- * the state of the any other specified random number generator.
- *
- * Runtime: O(n)
- *
- * @param {!Array<?>} arr The array to be shuffled.
- * @param {function():number=} opt_randFn Optional random function to use for
- * shuffling.
- * Takes no arguments, and returns a random number on the interval [0, 1).
- * Defaults to Math.random() using JavaScript's built-in Math library.
- */
-goog.array.shuffle = function(arr, opt_randFn) {
- var randFn = opt_randFn || Math.random;
-
- for (var i = arr.length - 1; i > 0; i--) {
- // Choose a random array index in [0, i] (inclusive with i).
- var j = Math.floor(randFn() * (i + 1));
-
- var tmp = arr[i];
- arr[i] = arr[j];
- arr[j] = tmp;
- }
-};
-
-
-/**
- * Returns a new array of elements from arr, based on the indexes of elements
- * provided by index_arr. For example, the result of index copying
- * ['a', 'b', 'c'] with index_arr [1,0,0,2] is ['b', 'a', 'a', 'c'].
- *
- * @param {!Array<T>} arr The array to get a indexed copy from.
- * @param {!Array<number>} index_arr An array of indexes to get from arr.
- * @return {!Array<T>} A new array of elements from arr in index_arr order.
- * @template T
+ * @typedef {function((number|undefined), number, number): (number|undefined)}
*/
-goog.array.copyByIndex = function(arr, index_arr) {
- var result = [];
- goog.array.forEach(index_arr, function(index) {
- result.push(arr[index]);
- });
- return result;
-};
-
-goog.provide('ol.array');
-
-goog.require('goog.array');
-goog.require('goog.asserts');
+ol.ResolutionConstraintType;
/**
- * @param {Array.<number>} arr Array.
- * @param {number} target Target.
- * @return {number} Index.
+ * @typedef {function((number|undefined), number): (number|undefined)}
*/
-ol.array.binaryFindNearest = function(arr, target) {
- var index = goog.array.binarySearch(arr, target,
- /**
- * @param {number} a A.
- * @param {number} b B.
- * @return {number} b minus a.
- */
- function(a, b) {
- return b - a;
- });
- if (index >= 0) {
- return index;
- } else if (index == -1) {
- return 0;
- } else if (index == -arr.length - 1) {
- return arr.length - 1;
- } else {
- var left = -index - 2;
- var right = -index - 1;
- if (arr[left] - target < target - arr[right]) {
- return left;
- } else {
- return right;
- }
- }
-};
+ol.RotationConstraintType;
/**
- * Compare function for array sort that is safe for numbers.
- * @param {*} a The first object to be compared.
- * @param {*} b The second object to be compared.
- * @return {number} A negative number, zero, or a positive number as the first
- * argument is less than, equal to, or greater than the second.
+ * An array of numbers representing a size: `[width, height]`.
+ * @typedef {Array.<number>}
+ * @api stable
*/
-ol.array.numberSafeCompareFunction = function(a, b) {
- return a > b ? 1 : a < b ? -1 : 0;
-};
+ol.Size;
/**
- * Whether the array contains the given object.
- * @param {Array.<*>} arr The array to test for the presence of the element.
- * @param {*} obj The object for which to test.
- * @return {boolean} The object is in the array.
+ * @typedef {{attributions: (ol.AttributionLike|undefined),
+ * extent: (null|ol.Extent|undefined),
+ * logo: (string|olx.LogoOptions|undefined),
+ * projection: ol.proj.ProjectionLike,
+ * resolutions: (Array.<number>|undefined),
+ * state: (ol.source.State|undefined)}}
*/
-ol.array.includes = function(arr, obj) {
- return arr.indexOf(obj) >= 0;
-};
+ol.SourceImageOptions;
/**
- * @param {Array.<number>} arr Array.
- * @param {number} target Target.
- * @param {number} direction 0 means return the nearest, > 0
- * means return the largest nearest, < 0 means return the
- * smallest nearest.
- * @return {number} Index.
+ * @typedef {{revision: number,
+ * resolution: number,
+ * extent: ol.Extent}}
*/
-ol.array.linearFindNearest = function(arr, target, direction) {
- var n = arr.length;
- if (arr[0] <= target) {
- return 0;
- } else if (target <= arr[n - 1]) {
- return n - 1;
- } else {
- var i;
- if (direction > 0) {
- for (i = 1; i < n; ++i) {
- if (arr[i] < target) {
- return i - 1;
- }
- }
- } else if (direction < 0) {
- for (i = 1; i < n; ++i) {
- if (arr[i] <= target) {
- return i;
- }
- }
- } else {
- for (i = 1; i < n; ++i) {
- if (arr[i] == target) {
- return i;
- } else if (arr[i] < target) {
- if (arr[i - 1] - target < target - arr[i]) {
- return i - 1;
- } else {
- return i;
- }
- }
- }
- }
- // We should never get here, but the compiler complains
- // if it finds a path for which no number is returned.
- goog.asserts.fail();
- return n - 1;
- }
-};
+ol.SourceRasterRenderedState;
/**
- * @param {Array.<*>} arr Array.
- * @param {number} begin Begin index.
- * @param {number} end End index.
+ * @typedef {{attributions: (ol.AttributionLike|undefined),
+ * logo: (string|olx.LogoOptions|undefined),
+ * projection: ol.proj.ProjectionLike,
+ * state: (ol.source.State|undefined),
+ * wrapX: (boolean|undefined)}}
*/
-ol.array.reverseSubArray = function(arr, begin, end) {
- goog.asserts.assert(begin >= 0,
- 'Array begin index should be equal to or greater than 0');
- goog.asserts.assert(end < arr.length,
- 'Array end index should be less than the array length');
- while (begin < end) {
- var tmp = arr[begin];
- arr[begin] = arr[end];
- arr[end] = tmp;
- ++begin;
- --end;
- }
-};
-
-goog.provide('ol.ResolutionConstraint');
-goog.provide('ol.ResolutionConstraintType');
-
-goog.require('ol.array');
-goog.require('ol.math');
+ol.SourceSourceOptions;
/**
- * @typedef {function((number|undefined), number, number): (number|undefined)}
+ * @typedef {{attributions: (ol.AttributionLike|undefined),
+ * cacheSize: (number|undefined),
+ * extent: (ol.Extent|undefined),
+ * logo: (string|olx.LogoOptions|undefined),
+ * opaque: (boolean|undefined),
+ * tilePixelRatio: (number|undefined),
+ * projection: ol.proj.ProjectionLike,
+ * state: (ol.source.State|undefined),
+ * tileGrid: (ol.tilegrid.TileGrid|undefined),
+ * wrapX: (boolean|undefined)}}
*/
-ol.ResolutionConstraintType;
+ol.SourceTileOptions;
/**
- * @param {Array.<number>} resolutions Resolutions.
- * @return {ol.ResolutionConstraintType} Zoom function.
+ * @typedef {{attributions: (ol.AttributionLike|undefined),
+ * cacheSize: (number|undefined),
+ * extent: (ol.Extent|undefined),
+ * logo: (string|olx.LogoOptions|undefined),
+ * opaque: (boolean|undefined),
+ * projection: ol.proj.ProjectionLike,
+ * state: (ol.source.State|undefined),
+ * tileGrid: (ol.tilegrid.TileGrid|undefined),
+ * tileLoadFunction: ol.TileLoadFunctionType,
+ * tilePixelRatio: (number|undefined),
+ * tileUrlFunction: (ol.TileUrlFunctionType|undefined),
+ * url: (string|undefined),
+ * urls: (Array.<string>|undefined),
+ * wrapX: (boolean|undefined)}}
*/
-ol.ResolutionConstraint.createSnapToResolutions =
- function(resolutions) {
- return (
- /**
- * @param {number|undefined} resolution Resolution.
- * @param {number} delta Delta.
- * @param {number} direction Direction.
- * @return {number|undefined} Resolution.
- */
- function(resolution, delta, direction) {
- if (resolution !== undefined) {
- var z =
- ol.array.linearFindNearest(resolutions, resolution, direction);
- z = ol.math.clamp(z + delta, 0, resolutions.length - 1);
- return resolutions[z];
- } else {
- return undefined;
- }
- });
-};
+ol.SourceUrlTileOptions;
/**
- * @param {number} power Power.
- * @param {number} maxResolution Maximum resolution.
- * @param {number=} opt_maxLevel Maximum level.
- * @return {ol.ResolutionConstraintType} Zoom function.
+ * An array of three numbers representing the location of a tile in a tile
+ * grid. The order is `z`, `x`, and `y`. `z` is the zoom level.
+ * @typedef {Array.<number>} ol.TileCoord
+ * @api
*/
-ol.ResolutionConstraint.createSnapToPower =
- function(power, maxResolution, opt_maxLevel) {
- return (
- /**
- * @param {number|undefined} resolution Resolution.
- * @param {number} delta Delta.
- * @param {number} direction Direction.
- * @return {number|undefined} Resolution.
- */
- function(resolution, delta, direction) {
- if (resolution !== undefined) {
- var offset;
- if (direction > 0) {
- offset = 0;
- } else if (direction < 0) {
- offset = 1;
- } else {
- offset = 0.5;
- }
- var oldLevel = Math.floor(
- Math.log(maxResolution / resolution) / Math.log(power) + offset);
- var newLevel = Math.max(oldLevel + delta, 0);
- if (opt_maxLevel !== undefined) {
- newLevel = Math.min(newLevel, opt_maxLevel);
- }
- return maxResolution / Math.pow(power, newLevel);
- } else {
- return undefined;
- }
- });
-};
-
-goog.provide('ol.RotationConstraint');
-goog.provide('ol.RotationConstraintType');
-
-goog.require('ol.math');
+ol.TileCoord;
/**
- * @typedef {function((number|undefined), number): (number|undefined)}
+ * A function that takes an {@link ol.Tile} for the tile and a `{string}` for
+ * the url as arguments.
+ *
+ * @typedef {function(ol.Tile, string)}
+ * @api
*/
-ol.RotationConstraintType;
+ol.TileLoadFunctionType;
/**
- * @param {number|undefined} rotation Rotation.
- * @param {number} delta Delta.
- * @return {number|undefined} Rotation.
+ * @typedef {function(ol.Tile, string, ol.Coordinate, number): number}
*/
-ol.RotationConstraint.disable = function(rotation, delta) {
- if (rotation !== undefined) {
- return 0;
- } else {
- return undefined;
- }
-};
+ol.TilePriorityFunction;
/**
- * @param {number|undefined} rotation Rotation.
- * @param {number} delta Delta.
- * @return {number|undefined} Rotation.
+ * @typedef {{
+ * dirty: boolean,
+ * renderedRenderOrder: (null|function(ol.Feature, ol.Feature):number),
+ * renderedTileRevision: number,
+ * renderedRevision: number,
+ * replayGroup: ol.render.IReplayGroup,
+ * skippedFeatures: Array.<string>}}
*/
-ol.RotationConstraint.none = function(rotation, delta) {
- if (rotation !== undefined) {
- return rotation + delta;
- } else {
- return undefined;
- }
-};
+ol.TileReplayState;
/**
- * @param {number} n N.
- * @return {ol.RotationConstraintType} Rotation constraint.
+ * {@link ol.source.Tile} sources use a function of this type to get the url
+ * that provides a tile for a given tile coordinate.
+ *
+ * This function takes an {@link ol.TileCoord} for the tile coordinate, a
+ * `{number}` representing the pixel ratio and an {@link ol.proj.Projection} for
+ * the projection as arguments and returns a `{string}` representing the tile
+ * URL, or undefined if no tile should be requested for the passed tile
+ * coordinate.
+ *
+ * @typedef {function(ol.TileCoord, number,
+ * ol.proj.Projection): (string|undefined)}
+ * @api
*/
-ol.RotationConstraint.createSnapToN = function(n) {
- var theta = 2 * Math.PI / n;
- return (
- /**
- * @param {number|undefined} rotation Rotation.
- * @param {number} delta Delta.
- * @return {number|undefined} Rotation.
- */
- function(rotation, delta) {
- if (rotation !== undefined) {
- rotation = Math.floor((rotation + delta) / theta + 0.5) * theta;
- return rotation;
- } else {
- return undefined;
- }
- });
-};
+ol.TileUrlFunctionType;
/**
- * @param {number=} opt_tolerance Tolerance.
- * @return {ol.RotationConstraintType} Rotation constraint.
+ * A transform function accepts an array of input coordinate values, an optional
+ * output array, and an optional dimension (default should be 2). The function
+ * transforms the input coordinate values, populates the output array, and
+ * returns the output array.
+ *
+ * @typedef {function(Array.<number>, Array.<number>=, number=): Array.<number>}
+ * @api stable
*/
-ol.RotationConstraint.createSnapToZero = function(opt_tolerance) {
- var tolerance = opt_tolerance || ol.math.toRadians(5);
- return (
- /**
- * @param {number|undefined} rotation Rotation.
- * @param {number} delta Delta.
- * @return {number|undefined} Rotation.
- */
- function(rotation, delta) {
- if (rotation !== undefined) {
- if (Math.abs(rotation + delta) <= tolerance) {
- return 0;
- } else {
- return rotation + delta;
- }
- } else {
- return undefined;
- }
- });
-};
-
-goog.provide('ol.Constraints');
-
-goog.require('ol.CenterConstraintType');
-goog.require('ol.ResolutionConstraintType');
-goog.require('ol.RotationConstraintType');
-
+ol.TransformFunction;
/**
- * @constructor
- * @param {ol.CenterConstraintType} centerConstraint Center constraint.
- * @param {ol.ResolutionConstraintType} resolutionConstraint
- * Resolution constraint.
- * @param {ol.RotationConstraintType} rotationConstraint
- * Rotation constraint.
+ * @typedef {{buf: ol.webgl.Buffer,
+ * buffer: WebGLBuffer}}
*/
-ol.Constraints =
- function(centerConstraint, resolutionConstraint, rotationConstraint) {
-
- /**
- * @type {ol.CenterConstraintType}
- */
- this.center = centerConstraint;
-
- /**
- * @type {ol.ResolutionConstraintType}
- */
- this.resolution = resolutionConstraint;
-
- /**
- * @type {ol.RotationConstraintType}
- */
- this.rotation = rotationConstraint;
+ol.WebglBufferCacheEntry;
-};
-
-// Copyright 2010 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview A global registry for entry points into a program,
- * so that they can be instrumented. Each module should register their
- * entry points with this registry. Designed to be compiled out
- * if no instrumentation is requested.
- *
- * Entry points may be registered before or after a call to
- * goog.debug.entryPointRegistry.monitorAll. If an entry point is registered
- * later, the existing monitor will instrument the new entry point.
- *
- * @author nicksantos@google.com (Nick Santos)
+ * @typedef {{magFilter: number, minFilter: number, texture: WebGLTexture}}
*/
-
-goog.provide('goog.debug.EntryPointMonitor');
-goog.provide('goog.debug.entryPointRegistry');
-
-goog.require('goog.asserts');
-
+ol.WebglTextureCacheEntry;
/**
- * @interface
+ * Number of features; bounds/extent.
+ * @typedef {{numberOfFeatures: number,
+ * bounds: ol.Extent}}
+ * @api stable
*/
-goog.debug.EntryPointMonitor = function() {};
+ol.WFSFeatureCollectionMetadata;
/**
- * Instruments a function.
- *
- * @param {!Function} fn A function to instrument.
- * @return {!Function} The instrumented function.
+ * Total deleted; total inserted; total updated; array of insert ids.
+ * @typedef {{totalDeleted: number,
+ * totalInserted: number,
+ * totalUpdated: number,
+ * insertIds: Array.<string>}}
+ * @api stable
*/
-goog.debug.EntryPointMonitor.prototype.wrap;
+ol.WFSTransactionResponse;
/**
- * Try to remove an instrumentation wrapper created by this monitor.
- * If the function passed to unwrap is not a wrapper created by this
- * monitor, then we will do nothing.
- *
- * Notice that some wrappers may not be unwrappable. For example, if other
- * monitors have applied their own wrappers, then it will be impossible to
- * unwrap them because their wrappers will have captured our wrapper.
- *
- * So it is important that entry points are unwrapped in the reverse
- * order that they were wrapped.
- *
- * @param {!Function} fn A function to unwrap.
- * @return {!Function} The unwrapped function, or {@code fn} if it was not
- * a wrapped function created by this monitor.
+ * @typedef {{type: number, value: (number|string|undefined), position: number}}
*/
-goog.debug.EntryPointMonitor.prototype.unwrap;
+ol.WKTToken;
/**
- * An array of entry point callbacks.
- * @type {!Array<function(!Function)>}
- * @private
+ * When using {@link ol.xml.makeChildAppender} or
+ * {@link ol.xml.makeSimpleNodeFactory}, the top `objectStack` item needs to
+ * have this structure.
+ * @typedef {{node:Node}}
*/
-goog.debug.entryPointRegistry.refList_ = [];
+ol.XmlNodeStackItem;
/**
- * Monitors that should wrap all the entry points.
- * @type {!Array<!goog.debug.EntryPointMonitor>}
- * @private
+ * @typedef {function(Node, Array.<*>)}
*/
-goog.debug.entryPointRegistry.monitors_ = [];
+ol.XmlParser;
/**
- * Whether goog.debug.entryPointRegistry.monitorAll has ever been called.
- * Checking this allows the compiler to optimize out the registrations.
- * @type {boolean}
- * @private
+ * @typedef {function(Node, *, Array.<*>)}
*/
-goog.debug.entryPointRegistry.monitorsMayExist_ = false;
+ol.XmlSerializer;
/**
- * Register an entry point with this module.
- *
- * The entry point will be instrumented when a monitor is passed to
- * goog.debug.entryPointRegistry.monitorAll. If this has already occurred, the
- * entry point is instrumented immediately.
+ * A function that takes an {@link ol.MapBrowserEvent} and returns a
+ * `{boolean}`. If the condition is met, true should be returned.
*
- * @param {function(!Function)} callback A callback function which is called
- * with a transforming function to instrument the entry point. The callback
- * is responsible for wrapping the relevant entry point with the
- * transforming function.
+ * @typedef {function(ol.MapBrowserEvent): boolean}
+ * @api stable
*/
-goog.debug.entryPointRegistry.register = function(callback) {
- // Don't use push(), so that this can be compiled out.
- goog.debug.entryPointRegistry.refList_[
- goog.debug.entryPointRegistry.refList_.length] = callback;
- // If no one calls monitorAll, this can be compiled out.
- if (goog.debug.entryPointRegistry.monitorsMayExist_) {
- var monitors = goog.debug.entryPointRegistry.monitors_;
- for (var i = 0; i < monitors.length; i++) {
- callback(goog.bind(monitors[i].wrap, monitors[i]));
- }
- }
-};
+ol.events.ConditionType;
/**
- * Configures a monitor to wrap all entry points.
- *
- * Entry points that have already been registered are immediately wrapped by
- * the monitor. When an entry point is registered in the future, it will also
- * be wrapped by the monitor when it is registered.
- *
- * @param {!goog.debug.EntryPointMonitor} monitor An entry point monitor.
+ * @typedef {EventTarget|ol.events.EventTarget|
+ * {addEventListener: function(string, Function, boolean=),
+ * removeEventListener: function(string, Function, boolean=),
+ * dispatchEvent: function(string)}}
*/
-goog.debug.entryPointRegistry.monitorAll = function(monitor) {
- goog.debug.entryPointRegistry.monitorsMayExist_ = true;
- var transformer = goog.bind(monitor.wrap, monitor);
- for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
- goog.debug.entryPointRegistry.refList_[i](transformer);
- }
- goog.debug.entryPointRegistry.monitors_.push(monitor);
-};
+ol.events.EventTargetLike;
/**
- * Try to unmonitor all the entry points that have already been registered. If
- * an entry point is registered in the future, it will not be wrapped by the
- * monitor when it is registered. Note that this may fail if the entry points
- * have additional wrapping.
+ * Key to use with {@link ol.Observable#unByKey}.
*
- * @param {!goog.debug.EntryPointMonitor} monitor The last monitor to wrap
- * the entry points.
- * @throws {Error} If the monitor is not the most recently configured monitor.
+ * @typedef {{bindTo: (Object|undefined),
+ * boundListener: (ol.events.ListenerFunctionType|undefined),
+ * callOnce: boolean,
+ * deleteIndex: (number|undefined),
+ * listener: ol.events.ListenerFunctionType,
+ * target: (EventTarget|ol.events.EventTarget),
+ * type: string}}
+ * @api
*/
-goog.debug.entryPointRegistry.unmonitorAllIfPossible = function(monitor) {
- var monitors = goog.debug.entryPointRegistry.monitors_;
- goog.asserts.assert(monitor == monitors[monitors.length - 1],
- 'Only the most recent monitor can be unwrapped.');
- var transformer = goog.bind(monitor.unwrap, monitor);
- for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
- goog.debug.entryPointRegistry.refList_[i](transformer);
- }
- monitors.length--;
-};
+ol.events.Key;
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Utilities used by goog.labs.userAgent tools. These functions
- * should not be used outside of goog.labs.userAgent.*.
- *
+ * Listener function. This function is called with an event object as argument.
+ * When the function returns `false`, event propagation will stop.
*
- * @author nnaze@google.com (Nathan Naze)
+ * @typedef {function(ol.events.Event)|function(ol.events.Event): boolean}
+ * @api
*/
-
-goog.provide('goog.labs.userAgent.util');
-
-goog.require('goog.string');
+ol.events.ListenerFunctionType;
/**
- * Gets the native userAgent string from navigator if it exists.
- * If navigator or navigator.userAgent string is missing, returns an empty
- * string.
- * @return {string}
- * @private
+ * A function that takes a {@link ol.MapBrowserEvent} and two
+ * {@link ol.Pixel}s and returns a `{boolean}`. If the condition is met,
+ * true should be returned.
+ * @typedef {function(ol.MapBrowserEvent, ol.Pixel, ol.Pixel):boolean}
+ * @api
*/
-goog.labs.userAgent.util.getNativeUserAgentString_ = function() {
- var navigator = goog.labs.userAgent.util.getNavigator_();
- if (navigator) {
- var userAgent = navigator.userAgent;
- if (userAgent) {
- return userAgent;
- }
- }
- return '';
-};
+ol.interaction.DragBoxEndConditionType;
/**
- * Getter for the native navigator.
- * This is a separate function so it can be stubbed out in testing.
- * @return {Navigator}
- * @private
+ * Function that takes coordinates and an optional existing geometry as
+ * arguments, and returns a geometry. The optional existing geometry is the
+ * geometry that is returned when the function is called without a second
+ * argument.
+ * @typedef {function(!(ol.Coordinate|Array.<ol.Coordinate>|
+ * Array.<Array.<ol.Coordinate>>), ol.geom.SimpleGeometry=):
+ * ol.geom.SimpleGeometry}
+ * @api
*/
-goog.labs.userAgent.util.getNavigator_ = function() {
- return goog.global.navigator;
-};
+ol.interaction.DrawGeometryFunctionType;
/**
- * A possible override for applications which wish to not check
- * navigator.userAgent but use a specified value for detection instead.
- * @private {string}
+ * @typedef {{depth: (Array.<number>|undefined),
+ * feature: ol.Feature,
+ * geometry: ol.geom.SimpleGeometry,
+ * index: (number|undefined),
+ * segment: Array.<ol.Extent>}}
*/
-goog.labs.userAgent.util.userAgent_ =
- goog.labs.userAgent.util.getNativeUserAgentString_();
+ol.interaction.SegmentDataType;
/**
- * Applications may override browser detection on the built in
- * navigator.userAgent object by setting this string. Set to null to use the
- * browser object instead.
- * @param {?string=} opt_userAgent The User-Agent override.
+ * A function that takes an {@link ol.Feature} or {@link ol.render.Feature} and
+ * an {@link ol.layer.Layer} and returns `true` if the feature may be selected
+ * or `false` otherwise.
+ * @typedef {function((ol.Feature|ol.render.Feature), ol.layer.Layer):
+ * boolean}
+ * @api
*/
-goog.labs.userAgent.util.setUserAgent = function(opt_userAgent) {
- goog.labs.userAgent.util.userAgent_ = opt_userAgent ||
- goog.labs.userAgent.util.getNativeUserAgentString_();
-};
+ol.interaction.SelectFilterFunction;
/**
- * @return {string} The user agent string.
+ * @typedef {{
+ * snapped: {boolean},
+ * vertex: (ol.Coordinate|null),
+ * vertexPixel: (ol.Pixel|null)
+ * }}
*/
-goog.labs.userAgent.util.getUserAgent = function() {
- return goog.labs.userAgent.util.userAgent_;
-};
+ol.interaction.SnapResultType;
/**
- * @param {string} str
- * @return {boolean} Whether the user agent contains the given string, ignoring
- * case.
+ * @typedef {{
+ * feature: ol.Feature,
+ * segment: Array.<ol.Coordinate>
+ * }}
*/
-goog.labs.userAgent.util.matchUserAgent = function(str) {
- var userAgent = goog.labs.userAgent.util.getUserAgent();
- return goog.string.contains(userAgent, str);
-};
+ol.interaction.SnapSegmentDataType;
/**
- * @param {string} str
- * @return {boolean} Whether the user agent contains the given string.
+ * A projection as {@link ol.proj.Projection}, SRS identifier string or
+ * undefined.
+ * @typedef {ol.proj.Projection|string|undefined} ol.proj.ProjectionLike
+ * @api stable
*/
-goog.labs.userAgent.util.matchUserAgentIgnoreCase = function(str) {
- var userAgent = goog.labs.userAgent.util.getUserAgent();
- return goog.string.caseInsensitiveContains(userAgent, str);
-};
+ol.proj.ProjectionLike;
/**
- * Parses the user agent into tuples for each section.
- * @param {string} userAgent
- * @return {!Array<!Array<string>>} Tuples of key, version, and the contents
- * of the parenthetical.
+ * A function that takes an array of input data, performs some operation, and
+ * returns an array of ouput data. For `'pixel'` type operations, functions
+ * will be called with an array of {@link ol.raster.Pixel} data and should
+ * return an array of the same. For `'image'` type operations, functions will
+ * be called with an array of {@link ImageData
+ * https://developer.mozilla.org/en-US/docs/Web/API/ImageData} and should return
+ * an array of the same. The operations are called with a second "data"
+ * argument, which can be used for storage. The data object is accessible
+ * from raster events, where it can be initialized in "beforeoperations" and
+ * accessed again in "afteroperations".
+ *
+ * @typedef {function((Array.<ol.raster.Pixel>|Array.<ImageData>), Object):
+ * (Array.<ol.raster.Pixel>|Array.<ImageData>)}
+ * @api
*/
-goog.labs.userAgent.util.extractVersionTuples = function(userAgent) {
- // Matches each section of a user agent string.
- // Example UA:
- // Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us)
- // AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405
- // This has three version tuples: Mozilla, AppleWebKit, and Mobile.
-
- var versionRegExp = new RegExp(
- // Key. Note that a key may have a space.
- // (i.e. 'Mobile Safari' in 'Mobile Safari/5.0')
- '(\\w[\\w ]+)' +
-
- '/' + // slash
- '([^\\s]+)' + // version (i.e. '5.0b')
- '\\s*' + // whitespace
- '(?:\\((.*?)\\))?', // parenthetical info. parentheses not matched.
- 'g');
-
- var data = [];
- var match;
-
- // Iterate and collect the version tuples. Each iteration will be the
- // next regex match.
- while (match = versionRegExp.exec(userAgent)) {
- data.push([
- match[1], // key
- match[2], // value
- // || undefined as this is not undefined in IE7 and IE8
- match[3] || undefined // info
- ]);
- }
-
- return data;
-};
-
+ol.raster.Operation;
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Utilities for manipulating objects/maps/hashes.
- * @author arv@google.com (Erik Arvidsson)
+ * An array of numbers representing pixel values.
+ * @typedef {Array.<number>} ol.raster.Pixel
+ * @api
*/
-
-goog.provide('goog.object');
+ol.raster.Pixel;
/**
- * Calls a function for each element in an object/map/hash.
- *
- * @param {Object<K,V>} obj The object over which to iterate.
- * @param {function(this:T,V,?,Object<K,V>):?} f The function to call
- * for every element. This function takes 3 arguments (the value, the
- * key and the object) and the return value is ignored.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @template T,K,V
+ * @typedef {{x: number, y: number, width: number, height: number}}
*/
-goog.object.forEach = function(obj, f, opt_obj) {
- for (var key in obj) {
- f.call(opt_obj, obj[key], key, obj);
- }
-};
+ol.style.AtlasBlock;
/**
- * Calls a function for each element in an object/map/hash. If that call returns
- * true, adds the element to a new object.
- *
- * @param {Object<K,V>} obj The object over which to iterate.
- * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to call
- * for every element. This
- * function takes 3 arguments (the value, the key and the object)
- * and should return a boolean. If the return value is true the
- * element is added to the result object. If it is false the
- * element is not included.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @return {!Object<K,V>} a new object in which only elements that passed the
- * test are present.
- * @template T,K,V
+ * Provides information for an image inside an atlas.
+ * `offsetX` and `offsetY` are the position of the image inside
+ * the atlas image `image`.
+ * @typedef {{offsetX: number, offsetY: number, image: HTMLCanvasElement}}
*/
-goog.object.filter = function(obj, f, opt_obj) {
- var res = {};
- for (var key in obj) {
- if (f.call(opt_obj, obj[key], key, obj)) {
- res[key] = obj[key];
- }
- }
- return res;
-};
+ol.style.AtlasInfo;
/**
- * For every element in an object/map/hash calls a function and inserts the
- * result into a new object.
- *
- * @param {Object<K,V>} obj The object over which to iterate.
- * @param {function(this:T,V,?,Object<K,V>):R} f The function to call
- * for every element. This function
- * takes 3 arguments (the value, the key and the object)
- * and should return something. The result will be inserted
- * into a new object.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @return {!Object<K,R>} a new object with the results from f.
- * @template T,K,V,R
+ * Provides information for an image inside an atlas manager.
+ * `offsetX` and `offsetY` is the position of the image inside
+ * the atlas image `image` and the position of the hit-detection image
+ * inside the hit-detection atlas image `hitImage`.
+ * @typedef {{offsetX: number, offsetY: number, image: HTMLCanvasElement,
+ * hitImage: HTMLCanvasElement}}
*/
-goog.object.map = function(obj, f, opt_obj) {
- var res = {};
- for (var key in obj) {
- res[key] = f.call(opt_obj, obj[key], key, obj);
- }
- return res;
-};
+ol.style.AtlasManagerInfo;
/**
- * Calls a function for each element in an object/map/hash. If any
- * call returns true, returns true (without checking the rest). If
- * all calls return false, returns false.
- *
- * @param {Object<K,V>} obj The object to check.
- * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to
- * call for every element. This function
- * takes 3 arguments (the value, the key and the object) and should
- * return a boolean.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @return {boolean} true if any element passes the test.
- * @template T,K,V
+ * @typedef {{strokeStyle: (string|undefined), strokeWidth: number,
+ * size: number, lineDash: Array.<number>}}
*/
-goog.object.some = function(obj, f, opt_obj) {
- for (var key in obj) {
- if (f.call(opt_obj, obj[key], key, obj)) {
- return true;
- }
- }
- return false;
-};
+ol.style.CircleRenderOptions;
/**
- * Calls a function for each element in an object/map/hash. If
- * all calls return true, returns true. If any call returns false, returns
- * false at this point and does not continue to check the remaining elements.
- *
- * @param {Object<K,V>} obj The object to check.
- * @param {?function(this:T,V,?,Object<K,V>):boolean} f The function to
- * call for every element. This function
- * takes 3 arguments (the value, the key and the object) and should
- * return a boolean.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @return {boolean} false if any element fails the test.
- * @template T,K,V
+ * @typedef {{opacity: number,
+ * rotateWithView: boolean,
+ * rotation: number,
+ * scale: number,
+ * snapToPixel: boolean}}
*/
-goog.object.every = function(obj, f, opt_obj) {
- for (var key in obj) {
- if (!f.call(opt_obj, obj[key], key, obj)) {
- return false;
- }
- }
- return true;
-};
+ol.style.ImageOptions;
/**
- * Returns the number of key-value pairs in the object map.
+ * A function that takes an {@link ol.Feature} as argument and returns an
+ * {@link ol.geom.Geometry} that will be rendered and styled for the feature.
*
- * @param {Object} obj The object for which to get the number of key-value
- * pairs.
- * @return {number} The number of key-value pairs in the object map.
+ * @typedef {function((ol.Feature|ol.render.Feature)):
+ * (ol.geom.Geometry|ol.render.Feature|undefined)}
+ * @api
*/
-goog.object.getCount = function(obj) {
- // JS1.5 has __count__ but it has been deprecated so it raises a warning...
- // in other words do not use. Also __count__ only includes the fields on the
- // actual object and not in the prototype chain.
- var rv = 0;
- for (var key in obj) {
- rv++;
- }
- return rv;
-};
+ol.style.GeometryFunction;
/**
- * Returns one key from the object map, if any exists.
- * For map literals the returned key will be the first one in most of the
- * browsers (a know exception is Konqueror).
- *
- * @param {Object} obj The object to pick a key from.
- * @return {string|undefined} The key or undefined if the object is empty.
+ * @typedef {{
+ * strokeStyle: (string|undefined),
+ * strokeWidth: number,
+ * size: number,
+ * lineCap: string,
+ * lineDash: Array.<number>,
+ * lineJoin: string,
+ * miterLimit: number
+ * }}
*/
-goog.object.getAnyKey = function(obj) {
- for (var key in obj) {
- return key;
- }
-};
+ol.style.RegularShapeRenderOptions;
/**
- * Returns one value from the object map, if any exists.
- * For map literals the returned value will be the first one in most of the
- * browsers (a know exception is Konqueror).
+ * A function that takes an {@link ol.Feature} and a `{number}` representing
+ * the view's resolution. The function should return a {@link ol.style.Style}
+ * or an array of them. This way e.g. a vector layer can be styled.
*
- * @param {Object<K,V>} obj The object to pick a value from.
- * @return {V|undefined} The value or undefined if the object is empty.
- * @template K,V
+ * @typedef {function((ol.Feature|ol.render.Feature), number):
+ * (ol.style.Style|Array.<ol.style.Style>)}
+ * @api
*/
-goog.object.getAnyValue = function(obj) {
- for (var key in obj) {
- return obj[key];
- }
-};
+ol.style.StyleFunction;
+goog.provide('ol.events');
+goog.provide('ol.events.EventType');
+goog.provide('ol.events.KeyCode');
-/**
- * Whether the object/hash/map contains the given object as a value.
- * An alias for goog.object.containsValue(obj, val).
- *
- * @param {Object<K,V>} obj The object in which to look for val.
- * @param {V} val The object for which to check.
- * @return {boolean} true if val is present.
- * @template K,V
- */
-goog.object.contains = function(obj, val) {
- return goog.object.containsValue(obj, val);
-};
+goog.require('ol.object');
+goog.require('ol.events.EventTargetLike');
/**
- * Returns the values of the object/map/hash.
- *
- * @param {Object<K,V>} obj The object from which to get the values.
- * @return {!Array<V>} The values in the object/map/hash.
- * @template K,V
+ * @enum {string}
+ * @const
*/
-goog.object.getValues = function(obj) {
- var res = [];
- var i = 0;
- for (var key in obj) {
- res[i++] = obj[key];
- }
- return res;
-};
-
+ol.events.EventType = {
+ /**
+ * Generic change event.
+ * @event ol.events.Event#change
+ * @api
+ */
+ CHANGE: 'change',
-/**
- * Returns the keys of the object/map/hash.
- *
- * @param {Object} obj The object from which to get the keys.
- * @return {!Array<string>} Array of property keys.
- */
-goog.object.getKeys = function(obj) {
- var res = [];
- var i = 0;
- for (var key in obj) {
- res[i++] = key;
- }
- return res;
+ CLICK: 'click',
+ DBLCLICK: 'dblclick',
+ DRAGENTER: 'dragenter',
+ DRAGOVER: 'dragover',
+ DROP: 'drop',
+ ERROR: 'error',
+ KEYDOWN: 'keydown',
+ KEYPRESS: 'keypress',
+ LOAD: 'load',
+ MOUSEDOWN: 'mousedown',
+ MOUSEMOVE: 'mousemove',
+ MOUSEOUT: 'mouseout',
+ MOUSEUP: 'mouseup',
+ MOUSEWHEEL: 'mousewheel',
+ MSPOINTERDOWN: 'mspointerdown',
+ RESIZE: 'resize',
+ TOUCHSTART: 'touchstart',
+ TOUCHMOVE: 'touchmove',
+ TOUCHEND: 'touchend',
+ WHEEL: 'wheel'
};
/**
- * Get a value from an object multiple levels deep. This is useful for
- * pulling values from deeply nested objects, such as JSON responses.
- * Example usage: getValueByKeys(jsonObj, 'foo', 'entries', 3)
- *
- * @param {!Object} obj An object to get the value from. Can be array-like.
- * @param {...(string|number|!Array<number|string>)} var_args A number of keys
- * (as strings, or numbers, for array-like objects). Can also be
- * specified as a single array of keys.
- * @return {*} The resulting value. If, at any point, the value for a key
- * is undefined, returns undefined.
+ * @enum {number}
+ * @const
*/
-goog.object.getValueByKeys = function(obj, var_args) {
- var isArrayLike = goog.isArrayLike(var_args);
- var keys = isArrayLike ? var_args : arguments;
-
- // Start with the 2nd parameter for the variable parameters syntax.
- for (var i = isArrayLike ? 0 : 1; i < keys.length; i++) {
- obj = obj[keys[i]];
- if (!goog.isDef(obj)) {
- break;
- }
- }
-
- return obj;
+ol.events.KeyCode = {
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40
};
/**
- * Whether the object/map/hash contains the given key.
- *
- * @param {Object} obj The object in which to look for key.
- * @param {*} key The key for which to check.
- * @return {boolean} true If the map contains the key.
+ * Property name on an event target for the listener map associated with the
+ * event target.
+ * @const {string}
+ * @private
*/
-goog.object.containsKey = function(obj, key) {
- return key in obj;
-};
+ol.events.LISTENER_MAP_PROP_ = 'olm_' + ((Math.random() * 1e4) | 0);
/**
- * Whether the object/map/hash contains the given value. This is O(n).
- *
- * @param {Object<K,V>} obj The object in which to look for val.
- * @param {V} val The value for which to check.
- * @return {boolean} true If the map contains the value.
- * @template K,V
+ * @param {ol.events.Key} listenerObj Listener object.
+ * @return {ol.events.ListenerFunctionType} Bound listener.
*/
-goog.object.containsValue = function(obj, val) {
- for (var key in obj) {
- if (obj[key] == val) {
- return true;
+ol.events.bindListener_ = function(listenerObj) {
+ var boundListener = function(evt) {
+ var listener = listenerObj.listener;
+ var bindTo = listenerObj.bindTo || listenerObj.target;
+ if (listenerObj.callOnce) {
+ ol.events.unlistenByKey(listenerObj);
}
+ return listener.call(bindTo, evt);
}
- return false;
+ listenerObj.boundListener = boundListener;
+ return boundListener;
};
/**
- * Searches an object for an element that satisfies the given condition and
- * returns its key.
- * @param {Object<K,V>} obj The object to search in.
- * @param {function(this:T,V,string,Object<K,V>):boolean} f The
- * function to call for every element. Takes 3 arguments (the value,
- * the key and the object) and should return a boolean.
- * @param {T=} opt_this An optional "this" context for the function.
- * @return {string|undefined} The key of an element for which the function
- * returns true or undefined if no such element is found.
- * @template T,K,V
+ * Finds the matching {@link ol.events.Key} in the given listener
+ * array.
+ *
+ * @param {!Array<!ol.events.Key>} listeners Array of listeners.
+ * @param {!Function} listener The listener function.
+ * @param {Object=} opt_this The `this` value inside the listener.
+ * @param {boolean=} opt_setDeleteIndex Set the deleteIndex on the matching
+ * listener, for {@link ol.events.unlistenByKey}.
+ * @return {ol.events.Key|undefined} The matching listener object.
+ * @private
*/
-goog.object.findKey = function(obj, f, opt_this) {
- for (var key in obj) {
- if (f.call(opt_this, obj[key], key, obj)) {
- return key;
+ol.events.findListener_ = function(listeners, listener, opt_this,
+ opt_setDeleteIndex) {
+ var listenerObj;
+ for (var i = 0, ii = listeners.length; i < ii; ++i) {
+ listenerObj = listeners[i];
+ if (listenerObj.listener === listener &&
+ listenerObj.bindTo === opt_this) {
+ if (opt_setDeleteIndex) {
+ listenerObj.deleteIndex = i;
+ }
+ return listenerObj;
}
}
return undefined;
@@ -7713,6402 +6165,3835 @@ goog.object.findKey = function(obj, f, opt_this) {
/**
- * Searches an object for an element that satisfies the given condition and
- * returns its value.
- * @param {Object<K,V>} obj The object to search in.
- * @param {function(this:T,V,string,Object<K,V>):boolean} f The function
- * to call for every element. Takes 3 arguments (the value, the key
- * and the object) and should return a boolean.
- * @param {T=} opt_this An optional "this" context for the function.
- * @return {V} The value of an element for which the function returns true or
- * undefined if no such element is found.
- * @template T,K,V
- */
-goog.object.findValue = function(obj, f, opt_this) {
- var key = goog.object.findKey(obj, f, opt_this);
- return key && obj[key];
-};
-
-
-/**
- * Whether the object/map/hash is empty.
- *
- * @param {Object} obj The object to test.
- * @return {boolean} true if obj is empty.
+ * @param {ol.events.EventTargetLike} target Target.
+ * @param {string} type Type.
+ * @return {Array.<ol.events.Key>|undefined} Listeners.
*/
-goog.object.isEmpty = function(obj) {
- for (var key in obj) {
- return false;
- }
- return true;
+ol.events.getListeners = function(target, type) {
+ var listenerMap = target[ol.events.LISTENER_MAP_PROP_];
+ return listenerMap ? listenerMap[type] : undefined;
};
/**
- * Removes all key value pairs from the object/map/hash.
- *
- * @param {Object} obj The object to clear.
+ * Get the lookup of listeners. If one does not exist on the target, it is
+ * created.
+ * @param {ol.events.EventTargetLike} target Target.
+ * @return {!Object.<string, Array.<ol.events.Key>>} Map of
+ * listeners by event type.
+ * @private
*/
-goog.object.clear = function(obj) {
- for (var i in obj) {
- delete obj[i];
+ol.events.getListenerMap_ = function(target) {
+ var listenerMap = target[ol.events.LISTENER_MAP_PROP_];
+ if (!listenerMap) {
+ listenerMap = target[ol.events.LISTENER_MAP_PROP_] = {};
}
+ return listenerMap;
};
/**
- * Removes a key-value pair based on the key.
- *
- * @param {Object} obj The object from which to remove the key.
- * @param {*} key The key to remove.
- * @return {boolean} Whether an element was removed.
+ * Clean up all listener objects of the given type. All properties on the
+ * listener objects will be removed, and if no listeners remain in the listener
+ * map, it will be removed from the target.
+ * @param {ol.events.EventTargetLike} target Target.
+ * @param {string} type Type.
+ * @private
*/
-goog.object.remove = function(obj, key) {
- var rv;
- if ((rv = key in obj)) {
- delete obj[key];
+ol.events.removeListeners_ = function(target, type) {
+ var listeners = ol.events.getListeners(target, type);
+ if (listeners) {
+ for (var i = 0, ii = listeners.length; i < ii; ++i) {
+ target.removeEventListener(type, listeners[i].boundListener);
+ ol.object.clear(listeners[i])
+ }
+ listeners.length = 0;
+ var listenerMap = target[ol.events.LISTENER_MAP_PROP_];
+ if (listenerMap) {
+ delete listenerMap[type];
+ if (Object.keys(listenerMap).length === 0) {
+ delete target[ol.events.LISTENER_MAP_PROP_];
+ }
+ }
}
- return rv;
};
/**
- * Adds a key-value pair to the object. Throws an exception if the key is
- * already in use. Use set if you want to change an existing pair.
+ * Registers an event listener on an event target. Inspired by
+ * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
- * @param {Object<K,V>} obj The object to which to add the key-value pair.
- * @param {string} key The key to add.
- * @param {V} val The value to add.
- * @template K,V
- */
-goog.object.add = function(obj, key, val) {
- if (key in obj) {
- throw Error('The object already contains the key "' + key + '"');
- }
- goog.object.set(obj, key, val);
-};
-
-
-/**
- * Returns the value for the given key.
+ * This function efficiently binds a `listener` to a `this` object, and returns
+ * a key for use with {@link ol.events.unlistenByKey}.
*
- * @param {Object<K,V>} obj The object from which to get the value.
- * @param {string} key The key for which to get the value.
- * @param {R=} opt_val The value to return if no item is found for the given
- * key (default is undefined).
- * @return {V|R|undefined} The value for the given key.
- * @template K,V,R
- */
-goog.object.get = function(obj, key, opt_val) {
- if (key in obj) {
- return obj[key];
+ * @param {ol.events.EventTargetLike} target Event target.
+ * @param {string} type Event type.
+ * @param {ol.events.ListenerFunctionType} listener Listener.
+ * @param {Object=} opt_this Object referenced by the `this` keyword in the
+ * listener. Default is the `target`.
+ * @param {boolean=} opt_once If true, add the listener as one-off listener.
+ * @return {ol.events.Key} Unique key for the listener.
+ */
+ol.events.listen = function(target, type, listener, opt_this, opt_once) {
+ var listenerMap = ol.events.getListenerMap_(target);
+ var listeners = listenerMap[type];
+ if (!listeners) {
+ listeners = listenerMap[type] = [];
+ }
+ var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
+ false);
+ if (listenerObj) {
+ if (!opt_once) {
+ // Turn one-off listener into a permanent one.
+ listenerObj.callOnce = false;
+ }
+ } else {
+ listenerObj = /** @type {ol.events.Key} */ ({
+ bindTo: opt_this,
+ callOnce: !!opt_once,
+ listener: listener,
+ target: target,
+ type: type
+ });
+ target.addEventListener(type, ol.events.bindListener_(listenerObj));
+ listeners.push(listenerObj);
}
- return opt_val;
-};
-
-/**
- * Adds a key-value pair to the object/map/hash.
- *
- * @param {Object<K,V>} obj The object to which to add the key-value pair.
- * @param {string} key The key to add.
- * @param {V} value The value to add.
- * @template K,V
- */
-goog.object.set = function(obj, key, value) {
- obj[key] = value;
+ return listenerObj;
};
/**
- * Adds a key-value pair to the object/map/hash if it doesn't exist yet.
+ * Registers a one-off event listener on an event target. Inspired by
+ * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
- * @param {Object<K,V>} obj The object to which to add the key-value pair.
- * @param {string} key The key to add.
- * @param {V} value The value to add if the key wasn't present.
- * @return {V} The value of the entry at the end of the function.
- * @template K,V
- */
-goog.object.setIfUndefined = function(obj, key, value) {
- return key in obj ? obj[key] : (obj[key] = value);
-};
-
-
-/**
- * Sets a key and value to an object if the key is not set. The value will be
- * the return value of the given function. If the key already exists, the
- * object will not be changed and the function will not be called (the function
- * will be lazily evaluated -- only called if necessary).
+ * This function efficiently binds a `listener` as self-unregistering listener
+ * to a `this` object, and returns a key for use with
+ * {@link ol.events.unlistenByKey} in case the listener needs to be unregistered
+ * before it is called.
*
- * This function is particularly useful for use with a map used a as a cache.
+ * When {@link ol.events.listen} is called with the same arguments after this
+ * function, the self-unregistering listener will be turned into a permanent
+ * listener.
*
- * @param {!Object<K,V>} obj The object to which to add the key-value pair.
- * @param {string} key The key to add.
- * @param {function():V} f The value to add if the key wasn't present.
- * @return {V} The value of the entry at the end of the function.
- * @template K,V
+ * @param {ol.events.EventTargetLike} target Event target.
+ * @param {string} type Event type.
+ * @param {ol.events.ListenerFunctionType} listener Listener.
+ * @param {Object=} opt_this Object referenced by the `this` keyword in the
+ * listener. Default is the `target`.
+ * @return {ol.events.Key} Key for unlistenByKey.
*/
-goog.object.setWithReturnValueIfNotSet = function(obj, key, f) {
- if (key in obj) {
- return obj[key];
- }
-
- var val = f();
- obj[key] = val;
- return val;
+ol.events.listenOnce = function(target, type, listener, opt_this) {
+ return ol.events.listen(target, type, listener, opt_this, true);
};
/**
- * Compares two objects for equality using === on the values.
+ * Unregisters an event listener on an event target. Inspired by
+ * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
- * @param {!Object<K,V>} a
- * @param {!Object<K,V>} b
- * @return {boolean}
- * @template K,V
- */
-goog.object.equals = function(a, b) {
- for (var k in a) {
- if (!(k in b) || a[k] !== b[k]) {
- return false;
- }
- }
- for (var k in b) {
- if (!(k in a)) {
- return false;
- }
- }
- return true;
-};
-
-
-/**
- * Does a flat clone of the object.
+ * To return a listener, this function needs to be called with the exact same
+ * arguments that were used for a previous {@link ol.events.listen} call.
*
- * @param {Object<K,V>} obj Object to clone.
- * @return {!Object<K,V>} Clone of the input object.
- * @template K,V
- */
-goog.object.clone = function(obj) {
- // We cannot use the prototype trick because a lot of methods depend on where
- // the actual key is set.
-
- var res = {};
- for (var key in obj) {
- res[key] = obj[key];
+ * @param {ol.events.EventTargetLike} target Event target.
+ * @param {string} type Event type.
+ * @param {ol.events.ListenerFunctionType} listener Listener.
+ * @param {Object=} opt_this Object referenced by the `this` keyword in the
+ * listener. Default is the `target`.
+ */
+ol.events.unlisten = function(target, type, listener, opt_this) {
+ var listeners = ol.events.getListeners(target, type);
+ if (listeners) {
+ var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
+ true);
+ if (listenerObj) {
+ ol.events.unlistenByKey(listenerObj);
+ }
}
- return res;
- // We could also use goog.mixin but I wanted this to be independent from that.
};
/**
- * Clones a value. The input may be an Object, Array, or basic type. Objects and
- * arrays will be cloned recursively.
+ * Unregisters event listeners on an event target. Inspired by
+ * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
- * WARNINGS:
- * <code>goog.object.unsafeClone</code> does not detect reference loops. Objects
- * that refer to themselves will cause infinite recursion.
+ * The argument passed to this function is the key returned from
+ * {@link ol.events.listen} or {@link ol.events.listenOnce}.
*
- * <code>goog.object.unsafeClone</code> is unaware of unique identifiers, and
- * copies UIDs created by <code>getUid</code> into cloned results.
- *
- * @param {*} obj The value to clone.
- * @return {*} A clone of the input value.
+ * @param {ol.events.Key} key The key.
*/
-goog.object.unsafeClone = function(obj) {
- var type = goog.typeOf(obj);
- if (type == 'object' || type == 'array') {
- if (goog.isFunction(obj.clone)) {
- return obj.clone();
- }
- var clone = type == 'array' ? [] : {};
- for (var key in obj) {
- clone[key] = goog.object.unsafeClone(obj[key]);
+ol.events.unlistenByKey = function(key) {
+ if (key && key.target) {
+ key.target.removeEventListener(key.type, key.boundListener);
+ var listeners = ol.events.getListeners(key.target, key.type);
+ if (listeners) {
+ var i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key);
+ if (i !== -1) {
+ listeners.splice(i, 1);
+ }
+ if (listeners.length === 0) {
+ ol.events.removeListeners_(key.target, key.type);
+ }
}
- return clone;
+ ol.object.clear(key);
}
-
- return obj;
};
/**
- * Returns a new object in which all the keys and values are interchanged
- * (keys become values and values become keys). If multiple keys map to the
- * same value, the chosen transposed value is implementation-dependent.
+ * Unregisters all event listeners on an event target. Inspired by
+ * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
- * @param {Object} obj The object to transpose.
- * @return {!Object} The transposed object.
+ * @param {ol.events.EventTargetLike} target Target.
*/
-goog.object.transpose = function(obj) {
- var transposed = {};
- for (var key in obj) {
- transposed[obj[key]] = key;
+ol.events.unlistenAll = function(target) {
+ var listenerMap = ol.events.getListenerMap_(target);
+ for (var type in listenerMap) {
+ ol.events.removeListeners_(target, type);
}
- return transposed;
};
+goog.provide('ol.Disposable');
-/**
- * The names of the fields that are defined on Object.prototype.
- * @type {Array<string>}
- * @private
- */
-goog.object.PROTOTYPE_FIELDS_ = [
- 'constructor',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'toLocaleString',
- 'toString',
- 'valueOf'
-];
-
+goog.require('ol');
/**
- * Extends an object with another object.
- * This operates 'in-place'; it does not create a new Object.
- *
- * Example:
- * var o = {};
- * goog.object.extend(o, {a: 0, b: 1});
- * o; // {a: 0, b: 1}
- * goog.object.extend(o, {b: 2, c: 3});
- * o; // {a: 0, b: 2, c: 3}
- *
- * @param {Object} target The object to modify. Existing properties will be
- * overwritten if they are also present in one of the objects in
- * {@code var_args}.
- * @param {...Object} var_args The objects from which values will be copied.
+ * Objects that need to clean up after themselves.
+ * @constructor
*/
-goog.object.extend = function(target, var_args) {
- var key, source;
- for (var i = 1; i < arguments.length; i++) {
- source = arguments[i];
- for (key in source) {
- target[key] = source[key];
- }
-
- // For IE the for-in-loop does not contain any properties that are not
- // enumerable on the prototype object (for example isPrototypeOf from
- // Object.prototype) and it will also not include 'replace' on objects that
- // extend String and change 'replace' (not that it is common for anyone to
- // extend anything except Object).
-
- for (var j = 0; j < goog.object.PROTOTYPE_FIELDS_.length; j++) {
- key = goog.object.PROTOTYPE_FIELDS_[j];
- if (Object.prototype.hasOwnProperty.call(source, key)) {
- target[key] = source[key];
- }
- }
- }
-};
-
+ol.Disposable = function() {};
/**
- * Creates a new object built from the key-value pairs provided as arguments.
- * @param {...*} var_args If only one argument is provided and it is an array
- * then this is used as the arguments, otherwise even arguments are used as
- * the property names and odd arguments are used as the property values.
- * @return {!Object} The new object.
- * @throws {Error} If there are uneven number of arguments or there is only one
- * non array argument.
+ * The object has already been disposed.
+ * @type {boolean}
+ * @private
*/
-goog.object.create = function(var_args) {
- var argLength = arguments.length;
- if (argLength == 1 && goog.isArray(arguments[0])) {
- return goog.object.create.apply(null, arguments[0]);
- }
-
- if (argLength % 2) {
- throw Error('Uneven number of arguments');
- }
-
- var rv = {};
- for (var i = 0; i < argLength; i += 2) {
- rv[arguments[i]] = arguments[i + 1];
- }
- return rv;
-};
-
+ol.Disposable.prototype.disposed_ = false;
/**
- * Creates a new object where the property names come from the arguments but
- * the value is always set to true
- * @param {...*} var_args If only one argument is provided and it is an array
- * then this is used as the arguments, otherwise the arguments are used
- * as the property names.
- * @return {!Object} The new object.
+ * Clean up.
*/
-goog.object.createSet = function(var_args) {
- var argLength = arguments.length;
- if (argLength == 1 && goog.isArray(arguments[0])) {
- return goog.object.createSet.apply(null, arguments[0]);
- }
-
- var rv = {};
- for (var i = 0; i < argLength; i++) {
- rv[arguments[i]] = true;
+ol.Disposable.prototype.dispose = function() {
+ if (!this.disposed_) {
+ this.disposed_ = true;
+ this.disposeInternal();
}
- return rv;
};
-
/**
- * Creates an immutable view of the underlying object, if the browser
- * supports immutable objects.
- *
- * In default mode, writes to this view will fail silently. In strict mode,
- * they will throw an error.
- *
- * @param {!Object<K,V>} obj An object.
- * @return {!Object<K,V>} An immutable view of that object, or the
- * original object if this browser does not support immutables.
- * @template K,V
+ * Extension point for disposable objects.
+ * @protected
*/
-goog.object.createImmutableView = function(obj) {
- var result = obj;
- if (Object.isFrozen && !Object.isFrozen(obj)) {
- result = Object.create(obj);
- Object.freeze(result);
- }
- return result;
-};
+ol.Disposable.prototype.disposeInternal = ol.nullFunction;
+goog.provide('ol.events.Event');
-/**
- * @param {!Object} obj An object.
- * @return {boolean} Whether this is an immutable view of the object.
- */
-goog.object.isImmutableView = function(obj) {
- return !!Object.isFrozen && Object.isFrozen(obj);
-};
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Closure user agent detection (Browser).
- * @see <a href="http://www.useragentstring.com/">User agent strings</a>
- * For more information on rendering engine, platform, or device see the other
- * sub-namespaces in goog.labs.userAgent, goog.labs.userAgent.platform,
- * goog.labs.userAgent.device respectively.)
+ * @classdesc
+ * Stripped down implementation of the W3C DOM Level 2 Event interface.
+ * @see {@link https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface}
*
- * @author martone@google.com (Andy Martone)
- */
-
-goog.provide('goog.labs.userAgent.browser');
-
-goog.require('goog.array');
-goog.require('goog.labs.userAgent.util');
-goog.require('goog.object');
-goog.require('goog.string');
-
-
-// TODO(nnaze): Refactor to remove excessive exclusion logic in matching
-// functions.
-
-
-/**
- * @return {boolean} Whether the user's browser is Opera.
- * @private
- */
-goog.labs.userAgent.browser.matchOpera_ = function() {
- return goog.labs.userAgent.util.matchUserAgent('Opera') ||
- goog.labs.userAgent.util.matchUserAgent('OPR');
-};
-
-
-/**
- * @return {boolean} Whether the user's browser is IE.
- * @private
- */
-goog.labs.userAgent.browser.matchIE_ = function() {
- return goog.labs.userAgent.util.matchUserAgent('Trident') ||
- goog.labs.userAgent.util.matchUserAgent('MSIE');
-};
-
-
-/**
- * @return {boolean} Whether the user's browser is Edge.
- * @private
+ * This implementation only provides `type` and `target` properties, and
+ * `stopPropagation` and `preventDefault` methods. It is meant as base class
+ * for higher level events defined in the library, and works with
+ * {@link ol.events.EventTarget}.
+ *
+ * @constructor
+ * @implements {oli.events.Event}
+ * @param {string} type Type.
+ * @param {Object=} opt_target Target.
*/
-goog.labs.userAgent.browser.matchEdge_ = function() {
- return goog.labs.userAgent.util.matchUserAgent('Edge');
-};
+ol.events.Event = function(type, opt_target) {
+ /**
+ * @type {boolean}
+ */
+ this.propagationStopped;
-/**
- * @return {boolean} Whether the user's browser is Firefox.
- * @private
- */
-goog.labs.userAgent.browser.matchFirefox_ = function() {
- return goog.labs.userAgent.util.matchUserAgent('Firefox');
-};
+ /**
+ * The event type.
+ * @type {string}
+ * @api stable
+ */
+ this.type = type;
+ /**
+ * The event target.
+ * @type {Object}
+ * @api stable
+ */
+ this.target = opt_target || null;
-/**
- * @return {boolean} Whether the user's browser is Safari.
- * @private
- */
-goog.labs.userAgent.browser.matchSafari_ = function() {
- return goog.labs.userAgent.util.matchUserAgent('Safari') &&
- !(goog.labs.userAgent.browser.matchChrome_() ||
- goog.labs.userAgent.browser.matchCoast_() ||
- goog.labs.userAgent.browser.matchOpera_() ||
- goog.labs.userAgent.browser.matchEdge_() ||
- goog.labs.userAgent.browser.isSilk() ||
- goog.labs.userAgent.util.matchUserAgent('Android'));
};
/**
- * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based
- * iOS browser).
- * @private
+ * Stop event propagation.
+ * @function
+ * @api stable
*/
-goog.labs.userAgent.browser.matchCoast_ = function() {
- return goog.labs.userAgent.util.matchUserAgent('Coast');
-};
-
+ol.events.Event.prototype.preventDefault =
/**
- * @return {boolean} Whether the user's browser is iOS Webview.
- * @private
+ * Stop event propagation.
+ * @function
+ * @api stable
*/
-goog.labs.userAgent.browser.matchIosWebview_ = function() {
- // iOS Webview does not show up as Chrome or Safari. Also check for Opera's
- // WebKit-based iOS browser, Coast.
- return (goog.labs.userAgent.util.matchUserAgent('iPad') ||
- goog.labs.userAgent.util.matchUserAgent('iPhone')) &&
- !goog.labs.userAgent.browser.matchSafari_() &&
- !goog.labs.userAgent.browser.matchChrome_() &&
- !goog.labs.userAgent.browser.matchCoast_() &&
- goog.labs.userAgent.util.matchUserAgent('AppleWebKit');
+ol.events.Event.prototype.stopPropagation = function() {
+ this.propagationStopped = true;
};
/**
- * @return {boolean} Whether the user's browser is Chrome.
- * @private
+ * @param {Event|ol.events.Event} evt Event
*/
-goog.labs.userAgent.browser.matchChrome_ = function() {
- return (goog.labs.userAgent.util.matchUserAgent('Chrome') ||
- goog.labs.userAgent.util.matchUserAgent('CriOS')) &&
- !goog.labs.userAgent.browser.matchOpera_() &&
- !goog.labs.userAgent.browser.matchEdge_();
+ol.events.Event.stopPropagation = function(evt) {
+ evt.stopPropagation();
};
/**
- * @return {boolean} Whether the user's browser is the Android browser.
- * @private
+ * @param {Event|ol.events.Event} evt Event
*/
-goog.labs.userAgent.browser.matchAndroidBrowser_ = function() {
- // Android can appear in the user agent string for Chrome on Android.
- // This is not the Android standalone browser if it does.
- return goog.labs.userAgent.util.matchUserAgent('Android') &&
- !(goog.labs.userAgent.browser.isChrome() ||
- goog.labs.userAgent.browser.isFirefox() ||
- goog.labs.userAgent.browser.isOpera() ||
- goog.labs.userAgent.browser.isSilk());
+ol.events.Event.preventDefault = function(evt) {
+ evt.preventDefault();
};
+goog.provide('ol.events.EventTarget');
-/**
- * @return {boolean} Whether the user's browser is Opera.
- */
-goog.labs.userAgent.browser.isOpera = goog.labs.userAgent.browser.matchOpera_;
-
-
-/**
- * @return {boolean} Whether the user's browser is IE.
- */
-goog.labs.userAgent.browser.isIE = goog.labs.userAgent.browser.matchIE_;
-
-
-/**
- * @return {boolean} Whether the user's browser is Edge.
- */
-goog.labs.userAgent.browser.isEdge = goog.labs.userAgent.browser.matchEdge_;
-
-
-/**
- * @return {boolean} Whether the user's browser is Firefox.
- */
-goog.labs.userAgent.browser.isFirefox =
- goog.labs.userAgent.browser.matchFirefox_;
-
-
-/**
- * @return {boolean} Whether the user's browser is Safari.
- */
-goog.labs.userAgent.browser.isSafari =
- goog.labs.userAgent.browser.matchSafari_;
-
-
-/**
- * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based
- * iOS browser).
- */
-goog.labs.userAgent.browser.isCoast =
- goog.labs.userAgent.browser.matchCoast_;
-
+goog.require('goog.asserts');
+goog.require('ol.Disposable');
+goog.require('ol.events');
+goog.require('ol.events.Event');
/**
- * @return {boolean} Whether the user's browser is iOS Webview.
+ * @classdesc
+ * A simplified implementation of the W3C DOM Level 2 EventTarget interface.
+ * @see {@link https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget}
+ *
+ * There are two important simplifications compared to the specification:
+ *
+ * 1. The handling of `useCapture` in `addEventListener` and
+ * `removeEventListener`. There is no real capture model.
+ * 2. The handling of `stopPropagation` and `preventDefault` on `dispatchEvent`.
+ * There is no event target hierarchy. When a listener calls
+ * `stopPropagation` or `preventDefault` on an event object, it means that no
+ * more listeners after this one will be called. Same as when the listener
+ * returns false.
+ *
+ * @constructor
+ * @extends {ol.Disposable}
*/
-goog.labs.userAgent.browser.isIosWebview =
- goog.labs.userAgent.browser.matchIosWebview_;
+ol.events.EventTarget = function() {
+ goog.base(this);
-/**
- * @return {boolean} Whether the user's browser is Chrome.
- */
-goog.labs.userAgent.browser.isChrome =
- goog.labs.userAgent.browser.matchChrome_;
-
+ /**
+ * @private
+ * @type {!Object.<string, number>}
+ */
+ this.pendingRemovals_ = {};
-/**
- * @return {boolean} Whether the user's browser is the Android browser.
- */
-goog.labs.userAgent.browser.isAndroidBrowser =
- goog.labs.userAgent.browser.matchAndroidBrowser_;
+ /**
+ * @private
+ * @type {!Object.<string, number>}
+ */
+ this.dispatching_ = {};
+ /**
+ * @private
+ * @type {!Object.<string, Array.<ol.events.ListenerFunctionType>>}
+ */
+ this.listeners_ = {};
-/**
- * For more information, see:
- * http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
- * @return {boolean} Whether the user's browser is Silk.
- */
-goog.labs.userAgent.browser.isSilk = function() {
- return goog.labs.userAgent.util.matchUserAgent('Silk');
};
+goog.inherits(ol.events.EventTarget, ol.Disposable);
/**
- * @return {string} The browser version or empty string if version cannot be
- * determined. Note that for Internet Explorer, this returns the version of
- * the browser, not the version of the rendering engine. (IE 8 in
- * compatibility mode will return 8.0 rather than 7.0. To determine the
- * rendering engine version, look at document.documentMode instead. See
- * http://msdn.microsoft.com/en-us/library/cc196988(v=vs.85).aspx for more
- * details.)
+ * @param {string} type Type.
+ * @param {ol.events.ListenerFunctionType} listener Listener.
*/
-goog.labs.userAgent.browser.getVersion = function() {
- var userAgentString = goog.labs.userAgent.util.getUserAgent();
- // Special case IE since IE's version is inside the parenthesis and
- // without the '/'.
- if (goog.labs.userAgent.browser.isIE()) {
- return goog.labs.userAgent.browser.getIEVersion_(userAgentString);
- }
-
- var versionTuples = goog.labs.userAgent.util.extractVersionTuples(
- userAgentString);
-
- // Construct a map for easy lookup.
- var versionMap = {};
- goog.array.forEach(versionTuples, function(tuple) {
- // Note that the tuple is of length three, but we only care about the
- // first two.
- var key = tuple[0];
- var value = tuple[1];
- versionMap[key] = value;
- });
-
- var versionMapHasKey = goog.partial(goog.object.containsKey, versionMap);
-
- // Gives the value with the first key it finds, otherwise empty string.
- function lookUpValueWithKeys(keys) {
- var key = goog.array.find(keys, versionMapHasKey);
- return versionMap[key] || '';
- }
-
- // Check Opera before Chrome since Opera 15+ has "Chrome" in the string.
- // See
- // http://my.opera.com/ODIN/blog/2013/07/15/opera-user-agent-strings-opera-15-and-beyond
- if (goog.labs.userAgent.browser.isOpera()) {
- // Opera 10 has Version/10.0 but Opera/9.8, so look for "Version" first.
- // Opera uses 'OPR' for more recent UAs.
- return lookUpValueWithKeys(['Version', 'Opera', 'OPR']);
+ol.events.EventTarget.prototype.addEventListener = function(type, listener) {
+ var listeners = this.listeners_[type];
+ if (!listeners) {
+ listeners = this.listeners_[type] = [];
}
-
- // Check Edge before Chrome since it has Chrome in the string.
- if (goog.labs.userAgent.browser.isEdge()) {
- return lookUpValueWithKeys(['Edge']);
- }
-
- if (goog.labs.userAgent.browser.isChrome()) {
- return lookUpValueWithKeys(['Chrome', 'CriOS']);
+ if (listeners.indexOf(listener) === -1) {
+ listeners.push(listener);
}
-
- // Usually products browser versions are in the third tuple after "Mozilla"
- // and the engine.
- var tuple = versionTuples[2];
- return tuple && tuple[1] || '';
};
/**
- * @param {string|number} version The version to check.
- * @return {boolean} Whether the browser version is higher or the same as the
- * given version.
- */
-goog.labs.userAgent.browser.isVersionOrHigher = function(version) {
- return goog.string.compareVersions(goog.labs.userAgent.browser.getVersion(),
- version) >= 0;
-};
-
-
-/**
- * Determines IE version. More information:
- * http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx#uaString
- * http://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
- * http://blogs.msdn.com/b/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx
- * http://blogs.msdn.com/b/ie/archive/2009/01/09/the-internet-explorer-8-user-agent-string-updated-edition.aspx
- *
- * @param {string} userAgent the User-Agent.
- * @return {string}
- * @private
+ * @param {{type: string,
+ * target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
+ * string} event Event or event type.
+ * @return {boolean|undefined} `false` if anyone called preventDefault on the
+ * event object or if any of the listeners returned false.
*/
-goog.labs.userAgent.browser.getIEVersion_ = function(userAgent) {
- // IE11 may identify itself as MSIE 9.0 or MSIE 10.0 due to an IE 11 upgrade
- // bug. Example UA:
- // Mozilla/5.0 (MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)
- // like Gecko.
- // See http://www.whatismybrowser.com/developers/unknown-user-agent-fragments.
- var rv = /rv: *([\d\.]*)/.exec(userAgent);
- if (rv && rv[1]) {
- return rv[1];
- }
-
- var version = '';
- var msie = /MSIE +([\d\.]+)/.exec(userAgent);
- if (msie && msie[1]) {
- // IE in compatibility mode usually identifies itself as MSIE 7.0; in this
- // case, use the Trident version to determine the version of IE. For more
- // details, see the links above.
- var tridentVersion = /Trident\/(\d.\d)/.exec(userAgent);
- if (msie[1] == '7.0') {
- if (tridentVersion && tridentVersion[1]) {
- switch (tridentVersion[1]) {
- case '4.0':
- version = '8.0';
- break;
- case '5.0':
- version = '9.0';
- break;
- case '6.0':
- version = '10.0';
- break;
- case '7.0':
- version = '11.0';
- break;
- }
- } else {
- version = '7.0';
+ol.events.EventTarget.prototype.dispatchEvent = function(event) {
+ var evt = typeof event === 'string' ? new ol.events.Event(event) : event;
+ var type = evt.type;
+ evt.target = this;
+ var listeners = this.listeners_[type];
+ var propagate;
+ if (listeners) {
+ if (!(type in this.dispatching_)) {
+ this.dispatching_[type] = 0;
+ this.pendingRemovals_[type] = 0;
+ }
+ ++this.dispatching_[type];
+ for (var i = 0, ii = listeners.length; i < ii; ++i) {
+ if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
+ propagate = false;
+ break;
}
- } else {
- version = msie[1];
}
+ --this.dispatching_[type];
+ if (this.dispatching_[type] === 0) {
+ var pendingRemovals = this.pendingRemovals_[type];
+ delete this.pendingRemovals_[type];
+ while (pendingRemovals--) {
+ this.removeEventListener(type, ol.nullFunction);
+ }
+ delete this.dispatching_[type];
+ }
+ return propagate;
}
- return version;
};
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Closure user agent detection.
- * @see http://en.wikipedia.org/wiki/User_agent
- * For more information on browser brand, platform, or device see the other
- * sub-namespaces in goog.labs.userAgent (browser, platform, and device).
- *
- */
-
-goog.provide('goog.labs.userAgent.engine');
-
-goog.require('goog.array');
-goog.require('goog.labs.userAgent.util');
-goog.require('goog.string');
-
-
-/**
- * @return {boolean} Whether the rendering engine is Presto.
- */
-goog.labs.userAgent.engine.isPresto = function() {
- return goog.labs.userAgent.util.matchUserAgent('Presto');
-};
-
-
-/**
- * @return {boolean} Whether the rendering engine is Trident.
- */
-goog.labs.userAgent.engine.isTrident = function() {
- // IE only started including the Trident token in IE8.
- return goog.labs.userAgent.util.matchUserAgent('Trident') ||
- goog.labs.userAgent.util.matchUserAgent('MSIE');
-};
-
-
-/**
- * @return {boolean} Whether the rendering engine is Edge.
+ * @inheritDoc
*/
-goog.labs.userAgent.engine.isEdge = function() {
- return goog.labs.userAgent.util.matchUserAgent('Edge');
+ol.events.EventTarget.prototype.disposeInternal = function() {
+ ol.events.unlistenAll(this);
};
/**
- * @return {boolean} Whether the rendering engine is WebKit.
+ * Get the listeners for a specified event type. Listeners are returned in the
+ * order that they will be called in.
+ *
+ * @param {string} type Type.
+ * @return {Array.<ol.events.ListenerFunctionType>} Listeners.
*/
-goog.labs.userAgent.engine.isWebKit = function() {
- return goog.labs.userAgent.util.matchUserAgentIgnoreCase('WebKit') &&
- !goog.labs.userAgent.engine.isEdge();
+ol.events.EventTarget.prototype.getListeners = function(type) {
+ return this.listeners_[type];
};
/**
- * @return {boolean} Whether the rendering engine is Gecko.
+ * @param {string=} opt_type Type. If not provided,
+ * `true` will be returned if this EventTarget has any listeners.
+ * @return {boolean} Has listeners.
*/
-goog.labs.userAgent.engine.isGecko = function() {
- return goog.labs.userAgent.util.matchUserAgent('Gecko') &&
- !goog.labs.userAgent.engine.isWebKit() &&
- !goog.labs.userAgent.engine.isTrident() &&
- !goog.labs.userAgent.engine.isEdge();
+ol.events.EventTarget.prototype.hasListener = function(opt_type) {
+ return opt_type ?
+ opt_type in this.listeners_ :
+ Object.keys(this.listeners_).length > 0;
};
/**
- * @return {string} The rendering engine's version or empty string if version
- * can't be determined.
- */
-goog.labs.userAgent.engine.getVersion = function() {
- var userAgentString = goog.labs.userAgent.util.getUserAgent();
- if (userAgentString) {
- var tuples = goog.labs.userAgent.util.extractVersionTuples(
- userAgentString);
-
- var engineTuple = goog.labs.userAgent.engine.getEngineTuple_(tuples);
- if (engineTuple) {
- // In Gecko, the version string is either in the browser info or the
- // Firefox version. See Gecko user agent string reference:
- // http://goo.gl/mULqa
- if (engineTuple[0] == 'Gecko') {
- return goog.labs.userAgent.engine.getVersionForKey_(
- tuples, 'Firefox');
- }
-
- return engineTuple[1];
- }
-
- // MSIE has only one version identifier, and the Trident version is
- // specified in the parenthetical. IE Edge is covered in the engine tuple
- // detection.
- var browserTuple = tuples[0];
- var info;
- if (browserTuple && (info = browserTuple[2])) {
- var match = /Trident\/([^\s;]+)/.exec(info);
- if (match) {
- return match[1];
+ * @param {string} type Type.
+ * @param {ol.events.ListenerFunctionType} listener Listener.
+ */
+ol.events.EventTarget.prototype.removeEventListener = function(type, listener) {
+ var listeners = this.listeners_[type];
+ if (listeners) {
+ var index = listeners.indexOf(listener);
+ goog.asserts.assert(index != -1, 'listener not found');
+ if (type in this.pendingRemovals_) {
+ // make listener a no-op, and remove later in #dispatchEvent()
+ listeners[index] = ol.nullFunction;
+ ++this.pendingRemovals_[type];
+ } else {
+ listeners.splice(index, 1);
+ if (listeners.length === 0) {
+ delete this.listeners_[type];
}
}
}
- return '';
-};
-
-
-/**
- * @param {!Array<!Array<string>>} tuples Extracted version tuples.
- * @return {!Array<string>|undefined} The engine tuple or undefined if not
- * found.
- * @private
- */
-goog.labs.userAgent.engine.getEngineTuple_ = function(tuples) {
- if (!goog.labs.userAgent.engine.isEdge()) {
- return tuples[1];
- }
- for (var i = 0; i < tuples.length; i++) {
- var tuple = tuples[i];
- if (tuple[0] == 'Edge') {
- return tuple;
- }
- }
};
+goog.provide('ol.Observable');
-/**
- * @param {string|number} version The version to check.
- * @return {boolean} Whether the rendering engine version is higher or the same
- * as the given version.
- */
-goog.labs.userAgent.engine.isVersionOrHigher = function(version) {
- return goog.string.compareVersions(goog.labs.userAgent.engine.getVersion(),
- version) >= 0;
-};
-
-
-/**
- * @param {!Array<!Array<string>>} tuples Version tuples.
- * @param {string} key The key to look for.
- * @return {string} The version string of the given key, if present.
- * Otherwise, the empty string.
- * @private
- */
-goog.labs.userAgent.engine.getVersionForKey_ = function(tuples, key) {
- // TODO(nnaze): Move to util if useful elsewhere.
-
- var pair = goog.array.find(tuples, function(pair) {
- return key == pair[0];
- });
-
- return pair && pair[1] || '';
-};
+goog.require('ol.events');
+goog.require('ol.events.EventTarget');
+goog.require('ol.events.EventType');
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Closure user agent platform detection.
- * @see <a href="http://www.useragentstring.com/">User agent strings</a>
- * For more information on browser brand, rendering engine, or device see the
- * other sub-namespaces in goog.labs.userAgent (browser, engine, and device
- * respectively).
+ * @classdesc
+ * Abstract base class; normally only used for creating subclasses and not
+ * instantiated in apps.
+ * An event target providing convenient methods for listener registration
+ * and unregistration. A generic `change` event is always available through
+ * {@link ol.Observable#changed}.
*
+ * @constructor
+ * @extends {ol.events.EventTarget}
+ * @fires change
+ * @struct
+ * @api stable
*/
+ol.Observable = function() {
-goog.provide('goog.labs.userAgent.platform');
-
-goog.require('goog.labs.userAgent.util');
-goog.require('goog.string');
-
-
-/**
- * @return {boolean} Whether the platform is Android.
- */
-goog.labs.userAgent.platform.isAndroid = function() {
- return goog.labs.userAgent.util.matchUserAgent('Android');
-};
-
-
-/**
- * @return {boolean} Whether the platform is iPod.
- */
-goog.labs.userAgent.platform.isIpod = function() {
- return goog.labs.userAgent.util.matchUserAgent('iPod');
-};
+ goog.base(this);
+ /**
+ * @private
+ * @type {number}
+ */
+ this.revision_ = 0;
-/**
- * @return {boolean} Whether the platform is iPhone.
- */
-goog.labs.userAgent.platform.isIphone = function() {
- return goog.labs.userAgent.util.matchUserAgent('iPhone') &&
- !goog.labs.userAgent.util.matchUserAgent('iPod') &&
- !goog.labs.userAgent.util.matchUserAgent('iPad');
};
+goog.inherits(ol.Observable, ol.events.EventTarget);
/**
- * @return {boolean} Whether the platform is iPad.
+ * Removes an event listener using the key returned by `on()` or `once()`.
+ * @param {ol.events.Key|Array.<ol.events.Key>} key The key returned by `on()`
+ * or `once()` (or an array of keys).
+ * @api stable
*/
-goog.labs.userAgent.platform.isIpad = function() {
- return goog.labs.userAgent.util.matchUserAgent('iPad');
+ol.Observable.unByKey = function(key) {
+ if (Array.isArray(key)) {
+ for (var i = 0, ii = key.length; i < ii; ++i) {
+ ol.events.unlistenByKey(key[i]);
+ }
+ } else {
+ ol.events.unlistenByKey(/** @type {ol.events.Key} */ (key));
+ }
};
/**
- * @return {boolean} Whether the platform is iOS.
+ * Increases the revision counter and dispatches a 'change' event.
+ * @api
*/
-goog.labs.userAgent.platform.isIos = function() {
- return goog.labs.userAgent.platform.isIphone() ||
- goog.labs.userAgent.platform.isIpad() ||
- goog.labs.userAgent.platform.isIpod();
+ol.Observable.prototype.changed = function() {
+ ++this.revision_;
+ this.dispatchEvent(ol.events.EventType.CHANGE);
};
/**
- * @return {boolean} Whether the platform is Mac.
+ * Triggered when the revision counter is increased.
+ * @event change
+ * @api
*/
-goog.labs.userAgent.platform.isMacintosh = function() {
- return goog.labs.userAgent.util.matchUserAgent('Macintosh');
-};
/**
- * Note: ChromeOS is not considered to be Linux as it does not report itself
- * as Linux in the user agent string.
- * @return {boolean} Whether the platform is Linux.
+ * Dispatches an event and calls all listeners listening for events
+ * of this type. The event parameter can either be a string or an
+ * Object with a `type` property.
+ *
+ * @param {{type: string,
+ * target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
+ * string} event Event object.
+ * @function
+ * @api
*/
-goog.labs.userAgent.platform.isLinux = function() {
- return goog.labs.userAgent.util.matchUserAgent('Linux');
-};
+ol.Observable.prototype.dispatchEvent;
/**
- * @return {boolean} Whether the platform is Windows.
+ * Get the version number for this object. Each time the object is modified,
+ * its version number will be incremented.
+ * @return {number} Revision.
+ * @api
*/
-goog.labs.userAgent.platform.isWindows = function() {
- return goog.labs.userAgent.util.matchUserAgent('Windows');
+ol.Observable.prototype.getRevision = function() {
+ return this.revision_;
};
/**
- * @return {boolean} Whether the platform is ChromeOS.
+ * Listen for a certain type of event.
+ * @param {string|Array.<string>} type The event type or array of event types.
+ * @param {function(?): ?} listener The listener function.
+ * @param {Object=} opt_this The object to use as `this` in `listener`.
+ * @return {ol.events.Key|Array.<ol.events.Key>} Unique key for the listener. If
+ * called with an array of event types as the first argument, the return
+ * will be an array of keys.
+ * @api stable
*/
-goog.labs.userAgent.platform.isChromeOS = function() {
- return goog.labs.userAgent.util.matchUserAgent('CrOS');
+ol.Observable.prototype.on = function(type, listener, opt_this) {
+ if (Array.isArray(type)) {
+ var len = type.length;
+ var keys = new Array(len);
+ for (var i = 0; i < len; ++i) {
+ keys[i] = ol.events.listen(this, type[i], listener, opt_this);
+ }
+ return keys;
+ } else {
+ return ol.events.listen(
+ this, /** @type {string} */ (type), listener, opt_this);
+ }
};
/**
- * The version of the platform. We only determine the version for Windows,
- * Mac, and Chrome OS. It doesn't make much sense on Linux. For Windows, we only
- * look at the NT version. Non-NT-based versions (e.g. 95, 98, etc.) are given
- * version 0.0.
- *
- * @return {string} The platform version or empty string if version cannot be
- * determined.
+ * Listen once for a certain type of event.
+ * @param {string|Array.<string>} type The event type or array of event types.
+ * @param {function(?): ?} listener The listener function.
+ * @param {Object=} opt_this The object to use as `this` in `listener`.
+ * @return {ol.events.Key|Array.<ol.events.Key>} Unique key for the listener. If
+ * called with an array of event types as the first argument, the return
+ * will be an array of keys.
+ * @api stable
*/
-goog.labs.userAgent.platform.getVersion = function() {
- var userAgentString = goog.labs.userAgent.util.getUserAgent();
- var version = '', re;
- if (goog.labs.userAgent.platform.isWindows()) {
- re = /Windows (?:NT|Phone) ([0-9.]+)/;
- var match = re.exec(userAgentString);
- if (match) {
- version = match[1];
- } else {
- version = '0.0';
+ol.Observable.prototype.once = function(type, listener, opt_this) {
+ if (Array.isArray(type)) {
+ var len = type.length;
+ var keys = new Array(len);
+ for (var i = 0; i < len; ++i) {
+ keys[i] = ol.events.listenOnce(this, type[i], listener, opt_this);
}
- } else if (goog.labs.userAgent.platform.isIos()) {
- re = /(?:iPhone|iPod|iPad|CPU)\s+OS\s+(\S+)/;
- var match = re.exec(userAgentString);
- // Report the version as x.y.z and not x_y_z
- version = match && match[1].replace(/_/g, '.');
- } else if (goog.labs.userAgent.platform.isMacintosh()) {
- re = /Mac OS X ([0-9_.]+)/;
- var match = re.exec(userAgentString);
- // Note: some old versions of Camino do not report an OSX version.
- // Default to 10.
- version = match ? match[1].replace(/_/g, '.') : '10';
- } else if (goog.labs.userAgent.platform.isAndroid()) {
- re = /Android\s+([^\);]+)(\)|;)/;
- var match = re.exec(userAgentString);
- version = match && match[1];
- } else if (goog.labs.userAgent.platform.isChromeOS()) {
- re = /(?:CrOS\s+(?:i686|x86_64)\s+([0-9.]+))/;
- var match = re.exec(userAgentString);
- version = match && match[1];
+ return keys;
+ } else {
+ return ol.events.listenOnce(
+ this, /** @type {string} */ (type), listener, opt_this);
}
- return version || '';
};
/**
- * @param {string|number} version The version to check.
- * @return {boolean} Whether the browser version is higher or the same as the
- * given version.
+ * Unlisten for a certain type of event.
+ * @param {string|Array.<string>} type The event type or array of event types.
+ * @param {function(?): ?} listener The listener function.
+ * @param {Object=} opt_this The object which was used as `this` by the
+ * `listener`.
+ * @api stable
*/
-goog.labs.userAgent.platform.isVersionOrHigher = function(version) {
- return goog.string.compareVersions(goog.labs.userAgent.platform.getVersion(),
- version) >= 0;
+ol.Observable.prototype.un = function(type, listener, opt_this) {
+ if (Array.isArray(type)) {
+ for (var i = 0, ii = type.length; i < ii; ++i) {
+ ol.events.unlisten(this, type[i], listener, opt_this);
+ }
+ return;
+ } else {
+ ol.events.unlisten(this, /** @type {string} */ (type), listener, opt_this);
+ }
};
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Rendering engine detection.
- * @see <a href="http://www.useragentstring.com/">User agent strings</a>
- * For information on the browser brand (such as Safari versus Chrome), see
- * goog.userAgent.product.
- * @author arv@google.com (Erik Arvidsson)
- * @see ../demos/useragent.html
- */
-
-goog.provide('goog.userAgent');
-
-goog.require('goog.labs.userAgent.browser');
-goog.require('goog.labs.userAgent.engine');
-goog.require('goog.labs.userAgent.platform');
-goog.require('goog.labs.userAgent.util');
-goog.require('goog.string');
-
-
-/**
- * @define {boolean} Whether we know at compile-time that the browser is IE.
- */
-goog.define('goog.userAgent.ASSUME_IE', false);
-
-
-/**
- * @define {boolean} Whether we know at compile-time that the browser is EDGE.
- */
-goog.define('goog.userAgent.ASSUME_EDGE', false);
-
-
-/**
- * @define {boolean} Whether we know at compile-time that the browser is GECKO.
- */
-goog.define('goog.userAgent.ASSUME_GECKO', false);
-
-
-/**
- * @define {boolean} Whether we know at compile-time that the browser is WEBKIT.
- */
-goog.define('goog.userAgent.ASSUME_WEBKIT', false);
-
-
-/**
- * @define {boolean} Whether we know at compile-time that the browser is a
- * mobile device running WebKit e.g. iPhone or Android.
- */
-goog.define('goog.userAgent.ASSUME_MOBILE_WEBKIT', false);
-
-
-/**
- * @define {boolean} Whether we know at compile-time that the browser is OPERA.
- */
-goog.define('goog.userAgent.ASSUME_OPERA', false);
-
/**
- * @define {boolean} Whether the
- * {@code goog.userAgent.isVersionOrHigher}
- * function will return true for any version.
- */
-goog.define('goog.userAgent.ASSUME_ANY_VERSION', false);
-
-
-/**
- * Whether we know the browser engine at compile-time.
- * @type {boolean}
- * @private
+ * Removes an event listener using the key returned by `on()` or `once()`.
+ * Note that using the {@link ol.Observable.unByKey} static function is to
+ * be preferred.
+ * @param {ol.events.Key|Array.<ol.events.Key>} key The key returned by `on()`
+ * or `once()` (or an array of keys).
+ * @function
+ * @api stable
*/
-goog.userAgent.BROWSER_KNOWN_ =
- goog.userAgent.ASSUME_IE ||
- goog.userAgent.ASSUME_EDGE ||
- goog.userAgent.ASSUME_GECKO ||
- goog.userAgent.ASSUME_MOBILE_WEBKIT ||
- goog.userAgent.ASSUME_WEBKIT ||
- goog.userAgent.ASSUME_OPERA;
+ol.Observable.prototype.unByKey = ol.Observable.unByKey;
+goog.provide('ol.Object');
+goog.provide('ol.ObjectEvent');
+goog.provide('ol.ObjectEventType');
-/**
- * Returns the userAgent string for the current browser.
- *
- * @return {string} The userAgent string.
- */
-goog.userAgent.getUserAgentString = function() {
- return goog.labs.userAgent.util.getUserAgent();
-};
+goog.require('ol.Observable');
+goog.require('ol.events');
+goog.require('ol.events.Event');
+goog.require('ol.object');
/**
- * TODO(nnaze): Change type to "Navigator" and update compilation targets.
- * @return {Object} The native navigator object.
+ * @enum {string}
*/
-goog.userAgent.getNavigator = function() {
- // Need a local navigator reference instead of using the global one,
- // to avoid the rare case where they reference different objects.
- // (in a WorkerPool, for example).
- return goog.global['navigator'] || null;
+ol.ObjectEventType = {
+ /**
+ * Triggered when a property is changed.
+ * @event ol.ObjectEvent#propertychange
+ * @api stable
+ */
+ PROPERTYCHANGE: 'propertychange'
};
/**
- * Whether the user agent is Opera.
- * @type {boolean}
- */
-goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_OPERA :
- goog.labs.userAgent.browser.isOpera();
-
-
-/**
- * Whether the user agent is Internet Explorer.
- * @type {boolean}
- */
-goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_IE :
- goog.labs.userAgent.browser.isIE();
-
-
-/**
- * Whether the user agent is Microsoft Edge.
- * @type {boolean}
- */
-goog.userAgent.EDGE = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_EDGE :
- goog.labs.userAgent.engine.isEdge();
-
-
-/**
- * Whether the user agent is MS Internet Explorer or MS Edge.
- * @type {boolean}
+ * @classdesc
+ * Events emitted by {@link ol.Object} instances are instances of this type.
+ *
+ * @param {string} type The event type.
+ * @param {string} key The property name.
+ * @param {*} oldValue The old value for `key`.
+ * @extends {ol.events.Event}
+ * @implements {oli.ObjectEvent}
+ * @constructor
*/
-goog.userAgent.EDGE_OR_IE = goog.userAgent.EDGE || goog.userAgent.IE;
-
+ol.ObjectEvent = function(type, key, oldValue) {
+ goog.base(this, type);
-/**
- * Whether the user agent is Gecko. Gecko is the rendering engine used by
- * Mozilla, Firefox, and others.
- * @type {boolean}
- */
-goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_GECKO :
- goog.labs.userAgent.engine.isGecko();
+ /**
+ * The name of the property whose value is changing.
+ * @type {string}
+ * @api stable
+ */
+ this.key = key;
+ /**
+ * The old value. To get the new value use `e.target.get(e.key)` where
+ * `e` is the event object.
+ * @type {*}
+ * @api stable
+ */
+ this.oldValue = oldValue;
-/**
- * Whether the user agent is WebKit. WebKit is the rendering engine that
- * Safari, Android and others use.
- * @type {boolean}
- */
-goog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT :
- goog.labs.userAgent.engine.isWebKit();
+};
+goog.inherits(ol.ObjectEvent, ol.events.Event);
/**
- * Whether the user agent is running on a mobile device.
+ * @classdesc
+ * Abstract base class; normally only used for creating subclasses and not
+ * instantiated in apps.
+ * Most non-trivial classes inherit from this.
*
- * This is a separate function so that the logic can be tested.
+ * This extends {@link ol.Observable} with observable properties, where each
+ * property is observable as well as the object as a whole.
*
- * TODO(nnaze): Investigate swapping in goog.labs.userAgent.device.isMobile().
+ * Classes that inherit from this have pre-defined properties, to which you can
+ * add your owns. The pre-defined properties are listed in this documentation as
+ * 'Observable Properties', and have their own accessors; for example,
+ * {@link ol.Map} has a `target` property, accessed with `getTarget()` and
+ * changed with `setTarget()`. Not all properties are however settable. There
+ * are also general-purpose accessors `get()` and `set()`. For example,
+ * `get('target')` is equivalent to `getTarget()`.
*
- * @return {boolean} Whether the user agent is running on a mobile device.
- * @private
- */
-goog.userAgent.isMobile_ = function() {
- return goog.userAgent.WEBKIT &&
- goog.labs.userAgent.util.matchUserAgent('Mobile');
-};
-
-
-/**
- * Whether the user agent is running on a mobile device.
+ * The `set` accessors trigger a change event, and you can monitor this by
+ * registering a listener. For example, {@link ol.View} has a `center`
+ * property, so `view.on('change:center', function(evt) {...});` would call the
+ * function whenever the value of the center property changes. Within the
+ * function, `evt.target` would be the view, so `evt.target.getCenter()` would
+ * return the new center.
*
- * TODO(nnaze): Consider deprecating MOBILE when labs.userAgent
- * is promoted as the gecko/webkit logic is likely inaccurate.
+ * You can add your own observable properties with
+ * `object.set('prop', 'value')`, and retrieve that with `object.get('prop')`.
+ * You can listen for changes on that property value with
+ * `object.on('change:prop', listener)`. You can get a list of all
+ * properties with {@link ol.Object#getProperties object.getProperties()}.
*
- * @type {boolean}
+ * Note that the observable properties are separate from standard JS properties.
+ * You can, for example, give your map object a title with
+ * `map.title='New title'` and with `map.set('title', 'Another title')`. The
+ * first will be a `hasOwnProperty`; the second will appear in
+ * `getProperties()`. Only the second is observable.
+ *
+ * Properties can be deleted by using the unset method. E.g.
+ * object.unset('foo').
+ *
+ * @constructor
+ * @extends {ol.Observable}
+ * @param {Object.<string, *>=} opt_values An object with key-value pairs.
+ * @fires ol.ObjectEvent
+ * @api
*/
-goog.userAgent.MOBILE = goog.userAgent.ASSUME_MOBILE_WEBKIT ||
- goog.userAgent.isMobile_();
-
+ol.Object = function(opt_values) {
+ goog.base(this);
-/**
- * Used while transitioning code to use WEBKIT instead.
- * @type {boolean}
- * @deprecated Use {@link goog.userAgent.product.SAFARI} instead.
- * TODO(nicksantos): Delete this from goog.userAgent.
- */
-goog.userAgent.SAFARI = goog.userAgent.WEBKIT;
+ // Call goog.getUid to ensure that the order of objects' ids is the same as
+ // the order in which they were created. This also helps to ensure that
+ // object properties are always added in the same order, which helps many
+ // JavaScript engines generate faster code.
+ goog.getUid(this);
+ /**
+ * @private
+ * @type {!Object.<string, *>}
+ */
+ this.values_ = {};
-/**
- * @return {string} the platform (operating system) the user agent is running
- * on. Default to empty string because navigator.platform may not be defined
- * (on Rhino, for example).
- * @private
- */
-goog.userAgent.determinePlatform_ = function() {
- var navigator = goog.userAgent.getNavigator();
- return navigator && navigator.platform || '';
+ if (opt_values !== undefined) {
+ this.setProperties(opt_values);
+ }
};
+goog.inherits(ol.Object, ol.Observable);
/**
- * The platform (operating system) the user agent is running on. Default to
- * empty string because navigator.platform may not be defined (on Rhino, for
- * example).
- * @type {string}
- */
-goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();
-
-
-/**
- * @define {boolean} Whether the user agent is running on a Macintosh operating
- * system.
- */
-goog.define('goog.userAgent.ASSUME_MAC', false);
-
-
-/**
- * @define {boolean} Whether the user agent is running on a Windows operating
- * system.
- */
-goog.define('goog.userAgent.ASSUME_WINDOWS', false);
-
-
-/**
- * @define {boolean} Whether the user agent is running on a Linux operating
- * system.
- */
-goog.define('goog.userAgent.ASSUME_LINUX', false);
-
-
-/**
- * @define {boolean} Whether the user agent is running on a X11 windowing
- * system.
- */
-goog.define('goog.userAgent.ASSUME_X11', false);
-
-
-/**
- * @define {boolean} Whether the user agent is running on Android.
- */
-goog.define('goog.userAgent.ASSUME_ANDROID', false);
-
-
-/**
- * @define {boolean} Whether the user agent is running on an iPhone.
- */
-goog.define('goog.userAgent.ASSUME_IPHONE', false);
-
-
-/**
- * @define {boolean} Whether the user agent is running on an iPad.
- */
-goog.define('goog.userAgent.ASSUME_IPAD', false);
-
-
-/**
- * @type {boolean}
* @private
+ * @type {Object.<string, string>}
*/
-goog.userAgent.PLATFORM_KNOWN_ =
- goog.userAgent.ASSUME_MAC ||
- goog.userAgent.ASSUME_WINDOWS ||
- goog.userAgent.ASSUME_LINUX ||
- goog.userAgent.ASSUME_X11 ||
- goog.userAgent.ASSUME_ANDROID ||
- goog.userAgent.ASSUME_IPHONE ||
- goog.userAgent.ASSUME_IPAD;
-
-
-/**
- * Whether the user agent is running on a Macintosh operating system.
- * @type {boolean}
- */
-goog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_MAC : goog.labs.userAgent.platform.isMacintosh();
-
-
-/**
- * Whether the user agent is running on a Windows operating system.
- * @type {boolean}
- */
-goog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_WINDOWS :
- goog.labs.userAgent.platform.isWindows();
+ol.Object.changeEventTypeCache_ = {};
/**
- * Whether the user agent is Linux per the legacy behavior of
- * goog.userAgent.LINUX, which considered ChromeOS to also be
- * Linux.
- * @return {boolean}
- * @private
+ * @param {string} key Key name.
+ * @return {string} Change name.
*/
-goog.userAgent.isLegacyLinux_ = function() {
- return goog.labs.userAgent.platform.isLinux() ||
- goog.labs.userAgent.platform.isChromeOS();
+ol.Object.getChangeEventType = function(key) {
+ return ol.Object.changeEventTypeCache_.hasOwnProperty(key) ?
+ ol.Object.changeEventTypeCache_[key] :
+ (ol.Object.changeEventTypeCache_[key] = 'change:' + key);
};
/**
- * Whether the user agent is running on a Linux operating system.
- *
- * Note that goog.userAgent.LINUX considers ChromeOS to be Linux,
- * while goog.labs.userAgent.platform considers ChromeOS and
- * Linux to be different OSes.
- *
- * @type {boolean}
- */
-goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_LINUX :
- goog.userAgent.isLegacyLinux_();
-
-
-/**
- * @return {boolean} Whether the user agent is an X11 windowing system.
- * @private
+ * Gets a value.
+ * @param {string} key Key name.
+ * @return {*} Value.
+ * @api stable
*/
-goog.userAgent.isX11_ = function() {
- var navigator = goog.userAgent.getNavigator();
- return !!navigator &&
- goog.string.contains(navigator['appVersion'] || '', 'X11');
+ol.Object.prototype.get = function(key) {
+ var value;
+ if (this.values_.hasOwnProperty(key)) {
+ value = this.values_[key];
+ }
+ return value;
};
/**
- * Whether the user agent is running on a X11 windowing system.
- * @type {boolean}
- */
-goog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_X11 :
- goog.userAgent.isX11_();
-
-
-/**
- * Whether the user agent is running on Android.
- * @type {boolean}
- */
-goog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_ANDROID :
- goog.labs.userAgent.platform.isAndroid();
-
-
-/**
- * Whether the user agent is running on an iPhone.
- * @type {boolean}
+ * Get a list of object property names.
+ * @return {Array.<string>} List of property names.
+ * @api stable
*/
-goog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_IPHONE :
- goog.labs.userAgent.platform.isIphone();
+ol.Object.prototype.getKeys = function() {
+ return Object.keys(this.values_);
+};
/**
- * Whether the user agent is running on an iPad.
- * @type {boolean}
+ * Get an object of all property names and values.
+ * @return {Object.<string, *>} Object.
+ * @api stable
*/
-goog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_IPAD :
- goog.labs.userAgent.platform.isIpad();
+ol.Object.prototype.getProperties = function() {
+ return ol.object.assign({}, this.values_);
+};
/**
- * @return {string} The string that describes the version number of the user
- * agent.
- * Assumes user agent is opera.
- * @private
+ * @param {string} key Key name.
+ * @param {*} oldValue Old value.
*/
-goog.userAgent.operaVersion_ = function() {
- var version = goog.global.opera.version;
- try {
- return version();
- } catch (e) {
- return version;
- }
+ol.Object.prototype.notify = function(key, oldValue) {
+ var eventType;
+ eventType = ol.Object.getChangeEventType(key);
+ this.dispatchEvent(new ol.ObjectEvent(eventType, key, oldValue));
+ eventType = ol.ObjectEventType.PROPERTYCHANGE;
+ this.dispatchEvent(new ol.ObjectEvent(eventType, key, oldValue));
};
/**
- * @return {string} The string that describes the version number of the user
- * agent.
- * @private
+ * Sets a value.
+ * @param {string} key Key name.
+ * @param {*} value Value.
+ * @param {boolean=} opt_silent Update without triggering an event.
+ * @api stable
*/
-goog.userAgent.determineVersion_ = function() {
- // All browsers have different ways to detect the version and they all have
- // different naming schemes.
-
- if (goog.userAgent.OPERA && goog.global['opera']) {
- return goog.userAgent.operaVersion_();
- }
-
- // version is a string rather than a number because it may contain 'b', 'a',
- // and so on.
- var version = '';
- var arr = goog.userAgent.getVersionRegexResult_();
- if (arr) {
- version = arr ? arr[1] : '';
- }
-
- if (goog.userAgent.IE) {
- // IE9 can be in document mode 9 but be reporting an inconsistent user agent
- // version. If it is identifying as a version lower than 9 we take the
- // documentMode as the version instead. IE8 has similar behavior.
- // It is recommended to set the X-UA-Compatible header to ensure that IE9
- // uses documentMode 9.
- var docMode = goog.userAgent.getDocumentMode_();
- if (docMode > parseFloat(version)) {
- return String(docMode);
+ol.Object.prototype.set = function(key, value, opt_silent) {
+ if (opt_silent) {
+ this.values_[key] = value;
+ } else {
+ var oldValue = this.values_[key];
+ this.values_[key] = value;
+ if (oldValue !== value) {
+ this.notify(key, oldValue);
}
}
-
- return version;
};
/**
- * @return {Array|undefined} The version regex matches from parsing the user
- * agent string. These regex statements must be executed inline so they can
- * be compiled out by the closure compiler with the rest of the useragent
- * detection logic when ASSUME_* is specified.
- * @private
+ * Sets a collection of key-value pairs. Note that this changes any existing
+ * properties and adds new ones (it does not remove any existing properties).
+ * @param {Object.<string, *>} values Values.
+ * @param {boolean=} opt_silent Update without triggering an event.
+ * @api stable
*/
-goog.userAgent.getVersionRegexResult_ = function() {
- var userAgent = goog.userAgent.getUserAgentString();
- if (goog.userAgent.GECKO) {
- return /rv\:([^\);]+)(\)|;)/.exec(userAgent);
- }
- if (goog.userAgent.EDGE) {
- return /Edge\/([\d\.]+)/.exec(userAgent);
- }
- if (goog.userAgent.IE) {
- return /\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(userAgent);
- }
- if (goog.userAgent.WEBKIT) {
- // WebKit/125.4
- return /WebKit\/(\S+)/.exec(userAgent);
+ol.Object.prototype.setProperties = function(values, opt_silent) {
+ var key;
+ for (key in values) {
+ this.set(key, values[key], opt_silent);
}
};
/**
- * @return {number|undefined} Returns the document mode (for testing).
- * @private
- */
-goog.userAgent.getDocumentMode_ = function() {
- // NOTE(user): goog.userAgent may be used in context where there is no DOM.
- var doc = goog.global['document'];
- return doc ? doc['documentMode'] : undefined;
-};
-
-
-/**
- * The version of the user agent. This is a string because it might contain
- * 'b' (as in beta) as well as multiple dots.
- * @type {string}
- */
-goog.userAgent.VERSION = goog.userAgent.determineVersion_();
-
-
-/**
- * Compares two version numbers.
- *
- * @param {string} v1 Version of first item.
- * @param {string} v2 Version of second item.
- *
- * @return {number} 1 if first argument is higher
- * 0 if arguments are equal
- * -1 if second argument is higher.
- * @deprecated Use goog.string.compareVersions.
- */
-goog.userAgent.compare = function(v1, v2) {
- return goog.string.compareVersions(v1, v2);
-};
-
-
-/**
- * Cache for {@link goog.userAgent.isVersionOrHigher}.
- * Calls to compareVersions are surprisingly expensive and, as a browser's
- * version number is unlikely to change during a session, we cache the results.
- * @const
- * @private
- */
-goog.userAgent.isVersionOrHigherCache_ = {};
-
-
-/**
- * Whether the user agent version is higher or the same as the given version.
- * NOTE: When checking the version numbers for Firefox and Safari, be sure to
- * use the engine's version, not the browser's version number. For example,
- * Firefox 3.0 corresponds to Gecko 1.9 and Safari 3.0 to Webkit 522.11.
- * Opera and Internet Explorer versions match the product release number.<br>
- * @see <a href="http://en.wikipedia.org/wiki/Safari_version_history">
- * Webkit</a>
- * @see <a href="http://en.wikipedia.org/wiki/Gecko_engine">Gecko</a>
- *
- * @param {string|number} version The version to check.
- * @return {boolean} Whether the user agent version is higher or the same as
- * the given version.
+ * Unsets a property.
+ * @param {string} key Key name.
+ * @param {boolean=} opt_silent Unset without triggering an event.
+ * @api stable
*/
-goog.userAgent.isVersionOrHigher = function(version) {
- return goog.userAgent.ASSUME_ANY_VERSION ||
- goog.userAgent.isVersionOrHigherCache_[version] ||
- (goog.userAgent.isVersionOrHigherCache_[version] =
- goog.string.compareVersions(goog.userAgent.VERSION, version) >= 0);
+ol.Object.prototype.unset = function(key, opt_silent) {
+ if (key in this.values_) {
+ var oldValue = this.values_[key];
+ delete this.values_[key];
+ if (!opt_silent) {
+ this.notify(key, oldValue);
+ }
+ }
};
+goog.provide('ol.array');
-/**
- * Deprecated alias to {@code goog.userAgent.isVersionOrHigher}.
- * @param {string|number} version The version to check.
- * @return {boolean} Whether the user agent version is higher or the same as
- * the given version.
- * @deprecated Use goog.userAgent.isVersionOrHigher().
- */
-goog.userAgent.isVersion = goog.userAgent.isVersionOrHigher;
+goog.require('goog.asserts');
/**
- * Whether the IE effective document mode is higher or the same as the given
- * document mode version.
- * NOTE: Only for IE, return false for another browser.
+ * Performs a binary search on the provided sorted list and returns the index of the item if found. If it can't be found it'll return -1.
+ * https://github.com/darkskyapp/binary-search
*
- * @param {number} documentMode The document mode version to check.
- * @return {boolean} Whether the IE effective document mode is higher or the
- * same as the given version.
+ * @param {Array.<*>} haystack Items to search through.
+ * @param {*} needle The item to look for.
+ * @param {Function=} opt_comparator Comparator function.
+ * @return {number} The index of the item if found, -1 if not.
*/
-goog.userAgent.isDocumentModeOrHigher = function(documentMode) {
- return goog.userAgent.DOCUMENT_MODE >= documentMode;
-};
-
+ol.array.binarySearch = function(haystack, needle, opt_comparator) {
+ var mid, cmp;
+ var comparator = opt_comparator || ol.array.numberSafeCompareFunction;
+ var low = 0;
+ var high = haystack.length;
+ var found = false;
-/**
- * Deprecated alias to {@code goog.userAgent.isDocumentModeOrHigher}.
- * @param {number} version The version to check.
- * @return {boolean} Whether the IE effective document mode is higher or the
- * same as the given version.
- * @deprecated Use goog.userAgent.isDocumentModeOrHigher().
- */
-goog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher;
+ while (low < high) {
+ /* Note that "(low + high) >>> 1" may overflow, and results in a typecast
+ * to double (which gives the wrong results). */
+ mid = low + (high - low >> 1);
+ cmp = +comparator(haystack[mid], needle);
+ if (cmp < 0.0) { /* Too low. */
+ low = mid + 1;
-/**
- * For IE version < 7, documentMode is undefined, so attempt to use the
- * CSS1Compat property to see if we are in standards mode. If we are in
- * standards mode, treat the browser version as the document mode. Otherwise,
- * IE is emulating version 5.
- * @type {number|undefined}
- * @const
- */
-goog.userAgent.DOCUMENT_MODE = (function() {
- var doc = goog.global['document'];
- var mode = goog.userAgent.getDocumentMode_();
- if (!doc || !goog.userAgent.IE) {
- return undefined;
+ } else { /* Key found or too high */
+ high = mid;
+ found = !cmp;
+ }
}
- return mode || (doc['compatMode'] == 'CSS1Compat' ?
- parseInt(goog.userAgent.VERSION, 10) : 5);
-})();
-
-// Copyright 2010 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Browser capability checks for the events package.
- *
- */
-
-
-goog.provide('goog.events.BrowserFeature');
-
-goog.require('goog.userAgent');
-
-
-/**
- * Enum of browser capabilities.
- * @enum {boolean}
- */
-goog.events.BrowserFeature = {
- /**
- * Whether the button attribute of the event is W3C compliant. False in
- * Internet Explorer prior to version 9; document-version dependent.
- */
- HAS_W3C_BUTTON: !goog.userAgent.IE ||
- goog.userAgent.isDocumentModeOrHigher(9),
-
- /**
- * Whether the browser supports full W3C event model.
- */
- HAS_W3C_EVENT_SUPPORT: !goog.userAgent.IE ||
- goog.userAgent.isDocumentModeOrHigher(9),
-
- /**
- * To prevent default in IE7-8 for certain keydown events we need set the
- * keyCode to -1.
- */
- SET_KEY_CODE_TO_PREVENT_DEFAULT: goog.userAgent.IE &&
- !goog.userAgent.isVersionOrHigher('9'),
-
- /**
- * Whether the {@code navigator.onLine} property is supported.
- */
- HAS_NAVIGATOR_ONLINE_PROPERTY: !goog.userAgent.WEBKIT ||
- goog.userAgent.isVersionOrHigher('528'),
-
- /**
- * Whether HTML5 network online/offline events are supported.
- */
- HAS_HTML5_NETWORK_EVENT_SUPPORT:
- goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9b') ||
- goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8') ||
- goog.userAgent.OPERA && goog.userAgent.isVersionOrHigher('9.5') ||
- goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('528'),
-
- /**
- * Whether HTML5 network events fire on document.body, or otherwise the
- * window.
- */
- HTML5_NETWORK_EVENTS_FIRE_ON_BODY:
- goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('8') ||
- goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'),
-
- /**
- * Whether touch is enabled in the browser.
- */
- TOUCH_ENABLED:
- ('ontouchstart' in goog.global ||
- !!(goog.global['document'] &&
- document.documentElement &&
- 'ontouchstart' in document.documentElement) ||
- // IE10 uses non-standard touch events, so it has a different check.
- !!(goog.global['navigator'] &&
- goog.global['navigator']['msMaxTouchPoints']))
-};
-
-// Copyright 2011 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Definition of the disposable interface. A disposable object
- * has a dispose method to to clean up references and resources.
- * @author nnaze@google.com (Nathan Naze)
- */
-
-
-goog.provide('goog.disposable.IDisposable');
-
-
-
-/**
- * Interface for a disposable object. If a instance requires cleanup
- * (references COM objects, DOM notes, or other disposable objects), it should
- * implement this interface (it may subclass goog.Disposable).
- * @interface
- */
-goog.disposable.IDisposable = function() {};
-
-
-/**
- * Disposes of the object and its resources.
- * @return {void} Nothing.
- */
-goog.disposable.IDisposable.prototype.dispose = goog.abstractMethod;
-
-
-/**
- * @return {boolean} Whether the object has been disposed of.
- */
-goog.disposable.IDisposable.prototype.isDisposed = goog.abstractMethod;
-
-// Copyright 2005 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Implements the disposable interface. The dispose method is used
- * to clean up references and resources.
- * @author arv@google.com (Erik Arvidsson)
- */
-
-
-goog.provide('goog.Disposable');
-/** @suppress {extraProvide} */
-goog.provide('goog.dispose');
-/** @suppress {extraProvide} */
-goog.provide('goog.disposeAll');
-
-goog.require('goog.disposable.IDisposable');
-
+ /* Key not found. */
+ return found ? low : ~low;
+}
/**
- * Class that provides the basic implementation for disposable objects. If your
- * class holds one or more references to COM objects, DOM nodes, or other
- * disposable objects, it should extend this class or implement the disposable
- * interface (defined in goog.disposable.IDisposable).
- * @constructor
- * @implements {goog.disposable.IDisposable}
+ * @param {Array.<number>} arr Array.
+ * @param {number} target Target.
+ * @return {number} Index.
*/
-goog.Disposable = function() {
- if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {
- if (goog.Disposable.INCLUDE_STACK_ON_CREATION) {
- this.creationStack = new Error().stack;
+ol.array.binaryFindNearest = function(arr, target) {
+ var index = ol.array.binarySearch(arr, target,
+ /**
+ * @param {number} a A.
+ * @param {number} b B.
+ * @return {number} b minus a.
+ */
+ function(a, b) {
+ return b - a;
+ });
+ if (index >= 0) {
+ return index;
+ } else if (index == -1) {
+ return 0;
+ } else if (index == -arr.length - 1) {
+ return arr.length - 1;
+ } else {
+ var left = -index - 2;
+ var right = -index - 1;
+ if (arr[left] - target < target - arr[right]) {
+ return left;
+ } else {
+ return right;
}
- goog.Disposable.instances_[goog.getUid(this)] = this;
}
- // Support sealing
- this.disposed_ = this.disposed_;
- this.onDisposeCallbacks_ = this.onDisposeCallbacks_;
};
/**
- * @enum {number} Different monitoring modes for Disposable.
+ * Compare function for array sort that is safe for numbers.
+ * @param {*} a The first object to be compared.
+ * @param {*} b The second object to be compared.
+ * @return {number} A negative number, zero, or a positive number as the first
+ * argument is less than, equal to, or greater than the second.
*/
-goog.Disposable.MonitoringMode = {
- /**
- * No monitoring.
- */
- OFF: 0,
- /**
- * Creating and disposing the goog.Disposable instances is monitored. All
- * disposable objects need to call the {@code goog.Disposable} base
- * constructor. The PERMANENT mode must be switched on before creating any
- * goog.Disposable instances.
- */
- PERMANENT: 1,
- /**
- * INTERACTIVE mode can be switched on and off on the fly without producing
- * errors. It also doesn't warn if the disposable objects don't call the
- * {@code goog.Disposable} base constructor.
- */
- INTERACTIVE: 2
+ol.array.numberSafeCompareFunction = function(a, b) {
+ return a > b ? 1 : a < b ? -1 : 0;
};
/**
- * @define {number} The monitoring mode of the goog.Disposable
- * instances. Default is OFF. Switching on the monitoring is only
- * recommended for debugging because it has a significant impact on
- * performance and memory usage. If switched off, the monitoring code
- * compiles down to 0 bytes.
- */
-goog.define('goog.Disposable.MONITORING_MODE', 0);
-
-
-/**
- * @define {boolean} Whether to attach creation stack to each created disposable
- * instance; This is only relevant for when MonitoringMode != OFF.
- */
-goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true);
-
-
-/**
- * Maps the unique ID of every undisposed {@code goog.Disposable} object to
- * the object itself.
- * @type {!Object<number, !goog.Disposable>}
- * @private
+ * Whether the array contains the given object.
+ * @param {Array.<*>} arr The array to test for the presence of the element.
+ * @param {*} obj The object for which to test.
+ * @return {boolean} The object is in the array.
*/
-goog.Disposable.instances_ = {};
+ol.array.includes = function(arr, obj) {
+ return arr.indexOf(obj) >= 0;
+};
/**
- * @return {!Array<!goog.Disposable>} All {@code goog.Disposable} objects that
- * haven't been disposed of.
+ * @param {Array.<number>} arr Array.
+ * @param {number} target Target.
+ * @param {number} direction 0 means return the nearest, > 0
+ * means return the largest nearest, < 0 means return the
+ * smallest nearest.
+ * @return {number} Index.
*/
-goog.Disposable.getUndisposedObjects = function() {
- var ret = [];
- for (var id in goog.Disposable.instances_) {
- if (goog.Disposable.instances_.hasOwnProperty(id)) {
- ret.push(goog.Disposable.instances_[Number(id)]);
+ol.array.linearFindNearest = function(arr, target, direction) {
+ var n = arr.length;
+ if (arr[0] <= target) {
+ return 0;
+ } else if (target <= arr[n - 1]) {
+ return n - 1;
+ } else {
+ var i;
+ if (direction > 0) {
+ for (i = 1; i < n; ++i) {
+ if (arr[i] < target) {
+ return i - 1;
+ }
+ }
+ } else if (direction < 0) {
+ for (i = 1; i < n; ++i) {
+ if (arr[i] <= target) {
+ return i;
+ }
+ }
+ } else {
+ for (i = 1; i < n; ++i) {
+ if (arr[i] == target) {
+ return i;
+ } else if (arr[i] < target) {
+ if (arr[i - 1] - target < target - arr[i]) {
+ return i - 1;
+ } else {
+ return i;
+ }
+ }
+ }
}
+ // We should never get here, but the compiler complains
+ // if it finds a path for which no number is returned.
+ goog.asserts.fail();
+ return n - 1;
}
- return ret;
};
/**
- * Clears the registry of undisposed objects but doesn't dispose of them.
+ * @param {Array.<*>} arr Array.
+ * @param {number} begin Begin index.
+ * @param {number} end End index.
*/
-goog.Disposable.clearUndisposedObjects = function() {
- goog.Disposable.instances_ = {};
+ol.array.reverseSubArray = function(arr, begin, end) {
+ goog.asserts.assert(begin >= 0,
+ 'Array begin index should be equal to or greater than 0');
+ goog.asserts.assert(end < arr.length,
+ 'Array end index should be less than the array length');
+ while (begin < end) {
+ var tmp = arr[begin];
+ arr[begin] = arr[end];
+ arr[end] = tmp;
+ ++begin;
+ --end;
+ }
};
/**
- * Whether the object has been disposed of.
- * @type {boolean}
- * @private
- */
-goog.Disposable.prototype.disposed_ = false;
-
-
-/**
- * Callbacks to invoke when this object is disposed.
- * @type {Array<!Function>}
- * @private
- */
-goog.Disposable.prototype.onDisposeCallbacks_;
-
-
-/**
- * If monitoring the goog.Disposable instances is enabled, stores the creation
- * stack trace of the Disposable instance.
- * @const {string}
- */
-goog.Disposable.prototype.creationStack;
-
-
-/**
- * @return {boolean} Whether the object has been disposed of.
- * @override
+ * @param {Array.<*>} arr Array.
+ * @return {!Array.<?>} Flattened Array.
*/
-goog.Disposable.prototype.isDisposed = function() {
- return this.disposed_;
+ol.array.flatten = function(arr) {
+ var data = arr.reduce(function(flattened, value) {
+ if (Array.isArray(value)) {
+ return flattened.concat(ol.array.flatten(value));
+ } else {
+ return flattened.concat(value);
+ }
+ }, []);
+ return data;
};
/**
- * @return {boolean} Whether the object has been disposed of.
- * @deprecated Use {@link #isDisposed} instead.
+ * @param {Array.<VALUE>} arr The array to modify.
+ * @param {Array.<VALUE>|VALUE} data The elements or arrays of elements
+ * to add to arr.
+ * @template VALUE
*/
-goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed;
+ol.array.extend = function(arr, data) {
+ var i;
+ var extension = goog.isArrayLike(data) ? data : [data];
+ var length = extension.length
+ for (i = 0; i < length; i++) {
+ arr[arr.length] = extension[i];
+ }
+}
/**
- * Disposes of the object. If the object hasn't already been disposed of, calls
- * {@link #disposeInternal}. Classes that extend {@code goog.Disposable} should
- * override {@link #disposeInternal} in order to delete references to COM
- * objects, DOM nodes, and other disposable objects. Reentrant.
- *
- * @return {void} Nothing.
- * @override
+ * @param {Array.<VALUE>} arr The array to modify.
+ * @param {VALUE} obj The element to remove.
+ * @template VALUE
+ * @return {boolean} If the element was removed.
*/
-goog.Disposable.prototype.dispose = function() {
- if (!this.disposed_) {
- // Set disposed_ to true first, in case during the chain of disposal this
- // gets disposed recursively.
- this.disposed_ = true;
- this.disposeInternal();
- if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {
- var uid = goog.getUid(this);
- if (goog.Disposable.MONITORING_MODE ==
- goog.Disposable.MonitoringMode.PERMANENT &&
- !goog.Disposable.instances_.hasOwnProperty(uid)) {
- throw Error(this + ' did not call the goog.Disposable base ' +
- 'constructor or was disposed of after a clearUndisposedObjects ' +
- 'call');
- }
- delete goog.Disposable.instances_[uid];
- }
+ol.array.remove = function(arr, obj) {
+ var i = arr.indexOf(obj);
+ var found = i > -1;
+ if (found) {
+ arr.splice(i, 1);
}
-};
+ return found;
+}
/**
- * Associates a disposable object with this object so that they will be disposed
- * together.
- * @param {goog.disposable.IDisposable} disposable that will be disposed when
- * this object is disposed.
+ * @param {Array.<VALUE>} arr The array to search in.
+ * @param {function(VALUE, number, ?) : boolean} func The function to compare.
+ * @template VALUE
+ * @return {VALUE} The element found.
*/
-goog.Disposable.prototype.registerDisposable = function(disposable) {
- this.addOnDisposeCallback(goog.partial(goog.dispose, disposable));
-};
-
+ol.array.find = function(arr, func) {
+ var length = arr.length >>> 0;
+ var value;
-/**
- * Invokes a callback function when this object is disposed. Callbacks are
- * invoked in the order in which they were added. If a callback is added to
- * an already disposed Disposable, it will be called immediately.
- * @param {function(this:T):?} callback The callback function.
- * @param {T=} opt_scope An optional scope to call the callback in.
- * @template T
- */
-goog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) {
- if (this.disposed_) {
- callback.call(opt_scope);
- return;
- }
- if (!this.onDisposeCallbacks_) {
- this.onDisposeCallbacks_ = [];
+ for (var i = 0; i < length; i++) {
+ value = arr[i];
+ if (func(value, i, arr)) {
+ return value;
+ }
}
-
- this.onDisposeCallbacks_.push(
- goog.isDef(opt_scope) ? goog.bind(callback, opt_scope) : callback);
-};
+ return null;
+}
/**
- * Deletes or nulls out any references to COM objects, DOM nodes, or other
- * disposable objects. Classes that extend {@code goog.Disposable} should
- * override this method.
- * Not reentrant. To avoid calling it twice, it must only be called from the
- * subclass' {@code disposeInternal} method. Everywhere else the public
- * {@code dispose} method must be used.
- * For example:
- * <pre>
- * mypackage.MyClass = function() {
- * mypackage.MyClass.base(this, 'constructor');
- * // Constructor logic specific to MyClass.
- * ...
- * };
- * goog.inherits(mypackage.MyClass, goog.Disposable);
- *
- * mypackage.MyClass.prototype.disposeInternal = function() {
- * // Dispose logic specific to MyClass.
- * ...
- * // Call superclass's disposeInternal at the end of the subclass's, like
- * // in C++, to avoid hard-to-catch issues.
- * mypackage.MyClass.base(this, 'disposeInternal');
- * };
- * </pre>
- * @protected
+ * @param {Array|Uint8ClampedArray} arr1 The first array to compare.
+ * @param {Array|Uint8ClampedArray} arr2 The second array to compare.
+ * @return {boolean} Whether the two arrays are equal.
*/
-goog.Disposable.prototype.disposeInternal = function() {
- if (this.onDisposeCallbacks_) {
- while (this.onDisposeCallbacks_.length) {
- this.onDisposeCallbacks_.shift()();
+ol.array.equals = function(arr1, arr2) {
+ var len1 = arr1.length;
+ if (len1 !== arr2.length) {
+ return false;
+ }
+ for (var i = 0; i < len1; i++) {
+ if (arr1[i] !== arr2[i]) {
+ return false;
}
}
-};
+ return true;
+}
/**
- * Returns True if we can verify the object is disposed.
- * Calls {@code isDisposed} on the argument if it supports it. If obj
- * is not an object with an isDisposed() method, return false.
- * @param {*} obj The object to investigate.
- * @return {boolean} True if we can verify the object is disposed.
+ * @param {Array.<*>} arr The array to sort (modifies original).
+ * @param {Function} compareFnc Comparison function.
*/
-goog.Disposable.isDisposed = function(obj) {
- if (obj && typeof obj.isDisposed == 'function') {
- return obj.isDisposed();
+ol.array.stableSort = function(arr, compareFnc) {
+ var length = arr.length;
+ var tmp = Array(arr.length);
+ var i;
+ for (i = 0; i < length; i++) {
+ tmp[i] = {index: i, value: arr[i]};
}
- return false;
-};
+ tmp.sort(function(a, b) {
+ return compareFnc(a.value, b.value) || a.index - b.index;
+ });
+ for (i = 0; i < arr.length; i++) {
+ arr[i] = tmp[i].value;
+ }
+}
/**
- * Calls {@code dispose} on the argument if it supports it. If obj is not an
- * object with a dispose() method, this is a no-op.
- * @param {*} obj The object to dispose of.
+ * @param {Array.<*>} arr The array to search in.
+ * @param {Function} func Comparison function.
+ * @return {number} Return index.
*/
-goog.dispose = function(obj) {
- if (obj && typeof obj.dispose == 'function') {
- obj.dispose();
- }
-};
+ol.array.findIndex = function(arr, func) {
+ var index;
+ var found = !arr.every(function(el, idx) {
+ index = idx;
+ return !func(el, idx, arr);
+ });
+ return found ? index : -1;
+}
/**
- * Calls {@code dispose} on each member of the list that supports it. (If the
- * member is an ArrayLike, then {@code goog.disposeAll()} will be called
- * recursively on each of its members.) If the member is not an object with a
- * {@code dispose()} method, then it is ignored.
- * @param {...*} var_args The list.
+ * @param {Array.<*>} arr The array to test.
+ * @param {Function=} opt_func Comparison function.
+ * @param {boolean=} opt_strict Strictly sorted (default false).
+ * @return {boolean} Return index.
*/
-goog.disposeAll = function(var_args) {
- for (var i = 0, len = arguments.length; i < len; ++i) {
- var disposable = arguments[i];
- if (goog.isArrayLike(disposable)) {
- goog.disposeAll.apply(null, disposable);
- } else {
- goog.dispose(disposable);
+ol.array.isSorted = function(arr, opt_func, opt_strict) {
+ var compare = opt_func || ol.array.numberSafeCompareFunction;
+ return arr.every(function(currentVal, index) {
+ if (index === 0) {
+ return true;
}
- }
-};
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
+ var res = compare(arr[index - 1], currentVal);
+ return !(res > 0 || opt_strict && res === 0);
+ });
+}
-goog.provide('goog.events.EventId');
+goog.provide('ol.ResolutionConstraint');
+goog.require('ol.array');
+goog.require('ol.math');
/**
- * A templated class that is used when registering for events. Typical usage:
- * <code>
- * /** @type {goog.events.EventId<MyEventObj>}
- * var myEventId = new goog.events.EventId(
- * goog.events.getUniqueId(('someEvent'));
- *
- * // No need to cast or declare here since the compiler knows the correct
- * // type of 'evt' (MyEventObj).
- * something.listen(myEventId, function(evt) {});
- * </code>
- *
- * @param {string} eventId
- * @template T
- * @constructor
- * @struct
- * @final
+ * @param {Array.<number>} resolutions Resolutions.
+ * @return {ol.ResolutionConstraintType} Zoom function.
*/
-goog.events.EventId = function(eventId) {
- /** @const */ this.id = eventId;
+ol.ResolutionConstraint.createSnapToResolutions = function(resolutions) {
+ return (
+ /**
+ * @param {number|undefined} resolution Resolution.
+ * @param {number} delta Delta.
+ * @param {number} direction Direction.
+ * @return {number|undefined} Resolution.
+ */
+ function(resolution, delta, direction) {
+ if (resolution !== undefined) {
+ var z =
+ ol.array.linearFindNearest(resolutions, resolution, direction);
+ z = ol.math.clamp(z + delta, 0, resolutions.length - 1);
+ return resolutions[z];
+ } else {
+ return undefined;
+ }
+ });
};
/**
- * @override
+ * @param {number} power Power.
+ * @param {number} maxResolution Maximum resolution.
+ * @param {number=} opt_maxLevel Maximum level.
+ * @return {ol.ResolutionConstraintType} Zoom function.
*/
-goog.events.EventId.prototype.toString = function() {
- return this.id;
+ol.ResolutionConstraint.createSnapToPower = function(power, maxResolution, opt_maxLevel) {
+ return (
+ /**
+ * @param {number|undefined} resolution Resolution.
+ * @param {number} delta Delta.
+ * @param {number} direction Direction.
+ * @return {number|undefined} Resolution.
+ */
+ function(resolution, delta, direction) {
+ if (resolution !== undefined) {
+ var offset;
+ if (direction > 0) {
+ offset = 0;
+ } else if (direction < 0) {
+ offset = 1;
+ } else {
+ offset = 0.5;
+ }
+ var oldLevel = Math.floor(
+ Math.log(maxResolution / resolution) / Math.log(power) + offset);
+ var newLevel = Math.max(oldLevel + delta, 0);
+ if (opt_maxLevel !== undefined) {
+ newLevel = Math.min(newLevel, opt_maxLevel);
+ }
+ return maxResolution / Math.pow(power, newLevel);
+ } else {
+ return undefined;
+ }
+ });
};
-// Copyright 2005 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview A base class for event objects.
- *
- */
-
-
-goog.provide('goog.events.Event');
-goog.provide('goog.events.EventLike');
-
-/**
- * goog.events.Event no longer depends on goog.Disposable. Keep requiring
- * goog.Disposable here to not break projects which assume this dependency.
- * @suppress {extraRequire}
- */
-goog.require('goog.Disposable');
-goog.require('goog.events.EventId');
-
-
-/**
- * A typedef for event like objects that are dispatchable via the
- * goog.events.dispatchEvent function. strings are treated as the type for a
- * goog.events.Event. Objects are treated as an extension of a new
- * goog.events.Event with the type property of the object being used as the type
- * of the Event.
- * @typedef {string|Object|goog.events.Event|goog.events.EventId}
- */
-goog.events.EventLike;
+goog.provide('ol.RotationConstraint');
+goog.require('ol.math');
/**
- * A base class for event objects, so that they can support preventDefault and
- * stopPropagation.
- *
- * @param {string|!goog.events.EventId} type Event Type.
- * @param {Object=} opt_target Reference to the object that is the target of
- * this event. It has to implement the {@code EventTarget} interface
- * declared at {@link http://developer.mozilla.org/en/DOM/EventTarget}.
- * @constructor
+ * @param {number|undefined} rotation Rotation.
+ * @param {number} delta Delta.
+ * @return {number|undefined} Rotation.
*/
-goog.events.Event = function(type, opt_target) {
- /**
- * Event type.
- * @type {string}
- */
- this.type = type instanceof goog.events.EventId ? String(type) : type;
-
- /**
- * TODO(tbreisacher): The type should probably be
- * EventTarget|goog.events.EventTarget.
- *
- * Target of the event.
- * @type {Object|undefined}
- */
- this.target = opt_target;
-
- /**
- * Object that had the listener attached.
- * @type {Object|undefined}
- */
- this.currentTarget = this.target;
-
- /**
- * Whether to cancel the event in internal capture/bubble processing for IE.
- * @type {boolean}
- * @public
- * @suppress {underscore|visibility} Technically public, but referencing this
- * outside this package is strongly discouraged.
- */
- this.propagationStopped_ = false;
-
- /**
- * Whether the default action has been prevented.
- * This is a property to match the W3C specification at
- * {@link http://www.w3.org/TR/DOM-Level-3-Events/
- * #events-event-type-defaultPrevented}.
- * Must be treated as read-only outside the class.
- * @type {boolean}
- */
- this.defaultPrevented = false;
-
- /**
- * Return value for in internal capture/bubble processing for IE.
- * @type {boolean}
- * @public
- * @suppress {underscore|visibility} Technically public, but referencing this
- * outside this package is strongly discouraged.
- */
- this.returnValue_ = true;
+ol.RotationConstraint.disable = function(rotation, delta) {
+ if (rotation !== undefined) {
+ return 0;
+ } else {
+ return undefined;
+ }
};
/**
- * Stops event propagation.
+ * @param {number|undefined} rotation Rotation.
+ * @param {number} delta Delta.
+ * @return {number|undefined} Rotation.
*/
-goog.events.Event.prototype.stopPropagation = function() {
- this.propagationStopped_ = true;
+ol.RotationConstraint.none = function(rotation, delta) {
+ if (rotation !== undefined) {
+ return rotation + delta;
+ } else {
+ return undefined;
+ }
};
/**
- * Prevents the default action, for example a link redirecting to a url.
+ * @param {number} n N.
+ * @return {ol.RotationConstraintType} Rotation constraint.
*/
-goog.events.Event.prototype.preventDefault = function() {
- this.defaultPrevented = true;
- this.returnValue_ = false;
+ol.RotationConstraint.createSnapToN = function(n) {
+ var theta = 2 * Math.PI / n;
+ return (
+ /**
+ * @param {number|undefined} rotation Rotation.
+ * @param {number} delta Delta.
+ * @return {number|undefined} Rotation.
+ */
+ function(rotation, delta) {
+ if (rotation !== undefined) {
+ rotation = Math.floor((rotation + delta) / theta + 0.5) * theta;
+ return rotation;
+ } else {
+ return undefined;
+ }
+ });
};
/**
- * Stops the propagation of the event. It is equivalent to
- * {@code e.stopPropagation()}, but can be used as the callback argument of
- * {@link goog.events.listen} without declaring another function.
- * @param {!goog.events.Event} e An event.
+ * @param {number=} opt_tolerance Tolerance.
+ * @return {ol.RotationConstraintType} Rotation constraint.
*/
-goog.events.Event.stopPropagation = function(e) {
- e.stopPropagation();
+ol.RotationConstraint.createSnapToZero = function(opt_tolerance) {
+ var tolerance = opt_tolerance || ol.math.toRadians(5);
+ return (
+ /**
+ * @param {number|undefined} rotation Rotation.
+ * @param {number} delta Delta.
+ * @return {number|undefined} Rotation.
+ */
+ function(rotation, delta) {
+ if (rotation !== undefined) {
+ if (Math.abs(rotation + delta) <= tolerance) {
+ return 0;
+ } else {
+ return rotation + delta;
+ }
+ } else {
+ return undefined;
+ }
+ });
};
+goog.provide('ol.string');
/**
- * Prevents the default action. It is equivalent to
- * {@code e.preventDefault()}, but can be used as the callback argument of
- * {@link goog.events.listen} without declaring another function.
- * @param {!goog.events.Event} e An event.
- */
-goog.events.Event.preventDefault = function(e) {
- e.preventDefault();
+ * @param {number} number Number to be formatted
+ * @param {number} width The desired width
+ * @param {number=} opt_precision Precision of the output string (i.e. number of decimal places)
+ * @returns {string} Formatted string
+*/
+ol.string.padNumber = function(number, width, opt_precision) {
+ var numberString = opt_precision !== undefined ? number.toFixed(opt_precision) : '' + number;
+ var decimal = numberString.indexOf('.');
+ decimal = decimal === -1 ? numberString.length : decimal;
+ return decimal > width ? numberString : new Array(1 + width - decimal).join('0') + numberString;
};
-// Copyright 2010 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
/**
- * @fileoverview Event Types.
- *
- * @author arv@google.com (Erik Arvidsson)
+ * Adapted from https://github.com/omichelsen/compare-versions/blob/master/index.js
+ * @param {string|number} v1 First version
+ * @param {string|number} v2 Second version
+ * @returns {number} Value
*/
+ol.string.compareVersions = function(v1, v2) {
+ var s1 = ('' + v1).split('.');
+ var s2 = ('' + v2).split('.');
+ for (var i = 0; i < Math.max(s1.length, s2.length); i++) {
+ var n1 = parseInt(s1[i] || '0', 10);
+ var n2 = parseInt(s2[i] || '0', 10);
-goog.provide('goog.events.EventType');
-
-goog.require('goog.userAgent');
-
+ if (n1 > n2) return 1;
+ if (n2 > n1) return -1;
+ }
-/**
- * Returns a prefixed event name for the current browser.
- * @param {string} eventName The name of the event.
- * @return {string} The prefixed event name.
- * @suppress {missingRequire|missingProvide}
- * @private
- */
-goog.events.getVendorPrefixedName_ = function(eventName) {
- return goog.userAgent.WEBKIT ? 'webkit' + eventName :
- (goog.userAgent.OPERA ? 'o' + eventName.toLowerCase() :
- eventName.toLowerCase());
+ return 0;
};
+goog.provide('ol.coordinate');
-/**
- * Constants for event names.
- * @enum {string}
- */
-goog.events.EventType = {
- // Mouse events
- CLICK: 'click',
- RIGHTCLICK: 'rightclick',
- DBLCLICK: 'dblclick',
- MOUSEDOWN: 'mousedown',
- MOUSEUP: 'mouseup',
- MOUSEOVER: 'mouseover',
- MOUSEOUT: 'mouseout',
- MOUSEMOVE: 'mousemove',
- MOUSEENTER: 'mouseenter',
- MOUSELEAVE: 'mouseleave',
- // Select start is non-standard.
- // See http://msdn.microsoft.com/en-us/library/ie/ms536969(v=vs.85).aspx.
- SELECTSTART: 'selectstart', // IE, Safari, Chrome
-
- // Wheel events
- // http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents
- WHEEL: 'wheel',
-
- // Key events
- KEYPRESS: 'keypress',
- KEYDOWN: 'keydown',
- KEYUP: 'keyup',
-
- // Focus
- BLUR: 'blur',
- FOCUS: 'focus',
- DEACTIVATE: 'deactivate', // IE only
- // NOTE: The following two events are not stable in cross-browser usage.
- // WebKit and Opera implement DOMFocusIn/Out.
- // IE implements focusin/out.
- // Gecko implements neither see bug at
- // https://bugzilla.mozilla.org/show_bug.cgi?id=396927.
- // The DOM Events Level 3 Draft deprecates DOMFocusIn in favor of focusin:
- // http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
- // You can use FOCUS in Capture phase until implementations converge.
- FOCUSIN: goog.userAgent.IE ? 'focusin' : 'DOMFocusIn',
- FOCUSOUT: goog.userAgent.IE ? 'focusout' : 'DOMFocusOut',
-
- // Forms
- CHANGE: 'change',
- RESET: 'reset',
- SELECT: 'select',
- SUBMIT: 'submit',
- INPUT: 'input',
- PROPERTYCHANGE: 'propertychange', // IE only
-
- // Drag and drop
- DRAGSTART: 'dragstart',
- DRAG: 'drag',
- DRAGENTER: 'dragenter',
- DRAGOVER: 'dragover',
- DRAGLEAVE: 'dragleave',
- DROP: 'drop',
- DRAGEND: 'dragend',
-
- // Touch events
- // Note that other touch events exist, but we should follow the W3C list here.
- // http://www.w3.org/TR/touch-events/#list-of-touchevent-types
- TOUCHSTART: 'touchstart',
- TOUCHMOVE: 'touchmove',
- TOUCHEND: 'touchend',
- TOUCHCANCEL: 'touchcancel',
-
- // Misc
- BEFOREUNLOAD: 'beforeunload',
- CONSOLEMESSAGE: 'consolemessage',
- CONTEXTMENU: 'contextmenu',
- DOMCONTENTLOADED: 'DOMContentLoaded',
- ERROR: 'error',
- HELP: 'help',
- LOAD: 'load',
- LOSECAPTURE: 'losecapture',
- ORIENTATIONCHANGE: 'orientationchange',
- READYSTATECHANGE: 'readystatechange',
- RESIZE: 'resize',
- SCROLL: 'scroll',
- UNLOAD: 'unload',
-
- // HTML 5 History events
- // See http://www.w3.org/TR/html5/browsers.html#event-definitions-0
- HASHCHANGE: 'hashchange',
- PAGEHIDE: 'pagehide',
- PAGESHOW: 'pageshow',
- POPSTATE: 'popstate',
-
- // Copy and Paste
- // Support is limited. Make sure it works on your favorite browser
- // before using.
- // http://www.quirksmode.org/dom/events/cutcopypaste.html
- COPY: 'copy',
- PASTE: 'paste',
- CUT: 'cut',
- BEFORECOPY: 'beforecopy',
- BEFORECUT: 'beforecut',
- BEFOREPASTE: 'beforepaste',
-
- // HTML5 online/offline events.
- // http://www.w3.org/TR/offline-webapps/#related
- ONLINE: 'online',
- OFFLINE: 'offline',
-
- // HTML 5 worker events
- MESSAGE: 'message',
- CONNECT: 'connect',
-
- // CSS animation events.
- /** @suppress {missingRequire} */
- ANIMATIONSTART: goog.events.getVendorPrefixedName_('AnimationStart'),
- /** @suppress {missingRequire} */
- ANIMATIONEND: goog.events.getVendorPrefixedName_('AnimationEnd'),
- /** @suppress {missingRequire} */
- ANIMATIONITERATION: goog.events.getVendorPrefixedName_('AnimationIteration'),
-
- // CSS transition events. Based on the browser support described at:
- // https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility
- /** @suppress {missingRequire} */
- TRANSITIONEND: goog.events.getVendorPrefixedName_('TransitionEnd'),
-
- // W3C Pointer Events
- // http://www.w3.org/TR/pointerevents/
- POINTERDOWN: 'pointerdown',
- POINTERUP: 'pointerup',
- POINTERCANCEL: 'pointercancel',
- POINTERMOVE: 'pointermove',
- POINTEROVER: 'pointerover',
- POINTEROUT: 'pointerout',
- POINTERENTER: 'pointerenter',
- POINTERLEAVE: 'pointerleave',
- GOTPOINTERCAPTURE: 'gotpointercapture',
- LOSTPOINTERCAPTURE: 'lostpointercapture',
-
- // IE specific events.
- // See http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx
- // Note: these events will be supplanted in IE11.
- MSGESTURECHANGE: 'MSGestureChange',
- MSGESTUREEND: 'MSGestureEnd',
- MSGESTUREHOLD: 'MSGestureHold',
- MSGESTURESTART: 'MSGestureStart',
- MSGESTURETAP: 'MSGestureTap',
- MSGOTPOINTERCAPTURE: 'MSGotPointerCapture',
- MSINERTIASTART: 'MSInertiaStart',
- MSLOSTPOINTERCAPTURE: 'MSLostPointerCapture',
- MSPOINTERCANCEL: 'MSPointerCancel',
- MSPOINTERDOWN: 'MSPointerDown',
- MSPOINTERENTER: 'MSPointerEnter',
- MSPOINTERHOVER: 'MSPointerHover',
- MSPOINTERLEAVE: 'MSPointerLeave',
- MSPOINTERMOVE: 'MSPointerMove',
- MSPOINTEROUT: 'MSPointerOut',
- MSPOINTEROVER: 'MSPointerOver',
- MSPOINTERUP: 'MSPointerUp',
-
- // Native IMEs/input tools events.
- TEXT: 'text',
- TEXTINPUT: 'textInput',
- COMPOSITIONSTART: 'compositionstart',
- COMPOSITIONUPDATE: 'compositionupdate',
- COMPOSITIONEND: 'compositionend',
-
- // Webview tag events
- // See http://developer.chrome.com/dev/apps/webview_tag.html
- EXIT: 'exit',
- LOADABORT: 'loadabort',
- LOADCOMMIT: 'loadcommit',
- LOADREDIRECT: 'loadredirect',
- LOADSTART: 'loadstart',
- LOADSTOP: 'loadstop',
- RESPONSIVE: 'responsive',
- SIZECHANGED: 'sizechanged',
- UNRESPONSIVE: 'unresponsive',
-
- // HTML5 Page Visibility API. See details at
- // {@code goog.labs.dom.PageVisibilityMonitor}.
- VISIBILITYCHANGE: 'visibilitychange',
-
- // LocalStorage event.
- STORAGE: 'storage',
-
- // DOM Level 2 mutation events (deprecated).
- DOMSUBTREEMODIFIED: 'DOMSubtreeModified',
- DOMNODEINSERTED: 'DOMNodeInserted',
- DOMNODEREMOVED: 'DOMNodeRemoved',
- DOMNODEREMOVEDFROMDOCUMENT: 'DOMNodeRemovedFromDocument',
- DOMNODEINSERTEDINTODOCUMENT: 'DOMNodeInsertedIntoDocument',
- DOMATTRMODIFIED: 'DOMAttrModified',
- DOMCHARACTERDATAMODIFIED: 'DOMCharacterDataModified',
-
- // Print events.
- BEFOREPRINT: 'beforeprint',
- AFTERPRINT: 'afterprint'
-};
+goog.require('ol.math');
+goog.require('ol.string');
-// Copyright 2009 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Useful compiler idioms.
+ * Add `delta` to `coordinate`. `coordinate` is modified in place and returned
+ * by the function.
*
- * @author johnlenz@google.com (John Lenz)
- */
-
-goog.provide('goog.reflect');
-
-
-/**
- * Syntax for object literal casts.
- * @see http://go/jscompiler-renaming
- * @see https://github.com/google/closure-compiler/wiki/Type-Based-Property-Renaming
+ * Example:
*
- * Use this if you have an object literal whose keys need to have the same names
- * as the properties of some class even after they are renamed by the compiler.
+ * var coord = [7.85, 47.983333];
+ * ol.coordinate.add(coord, [-2, 4]);
+ * // coord is now [5.85, 51.983333]
*
- * @param {!Function} type Type to cast to.
- * @param {Object} object Object literal to cast.
- * @return {Object} The object literal.
- */
-goog.reflect.object = function(type, object) {
- return object;
-};
-
-
-/**
- * To assert to the compiler that an operation is needed when it would
- * otherwise be stripped. For example:
- * <code>
- * // Force a layout
- * goog.reflect.sinkValue(dialog.offsetHeight);
- * </code>
- * @type {!Function}
- */
-goog.reflect.sinkValue = function(x) {
- goog.reflect.sinkValue[' '](x);
- return x;
-};
-
-
-/**
- * The compiler should optimize this function away iff no one ever uses
- * goog.reflect.sinkValue.
- */
-goog.reflect.sinkValue[' '] = goog.nullFunction;
-
-
-/**
- * Check if a property can be accessed without throwing an exception.
- * @param {Object} obj The owner of the property.
- * @param {string} prop The property name.
- * @return {boolean} Whether the property is accessible. Will also return true
- * if obj is null.
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @param {ol.Coordinate} delta Delta.
+ * @return {ol.Coordinate} The input coordinate adjusted by the given delta.
+ * @api stable
*/
-goog.reflect.canAccessProperty = function(obj, prop) {
- /** @preserveTry */
- try {
- goog.reflect.sinkValue(obj[prop]);
- return true;
- } catch (e) {}
- return false;
+ol.coordinate.add = function(coordinate, delta) {
+ coordinate[0] += delta[0];
+ coordinate[1] += delta[1];
+ return coordinate;
};
-// Copyright 2005 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview A patched, standardized event object for browser events.
- *
- * <pre>
- * The patched event object contains the following members:
- * - type {string} Event type, e.g. 'click'
- * - target {Object} The element that actually triggered the event
- * - currentTarget {Object} The element the listener is attached to
- * - relatedTarget {Object} For mouseover and mouseout, the previous object
- * - offsetX {number} X-coordinate relative to target
- * - offsetY {number} Y-coordinate relative to target
- * - clientX {number} X-coordinate relative to viewport
- * - clientY {number} Y-coordinate relative to viewport
- * - screenX {number} X-coordinate relative to the edge of the screen
- * - screenY {number} Y-coordinate relative to the edge of the screen
- * - button {number} Mouse button. Use isButton() to test.
- * - keyCode {number} Key-code
- * - ctrlKey {boolean} Was ctrl key depressed
- * - altKey {boolean} Was alt key depressed
- * - shiftKey {boolean} Was shift key depressed
- * - metaKey {boolean} Was meta key depressed
- * - defaultPrevented {boolean} Whether the default action has been prevented
- * - state {Object} History state object
- *
- * NOTE: The keyCode member contains the raw browser keyCode. For normalized
- * key and character code use {@link goog.events.KeyHandler}.
- * </pre>
+ * Calculates the point closest to the passed coordinate on the passed segment.
+ * This is the foot of the perpendicular of the coordinate to the segment when
+ * the foot is on the segment, or the closest segment coordinate when the foot
+ * is outside the segment.
*
- * @author arv@google.com (Erik Arvidsson)
- */
-
-goog.provide('goog.events.BrowserEvent');
-goog.provide('goog.events.BrowserEvent.MouseButton');
-
-goog.require('goog.events.BrowserFeature');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventType');
-goog.require('goog.reflect');
-goog.require('goog.userAgent');
-
-
-
-/**
- * Accepts a browser event object and creates a patched, cross browser event
- * object.
- * The content of this object will not be initialized if no event object is
- * provided. If this is the case, init() needs to be invoked separately.
- * @param {Event=} opt_e Browser event object.
- * @param {EventTarget=} opt_currentTarget Current target for event.
- * @constructor
- * @extends {goog.events.Event}
+ * @param {ol.Coordinate} coordinate The coordinate.
+ * @param {Array.<ol.Coordinate>} segment The two coordinates of the segment.
+ * @return {ol.Coordinate} The foot of the perpendicular of the coordinate to
+ * the segment.
*/
-goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
- goog.events.BrowserEvent.base(this, 'constructor', opt_e ? opt_e.type : '');
-
- /**
- * Target that fired the event.
- * @override
- * @type {Node}
- */
- this.target = null;
-
- /**
- * Node that had the listener attached.
- * @override
- * @type {Node|undefined}
- */
- this.currentTarget = null;
-
- /**
- * For mouseover and mouseout events, the related object for the event.
- * @type {Node}
- */
- this.relatedTarget = null;
-
- /**
- * X-coordinate relative to target.
- * @type {number}
- */
- this.offsetX = 0;
-
- /**
- * Y-coordinate relative to target.
- * @type {number}
- */
- this.offsetY = 0;
-
- /**
- * X-coordinate relative to the window.
- * @type {number}
- */
- this.clientX = 0;
-
- /**
- * Y-coordinate relative to the window.
- * @type {number}
- */
- this.clientY = 0;
-
- /**
- * X-coordinate relative to the monitor.
- * @type {number}
- */
- this.screenX = 0;
-
- /**
- * Y-coordinate relative to the monitor.
- * @type {number}
- */
- this.screenY = 0;
-
- /**
- * Which mouse button was pressed.
- * @type {number}
- */
- this.button = 0;
-
- /**
- * Keycode of key press.
- * @type {number}
- */
- this.keyCode = 0;
-
- /**
- * Keycode of key press.
- * @type {number}
- */
- this.charCode = 0;
-
- /**
- * Whether control was pressed at time of event.
- * @type {boolean}
- */
- this.ctrlKey = false;
-
- /**
- * Whether alt was pressed at time of event.
- * @type {boolean}
- */
- this.altKey = false;
-
- /**
- * Whether shift was pressed at time of event.
- * @type {boolean}
- */
- this.shiftKey = false;
-
- /**
- * Whether the meta key was pressed at time of event.
- * @type {boolean}
- */
- this.metaKey = false;
-
- /**
- * History state object, only set for PopState events where it's a copy of the
- * state object provided to pushState or replaceState.
- * @type {Object}
- */
- this.state = null;
-
- /**
- * Whether the default platform modifier key was pressed at time of event.
- * (This is control for all platforms except Mac, where it's Meta.)
- * @type {boolean}
- */
- this.platformModifierKey = false;
-
- /**
- * The browser event object.
- * @private {Event}
- */
- this.event_ = null;
-
- if (opt_e) {
- this.init(opt_e, opt_currentTarget);
+ol.coordinate.closestOnSegment = function(coordinate, segment) {
+ var x0 = coordinate[0];
+ var y0 = coordinate[1];
+ var start = segment[0];
+ var end = segment[1];
+ var x1 = start[0];
+ var y1 = start[1];
+ var x2 = end[0];
+ var y2 = end[1];
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+ var along = (dx === 0 && dy === 0) ? 0 :
+ ((dx * (x0 - x1)) + (dy * (y0 - y1))) / ((dx * dx + dy * dy) || 0);
+ var x, y;
+ if (along <= 0) {
+ x = x1;
+ y = y1;
+ } else if (along >= 1) {
+ x = x2;
+ y = y2;
+ } else {
+ x = x1 + along * dx;
+ y = y1 + along * dy;
}
+ return [x, y];
};
-goog.inherits(goog.events.BrowserEvent, goog.events.Event);
/**
- * Normalized button constants for the mouse.
- * @enum {number}
+ * Returns a {@link ol.CoordinateFormatType} function that can be used to format
+ * a {ol.Coordinate} to a string.
+ *
+ * Example without specifying the fractional digits:
+ *
+ * var coord = [7.85, 47.983333];
+ * var stringifyFunc = ol.coordinate.createStringXY();
+ * var out = stringifyFunc(coord);
+ * // out is now '8, 48'
+ *
+ * Example with explicitly specifying 2 fractional digits:
+ *
+ * var coord = [7.85, 47.983333];
+ * var stringifyFunc = ol.coordinate.createStringXY(2);
+ * var out = stringifyFunc(coord);
+ * // out is now '7.85, 47.98'
+ *
+ * @param {number=} opt_fractionDigits The number of digits to include
+ * after the decimal point. Default is `0`.
+ * @return {ol.CoordinateFormatType} Coordinate format.
+ * @api stable
*/
-goog.events.BrowserEvent.MouseButton = {
- LEFT: 0,
- MIDDLE: 1,
- RIGHT: 2
+ol.coordinate.createStringXY = function(opt_fractionDigits) {
+ return (
+ /**
+ * @param {ol.Coordinate|undefined} coordinate Coordinate.
+ * @return {string} String XY.
+ */
+ function(coordinate) {
+ return ol.coordinate.toStringXY(coordinate, opt_fractionDigits);
+ });
};
/**
- * Static data for mapping mouse buttons.
- * @type {!Array<number>}
- */
-goog.events.BrowserEvent.IEButtonMap = [
- 1, // LEFT
- 4, // MIDDLE
- 2 // RIGHT
-];
-
-
-/**
- * Accepts a browser event object and creates a patched, cross browser event
- * object.
- * @param {Event} e Browser event object.
- * @param {EventTarget=} opt_currentTarget Current target for event.
+ * @private
+ * @param {number} degrees Degrees.
+ * @param {string} hemispheres Hemispheres.
+ * @param {number=} opt_fractionDigits The number of digits to include
+ * after the decimal point. Default is `0`.
+ * @return {string} String.
*/
-goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {
- var type = this.type = e.type;
-
- /**
- * On touch devices use the first "changed touch" as the relevant touch.
- * @type {Touch}
- */
- var relevantTouch = e.changedTouches ? e.changedTouches[0] : null;
-
- // TODO(nicksantos): Change this.target to type EventTarget.
- this.target = /** @type {Node} */ (e.target) || e.srcElement;
-
- // TODO(nicksantos): Change this.currentTarget to type EventTarget.
- this.currentTarget = /** @type {Node} */ (opt_currentTarget);
-
- var relatedTarget = /** @type {Node} */ (e.relatedTarget);
- if (relatedTarget) {
- // There's a bug in FireFox where sometimes, relatedTarget will be a
- // chrome element, and accessing any property of it will get a permission
- // denied exception. See:
- // https://bugzilla.mozilla.org/show_bug.cgi?id=497780
- if (goog.userAgent.GECKO) {
- if (!goog.reflect.canAccessProperty(relatedTarget, 'nodeName')) {
- relatedTarget = null;
- }
- }
- // TODO(arv): Use goog.events.EventType when it has been refactored into its
- // own file.
- } else if (type == goog.events.EventType.MOUSEOVER) {
- relatedTarget = e.fromElement;
- } else if (type == goog.events.EventType.MOUSEOUT) {
- relatedTarget = e.toElement;
- }
-
- this.relatedTarget = relatedTarget;
-
- if (!goog.isNull(relevantTouch)) {
- this.clientX = relevantTouch.clientX !== undefined ?
- relevantTouch.clientX : relevantTouch.pageX;
- this.clientY = relevantTouch.clientY !== undefined ?
- relevantTouch.clientY : relevantTouch.pageY;
- this.screenX = relevantTouch.screenX || 0;
- this.screenY = relevantTouch.screenY || 0;
- } else {
- // Webkit emits a lame warning whenever layerX/layerY is accessed.
- // http://code.google.com/p/chromium/issues/detail?id=101733
- this.offsetX = (goog.userAgent.WEBKIT || e.offsetX !== undefined) ?
- e.offsetX : e.layerX;
- this.offsetY = (goog.userAgent.WEBKIT || e.offsetY !== undefined) ?
- e.offsetY : e.layerY;
- this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;
- this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;
- this.screenX = e.screenX || 0;
- this.screenY = e.screenY || 0;
- }
-
- this.button = e.button;
-
- this.keyCode = e.keyCode || 0;
- this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);
- this.ctrlKey = e.ctrlKey;
- this.altKey = e.altKey;
- this.shiftKey = e.shiftKey;
- this.metaKey = e.metaKey;
- this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;
- this.state = e.state;
- this.event_ = e;
- if (e.defaultPrevented) {
- this.preventDefault();
- }
+ol.coordinate.degreesToStringHDMS_ = function(degrees, hemispheres, opt_fractionDigits) {
+ var normalizedDegrees = ol.math.modulo(degrees + 180, 360) - 180;
+ var x = Math.abs(3600 * normalizedDegrees);
+ var dflPrecision = opt_fractionDigits || 0;
+ return Math.floor(x / 3600) + '\u00b0 ' +
+ ol.string.padNumber(Math.floor((x / 60) % 60), 2) + '\u2032 ' +
+ ol.string.padNumber((x % 60), 2, dflPrecision) + '\u2033 ' +
+ hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0);
};
/**
- * Tests to see which button was pressed during the event. This is really only
- * useful in IE and Gecko browsers. And in IE, it's only useful for
- * mousedown/mouseup events, because click only fires for the left mouse button.
+ * Transforms the given {@link ol.Coordinate} to a string using the given string
+ * template. The strings `{x}` and `{y}` in the template will be replaced with
+ * the first and second coordinate values respectively.
*
- * Safari 2 only reports the left button being clicked, and uses the value '1'
- * instead of 0. Opera only reports a mousedown event for the middle button, and
- * no mouse events for the right button. Opera has default behavior for left and
- * middle click that can only be overridden via a configuration setting.
+ * Example without specifying the fractional digits:
*
- * There's a nice table of this mess at http://www.unixpapa.com/js/mouse.html.
+ * var coord = [7.85, 47.983333];
+ * var template = 'Coordinate is ({x}|{y}).';
+ * var out = ol.coordinate.format(coord, template);
+ * // out is now 'Coordinate is (8|48).'
*
- * @param {goog.events.BrowserEvent.MouseButton} button The button
- * to test for.
- * @return {boolean} True if button was pressed.
- */
-goog.events.BrowserEvent.prototype.isButton = function(button) {
- if (!goog.events.BrowserFeature.HAS_W3C_BUTTON) {
- if (this.type == 'click') {
- return button == goog.events.BrowserEvent.MouseButton.LEFT;
- } else {
- return !!(this.event_.button &
- goog.events.BrowserEvent.IEButtonMap[button]);
- }
- } else {
- return this.event_.button == button;
- }
-};
-
-
-/**
- * Whether this has an "action"-producing mouse button.
+ * Example explicitly specifying the fractional digits:
*
- * By definition, this includes left-click on windows/linux, and left-click
- * without the ctrl key on Macs.
+ * var coord = [7.85, 47.983333];
+ * var template = 'Coordinate is ({x}|{y}).';
+ * var out = ol.coordinate.format(coord, template, 2);
+ * // out is now 'Coordinate is (7.85|47.98).'
*
- * @return {boolean} The result.
- */
-goog.events.BrowserEvent.prototype.isMouseActionButton = function() {
- // Webkit does not ctrl+click to be a right-click, so we
- // normalize it to behave like Gecko and Opera.
- return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) &&
- !(goog.userAgent.WEBKIT && goog.userAgent.MAC && this.ctrlKey);
-};
-
-
-/**
- * @override
+ * @param {ol.Coordinate|undefined} coordinate Coordinate.
+ * @param {string} template A template string with `{x}` and `{y}` placeholders
+ * that will be replaced by first and second coordinate values.
+ * @param {number=} opt_fractionDigits The number of digits to include
+ * after the decimal point. Default is `0`.
+ * @return {string} Formatted coordinate.
+ * @api stable
*/
-goog.events.BrowserEvent.prototype.stopPropagation = function() {
- goog.events.BrowserEvent.superClass_.stopPropagation.call(this);
- if (this.event_.stopPropagation) {
- this.event_.stopPropagation();
+ol.coordinate.format = function(coordinate, template, opt_fractionDigits) {
+ if (coordinate) {
+ return template
+ .replace('{x}', coordinate[0].toFixed(opt_fractionDigits))
+ .replace('{y}', coordinate[1].toFixed(opt_fractionDigits));
} else {
- this.event_.cancelBubble = true;
+ return '';
}
};
/**
- * @override
+ * @param {ol.Coordinate} coordinate1 First coordinate.
+ * @param {ol.Coordinate} coordinate2 Second coordinate.
+ * @return {boolean} Whether the passed coordinates are equal.
*/
-goog.events.BrowserEvent.prototype.preventDefault = function() {
- goog.events.BrowserEvent.superClass_.preventDefault.call(this);
- var be = this.event_;
- if (!be.preventDefault) {
- be.returnValue = false;
- if (goog.events.BrowserFeature.SET_KEY_CODE_TO_PREVENT_DEFAULT) {
- /** @preserveTry */
- try {
- // Most keys can be prevented using returnValue. Some special keys
- // require setting the keyCode to -1 as well:
- //
- // In IE7:
- // F3, F5, F10, F11, Ctrl+P, Crtl+O, Ctrl+F (these are taken from IE6)
- //
- // In IE8:
- // Ctrl+P, Crtl+O, Ctrl+F (F1-F12 cannot be stopped through the event)
- //
- // We therefore do this for all function keys as well as when Ctrl key
- // is pressed.
- var VK_F1 = 112;
- var VK_F12 = 123;
- if (be.ctrlKey || be.keyCode >= VK_F1 && be.keyCode <= VK_F12) {
- be.keyCode = -1;
- }
- } catch (ex) {
- // IE throws an 'access denied' exception when trying to change
- // keyCode in some situations (e.g. srcElement is input[type=file],
- // or srcElement is an anchor tag rewritten by parent's innerHTML).
- // Do nothing in this case.
- }
+ol.coordinate.equals = function(coordinate1, coordinate2) {
+ var equals = true;
+ for (var i = coordinate1.length - 1; i >= 0; --i) {
+ if (coordinate1[i] != coordinate2[i]) {
+ equals = false;
+ break;
}
- } else {
- be.preventDefault();
}
+ return equals;
};
/**
- * @return {Event} The underlying browser event object.
- */
-goog.events.BrowserEvent.prototype.getBrowserEvent = function() {
- return this.event_;
-};
-
-// Copyright 2012 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview An interface for a listenable JavaScript object.
- * @author chrishenry@google.com (Chris Henry)
- */
-
-goog.provide('goog.events.Listenable');
-goog.provide('goog.events.ListenableKey');
-
-/** @suppress {extraRequire} */
-goog.require('goog.events.EventId');
-
-
-
-/**
- * A listenable interface. A listenable is an object with the ability
- * to dispatch/broadcast events to "event listeners" registered via
- * listen/listenOnce.
- *
- * The interface allows for an event propagation mechanism similar
- * to one offered by native browser event targets, such as
- * capture/bubble mechanism, stopping propagation, and preventing
- * default actions. Capture/bubble mechanism depends on the ancestor
- * tree constructed via {@code #getParentEventTarget}; this tree
- * must be directed acyclic graph. The meaning of default action(s)
- * in preventDefault is specific to a particular use case.
- *
- * Implementations that do not support capture/bubble or can not have
- * a parent listenable can simply not implement any ability to set the
- * parent listenable (and have {@code #getParentEventTarget} return
- * null).
+ * Rotate `coordinate` by `angle`. `coordinate` is modified in place and
+ * returned by the function.
*
- * Implementation of this class can be used with or independently from
- * goog.events.
+ * Example:
*
- * Implementation must call {@code #addImplementation(implClass)}.
+ * var coord = [7.85, 47.983333];
+ * var rotateRadians = Math.PI / 2; // 90 degrees
+ * ol.coordinate.rotate(coord, rotateRadians);
+ * // coord is now [-47.983333, 7.85]
*
- * @interface
- * @see goog.events
- * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @param {number} angle Angle in radian.
+ * @return {ol.Coordinate} Coordinate.
+ * @api stable
*/
-goog.events.Listenable = function() {};
+ol.coordinate.rotate = function(coordinate, angle) {
+ var cosAngle = Math.cos(angle);
+ var sinAngle = Math.sin(angle);
+ var x = coordinate[0] * cosAngle - coordinate[1] * sinAngle;
+ var y = coordinate[1] * cosAngle + coordinate[0] * sinAngle;
+ coordinate[0] = x;
+ coordinate[1] = y;
+ return coordinate;
+};
/**
- * An expando property to indicate that an object implements
- * goog.events.Listenable.
+ * Scale `coordinate` by `scale`. `coordinate` is modified in place and returned
+ * by the function.
*
- * See addImplementation/isImplementedBy.
+ * Example:
*
- * @type {string}
- * @const
+ * var coord = [7.85, 47.983333];
+ * var scale = 1.2;
+ * ol.coordinate.scale(coord, scale);
+ * // coord is now [9.42, 57.5799996]
+ *
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @param {number} scale Scale factor.
+ * @return {ol.Coordinate} Coordinate.
*/
-goog.events.Listenable.IMPLEMENTED_BY_PROP =
- 'closure_listenable_' + ((Math.random() * 1e6) | 0);
+ol.coordinate.scale = function(coordinate, scale) {
+ coordinate[0] *= scale;
+ coordinate[1] *= scale;
+ return coordinate;
+};
/**
- * Marks a given class (constructor) as an implementation of
- * Listenable, do that we can query that fact at runtime. The class
- * must have already implemented the interface.
- * @param {!Function} cls The class constructor. The corresponding
- * class must have already implemented the interface.
+ * Subtract `delta` to `coordinate`. `coordinate` is modified in place and
+ * returned by the function.
+ *
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @param {ol.Coordinate} delta Delta.
+ * @return {ol.Coordinate} Coordinate.
*/
-goog.events.Listenable.addImplementation = function(cls) {
- cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true;
+ol.coordinate.sub = function(coordinate, delta) {
+ coordinate[0] -= delta[0];
+ coordinate[1] -= delta[1];
+ return coordinate;
};
/**
- * @param {Object} obj The object to check.
- * @return {boolean} Whether a given instance implements Listenable. The
- * class/superclass of the instance must call addImplementation.
+ * @param {ol.Coordinate} coord1 First coordinate.
+ * @param {ol.Coordinate} coord2 Second coordinate.
+ * @return {number} Squared distance between coord1 and coord2.
*/
-goog.events.Listenable.isImplementedBy = function(obj) {
- return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]);
+ol.coordinate.squaredDistance = function(coord1, coord2) {
+ var dx = coord1[0] - coord2[0];
+ var dy = coord1[1] - coord2[1];
+ return dx * dx + dy * dy;
};
/**
- * Adds an event listener. A listener can only be added once to an
- * object and if it is added again the key for the listener is
- * returned. Note that if the existing listener is a one-off listener
- * (registered via listenOnce), it will no longer be a one-off
- * listener after a call to listen().
+ * Calculate the squared distance from a coordinate to a line segment.
*
- * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
- * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
- * method.
- * @param {boolean=} opt_useCapture Whether to fire in capture phase
- * (defaults to false).
- * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
- * listener.
- * @return {goog.events.ListenableKey} Unique key for the listener.
- * @template SCOPE,EVENTOBJ
+ * @param {ol.Coordinate} coordinate Coordinate of the point.
+ * @param {Array.<ol.Coordinate>} segment Line segment (2 coordinates).
+ * @return {number} Squared distance from the point to the line segment.
*/
-goog.events.Listenable.prototype.listen;
+ol.coordinate.squaredDistanceToSegment = function(coordinate, segment) {
+ return ol.coordinate.squaredDistance(coordinate,
+ ol.coordinate.closestOnSegment(coordinate, segment));
+};
/**
- * Adds an event listener that is removed automatically after the
- * listener fired once.
+ * Format a geographic coordinate with the hemisphere, degrees, minutes, and
+ * seconds.
*
- * If an existing listener already exists, listenOnce will do
- * nothing. In particular, if the listener was previously registered
- * via listen(), listenOnce() will not turn the listener into a
- * one-off listener. Similarly, if there is already an existing
- * one-off listener, listenOnce does not modify the listeners (it is
- * still a once listener).
+ * Example without specifying fractional digits:
*
- * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
- * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
- * method.
- * @param {boolean=} opt_useCapture Whether to fire in capture phase
- * (defaults to false).
- * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
- * listener.
- * @return {goog.events.ListenableKey} Unique key for the listener.
- * @template SCOPE,EVENTOBJ
- */
-goog.events.Listenable.prototype.listenOnce;
-
-
-/**
- * Removes an event listener which was added with listen() or listenOnce().
+ * var coord = [7.85, 47.983333];
+ * var out = ol.coordinate.toStringHDMS(coord);
+ * // out is now '47° 58′ 60″ N 7° 50′ 60″ E'
*
- * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
- * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
- * method.
- * @param {boolean=} opt_useCapture Whether to fire in capture phase
- * (defaults to false).
- * @param {SCOPE=} opt_listenerScope Object in whose scope to call
- * the listener.
- * @return {boolean} Whether any listener was removed.
- * @template SCOPE,EVENTOBJ
- */
-goog.events.Listenable.prototype.unlisten;
-
-
-/**
- * Removes an event listener which was added with listen() by the key
- * returned by listen().
+ * Example explicitly specifying 1 fractional digit:
+ *
+ * var coord = [7.85, 47.983333];
+ * var out = ol.coordinate.toStringHDMS(coord, 1);
+ * // out is now '47° 58′ 60.0″ N 7° 50′ 60.0″ E'
*
- * @param {goog.events.ListenableKey} key The key returned by
- * listen() or listenOnce().
- * @return {boolean} Whether any listener was removed.
+ * @param {ol.Coordinate|undefined} coordinate Coordinate.
+ * @param {number=} opt_fractionDigits The number of digits to include
+ * after the decimal point. Default is `0`.
+ * @return {string} Hemisphere, degrees, minutes and seconds.
+ * @api stable
*/
-goog.events.Listenable.prototype.unlistenByKey;
+ol.coordinate.toStringHDMS = function(coordinate, opt_fractionDigits) {
+ if (coordinate) {
+ return ol.coordinate.degreesToStringHDMS_(coordinate[1], 'NS', opt_fractionDigits) + ' ' +
+ ol.coordinate.degreesToStringHDMS_(coordinate[0], 'EW', opt_fractionDigits);
+ } else {
+ return '';
+ }
+};
/**
- * Dispatches an event (or event like object) and calls all listeners
- * listening for events of this type. The type of the event is decided by the
- * type property on the event object.
+ * Format a coordinate as a comma delimited string.
*
- * If any of the listeners returns false OR calls preventDefault then this
- * function will return false. If one of the capture listeners calls
- * stopPropagation, then the bubble listeners won't fire.
+ * Example without specifying fractional digits:
*
- * @param {goog.events.EventLike} e Event object.
- * @return {boolean} If anyone called preventDefault on the event object (or
- * if any of the listeners returns false) this will also return false.
- */
-goog.events.Listenable.prototype.dispatchEvent;
-
-
-/**
- * Removes all listeners from this listenable. If type is specified,
- * it will only remove listeners of the particular type. otherwise all
- * registered listeners will be removed.
+ * var coord = [7.85, 47.983333];
+ * var out = ol.coordinate.toStringXY(coord);
+ * // out is now '8, 48'
*
- * @param {string=} opt_type Type of event to remove, default is to
- * remove all types.
- * @return {number} Number of listeners removed.
- */
-goog.events.Listenable.prototype.removeAllListeners;
-
-
-/**
- * Returns the parent of this event target to use for capture/bubble
- * mechanism.
+ * Example explicitly specifying 1 fractional digit:
*
- * NOTE(chrishenry): The name reflects the original implementation of
- * custom event target ({@code goog.events.EventTarget}). We decided
- * that changing the name is not worth it.
+ * var coord = [7.85, 47.983333];
+ * var out = ol.coordinate.toStringXY(coord, 1);
+ * // out is now '7.8, 48.0'
*
- * @return {goog.events.Listenable} The parent EventTarget or null if
- * there is no parent.
+ * @param {ol.Coordinate|undefined} coordinate Coordinate.
+ * @param {number=} opt_fractionDigits The number of digits to include
+ * after the decimal point. Default is `0`.
+ * @return {string} XY.
+ * @api stable
*/
-goog.events.Listenable.prototype.getParentEventTarget;
+ol.coordinate.toStringXY = function(coordinate, opt_fractionDigits) {
+ return ol.coordinate.format(coordinate, '{x}, {y}', opt_fractionDigits);
+};
/**
- * Fires all registered listeners in this listenable for the given
- * type and capture mode, passing them the given eventObject. This
- * does not perform actual capture/bubble. Only implementors of the
- * interface should be using this.
+ * Create an ol.Coordinate from an Array and take into account axis order.
*
- * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the
- * listeners to fire.
- * @param {boolean} capture The capture mode of the listeners to fire.
- * @param {EVENTOBJ} eventObject The event object to fire.
- * @return {boolean} Whether all listeners succeeded without
- * attempting to prevent default behavior. If any listener returns
- * false or called goog.events.Event#preventDefault, this returns
- * false.
- * @template EVENTOBJ
- */
-goog.events.Listenable.prototype.fireListeners;
-
-
-/**
- * Gets all listeners in this listenable for the given type and
- * capture mode.
+ * Examples:
*
- * @param {string|!goog.events.EventId} type The type of the listeners to fire.
- * @param {boolean} capture The capture mode of the listeners to fire.
- * @return {!Array<goog.events.ListenableKey>} An array of registered
- * listeners.
- * @template EVENTOBJ
- */
-goog.events.Listenable.prototype.getListeners;
-
-
-/**
- * Gets the goog.events.ListenableKey for the event or null if no such
- * listener is in use.
+ * var northCoord = ol.coordinate.fromProjectedArray([1, 2], 'n');
+ * // northCoord is now [2, 1]
*
- * @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event
- * without the 'on' prefix.
- * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The
- * listener function to get.
- * @param {boolean} capture Whether the listener is a capturing listener.
- * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
- * listener.
- * @return {goog.events.ListenableKey} the found listener or null if not found.
- * @template SCOPE,EVENTOBJ
- */
-goog.events.Listenable.prototype.getListener;
-
-
-/**
- * Whether there is any active listeners matching the specified
- * signature. If either the type or capture parameters are
- * unspecified, the function will match on the remaining criteria.
+ * var eastCoord = ol.coordinate.fromProjectedArray([1, 2], 'e');
+ * // eastCoord is now [1, 2]
*
- * @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type.
- * @param {boolean=} opt_capture Whether to check for capture or bubble
- * listeners.
- * @return {boolean} Whether there is any active listeners matching
- * the requested type and/or capture phase.
- * @template EVENTOBJ
- */
-goog.events.Listenable.prototype.hasListener;
-
-
-
-/**
- * An interface that describes a single registered listener.
- * @interface
- */
-goog.events.ListenableKey = function() {};
-
-
-/**
- * Counter used to create a unique key
- * @type {number}
- * @private
- */
-goog.events.ListenableKey.counter_ = 0;
-
-
-/**
- * Reserves a key to be used for ListenableKey#key field.
- * @return {number} A number to be used to fill ListenableKey#key
- * field.
- */
-goog.events.ListenableKey.reserveKey = function() {
- return ++goog.events.ListenableKey.counter_;
-};
-
-
-/**
- * The source event target.
- * @type {!(Object|goog.events.Listenable|goog.events.EventTarget)}
- */
-goog.events.ListenableKey.prototype.src;
-
-
-/**
- * The event type the listener is listening to.
- * @type {string}
- */
-goog.events.ListenableKey.prototype.type;
-
-
-/**
- * The listener function.
- * @type {function(?):?|{handleEvent:function(?):?}|null}
- */
-goog.events.ListenableKey.prototype.listener;
-
-
-/**
- * Whether the listener works on capture phase.
- * @type {boolean}
- */
-goog.events.ListenableKey.prototype.capture;
-
-
-/**
- * The 'this' object for the listener function's scope.
- * @type {Object}
- */
-goog.events.ListenableKey.prototype.handler;
-
-
-/**
- * A globally unique number to identify the key.
- * @type {number}
- */
-goog.events.ListenableKey.prototype.key;
-
-// Copyright 2005 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Listener object.
- * @see ../demos/events.html
- */
-
-goog.provide('goog.events.Listener');
-
-goog.require('goog.events.ListenableKey');
-
-
-
-/**
- * Simple class that stores information about a listener
- * @param {!Function} listener Callback function.
- * @param {Function} proxy Wrapper for the listener that patches the event.
- * @param {EventTarget|goog.events.Listenable} src Source object for
- * the event.
- * @param {string} type Event type.
- * @param {boolean} capture Whether in capture or bubble phase.
- * @param {Object=} opt_handler Object in whose context to execute the callback.
- * @implements {goog.events.ListenableKey}
- * @constructor
+ * @param {Array} array The array with coordinates.
+ * @param {string} axis the axis info.
+ * @return {ol.Coordinate} The coordinate created.
*/
-goog.events.Listener = function(
- listener, proxy, src, type, capture, opt_handler) {
- if (goog.events.Listener.ENABLE_MONITORING) {
- this.creationStack = new Error().stack;
+ol.coordinate.fromProjectedArray = function(array, axis) {
+ var firstAxis = axis.charAt(0);
+ if (firstAxis === 'n' || firstAxis === 's') {
+ return [array[1], array[0]];
+ } else {
+ return array;
}
-
- /**
- * Callback function.
- * @type {Function}
- */
- this.listener = listener;
-
- /**
- * A wrapper over the original listener. This is used solely to
- * handle native browser events (it is used to simulate the capture
- * phase and to patch the event object).
- * @type {Function}
- */
- this.proxy = proxy;
-
- /**
- * Object or node that callback is listening to
- * @type {EventTarget|goog.events.Listenable}
- */
- this.src = src;
-
- /**
- * The event type.
- * @const {string}
- */
- this.type = type;
-
- /**
- * Whether the listener is being called in the capture or bubble phase
- * @const {boolean}
- */
- this.capture = !!capture;
-
- /**
- * Optional object whose context to execute the listener in
- * @type {Object|undefined}
- */
- this.handler = opt_handler;
-
- /**
- * The key of the listener.
- * @const {number}
- * @override
- */
- this.key = goog.events.ListenableKey.reserveKey();
-
- /**
- * Whether to remove the listener after it has been called.
- * @type {boolean}
- */
- this.callOnce = false;
-
- /**
- * Whether the listener has been removed.
- * @type {boolean}
- */
- this.removed = false;
};
+goog.provide('ol.extent');
+goog.provide('ol.extent.Corner');
+goog.provide('ol.extent.Relationship');
-/**
- * @define {boolean} Whether to enable the monitoring of the
- * goog.events.Listener instances. Switching on the monitoring is only
- * recommended for debugging because it has a significant impact on
- * performance and memory usage. If switched off, the monitoring code
- * compiles down to 0 bytes.
- */
-goog.define('goog.events.Listener.ENABLE_MONITORING', false);
+goog.require('goog.asserts');
/**
- * If monitoring the goog.events.Listener instances is enabled, stores the
- * creation stack trace of the Disposable instance.
- * @type {string}
+ * Extent corner.
+ * @enum {string}
*/
-goog.events.Listener.prototype.creationStack;
+ol.extent.Corner = {
+ BOTTOM_LEFT: 'bottom-left',
+ BOTTOM_RIGHT: 'bottom-right',
+ TOP_LEFT: 'top-left',
+ TOP_RIGHT: 'top-right'
+};
/**
- * Marks this listener as removed. This also remove references held by
- * this listener object (such as listener and event source).
+ * Relationship to an extent.
+ * @enum {number}
*/
-goog.events.Listener.prototype.markAsRemoved = function() {
- this.removed = true;
- this.listener = null;
- this.proxy = null;
- this.src = null;
- this.handler = null;
+ol.extent.Relationship = {
+ UNKNOWN: 0,
+ INTERSECTING: 1,
+ ABOVE: 2,
+ RIGHT: 4,
+ BELOW: 8,
+ LEFT: 16
};
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview A map of listeners that provides utility functions to
- * deal with listeners on an event target. Used by
- * {@code goog.events.EventTarget}.
- *
- * WARNING: Do not use this class from outside goog.events package.
+ * Build an extent that includes all given coordinates.
*
- * @visibility {//closure/goog/bin/sizetests:__pkg__}
- * @visibility {//closure/goog/events:__pkg__}
- * @visibility {//closure/goog/labs/events:__pkg__}
- */
-
-goog.provide('goog.events.ListenerMap');
-
-goog.require('goog.array');
-goog.require('goog.events.Listener');
-goog.require('goog.object');
-
-
-
-/**
- * Creates a new listener map.
- * @param {EventTarget|goog.events.Listenable} src The src object.
- * @constructor
- * @final
+ * @param {Array.<ol.Coordinate>} coordinates Coordinates.
+ * @return {ol.Extent} Bounding extent.
+ * @api stable
*/
-goog.events.ListenerMap = function(src) {
- /** @type {EventTarget|goog.events.Listenable} */
- this.src = src;
-
- /**
- * Maps of event type to an array of listeners.
- * @type {Object<string, !Array<!goog.events.Listener>>}
- */
- this.listeners = {};
-
- /**
- * The count of types in this map that have registered listeners.
- * @private {number}
- */
- this.typeCount_ = 0;
+ol.extent.boundingExtent = function(coordinates) {
+ var extent = ol.extent.createEmpty();
+ for (var i = 0, ii = coordinates.length; i < ii; ++i) {
+ ol.extent.extendCoordinate(extent, coordinates[i]);
+ }
+ return extent;
};
/**
- * @return {number} The count of event types in this map that actually
- * have registered listeners.
+ * @param {Array.<number>} xs Xs.
+ * @param {Array.<number>} ys Ys.
+ * @param {ol.Extent=} opt_extent Destination extent.
+ * @private
+ * @return {ol.Extent} Extent.
*/
-goog.events.ListenerMap.prototype.getTypeCount = function() {
- return this.typeCount_;
+ol.extent.boundingExtentXYs_ = function(xs, ys, opt_extent) {
+ goog.asserts.assert(xs.length > 0, 'xs length should be larger than 0');
+ goog.asserts.assert(ys.length > 0, 'ys length should be larger than 0');
+ var minX = Math.min.apply(null, xs);
+ var minY = Math.min.apply(null, ys);
+ var maxX = Math.max.apply(null, xs);
+ var maxY = Math.max.apply(null, ys);
+ return ol.extent.createOrUpdate(minX, minY, maxX, maxY, opt_extent);
};
/**
- * @return {number} Total number of registered listeners.
+ * Return extent increased by the provided value.
+ * @param {ol.Extent} extent Extent.
+ * @param {number} value The amount by which the extent should be buffered.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} Extent.
+ * @api stable
*/
-goog.events.ListenerMap.prototype.getListenerCount = function() {
- var count = 0;
- for (var type in this.listeners) {
- count += this.listeners[type].length;
+ol.extent.buffer = function(extent, value, opt_extent) {
+ if (opt_extent) {
+ opt_extent[0] = extent[0] - value;
+ opt_extent[1] = extent[1] - value;
+ opt_extent[2] = extent[2] + value;
+ opt_extent[3] = extent[3] + value;
+ return opt_extent;
+ } else {
+ return [
+ extent[0] - value,
+ extent[1] - value,
+ extent[2] + value,
+ extent[3] + value
+ ];
}
- return count;
};
/**
- * Adds an event listener. A listener can only be added once to an
- * object and if it is added again the key for the listener is
- * returned.
- *
- * Note that a one-off listener will not change an existing listener,
- * if any. On the other hand a normal listener will change existing
- * one-off listener to become a normal listener.
+ * Creates a clone of an extent.
*
- * @param {string|!goog.events.EventId} type The listener event type.
- * @param {!Function} listener This listener callback method.
- * @param {boolean} callOnce Whether the listener is a one-off
- * listener.
- * @param {boolean=} opt_useCapture The capture mode of the listener.
- * @param {Object=} opt_listenerScope Object in whose scope to call the
- * listener.
- * @return {goog.events.ListenableKey} Unique key for the listener.
+ * @param {ol.Extent} extent Extent to clone.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} The clone.
*/
-goog.events.ListenerMap.prototype.add = function(
- type, listener, callOnce, opt_useCapture, opt_listenerScope) {
- var typeStr = type.toString();
- var listenerArray = this.listeners[typeStr];
- if (!listenerArray) {
- listenerArray = this.listeners[typeStr] = [];
- this.typeCount_++;
- }
-
- var listenerObj;
- var index = goog.events.ListenerMap.findListenerIndex_(
- listenerArray, listener, opt_useCapture, opt_listenerScope);
- if (index > -1) {
- listenerObj = listenerArray[index];
- if (!callOnce) {
- // Ensure that, if there is an existing callOnce listener, it is no
- // longer a callOnce listener.
- listenerObj.callOnce = false;
- }
+ol.extent.clone = function(extent, opt_extent) {
+ if (opt_extent) {
+ opt_extent[0] = extent[0];
+ opt_extent[1] = extent[1];
+ opt_extent[2] = extent[2];
+ opt_extent[3] = extent[3];
+ return opt_extent;
} else {
- listenerObj = new goog.events.Listener(
- listener, null, this.src, typeStr, !!opt_useCapture, opt_listenerScope);
- listenerObj.callOnce = callOnce;
- listenerArray.push(listenerObj);
+ return extent.slice();
}
- return listenerObj;
};
/**
- * Removes a matching listener.
- * @param {string|!goog.events.EventId} type The listener event type.
- * @param {!Function} listener This listener callback method.
- * @param {boolean=} opt_useCapture The capture mode of the listener.
- * @param {Object=} opt_listenerScope Object in whose scope to call the
- * listener.
- * @return {boolean} Whether any listener was removed.
+ * @param {ol.Extent} extent Extent.
+ * @param {number} x X.
+ * @param {number} y Y.
+ * @return {number} Closest squared distance.
*/
-goog.events.ListenerMap.prototype.remove = function(
- type, listener, opt_useCapture, opt_listenerScope) {
- var typeStr = type.toString();
- if (!(typeStr in this.listeners)) {
- return false;
+ol.extent.closestSquaredDistanceXY = function(extent, x, y) {
+ var dx, dy;
+ if (x < extent[0]) {
+ dx = extent[0] - x;
+ } else if (extent[2] < x) {
+ dx = x - extent[2];
+ } else {
+ dx = 0;
}
-
- var listenerArray = this.listeners[typeStr];
- var index = goog.events.ListenerMap.findListenerIndex_(
- listenerArray, listener, opt_useCapture, opt_listenerScope);
- if (index > -1) {
- var listenerObj = listenerArray[index];
- listenerObj.markAsRemoved();
- goog.array.removeAt(listenerArray, index);
- if (listenerArray.length == 0) {
- delete this.listeners[typeStr];
- this.typeCount_--;
- }
- return true;
+ if (y < extent[1]) {
+ dy = extent[1] - y;
+ } else if (extent[3] < y) {
+ dy = y - extent[3];
+ } else {
+ dy = 0;
}
- return false;
+ return dx * dx + dy * dy;
};
/**
- * Removes the given listener object.
- * @param {goog.events.ListenableKey} listener The listener to remove.
- * @return {boolean} Whether the listener is removed.
+ * Check if the passed coordinate is contained or on the edge of the extent.
+ *
+ * @param {ol.Extent} extent Extent.
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @return {boolean} The coordinate is contained in the extent.
+ * @api stable
*/
-goog.events.ListenerMap.prototype.removeByKey = function(listener) {
- var type = listener.type;
- if (!(type in this.listeners)) {
- return false;
- }
-
- var removed = goog.array.remove(this.listeners[type], listener);
- if (removed) {
- listener.markAsRemoved();
- if (this.listeners[type].length == 0) {
- delete this.listeners[type];
- this.typeCount_--;
- }
- }
- return removed;
+ol.extent.containsCoordinate = function(extent, coordinate) {
+ return ol.extent.containsXY(extent, coordinate[0], coordinate[1]);
};
/**
- * Removes all listeners from this map. If opt_type is provided, only
- * listeners that match the given type are removed.
- * @param {string|!goog.events.EventId=} opt_type Type of event to remove.
- * @return {number} Number of listeners removed.
+ * Check if one extent contains another.
+ *
+ * An extent is deemed contained if it lies completely within the other extent,
+ * including if they share one or more edges.
+ *
+ * @param {ol.Extent} extent1 Extent 1.
+ * @param {ol.Extent} extent2 Extent 2.
+ * @return {boolean} The second extent is contained by or on the edge of the
+ * first.
+ * @api stable
*/
-goog.events.ListenerMap.prototype.removeAll = function(opt_type) {
- var typeStr = opt_type && opt_type.toString();
- var count = 0;
- for (var type in this.listeners) {
- if (!typeStr || type == typeStr) {
- var listenerArray = this.listeners[type];
- for (var i = 0; i < listenerArray.length; i++) {
- ++count;
- listenerArray[i].markAsRemoved();
- }
- delete this.listeners[type];
- this.typeCount_--;
- }
- }
- return count;
+ol.extent.containsExtent = function(extent1, extent2) {
+ return extent1[0] <= extent2[0] && extent2[2] <= extent1[2] &&
+ extent1[1] <= extent2[1] && extent2[3] <= extent1[3];
};
/**
- * Gets all listeners that match the given type and capture mode. The
- * returned array is a copy (but the listener objects are not).
- * @param {string|!goog.events.EventId} type The type of the listeners
- * to retrieve.
- * @param {boolean} capture The capture mode of the listeners to retrieve.
- * @return {!Array<goog.events.ListenableKey>} An array of matching
- * listeners.
+ * Check if the passed coordinate is contained or on the edge of the extent.
+ *
+ * @param {ol.Extent} extent Extent.
+ * @param {number} x X coordinate.
+ * @param {number} y Y coordinate.
+ * @return {boolean} The x, y values are contained in the extent.
+ * @api stable
*/
-goog.events.ListenerMap.prototype.getListeners = function(type, capture) {
- var listenerArray = this.listeners[type.toString()];
- var rv = [];
- if (listenerArray) {
- for (var i = 0; i < listenerArray.length; ++i) {
- var listenerObj = listenerArray[i];
- if (listenerObj.capture == capture) {
- rv.push(listenerObj);
- }
- }
- }
- return rv;
+ol.extent.containsXY = function(extent, x, y) {
+ return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];
};
/**
- * Gets the goog.events.ListenableKey for the event or null if no such
- * listener is in use.
- *
- * @param {string|!goog.events.EventId} type The type of the listener
- * to retrieve.
- * @param {!Function} listener The listener function to get.
- * @param {boolean} capture Whether the listener is a capturing listener.
- * @param {Object=} opt_listenerScope Object in whose scope to call the
- * listener.
- * @return {goog.events.ListenableKey} the found listener or null if not found.
+ * Get the relationship between a coordinate and extent.
+ * @param {ol.Extent} extent The extent.
+ * @param {ol.Coordinate} coordinate The coordinate.
+ * @return {number} The relationship (bitwise compare with
+ * ol.extent.Relationship).
*/
-goog.events.ListenerMap.prototype.getListener = function(
- type, listener, capture, opt_listenerScope) {
- var listenerArray = this.listeners[type.toString()];
- var i = -1;
- if (listenerArray) {
- i = goog.events.ListenerMap.findListenerIndex_(
- listenerArray, listener, capture, opt_listenerScope);
+ol.extent.coordinateRelationship = function(extent, coordinate) {
+ var minX = extent[0];
+ var minY = extent[1];
+ var maxX = extent[2];
+ var maxY = extent[3];
+ var x = coordinate[0];
+ var y = coordinate[1];
+ var relationship = ol.extent.Relationship.UNKNOWN;
+ if (x < minX) {
+ relationship = relationship | ol.extent.Relationship.LEFT;
+ } else if (x > maxX) {
+ relationship = relationship | ol.extent.Relationship.RIGHT;
+ }
+ if (y < minY) {
+ relationship = relationship | ol.extent.Relationship.BELOW;
+ } else if (y > maxY) {
+ relationship = relationship | ol.extent.Relationship.ABOVE;
+ }
+ if (relationship === ol.extent.Relationship.UNKNOWN) {
+ relationship = ol.extent.Relationship.INTERSECTING;
}
- return i > -1 ? listenerArray[i] : null;
+ return relationship;
};
/**
- * Whether there is a matching listener. If either the type or capture
- * parameters are unspecified, the function will match on the
- * remaining criteria.
- *
- * @param {string|!goog.events.EventId=} opt_type The type of the listener.
- * @param {boolean=} opt_capture The capture mode of the listener.
- * @return {boolean} Whether there is an active listener matching
- * the requested type and/or capture phase.
+ * Create an empty extent.
+ * @return {ol.Extent} Empty extent.
+ * @api stable
*/
-goog.events.ListenerMap.prototype.hasListener = function(
- opt_type, opt_capture) {
- var hasType = goog.isDef(opt_type);
- var typeStr = hasType ? opt_type.toString() : '';
- var hasCapture = goog.isDef(opt_capture);
-
- return goog.object.some(
- this.listeners, function(listenerArray, type) {
- for (var i = 0; i < listenerArray.length; ++i) {
- if ((!hasType || listenerArray[i].type == typeStr) &&
- (!hasCapture || listenerArray[i].capture == opt_capture)) {
- return true;
- }
- }
-
- return false;
- });
+ol.extent.createEmpty = function() {
+ return [Infinity, Infinity, -Infinity, -Infinity];
};
/**
- * Finds the index of a matching goog.events.Listener in the given
- * listenerArray.
- * @param {!Array<!goog.events.Listener>} listenerArray Array of listener.
- * @param {!Function} listener The listener function.
- * @param {boolean=} opt_useCapture The capture flag for the listener.
- * @param {Object=} opt_listenerScope The listener scope.
- * @return {number} The index of the matching listener within the
- * listenerArray.
- * @private
- */
-goog.events.ListenerMap.findListenerIndex_ = function(
- listenerArray, listener, opt_useCapture, opt_listenerScope) {
- for (var i = 0; i < listenerArray.length; ++i) {
- var listenerObj = listenerArray[i];
- if (!listenerObj.removed &&
- listenerObj.listener == listener &&
- listenerObj.capture == !!opt_useCapture &&
- listenerObj.handler == opt_listenerScope) {
- return i;
- }
+ * Create a new extent or update the provided extent.
+ * @param {number} minX Minimum X.
+ * @param {number} minY Minimum Y.
+ * @param {number} maxX Maximum X.
+ * @param {number} maxY Maximum Y.
+ * @param {ol.Extent=} opt_extent Destination extent.
+ * @return {ol.Extent} Extent.
+ */
+ol.extent.createOrUpdate = function(minX, minY, maxX, maxY, opt_extent) {
+ if (opt_extent) {
+ opt_extent[0] = minX;
+ opt_extent[1] = minY;
+ opt_extent[2] = maxX;
+ opt_extent[3] = maxY;
+ return opt_extent;
+ } else {
+ return [minX, minY, maxX, maxY];
}
- return -1;
};
-// Copyright 2005 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview An event manager for both native browser event
- * targets and custom JavaScript event targets
- * ({@code goog.events.Listenable}). This provides an abstraction
- * over browsers' event systems.
- *
- * It also provides a simulation of W3C event model's capture phase in
- * Internet Explorer (IE 8 and below). Caveat: the simulation does not
- * interact well with listeners registered directly on the elements
- * (bypassing goog.events) or even with listeners registered via
- * goog.events in a separate JS binary. In these cases, we provide
- * no ordering guarantees.
- *
- * The listeners will receive a "patched" event object. Such event object
- * contains normalized values for certain event properties that differs in
- * different browsers.
- *
- * Example usage:
- * <pre>
- * goog.events.listen(myNode, 'click', function(e) { alert('woo') });
- * goog.events.listen(myNode, 'mouseover', mouseHandler, true);
- * goog.events.unlisten(myNode, 'mouseover', mouseHandler, true);
- * goog.events.removeAll(myNode);
- * </pre>
- *
- * in IE and event object patching]
- * @author arv@google.com (Erik Arvidsson)
- *
- * @see ../demos/events.html
- * @see ../demos/event-propagation.html
- * @see ../demos/stopevent.html
- */
-
-// IMPLEMENTATION NOTES:
-// goog.events stores an auxiliary data structure on each EventTarget
-// source being listened on. This allows us to take advantage of GC,
-// having the data structure GC'd when the EventTarget is GC'd. This
-// GC behavior is equivalent to using W3C DOM Events directly.
-
-goog.provide('goog.events');
-goog.provide('goog.events.CaptureSimulationMode');
-goog.provide('goog.events.Key');
-goog.provide('goog.events.ListenableType');
-
-goog.require('goog.asserts');
-goog.require('goog.debug.entryPointRegistry');
-goog.require('goog.events.BrowserEvent');
-goog.require('goog.events.BrowserFeature');
-goog.require('goog.events.Listenable');
-goog.require('goog.events.ListenerMap');
-
-goog.forwardDeclare('goog.debug.ErrorHandler');
-goog.forwardDeclare('goog.events.EventWrapper');
-
-
-/**
- * @typedef {number|goog.events.ListenableKey}
- */
-goog.events.Key;
-
-
-/**
- * @typedef {EventTarget|goog.events.Listenable}
- */
-goog.events.ListenableType;
-
-
-/**
- * Property name on a native event target for the listener map
- * associated with the event target.
- * @private @const {string}
- */
-goog.events.LISTENER_MAP_PROP_ = 'closure_lm_' + ((Math.random() * 1e6) | 0);
-
-
-/**
- * String used to prepend to IE event types.
- * @const
- * @private
- */
-goog.events.onString_ = 'on';
-
/**
- * Map of computed "on<eventname>" strings for IE event types. Caching
- * this removes an extra object allocation in goog.events.listen which
- * improves IE6 performance.
- * @const
- * @dict
- * @private
- */
-goog.events.onStringMap_ = {};
-
-
-/**
- * @enum {number} Different capture simulation mode for IE8-.
+ * Create a new empty extent or make the provided one empty.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} Extent.
*/
-goog.events.CaptureSimulationMode = {
- /**
- * Does not perform capture simulation. Will asserts in IE8- when you
- * add capture listeners.
- */
- OFF_AND_FAIL: 0,
-
- /**
- * Does not perform capture simulation, silently ignore capture
- * listeners.
- */
- OFF_AND_SILENT: 1,
-
- /**
- * Performs capture simulation.
- */
- ON: 2
+ol.extent.createOrUpdateEmpty = function(opt_extent) {
+ return ol.extent.createOrUpdate(
+ Infinity, Infinity, -Infinity, -Infinity, opt_extent);
};
/**
- * @define {number} The capture simulation mode for IE8-. By default,
- * this is ON.
- */
-goog.define('goog.events.CAPTURE_SIMULATION_MODE', 2);
-
-
-/**
- * Estimated count of total native listeners.
- * @private {number}
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} Extent.
*/
-goog.events.listenerCountEstimate_ = 0;
+ol.extent.createOrUpdateFromCoordinate = function(coordinate, opt_extent) {
+ var x = coordinate[0];
+ var y = coordinate[1];
+ return ol.extent.createOrUpdate(x, y, x, y, opt_extent);
+};
/**
- * Adds an event listener for a specific event on a native event
- * target (such as a DOM element) or an object that has implemented
- * {@link goog.events.Listenable}. A listener can only be added once
- * to an object and if it is added again the key for the listener is
- * returned. Note that if the existing listener is a one-off listener
- * (registered via listenOnce), it will no longer be a one-off
- * listener after a call to listen().
- *
- * @param {EventTarget|goog.events.Listenable} src The node to listen
- * to events on.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type or array of event types.
- * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
- * listener Callback method, or an object with a handleEvent function.
- * WARNING: passing an Object is now softly deprecated.
- * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
- * false).
- * @param {T=} opt_handler Element in whose scope to call the listener.
- * @return {goog.events.Key} Unique key for the listener.
- * @template T,EVENTOBJ
+ * @param {Array.<ol.Coordinate>} coordinates Coordinates.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} Extent.
*/
-goog.events.listen = function(src, type, listener, opt_capt, opt_handler) {
- if (goog.isArray(type)) {
- for (var i = 0; i < type.length; i++) {
- goog.events.listen(src, type[i], listener, opt_capt, opt_handler);
- }
- return null;
- }
-
- listener = goog.events.wrapListener(listener);
- if (goog.events.Listenable.isImplementedBy(src)) {
- return src.listen(
- /** @type {string|!goog.events.EventId} */ (type),
- listener, opt_capt, opt_handler);
- } else {
- return goog.events.listen_(
- /** @type {!EventTarget} */ (src),
- /** @type {string|!goog.events.EventId} */ (type),
- listener, /* callOnce */ false, opt_capt, opt_handler);
- }
+ol.extent.createOrUpdateFromCoordinates = function(coordinates, opt_extent) {
+ var extent = ol.extent.createOrUpdateEmpty(opt_extent);
+ return ol.extent.extendCoordinates(extent, coordinates);
};
/**
- * Adds an event listener for a specific event on a native event
- * target. A listener can only be added once to an object and if it
- * is added again the key for the listener is returned.
- *
- * Note that a one-off listener will not change an existing listener,
- * if any. On the other hand a normal listener will change existing
- * one-off listener to become a normal listener.
- *
- * @param {EventTarget} src The node to listen to events on.
- * @param {string|!goog.events.EventId} type Event type.
- * @param {!Function} listener Callback function.
- * @param {boolean} callOnce Whether the listener is a one-off
- * listener or otherwise.
- * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
- * false).
- * @param {Object=} opt_handler Element in whose scope to call the listener.
- * @return {goog.events.ListenableKey} Unique key for the listener.
- * @private
+ * @param {Array.<number>} flatCoordinates Flat coordinates.
+ * @param {number} offset Offset.
+ * @param {number} end End.
+ * @param {number} stride Stride.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} Extent.
*/
-goog.events.listen_ = function(
- src, type, listener, callOnce, opt_capt, opt_handler) {
- if (!type) {
- throw Error('Invalid event type');
- }
-
- var capture = !!opt_capt;
- if (capture && !goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
- if (goog.events.CAPTURE_SIMULATION_MODE ==
- goog.events.CaptureSimulationMode.OFF_AND_FAIL) {
- goog.asserts.fail('Can not register capture listener in IE8-.');
- return null;
- } else if (goog.events.CAPTURE_SIMULATION_MODE ==
- goog.events.CaptureSimulationMode.OFF_AND_SILENT) {
- return null;
- }
- }
-
- var listenerMap = goog.events.getListenerMap_(src);
- if (!listenerMap) {
- src[goog.events.LISTENER_MAP_PROP_] = listenerMap =
- new goog.events.ListenerMap(src);
- }
-
- var listenerObj = listenerMap.add(
- type, listener, callOnce, opt_capt, opt_handler);
-
- // If the listenerObj already has a proxy, it has been set up
- // previously. We simply return.
- if (listenerObj.proxy) {
- return listenerObj;
- }
-
- var proxy = goog.events.getProxy();
- listenerObj.proxy = proxy;
-
- proxy.src = src;
- proxy.listener = listenerObj;
-
- // Attach the proxy through the browser's API
- if (src.addEventListener) {
- src.addEventListener(type.toString(), proxy, capture);
- } else if (src.attachEvent) {
- // The else if above used to be an unconditional else. It would call
- // exception on IE11, spoiling the day of some callers. The previous
- // incarnation of this code, from 2007, indicates that it replaced an
- // earlier still version that caused excess allocations on IE6.
- src.attachEvent(goog.events.getOnString_(type.toString()), proxy);
- } else {
- throw Error('addEventListener and attachEvent are unavailable.');
- }
-
- goog.events.listenerCountEstimate_++;
- return listenerObj;
+ol.extent.createOrUpdateFromFlatCoordinates = function(flatCoordinates, offset, end, stride, opt_extent) {
+ var extent = ol.extent.createOrUpdateEmpty(opt_extent);
+ return ol.extent.extendFlatCoordinates(
+ extent, flatCoordinates, offset, end, stride);
};
/**
- * Helper function for returning a proxy function.
- * @return {!Function} A new or reused function object.
+ * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} Extent.
*/
-goog.events.getProxy = function() {
- var proxyCallbackFunction = goog.events.handleBrowserEvent_;
- // Use a local var f to prevent one allocation.
- var f = goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT ?
- function(eventObject) {
- return proxyCallbackFunction.call(f.src, f.listener, eventObject);
- } :
- function(eventObject) {
- var v = proxyCallbackFunction.call(f.src, f.listener, eventObject);
- // NOTE(chrishenry): In IE, we hack in a capture phase. However, if
- // there is inline event handler which tries to prevent default (for
- // example <a href="..." onclick="return false">...</a>) in a
- // descendant element, the prevent default will be overridden
- // by this listener if this listener were to return true. Hence, we
- // return undefined.
- if (!v) return v;
- };
- return f;
+ol.extent.createOrUpdateFromRings = function(rings, opt_extent) {
+ var extent = ol.extent.createOrUpdateEmpty(opt_extent);
+ return ol.extent.extendRings(extent, rings);
};
/**
- * Adds an event listener for a specific event on a native event
- * target (such as a DOM element) or an object that has implemented
- * {@link goog.events.Listenable}. After the event has fired the event
- * listener is removed from the target.
- *
- * If an existing listener already exists, listenOnce will do
- * nothing. In particular, if the listener was previously registered
- * via listen(), listenOnce() will not turn the listener into a
- * one-off listener. Similarly, if there is already an existing
- * one-off listener, listenOnce does not modify the listeners (it is
- * still a once listener).
- *
- * @param {EventTarget|goog.events.Listenable} src The node to listen
- * to events on.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type or array of event types.
- * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
- * listener Callback method.
- * @param {boolean=} opt_capt Fire in capture phase?.
- * @param {T=} opt_handler Element in whose scope to call the listener.
- * @return {goog.events.Key} Unique key for the listener.
- * @template T,EVENTOBJ
+ * Empty an extent in place.
+ * @param {ol.Extent} extent Extent.
+ * @return {ol.Extent} Extent.
*/
-goog.events.listenOnce = function(src, type, listener, opt_capt, opt_handler) {
- if (goog.isArray(type)) {
- for (var i = 0; i < type.length; i++) {
- goog.events.listenOnce(src, type[i], listener, opt_capt, opt_handler);
- }
- return null;
- }
-
- listener = goog.events.wrapListener(listener);
- if (goog.events.Listenable.isImplementedBy(src)) {
- return src.listenOnce(
- /** @type {string|!goog.events.EventId} */ (type),
- listener, opt_capt, opt_handler);
- } else {
- return goog.events.listen_(
- /** @type {!EventTarget} */ (src),
- /** @type {string|!goog.events.EventId} */ (type),
- listener, /* callOnce */ true, opt_capt, opt_handler);
- }
+ol.extent.empty = function(extent) {
+ extent[0] = extent[1] = Infinity;
+ extent[2] = extent[3] = -Infinity;
+ return extent;
};
/**
- * Adds an event listener with a specific event wrapper on a DOM Node or an
- * object that has implemented {@link goog.events.Listenable}. A listener can
- * only be added once to an object.
- *
- * @param {EventTarget|goog.events.Listenable} src The target to
- * listen to events on.
- * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
- * @param {function(this:T, ?):?|{handleEvent:function(?):?}|null} listener
- * Callback method, or an object with a handleEvent function.
- * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
- * false).
- * @param {T=} opt_handler Element in whose scope to call the listener.
- * @template T
+ * Determine if two extents are equivalent.
+ * @param {ol.Extent} extent1 Extent 1.
+ * @param {ol.Extent} extent2 Extent 2.
+ * @return {boolean} The two extents are equivalent.
+ * @api stable
*/
-goog.events.listenWithWrapper = function(src, wrapper, listener, opt_capt,
- opt_handler) {
- wrapper.listen(src, listener, opt_capt, opt_handler);
+ol.extent.equals = function(extent1, extent2) {
+ return extent1[0] == extent2[0] && extent1[2] == extent2[2] &&
+ extent1[1] == extent2[1] && extent1[3] == extent2[3];
};
/**
- * Removes an event listener which was added with listen().
- *
- * @param {EventTarget|goog.events.Listenable} src The target to stop
- * listening to events on.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type or array of event types to unlisten to.
- * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
- * listener function to remove.
- * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
- * whether the listener is fired during the capture or bubble phase of the
- * event.
- * @param {Object=} opt_handler Element in whose scope to call the listener.
- * @return {?boolean} indicating whether the listener was there to remove.
- * @template EVENTOBJ
+ * Modify an extent to include another extent.
+ * @param {ol.Extent} extent1 The extent to be modified.
+ * @param {ol.Extent} extent2 The extent that will be included in the first.
+ * @return {ol.Extent} A reference to the first (extended) extent.
+ * @api stable
*/
-goog.events.unlisten = function(src, type, listener, opt_capt, opt_handler) {
- if (goog.isArray(type)) {
- for (var i = 0; i < type.length; i++) {
- goog.events.unlisten(src, type[i], listener, opt_capt, opt_handler);
- }
- return null;
+ol.extent.extend = function(extent1, extent2) {
+ if (extent2[0] < extent1[0]) {
+ extent1[0] = extent2[0];
}
-
- listener = goog.events.wrapListener(listener);
- if (goog.events.Listenable.isImplementedBy(src)) {
- return src.unlisten(
- /** @type {string|!goog.events.EventId} */ (type),
- listener, opt_capt, opt_handler);
+ if (extent2[2] > extent1[2]) {
+ extent1[2] = extent2[2];
}
-
- if (!src) {
- // TODO(chrishenry): We should tighten the API to only accept
- // non-null objects, or add an assertion here.
- return false;
+ if (extent2[1] < extent1[1]) {
+ extent1[1] = extent2[1];
}
-
- var capture = !!opt_capt;
- var listenerMap = goog.events.getListenerMap_(
- /** @type {!EventTarget} */ (src));
- if (listenerMap) {
- var listenerObj = listenerMap.getListener(
- /** @type {string|!goog.events.EventId} */ (type),
- listener, capture, opt_handler);
- if (listenerObj) {
- return goog.events.unlistenByKey(listenerObj);
- }
+ if (extent2[3] > extent1[3]) {
+ extent1[3] = extent2[3];
}
-
- return false;
+ return extent1;
};
/**
- * Removes an event listener which was added with listen() by the key
- * returned by listen().
- *
- * @param {goog.events.Key} key The key returned by listen() for this
- * event listener.
- * @return {boolean} indicating whether the listener was there to remove.
+ * @param {ol.Extent} extent Extent.
+ * @param {ol.Coordinate} coordinate Coordinate.
*/
-goog.events.unlistenByKey = function(key) {
- // TODO(chrishenry): Remove this check when tests that rely on this
- // are fixed.
- if (goog.isNumber(key)) {
- return false;
- }
-
- var listener = key;
- if (!listener || listener.removed) {
- return false;
+ol.extent.extendCoordinate = function(extent, coordinate) {
+ if (coordinate[0] < extent[0]) {
+ extent[0] = coordinate[0];
}
-
- var src = listener.src;
- if (goog.events.Listenable.isImplementedBy(src)) {
- return src.unlistenByKey(listener);
+ if (coordinate[0] > extent[2]) {
+ extent[2] = coordinate[0];
}
-
- var type = listener.type;
- var proxy = listener.proxy;
- if (src.removeEventListener) {
- src.removeEventListener(type, proxy, listener.capture);
- } else if (src.detachEvent) {
- src.detachEvent(goog.events.getOnString_(type), proxy);
+ if (coordinate[1] < extent[1]) {
+ extent[1] = coordinate[1];
}
- goog.events.listenerCountEstimate_--;
-
- var listenerMap = goog.events.getListenerMap_(
- /** @type {!EventTarget} */ (src));
- // TODO(chrishenry): Try to remove this conditional and execute the
- // first branch always. This should be safe.
- if (listenerMap) {
- listenerMap.removeByKey(listener);
- if (listenerMap.getTypeCount() == 0) {
- // Null the src, just because this is simple to do (and useful
- // for IE <= 7).
- listenerMap.src = null;
- // We don't use delete here because IE does not allow delete
- // on a window object.
- src[goog.events.LISTENER_MAP_PROP_] = null;
- }
- } else {
- listener.markAsRemoved();
+ if (coordinate[1] > extent[3]) {
+ extent[3] = coordinate[1];
}
-
- return true;
};
/**
- * Removes an event listener which was added with listenWithWrapper().
- *
- * @param {EventTarget|goog.events.Listenable} src The target to stop
- * listening to events on.
- * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
- * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
- * listener function to remove.
- * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
- * whether the listener is fired during the capture or bubble phase of the
- * event.
- * @param {Object=} opt_handler Element in whose scope to call the listener.
+ * @param {ol.Extent} extent Extent.
+ * @param {Array.<ol.Coordinate>} coordinates Coordinates.
+ * @return {ol.Extent} Extent.
*/
-goog.events.unlistenWithWrapper = function(src, wrapper, listener, opt_capt,
- opt_handler) {
- wrapper.unlisten(src, listener, opt_capt, opt_handler);
+ol.extent.extendCoordinates = function(extent, coordinates) {
+ var i, ii;
+ for (i = 0, ii = coordinates.length; i < ii; ++i) {
+ ol.extent.extendCoordinate(extent, coordinates[i]);
+ }
+ return extent;
};
/**
- * Removes all listeners from an object. You can also optionally
- * remove listeners of a particular type.
- *
- * @param {Object|undefined} obj Object to remove listeners from. Must be an
- * EventTarget or a goog.events.Listenable.
- * @param {string|!goog.events.EventId=} opt_type Type of event to remove.
- * Default is all types.
- * @return {number} Number of listeners removed.
+ * @param {ol.Extent} extent Extent.
+ * @param {Array.<number>} flatCoordinates Flat coordinates.
+ * @param {number} offset Offset.
+ * @param {number} end End.
+ * @param {number} stride Stride.
+ * @return {ol.Extent} Extent.
*/
-goog.events.removeAll = function(obj, opt_type) {
- // TODO(chrishenry): Change the type of obj to
- // (!EventTarget|!goog.events.Listenable).
-
- if (!obj) {
- return 0;
- }
-
- if (goog.events.Listenable.isImplementedBy(obj)) {
- return obj.removeAllListeners(opt_type);
+ol.extent.extendFlatCoordinates = function(extent, flatCoordinates, offset, end, stride) {
+ for (; offset < end; offset += stride) {
+ ol.extent.extendXY(
+ extent, flatCoordinates[offset], flatCoordinates[offset + 1]);
}
+ return extent;
+};
- var listenerMap = goog.events.getListenerMap_(
- /** @type {!EventTarget} */ (obj));
- if (!listenerMap) {
- return 0;
- }
- var count = 0;
- var typeStr = opt_type && opt_type.toString();
- for (var type in listenerMap.listeners) {
- if (!typeStr || type == typeStr) {
- // Clone so that we don't need to worry about unlistenByKey
- // changing the content of the ListenerMap.
- var listeners = listenerMap.listeners[type].concat();
- for (var i = 0; i < listeners.length; ++i) {
- if (goog.events.unlistenByKey(listeners[i])) {
- ++count;
- }
- }
- }
+/**
+ * @param {ol.Extent} extent Extent.
+ * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
+ * @return {ol.Extent} Extent.
+ */
+ol.extent.extendRings = function(extent, rings) {
+ var i, ii;
+ for (i = 0, ii = rings.length; i < ii; ++i) {
+ ol.extent.extendCoordinates(extent, rings[i]);
}
- return count;
+ return extent;
};
/**
- * Gets the listeners for a given object, type and capture phase.
- *
- * @param {Object} obj Object to get listeners for.
- * @param {string|!goog.events.EventId} type Event type.
- * @param {boolean} capture Capture phase?.
- * @return {Array<goog.events.Listener>} Array of listener objects.
+ * @param {ol.Extent} extent Extent.
+ * @param {number} x X.
+ * @param {number} y Y.
*/
-goog.events.getListeners = function(obj, type, capture) {
- if (goog.events.Listenable.isImplementedBy(obj)) {
- return obj.getListeners(type, capture);
- } else {
- if (!obj) {
- // TODO(chrishenry): We should tighten the API to accept
- // !EventTarget|goog.events.Listenable, and add an assertion here.
- return [];
- }
-
- var listenerMap = goog.events.getListenerMap_(
- /** @type {!EventTarget} */ (obj));
- return listenerMap ? listenerMap.getListeners(type, capture) : [];
- }
+ol.extent.extendXY = function(extent, x, y) {
+ extent[0] = Math.min(extent[0], x);
+ extent[1] = Math.min(extent[1], y);
+ extent[2] = Math.max(extent[2], x);
+ extent[3] = Math.max(extent[3], y);
};
/**
- * Gets the goog.events.Listener for the event or null if no such listener is
- * in use.
- *
- * @param {EventTarget|goog.events.Listenable} src The target from
- * which to get listeners.
- * @param {?string|!goog.events.EventId<EVENTOBJ>} type The type of the event.
- * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null} listener The
- * listener function to get.
- * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
- * whether the listener is fired during the
- * capture or bubble phase of the event.
- * @param {Object=} opt_handler Element in whose scope to call the listener.
- * @return {goog.events.ListenableKey} the found listener or null if not found.
- * @template EVENTOBJ
+ * This function calls `callback` for each corner of the extent. If the
+ * callback returns a truthy value the function returns that value
+ * immediately. Otherwise the function returns `false`.
+ * @param {ol.Extent} extent Extent.
+ * @param {function(this:T, ol.Coordinate): S} callback Callback.
+ * @param {T=} opt_this Value to use as `this` when executing `callback`.
+ * @return {S|boolean} Value.
+ * @template S, T
*/
-goog.events.getListener = function(src, type, listener, opt_capt, opt_handler) {
- // TODO(chrishenry): Change type from ?string to string, or add assertion.
- type = /** @type {string} */ (type);
- listener = goog.events.wrapListener(listener);
- var capture = !!opt_capt;
- if (goog.events.Listenable.isImplementedBy(src)) {
- return src.getListener(type, listener, capture, opt_handler);
+ol.extent.forEachCorner = function(extent, callback, opt_this) {
+ var val;
+ val = callback.call(opt_this, ol.extent.getBottomLeft(extent));
+ if (val) {
+ return val;
}
-
- if (!src) {
- // TODO(chrishenry): We should tighten the API to only accept
- // non-null objects, or add an assertion here.
- return null;
+ val = callback.call(opt_this, ol.extent.getBottomRight(extent));
+ if (val) {
+ return val;
}
-
- var listenerMap = goog.events.getListenerMap_(
- /** @type {!EventTarget} */ (src));
- if (listenerMap) {
- return listenerMap.getListener(type, listener, capture, opt_handler);
+ val = callback.call(opt_this, ol.extent.getTopRight(extent));
+ if (val) {
+ return val;
}
- return null;
+ val = callback.call(opt_this, ol.extent.getTopLeft(extent));
+ if (val) {
+ return val;
+ }
+ return false;
};
/**
- * Returns whether an event target has any active listeners matching the
- * specified signature. If either the type or capture parameters are
- * unspecified, the function will match on the remaining criteria.
- *
- * @param {EventTarget|goog.events.Listenable} obj Target to get
- * listeners for.
- * @param {string|!goog.events.EventId=} opt_type Event type.
- * @param {boolean=} opt_capture Whether to check for capture or bubble-phase
- * listeners.
- * @return {boolean} Whether an event target has one or more listeners matching
- * the requested type and/or capture phase.
+ * @param {ol.Extent} extent Extent.
+ * @return {number} Area.
*/
-goog.events.hasListener = function(obj, opt_type, opt_capture) {
- if (goog.events.Listenable.isImplementedBy(obj)) {
- return obj.hasListener(opt_type, opt_capture);
+ol.extent.getArea = function(extent) {
+ var area = 0;
+ if (!ol.extent.isEmpty(extent)) {
+ area = ol.extent.getWidth(extent) * ol.extent.getHeight(extent);
}
-
- var listenerMap = goog.events.getListenerMap_(
- /** @type {!EventTarget} */ (obj));
- return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture);
+ return area;
};
/**
- * Provides a nice string showing the normalized event objects public members
- * @param {Object} e Event Object.
- * @return {string} String of the public members of the normalized event object.
+ * Get the bottom left coordinate of an extent.
+ * @param {ol.Extent} extent Extent.
+ * @return {ol.Coordinate} Bottom left coordinate.
+ * @api stable
*/
-goog.events.expose = function(e) {
- var str = [];
- for (var key in e) {
- if (e[key] && e[key].id) {
- str.push(key + ' = ' + e[key] + ' (' + e[key].id + ')');
- } else {
- str.push(key + ' = ' + e[key]);
- }
- }
- return str.join('\n');
+ol.extent.getBottomLeft = function(extent) {
+ return [extent[0], extent[1]];
};
/**
- * Returns a string with on prepended to the specified type. This is used for IE
- * which expects "on" to be prepended. This function caches the string in order
- * to avoid extra allocations in steady state.
- * @param {string} type Event type.
- * @return {string} The type string with 'on' prepended.
- * @private
+ * Get the bottom right coordinate of an extent.
+ * @param {ol.Extent} extent Extent.
+ * @return {ol.Coordinate} Bottom right coordinate.
+ * @api stable
*/
-goog.events.getOnString_ = function(type) {
- if (type in goog.events.onStringMap_) {
- return goog.events.onStringMap_[type];
- }
- return goog.events.onStringMap_[type] = goog.events.onString_ + type;
+ol.extent.getBottomRight = function(extent) {
+ return [extent[2], extent[1]];
};
/**
- * Fires an object's listeners of a particular type and phase
- *
- * @param {Object} obj Object whose listeners to call.
- * @param {string|!goog.events.EventId} type Event type.
- * @param {boolean} capture Which event phase.
- * @param {Object} eventObject Event object to be passed to listener.
- * @return {boolean} True if all listeners returned true else false.
+ * Get the center coordinate of an extent.
+ * @param {ol.Extent} extent Extent.
+ * @return {ol.Coordinate} Center.
+ * @api stable
*/
-goog.events.fireListeners = function(obj, type, capture, eventObject) {
- if (goog.events.Listenable.isImplementedBy(obj)) {
- return obj.fireListeners(type, capture, eventObject);
- }
-
- return goog.events.fireListeners_(obj, type, capture, eventObject);
+ol.extent.getCenter = function(extent) {
+ return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2];
};
/**
- * Fires an object's listeners of a particular type and phase.
- * @param {Object} obj Object whose listeners to call.
- * @param {string|!goog.events.EventId} type Event type.
- * @param {boolean} capture Which event phase.
- * @param {Object} eventObject Event object to be passed to listener.
- * @return {boolean} True if all listeners returned true else false.
- * @private
+ * Get a corner coordinate of an extent.
+ * @param {ol.Extent} extent Extent.
+ * @param {ol.extent.Corner} corner Corner.
+ * @return {ol.Coordinate} Corner coordinate.
*/
-goog.events.fireListeners_ = function(obj, type, capture, eventObject) {
- /** @type {boolean} */
- var retval = true;
-
- var listenerMap = goog.events.getListenerMap_(
- /** @type {EventTarget} */ (obj));
- if (listenerMap) {
- // TODO(chrishenry): Original code avoids array creation when there
- // is no listener, so we do the same. If this optimization turns
- // out to be not required, we can replace this with
- // listenerMap.getListeners(type, capture) instead, which is simpler.
- var listenerArray = listenerMap.listeners[type.toString()];
- if (listenerArray) {
- listenerArray = listenerArray.concat();
- for (var i = 0; i < listenerArray.length; i++) {
- var listener = listenerArray[i];
- // We might not have a listener if the listener was removed.
- if (listener && listener.capture == capture && !listener.removed) {
- var result = goog.events.fireListener(listener, eventObject);
- retval = retval && (result !== false);
- }
- }
- }
+ol.extent.getCorner = function(extent, corner) {
+ var coordinate;
+ if (corner === ol.extent.Corner.BOTTOM_LEFT) {
+ coordinate = ol.extent.getBottomLeft(extent);
+ } else if (corner === ol.extent.Corner.BOTTOM_RIGHT) {
+ coordinate = ol.extent.getBottomRight(extent);
+ } else if (corner === ol.extent.Corner.TOP_LEFT) {
+ coordinate = ol.extent.getTopLeft(extent);
+ } else if (corner === ol.extent.Corner.TOP_RIGHT) {
+ coordinate = ol.extent.getTopRight(extent);
+ } else {
+ goog.asserts.fail('Invalid corner: %s', corner);
}
- return retval;
+ goog.asserts.assert(coordinate, 'coordinate should be defined');
+ return coordinate;
};
/**
- * Fires a listener with a set of arguments
- *
- * @param {goog.events.Listener} listener The listener object to call.
- * @param {Object} eventObject The event object to pass to the listener.
- * @return {boolean} Result of listener.
+ * @param {ol.Extent} extent1 Extent 1.
+ * @param {ol.Extent} extent2 Extent 2.
+ * @return {number} Enlarged area.
*/
-goog.events.fireListener = function(listener, eventObject) {
- var listenerFn = listener.listener;
- var listenerHandler = listener.handler || listener.src;
-
- if (listener.callOnce) {
- goog.events.unlistenByKey(listener);
- }
- return listenerFn.call(listenerHandler, eventObject);
+ol.extent.getEnlargedArea = function(extent1, extent2) {
+ var minX = Math.min(extent1[0], extent2[0]);
+ var minY = Math.min(extent1[1], extent2[1]);
+ var maxX = Math.max(extent1[2], extent2[2]);
+ var maxY = Math.max(extent1[3], extent2[3]);
+ return (maxX - minX) * (maxY - minY);
};
/**
- * Gets the total number of listeners currently in the system.
- * @return {number} Number of listeners.
- * @deprecated This returns estimated count, now that Closure no longer
- * stores a central listener registry. We still return an estimation
- * to keep existing listener-related tests passing. In the near future,
- * this function will be removed.
+ * @param {ol.Coordinate} center Center.
+ * @param {number} resolution Resolution.
+ * @param {number} rotation Rotation.
+ * @param {ol.Size} size Size.
+ * @param {ol.Extent=} opt_extent Destination extent.
+ * @return {ol.Extent} Extent.
*/
-goog.events.getTotalListenerCount = function() {
- return goog.events.listenerCountEstimate_;
+ol.extent.getForViewAndSize = function(center, resolution, rotation, size, opt_extent) {
+ var dx = resolution * size[0] / 2;
+ var dy = resolution * size[1] / 2;
+ var cosRotation = Math.cos(rotation);
+ var sinRotation = Math.sin(rotation);
+ var xCos = dx * cosRotation;
+ var xSin = dx * sinRotation;
+ var yCos = dy * cosRotation;
+ var ySin = dy * sinRotation;
+ var x = center[0];
+ var y = center[1];
+ var x0 = x - xCos + ySin;
+ var x1 = x - xCos - ySin;
+ var x2 = x + xCos - ySin;
+ var x3 = x + xCos + ySin;
+ var y0 = y - xSin - yCos;
+ var y1 = y - xSin + yCos;
+ var y2 = y + xSin + yCos;
+ var y3 = y + xSin - yCos;
+ return ol.extent.createOrUpdate(
+ Math.min(x0, x1, x2, x3), Math.min(y0, y1, y2, y3),
+ Math.max(x0, x1, x2, x3), Math.max(y0, y1, y2, y3),
+ opt_extent);
};
/**
- * Dispatches an event (or event like object) and calls all listeners
- * listening for events of this type. The type of the event is decided by the
- * type property on the event object.
- *
- * If any of the listeners returns false OR calls preventDefault then this
- * function will return false. If one of the capture listeners calls
- * stopPropagation, then the bubble listeners won't fire.
- *
- * @param {goog.events.Listenable} src The event target.
- * @param {goog.events.EventLike} e Event object.
- * @return {boolean} If anyone called preventDefault on the event object (or
- * if any of the handlers returns false) this will also return false.
- * If there are no handlers, or if all handlers return true, this returns
- * true.
+ * Get the height of an extent.
+ * @param {ol.Extent} extent Extent.
+ * @return {number} Height.
+ * @api stable
*/
-goog.events.dispatchEvent = function(src, e) {
- goog.asserts.assert(
- goog.events.Listenable.isImplementedBy(src),
- 'Can not use goog.events.dispatchEvent with ' +
- 'non-goog.events.Listenable instance.');
- return src.dispatchEvent(e);
+ol.extent.getHeight = function(extent) {
+ return extent[3] - extent[1];
};
/**
- * Installs exception protection for the browser event entry point using the
- * given error handler.
- *
- * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
- * protect the entry point.
+ * @param {ol.Extent} extent1 Extent 1.
+ * @param {ol.Extent} extent2 Extent 2.
+ * @return {number} Intersection area.
*/
-goog.events.protectBrowserEventEntryPoint = function(errorHandler) {
- goog.events.handleBrowserEvent_ = errorHandler.protectEntryPoint(
- goog.events.handleBrowserEvent_);
+ol.extent.getIntersectionArea = function(extent1, extent2) {
+ var intersection = ol.extent.getIntersection(extent1, extent2);
+ return ol.extent.getArea(intersection);
};
/**
- * Handles an event and dispatches it to the correct listeners. This
- * function is a proxy for the real listener the user specified.
- *
- * @param {goog.events.Listener} listener The listener object.
- * @param {Event=} opt_evt Optional event object that gets passed in via the
- * native event handlers.
- * @return {boolean} Result of the event handler.
- * @this {EventTarget} The object or Element that fired the event.
- * @private
+ * Get the intersection of two extents.
+ * @param {ol.Extent} extent1 Extent 1.
+ * @param {ol.Extent} extent2 Extent 2.
+ * @param {ol.Extent=} opt_extent Optional extent to populate with intersection.
+ * @return {ol.Extent} Intersecting extent.
+ * @api stable
*/
-goog.events.handleBrowserEvent_ = function(listener, opt_evt) {
- if (listener.removed) {
- return true;
- }
-
- // Synthesize event propagation if the browser does not support W3C
- // event model.
- if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
- var ieEvent = opt_evt ||
- /** @type {Event} */ (goog.getObjectByName('window.event'));
- var evt = new goog.events.BrowserEvent(ieEvent, this);
- /** @type {boolean} */
- var retval = true;
-
- if (goog.events.CAPTURE_SIMULATION_MODE ==
- goog.events.CaptureSimulationMode.ON) {
- // If we have not marked this event yet, we should perform capture
- // simulation.
- if (!goog.events.isMarkedIeEvent_(ieEvent)) {
- goog.events.markIeEvent_(ieEvent);
-
- var ancestors = [];
- for (var parent = evt.currentTarget; parent;
- parent = parent.parentNode) {
- ancestors.push(parent);
- }
-
- // Fire capture listeners.
- var type = listener.type;
- for (var i = ancestors.length - 1; !evt.propagationStopped_ && i >= 0;
- i--) {
- evt.currentTarget = ancestors[i];
- var result = goog.events.fireListeners_(ancestors[i], type, true, evt);
- retval = retval && result;
- }
-
- // Fire bubble listeners.
- //
- // We can technically rely on IE to perform bubble event
- // propagation. However, it turns out that IE fires events in
- // opposite order of attachEvent registration, which broke
- // some code and tests that rely on the order. (While W3C DOM
- // Level 2 Events TR leaves the event ordering unspecified,
- // modern browsers and W3C DOM Level 3 Events Working Draft
- // actually specify the order as the registration order.)
- for (var i = 0; !evt.propagationStopped_ && i < ancestors.length; i++) {
- evt.currentTarget = ancestors[i];
- var result = goog.events.fireListeners_(ancestors[i], type, false, evt);
- retval = retval && result;
- }
- }
+ol.extent.getIntersection = function(extent1, extent2, opt_extent) {
+ var intersection = opt_extent ? opt_extent : ol.extent.createEmpty();
+ if (ol.extent.intersects(extent1, extent2)) {
+ if (extent1[0] > extent2[0]) {
+ intersection[0] = extent1[0];
} else {
- retval = goog.events.fireListener(listener, evt);
+ intersection[0] = extent2[0];
}
- return retval;
- }
-
- // Otherwise, simply fire the listener.
- return goog.events.fireListener(
- listener, new goog.events.BrowserEvent(opt_evt, this));
-};
-
-
-/**
- * This is used to mark the IE event object so we do not do the Closure pass
- * twice for a bubbling event.
- * @param {Event} e The IE browser event.
- * @private
- */
-goog.events.markIeEvent_ = function(e) {
- // Only the keyCode and the returnValue can be changed. We use keyCode for
- // non keyboard events.
- // event.returnValue is a bit more tricky. It is undefined by default. A
- // boolean false prevents the default action. In a window.onbeforeunload and
- // the returnValue is non undefined it will be alerted. However, we will only
- // modify the returnValue for keyboard events. We can get a problem if non
- // closure events sets the keyCode or the returnValue
-
- var useReturnValue = false;
-
- if (e.keyCode == 0) {
- // We cannot change the keyCode in case that srcElement is input[type=file].
- // We could test that that is the case but that would allocate 3 objects.
- // If we use try/catch we will only allocate extra objects in the case of a
- // failure.
- /** @preserveTry */
- try {
- e.keyCode = -1;
- return;
- } catch (ex) {
- useReturnValue = true;
+ if (extent1[1] > extent2[1]) {
+ intersection[1] = extent1[1];
+ } else {
+ intersection[1] = extent2[1];
+ }
+ if (extent1[2] < extent2[2]) {
+ intersection[2] = extent1[2];
+ } else {
+ intersection[2] = extent2[2];
+ }
+ if (extent1[3] < extent2[3]) {
+ intersection[3] = extent1[3];
+ } else {
+ intersection[3] = extent2[3];
}
}
-
- if (useReturnValue ||
- /** @type {boolean|undefined} */ (e.returnValue) == undefined) {
- e.returnValue = true;
- }
+ return intersection;
};
/**
- * This is used to check if an IE event has already been handled by the Closure
- * system so we do not do the Closure pass twice for a bubbling event.
- * @param {Event} e The IE browser event.
- * @return {boolean} True if the event object has been marked.
- * @private
+ * @param {ol.Extent} extent Extent.
+ * @return {number} Margin.
*/
-goog.events.isMarkedIeEvent_ = function(e) {
- return e.keyCode < 0 || e.returnValue != undefined;
+ol.extent.getMargin = function(extent) {
+ return ol.extent.getWidth(extent) + ol.extent.getHeight(extent);
};
/**
- * Counter to create unique event ids.
- * @private {number}
- */
-goog.events.uniqueIdCounter_ = 0;
-
-
-/**
- * Creates a unique event id.
- *
- * @param {string} identifier The identifier.
- * @return {string} A unique identifier.
- * @idGenerator
+ * Get the size (width, height) of an extent.
+ * @param {ol.Extent} extent The extent.
+ * @return {ol.Size} The extent size.
+ * @api stable
*/
-goog.events.getUniqueId = function(identifier) {
- return identifier + '_' + goog.events.uniqueIdCounter_++;
+ol.extent.getSize = function(extent) {
+ return [extent[2] - extent[0], extent[3] - extent[1]];
};
/**
- * @param {EventTarget} src The source object.
- * @return {goog.events.ListenerMap} A listener map for the given
- * source object, or null if none exists.
- * @private
+ * Get the top left coordinate of an extent.
+ * @param {ol.Extent} extent Extent.
+ * @return {ol.Coordinate} Top left coordinate.
+ * @api stable
*/
-goog.events.getListenerMap_ = function(src) {
- var listenerMap = src[goog.events.LISTENER_MAP_PROP_];
- // IE serializes the property as well (e.g. when serializing outer
- // HTML). So we must check that the value is of the correct type.
- return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null;
+ol.extent.getTopLeft = function(extent) {
+ return [extent[0], extent[3]];
};
/**
- * Expando property for listener function wrapper for Object with
- * handleEvent.
- * @private @const {string}
+ * Get the top right coordinate of an extent.
+ * @param {ol.Extent} extent Extent.
+ * @return {ol.Coordinate} Top right coordinate.
+ * @api stable
*/
-goog.events.LISTENER_WRAPPER_PROP_ = '__closure_events_fn_' +
- ((Math.random() * 1e9) >>> 0);
+ol.extent.getTopRight = function(extent) {
+ return [extent[2], extent[3]];
+};
/**
- * @param {Object|Function} listener The listener function or an
- * object that contains handleEvent method.
- * @return {!Function} Either the original function or a function that
- * calls obj.handleEvent. If the same listener is passed to this
- * function more than once, the same function is guaranteed to be
- * returned.
+ * Get the width of an extent.
+ * @param {ol.Extent} extent Extent.
+ * @return {number} Width.
+ * @api stable
*/
-goog.events.wrapListener = function(listener) {
- goog.asserts.assert(listener, 'Listener can not be null.');
-
- if (goog.isFunction(listener)) {
- return listener;
- }
-
- goog.asserts.assert(
- listener.handleEvent, 'An object listener must have handleEvent method.');
- if (!listener[goog.events.LISTENER_WRAPPER_PROP_]) {
- listener[goog.events.LISTENER_WRAPPER_PROP_] =
- function(e) { return listener.handleEvent(e); };
- }
- return listener[goog.events.LISTENER_WRAPPER_PROP_];
+ol.extent.getWidth = function(extent) {
+ return extent[2] - extent[0];
};
-// Register the browser event handler as an entry point, so that
-// it can be monitored for exception handling, etc.
-goog.debug.entryPointRegistry.register(
- /**
- * @param {function(!Function): !Function} transformer The transforming
- * function.
- */
- function(transformer) {
- goog.events.handleBrowserEvent_ = transformer(
- goog.events.handleBrowserEvent_);
- });
-
-// Copyright 2005 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
/**
- * @fileoverview A disposable implementation of a custom
- * listenable/event target. See also: documentation for
- * {@code goog.events.Listenable}.
- *
- * @author arv@google.com (Erik Arvidsson) [Original implementation]
- * @see ../demos/eventtarget.html
- * @see goog.events.Listenable
+ * Determine if one extent intersects another.
+ * @param {ol.Extent} extent1 Extent 1.
+ * @param {ol.Extent} extent2 Extent.
+ * @return {boolean} The two extents intersect.
+ * @api stable
*/
-
-goog.provide('goog.events.EventTarget');
-
-goog.require('goog.Disposable');
-goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.events.Listenable');
-goog.require('goog.events.ListenerMap');
-goog.require('goog.object');
-
+ol.extent.intersects = function(extent1, extent2) {
+ return extent1[0] <= extent2[2] &&
+ extent1[2] >= extent2[0] &&
+ extent1[1] <= extent2[3] &&
+ extent1[3] >= extent2[1];
+};
/**
- * An implementation of {@code goog.events.Listenable} with full W3C
- * EventTarget-like support (capture/bubble mechanism, stopping event
- * propagation, preventing default actions).
- *
- * You may subclass this class to turn your class into a Listenable.
- *
- * Unless propagation is stopped, an event dispatched by an
- * EventTarget will bubble to the parent returned by
- * {@code getParentEventTarget}. To set the parent, call
- * {@code setParentEventTarget}. Subclasses that don't support
- * changing the parent can override the setter to throw an error.
- *
- * Example usage:
- * <pre>
- * var source = new goog.events.EventTarget();
- * function handleEvent(e) {
- * alert('Type: ' + e.type + '; Target: ' + e.target);
- * }
- * source.listen('foo', handleEvent);
- * // Or: goog.events.listen(source, 'foo', handleEvent);
- * ...
- * source.dispatchEvent('foo'); // will call handleEvent
- * ...
- * source.unlisten('foo', handleEvent);
- * // Or: goog.events.unlisten(source, 'foo', handleEvent);
- * </pre>
- *
- * @constructor
- * @extends {goog.Disposable}
- * @implements {goog.events.Listenable}
+ * Determine if an extent is empty.
+ * @param {ol.Extent} extent Extent.
+ * @return {boolean} Is empty.
+ * @api stable
*/
-goog.events.EventTarget = function() {
- goog.Disposable.call(this);
-
- /**
- * Maps of event type to an array of listeners.
- * @private {!goog.events.ListenerMap}
- */
- this.eventTargetListeners_ = new goog.events.ListenerMap(this);
-
- /**
- * The object to use for event.target. Useful when mixing in an
- * EventTarget to another object.
- * @private {!Object}
- */
- this.actualEventTarget_ = this;
-
- /**
- * Parent event target, used during event bubbling.
- *
- * TODO(chrishenry): Change this to goog.events.Listenable. This
- * currently breaks people who expect getParentEventTarget to return
- * goog.events.EventTarget.
- *
- * @private {goog.events.EventTarget}
- */
- this.parentEventTarget_ = null;
+ol.extent.isEmpty = function(extent) {
+ return extent[2] < extent[0] || extent[3] < extent[1];
};
-goog.inherits(goog.events.EventTarget, goog.Disposable);
-goog.events.Listenable.addImplementation(goog.events.EventTarget);
/**
- * An artificial cap on the number of ancestors you can have. This is mainly
- * for loop detection.
- * @const {number}
- * @private
+ * @param {ol.Extent} extent Extent.
+ * @return {boolean} Is infinite.
*/
-goog.events.EventTarget.MAX_ANCESTORS_ = 1000;
+ol.extent.isInfinite = function(extent) {
+ return extent[0] == -Infinity || extent[1] == -Infinity ||
+ extent[2] == Infinity || extent[3] == Infinity;
+};
/**
- * Returns the parent of this event target to use for bubbling.
- *
- * @return {goog.events.EventTarget} The parent EventTarget or null if
- * there is no parent.
- * @override
+ * @param {ol.Extent} extent Extent.
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @return {ol.Coordinate} Coordinate.
*/
-goog.events.EventTarget.prototype.getParentEventTarget = function() {
- return this.parentEventTarget_;
+ol.extent.normalize = function(extent, coordinate) {
+ return [
+ (coordinate[0] - extent[0]) / (extent[2] - extent[0]),
+ (coordinate[1] - extent[1]) / (extent[3] - extent[1])
+ ];
};
/**
- * Sets the parent of this event target to use for capture/bubble
- * mechanism.
- * @param {goog.events.EventTarget} parent Parent listenable (null if none).
+ * @param {ol.Extent} extent Extent.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} Extent.
*/
-goog.events.EventTarget.prototype.setParentEventTarget = function(parent) {
- this.parentEventTarget_ = parent;
+ol.extent.returnOrUpdate = function(extent, opt_extent) {
+ if (opt_extent) {
+ opt_extent[0] = extent[0];
+ opt_extent[1] = extent[1];
+ opt_extent[2] = extent[2];
+ opt_extent[3] = extent[3];
+ return opt_extent;
+ } else {
+ return extent;
+ }
};
/**
- * Adds an event listener to the event target. The same handler can only be
- * added once per the type. Even if you add the same handler multiple times
- * using the same type then it will only be called once when the event is
- * dispatched.
- *
- * @param {string} type The type of the event to listen for.
- * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
- * to handle the event. The handler can also be an object that implements
- * the handleEvent method which takes the event object as argument.
- * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
- * whether the listener is fired during the capture or bubble phase
- * of the event.
- * @param {Object=} opt_handlerScope Object in whose scope to call
- * the listener.
- * @deprecated Use {@code #listen} instead, when possible. Otherwise, use
- * {@code goog.events.listen} if you are passing Object
- * (instead of Function) as handler.
+ * @param {ol.Extent} extent Extent.
+ * @param {number} value Value.
*/
-goog.events.EventTarget.prototype.addEventListener = function(
- type, handler, opt_capture, opt_handlerScope) {
- goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);
+ol.extent.scaleFromCenter = function(extent, value) {
+ var deltaX = ((extent[2] - extent[0]) / 2) * (value - 1);
+ var deltaY = ((extent[3] - extent[1]) / 2) * (value - 1);
+ extent[0] -= deltaX;
+ extent[2] += deltaX;
+ extent[1] -= deltaY;
+ extent[3] += deltaY;
};
/**
- * Removes an event listener from the event target. The handler must be the
- * same object as the one added. If the handler has not been added then
- * nothing is done.
- *
- * @param {string} type The type of the event to listen for.
- * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
- * to handle the event. The handler can also be an object that implements
- * the handleEvent method which takes the event object as argument.
- * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
- * whether the listener is fired during the capture or bubble phase
- * of the event.
- * @param {Object=} opt_handlerScope Object in whose scope to call
- * the listener.
- * @deprecated Use {@code #unlisten} instead, when possible. Otherwise, use
- * {@code goog.events.unlisten} if you are passing Object
- * (instead of Function) as handler.
+ * Determine if the segment between two coordinates intersects (crosses,
+ * touches, or is contained by) the provided extent.
+ * @param {ol.Extent} extent The extent.
+ * @param {ol.Coordinate} start Segment start coordinate.
+ * @param {ol.Coordinate} end Segment end coordinate.
+ * @return {boolean} The segment intersects the extent.
*/
-goog.events.EventTarget.prototype.removeEventListener = function(
- type, handler, opt_capture, opt_handlerScope) {
- goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.dispatchEvent = function(e) {
- this.assertInitialized_();
-
- var ancestorsTree, ancestor = this.getParentEventTarget();
- if (ancestor) {
- ancestorsTree = [];
- var ancestorCount = 1;
- for (; ancestor; ancestor = ancestor.getParentEventTarget()) {
- ancestorsTree.push(ancestor);
- goog.asserts.assert(
- (++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_),
- 'infinite loop');
+ol.extent.intersectsSegment = function(extent, start, end) {
+ var intersects = false;
+ var startRel = ol.extent.coordinateRelationship(extent, start);
+ var endRel = ol.extent.coordinateRelationship(extent, end);
+ if (startRel === ol.extent.Relationship.INTERSECTING ||
+ endRel === ol.extent.Relationship.INTERSECTING) {
+ intersects = true;
+ } else {
+ var minX = extent[0];
+ var minY = extent[1];
+ var maxX = extent[2];
+ var maxY = extent[3];
+ var startX = start[0];
+ var startY = start[1];
+ var endX = end[0];
+ var endY = end[1];
+ var slope = (endY - startY) / (endX - startX);
+ var x, y;
+ if (!!(endRel & ol.extent.Relationship.ABOVE) &&
+ !(startRel & ol.extent.Relationship.ABOVE)) {
+ // potentially intersects top
+ x = endX - ((endY - maxY) / slope);
+ intersects = x >= minX && x <= maxX;
+ }
+ if (!intersects && !!(endRel & ol.extent.Relationship.RIGHT) &&
+ !(startRel & ol.extent.Relationship.RIGHT)) {
+ // potentially intersects right
+ y = endY - ((endX - maxX) * slope);
+ intersects = y >= minY && y <= maxY;
+ }
+ if (!intersects && !!(endRel & ol.extent.Relationship.BELOW) &&
+ !(startRel & ol.extent.Relationship.BELOW)) {
+ // potentially intersects bottom
+ x = endX - ((endY - minY) / slope);
+ intersects = x >= minX && x <= maxX;
+ }
+ if (!intersects && !!(endRel & ol.extent.Relationship.LEFT) &&
+ !(startRel & ol.extent.Relationship.LEFT)) {
+ // potentially intersects left
+ y = endY - ((endX - minX) * slope);
+ intersects = y >= minY && y <= maxY;
}
- }
- return goog.events.EventTarget.dispatchEventInternal_(
- this.actualEventTarget_, e, ancestorsTree);
+ }
+ return intersects;
};
/**
- * Removes listeners from this object. Classes that extend EventTarget may
- * need to override this method in order to remove references to DOM Elements
- * and additional listeners.
- * @override
+ * @param {ol.Extent} extent1 Extent 1.
+ * @param {ol.Extent} extent2 Extent 2.
+ * @return {boolean} Touches.
*/
-goog.events.EventTarget.prototype.disposeInternal = function() {
- goog.events.EventTarget.superClass_.disposeInternal.call(this);
-
- this.removeAllListeners();
- this.parentEventTarget_ = null;
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.listen = function(
- type, listener, opt_useCapture, opt_listenerScope) {
- this.assertInitialized_();
- return this.eventTargetListeners_.add(
- String(type), listener, false /* callOnce */, opt_useCapture,
- opt_listenerScope);
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.listenOnce = function(
- type, listener, opt_useCapture, opt_listenerScope) {
- return this.eventTargetListeners_.add(
- String(type), listener, true /* callOnce */, opt_useCapture,
- opt_listenerScope);
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.unlisten = function(
- type, listener, opt_useCapture, opt_listenerScope) {
- return this.eventTargetListeners_.remove(
- String(type), listener, opt_useCapture, opt_listenerScope);
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.unlistenByKey = function(key) {
- return this.eventTargetListeners_.removeByKey(key);
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {
- // TODO(chrishenry): Previously, removeAllListeners can be called on
- // uninitialized EventTarget, so we preserve that behavior. We
- // should remove this when usages that rely on that fact are purged.
- if (!this.eventTargetListeners_) {
- return 0;
- }
- return this.eventTargetListeners_.removeAll(opt_type);
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.fireListeners = function(
- type, capture, eventObject) {
- // TODO(chrishenry): Original code avoids array creation when there
- // is no listener, so we do the same. If this optimization turns
- // out to be not required, we can replace this with
- // getListeners(type, capture) instead, which is simpler.
- var listenerArray = this.eventTargetListeners_.listeners[String(type)];
- if (!listenerArray) {
- return true;
- }
- listenerArray = listenerArray.concat();
-
- var rv = true;
- for (var i = 0; i < listenerArray.length; ++i) {
- var listener = listenerArray[i];
- // We might not have a listener if the listener was removed.
- if (listener && !listener.removed && listener.capture == capture) {
- var listenerFn = listener.listener;
- var listenerHandler = listener.handler || listener.src;
-
- if (listener.callOnce) {
- this.unlistenByKey(listener);
- }
- rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;
- }
- }
-
- return rv && eventObject.returnValue_ != false;
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.getListeners = function(type, capture) {
- return this.eventTargetListeners_.getListeners(String(type), capture);
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.getListener = function(
- type, listener, capture, opt_listenerScope) {
- return this.eventTargetListeners_.getListener(
- String(type), listener, capture, opt_listenerScope);
-};
-
-
-/** @override */
-goog.events.EventTarget.prototype.hasListener = function(
- opt_type, opt_capture) {
- var id = goog.isDef(opt_type) ? String(opt_type) : undefined;
- return this.eventTargetListeners_.hasListener(id, opt_capture);
+ol.extent.touches = function(extent1, extent2) {
+ var intersects = ol.extent.intersects(extent1, extent2);
+ return intersects &&
+ (extent1[0] == extent2[2] || extent1[2] == extent2[0] ||
+ extent1[1] == extent2[3] || extent1[3] == extent2[1]);
};
/**
- * Sets the target to be used for {@code event.target} when firing
- * event. Mainly used for testing. For example, see
- * {@code goog.testing.events.mixinListenable}.
- * @param {!Object} target The target.
+ * Apply a transform function to the extent.
+ * @param {ol.Extent} extent Extent.
+ * @param {ol.TransformFunction} transformFn Transform function. Called with
+ * [minX, minY, maxX, maxY] extent coordinates.
+ * @param {ol.Extent=} opt_extent Destination extent.
+ * @return {ol.Extent} Extent.
+ * @api stable
*/
-goog.events.EventTarget.prototype.setTargetForTesting = function(target) {
- this.actualEventTarget_ = target;
+ol.extent.applyTransform = function(extent, transformFn, opt_extent) {
+ var coordinates = [
+ extent[0], extent[1],
+ extent[0], extent[3],
+ extent[2], extent[1],
+ extent[2], extent[3]
+ ];
+ transformFn(coordinates, coordinates, 2);
+ var xs = [coordinates[0], coordinates[2], coordinates[4], coordinates[6]];
+ var ys = [coordinates[1], coordinates[3], coordinates[5], coordinates[7]];
+ return ol.extent.boundingExtentXYs_(xs, ys, opt_extent);
};
+goog.provide('ol.functions');
/**
- * Asserts that the event target instance is initialized properly.
- * @private
+ * Always returns true.
+ * @returns {boolean} true.
*/
-goog.events.EventTarget.prototype.assertInitialized_ = function() {
- goog.asserts.assert(
- this.eventTargetListeners_,
- 'Event target is not initialized. Did you call the superclass ' +
- '(goog.events.EventTarget) constructor?');
+ol.functions.TRUE = function() {
+ return true;
};
-
/**
- * Dispatches the given event on the ancestorsTree.
- *
- * @param {!Object} target The target to dispatch on.
- * @param {goog.events.Event|Object|string} e The event object.
- * @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors
- * tree of the target, in reverse order from the closest ancestor
- * to the root event target. May be null if the target has no ancestor.
- * @return {boolean} If anyone called preventDefault on the event object (or
- * if any of the listeners returns false) this will also return false.
- * @private
+ * Always returns false.
+ * @returns {boolean} false.
*/
-goog.events.EventTarget.dispatchEventInternal_ = function(
- target, e, opt_ancestorsTree) {
- var type = e.type || /** @type {string} */ (e);
-
- // If accepting a string or object, create a custom event object so that
- // preventDefault and stopPropagation work with the event.
- if (goog.isString(e)) {
- e = new goog.events.Event(e, target);
- } else if (!(e instanceof goog.events.Event)) {
- var oldEvent = e;
- e = new goog.events.Event(type, target);
- goog.object.extend(e, oldEvent);
- } else {
- e.target = e.target || target;
- }
-
- var rv = true, currentTarget;
-
- // Executes all capture listeners on the ancestors, if any.
- if (opt_ancestorsTree) {
- for (var i = opt_ancestorsTree.length - 1; !e.propagationStopped_ && i >= 0;
- i--) {
- currentTarget = e.currentTarget = opt_ancestorsTree[i];
- rv = currentTarget.fireListeners(type, true, e) && rv;
- }
- }
-
- // Executes capture and bubble listeners on the target.
- if (!e.propagationStopped_) {
- currentTarget = e.currentTarget = target;
- rv = currentTarget.fireListeners(type, true, e) && rv;
- if (!e.propagationStopped_) {
- rv = currentTarget.fireListeners(type, false, e) && rv;
- }
- }
-
- // Executes all bubble listeners on the ancestors, if any.
- if (opt_ancestorsTree) {
- for (i = 0; !e.propagationStopped_ && i < opt_ancestorsTree.length; i++) {
- currentTarget = e.currentTarget = opt_ancestorsTree[i];
- rv = currentTarget.fireListeners(type, false, e) && rv;
- }
- }
-
- return rv;
+ol.functions.FALSE = function() {
+ return false;
};
-goog.provide('ol.Observable');
+/**
+ * @license
+ * Latitude/longitude spherical geodesy formulae taken from
+ * http://www.movable-type.co.uk/scripts/latlong.html
+ * Licensed under CC-BY-3.0.
+ */
-goog.require('goog.events');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
+goog.provide('ol.Sphere');
+goog.require('ol.math');
/**
* @classdesc
- * Abstract base class; normally only used for creating subclasses and not
- * instantiated in apps.
- * An event target providing convenient methods for listener registration
- * and unregistration. A generic `change` event is always available through
- * {@link ol.Observable#changed}.
+ * Class to create objects that can be used with {@link
+ * ol.geom.Polygon.circular}.
+ *
+ * For example to create a sphere whose radius is equal to the semi-major
+ * axis of the WGS84 ellipsoid:
+ *
+ * ```js
+ * var wgs84Sphere= new ol.Sphere(6378137);
+ * ```
*
* @constructor
- * @extends {goog.events.EventTarget}
- * @fires change
- * @struct
- * @api stable
+ * @param {number} radius Radius.
+ * @api
*/
-ol.Observable = function() {
-
- goog.base(this);
+ol.Sphere = function(radius) {
/**
- * @private
* @type {number}
*/
- this.revision_ = 0;
+ this.radius = radius;
};
-goog.inherits(ol.Observable, goog.events.EventTarget);
/**
- * Removes an event listener using the key returned by `on()` or `once()`.
- * @param {goog.events.Key} key The key returned by `on()` or `once()`.
- * @api stable
+ * Returns the geodesic area for a list of coordinates.
+ *
+ * [Reference](http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409)
+ * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
+ * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
+ * Laboratory, Pasadena, CA, June 2007
+ *
+ * @param {Array.<ol.Coordinate>} coordinates List of coordinates of a linear
+ * ring. If the ring is oriented clockwise, the area will be positive,
+ * otherwise it will be negative.
+ * @return {number} Area.
+ * @api
*/
-ol.Observable.unByKey = function(key) {
- goog.events.unlistenByKey(key);
+ol.Sphere.prototype.geodesicArea = function(coordinates) {
+ var area = 0, len = coordinates.length;
+ var x1 = coordinates[len - 1][0];
+ var y1 = coordinates[len - 1][1];
+ for (var i = 0; i < len; i++) {
+ var x2 = coordinates[i][0], y2 = coordinates[i][1];
+ area += ol.math.toRadians(x2 - x1) *
+ (2 + Math.sin(ol.math.toRadians(y1)) +
+ Math.sin(ol.math.toRadians(y2)));
+ x1 = x2;
+ y1 = y2;
+ }
+ return area * this.radius * this.radius / 2.0;
};
/**
- * Increases the revision counter and dispatches a 'change' event.
+ * Returns the distance from c1 to c2 using the haversine formula.
+ *
+ * @param {ol.Coordinate} c1 Coordinate 1.
+ * @param {ol.Coordinate} c2 Coordinate 2.
+ * @return {number} Haversine distance.
* @api
*/
-ol.Observable.prototype.changed = function() {
- ++this.revision_;
- this.dispatchEvent(goog.events.EventType.CHANGE);
+ol.Sphere.prototype.haversineDistance = function(c1, c2) {
+ var lat1 = ol.math.toRadians(c1[1]);
+ var lat2 = ol.math.toRadians(c2[1]);
+ var deltaLatBy2 = (lat2 - lat1) / 2;
+ var deltaLonBy2 = ol.math.toRadians(c2[0] - c1[0]) / 2;
+ var a = Math.sin(deltaLatBy2) * Math.sin(deltaLatBy2) +
+ Math.sin(deltaLonBy2) * Math.sin(deltaLonBy2) *
+ Math.cos(lat1) * Math.cos(lat2);
+ return 2 * this.radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
};
/**
- * Triggered when the revision counter is increased.
- * @event change
- * @api
+ * Returns the coordinate at the given distance and bearing from `c1`.
+ *
+ * @param {ol.Coordinate} c1 The origin point (`[lon, lat]` in degrees).
+ * @param {number} distance The great-circle distance between the origin
+ * point and the target point.
+ * @param {number} bearing The bearing (in radians).
+ * @return {ol.Coordinate} The target point.
*/
+ol.Sphere.prototype.offset = function(c1, distance, bearing) {
+ var lat1 = ol.math.toRadians(c1[1]);
+ var lon1 = ol.math.toRadians(c1[0]);
+ var dByR = distance / this.radius;
+ var lat = Math.asin(
+ Math.sin(lat1) * Math.cos(dByR) +
+ Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing));
+ var lon = lon1 + Math.atan2(
+ Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1),
+ Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat));
+ return [ol.math.toDegrees(lon), ol.math.toDegrees(lat)];
+};
+goog.provide('ol.sphere.NORMAL');
-/**
- * Dispatches an event and calls all listeners listening for events
- * of this type. The event parameter can either be a string or an
- * Object with a `type` property.
- *
- * @param {goog.events.EventLike} event Event object.
- * @function
- * @api
- */
-ol.Observable.prototype.dispatchEvent;
+goog.require('ol.Sphere');
/**
- * Get the version number for this object. Each time the object is modified,
- * its version number will be incremented.
- * @return {number} Revision.
- * @api
+ * The normal sphere.
+ * @const
+ * @type {ol.Sphere}
*/
-ol.Observable.prototype.getRevision = function() {
- return this.revision_;
-};
+ol.sphere.NORMAL = new ol.Sphere(6370997);
+goog.provide('ol.proj');
+goog.provide('ol.proj.METERS_PER_UNIT');
+goog.provide('ol.proj.Projection');
+goog.provide('ol.proj.Units');
-/**
- * Listen for a certain type of event.
- * @param {string|Array.<string>} type The event type or array of event types.
- * @param {function(?): ?} listener The listener function.
- * @param {Object=} opt_this The object to use as `this` in `listener`.
- * @return {goog.events.Key} Unique key for the listener.
- * @api stable
- */
-ol.Observable.prototype.on = function(type, listener, opt_this) {
- return goog.events.listen(this, type, listener, false, opt_this);
-};
+goog.require('goog.asserts');
+goog.require('ol');
+goog.require('ol.extent');
+goog.require('ol.object');
+goog.require('ol.sphere.NORMAL');
/**
- * Listen once for a certain type of event.
- * @param {string|Array.<string>} type The event type or array of event types.
- * @param {function(?): ?} listener The listener function.
- * @param {Object=} opt_this The object to use as `this` in `listener`.
- * @return {goog.events.Key} Unique key for the listener.
+ * Projection units: `'degrees'`, `'ft'`, `'m'`, `'pixels'`, `'tile-pixels'` or
+ * `'us-ft'`.
+ * @enum {string}
* @api stable
*/
-ol.Observable.prototype.once = function(type, listener, opt_this) {
- return goog.events.listenOnce(this, type, listener, false, opt_this);
+ol.proj.Units = {
+ DEGREES: 'degrees',
+ FEET: 'ft',
+ METERS: 'm',
+ PIXELS: 'pixels',
+ TILE_PIXELS: 'tile-pixels',
+ USFEET: 'us-ft'
};
/**
- * Unlisten for a certain type of event.
- * @param {string|Array.<string>} type The event type or array of event types.
- * @param {function(?): ?} listener The listener function.
- * @param {Object=} opt_this The object which was used as `this` by the
- * `listener`.
+ * Meters per unit lookup table.
+ * @const
+ * @type {Object.<ol.proj.Units, number>}
* @api stable
*/
-ol.Observable.prototype.un = function(type, listener, opt_this) {
- goog.events.unlisten(this, type, listener, false, opt_this);
-};
+ol.proj.METERS_PER_UNIT = {};
+ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] =
+ 2 * Math.PI * ol.sphere.NORMAL.radius / 360;
+ol.proj.METERS_PER_UNIT[ol.proj.Units.FEET] = 0.3048;
+ol.proj.METERS_PER_UNIT[ol.proj.Units.METERS] = 1;
+ol.proj.METERS_PER_UNIT[ol.proj.Units.USFEET] = 1200 / 3937;
/**
- * Removes an event listener using the key returned by `on()` or `once()`.
- * Note that using the {@link ol.Observable.unByKey} static function is to
- * be preferred.
- * @param {goog.events.Key} key The key returned by `on()` or `once()`.
- * @function
+ * @classdesc
+ * Projection definition class. One of these is created for each projection
+ * supported in the application and stored in the {@link ol.proj} namespace.
+ * You can use these in applications, but this is not required, as API params
+ * and options use {@link ol.proj.ProjectionLike} which means the simple string
+ * code will suffice.
+ *
+ * You can use {@link ol.proj.get} to retrieve the object for a particular
+ * projection.
+ *
+ * The library includes definitions for `EPSG:4326` and `EPSG:3857`, together
+ * with the following aliases:
+ * * `EPSG:4326`: CRS:84, urn:ogc:def:crs:EPSG:6.6:4326,
+ * urn:ogc:def:crs:OGC:1.3:CRS84, urn:ogc:def:crs:OGC:2:84,
+ * http://www.opengis.net/gml/srs/epsg.xml#4326,
+ * urn:x-ogc:def:crs:EPSG:4326
+ * * `EPSG:3857`: EPSG:102100, EPSG:102113, EPSG:900913,
+ * urn:ogc:def:crs:EPSG:6.18:3:3857,
+ * http://www.opengis.net/gml/srs/epsg.xml#3857
+ *
+ * If you use proj4js, aliases can be added using `proj4.defs()`; see
+ * [documentation](https://github.com/proj4js/proj4js). To set an alternative
+ * namespace for proj4, use {@link ol.proj.setProj4}.
+ *
+ * @constructor
+ * @param {olx.ProjectionOptions} options Projection options.
+ * @struct
* @api stable
*/
-ol.Observable.prototype.unByKey = ol.Observable.unByKey;
-
-goog.provide('ol.Object');
-goog.provide('ol.ObjectEvent');
-goog.provide('ol.ObjectEventType');
-
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('ol.Observable');
-
+ol.proj.Projection = function(options) {
-/**
- * @enum {string}
- */
-ol.ObjectEventType = {
/**
- * Triggered when a property is changed.
- * @event ol.ObjectEvent#propertychange
- * @api stable
+ * @private
+ * @type {string}
*/
- PROPERTYCHANGE: 'propertychange'
-};
+ this.code_ = options.code;
+ /**
+ * @private
+ * @type {ol.proj.Units}
+ */
+ this.units_ = /** @type {ol.proj.Units} */ (options.units);
+ /**
+ * @private
+ * @type {ol.Extent}
+ */
+ this.extent_ = options.extent !== undefined ? options.extent : null;
-/**
- * @classdesc
- * Events emitted by {@link ol.Object} instances are instances of this type.
- *
- * @param {string} type The event type.
- * @param {string} key The property name.
- * @param {*} oldValue The old value for `key`.
- * @extends {goog.events.Event}
- * @implements {oli.ObjectEvent}
- * @constructor
- */
-ol.ObjectEvent = function(type, key, oldValue) {
- goog.base(this, type);
+ /**
+ * @private
+ * @type {ol.Extent}
+ */
+ this.worldExtent_ = options.worldExtent !== undefined ?
+ options.worldExtent : null;
/**
- * The name of the property whose value is changing.
+ * @private
* @type {string}
- * @api stable
*/
- this.key = key;
+ this.axisOrientation_ = options.axisOrientation !== undefined ?
+ options.axisOrientation : 'enu';
/**
- * The old value. To get the new value use `e.target.get(e.key)` where
- * `e` is the event object.
- * @type {*}
- * @api stable
+ * @private
+ * @type {boolean}
*/
- this.oldValue = oldValue;
-
-};
-goog.inherits(ol.ObjectEvent, goog.events.Event);
+ this.global_ = options.global !== undefined ? options.global : false;
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.canWrapX_ = !!(this.global_ && this.extent_);
-/**
- * @classdesc
- * Abstract base class; normally only used for creating subclasses and not
- * instantiated in apps.
- * Most non-trivial classes inherit from this.
- *
- * This extends {@link ol.Observable} with observable properties, where each
- * property is observable as well as the object as a whole.
- *
- * Classes that inherit from this have pre-defined properties, to which you can
- * add your owns. The pre-defined properties are listed in this documentation as
- * 'Observable Properties', and have their own accessors; for example,
- * {@link ol.Map} has a `target` property, accessed with `getTarget()` and
- * changed with `setTarget()`. Not all properties are however settable. There
- * are also general-purpose accessors `get()` and `set()`. For example,
- * `get('target')` is equivalent to `getTarget()`.
- *
- * The `set` accessors trigger a change event, and you can monitor this by
- * registering a listener. For example, {@link ol.View} has a `center`
- * property, so `view.on('change:center', function(evt) {...});` would call the
- * function whenever the value of the center property changes. Within the
- * function, `evt.target` would be the view, so `evt.target.getCenter()` would
- * return the new center.
- *
- * You can add your own observable properties with
- * `object.set('prop', 'value')`, and retrieve that with `object.get('prop')`.
- * You can listen for changes on that property value with
- * `object.on('change:prop', listener)`. You can get a list of all
- * properties with {@link ol.Object#getProperties object.getProperties()}.
- *
- * Note that the observable properties are separate from standard JS properties.
- * You can, for example, give your map object a title with
- * `map.title='New title'` and with `map.set('title', 'Another title')`. The
- * first will be a `hasOwnProperty`; the second will appear in
- * `getProperties()`. Only the second is observable.
- *
- * Properties can be deleted by using the unset method. E.g.
- * object.unset('foo').
- *
- * @constructor
- * @extends {ol.Observable}
- * @param {Object.<string, *>=} opt_values An object with key-value pairs.
- * @fires ol.ObjectEvent
- * @api
- */
-ol.Object = function(opt_values) {
- goog.base(this);
+ /**
+ * @private
+ * @type {function(number, ol.Coordinate):number}
+ */
+ this.getPointResolutionFunc_ = options.getPointResolution !== undefined ?
+ options.getPointResolution : this.getPointResolution_;
- // Call goog.getUid to ensure that the order of objects' ids is the same as
- // the order in which they were created. This also helps to ensure that
- // object properties are always added in the same order, which helps many
- // JavaScript engines generate faster code.
- goog.getUid(this);
+ /**
+ * @private
+ * @type {ol.tilegrid.TileGrid}
+ */
+ this.defaultTileGrid_ = null;
/**
* @private
- * @type {!Object.<string, *>}
+ * @type {number|undefined}
*/
- this.values_ = {};
+ this.metersPerUnit_ = options.metersPerUnit;
- if (opt_values !== undefined) {
- this.setProperties(opt_values);
+ var projections = ol.proj.projections_;
+ var code = options.code;
+ goog.asserts.assert(code !== undefined,
+ 'Option "code" is required for constructing instance');
+ if (ol.ENABLE_PROJ4JS) {
+ var proj4js = ol.proj.proj4_ || ol.global['proj4'];
+ if (typeof proj4js == 'function' && projections[code] === undefined) {
+ var def = proj4js.defs(code);
+ if (def !== undefined) {
+ if (def.axis !== undefined && options.axisOrientation === undefined) {
+ this.axisOrientation_ = def.axis;
+ }
+ if (options.metersPerUnit === undefined) {
+ this.metersPerUnit_ = def.to_meter;
+ }
+ if (options.units === undefined) {
+ this.units_ = def.units;
+ }
+ var currentCode, currentDef, currentProj, proj4Transform;
+ for (currentCode in projections) {
+ currentDef = proj4js.defs(currentCode);
+ if (currentDef !== undefined) {
+ currentProj = ol.proj.get(currentCode);
+ if (currentDef === def) {
+ ol.proj.addEquivalentProjections([currentProj, this]);
+ } else {
+ proj4Transform = proj4js(currentCode, code);
+ ol.proj.addCoordinateTransforms(currentProj, this,
+ proj4Transform.forward, proj4Transform.inverse);
+ }
+ }
+ }
+ }
+ }
}
+
};
-goog.inherits(ol.Object, ol.Observable);
/**
- * @private
- * @type {Object.<string, string>}
+ * @return {boolean} The projection is suitable for wrapping the x-axis
*/
-ol.Object.changeEventTypeCache_ = {};
+ol.proj.Projection.prototype.canWrapX = function() {
+ return this.canWrapX_;
+};
/**
- * @param {string} key Key name.
- * @return {string} Change name.
+ * Get the code for this projection, e.g. 'EPSG:4326'.
+ * @return {string} Code.
+ * @api stable
*/
-ol.Object.getChangeEventType = function(key) {
- return ol.Object.changeEventTypeCache_.hasOwnProperty(key) ?
- ol.Object.changeEventTypeCache_[key] :
- (ol.Object.changeEventTypeCache_[key] = 'change:' + key);
+ol.proj.Projection.prototype.getCode = function() {
+ return this.code_;
};
/**
- * Gets a value.
- * @param {string} key Key name.
- * @return {*} Value.
+ * Get the validity extent for this projection.
+ * @return {ol.Extent} Extent.
* @api stable
*/
-ol.Object.prototype.get = function(key) {
- var value;
- if (this.values_.hasOwnProperty(key)) {
- value = this.values_[key];
- }
- return value;
+ol.proj.Projection.prototype.getExtent = function() {
+ return this.extent_;
};
/**
- * Get a list of object property names.
- * @return {Array.<string>} List of property names.
+ * Get the units of this projection.
+ * @return {ol.proj.Units} Units.
* @api stable
*/
-ol.Object.prototype.getKeys = function() {
- return Object.keys(this.values_);
+ol.proj.Projection.prototype.getUnits = function() {
+ return this.units_;
};
/**
- * Get an object of all property names and values.
- * @return {Object.<string, *>} Object.
+ * Get the amount of meters per unit of this projection. If the projection is
+ * not configured with `metersPerUnit` or a units identifier, the return is
+ * `undefined`.
+ * @return {number|undefined} Meters.
* @api stable
*/
-ol.Object.prototype.getProperties = function() {
- var properties = {};
- var key;
- for (key in this.values_) {
- properties[key] = this.values_[key];
- }
- return properties;
+ol.proj.Projection.prototype.getMetersPerUnit = function() {
+ return this.metersPerUnit_ || ol.proj.METERS_PER_UNIT[this.units_];
};
/**
- * @param {string} key Key name.
- * @param {*} oldValue Old value.
+ * Get the world extent for this projection.
+ * @return {ol.Extent} Extent.
+ * @api
*/
-ol.Object.prototype.notify = function(key, oldValue) {
- var eventType;
- eventType = ol.Object.getChangeEventType(key);
- this.dispatchEvent(new ol.ObjectEvent(eventType, key, oldValue));
- eventType = ol.ObjectEventType.PROPERTYCHANGE;
- this.dispatchEvent(new ol.ObjectEvent(eventType, key, oldValue));
+ol.proj.Projection.prototype.getWorldExtent = function() {
+ return this.worldExtent_;
};
/**
- * Sets a value.
- * @param {string} key Key name.
- * @param {*} value Value.
- * @param {boolean=} opt_silent Update without triggering an event.
- * @api stable
+ * Get the axis orientation of this projection.
+ * Example values are:
+ * enu - the default easting, northing, elevation.
+ * neu - northing, easting, up - useful for "lat/long" geographic coordinates,
+ * or south orientated transverse mercator.
+ * wnu - westing, northing, up - some planetary coordinate systems have
+ * "west positive" coordinate systems
+ * @return {string} Axis orientation.
*/
-ol.Object.prototype.set = function(key, value, opt_silent) {
- if (opt_silent) {
- this.values_[key] = value;
- } else {
- var oldValue = this.values_[key];
- this.values_[key] = value;
- if (oldValue !== value) {
- this.notify(key, oldValue);
- }
- }
+ol.proj.Projection.prototype.getAxisOrientation = function() {
+ return this.axisOrientation_;
};
/**
- * Sets a collection of key-value pairs. Note that this changes any existing
- * properties and adds new ones (it does not remove any existing properties).
- * @param {Object.<string, *>} values Values.
- * @param {boolean=} opt_silent Update without triggering an event.
+ * Is this projection a global projection which spans the whole world?
+ * @return {boolean} Whether the projection is global.
* @api stable
*/
-ol.Object.prototype.setProperties = function(values, opt_silent) {
- var key;
- for (key in values) {
- this.set(key, values[key], opt_silent);
- }
+ol.proj.Projection.prototype.isGlobal = function() {
+ return this.global_;
};
/**
- * Unsets a property.
- * @param {string} key Key name.
- * @param {boolean=} opt_silent Unset without triggering an event.
- * @api stable
- */
-ol.Object.prototype.unset = function(key, opt_silent) {
- if (key in this.values_) {
- var oldValue = this.values_[key];
- delete this.values_[key];
- if (!opt_silent) {
- this.notify(key, oldValue);
- }
- }
+* Set if the projection is a global projection which spans the whole world
+* @param {boolean} global Whether the projection is global.
+* @api stable
+*/
+ol.proj.Projection.prototype.setGlobal = function(global) {
+ this.global_ = global;
+ this.canWrapX_ = !!(global && this.extent_);
};
-goog.provide('ol.Size');
-goog.provide('ol.size');
-
-
-goog.require('goog.asserts');
-
/**
- * An array of numbers representing a size: `[width, height]`.
- * @typedef {Array.<number>}
- * @api stable
+ * @return {ol.tilegrid.TileGrid} The default tile grid.
*/
-ol.Size;
+ol.proj.Projection.prototype.getDefaultTileGrid = function() {
+ return this.defaultTileGrid_;
+};
/**
- * Returns a buffered size.
- * @param {ol.Size} size Size.
- * @param {number} buffer Buffer.
- * @param {ol.Size=} opt_size Optional reusable size array.
- * @return {ol.Size}
+ * @param {ol.tilegrid.TileGrid} tileGrid The default tile grid.
*/
-ol.size.buffer = function(size, buffer, opt_size) {
- if (opt_size === undefined) {
- opt_size = [0, 0];
- }
- opt_size[0] = size[0] + 2 * buffer;
- opt_size[1] = size[1] + 2 * buffer;
- return opt_size;
+ol.proj.Projection.prototype.setDefaultTileGrid = function(tileGrid) {
+ this.defaultTileGrid_ = tileGrid;
};
/**
- * Compares sizes for equality.
- * @param {ol.Size} a Size.
- * @param {ol.Size} b Size.
- * @return {boolean} Equals.
+ * Set the validity extent for this projection.
+ * @param {ol.Extent} extent Extent.
+ * @api stable
*/
-ol.size.equals = function(a, b) {
- return a[0] == b[0] && a[1] == b[1];
+ol.proj.Projection.prototype.setExtent = function(extent) {
+ this.extent_ = extent;
+ this.canWrapX_ = !!(this.global_ && extent);
};
/**
- * Determines if a size has a positive area.
- * @param {ol.Size} size The size to test.
- * @return {boolean} The size has a positive area.
+ * Set the world extent for this projection.
+ * @param {ol.Extent} worldExtent World extent
+ * [minlon, minlat, maxlon, maxlat].
+ * @api
*/
-ol.size.hasArea = function(size) {
- return size[0] > 0 && size[1] > 0;
+ol.proj.Projection.prototype.setWorldExtent = function(worldExtent) {
+ this.worldExtent_ = worldExtent;
};
/**
- * Returns a size scaled by a ratio. The result will be an array of integers.
- * @param {ol.Size} size Size.
- * @param {number} ratio Ratio.
- * @param {ol.Size=} opt_size Optional reusable size array.
- * @return {ol.Size}
- */
-ol.size.scale = function(size, ratio, opt_size) {
- if (opt_size === undefined) {
- opt_size = [0, 0];
- }
- opt_size[0] = (size[0] * ratio + 0.5) | 0;
- opt_size[1] = (size[1] * ratio + 0.5) | 0;
- return opt_size;
+* Set the getPointResolution function for this projection.
+* @param {function(number, ol.Coordinate):number} func Function
+* @api
+*/
+ol.proj.Projection.prototype.setGetPointResolution = function(func) {
+ this.getPointResolutionFunc_ = func;
};
/**
- * Returns an `ol.Size` array for the passed in number (meaning: square) or
- * `ol.Size` array.
- * (meaning: non-square),
- * @param {number|ol.Size} size Width and height.
- * @param {ol.Size=} opt_size Optional reusable size array.
- * @return {ol.Size} Size.
- * @api stable
- */
-ol.size.toSize = function(size, opt_size) {
- if (goog.isArray(size)) {
- return size;
+* Default version.
+* Get the resolution of the point in degrees or distance units.
+* For projections with degrees as the unit this will simply return the
+* provided resolution. For other projections the point resolution is
+* estimated by transforming the 'point' pixel to EPSG:4326,
+* measuring its width and height on the normal sphere,
+* and taking the average of the width and height.
+* @param {number} resolution Nominal resolution in projection units.
+* @param {ol.Coordinate} point Point to find adjusted resolution at.
+* @return {number} Point resolution at point in projection units.
+* @private
+*/
+ol.proj.Projection.prototype.getPointResolution_ = function(resolution, point) {
+ var units = this.getUnits();
+ if (units == ol.proj.Units.DEGREES) {
+ return resolution;
} else {
- goog.asserts.assert(goog.isNumber(size));
- if (opt_size === undefined) {
- opt_size = [size, size];
- } else {
- opt_size[0] = size;
- opt_size[1] = size;
+ // Estimate point resolution by transforming the center pixel to EPSG:4326,
+ // measuring its width and height on the normal sphere, and taking the
+ // average of the width and height.
+ var toEPSG4326 = ol.proj.getTransformFromProjections(
+ this, ol.proj.get('EPSG:4326'));
+ var vertices = [
+ point[0] - resolution / 2, point[1],
+ point[0] + resolution / 2, point[1],
+ point[0], point[1] - resolution / 2,
+ point[0], point[1] + resolution / 2
+ ];
+ vertices = toEPSG4326(vertices, vertices, 2);
+ var width = ol.sphere.NORMAL.haversineDistance(
+ vertices.slice(0, 2), vertices.slice(2, 4));
+ var height = ol.sphere.NORMAL.haversineDistance(
+ vertices.slice(4, 6), vertices.slice(6, 8));
+ var pointResolution = (width + height) / 2;
+ var metersPerUnit = this.getMetersPerUnit();
+ if (metersPerUnit !== undefined) {
+ pointResolution /= metersPerUnit;
}
- return opt_size;
+ return pointResolution;
}
};
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Additional mathematical functions.
+ * Get the resolution of the point in degrees or distance units.
+ * For projections with degrees as the unit this will simply return the
+ * provided resolution. The default for other projections is to estimate
+ * the point resolution by transforming the 'point' pixel to EPSG:4326,
+ * measuring its width and height on the normal sphere,
+ * and taking the average of the width and height.
+ * An alternative implementation may be given when constructing a
+ * projection. For many local projections,
+ * such a custom function will return the resolution unchanged.
+ * @param {number} resolution Resolution in projection units.
+ * @param {ol.Coordinate} point Point.
+ * @return {number} Point resolution in projection units.
+ * @api
*/
+ol.proj.Projection.prototype.getPointResolution = function(resolution, point) {
+ return this.getPointResolutionFunc_(resolution, point);
+};
-goog.provide('goog.math');
-goog.require('goog.array');
-goog.require('goog.asserts');
+/**
+ * @private
+ * @type {Object.<string, ol.proj.Projection>}
+ */
+ol.proj.projections_ = {};
/**
- * Returns a random integer greater than or equal to 0 and less than {@code a}.
- * @param {number} a The upper bound for the random integer (exclusive).
- * @return {number} A random integer N such that 0 <= N < a.
+ * @private
+ * @type {Object.<string, Object.<string, ol.TransformFunction>>}
*/
-goog.math.randomInt = function(a) {
- return Math.floor(Math.random() * a);
-};
+ol.proj.transforms_ = {};
/**
- * Returns a random number greater than or equal to {@code a} and less than
- * {@code b}.
- * @param {number} a The lower bound for the random number (inclusive).
- * @param {number} b The upper bound for the random number (exclusive).
- * @return {number} A random number N such that a <= N < b.
+ * @private
+ * @type {proj4}
*/
-goog.math.uniformRandom = function(a, b) {
- return a + Math.random() * (b - a);
-};
+ol.proj.proj4_ = null;
+
+
+if (ol.ENABLE_PROJ4JS) {
+ /**
+ * Register proj4. If not explicitly registered, it will be assumed that
+ * proj4js will be loaded in the global namespace. For example in a
+ * browserify ES6 environment you could use:
+ *
+ * import ol from 'openlayers';
+ * import proj4 from 'proj4';
+ * ol.proj.setProj4(proj4);
+ *
+ * @param {proj4} proj4 Proj4.
+ * @api
+ */
+ ol.proj.setProj4 = function(proj4) {
+ goog.asserts.assert(typeof proj4 == 'function',
+ 'proj4 argument should be a function');
+ ol.proj.proj4_ = proj4;
+ };
+}
/**
- * Takes a number and clamps it to within the provided bounds.
- * @param {number} value The input number.
- * @param {number} min The minimum value to return.
- * @param {number} max The maximum value to return.
- * @return {number} The input number if it is within bounds, or the nearest
- * number within the bounds.
+ * Registers transformation functions that don't alter coordinates. Those allow
+ * to transform between projections with equal meaning.
+ *
+ * @param {Array.<ol.proj.Projection>} projections Projections.
+ * @api
*/
-goog.math.clamp = function(value, min, max) {
- return Math.min(Math.max(value, min), max);
+ol.proj.addEquivalentProjections = function(projections) {
+ ol.proj.addProjections(projections);
+ projections.forEach(function(source) {
+ projections.forEach(function(destination) {
+ if (source !== destination) {
+ ol.proj.addTransform(source, destination, ol.proj.cloneTransform);
+ }
+ });
+ });
};
/**
- * The % operator in JavaScript returns the remainder of a / b, but differs from
- * some other languages in that the result will have the same sign as the
- * dividend. For example, -1 % 8 == -1, whereas in some other languages
- * (such as Python) the result would be 7. This function emulates the more
- * correct modulo behavior, which is useful for certain applications such as
- * calculating an offset index in a circular list.
+ * Registers transformation functions to convert coordinates in any projection
+ * in projection1 to any projection in projection2.
*
- * @param {number} a The dividend.
- * @param {number} b The divisor.
- * @return {number} a % b where the result is between 0 and b (either 0 <= x < b
- * or b < x <= 0, depending on the sign of b).
+ * @param {Array.<ol.proj.Projection>} projections1 Projections with equal
+ * meaning.
+ * @param {Array.<ol.proj.Projection>} projections2 Projections with equal
+ * meaning.
+ * @param {ol.TransformFunction} forwardTransform Transformation from any
+ * projection in projection1 to any projection in projection2.
+ * @param {ol.TransformFunction} inverseTransform Transform from any projection
+ * in projection2 to any projection in projection1..
*/
-goog.math.modulo = function(a, b) {
- var r = a % b;
- // If r and b differ in sign, add b to wrap the result to the correct sign.
- return (r * b < 0) ? r + b : r;
+ol.proj.addEquivalentTransforms = function(projections1, projections2, forwardTransform, inverseTransform) {
+ projections1.forEach(function(projection1) {
+ projections2.forEach(function(projection2) {
+ ol.proj.addTransform(projection1, projection2, forwardTransform);
+ ol.proj.addTransform(projection2, projection1, inverseTransform);
+ });
+ });
};
/**
- * Performs linear interpolation between values a and b. Returns the value
- * between a and b proportional to x (when x is between 0 and 1. When x is
- * outside this range, the return value is a linear extrapolation).
- * @param {number} a A number.
- * @param {number} b A number.
- * @param {number} x The proportion between a and b.
- * @return {number} The interpolated value between a and b.
+ * Add a Projection object to the list of supported projections that can be
+ * looked up by their code.
+ *
+ * @param {ol.proj.Projection} projection Projection instance.
+ * @api stable
*/
-goog.math.lerp = function(a, b, x) {
- return a + x * (b - a);
+ol.proj.addProjection = function(projection) {
+ ol.proj.projections_[projection.getCode()] = projection;
+ ol.proj.addTransform(projection, projection, ol.proj.cloneTransform);
};
/**
- * Tests whether the two values are equal to each other, within a certain
- * tolerance to adjust for floating point errors.
- * @param {number} a A number.
- * @param {number} b A number.
- * @param {number=} opt_tolerance Optional tolerance range. Defaults
- * to 0.000001. If specified, should be greater than 0.
- * @return {boolean} Whether {@code a} and {@code b} are nearly equal.
+ * @param {Array.<ol.proj.Projection>} projections Projections.
*/
-goog.math.nearlyEquals = function(a, b, opt_tolerance) {
- return Math.abs(a - b) <= (opt_tolerance || 0.000001);
+ol.proj.addProjections = function(projections) {
+ var addedProjections = [];
+ projections.forEach(function(projection) {
+ addedProjections.push(ol.proj.addProjection(projection));
+ });
};
-// TODO(user): Rename to normalizeAngle, retaining old name as deprecated
-// alias.
/**
- * Normalizes an angle to be in range [0-360). Angles outside this range will
- * be normalized to be the equivalent angle with that range.
- * @param {number} angle Angle in degrees.
- * @return {number} Standardized angle.
+ * FIXME empty description for jsdoc
*/
-goog.math.standardAngle = function(angle) {
- return goog.math.modulo(angle, 360);
+ol.proj.clearAllProjections = function() {
+ ol.proj.projections_ = {};
+ ol.proj.transforms_ = {};
};
/**
- * Normalizes an angle to be in range [0-2*PI). Angles outside this range will
- * be normalized to be the equivalent angle with that range.
- * @param {number} angle Angle in radians.
- * @return {number} Standardized angle.
+ * @param {ol.proj.Projection|string|undefined} projection Projection.
+ * @param {string} defaultCode Default code.
+ * @return {ol.proj.Projection} Projection.
*/
-goog.math.standardAngleInRadians = function(angle) {
- return goog.math.modulo(angle, 2 * Math.PI);
+ol.proj.createProjection = function(projection, defaultCode) {
+ if (!projection) {
+ return ol.proj.get(defaultCode);
+ } else if (typeof projection === 'string') {
+ return ol.proj.get(projection);
+ } else {
+ goog.asserts.assertInstanceof(projection, ol.proj.Projection,
+ 'projection should be an ol.proj.Projection');
+ return projection;
+ }
};
/**
- * Converts degrees to radians.
- * @param {number} angleDegrees Angle in degrees.
- * @return {number} Angle in radians.
+ * Registers a conversion function to convert coordinates from the source
+ * projection to the destination projection.
+ *
+ * @param {ol.proj.Projection} source Source.
+ * @param {ol.proj.Projection} destination Destination.
+ * @param {ol.TransformFunction} transformFn Transform.
*/
-goog.math.toRadians = function(angleDegrees) {
- return angleDegrees * Math.PI / 180;
+ol.proj.addTransform = function(source, destination, transformFn) {
+ var sourceCode = source.getCode();
+ var destinationCode = destination.getCode();
+ var transforms = ol.proj.transforms_;
+ if (!(sourceCode in transforms)) {
+ transforms[sourceCode] = {};
+ }
+ transforms[sourceCode][destinationCode] = transformFn;
};
/**
- * Converts radians to degrees.
- * @param {number} angleRadians Angle in radians.
- * @return {number} Angle in degrees.
+ * Registers coordinate transform functions to convert coordinates between the
+ * source projection and the destination projection.
+ * The forward and inverse functions convert coordinate pairs; this function
+ * converts these into the functions used internally which also handle
+ * extents and coordinate arrays.
+ *
+ * @param {ol.proj.ProjectionLike} source Source projection.
+ * @param {ol.proj.ProjectionLike} destination Destination projection.
+ * @param {function(ol.Coordinate): ol.Coordinate} forward The forward transform
+ * function (that is, from the source projection to the destination
+ * projection) that takes a {@link ol.Coordinate} as argument and returns
+ * the transformed {@link ol.Coordinate}.
+ * @param {function(ol.Coordinate): ol.Coordinate} inverse The inverse transform
+ * function (that is, from the destination projection to the source
+ * projection) that takes a {@link ol.Coordinate} as argument and returns
+ * the transformed {@link ol.Coordinate}.
+ * @api stable
*/
-goog.math.toDegrees = function(angleRadians) {
- return angleRadians * 180 / Math.PI;
+ol.proj.addCoordinateTransforms = function(source, destination, forward, inverse) {
+ var sourceProj = ol.proj.get(source);
+ var destProj = ol.proj.get(destination);
+ ol.proj.addTransform(sourceProj, destProj,
+ ol.proj.createTransformFromCoordinateTransform(forward));
+ ol.proj.addTransform(destProj, sourceProj,
+ ol.proj.createTransformFromCoordinateTransform(inverse));
};
/**
- * For a given angle and radius, finds the X portion of the offset.
- * @param {number} degrees Angle in degrees (zero points in +X direction).
- * @param {number} radius Radius.
- * @return {number} The x-distance for the angle and radius.
+ * Creates a {@link ol.TransformFunction} from a simple 2D coordinate transform
+ * function.
+ * @param {function(ol.Coordinate): ol.Coordinate} transform Coordinate
+ * transform.
+ * @return {ol.TransformFunction} Transform function.
*/
-goog.math.angleDx = function(degrees, radius) {
- return radius * Math.cos(goog.math.toRadians(degrees));
+ol.proj.createTransformFromCoordinateTransform = function(transform) {
+ return (
+ /**
+ * @param {Array.<number>} input Input.
+ * @param {Array.<number>=} opt_output Output.
+ * @param {number=} opt_dimension Dimension.
+ * @return {Array.<number>} Output.
+ */
+ function(input, opt_output, opt_dimension) {
+ var length = input.length;
+ var dimension = opt_dimension !== undefined ? opt_dimension : 2;
+ var output = opt_output !== undefined ? opt_output : new Array(length);
+ var point, i, j;
+ for (i = 0; i < length; i += dimension) {
+ point = transform([input[i], input[i + 1]]);
+ output[i] = point[0];
+ output[i + 1] = point[1];
+ for (j = dimension - 1; j >= 2; --j) {
+ output[i + j] = input[i + j];
+ }
+ }
+ return output;
+ });
};
/**
- * For a given angle and radius, finds the Y portion of the offset.
- * @param {number} degrees Angle in degrees (zero points in +X direction).
- * @param {number} radius Radius.
- * @return {number} The y-distance for the angle and radius.
+ * Unregisters the conversion function to convert coordinates from the source
+ * projection to the destination projection. This method is used to clean up
+ * cached transforms during testing.
+ *
+ * @param {ol.proj.Projection} source Source projection.
+ * @param {ol.proj.Projection} destination Destination projection.
+ * @return {ol.TransformFunction} transformFn The unregistered transform.
*/
-goog.math.angleDy = function(degrees, radius) {
- return radius * Math.sin(goog.math.toRadians(degrees));
+ol.proj.removeTransform = function(source, destination) {
+ var sourceCode = source.getCode();
+ var destinationCode = destination.getCode();
+ var transforms = ol.proj.transforms_;
+ goog.asserts.assert(sourceCode in transforms,
+ 'sourceCode should be in transforms');
+ goog.asserts.assert(destinationCode in transforms[sourceCode],
+ 'destinationCode should be in transforms of sourceCode');
+ var transform = transforms[sourceCode][destinationCode];
+ delete transforms[sourceCode][destinationCode];
+ if (ol.object.isEmpty(transforms[sourceCode])) {
+ delete transforms[sourceCode];
+ }
+ return transform;
};
/**
- * Computes the angle between two points (x1,y1) and (x2,y2).
- * Angle zero points in the +X direction, 90 degrees points in the +Y
- * direction (down) and from there we grow clockwise towards 360 degrees.
- * @param {number} x1 x of first point.
- * @param {number} y1 y of first point.
- * @param {number} x2 x of second point.
- * @param {number} y2 y of second point.
- * @return {number} Standardized angle in degrees of the vector from
- * x1,y1 to x2,y2.
+ * Transforms a coordinate from longitude/latitude to a different projection.
+ * @param {ol.Coordinate} coordinate Coordinate as longitude and latitude, i.e.
+ * an array with longitude as 1st and latitude as 2nd element.
+ * @param {ol.proj.ProjectionLike=} opt_projection Target projection. The
+ * default is Web Mercator, i.e. 'EPSG:3857'.
+ * @return {ol.Coordinate} Coordinate projected to the target projection.
+ * @api stable
*/
-goog.math.angle = function(x1, y1, x2, y2) {
- return goog.math.standardAngle(goog.math.toDegrees(Math.atan2(y2 - y1,
- x2 - x1)));
+ol.proj.fromLonLat = function(coordinate, opt_projection) {
+ return ol.proj.transform(coordinate, 'EPSG:4326',
+ opt_projection !== undefined ? opt_projection : 'EPSG:3857');
};
/**
- * Computes the difference between startAngle and endAngle (angles in degrees).
- * @param {number} startAngle Start angle in degrees.
- * @param {number} endAngle End angle in degrees.
- * @return {number} The number of degrees that when added to
- * startAngle will result in endAngle. Positive numbers mean that the
- * direction is clockwise. Negative numbers indicate a counter-clockwise
- * direction.
- * The shortest route (clockwise vs counter-clockwise) between the angles
- * is used.
- * When the difference is 180 degrees, the function returns 180 (not -180)
- * angleDifference(30, 40) is 10, and angleDifference(40, 30) is -10.
- * angleDifference(350, 10) is 20, and angleDifference(10, 350) is -20.
+ * Transforms a coordinate to longitude/latitude.
+ * @param {ol.Coordinate} coordinate Projected coordinate.
+ * @param {ol.proj.ProjectionLike=} opt_projection Projection of the coordinate.
+ * The default is Web Mercator, i.e. 'EPSG:3857'.
+ * @return {ol.Coordinate} Coordinate as longitude and latitude, i.e. an array
+ * with longitude as 1st and latitude as 2nd element.
+ * @api stable
*/
-goog.math.angleDifference = function(startAngle, endAngle) {
- var d = goog.math.standardAngle(endAngle) -
- goog.math.standardAngle(startAngle);
- if (d > 180) {
- d = d - 360;
- } else if (d <= -180) {
- d = 360 + d;
- }
- return d;
+ol.proj.toLonLat = function(coordinate, opt_projection) {
+ return ol.proj.transform(coordinate,
+ opt_projection !== undefined ? opt_projection : 'EPSG:3857', 'EPSG:4326');
};
/**
- * Returns the sign of a number as per the "sign" or "signum" function.
- * @param {number} x The number to take the sign of.
- * @return {number} -1 when negative, 1 when positive, 0 when 0. Preserves
- * signed zeros and NaN.
+ * Fetches a Projection object for the code specified.
+ *
+ * @param {ol.proj.ProjectionLike} projectionLike Either a code string which is
+ * a combination of authority and identifier such as "EPSG:4326", or an
+ * existing projection object, or undefined.
+ * @return {ol.proj.Projection} Projection object, or null if not in list.
+ * @api stable
*/
-goog.math.sign = Math.sign || function(x) {
- if (x > 0) {
- return 1;
- }
- if (x < 0) {
- return -1;
+ol.proj.get = function(projectionLike) {
+ var projection;
+ if (projectionLike instanceof ol.proj.Projection) {
+ projection = projectionLike;
+ } else if (typeof projectionLike === 'string') {
+ var code = projectionLike;
+ projection = ol.proj.projections_[code];
+ if (ol.ENABLE_PROJ4JS) {
+ var proj4js = ol.proj.proj4_ || ol.global['proj4'];
+ if (projection === undefined && typeof proj4js == 'function' &&
+ proj4js.defs(code) !== undefined) {
+ projection = new ol.proj.Projection({code: code});
+ ol.proj.addProjection(projection);
+ }
+ }
+ } else {
+ projection = null;
}
- return x; // Preserves signed zeros and NaN.
+ return projection;
};
/**
- * JavaScript implementation of Longest Common Subsequence problem.
- * http://en.wikipedia.org/wiki/Longest_common_subsequence
- *
- * Returns the longest possible array that is subarray of both of given arrays.
+ * Checks if two projections are the same, that is every coordinate in one
+ * projection does represent the same geographic point as the same coordinate in
+ * the other projection.
*
- * @param {Array<Object>} array1 First array of objects.
- * @param {Array<Object>} array2 Second array of objects.
- * @param {Function=} opt_compareFn Function that acts as a custom comparator
- * for the array ojects. Function should return true if objects are equal,
- * otherwise false.
- * @param {Function=} opt_collectorFn Function used to decide what to return
- * as a result subsequence. It accepts 2 arguments: index of common element
- * in the first array and index in the second. The default function returns
- * element from the first array.
- * @return {!Array<Object>} A list of objects that are common to both arrays
- * such that there is no common subsequence with size greater than the
- * length of the list.
+ * @param {ol.proj.Projection} projection1 Projection 1.
+ * @param {ol.proj.Projection} projection2 Projection 2.
+ * @return {boolean} Equivalent.
+ * @api
*/
-goog.math.longestCommonSubsequence = function(
- array1, array2, opt_compareFn, opt_collectorFn) {
-
- var compare = opt_compareFn || function(a, b) {
- return a == b;
- };
-
- var collect = opt_collectorFn || function(i1, i2) {
- return array1[i1];
- };
-
- var length1 = array1.length;
- var length2 = array2.length;
-
- var arr = [];
- for (var i = 0; i < length1 + 1; i++) {
- arr[i] = [];
- arr[i][0] = 0;
- }
-
- for (var j = 0; j < length2 + 1; j++) {
- arr[0][j] = 0;
- }
-
- for (i = 1; i <= length1; i++) {
- for (j = 1; j <= length2; j++) {
- if (compare(array1[i - 1], array2[j - 1])) {
- arr[i][j] = arr[i - 1][j - 1] + 1;
- } else {
- arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
- }
- }
+ol.proj.equivalent = function(projection1, projection2) {
+ if (projection1 === projection2) {
+ return true;
}
-
- // Backtracking
- var result = [];
- var i = length1, j = length2;
- while (i > 0 && j > 0) {
- if (compare(array1[i - 1], array2[j - 1])) {
- result.unshift(collect(i - 1, j - 1));
- i--;
- j--;
- } else {
- if (arr[i - 1][j] > arr[i][j - 1]) {
- i--;
- } else {
- j--;
- }
- }
+ var equalUnits = projection1.getUnits() === projection2.getUnits();
+ if (projection1.getCode() === projection2.getCode()) {
+ return equalUnits;
+ } else {
+ var transformFn = ol.proj.getTransformFromProjections(
+ projection1, projection2);
+ return transformFn === ol.proj.cloneTransform && equalUnits;
}
-
- return result;
};
/**
- * Returns the sum of the arguments.
- * @param {...number} var_args Numbers to add.
- * @return {number} The sum of the arguments (0 if no arguments were provided,
- * {@code NaN} if any of the arguments is not a valid number).
+ * Given the projection-like objects, searches for a transformation
+ * function to convert a coordinates array from the source projection to the
+ * destination projection.
+ *
+ * @param {ol.proj.ProjectionLike} source Source.
+ * @param {ol.proj.ProjectionLike} destination Destination.
+ * @return {ol.TransformFunction} Transform function.
+ * @api stable
*/
-goog.math.sum = function(var_args) {
- return /** @type {number} */ (goog.array.reduce(arguments,
- function(sum, value) {
- return sum + value;
- }, 0));
+ol.proj.getTransform = function(source, destination) {
+ var sourceProjection = ol.proj.get(source);
+ var destinationProjection = ol.proj.get(destination);
+ return ol.proj.getTransformFromProjections(
+ sourceProjection, destinationProjection);
};
/**
- * Returns the arithmetic mean of the arguments.
- * @param {...number} var_args Numbers to average.
- * @return {number} The average of the arguments ({@code NaN} if no arguments
- * were provided or any of the arguments is not a valid number).
+ * Searches in the list of transform functions for the function for converting
+ * coordinates from the source projection to the destination projection.
+ *
+ * @param {ol.proj.Projection} sourceProjection Source Projection object.
+ * @param {ol.proj.Projection} destinationProjection Destination Projection
+ * object.
+ * @return {ol.TransformFunction} Transform function.
*/
-goog.math.average = function(var_args) {
- return goog.math.sum.apply(null, arguments) / arguments.length;
+ol.proj.getTransformFromProjections = function(sourceProjection, destinationProjection) {
+ var transforms = ol.proj.transforms_;
+ var sourceCode = sourceProjection.getCode();
+ var destinationCode = destinationProjection.getCode();
+ var transform;
+ if (sourceCode in transforms && destinationCode in transforms[sourceCode]) {
+ transform = transforms[sourceCode][destinationCode];
+ }
+ if (transform === undefined) {
+ goog.asserts.assert(transform !== undefined, 'transform should be defined');
+ transform = ol.proj.identityTransform;
+ }
+ return transform;
};
/**
- * Returns the unbiased sample variance of the arguments. For a definition,
- * see e.g. http://en.wikipedia.org/wiki/Variance
- * @param {...number} var_args Number samples to analyze.
- * @return {number} The unbiased sample variance of the arguments (0 if fewer
- * than two samples were provided, or {@code NaN} if any of the samples is
- * not a valid number).
+ * @param {Array.<number>} input Input coordinate array.
+ * @param {Array.<number>=} opt_output Output array of coordinate values.
+ * @param {number=} opt_dimension Dimension.
+ * @return {Array.<number>} Input coordinate array (same array as input).
*/
-goog.math.sampleVariance = function(var_args) {
- var sampleSize = arguments.length;
- if (sampleSize < 2) {
- return 0;
+ol.proj.identityTransform = function(input, opt_output, opt_dimension) {
+ if (opt_output !== undefined && input !== opt_output) {
+ // TODO: consider making this a warning instead
+ goog.asserts.fail('This should not be used internally.');
+ for (var i = 0, ii = input.length; i < ii; ++i) {
+ opt_output[i] = input[i];
+ }
+ input = opt_output;
}
-
- var mean = goog.math.average.apply(null, arguments);
- var variance = goog.math.sum.apply(null, goog.array.map(arguments,
- function(val) {
- return Math.pow(val - mean, 2);
- })) / (sampleSize - 1);
-
- return variance;
+ return input;
};
/**
- * Returns the sample standard deviation of the arguments. For a definition of
- * sample standard deviation, see e.g.
- * http://en.wikipedia.org/wiki/Standard_deviation
- * @param {...number} var_args Number samples to analyze.
- * @return {number} The sample standard deviation of the arguments (0 if fewer
- * than two samples were provided, or {@code NaN} if any of the samples is
- * not a valid number).
+ * @param {Array.<number>} input Input coordinate array.
+ * @param {Array.<number>=} opt_output Output array of coordinate values.
+ * @param {number=} opt_dimension Dimension.
+ * @return {Array.<number>} Output coordinate array (new array, same coordinate
+ * values).
*/
-goog.math.standardDeviation = function(var_args) {
- return Math.sqrt(goog.math.sampleVariance.apply(null, arguments));
+ol.proj.cloneTransform = function(input, opt_output, opt_dimension) {
+ var output;
+ if (opt_output !== undefined) {
+ for (var i = 0, ii = input.length; i < ii; ++i) {
+ opt_output[i] = input[i];
+ }
+ output = opt_output;
+ } else {
+ output = input.slice();
+ }
+ return output;
};
/**
- * Returns whether the supplied number represents an integer, i.e. that is has
- * no fractional component. No range-checking is performed on the number.
- * @param {number} num The number to test.
- * @return {boolean} Whether {@code num} is an integer.
+ * Transforms a coordinate from source projection to destination projection.
+ * This returns a new coordinate (and does not modify the original).
+ *
+ * See {@link ol.proj.transformExtent} for extent transformation.
+ * See the transform method of {@link ol.geom.Geometry} and its subclasses for
+ * geometry transforms.
+ *
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @param {ol.proj.ProjectionLike} source Source projection-like.
+ * @param {ol.proj.ProjectionLike} destination Destination projection-like.
+ * @return {ol.Coordinate} Coordinate.
+ * @api stable
*/
-goog.math.isInt = function(num) {
- return isFinite(num) && num % 1 == 0;
+ol.proj.transform = function(coordinate, source, destination) {
+ var transformFn = ol.proj.getTransform(source, destination);
+ return transformFn(coordinate, undefined, coordinate.length);
};
/**
- * Returns whether the supplied number is finite and not NaN.
- * @param {number} num The number to test.
- * @return {boolean} Whether {@code num} is a finite number.
+ * Transforms an extent from source projection to destination projection. This
+ * returns a new extent (and does not modify the original).
+ *
+ * @param {ol.Extent} extent The extent to transform.
+ * @param {ol.proj.ProjectionLike} source Source projection-like.
+ * @param {ol.proj.ProjectionLike} destination Destination projection-like.
+ * @return {ol.Extent} The transformed extent.
+ * @api stable
*/
-goog.math.isFiniteNumber = function(num) {
- return isFinite(num) && !isNaN(num);
+ol.proj.transformExtent = function(extent, source, destination) {
+ var transformFn = ol.proj.getTransform(source, destination);
+ return ol.extent.applyTransform(extent, transformFn);
};
/**
- * @param {number} num The number to test.
- * @return {boolean} Whether it is negative zero.
+ * Transforms the given point to the destination projection.
+ *
+ * @param {ol.Coordinate} point Point.
+ * @param {ol.proj.Projection} sourceProjection Source projection.
+ * @param {ol.proj.Projection} destinationProjection Destination projection.
+ * @return {ol.Coordinate} Point.
*/
-goog.math.isNegativeZero = function(num) {
- return num == 0 && 1 / num < 0;
+ol.proj.transformWithProjections = function(point, sourceProjection, destinationProjection) {
+ var transformFn = ol.proj.getTransformFromProjections(
+ sourceProjection, destinationProjection);
+ return transformFn(point);
};
+goog.provide('ol.geom.Geometry');
+goog.provide('ol.geom.GeometryLayout');
+goog.provide('ol.geom.GeometryType');
+
+goog.require('goog.asserts');
+goog.require('ol.functions');
+goog.require('ol.Object');
+goog.require('ol.extent');
+goog.require('ol.proj');
+goog.require('ol.proj.Units');
+
/**
- * Returns the precise value of floor(log10(num)).
- * Simpler implementations didn't work because of floating point rounding
- * errors. For example
- * <ul>
- * <li>Math.floor(Math.log(num) / Math.LN10) is off by one for num == 1e+3.
- * <li>Math.floor(Math.log(num) * Math.LOG10E) is off by one for num == 1e+15.
- * <li>Math.floor(Math.log10(num)) is off by one for num == 1e+15 - 1.
- * </ul>
- * @param {number} num A floating point number.
- * @return {number} Its logarithm to base 10 rounded down to the nearest
- * integer if num > 0. -Infinity if num == 0. NaN if num < 0.
+ * The geometry type. One of `'Point'`, `'LineString'`, `'LinearRing'`,
+ * `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`,
+ * `'GeometryCollection'`, `'Circle'`.
+ * @enum {string}
+ * @api stable
*/
-goog.math.log10Floor = function(num) {
- if (num > 0) {
- var x = Math.round(Math.log(num) * Math.LOG10E);
- return x - (parseFloat('1e' + x) > num);
- }
- return num == 0 ? -Infinity : NaN;
+ol.geom.GeometryType = {
+ POINT: 'Point',
+ LINE_STRING: 'LineString',
+ LINEAR_RING: 'LinearRing',
+ POLYGON: 'Polygon',
+ MULTI_POINT: 'MultiPoint',
+ MULTI_LINE_STRING: 'MultiLineString',
+ MULTI_POLYGON: 'MultiPolygon',
+ GEOMETRY_COLLECTION: 'GeometryCollection',
+ CIRCLE: 'Circle'
};
/**
- * A tweaked variant of {@code Math.floor} which tolerates if the passed number
- * is infinitesimally smaller than the closest integer. It often happens with
- * the results of floating point calculations because of the finite precision
- * of the intermediate results. For example {@code Math.floor(Math.log(1000) /
- * Math.LN10) == 2}, not 3 as one would expect.
- * @param {number} num A number.
- * @param {number=} opt_epsilon An infinitesimally small positive number, the
- * rounding error to tolerate.
- * @return {number} The largest integer less than or equal to {@code num}.
+ * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
+ * or measure ('M') coordinate is available. Supported values are `'XY'`,
+ * `'XYZ'`, `'XYM'`, `'XYZM'`.
+ * @enum {string}
+ * @api stable
*/
-goog.math.safeFloor = function(num, opt_epsilon) {
- goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
- return Math.floor(num + (opt_epsilon || 2e-15));
+ol.geom.GeometryLayout = {
+ XY: 'XY',
+ XYZ: 'XYZ',
+ XYM: 'XYM',
+ XYZM: 'XYZM'
};
/**
- * A tweaked variant of {@code Math.ceil}. See {@code goog.math.safeFloor} for
- * details.
- * @param {number} num A number.
- * @param {number=} opt_epsilon An infinitesimally small positive number, the
- * rounding error to tolerate.
- * @return {number} The smallest integer greater than or equal to {@code num}.
+ * @classdesc
+ * Abstract base class; normally only used for creating subclasses and not
+ * instantiated in apps.
+ * Base class for vector geometries.
+ *
+ * To get notified of changes to the geometry, register a listener for the
+ * generic `change` event on your geometry instance.
+ *
+ * @constructor
+ * @extends {ol.Object}
+ * @api stable
*/
-goog.math.safeCeil = function(num, opt_epsilon) {
- goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
- return Math.ceil(num - (opt_epsilon || 2e-15));
-};
+ol.geom.Geometry = function() {
-goog.provide('ol.Coordinate');
-goog.provide('ol.CoordinateFormatType');
-goog.provide('ol.coordinate');
+ goog.base(this);
-goog.require('goog.math');
-goog.require('goog.string');
+ /**
+ * @private
+ * @type {ol.Extent}
+ */
+ this.extent_ = ol.extent.createEmpty();
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this.extentRevision_ = -1;
+
+ /**
+ * @protected
+ * @type {Object.<string, ol.geom.Geometry>}
+ */
+ this.simplifiedGeometryCache = {};
+
+ /**
+ * @protected
+ * @type {number}
+ */
+ this.simplifiedGeometryMaxMinSquaredTolerance = 0;
+
+ /**
+ * @protected
+ * @type {number}
+ */
+ this.simplifiedGeometryRevision = 0;
+
+};
+goog.inherits(ol.geom.Geometry, ol.Object);
/**
- * A function that takes a {@link ol.Coordinate} and transforms it into a
- * `{string}`.
- *
- * @typedef {function((ol.Coordinate|undefined)): string}
- * @api stable
+ * Make a complete copy of the geometry.
+ * @function
+ * @return {!ol.geom.Geometry} Clone.
*/
-ol.CoordinateFormatType;
+ol.geom.Geometry.prototype.clone = goog.abstractMethod;
/**
- * An array of numbers representing an xy coordinate. Example: `[16, 48]`.
- * @typedef {Array.<number>} ol.Coordinate
- * @api stable
+ * @param {number} x X.
+ * @param {number} y Y.
+ * @param {ol.Coordinate} closestPoint Closest point.
+ * @param {number} minSquaredDistance Minimum squared distance.
+ * @return {number} Minimum squared distance.
*/
-ol.Coordinate;
+ol.geom.Geometry.prototype.closestPointXY = goog.abstractMethod;
/**
- * Add `delta` to `coordinate`. `coordinate` is modified in place and returned
- * by the function.
- *
- * Example:
- *
- * var coord = [7.85, 47.983333];
- * ol.coordinate.add(coord, [-2, 4]);
- * // coord is now [5.85, 51.983333]
- *
- * @param {ol.Coordinate} coordinate Coordinate.
- * @param {ol.Coordinate} delta Delta.
- * @return {ol.Coordinate} The input coordinate adjusted by the given delta.
+ * Return the closest point of the geometry to the passed point as
+ * {@link ol.Coordinate coordinate}.
+ * @param {ol.Coordinate} point Point.
+ * @param {ol.Coordinate=} opt_closestPoint Closest point.
+ * @return {ol.Coordinate} Closest point.
* @api stable
*/
-ol.coordinate.add = function(coordinate, delta) {
- coordinate[0] += delta[0];
- coordinate[1] += delta[1];
- return coordinate;
+ol.geom.Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) {
+ var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];
+ this.closestPointXY(point[0], point[1], closestPoint, Infinity);
+ return closestPoint;
};
/**
- * Calculates the point closest to the passed coordinate on the passed segment.
- * This is the foot of the perpendicular of the coordinate to the segment when
- * the foot is on the segment, or the closest segment coordinate when the foot
- * is outside the segment.
- *
- * @param {ol.Coordinate} coordinate The coordinate.
- * @param {Array.<ol.Coordinate>} segment The two coordinates of the segment.
- * @return {ol.Coordinate} The foot of the perpendicular of the coordinate to
- * the segment.
+ * @param {ol.Coordinate} coordinate Coordinate.
+ * @return {boolean} Contains coordinate.
*/
-ol.coordinate.closestOnSegment = function(coordinate, segment) {
- var x0 = coordinate[0];
- var y0 = coordinate[1];
- var start = segment[0];
- var end = segment[1];
- var x1 = start[0];
- var y1 = start[1];
- var x2 = end[0];
- var y2 = end[1];
- var dx = x2 - x1;
- var dy = y2 - y1;
- var along = (dx === 0 && dy === 0) ? 0 :
- ((dx * (x0 - x1)) + (dy * (y0 - y1))) / ((dx * dx + dy * dy) || 0);
- var x, y;
- if (along <= 0) {
- x = x1;
- y = y1;
- } else if (along >= 1) {
- x = x2;
- y = y2;
- } else {
- x = x1 + along * dx;
- y = y1 + along * dy;
- }
- return [x, y];
+ol.geom.Geometry.prototype.containsCoordinate = function(coordinate) {
+ return this.containsXY(coordinate[0], coordinate[1]);
};
/**
- * Returns a {@link ol.CoordinateFormatType} function that can be used to format
- * a {ol.Coordinate} to a string.
- *
- * Example without specifying the fractional digits:
- *
- * var coord = [7.85, 47.983333];
- * var stringifyFunc = ol.coordinate.createStringXY();
- * var out = stringifyFunc(coord);
- * // out is now '8, 48'
- *
- * Example with explicitly specifying 2 fractional digits:
- *
- * var coord = [7.85, 47.983333];
- * var stringifyFunc = ol.coordinate.createStringXY(2);
- * var out = stringifyFunc(coord);
- * // out is now '7.85, 47.98'
- *
- * @param {number=} opt_fractionDigits The number of digits to include
- * after the decimal point. Default is `0`.
- * @return {ol.CoordinateFormatType} Coordinate format.
- * @api stable
+ * @param {ol.Extent} extent Extent.
+ * @protected
+ * @return {ol.Extent} extent Extent.
*/
-ol.coordinate.createStringXY = function(opt_fractionDigits) {
- return (
- /**
- * @param {ol.Coordinate|undefined} coordinate Coordinate.
- * @return {string} String XY.
- */
- function(coordinate) {
- return ol.coordinate.toStringXY(coordinate, opt_fractionDigits);
- });
-};
+ol.geom.Geometry.prototype.computeExtent = goog.abstractMethod;
/**
- * @private
- * @param {number} degrees Degrees.
- * @param {string} hemispheres Hemispheres.
- * @return {string} String.
+ * @param {number} x X.
+ * @param {number} y Y.
+ * @return {boolean} Contains (x, y).
*/
-ol.coordinate.degreesToStringHDMS_ = function(degrees, hemispheres) {
- var normalizedDegrees = goog.math.modulo(degrees + 180, 360) - 180;
- var x = Math.abs(Math.round(3600 * normalizedDegrees));
- return Math.floor(x / 3600) + '\u00b0 ' +
- goog.string.padNumber(Math.floor((x / 60) % 60), 2) + '\u2032 ' +
- goog.string.padNumber(Math.floor(x % 60), 2) + '\u2033 ' +
- hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0);
-};
+ol.geom.Geometry.prototype.containsXY = ol.functions.FALSE;
/**
- * Transforms the given {@link ol.Coordinate} to a string using the given string
- * template. The strings `{x}` and `{y}` in the template will be replaced with
- * the first and second coordinate values respectively.
- *
- * Example without specifying the fractional digits:
- *
- * var coord = [7.85, 47.983333];
- * var template = 'Coordinate is ({x}|{y}).';
- * var out = ol.coordinate.format(coord, template);
- * // out is now 'Coordinate is (8|48).'
- *
- * Example explicitly specifying the fractional digits:
- *
- * var coord = [7.85, 47.983333];
- * var template = 'Coordinate is ({x}|{y}).';
- * var out = ol.coordinate.format(coord, template, 2);
- * // out is now 'Coordinate is (7.85|47.98).'
- *
- * @param {ol.Coordinate|undefined} coordinate Coordinate.
- * @param {string} template A template string with `{x}` and `{y}` placeholders
- * that will be replaced by first and second coordinate values.
- * @param {number=} opt_fractionDigits The number of digits to include
- * after the decimal point. Default is `0`.
- * @return {string} Formatted coordinate.
+ * Get the extent of the geometry.
+ * @param {ol.Extent=} opt_extent Extent.
+ * @return {ol.Extent} extent Extent.
* @api stable
*/
-ol.coordinate.format = function(coordinate, template, opt_fractionDigits) {
- if (coordinate) {
- return template
- .replace('{x}', coordinate[0].toFixed(opt_fractionDigits))
- .replace('{y}', coordinate[1].toFixed(opt_fractionDigits));
- } else {
- return '';
+ol.geom.Geometry.prototype.getExtent = function(opt_extent) {
+ if (this.extentRevision_ != this.getRevision()) {
+ this.extent_ = this.computeExtent(this.extent_);
+ this.extentRevision_ = this.getRevision();
}
+ return ol.extent.returnOrUpdate(this.extent_, opt_extent);
};
/**
- * @param {ol.Coordinate} coordinate1 First coordinate.
- * @param {ol.Coordinate} coordinate2 Second coordinate.
- * @return {boolean} Whether the passed coordinates are equal.
+ * Rotate the geometry around a given coordinate. This modifies the geometry
+ * coordinates in place.
+ * @param {number} angle Rotation angle in radians.
+ * @param {ol.Coordinate} anchor The rotation center.
+ * @api
+ * @function
*/
-ol.coordinate.equals = function(coordinate1, coordinate2) {
- var equals = true;
- for (var i = coordinate1.length - 1; i >= 0; --i) {
- if (coordinate1[i] != coordinate2[i]) {
- equals = false;
- break;
- }
- }
- return equals;
-};
+ol.geom.Geometry.prototype.rotate = goog.abstractMethod;
/**
- * Rotate `coordinate` by `angle`. `coordinate` is modified in place and
- * returned by the function.
- *
- * Example:
- *
- * var coord = [7.85, 47.983333];
- * var rotateRadians = Math.PI / 2; // 90 degrees
- * ol.coordinate.rotate(coord, rotateRadians);
- * // coord is now [-47.983333, 7.85]
- *
- * @param {ol.Coordinate} coordinate Coordinate.
- * @param {number} angle Angle in radian.
- * @return {ol.Coordinate} Coordinate.
- * @api stable
+ * Create a simplified version of this geometry. For linestrings, this uses
+ * the the {@link
+ * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
+ * Douglas Peucker} algorithm. For polygons, a quantization-based
+ * simplification is used to preserve topology.
+ * @function
+ * @param {number} tolerance The tolerance distance for simplification.
+ * @return {ol.geom.Geometry} A new, simplified version of the original
+ * geometry.
+ * @api
*/
-ol.coordinate.rotate = function(coordinate, angle) {
- var cosAngle = Math.cos(angle);
- var sinAngle = Math.sin(angle);
- var x = coordinate[0] * cosAngle - coordinate[1] * sinAngle;
- var y = coordinate[1] * cosAngle + coordinate[0] * sinAngle;
- coordinate[0] = x;
- coordinate[1] = y;
- return coordinate;
+ol.geom.Geometry.prototype.simplify = function(tolerance) {
+ return this.getSimplifiedGeometry(tolerance * tolerance);
};
/**
- * Scale `coordinate` by `scale`. `coordinate` is modified in place and returned
- * by the function.
- *
- * Example:
- *
- * var coord = [7.85, 47.983333];
- * var scale = 1.2;
- * ol.coordinate.scale(coord, scale);
- * // coord is now [9.42, 57.5799996]
- *
- * @param {ol.Coordinate} coordinate Coordinate.
- * @param {number} scale Scale factor.
- * @return {ol.Coordinate} Coordinate.
+ * Create a simplified version of this geometry using the Douglas Peucker
+ * algorithm.
+ * @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
+ * @function
+ * @param {number} squaredTolerance Squared tolerance.
+ * @return {ol.geom.Geometry} Simplified geometry.
*/
-ol.coordinate.scale = function(coordinate, scale) {
- coordinate[0] *= scale;
- coordinate[1] *= scale;
- return coordinate;
-};
+ol.geom.Geometry.prototype.getSimplifiedGeometry = goog.abstractMethod;
/**
- * Subtract `delta` to `coordinate`. `coordinate` is modified in place and
- * returned by the function.
- *
- * @param {ol.Coordinate} coordinate Coordinate.
- * @param {ol.Coordinate} delta Delta.
- * @return {ol.Coordinate} Coordinate.
+ * Get the type of this geometry.
+ * @function
+ * @return {ol.geom.GeometryType} Geometry type.
*/
-ol.coordinate.sub = function(coordinate, delta) {
- coordinate[0] -= delta[0];
- coordinate[1] -= delta[1];
- return coordinate;
-};
+ol.geom.Geometry.prototype.getType = goog.abstractMethod;
/**
- * @param {ol.Coordinate} coord1 First coordinate.
- * @param {ol.Coordinate} coord2 Second coordinate.
- * @return {number} Squared distance between coord1 and coord2.
+ * Apply a transform function to each coordinate of the geometry.
+ * The geometry is modified in place.
+ * If you do not want the geometry modified in place, first `clone()` it and
+ * then use this function on the clone.
+ * @function
+ * @param {ol.TransformFunction} transformFn Transform.
*/
-ol.coordinate.squaredDistance = function(coord1, coord2) {
- var dx = coord1[0] - coord2[0];
- var dy = coord1[1] - coord2[1];
- return dx * dx + dy * dy;
-};
+ol.geom.Geometry.prototype.applyTransform = goog.abstractMethod;
/**
- * Calculate the squared distance from a coordinate to a line segment.
- *
- * @param {ol.Coordinate} coordinate Coordinate of the point.
- * @param {Array.<ol.Coordinate>} segment Line segment (2 coordinates).
- * @return {number} Squared distance from the point to the line segment.
+ * Test if the geometry and the passed extent intersect.
+ * @param {ol.Extent} extent Extent.
+ * @return {boolean} `true` if the geometry and the extent intersect.
+ * @function
*/
-ol.coordinate.squaredDistanceToSegment = function(coordinate, segment) {
- return ol.coordinate.squaredDistance(coordinate,
- ol.coordinate.closestOnSegment(coordinate, segment));
-};
+ol.geom.Geometry.prototype.intersectsExtent = goog.abstractMethod;
/**
- * Format a geographic coordinate with the hemisphere, degrees, minutes, and
- * seconds.
- *
- * Example:
- *
- * var coord = [7.85, 47.983333];
- * var out = ol.coordinate.toStringHDMS(coord);
- * // out is now '47° 59′ 0″ N 7° 51′ 0″ E'
- *
- * @param {ol.Coordinate|undefined} coordinate Coordinate.
- * @return {string} Hemisphere, degrees, minutes and seconds.
- * @api stable
+ * Translate the geometry. This modifies the geometry coordinates in place. If
+ * instead you want a new geometry, first `clone()` this geometry.
+ * @param {number} deltaX Delta X.
+ * @param {number} deltaY Delta Y.
+ * @function
*/
-ol.coordinate.toStringHDMS = function(coordinate) {
- if (coordinate) {
- return ol.coordinate.degreesToStringHDMS_(coordinate[1], 'NS') + ' ' +
- ol.coordinate.degreesToStringHDMS_(coordinate[0], 'EW');
- } else {
- return '';
- }
-};
+ol.geom.Geometry.prototype.translate = goog.abstractMethod;
/**
- * Format a coordinate as a comma delimited string.
- *
- * Example without specifying fractional digits:
- *
- * var coord = [7.85, 47.983333];
- * var out = ol.coordinate.toStringXY(coord);
- * // out is now '8, 48'
- *
- * Example explicitly specifying 1 fractional digit:
- *
- * var coord = [7.85, 47.983333];
- * var out = ol.coordinate.toStringXY(coord, 1);
- * // out is now '7.8, 48.0'
+ * Transform each coordinate of the geometry from one coordinate reference
+ * system to another. The geometry is modified in place.
+ * For example, a line will be transformed to a line and a circle to a circle.
+ * If you do not want the geometry modified in place, first `clone()` it and
+ * then use this function on the clone.
*
- * @param {ol.Coordinate|undefined} coordinate Coordinate.
- * @param {number=} opt_fractionDigits The number of digits to include
- * after the decimal point. Default is `0`.
- * @return {string} XY.
+ * @param {ol.proj.ProjectionLike} source The current projection. Can be a
+ * string identifier or a {@link ol.proj.Projection} object.
+ * @param {ol.proj.ProjectionLike} destination The desired projection. Can be a
+ * string identifier or a {@link ol.proj.Projection} object.
+ * @return {ol.geom.Geometry} This geometry. Note that original geometry is
+ * modified in place.
* @api stable
*/
-ol.coordinate.toStringXY = function(coordinate, opt_fractionDigits) {
- return ol.coordinate.format(coordinate, '{x}, {y}', opt_fractionDigits);
-};
-
-
-/**
- * Create an ol.Coordinate from an Array and take into account axis order.
- *
- * Examples:
- *
- * var northCoord = ol.coordinate.fromProjectedArray([1, 2], 'n');
- * // northCoord is now [2, 1]
- *
- * var eastCoord = ol.coordinate.fromProjectedArray([1, 2], 'e');
- * // eastCoord is now [1, 2]
- *
- * @param {Array} array The array with coordinates.
- * @param {string} axis the axis info.
- * @return {ol.Coordinate} The coordinate created.
- */
-ol.coordinate.fromProjectedArray = function(array, axis) {
- var firstAxis = axis.charAt(0);
- if (firstAxis === 'n' || firstAxis === 's') {
- return [array[1], array[0]];
- } else {
- return array;
- }
+ol.geom.Geometry.prototype.transform = function(source, destination) {
+ goog.asserts.assert(
+ ol.proj.get(source).getUnits() !== ol.proj.Units.TILE_PIXELS &&
+ ol.proj.get(destination).getUnits() !== ol.proj.Units.TILE_PIXELS,
+ 'cannot transform geometries with TILE_PIXELS units');
+ this.applyTransform(ol.proj.getTransform(source, destination));
+ return this;
};
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
@@ -14149,6 +10034,7 @@ goog.provide('goog.vec.Float32Array');
* The length of the array, or an array to initialize the contents of the
* new Float32Array.
* @constructor
+ * @implements {IArrayLike<number>}
* @final
*/
goog.vec.Float32Array = function(p0) {
@@ -14212,14 +10098,18 @@ goog.vec.Float32Array.prototype.toString = Array.prototype.join;
* goog.vec.Float32Array as Float32Array.
*/
if (typeof Float32Array == 'undefined') {
- goog.exportProperty(goog.vec.Float32Array, 'BYTES_PER_ELEMENT',
- goog.vec.Float32Array.BYTES_PER_ELEMENT);
- goog.exportProperty(goog.vec.Float32Array.prototype, 'BYTES_PER_ELEMENT',
- goog.vec.Float32Array.prototype.BYTES_PER_ELEMENT);
- goog.exportProperty(goog.vec.Float32Array.prototype, 'set',
- goog.vec.Float32Array.prototype.set);
- goog.exportProperty(goog.vec.Float32Array.prototype, 'toString',
- goog.vec.Float32Array.prototype.toString);
+ goog.exportProperty(
+ goog.vec.Float32Array, 'BYTES_PER_ELEMENT',
+ goog.vec.Float32Array.BYTES_PER_ELEMENT);
+ goog.exportProperty(
+ goog.vec.Float32Array.prototype, 'BYTES_PER_ELEMENT',
+ goog.vec.Float32Array.prototype.BYTES_PER_ELEMENT);
+ goog.exportProperty(
+ goog.vec.Float32Array.prototype, 'set',
+ goog.vec.Float32Array.prototype.set);
+ goog.exportProperty(
+ goog.vec.Float32Array.prototype, 'toString',
+ goog.vec.Float32Array.prototype.toString);
goog.exportSymbol('Float32Array', goog.vec.Float32Array);
}
@@ -14261,6 +10151,7 @@ goog.provide('goog.vec.Float64Array');
* The length of the array, or an array to initialize the contents of the
* new Float64Array.
* @constructor
+ * @implements {IArrayLike<number>}
* @final
*/
goog.vec.Float64Array = function(p0) {
@@ -14325,20 +10216,24 @@ goog.vec.Float64Array.prototype.toString = Array.prototype.join;
*/
if (typeof Float64Array == 'undefined') {
try {
- goog.exportProperty(goog.vec.Float64Array, 'BYTES_PER_ELEMENT',
- goog.vec.Float64Array.BYTES_PER_ELEMENT);
+ goog.exportProperty(
+ goog.vec.Float64Array, 'BYTES_PER_ELEMENT',
+ goog.vec.Float64Array.BYTES_PER_ELEMENT);
} catch (float64ArrayError) {
// Do nothing. This code is in place to fix b/7225850, in which an error
// is incorrectly thrown for Google TV on an old Chrome.
// TODO(user): remove after that version is retired.
}
- goog.exportProperty(goog.vec.Float64Array.prototype, 'BYTES_PER_ELEMENT',
- goog.vec.Float64Array.prototype.BYTES_PER_ELEMENT);
- goog.exportProperty(goog.vec.Float64Array.prototype, 'set',
- goog.vec.Float64Array.prototype.set);
- goog.exportProperty(goog.vec.Float64Array.prototype, 'toString',
- goog.vec.Float64Array.prototype.toString);
+ goog.exportProperty(
+ goog.vec.Float64Array.prototype, 'BYTES_PER_ELEMENT',
+ goog.vec.Float64Array.prototype.BYTES_PER_ELEMENT);
+ goog.exportProperty(
+ goog.vec.Float64Array.prototype, 'set',
+ goog.vec.Float64Array.prototype.set);
+ goog.exportProperty(
+ goog.vec.Float64Array.prototype, 'toString',
+ goog.vec.Float64Array.prototype.toString);
goog.exportSymbol('Float64Array', goog.vec.Float64Array);
}
@@ -14499,7 +10394,7 @@ goog.vec.Vec3.create = function() {
/**
- * Creates a new 3 element FLoat32 vector initialized with the value from the
+ * Creates a new 3 element Float32 vector initialized with the value from the
* given array.
*
* @param {goog.vec.Vec3.AnyType} vec The source 3 element array.
@@ -14955,8 +10850,8 @@ goog.vec.Vec3.min = function(vec0, limit, resultVec) {
* @return {boolean} True if the vectors are equal, false otherwise.
*/
goog.vec.Vec3.equals = function(v0, v1) {
- return v0.length == v1.length &&
- v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2];
+ return v0.length == v1.length && v0[0] == v1[0] && v0[1] == v1[1] &&
+ v0[2] == v1[2];
};
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
@@ -15435,8 +11330,8 @@ goog.vec.Vec4.min = function(vec0, limit, resultVec) {
* @return {boolean} True if the vectors are equal, false otherwise.
*/
goog.vec.Vec4.equals = function(v0, v1) {
- return v0.length == v1.length &&
- v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2] && v0[3] == v1[3];
+ return v0.length == v1.length && v0[0] == v1[0] && v0[1] == v1[1] &&
+ v0[2] == v1[2] && v0[3] == v1[3];
};
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
@@ -15512,11 +11407,8 @@ goog.vec.Mat4.createFloat64 = function() {
*/
goog.vec.Mat4.createNumber = function() {
var a = new Array(16);
- goog.vec.Mat4.setFromValues(a,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0);
+ goog.vec.Mat4.setFromValues(
+ a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
return a;
};
@@ -15565,11 +11457,8 @@ goog.vec.Mat4.createFloat64Identity = function() {
*/
goog.vec.Mat4.createNumberIdentity = function() {
var a = new Array(16);
- goog.vec.Mat4.setFromValues(a,
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1);
+ goog.vec.Mat4.setFromValues(
+ a, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
return a;
};
@@ -15622,10 +11511,8 @@ goog.vec.Mat4.createFloat32FromArray = function(matrix) {
* @return {!goog.vec.Mat4.Float32} The new, 16 element array.
*/
goog.vec.Mat4.createFloat32FromValues = function(
- v00, v10, v20, v30,
- v01, v11, v21, v31,
- v02, v12, v22, v32,
- v03, v13, v23, v33) {
+ v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32, v03, v13, v23,
+ v33) {
var newMatrix = goog.vec.Mat4.createFloat32();
goog.vec.Mat4.setFromValues(
newMatrix, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
@@ -15679,10 +11566,8 @@ goog.vec.Mat4.createFloat64FromArray = function(matrix) {
* @return {!goog.vec.Mat4.Float64} The new, 16 element array.
*/
goog.vec.Mat4.createFloat64FromValues = function(
- v00, v10, v20, v30,
- v01, v11, v21, v31,
- v02, v12, v22, v32,
- v03, v13, v23, v33) {
+ v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32, v03, v13, v23,
+ v33) {
var newMatrix = goog.vec.Mat4.createFloat64();
goog.vec.Mat4.setFromValues(
newMatrix, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
@@ -15738,13 +11623,11 @@ goog.vec.Mat4.createFromArray = function(matrix) {
* @return {!goog.vec.Mat4.Type} The new, 16 element array.
*/
goog.vec.Mat4.createFromValues = function(
- v00, v10, v20, v30,
- v01, v11, v21, v31,
- v02, v12, v22, v32,
- v03, v13, v23, v33) {
+ v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32, v03, v13, v23,
+ v33) {
return goog.vec.Mat4.createFloat32FromValues(
- v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
- v03, v13, v23, v33);
+ v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32, v03, v13, v23,
+ v33);
};
@@ -15814,8 +11697,8 @@ goog.vec.Mat4.setElement = function(mat, row, column, value) {
* chained together.
*/
goog.vec.Mat4.setFromValues = function(
- mat, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
- v03, v13, v23, v33) {
+ mat, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32, v03, v13,
+ v23, v33) {
mat[0] = v00;
mat[1] = v10;
mat[2] = v20;
@@ -16495,23 +12378,12 @@ goog.vec.Mat4.invert = function(mat, resultMat) {
* @return {boolean} True if the the two matrices are equivalent.
*/
goog.vec.Mat4.equals = function(mat0, mat1) {
- return mat0.length == mat1.length &&
- mat0[0] == mat1[0] &&
- mat0[1] == mat1[1] &&
- mat0[2] == mat1[2] &&
- mat0[3] == mat1[3] &&
- mat0[4] == mat1[4] &&
- mat0[5] == mat1[5] &&
- mat0[6] == mat1[6] &&
- mat0[7] == mat1[7] &&
- mat0[8] == mat1[8] &&
- mat0[9] == mat1[9] &&
- mat0[10] == mat1[10] &&
- mat0[11] == mat1[11] &&
- mat0[12] == mat1[12] &&
- mat0[13] == mat1[13] &&
- mat0[14] == mat1[14] &&
- mat0[15] == mat1[15];
+ return mat0.length == mat1.length && mat0[0] == mat1[0] &&
+ mat0[1] == mat1[1] && mat0[2] == mat1[2] && mat0[3] == mat1[3] &&
+ mat0[4] == mat1[4] && mat0[5] == mat1[5] && mat0[6] == mat1[6] &&
+ mat0[7] == mat1[7] && mat0[8] == mat1[8] && mat0[9] == mat1[9] &&
+ mat0[10] == mat1[10] && mat0[11] == mat1[11] && mat0[12] == mat1[12] &&
+ mat0[13] == mat1[13] && mat0[14] == mat1[14] && mat0[15] == mat1[15];
};
@@ -16652,21 +12524,12 @@ goog.vec.Mat4.makeRotate = function(mat, angle, ax, ay, az) {
var d = 1 - c;
var s = Math.sin(angle);
- return goog.vec.Mat4.setFromValues(mat,
- ax * ax * d + c,
- ax * ay * d + az * s,
- ax * az * d - ay * s,
- 0,
+ return goog.vec.Mat4.setFromValues(
+ mat, ax * ax * d + c, ax * ay * d + az * s, ax * az * d - ay * s, 0,
- ax * ay * d - az * s,
- ay * ay * d + c,
- ay * az * d + ax * s,
- 0,
+ ax * ay * d - az * s, ay * ay * d + c, ay * az * d + ax * s, 0,
- ax * az * d + ay * s,
- ay * az * d - ax * s,
- az * az * d + c,
- 0,
+ ax * az * d + ay * s, ay * az * d - ax * s, az * az * d + c, 0,
0, 0, 0, 1);
};
@@ -16744,12 +12607,8 @@ goog.vec.Mat4.makeFrustum = function(mat, left, right, bottom, top, near, far) {
var c = -(far + near) / (far - near);
var d = -(2 * far * near) / (far - near);
- return goog.vec.Mat4.setFromValues(mat,
- x, 0, 0, 0,
- 0, y, 0, 0,
- a, b, c, -1,
- 0, 0, d, 0
- );
+ return goog.vec.Mat4.setFromValues(
+ mat, x, 0, 0, 0, 0, y, 0, 0, a, b, c, -1, 0, 0, d, 0);
};
@@ -16775,12 +12634,9 @@ goog.vec.Mat4.makePerspective = function(mat, fovy, aspect, near, far) {
}
var cot = Math.cos(angle) / sinAngle;
- return goog.vec.Mat4.setFromValues(mat,
- cot / aspect, 0, 0, 0,
- 0, cot, 0, 0,
- 0, 0, -(far + near) / dz, -1,
- 0, 0, -(2 * near * far) / dz, 0
- );
+ return goog.vec.Mat4.setFromValues(
+ mat, cot / aspect, 0, 0, 0, 0, cot, 0, 0, 0, 0, -(far + near) / dz, -1, 0,
+ 0, -(2 * near * far) / dz, 0);
};
@@ -16805,12 +12661,8 @@ goog.vec.Mat4.makeOrtho = function(mat, left, right, bottom, top, near, far) {
var b = -(top + bottom) / (top - bottom);
var c = -(far + near) / (far - near);
- return goog.vec.Mat4.setFromValues(mat,
- x, 0, 0, 0,
- 0, y, 0, 0,
- 0, 0, z, 0,
- a, b, c, 1
- );
+ return goog.vec.Mat4.setFromValues(
+ mat, x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, a, b, c, 1);
};
@@ -16854,8 +12706,7 @@ goog.vec.Mat4.makeLookAt = function(mat, eyePt, centerPt, worldUpVec) {
goog.vec.Mat4.setRow(mat, 1, upVec);
goog.vec.Mat4.setRow(mat, 2, fwdVec);
goog.vec.Mat4.setRowValues(mat, 3, 0, 0, 0, 1);
- goog.vec.Mat4.translate(
- mat, -eyePt[0], -eyePt[1], -eyePt[2]);
+ goog.vec.Mat4.translate(mat, -eyePt[0], -eyePt[1], -eyePt[2]);
return mat;
};
@@ -17008,8 +12859,8 @@ goog.vec.Mat4.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
// For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
// signTheta2.
- euler[1] = ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) *
- signTheta2;
+ euler[1] =
+ ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) * signTheta2;
return euler;
};
@@ -17031,8 +12882,7 @@ goog.vec.Mat4.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
*/
goog.vec.Mat4.translate = function(mat, x, y, z) {
return goog.vec.Mat4.setColumnValues(
- mat, 3,
- mat[0] * x + mat[4] * y + mat[8] * z + mat[12],
+ mat, 3, mat[0] * x + mat[4] * y + mat[8] * z + mat[12],
mat[1] * x + mat[5] * y + mat[9] * z + mat[13],
mat[2] * x + mat[6] * y + mat[10] * z + mat[14],
mat[3] * x + mat[7] * y + mat[11] * z + mat[15]);
@@ -17055,11 +12905,9 @@ goog.vec.Mat4.translate = function(mat, x, y, z) {
*/
goog.vec.Mat4.scale = function(mat, x, y, z) {
return goog.vec.Mat4.setFromValues(
- mat,
- mat[0] * x, mat[1] * x, mat[2] * x, mat[3] * x,
- mat[4] * y, mat[5] * y, mat[6] * y, mat[7] * y,
- mat[8] * z, mat[9] * z, mat[10] * z, mat[11] * z,
- mat[12], mat[13], mat[14], mat[15]);
+ mat, mat[0] * x, mat[1] * x, mat[2] * x, mat[3] * x, mat[4] * y,
+ mat[5] * y, mat[6] * y, mat[7] * y, mat[8] * z, mat[9] * z, mat[10] * z,
+ mat[11] * z, mat[12], mat[13], mat[14], mat[15]);
};
@@ -17100,21 +12948,14 @@ goog.vec.Mat4.rotate = function(mat, angle, x, y, z) {
var r22 = z * z * diffCosAngle + cosAngle;
return goog.vec.Mat4.setFromValues(
- mat,
- m00 * r00 + m01 * r10 + m02 * r20,
- m10 * r00 + m11 * r10 + m12 * r20,
- m20 * r00 + m21 * r10 + m22 * r20,
- m30 * r00 + m31 * r10 + m32 * r20,
-
- m00 * r01 + m01 * r11 + m02 * r21,
- m10 * r01 + m11 * r11 + m12 * r21,
- m20 * r01 + m21 * r11 + m22 * r21,
- m30 * r01 + m31 * r11 + m32 * r21,
-
- m00 * r02 + m01 * r12 + m02 * r22,
- m10 * r02 + m11 * r12 + m12 * r22,
- m20 * r02 + m21 * r12 + m22 * r22,
- m30 * r02 + m31 * r12 + m32 * r22,
+ mat, m00 * r00 + m01 * r10 + m02 * r20, m10 * r00 + m11 * r10 + m12 * r20,
+ m20 * r00 + m21 * r10 + m22 * r20, m30 * r00 + m31 * r10 + m32 * r20,
+
+ m00 * r01 + m01 * r11 + m02 * r21, m10 * r01 + m11 * r11 + m12 * r21,
+ m20 * r01 + m21 * r11 + m22 * r21, m30 * r01 + m31 * r11 + m32 * r21,
+
+ m00 * r02 + m01 * r12 + m02 * r22, m10 * r02 + m11 * r12 + m12 * r22,
+ m20 * r02 + m21 * r12 + m22 * r22, m30 * r02 + m31 * r12 + m32 * r22,
m03, m13, m23, m33);
};
@@ -17237,10 +13078,8 @@ goog.vec.Mat4.getTranslation = function(mat, translation) {
* @type {!Array<!goog.vec.Vec3.Type>}
* @private
*/
-goog.vec.Mat4.tmpVec3_ = [
- goog.vec.Vec3.createFloat64(),
- goog.vec.Vec3.createFloat64()
-];
+goog.vec.Mat4.tmpVec3_ =
+ [goog.vec.Vec3.createFloat64(), goog.vec.Vec3.createFloat64()];
/**
@@ -17248,8 +13087,7 @@ goog.vec.Mat4.tmpVec3_ = [
* @private
*/
goog.vec.Mat4.tmpVec4_ = [
- goog.vec.Vec4.createFloat64(),
- goog.vec.Vec4.createFloat64(),
+ goog.vec.Vec4.createFloat64(), goog.vec.Vec4.createFloat64(),
goog.vec.Vec4.createFloat64()
];
@@ -17258,2610 +13096,70 @@ goog.vec.Mat4.tmpVec4_ = [
* @type {!Array<!goog.vec.Mat4.Type>}
* @private
*/
-goog.vec.Mat4.tmpMat4_ = [
- goog.vec.Mat4.createFloat64()
-];
-
-goog.provide('ol.TransformFunction');
-
+goog.vec.Mat4.tmpMat4_ = [goog.vec.Mat4.createFloat64()];
-/**
- * A transform function accepts an array of input coordinate values, an optional
- * output array, and an optional dimension (default should be 2). The function
- * transforms the input coordinate values, populates the output array, and
- * returns the output array.
- *
- * @typedef {function(Array.<number>, Array.<number>=, number=): Array.<number>}
- * @api stable
- */
-ol.TransformFunction;
-
-goog.provide('ol.Extent');
-goog.provide('ol.extent');
-goog.provide('ol.extent.Corner');
-goog.provide('ol.extent.Relationship');
+goog.provide('ol.geom.flat.transform');
-goog.require('goog.asserts');
goog.require('goog.vec.Mat4');
-goog.require('ol.Coordinate');
-goog.require('ol.Size');
-goog.require('ol.TransformFunction');
-
-
-/**
- * An array of numbers representing an extent: `[minx, miny, maxx, maxy]`.
- * @typedef {Array.<number>}
- * @api stable
- */
-ol.Extent;
-
-
-/**
- * Extent corner.
- * @enum {string}
- */
-ol.extent.Corner = {
- BOTTOM_LEFT: 'bottom-left',
- BOTTOM_RIGHT: 'bottom-right',
- TOP_LEFT: 'top-left',
- TOP_RIGHT: 'top-right'
-};
-
-
-/**
- * Relationship to an extent.
- * @enum {number}
- */
-ol.extent.Relationship = {
- UNKNOWN: 0,
- INTERSECTING: 1,
- ABOVE: 2,
- RIGHT: 4,
- BELOW: 8,
- LEFT: 16
-};
-
-
-/**
- * Build an extent that includes all given coordinates.
- *
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @return {ol.Extent} Bounding extent.
- * @api stable
- */
-ol.extent.boundingExtent = function(coordinates) {
- var extent = ol.extent.createEmpty();
- for (var i = 0, ii = coordinates.length; i < ii; ++i) {
- ol.extent.extendCoordinate(extent, coordinates[i]);
- }
- return extent;
-};
-
-
-/**
- * @param {Array.<number>} xs Xs.
- * @param {Array.<number>} ys Ys.
- * @param {ol.Extent=} opt_extent Destination extent.
- * @private
- * @return {ol.Extent} Extent.
- */
-ol.extent.boundingExtentXYs_ = function(xs, ys, opt_extent) {
- goog.asserts.assert(xs.length > 0, 'xs length should be larger than 0');
- goog.asserts.assert(ys.length > 0, 'ys length should be larger than 0');
- var minX = Math.min.apply(null, xs);
- var minY = Math.min.apply(null, ys);
- var maxX = Math.max.apply(null, xs);
- var maxY = Math.max.apply(null, ys);
- return ol.extent.createOrUpdate(minX, minY, maxX, maxY, opt_extent);
-};
-
-
-/**
- * Return extent increased by the provided value.
- * @param {ol.Extent} extent Extent.
- * @param {number} value The amount by which the extent should be buffered.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- * @api stable
- */
-ol.extent.buffer = function(extent, value, opt_extent) {
- if (opt_extent) {
- opt_extent[0] = extent[0] - value;
- opt_extent[1] = extent[1] - value;
- opt_extent[2] = extent[2] + value;
- opt_extent[3] = extent[3] + value;
- return opt_extent;
- } else {
- return [
- extent[0] - value,
- extent[1] - value,
- extent[2] + value,
- extent[3] + value
- ];
- }
-};
-
-
-/**
- * Creates a clone of an extent.
- *
- * @param {ol.Extent} extent Extent to clone.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} The clone.
- */
-ol.extent.clone = function(extent, opt_extent) {
- if (opt_extent) {
- opt_extent[0] = extent[0];
- opt_extent[1] = extent[1];
- opt_extent[2] = extent[2];
- opt_extent[3] = extent[3];
- return opt_extent;
- } else {
- return extent.slice();
- }
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {number} x X.
- * @param {number} y Y.
- * @return {number} Closest squared distance.
- */
-ol.extent.closestSquaredDistanceXY = function(extent, x, y) {
- var dx, dy;
- if (x < extent[0]) {
- dx = extent[0] - x;
- } else if (extent[2] < x) {
- dx = x - extent[2];
- } else {
- dx = 0;
- }
- if (y < extent[1]) {
- dy = extent[1] - y;
- } else if (extent[3] < y) {
- dy = y - extent[3];
- } else {
- dy = 0;
- }
- return dx * dx + dy * dy;
-};
-
-
-/**
- * Check if the passed coordinate is contained or on the edge of the extent.
- *
- * @param {ol.Extent} extent Extent.
- * @param {ol.Coordinate} coordinate Coordinate.
- * @return {boolean} The coordinate is contained in the extent.
- * @api stable
- */
-ol.extent.containsCoordinate = function(extent, coordinate) {
- return ol.extent.containsXY(extent, coordinate[0], coordinate[1]);
-};
-
-
-/**
- * Check if one extent contains another.
- *
- * An extent is deemed contained if it lies completely within the other extent,
- * including if they share one or more edges.
- *
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {boolean} The second extent is contained by or on the edge of the
- * first.
- * @api stable
- */
-ol.extent.containsExtent = function(extent1, extent2) {
- return extent1[0] <= extent2[0] && extent2[2] <= extent1[2] &&
- extent1[1] <= extent2[1] && extent2[3] <= extent1[3];
-};
-
-
-/**
- * Check if the passed coordinate is contained or on the edge of the extent.
- *
- * @param {ol.Extent} extent Extent.
- * @param {number} x X coordinate.
- * @param {number} y Y coordinate.
- * @return {boolean} The x, y values are contained in the extent.
- * @api stable
- */
-ol.extent.containsXY = function(extent, x, y) {
- return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];
-};
-
-
-/**
- * Get the relationship between a coordinate and extent.
- * @param {ol.Extent} extent The extent.
- * @param {ol.Coordinate} coordinate The coordinate.
- * @return {number} The relationship (bitwise compare with
- * ol.extent.Relationship).
- */
-ol.extent.coordinateRelationship = function(extent, coordinate) {
- var minX = extent[0];
- var minY = extent[1];
- var maxX = extent[2];
- var maxY = extent[3];
- var x = coordinate[0];
- var y = coordinate[1];
- var relationship = ol.extent.Relationship.UNKNOWN;
- if (x < minX) {
- relationship = relationship | ol.extent.Relationship.LEFT;
- } else if (x > maxX) {
- relationship = relationship | ol.extent.Relationship.RIGHT;
- }
- if (y < minY) {
- relationship = relationship | ol.extent.Relationship.BELOW;
- } else if (y > maxY) {
- relationship = relationship | ol.extent.Relationship.ABOVE;
- }
- if (relationship === ol.extent.Relationship.UNKNOWN) {
- relationship = ol.extent.Relationship.INTERSECTING;
- }
- return relationship;
-};
-
-
-/**
- * Create an empty extent.
- * @return {ol.Extent} Empty extent.
- * @api stable
- */
-ol.extent.createEmpty = function() {
- return [Infinity, Infinity, -Infinity, -Infinity];
-};
-
-
-/**
- * Create a new extent or update the provided extent.
- * @param {number} minX Minimum X.
- * @param {number} minY Minimum Y.
- * @param {number} maxX Maximum X.
- * @param {number} maxY Maximum Y.
- * @param {ol.Extent=} opt_extent Destination extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.createOrUpdate = function(minX, minY, maxX, maxY, opt_extent) {
- if (opt_extent) {
- opt_extent[0] = minX;
- opt_extent[1] = minY;
- opt_extent[2] = maxX;
- opt_extent[3] = maxY;
- return opt_extent;
- } else {
- return [minX, minY, maxX, maxY];
- }
-};
-
-
-/**
- * Create a new empty extent or make the provided one empty.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.createOrUpdateEmpty = function(opt_extent) {
- return ol.extent.createOrUpdate(
- Infinity, Infinity, -Infinity, -Infinity, opt_extent);
-};
-
-
-/**
- * @param {ol.Coordinate} coordinate Coordinate.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.createOrUpdateFromCoordinate = function(coordinate, opt_extent) {
- var x = coordinate[0];
- var y = coordinate[1];
- return ol.extent.createOrUpdate(x, y, x, y, opt_extent);
-};
-
-
-/**
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.createOrUpdateFromCoordinates = function(coordinates, opt_extent) {
- var extent = ol.extent.createOrUpdateEmpty(opt_extent);
- return ol.extent.extendCoordinates(extent, coordinates);
-};
-
-
-/**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.createOrUpdateFromFlatCoordinates =
- function(flatCoordinates, offset, end, stride, opt_extent) {
- var extent = ol.extent.createOrUpdateEmpty(opt_extent);
- return ol.extent.extendFlatCoordinates(
- extent, flatCoordinates, offset, end, stride);
-};
-
-
-/**
- * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.createOrUpdateFromRings = function(rings, opt_extent) {
- var extent = ol.extent.createOrUpdateEmpty(opt_extent);
- return ol.extent.extendRings(extent, rings);
-};
-
-
-/**
- * Empty an extent in place.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.empty = function(extent) {
- extent[0] = extent[1] = Infinity;
- extent[2] = extent[3] = -Infinity;
- return extent;
-};
-
-
-/**
- * Determine if two extents are equivalent.
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {boolean} The two extents are equivalent.
- * @api stable
- */
-ol.extent.equals = function(extent1, extent2) {
- return extent1[0] == extent2[0] && extent1[2] == extent2[2] &&
- extent1[1] == extent2[1] && extent1[3] == extent2[3];
-};
-
-
-/**
- * Modify an extent to include another extent.
- * @param {ol.Extent} extent1 The extent to be modified.
- * @param {ol.Extent} extent2 The extent that will be included in the first.
- * @return {ol.Extent} A reference to the first (extended) extent.
- * @api stable
- */
-ol.extent.extend = function(extent1, extent2) {
- if (extent2[0] < extent1[0]) {
- extent1[0] = extent2[0];
- }
- if (extent2[2] > extent1[2]) {
- extent1[2] = extent2[2];
- }
- if (extent2[1] < extent1[1]) {
- extent1[1] = extent2[1];
- }
- if (extent2[3] > extent1[3]) {
- extent1[3] = extent2[3];
- }
- return extent1;
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {ol.Coordinate} coordinate Coordinate.
- */
-ol.extent.extendCoordinate = function(extent, coordinate) {
- if (coordinate[0] < extent[0]) {
- extent[0] = coordinate[0];
- }
- if (coordinate[0] > extent[2]) {
- extent[2] = coordinate[0];
- }
- if (coordinate[1] < extent[1]) {
- extent[1] = coordinate[1];
- }
- if (coordinate[1] > extent[3]) {
- extent[3] = coordinate[1];
- }
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @return {ol.Extent} Extent.
- */
-ol.extent.extendCoordinates = function(extent, coordinates) {
- var i, ii;
- for (i = 0, ii = coordinates.length; i < ii; ++i) {
- ol.extent.extendCoordinate(extent, coordinates[i]);
- }
- return extent;
-};
/**
- * @param {ol.Extent} extent Extent.
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {number} end End.
* @param {number} stride Stride.
- * @return {ol.Extent} Extent.
- */
-ol.extent.extendFlatCoordinates =
- function(extent, flatCoordinates, offset, end, stride) {
- for (; offset < end; offset += stride) {
- ol.extent.extendXY(
- extent, flatCoordinates[offset], flatCoordinates[offset + 1]);
- }
- return extent;
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
- * @return {ol.Extent} Extent.
- */
-ol.extent.extendRings = function(extent, rings) {
- var i, ii;
- for (i = 0, ii = rings.length; i < ii; ++i) {
- ol.extent.extendCoordinates(extent, rings[i]);
- }
- return extent;
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {number} x X.
- * @param {number} y Y.
- */
-ol.extent.extendXY = function(extent, x, y) {
- extent[0] = Math.min(extent[0], x);
- extent[1] = Math.min(extent[1], y);
- extent[2] = Math.max(extent[2], x);
- extent[3] = Math.max(extent[3], y);
-};
-
-
-/**
- * This function calls `callback` for each corner of the extent. If the
- * callback returns a truthy value the function returns that value
- * immediately. Otherwise the function returns `false`.
- * @param {ol.Extent} extent Extent.
- * @param {function(this:T, ol.Coordinate): S} callback Callback.
- * @param {T=} opt_this Value to use as `this` when executing `callback`.
- * @return {S|boolean} Value.
- * @template S, T
- */
-ol.extent.forEachCorner = function(extent, callback, opt_this) {
- var val;
- val = callback.call(opt_this, ol.extent.getBottomLeft(extent));
- if (val) {
- return val;
- }
- val = callback.call(opt_this, ol.extent.getBottomRight(extent));
- if (val) {
- return val;
- }
- val = callback.call(opt_this, ol.extent.getTopRight(extent));
- if (val) {
- return val;
- }
- val = callback.call(opt_this, ol.extent.getTopLeft(extent));
- if (val) {
- return val;
- }
- return false;
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @return {number} Area.
- */
-ol.extent.getArea = function(extent) {
- var area = 0;
- if (!ol.extent.isEmpty(extent)) {
- area = ol.extent.getWidth(extent) * ol.extent.getHeight(extent);
- }
- return area;
-};
-
-
-/**
- * Get the bottom left coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Bottom left coordinate.
- * @api stable
- */
-ol.extent.getBottomLeft = function(extent) {
- return [extent[0], extent[1]];
-};
-
-
-/**
- * Get the bottom right coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Bottom right coordinate.
- * @api stable
- */
-ol.extent.getBottomRight = function(extent) {
- return [extent[2], extent[1]];
-};
-
-
-/**
- * Get the center coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Center.
- * @api stable
- */
-ol.extent.getCenter = function(extent) {
- return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2];
-};
-
-
-/**
- * Get a corner coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @param {ol.extent.Corner} corner Corner.
- * @return {ol.Coordinate} Corner coordinate.
- */
-ol.extent.getCorner = function(extent, corner) {
- var coordinate;
- if (corner === ol.extent.Corner.BOTTOM_LEFT) {
- coordinate = ol.extent.getBottomLeft(extent);
- } else if (corner === ol.extent.Corner.BOTTOM_RIGHT) {
- coordinate = ol.extent.getBottomRight(extent);
- } else if (corner === ol.extent.Corner.TOP_LEFT) {
- coordinate = ol.extent.getTopLeft(extent);
- } else if (corner === ol.extent.Corner.TOP_RIGHT) {
- coordinate = ol.extent.getTopRight(extent);
- } else {
- goog.asserts.fail('Invalid corner: %s', corner);
- }
- goog.asserts.assert(coordinate, 'coordinate should be defined');
- return coordinate;
-};
-
-
-/**
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {number} Enlarged area.
- */
-ol.extent.getEnlargedArea = function(extent1, extent2) {
- var minX = Math.min(extent1[0], extent2[0]);
- var minY = Math.min(extent1[1], extent2[1]);
- var maxX = Math.max(extent1[2], extent2[2]);
- var maxY = Math.max(extent1[3], extent2[3]);
- return (maxX - minX) * (maxY - minY);
-};
-
-
-/**
- * @param {ol.Coordinate} center Center.
- * @param {number} resolution Resolution.
- * @param {number} rotation Rotation.
- * @param {ol.Size} size Size.
- * @param {ol.Extent=} opt_extent Destination extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.getForViewAndSize =
- function(center, resolution, rotation, size, opt_extent) {
- var dx = resolution * size[0] / 2;
- var dy = resolution * size[1] / 2;
- var cosRotation = Math.cos(rotation);
- var sinRotation = Math.sin(rotation);
- /** @type {Array.<number>} */
- var xs = [-dx, -dx, dx, dx];
- /** @type {Array.<number>} */
- var ys = [-dy, dy, -dy, dy];
- var i, x, y;
- for (i = 0; i < 4; ++i) {
- x = xs[i];
- y = ys[i];
- xs[i] = center[0] + x * cosRotation - y * sinRotation;
- ys[i] = center[1] + x * sinRotation + y * cosRotation;
- }
- return ol.extent.boundingExtentXYs_(xs, ys, opt_extent);
-};
-
-
-/**
- * Get the height of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {number} Height.
- * @api stable
- */
-ol.extent.getHeight = function(extent) {
- return extent[3] - extent[1];
-};
-
-
-/**
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {number} Intersection area.
- */
-ol.extent.getIntersectionArea = function(extent1, extent2) {
- var intersection = ol.extent.getIntersection(extent1, extent2);
- return ol.extent.getArea(intersection);
-};
-
-
-/**
- * Get the intersection of two extents.
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @param {ol.Extent=} opt_extent Optional extent to populate with intersection.
- * @return {ol.Extent} Intersecting extent.
- * @api stable
- */
-ol.extent.getIntersection = function(extent1, extent2, opt_extent) {
- var intersection = opt_extent ? opt_extent : ol.extent.createEmpty();
- if (ol.extent.intersects(extent1, extent2)) {
- if (extent1[0] > extent2[0]) {
- intersection[0] = extent1[0];
- } else {
- intersection[0] = extent2[0];
- }
- if (extent1[1] > extent2[1]) {
- intersection[1] = extent1[1];
- } else {
- intersection[1] = extent2[1];
- }
- if (extent1[2] < extent2[2]) {
- intersection[2] = extent1[2];
- } else {
- intersection[2] = extent2[2];
- }
- if (extent1[3] < extent2[3]) {
- intersection[3] = extent1[3];
- } else {
- intersection[3] = extent2[3];
- }
- }
- return intersection;
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @return {number} Margin.
- */
-ol.extent.getMargin = function(extent) {
- return ol.extent.getWidth(extent) + ol.extent.getHeight(extent);
-};
-
-
-/**
- * Get the size (width, height) of an extent.
- * @param {ol.Extent} extent The extent.
- * @return {ol.Size} The extent size.
- * @api stable
- */
-ol.extent.getSize = function(extent) {
- return [extent[2] - extent[0], extent[3] - extent[1]];
-};
-
-
-/**
- * Get the top left coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Top left coordinate.
- * @api stable
- */
-ol.extent.getTopLeft = function(extent) {
- return [extent[0], extent[3]];
-};
-
-
-/**
- * Get the top right coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Top right coordinate.
- * @api stable
- */
-ol.extent.getTopRight = function(extent) {
- return [extent[2], extent[3]];
-};
-
-
-/**
- * Get the width of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {number} Width.
- * @api stable
- */
-ol.extent.getWidth = function(extent) {
- return extent[2] - extent[0];
-};
-
-
-/**
- * Determine if one extent intersects another.
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent.
- * @return {boolean} The two extents intersect.
- * @api stable
- */
-ol.extent.intersects = function(extent1, extent2) {
- return extent1[0] <= extent2[2] &&
- extent1[2] >= extent2[0] &&
- extent1[1] <= extent2[3] &&
- extent1[3] >= extent2[1];
-};
-
-
-/**
- * Determine if an extent is empty.
- * @param {ol.Extent} extent Extent.
- * @return {boolean} Is empty.
- * @api stable
- */
-ol.extent.isEmpty = function(extent) {
- return extent[2] < extent[0] || extent[3] < extent[1];
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @return {boolean} Is infinite.
- */
-ol.extent.isInfinite = function(extent) {
- return extent[0] == -Infinity || extent[1] == -Infinity ||
- extent[2] == Infinity || extent[3] == Infinity;
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {ol.Coordinate} coordinate Coordinate.
- * @return {ol.Coordinate} Coordinate.
- */
-ol.extent.normalize = function(extent, coordinate) {
- return [
- (coordinate[0] - extent[0]) / (extent[2] - extent[0]),
- (coordinate[1] - extent[1]) / (extent[3] - extent[1])
- ];
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
-ol.extent.returnOrUpdate = function(extent, opt_extent) {
- if (opt_extent) {
- opt_extent[0] = extent[0];
- opt_extent[1] = extent[1];
- opt_extent[2] = extent[2];
- opt_extent[3] = extent[3];
- return opt_extent;
- } else {
- return extent;
- }
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {number} value Value.
- */
-ol.extent.scaleFromCenter = function(extent, value) {
- var deltaX = ((extent[2] - extent[0]) / 2) * (value - 1);
- var deltaY = ((extent[3] - extent[1]) / 2) * (value - 1);
- extent[0] -= deltaX;
- extent[2] += deltaX;
- extent[1] -= deltaY;
- extent[3] += deltaY;
-};
-
-
-/**
- * Determine if the segment between two coordinates intersects (crosses,
- * touches, or is contained by) the provided extent.
- * @param {ol.Extent} extent The extent.
- * @param {ol.Coordinate} start Segment start coordinate.
- * @param {ol.Coordinate} end Segment end coordinate.
- * @return {boolean} The segment intersects the extent.
- */
-ol.extent.intersectsSegment = function(extent, start, end) {
- var intersects = false;
- var startRel = ol.extent.coordinateRelationship(extent, start);
- var endRel = ol.extent.coordinateRelationship(extent, end);
- if (startRel === ol.extent.Relationship.INTERSECTING ||
- endRel === ol.extent.Relationship.INTERSECTING) {
- intersects = true;
- } else {
- var minX = extent[0];
- var minY = extent[1];
- var maxX = extent[2];
- var maxY = extent[3];
- var startX = start[0];
- var startY = start[1];
- var endX = end[0];
- var endY = end[1];
- var slope = (endY - startY) / (endX - startX);
- var x, y;
- if (!!(endRel & ol.extent.Relationship.ABOVE) &&
- !(startRel & ol.extent.Relationship.ABOVE)) {
- // potentially intersects top
- x = endX - ((endY - maxY) / slope);
- intersects = x >= minX && x <= maxX;
- }
- if (!intersects && !!(endRel & ol.extent.Relationship.RIGHT) &&
- !(startRel & ol.extent.Relationship.RIGHT)) {
- // potentially intersects right
- y = endY - ((endX - maxX) * slope);
- intersects = y >= minY && y <= maxY;
- }
- if (!intersects && !!(endRel & ol.extent.Relationship.BELOW) &&
- !(startRel & ol.extent.Relationship.BELOW)) {
- // potentially intersects bottom
- x = endX - ((endY - minY) / slope);
- intersects = x >= minX && x <= maxX;
- }
- if (!intersects && !!(endRel & ol.extent.Relationship.LEFT) &&
- !(startRel & ol.extent.Relationship.LEFT)) {
- // potentially intersects left
- y = endY - ((endX - minX) * slope);
- intersects = y >= minY && y <= maxY;
- }
-
- }
- return intersects;
-};
-
-
-/**
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {boolean} Touches.
- */
-ol.extent.touches = function(extent1, extent2) {
- var intersects = ol.extent.intersects(extent1, extent2);
- return intersects &&
- (extent1[0] == extent2[2] || extent1[2] == extent2[0] ||
- extent1[1] == extent2[3] || extent1[3] == extent2[1]);
-};
-
-
-/**
- * Apply a transform function to the extent.
- * @param {ol.Extent} extent Extent.
- * @param {ol.TransformFunction} transformFn Transform function. Called with
- * [minX, minY, maxX, maxY] extent coordinates.
- * @param {ol.Extent=} opt_extent Destination extent.
- * @return {ol.Extent} Extent.
- * @api stable
- */
-ol.extent.applyTransform = function(extent, transformFn, opt_extent) {
- var coordinates = [
- extent[0], extent[1],
- extent[0], extent[3],
- extent[2], extent[1],
- extent[2], extent[3]
- ];
- transformFn(coordinates, coordinates, 2);
- var xs = [coordinates[0], coordinates[2], coordinates[4], coordinates[6]];
- var ys = [coordinates[1], coordinates[3], coordinates[5], coordinates[7]];
- return ol.extent.boundingExtentXYs_(xs, ys, opt_extent);
-};
-
-
-/**
- * Apply a 2d transform to an extent.
- * @param {ol.Extent} extent Input extent.
- * @param {goog.vec.Mat4.Number} transform The transform matrix.
- * @param {ol.Extent=} opt_extent Optional extent for return values.
- * @return {ol.Extent} The transformed extent.
+ * @param {goog.vec.Mat4.Number} transform Transform.
+ * @param {Array.<number>=} opt_dest Destination.
+ * @return {Array.<number>} Transformed coordinates.
*/
-ol.extent.transform2D = function(extent, transform, opt_extent) {
- var dest = opt_extent ? opt_extent : [];
+ol.geom.flat.transform.transform2D = function(flatCoordinates, offset, end, stride, transform, opt_dest) {
var m00 = goog.vec.Mat4.getElement(transform, 0, 0);
var m10 = goog.vec.Mat4.getElement(transform, 1, 0);
var m01 = goog.vec.Mat4.getElement(transform, 0, 1);
var m11 = goog.vec.Mat4.getElement(transform, 1, 1);
var m03 = goog.vec.Mat4.getElement(transform, 0, 3);
var m13 = goog.vec.Mat4.getElement(transform, 1, 3);
- var xi = [0, 2, 0, 2];
- var yi = [1, 1, 3, 3];
- var xs = [];
- var ys = [];
- var i, x, y;
- for (i = 0; i < 4; ++i) {
- x = extent[xi[i]];
- y = extent[yi[i]];
- xs[i] = m00 * x + m01 * y + m03;
- ys[i] = m10 * x + m11 * y + m13;
- }
- dest[0] = Math.min.apply(null, xs);
- dest[1] = Math.min.apply(null, ys);
- dest[2] = Math.max.apply(null, xs);
- dest[3] = Math.max.apply(null, ys);
- return dest;
-};
-
-// Copyright 2008 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Utilities for creating functions. Loosely inspired by the
- * java classes: http://goo.gl/GM0Hmu and http://goo.gl/6k7nI8.
- *
- * @author nicksantos@google.com (Nick Santos)
- */
-
-
-goog.provide('goog.functions');
-
-
-/**
- * Creates a function that always returns the same value.
- * @param {T} retValue The value to return.
- * @return {function():T} The new function.
- * @template T
- */
-goog.functions.constant = function(retValue) {
- return function() {
- return retValue;
- };
-};
-
-
-/**
- * Always returns false.
- * @type {function(...): boolean}
- */
-goog.functions.FALSE = goog.functions.constant(false);
-
-
-/**
- * Always returns true.
- * @type {function(...): boolean}
- */
-goog.functions.TRUE = goog.functions.constant(true);
-
-
-/**
- * Always returns NULL.
- * @type {function(...): null}
- */
-goog.functions.NULL = goog.functions.constant(null);
-
-
-/**
- * A simple function that returns the first argument of whatever is passed
- * into it.
- * @param {T=} opt_returnValue The single value that will be returned.
- * @param {...*} var_args Optional trailing arguments. These are ignored.
- * @return {T} The first argument passed in, or undefined if nothing was passed.
- * @template T
- */
-goog.functions.identity = function(opt_returnValue, var_args) {
- return opt_returnValue;
-};
-
-
-/**
- * Creates a function that always throws an error with the given message.
- * @param {string} message The error message.
- * @return {!Function} The error-throwing function.
- */
-goog.functions.error = function(message) {
- return function() {
- throw Error(message);
- };
-};
-
-
-/**
- * Creates a function that throws the given object.
- * @param {*} err An object to be thrown.
- * @return {!Function} The error-throwing function.
- */
-goog.functions.fail = function(err) {
- return function() {
- throw err;
- }
-};
-
-
-/**
- * Given a function, create a function that keeps opt_numArgs arguments and
- * silently discards all additional arguments.
- * @param {Function} f The original function.
- * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.
- * @return {!Function} A version of f that only keeps the first opt_numArgs
- * arguments.
- */
-goog.functions.lock = function(f, opt_numArgs) {
- opt_numArgs = opt_numArgs || 0;
- return function() {
- return f.apply(this, Array.prototype.slice.call(arguments, 0, opt_numArgs));
- };
-};
-
-
-/**
- * Creates a function that returns its nth argument.
- * @param {number} n The position of the return argument.
- * @return {!Function} A new function.
- */
-goog.functions.nth = function(n) {
- return function() {
- return arguments[n];
- };
-};
-
-
-/**
- * Given a function, create a new function that swallows its return value
- * and replaces it with a new one.
- * @param {Function} f A function.
- * @param {T} retValue A new return value.
- * @return {function(...?):T} A new function.
- * @template T
- */
-goog.functions.withReturnValue = function(f, retValue) {
- return goog.functions.sequence(f, goog.functions.constant(retValue));
-};
-
-
-/**
- * Creates a function that returns whether its arguement equals the given value.
- *
- * Example:
- * var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));
- *
- * @param {*} value The value to compare to.
- * @param {boolean=} opt_useLooseComparison Whether to use a loose (==)
- * comparison rather than a strict (===) one. Defaults to false.
- * @return {function(*):boolean} The new function.
- */
-goog.functions.equalTo = function(value, opt_useLooseComparison) {
- return function(other) {
- return opt_useLooseComparison ? (value == other) : (value === other);
- };
-};
-
-
-/**
- * Creates the composition of the functions passed in.
- * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
- * @param {function(...?):T} fn The final function.
- * @param {...Function} var_args A list of functions.
- * @return {function(...?):T} The composition of all inputs.
- * @template T
- */
-goog.functions.compose = function(fn, var_args) {
- var functions = arguments;
- var length = functions.length;
- return function() {
- var result;
- if (length) {
- result = functions[length - 1].apply(this, arguments);
- }
-
- for (var i = length - 2; i >= 0; i--) {
- result = functions[i].call(this, result);
- }
- return result;
- };
-};
-
-
-/**
- * Creates a function that calls the functions passed in in sequence, and
- * returns the value of the last function. For example,
- * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).
- * @param {...Function} var_args A list of functions.
- * @return {!Function} A function that calls all inputs in sequence.
- */
-goog.functions.sequence = function(var_args) {
- var functions = arguments;
- var length = functions.length;
- return function() {
- var result;
- for (var i = 0; i < length; i++) {
- result = functions[i].apply(this, arguments);
- }
- return result;
- };
-};
-
-
-/**
- * Creates a function that returns true if each of its components evaluates
- * to true. The components are evaluated in order, and the evaluation will be
- * short-circuited as soon as a function returns false.
- * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).
- * @param {...Function} var_args A list of functions.
- * @return {function(...?):boolean} A function that ANDs its component
- * functions.
- */
-goog.functions.and = function(var_args) {
- var functions = arguments;
- var length = functions.length;
- return function() {
- for (var i = 0; i < length; i++) {
- if (!functions[i].apply(this, arguments)) {
- return false;
- }
- }
- return true;
- };
-};
-
-
-/**
- * Creates a function that returns true if any of its components evaluates
- * to true. The components are evaluated in order, and the evaluation will be
- * short-circuited as soon as a function returns true.
- * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).
- * @param {...Function} var_args A list of functions.
- * @return {function(...?):boolean} A function that ORs its component
- * functions.
- */
-goog.functions.or = function(var_args) {
- var functions = arguments;
- var length = functions.length;
- return function() {
- for (var i = 0; i < length; i++) {
- if (functions[i].apply(this, arguments)) {
- return true;
- }
- }
- return false;
- };
-};
-
-
-/**
- * Creates a function that returns the Boolean opposite of a provided function.
- * For example, (goog.functions.not(f))(x) is equivalent to !f(x).
- * @param {!Function} f The original function.
- * @return {function(...?):boolean} A function that delegates to f and returns
- * opposite.
- */
-goog.functions.not = function(f) {
- return function() {
- return !f.apply(this, arguments);
- };
-};
-
-
-/**
- * Generic factory function to construct an object given the constructor
- * and the arguments. Intended to be bound to create object factories.
- *
- * Example:
- *
- * var factory = goog.partial(goog.functions.create, Class);
- *
- * @param {function(new:T, ...)} constructor The constructor for the Object.
- * @param {...*} var_args The arguments to be passed to the constructor.
- * @return {T} A new instance of the class given in {@code constructor}.
- * @template T
- */
-goog.functions.create = function(constructor, var_args) {
- /**
- * @constructor
- * @final
- */
- var temp = function() {};
- temp.prototype = constructor.prototype;
-
- // obj will have constructor's prototype in its chain and
- // 'obj instanceof constructor' will be true.
- var obj = new temp();
-
- // obj is initialized by constructor.
- // arguments is only array-like so lacks shift(), but can be used with
- // the Array prototype function.
- constructor.apply(obj, Array.prototype.slice.call(arguments, 1));
- return obj;
-};
-
-
-/**
- * @define {boolean} Whether the return value cache should be used.
- * This should only be used to disable caches when testing.
- */
-goog.define('goog.functions.CACHE_RETURN_VALUE', true);
-
-
-/**
- * Gives a wrapper function that caches the return value of a parameterless
- * function when first called.
- *
- * When called for the first time, the given function is called and its
- * return value is cached (thus this is only appropriate for idempotent
- * functions). Subsequent calls will return the cached return value. This
- * allows the evaluation of expensive functions to be delayed until first used.
- *
- * To cache the return values of functions with parameters, see goog.memoize.
- *
- * @param {!function():T} fn A function to lazily evaluate.
- * @return {!function():T} A wrapped version the function.
- * @template T
- */
-goog.functions.cacheReturnValue = function(fn) {
- var called = false;
- var value;
-
- return function() {
- if (!goog.functions.CACHE_RETURN_VALUE) {
- return fn();
- }
-
- if (!called) {
- value = fn();
- called = true;
- }
-
- return value;
- }
-};
-
-
-/**
- * Wraps a function to allow it to be called, at most, once. All
- * additional calls are no-ops.
- *
- * This is particularly useful for initialization functions
- * that should be called, at most, once.
- *
- * @param {function():*} f Function to call.
- * @return {function():undefined} Wrapped function.
- */
-goog.functions.once = function(f) {
- // Keep a reference to the function that we null out when we're done with
- // it -- that way, the function can be GC'd when we're done with it.
- var inner = f;
- return function() {
- if (inner) {
- var tmp = inner;
- inner = null;
- tmp();
- }
- };
-};
-
-
-/**
- * Wraps a function to allow it to be called, at most, once for each sequence of
- * calls fired repeatedly so long as they are fired less than a specified
- * interval apart (in milliseconds). Whether it receives one signal or multiple,
- * it will always wait until a full interval has elapsed since the last signal
- * before performing the action.
- *
- * This is particularly useful for bulking up repeated user actions (e.g. only
- * refreshing a view once a user finishes typing rather than updating with every
- * keystroke). For more stateful debouncing with support for pausing, resuming,
- * and canceling debounced actions, use {@code goog.async.Debouncer}.
- *
- * @param {function(this:SCOPE):*} f Function to call.
- * @param {number} interval Interval over which to debounce. The function will
- * only be called after the full interval has elapsed since the last call.
- * @param {SCOPE=} opt_scope Object in whose scope to call the function.
- * @return {function():undefined} Wrapped function.
- * @template SCOPE
- */
-goog.functions.debounce = function(f, interval, opt_scope) {
- if (opt_scope) {
- f = goog.bind(f, opt_scope);
- }
- var timeout = null;
- return function() {
- goog.global.clearTimeout(timeout);
- timeout = goog.global.setTimeout(f, interval);
- };
-};
-
-
-/**
- * Wraps a function to allow it to be called, at most, once per interval
- * (specified in milliseconds). If it is called multiple times while it is
- * waiting, it will only perform the action once at the end of the interval.
- *
- * This is particularly useful for limiting repeated user requests (e.g.
- * preventing a user from spamming a server with frequent view refreshes). For
- * more stateful throttling with support for pausing, resuming, and canceling
- * throttled actions, use {@code goog.async.Throttle}.
- *
- * @param {function(this:SCOPE):*} f Function to call.
- * @param {number} interval Interval over which to throttle. The function can
- * only be called once per interval.
- * @param {SCOPE=} opt_scope Object in whose scope to call the function.
- * @return {function():undefined} Wrapped function.
- * @template SCOPE
- */
-goog.functions.throttle = function(f, interval, opt_scope) {
- if (opt_scope) {
- f = goog.bind(f, opt_scope);
- }
- var timeout = null;
- var shouldFire = false;
- var fire = function() {
- timeout = goog.global.setTimeout(handleTimeout, interval);
- f();
- };
- var handleTimeout = function() {
- timeout = null;
- if (shouldFire) {
- shouldFire = false;
- fire();
- }
- };
-
- return function() {
- if (!timeout) {
- fire();
- } else {
- shouldFire = true;
- }
- };
-};
-
-/**
- * @license
- * Latitude/longitude spherical geodesy formulae taken from
- * http://www.movable-type.co.uk/scripts/latlong.html
- * Licensed under CC-BY-3.0.
- */
-
-goog.provide('ol.Sphere');
-
-goog.require('ol.math');
-
-
-
-/**
- * @classdesc
- * Class to create objects that can be used with {@link
- * ol.geom.Polygon.circular}.
- *
- * For example to create a sphere whose radius is equal to the semi-major
- * axis of the WGS84 ellipsoid:
- *
- * ```js
- * var wgs84Sphere= new ol.Sphere(6378137);
- * ```
- *
- * @constructor
- * @param {number} radius Radius.
- * @api
- */
-ol.Sphere = function(radius) {
-
- /**
- * @type {number}
- */
- this.radius = radius;
-
-};
-
-
-/**
- * Returns the geodesic area for a list of coordinates.
- *
- * [Reference](http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409)
- * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
- * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
- * Laboratory, Pasadena, CA, June 2007
- *
- * @param {Array.<ol.Coordinate>} coordinates List of coordinates of a linear
- * ring. If the ring is oriented clockwise, the area will be positive,
- * otherwise it will be negative.
- * @return {number} Area.
- * @api
- */
-ol.Sphere.prototype.geodesicArea = function(coordinates) {
- var area = 0, len = coordinates.length;
- var x1 = coordinates[len - 1][0];
- var y1 = coordinates[len - 1][1];
- for (var i = 0; i < len; i++) {
- var x2 = coordinates[i][0], y2 = coordinates[i][1];
- area += ol.math.toRadians(x2 - x1) *
- (2 + Math.sin(ol.math.toRadians(y1)) +
- Math.sin(ol.math.toRadians(y2)));
- x1 = x2;
- y1 = y2;
- }
- return area * this.radius * this.radius / 2.0;
-};
-
-
-/**
- * Returns the distance from c1 to c2 using the haversine formula.
- *
- * @param {ol.Coordinate} c1 Coordinate 1.
- * @param {ol.Coordinate} c2 Coordinate 2.
- * @return {number} Haversine distance.
- * @api
- */
-ol.Sphere.prototype.haversineDistance = function(c1, c2) {
- var lat1 = ol.math.toRadians(c1[1]);
- var lat2 = ol.math.toRadians(c2[1]);
- var deltaLatBy2 = (lat2 - lat1) / 2;
- var deltaLonBy2 = ol.math.toRadians(c2[0] - c1[0]) / 2;
- var a = Math.sin(deltaLatBy2) * Math.sin(deltaLatBy2) +
- Math.sin(deltaLonBy2) * Math.sin(deltaLonBy2) *
- Math.cos(lat1) * Math.cos(lat2);
- return 2 * this.radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
-};
-
-
-/**
- * Returns the coordinate at the given distance and bearing from `c1`.
- *
- * @param {ol.Coordinate} c1 The origin point (`[lon, lat]` in degrees).
- * @param {number} distance The great-circle distance between the origin
- * point and the target point.
- * @param {number} bearing The bearing (in radians).
- * @return {ol.Coordinate} The target point.
- */
-ol.Sphere.prototype.offset = function(c1, distance, bearing) {
- var lat1 = ol.math.toRadians(c1[1]);
- var lon1 = ol.math.toRadians(c1[0]);
- var dByR = distance / this.radius;
- var lat = Math.asin(
- Math.sin(lat1) * Math.cos(dByR) +
- Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing));
- var lon = lon1 + Math.atan2(
- Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1),
- Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat));
- return [ol.math.toDegrees(lon), ol.math.toDegrees(lat)];
-};
-
-goog.provide('ol.sphere.NORMAL');
-
-goog.require('ol.Sphere');
-
-
-/**
- * The normal sphere.
- * @const
- * @type {ol.Sphere}
- */
-ol.sphere.NORMAL = new ol.Sphere(6370997);
-
-goog.provide('ol.proj');
-goog.provide('ol.proj.METERS_PER_UNIT');
-goog.provide('ol.proj.Projection');
-goog.provide('ol.proj.ProjectionLike');
-goog.provide('ol.proj.Units');
-
-goog.require('goog.asserts');
-goog.require('goog.object');
-goog.require('ol');
-goog.require('ol.Extent');
-goog.require('ol.TransformFunction');
-goog.require('ol.extent');
-goog.require('ol.sphere.NORMAL');
-
-
-/**
- * A projection as {@link ol.proj.Projection}, SRS identifier string or
- * undefined.
- * @typedef {ol.proj.Projection|string|undefined} ol.proj.ProjectionLike
- * @api stable
- */
-ol.proj.ProjectionLike;
-
-
-/**
- * Projection units: `'degrees'`, `'ft'`, `'m'`, `'pixels'`, `'tile-pixels'` or
- * `'us-ft'`.
- * @enum {string}
- * @api stable
- */
-ol.proj.Units = {
- DEGREES: 'degrees',
- FEET: 'ft',
- METERS: 'm',
- PIXELS: 'pixels',
- TILE_PIXELS: 'tile-pixels',
- USFEET: 'us-ft'
-};
-
-
-/**
- * Meters per unit lookup table.
- * @const
- * @type {Object.<ol.proj.Units, number>}
- * @api stable
- */
-ol.proj.METERS_PER_UNIT = {};
-ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] =
- 2 * Math.PI * ol.sphere.NORMAL.radius / 360;
-ol.proj.METERS_PER_UNIT[ol.proj.Units.FEET] = 0.3048;
-ol.proj.METERS_PER_UNIT[ol.proj.Units.METERS] = 1;
-ol.proj.METERS_PER_UNIT[ol.proj.Units.USFEET] = 1200 / 3937;
-
-
-
-/**
- * @classdesc
- * Projection definition class. One of these is created for each projection
- * supported in the application and stored in the {@link ol.proj} namespace.
- * You can use these in applications, but this is not required, as API params
- * and options use {@link ol.proj.ProjectionLike} which means the simple string
- * code will suffice.
- *
- * You can use {@link ol.proj.get} to retrieve the object for a particular
- * projection.
- *
- * The library includes definitions for `EPSG:4326` and `EPSG:3857`, together
- * with the following aliases:
- * * `EPSG:4326`: CRS:84, urn:ogc:def:crs:EPSG:6.6:4326,
- * urn:ogc:def:crs:OGC:1.3:CRS84, urn:ogc:def:crs:OGC:2:84,
- * http://www.opengis.net/gml/srs/epsg.xml#4326,
- * urn:x-ogc:def:crs:EPSG:4326
- * * `EPSG:3857`: EPSG:102100, EPSG:102113, EPSG:900913,
- * urn:ogc:def:crs:EPSG:6.18:3:3857,
- * http://www.opengis.net/gml/srs/epsg.xml#3857
- *
- * If you use proj4js, aliases can be added using `proj4.defs()`; see
- * [documentation](https://github.com/proj4js/proj4js).
- *
- * @constructor
- * @param {olx.ProjectionOptions} options Projection options.
- * @struct
- * @api stable
- */
-ol.proj.Projection = function(options) {
-
- /**
- * @private
- * @type {string}
- */
- this.code_ = options.code;
-
- /**
- * @private
- * @type {ol.proj.Units}
- */
- this.units_ = /** @type {ol.proj.Units} */ (options.units);
-
- /**
- * @private
- * @type {ol.Extent}
- */
- this.extent_ = options.extent !== undefined ? options.extent : null;
-
- /**
- * @private
- * @type {ol.Extent}
- */
- this.worldExtent_ = options.worldExtent !== undefined ?
- options.worldExtent : null;
-
- /**
- * @private
- * @type {string}
- */
- this.axisOrientation_ = options.axisOrientation !== undefined ?
- options.axisOrientation : 'enu';
-
- /**
- * @private
- * @type {boolean}
- */
- this.global_ = options.global !== undefined ? options.global : false;
-
-
- /**
- * @private
- * @type {boolean}
- */
- this.canWrapX_ = !!(this.global_ && this.extent_);
-
- /**
- * @private
- * @type {function(number, ol.Coordinate):number}
- */
- this.getPointResolutionFunc_ = options.getPointResolution !== undefined ?
- options.getPointResolution : this.getPointResolution_;
-
- /**
- * @private
- * @type {ol.tilegrid.TileGrid}
- */
- this.defaultTileGrid_ = null;
-
- var projections = ol.proj.projections_;
- var code = options.code;
- goog.asserts.assert(code !== undefined,
- 'Option "code" is required for constructing instance');
- if (ol.ENABLE_PROJ4JS && typeof proj4 == 'function' &&
- projections[code] === undefined) {
- var def = proj4.defs(code);
- if (def !== undefined) {
- if (def.axis !== undefined && options.axisOrientation === undefined) {
- this.axisOrientation_ = def.axis;
- }
- if (options.units === undefined) {
- var units = def.units;
- if (def.to_meter !== undefined) {
- if (units === undefined ||
- ol.proj.METERS_PER_UNIT[units] === undefined) {
- units = def.to_meter.toString();
- ol.proj.METERS_PER_UNIT[units] = def.to_meter;
- }
- }
- this.units_ = units;
- }
- var currentCode, currentDef, currentProj, proj4Transform;
- for (currentCode in projections) {
- currentDef = proj4.defs(currentCode);
- if (currentDef !== undefined) {
- currentProj = ol.proj.get(currentCode);
- if (currentDef === def) {
- ol.proj.addEquivalentProjections([currentProj, this]);
- } else {
- proj4Transform = proj4(currentCode, code);
- ol.proj.addCoordinateTransforms(currentProj, this,
- proj4Transform.forward, proj4Transform.inverse);
- }
- }
- }
- }
- }
-
-};
-
-
-/**
- * @return {boolean} The projection is suitable for wrapping the x-axis
- */
-ol.proj.Projection.prototype.canWrapX = function() {
- return this.canWrapX_;
-};
-
-
-/**
- * Get the code for this projection, e.g. 'EPSG:4326'.
- * @return {string} Code.
- * @api stable
- */
-ol.proj.Projection.prototype.getCode = function() {
- return this.code_;
-};
-
-
-/**
- * Get the validity extent for this projection.
- * @return {ol.Extent} Extent.
- * @api stable
- */
-ol.proj.Projection.prototype.getExtent = function() {
- return this.extent_;
-};
-
-
-/**
- * Get the units of this projection.
- * @return {ol.proj.Units} Units.
- * @api stable
- */
-ol.proj.Projection.prototype.getUnits = function() {
- return this.units_;
-};
-
-
-/**
- * Get the amount of meters per unit of this projection. If the projection is
- * not configured with a units identifier, the return is `undefined`.
- * @return {number|undefined} Meters.
- * @api stable
- */
-ol.proj.Projection.prototype.getMetersPerUnit = function() {
- return ol.proj.METERS_PER_UNIT[this.units_];
-};
-
-
-/**
- * Get the world extent for this projection.
- * @return {ol.Extent} Extent.
- * @api
- */
-ol.proj.Projection.prototype.getWorldExtent = function() {
- return this.worldExtent_;
-};
-
-
-/**
- * Get the axis orientation of this projection.
- * Example values are:
- * enu - the default easting, northing, elevation.
- * neu - northing, easting, up - useful for "lat/long" geographic coordinates,
- * or south orientated transverse mercator.
- * wnu - westing, northing, up - some planetary coordinate systems have
- * "west positive" coordinate systems
- * @return {string} Axis orientation.
- */
-ol.proj.Projection.prototype.getAxisOrientation = function() {
- return this.axisOrientation_;
-};
-
-
-/**
- * Is this projection a global projection which spans the whole world?
- * @return {boolean} Whether the projection is global.
- * @api stable
- */
-ol.proj.Projection.prototype.isGlobal = function() {
- return this.global_;
-};
-
-
-/**
-* Set if the projection is a global projection which spans the whole world
-* @param {boolean} global Whether the projection is global.
-* @api stable
-*/
-ol.proj.Projection.prototype.setGlobal = function(global) {
- this.global_ = global;
- this.canWrapX_ = !!(global && this.extent_);
-};
-
-
-/**
- * @return {ol.tilegrid.TileGrid} The default tile grid.
- */
-ol.proj.Projection.prototype.getDefaultTileGrid = function() {
- return this.defaultTileGrid_;
-};
-
-
-/**
- * @param {ol.tilegrid.TileGrid} tileGrid The default tile grid.
- */
-ol.proj.Projection.prototype.setDefaultTileGrid = function(tileGrid) {
- this.defaultTileGrid_ = tileGrid;
-};
-
-
-/**
- * Set the validity extent for this projection.
- * @param {ol.Extent} extent Extent.
- * @api stable
- */
-ol.proj.Projection.prototype.setExtent = function(extent) {
- this.extent_ = extent;
- this.canWrapX_ = !!(this.global_ && extent);
-};
-
-
-/**
- * Set the world extent for this projection.
- * @param {ol.Extent} worldExtent World extent
- * [minlon, minlat, maxlon, maxlat].
- * @api
- */
-ol.proj.Projection.prototype.setWorldExtent = function(worldExtent) {
- this.worldExtent_ = worldExtent;
-};
-
-
-/**
-* Set the getPointResolution function for this projection.
-* @param {function(number, ol.Coordinate):number} func Function
-* @api
-*/
-ol.proj.Projection.prototype.setGetPointResolution = function(func) {
- this.getPointResolutionFunc_ = func;
-};
-
-
-/**
-* Default version.
-* Get the resolution of the point in degrees or distance units.
-* For projections with degrees as the unit this will simply return the
-* provided resolution. For other projections the point resolution is
-* estimated by transforming the 'point' pixel to EPSG:4326,
-* measuring its width and height on the normal sphere,
-* and taking the average of the width and height.
-* @param {number} resolution Nominal resolution in projection units.
-* @param {ol.Coordinate} point Point to find adjusted resolution at.
-* @return {number} Point resolution at point in projection units.
-* @private
-*/
-ol.proj.Projection.prototype.getPointResolution_ = function(resolution, point) {
- var units = this.getUnits();
- if (units == ol.proj.Units.DEGREES) {
- return resolution;
- } else {
- // Estimate point resolution by transforming the center pixel to EPSG:4326,
- // measuring its width and height on the normal sphere, and taking the
- // average of the width and height.
- var toEPSG4326 = ol.proj.getTransformFromProjections(
- this, ol.proj.get('EPSG:4326'));
- var vertices = [
- point[0] - resolution / 2, point[1],
- point[0] + resolution / 2, point[1],
- point[0], point[1] - resolution / 2,
- point[0], point[1] + resolution / 2
- ];
- vertices = toEPSG4326(vertices, vertices, 2);
- var width = ol.sphere.NORMAL.haversineDistance(
- vertices.slice(0, 2), vertices.slice(2, 4));
- var height = ol.sphere.NORMAL.haversineDistance(
- vertices.slice(4, 6), vertices.slice(6, 8));
- var pointResolution = (width + height) / 2;
- var metersPerUnit = this.getMetersPerUnit();
- if (metersPerUnit !== undefined) {
- pointResolution /= metersPerUnit;
- }
- return pointResolution;
- }
-};
-
-
-/**
- * Get the resolution of the point in degrees or distance units.
- * For projections with degrees as the unit this will simply return the
- * provided resolution. The default for other projections is to estimate
- * the point resolution by transforming the 'point' pixel to EPSG:4326,
- * measuring its width and height on the normal sphere,
- * and taking the average of the width and height.
- * An alternative implementation may be given when constructing a
- * projection. For many local projections,
- * such a custom function will return the resolution unchanged.
- * @param {number} resolution Resolution in projection units.
- * @param {ol.Coordinate} point Point.
- * @return {number} Point resolution in projection units.
- * @api
- */
-ol.proj.Projection.prototype.getPointResolution = function(resolution, point) {
- return this.getPointResolutionFunc_(resolution, point);
-};
-
-
-/**
- * @private
- * @type {Object.<string, ol.proj.Projection>}
- */
-ol.proj.projections_ = {};
-
-
-/**
- * @private
- * @type {Object.<string, Object.<string, ol.TransformFunction>>}
- */
-ol.proj.transforms_ = {};
-
-
-/**
- * Registers transformation functions that don't alter coordinates. Those allow
- * to transform between projections with equal meaning.
- *
- * @param {Array.<ol.proj.Projection>} projections Projections.
- * @api
- */
-ol.proj.addEquivalentProjections = function(projections) {
- ol.proj.addProjections(projections);
- projections.forEach(function(source) {
- projections.forEach(function(destination) {
- if (source !== destination) {
- ol.proj.addTransform(source, destination, ol.proj.cloneTransform);
- }
- });
- });
-};
-
-
-/**
- * Registers transformation functions to convert coordinates in any projection
- * in projection1 to any projection in projection2.
- *
- * @param {Array.<ol.proj.Projection>} projections1 Projections with equal
- * meaning.
- * @param {Array.<ol.proj.Projection>} projections2 Projections with equal
- * meaning.
- * @param {ol.TransformFunction} forwardTransform Transformation from any
- * projection in projection1 to any projection in projection2.
- * @param {ol.TransformFunction} inverseTransform Transform from any projection
- * in projection2 to any projection in projection1..
- */
-ol.proj.addEquivalentTransforms =
- function(projections1, projections2, forwardTransform, inverseTransform) {
- projections1.forEach(function(projection1) {
- projections2.forEach(function(projection2) {
- ol.proj.addTransform(projection1, projection2, forwardTransform);
- ol.proj.addTransform(projection2, projection1, inverseTransform);
- });
- });
-};
-
-
-/**
- * Add a Projection object to the list of supported projections that can be
- * looked up by their code.
- *
- * @param {ol.proj.Projection} projection Projection instance.
- * @api stable
- */
-ol.proj.addProjection = function(projection) {
- ol.proj.projections_[projection.getCode()] = projection;
- ol.proj.addTransform(projection, projection, ol.proj.cloneTransform);
-};
-
-
-/**
- * @param {Array.<ol.proj.Projection>} projections Projections.
- */
-ol.proj.addProjections = function(projections) {
- var addedProjections = [];
- projections.forEach(function(projection) {
- addedProjections.push(ol.proj.addProjection(projection));
- });
-};
-
-
-/**
- * FIXME empty description for jsdoc
- */
-ol.proj.clearAllProjections = function() {
- ol.proj.projections_ = {};
- ol.proj.transforms_ = {};
-};
-
-
-/**
- * @param {ol.proj.Projection|string|undefined} projection Projection.
- * @param {string} defaultCode Default code.
- * @return {ol.proj.Projection} Projection.
- */
-ol.proj.createProjection = function(projection, defaultCode) {
- if (!projection) {
- return ol.proj.get(defaultCode);
- } else if (goog.isString(projection)) {
- return ol.proj.get(projection);
- } else {
- goog.asserts.assertInstanceof(projection, ol.proj.Projection,
- 'projection should be an ol.proj.Projection');
- return projection;
- }
-};
-
-
-/**
- * Registers a conversion function to convert coordinates from the source
- * projection to the destination projection.
- *
- * @param {ol.proj.Projection} source Source.
- * @param {ol.proj.Projection} destination Destination.
- * @param {ol.TransformFunction} transformFn Transform.
- */
-ol.proj.addTransform = function(source, destination, transformFn) {
- var sourceCode = source.getCode();
- var destinationCode = destination.getCode();
- var transforms = ol.proj.transforms_;
- if (!(sourceCode in transforms)) {
- transforms[sourceCode] = {};
- }
- transforms[sourceCode][destinationCode] = transformFn;
-};
-
-
-/**
- * Registers coordinate transform functions to convert coordinates between the
- * source projection and the destination projection.
- * The forward and inverse functions convert coordinate pairs; this function
- * converts these into the functions used internally which also handle
- * extents and coordinate arrays.
- *
- * @param {ol.proj.ProjectionLike} source Source projection.
- * @param {ol.proj.ProjectionLike} destination Destination projection.
- * @param {function(ol.Coordinate): ol.Coordinate} forward The forward transform
- * function (that is, from the source projection to the destination
- * projection) that takes a {@link ol.Coordinate} as argument and returns
- * the transformed {@link ol.Coordinate}.
- * @param {function(ol.Coordinate): ol.Coordinate} inverse The inverse transform
- * function (that is, from the destination projection to the source
- * projection) that takes a {@link ol.Coordinate} as argument and returns
- * the transformed {@link ol.Coordinate}.
- * @api stable
- */
-ol.proj.addCoordinateTransforms =
- function(source, destination, forward, inverse) {
- var sourceProj = ol.proj.get(source);
- var destProj = ol.proj.get(destination);
- ol.proj.addTransform(sourceProj, destProj,
- ol.proj.createTransformFromCoordinateTransform(forward));
- ol.proj.addTransform(destProj, sourceProj,
- ol.proj.createTransformFromCoordinateTransform(inverse));
-};
-
-
-/**
- * Creates a {@link ol.TransformFunction} from a simple 2D coordinate transform
- * function.
- * @param {function(ol.Coordinate): ol.Coordinate} transform Coordinate
- * transform.
- * @return {ol.TransformFunction} Transform function.
- */
-ol.proj.createTransformFromCoordinateTransform = function(transform) {
- return (
- /**
- * @param {Array.<number>} input Input.
- * @param {Array.<number>=} opt_output Output.
- * @param {number=} opt_dimension Dimension.
- * @return {Array.<number>} Output.
- */
- function(input, opt_output, opt_dimension) {
- var length = input.length;
- var dimension = opt_dimension !== undefined ? opt_dimension : 2;
- var output = opt_output !== undefined ? opt_output : new Array(length);
- var point, i, j;
- for (i = 0; i < length; i += dimension) {
- point = transform([input[i], input[i + 1]]);
- output[i] = point[0];
- output[i + 1] = point[1];
- for (j = dimension - 1; j >= 2; --j) {
- output[i + j] = input[i + j];
- }
- }
- return output;
- });
-};
-
-
-/**
- * Unregisters the conversion function to convert coordinates from the source
- * projection to the destination projection. This method is used to clean up
- * cached transforms during testing.
- *
- * @param {ol.proj.Projection} source Source projection.
- * @param {ol.proj.Projection} destination Destination projection.
- * @return {ol.TransformFunction} transformFn The unregistered transform.
- */
-ol.proj.removeTransform = function(source, destination) {
- var sourceCode = source.getCode();
- var destinationCode = destination.getCode();
- var transforms = ol.proj.transforms_;
- goog.asserts.assert(sourceCode in transforms,
- 'sourceCode should be in transforms');
- goog.asserts.assert(destinationCode in transforms[sourceCode],
- 'destinationCode should be in transforms of sourceCode');
- var transform = transforms[sourceCode][destinationCode];
- delete transforms[sourceCode][destinationCode];
- if (goog.object.isEmpty(transforms[sourceCode])) {
- delete transforms[sourceCode];
- }
- return transform;
-};
-
-
-/**
- * Transforms a coordinate from longitude/latitude to a different projection.
- * @param {ol.Coordinate} coordinate Coordinate as longitude and latitude, i.e.
- * an array with longitude as 1st and latitude as 2nd element.
- * @param {ol.proj.ProjectionLike=} opt_projection Target projection. The
- * default is Web Mercator, i.e. 'EPSG:3857'.
- * @return {ol.Coordinate} Coordinate projected to the target projection.
- * @api stable
- */
-ol.proj.fromLonLat = function(coordinate, opt_projection) {
- return ol.proj.transform(coordinate, 'EPSG:4326',
- opt_projection !== undefined ? opt_projection : 'EPSG:3857');
-};
-
-
-/**
- * Transforms a coordinate to longitude/latitude.
- * @param {ol.Coordinate} coordinate Projected coordinate.
- * @param {ol.proj.ProjectionLike=} opt_projection Projection of the coordinate.
- * The default is Web Mercator, i.e. 'EPSG:3857'.
- * @return {ol.Coordinate} Coordinate as longitude and latitude, i.e. an array
- * with longitude as 1st and latitude as 2nd element.
- * @api stable
- */
-ol.proj.toLonLat = function(coordinate, opt_projection) {
- return ol.proj.transform(coordinate,
- opt_projection !== undefined ? opt_projection : 'EPSG:3857', 'EPSG:4326');
-};
-
-
-/**
- * Fetches a Projection object for the code specified.
- *
- * @param {ol.proj.ProjectionLike} projectionLike Either a code string which is
- * a combination of authority and identifier such as "EPSG:4326", or an
- * existing projection object, or undefined.
- * @return {ol.proj.Projection} Projection object, or null if not in list.
- * @api stable
- */
-ol.proj.get = function(projectionLike) {
- var projection;
- if (projectionLike instanceof ol.proj.Projection) {
- projection = projectionLike;
- } else if (goog.isString(projectionLike)) {
- var code = projectionLike;
- projection = ol.proj.projections_[code];
- if (ol.ENABLE_PROJ4JS && projection === undefined &&
- typeof proj4 == 'function' && proj4.defs(code) !== undefined) {
- projection = new ol.proj.Projection({code: code});
- ol.proj.addProjection(projection);
- }
- } else {
- projection = null;
- }
- return projection;
-};
-
-
-/**
- * Checks if two projections are the same, that is every coordinate in one
- * projection does represent the same geographic point as the same coordinate in
- * the other projection.
- *
- * @param {ol.proj.Projection} projection1 Projection 1.
- * @param {ol.proj.Projection} projection2 Projection 2.
- * @return {boolean} Equivalent.
- */
-ol.proj.equivalent = function(projection1, projection2) {
- if (projection1 === projection2) {
- return true;
- }
- var equalUnits = projection1.getUnits() === projection2.getUnits();
- if (projection1.getCode() === projection2.getCode()) {
- return equalUnits;
- } else {
- var transformFn = ol.proj.getTransformFromProjections(
- projection1, projection2);
- return transformFn === ol.proj.cloneTransform && equalUnits;
- }
-};
-
-
-/**
- * Given the projection-like objects, searches for a transformation
- * function to convert a coordinates array from the source projection to the
- * destination projection.
- *
- * @param {ol.proj.ProjectionLike} source Source.
- * @param {ol.proj.ProjectionLike} destination Destination.
- * @return {ol.TransformFunction} Transform function.
- * @api stable
- */
-ol.proj.getTransform = function(source, destination) {
- var sourceProjection = ol.proj.get(source);
- var destinationProjection = ol.proj.get(destination);
- return ol.proj.getTransformFromProjections(
- sourceProjection, destinationProjection);
-};
-
-
-/**
- * Searches in the list of transform functions for the function for converting
- * coordinates from the source projection to the destination projection.
- *
- * @param {ol.proj.Projection} sourceProjection Source Projection object.
- * @param {ol.proj.Projection} destinationProjection Destination Projection
- * object.
- * @return {ol.TransformFunction} Transform function.
- */
-ol.proj.getTransformFromProjections =
- function(sourceProjection, destinationProjection) {
- var transforms = ol.proj.transforms_;
- var sourceCode = sourceProjection.getCode();
- var destinationCode = destinationProjection.getCode();
- var transform;
- if (sourceCode in transforms && destinationCode in transforms[sourceCode]) {
- transform = transforms[sourceCode][destinationCode];
- }
- if (transform === undefined) {
- goog.asserts.assert(transform !== undefined, 'transform should be defined');
- transform = ol.proj.identityTransform;
- }
- return transform;
-};
-
-
-/**
- * @param {Array.<number>} input Input coordinate array.
- * @param {Array.<number>=} opt_output Output array of coordinate values.
- * @param {number=} opt_dimension Dimension.
- * @return {Array.<number>} Input coordinate array (same array as input).
- */
-ol.proj.identityTransform = function(input, opt_output, opt_dimension) {
- if (opt_output !== undefined && input !== opt_output) {
- // TODO: consider making this a warning instead
- goog.asserts.fail('This should not be used internally.');
- for (var i = 0, ii = input.length; i < ii; ++i) {
- opt_output[i] = input[i];
- }
- input = opt_output;
- }
- return input;
-};
-
-
-/**
- * @param {Array.<number>} input Input coordinate array.
- * @param {Array.<number>=} opt_output Output array of coordinate values.
- * @param {number=} opt_dimension Dimension.
- * @return {Array.<number>} Output coordinate array (new array, same coordinate
- * values).
- */
-ol.proj.cloneTransform = function(input, opt_output, opt_dimension) {
- var output;
- if (opt_output !== undefined) {
- for (var i = 0, ii = input.length; i < ii; ++i) {
- opt_output[i] = input[i];
- }
- output = opt_output;
- } else {
- output = input.slice();
+ var dest = opt_dest ? opt_dest : [];
+ var i = 0;
+ var j;
+ for (j = offset; j < end; j += stride) {
+ var x = flatCoordinates[j];
+ var y = flatCoordinates[j + 1];
+ dest[i++] = m00 * x + m01 * y + m03;
+ dest[i++] = m10 * x + m11 * y + m13;
}
- return output;
-};
-
-
-/**
- * Transforms a coordinate from source projection to destination projection.
- * This returns a new coordinate (and does not modify the original).
- *
- * See {@link ol.proj.transformExtent} for extent transformation.
- * See the transform method of {@link ol.geom.Geometry} and its subclasses for
- * geometry transforms.
- *
- * @param {ol.Coordinate} coordinate Coordinate.
- * @param {ol.proj.ProjectionLike} source Source projection-like.
- * @param {ol.proj.ProjectionLike} destination Destination projection-like.
- * @return {ol.Coordinate} Coordinate.
- * @api stable
- */
-ol.proj.transform = function(coordinate, source, destination) {
- var transformFn = ol.proj.getTransform(source, destination);
- return transformFn(coordinate, undefined, coordinate.length);
-};
-
-
-/**
- * Transforms an extent from source projection to destination projection. This
- * returns a new extent (and does not modify the original).
- *
- * @param {ol.Extent} extent The extent to transform.
- * @param {ol.proj.ProjectionLike} source Source projection-like.
- * @param {ol.proj.ProjectionLike} destination Destination projection-like.
- * @return {ol.Extent} The transformed extent.
- * @api stable
- */
-ol.proj.transformExtent = function(extent, source, destination) {
- var transformFn = ol.proj.getTransform(source, destination);
- return ol.extent.applyTransform(extent, transformFn);
-};
-
-
-/**
- * Transforms the given point to the destination projection.
- *
- * @param {ol.Coordinate} point Point.
- * @param {ol.proj.Projection} sourceProjection Source projection.
- * @param {ol.proj.Projection} destinationProjection Destination projection.
- * @return {ol.Coordinate} Point.
- */
-ol.proj.transformWithProjections =
- function(point, sourceProjection, destinationProjection) {
- var transformFn = ol.proj.getTransformFromProjections(
- sourceProjection, destinationProjection);
- return transformFn(point);
-};
-
-goog.provide('ol.geom.Geometry');
-goog.provide('ol.geom.GeometryLayout');
-goog.provide('ol.geom.GeometryType');
-
-goog.require('goog.asserts');
-goog.require('goog.functions');
-goog.require('ol.Object');
-goog.require('ol.extent');
-goog.require('ol.proj');
-goog.require('ol.proj.Units');
-
-
-/**
- * The geometry type. One of `'Point'`, `'LineString'`, `'LinearRing'`,
- * `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`,
- * `'GeometryCollection'`, `'Circle'`.
- * @enum {string}
- * @api stable
- */
-ol.geom.GeometryType = {
- POINT: 'Point',
- LINE_STRING: 'LineString',
- LINEAR_RING: 'LinearRing',
- POLYGON: 'Polygon',
- MULTI_POINT: 'MultiPoint',
- MULTI_LINE_STRING: 'MultiLineString',
- MULTI_POLYGON: 'MultiPolygon',
- GEOMETRY_COLLECTION: 'GeometryCollection',
- CIRCLE: 'Circle'
-};
-
-
-/**
- * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
- * or measure ('M') coordinate is available. Supported values are `'XY'`,
- * `'XYZ'`, `'XYM'`, `'XYZM'`.
- * @enum {string}
- * @api stable
- */
-ol.geom.GeometryLayout = {
- XY: 'XY',
- XYZ: 'XYZ',
- XYM: 'XYM',
- XYZM: 'XYZM'
-};
-
-
-
-/**
- * @classdesc
- * Abstract base class; normally only used for creating subclasses and not
- * instantiated in apps.
- * Base class for vector geometries.
- *
- * To get notified of changes to the geometry, register a listener for the
- * generic `change` event on your geometry instance.
- *
- * @constructor
- * @extends {ol.Object}
- * @api stable
- */
-ol.geom.Geometry = function() {
-
- goog.base(this);
-
- /**
- * @private
- * @type {ol.Extent}
- */
- this.extent_ = ol.extent.createEmpty();
-
- /**
- * @private
- * @type {number}
- */
- this.extentRevision_ = -1;
-
- /**
- * @protected
- * @type {Object.<string, ol.geom.Geometry>}
- */
- this.simplifiedGeometryCache = {};
-
- /**
- * @protected
- * @type {number}
- */
- this.simplifiedGeometryMaxMinSquaredTolerance = 0;
-
- /**
- * @protected
- * @type {number}
- */
- this.simplifiedGeometryRevision = 0;
-
-};
-goog.inherits(ol.geom.Geometry, ol.Object);
-
-
-/**
- * Make a complete copy of the geometry.
- * @function
- * @return {!ol.geom.Geometry} Clone.
- */
-ol.geom.Geometry.prototype.clone = goog.abstractMethod;
-
-
-/**
- * @param {number} x X.
- * @param {number} y Y.
- * @param {ol.Coordinate} closestPoint Closest point.
- * @param {number} minSquaredDistance Minimum squared distance.
- * @return {number} Minimum squared distance.
- */
-ol.geom.Geometry.prototype.closestPointXY = goog.abstractMethod;
-
-
-/**
- * Return the closest point of the geometry to the passed point as
- * {@link ol.Coordinate coordinate}.
- * @param {ol.Coordinate} point Point.
- * @param {ol.Coordinate=} opt_closestPoint Closest point.
- * @return {ol.Coordinate} Closest point.
- * @api stable
- */
-ol.geom.Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) {
- var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];
- this.closestPointXY(point[0], point[1], closestPoint, Infinity);
- return closestPoint;
-};
-
-
-/**
- * @param {ol.Coordinate} coordinate Coordinate.
- * @return {boolean} Contains coordinate.
- */
-ol.geom.Geometry.prototype.containsCoordinate = function(coordinate) {
- return this.containsXY(coordinate[0], coordinate[1]);
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @protected
- * @return {ol.Extent} extent Extent.
- */
-ol.geom.Geometry.prototype.computeExtent = goog.abstractMethod;
-
-
-/**
- * @param {number} x X.
- * @param {number} y Y.
- * @return {boolean} Contains (x, y).
- */
-ol.geom.Geometry.prototype.containsXY = goog.functions.FALSE;
-
-
-/**
- * Get the extent of the geometry.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} extent Extent.
- * @api stable
- */
-ol.geom.Geometry.prototype.getExtent = function(opt_extent) {
- if (this.extentRevision_ != this.getRevision()) {
- this.extent_ = this.computeExtent(this.extent_);
- this.extentRevision_ = this.getRevision();
+ if (opt_dest && dest.length != i) {
+ dest.length = i;
}
- return ol.extent.returnOrUpdate(this.extent_, opt_extent);
-};
-
-
-/**
- * Create a simplified version of this geometry. For linestrings, this uses
- * the the {@link
- * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
- * Douglas Peucker} algorithm. For polygons, a quantization-based
- * simplification is used to preserve topology.
- * @function
- * @param {number} tolerance The tolerance distance for simplification.
- * @return {ol.geom.Geometry} A new, simplified version of the original
- * geometry.
- * @api
- */
-ol.geom.Geometry.prototype.simplify = function(tolerance) {
- return this.getSimplifiedGeometry(tolerance * tolerance);
-};
-
-
-/**
- * Create a simplified version of this geometry using the Douglas Peucker
- * algorithm.
- * @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
- * @function
- * @param {number} squaredTolerance Squared tolerance.
- * @return {ol.geom.Geometry} Simplified geometry.
- */
-ol.geom.Geometry.prototype.getSimplifiedGeometry = goog.abstractMethod;
-
-
-/**
- * Get the type of this geometry.
- * @function
- * @return {ol.geom.GeometryType} Geometry type.
- */
-ol.geom.Geometry.prototype.getType = goog.abstractMethod;
-
-
-/**
- * Apply a transform function to each coordinate of the geometry.
- * The geometry is modified in place.
- * If you do not want the geometry modified in place, first clone() it and
- * then use this function on the clone.
- * @function
- * @param {ol.TransformFunction} transformFn Transform.
- */
-ol.geom.Geometry.prototype.applyTransform = goog.abstractMethod;
-
-
-/**
- * Test if the geometry and the passed extent intersect.
- * @param {ol.Extent} extent Extent.
- * @return {boolean} `true` if the geometry and the extent intersect.
- * @function
- */
-ol.geom.Geometry.prototype.intersectsExtent = goog.abstractMethod;
-
-
-/**
- * Translate the geometry. This modifies the geometry coordinates in place. If
- * instead you want a new geometry, first `clone()` this geometry.
- * @param {number} deltaX Delta X.
- * @param {number} deltaY Delta Y.
- * @function
- */
-ol.geom.Geometry.prototype.translate = goog.abstractMethod;
-
-
-/**
- * Transform each coordinate of the geometry from one coordinate reference
- * system to another. The geometry is modified in place.
- * For example, a line will be transformed to a line and a circle to a circle.
- * If you do not want the geometry modified in place, first clone() it and
- * then use this function on the clone.
- *
- * @param {ol.proj.ProjectionLike} source The current projection. Can be a
- * string identifier or a {@link ol.proj.Projection} object.
- * @param {ol.proj.ProjectionLike} destination The desired projection. Can be a
- * string identifier or a {@link ol.proj.Projection} object.
- * @return {ol.geom.Geometry} This geometry. Note that original geometry is
- * modified in place.
- * @api stable
- */
-ol.geom.Geometry.prototype.transform = function(source, destination) {
- goog.asserts.assert(
- ol.proj.get(source).getUnits() !== ol.proj.Units.TILE_PIXELS &&
- ol.proj.get(destination).getUnits() !== ol.proj.Units.TILE_PIXELS,
- 'cannot transform geometries with TILE_PIXELS units');
- this.applyTransform(ol.proj.getTransform(source, destination));
- return this;
+ return dest;
};
-goog.provide('ol.geom.flat.transform');
-
-goog.require('goog.vec.Mat4');
-
/**
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {number} end End.
* @param {number} stride Stride.
- * @param {goog.vec.Mat4.Number} transform Transform.
+ * @param {number} angle Angle.
+ * @param {Array.<number>} anchor Rotation anchor point.
* @param {Array.<number>=} opt_dest Destination.
* @return {Array.<number>} Transformed coordinates.
*/
-ol.geom.flat.transform.transform2D =
- function(flatCoordinates, offset, end, stride, transform, opt_dest) {
- var m00 = goog.vec.Mat4.getElement(transform, 0, 0);
- var m10 = goog.vec.Mat4.getElement(transform, 1, 0);
- var m01 = goog.vec.Mat4.getElement(transform, 0, 1);
- var m11 = goog.vec.Mat4.getElement(transform, 1, 1);
- var m03 = goog.vec.Mat4.getElement(transform, 0, 3);
- var m13 = goog.vec.Mat4.getElement(transform, 1, 3);
+ol.geom.flat.transform.rotate = function(flatCoordinates, offset, end, stride, angle, anchor, opt_dest) {
var dest = opt_dest ? opt_dest : [];
+ var cos = Math.cos(angle);
+ var sin = Math.sin(angle);
+ var anchorX = anchor[0];
+ var anchorY = anchor[1];
var i = 0;
- var j;
- for (j = offset; j < end; j += stride) {
- var x = flatCoordinates[j];
- var y = flatCoordinates[j + 1];
- dest[i++] = m00 * x + m01 * y + m03;
- dest[i++] = m10 * x + m11 * y + m13;
+ for (var j = offset; j < end; j += stride) {
+ var deltaX = flatCoordinates[j] - anchorX;
+ var deltaY = flatCoordinates[j + 1] - anchorY;
+ dest[i++] = anchorX + deltaX * cos - deltaY * sin;
+ dest[i++] = anchorY + deltaX * sin + deltaY * cos;
+ for (var k = j + 2; k < j + stride; ++k) {
+ dest[i++] = flatCoordinates[k];
+ }
}
if (opt_dest && dest.length != i) {
dest.length = i;
@@ -19880,8 +13178,7 @@ ol.geom.flat.transform.transform2D =
* @param {Array.<number>=} opt_dest Destination.
* @return {Array.<number>} Transformed coordinates.
*/
-ol.geom.flat.transform.translate =
- function(flatCoordinates, offset, end, stride, deltaX, deltaY, opt_dest) {
+ol.geom.flat.transform.translate = function(flatCoordinates, offset, end, stride, deltaX, deltaY, opt_dest) {
var dest = opt_dest ? opt_dest : [];
var i = 0;
var j, k;
@@ -19901,13 +13198,12 @@ ol.geom.flat.transform.translate =
goog.provide('ol.geom.SimpleGeometry');
goog.require('goog.asserts');
-goog.require('goog.functions');
-goog.require('goog.object');
+goog.require('ol.functions');
goog.require('ol.extent');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryLayout');
goog.require('ol.geom.flat.transform');
-
+goog.require('ol.object');
/**
@@ -19985,7 +13281,7 @@ ol.geom.SimpleGeometry.getStrideForLayout = function(layout) {
/**
* @inheritDoc
*/
-ol.geom.SimpleGeometry.prototype.containsXY = goog.functions.FALSE;
+ol.geom.SimpleGeometry.prototype.containsXY = ol.functions.FALSE;
/**
@@ -20045,10 +13341,9 @@ ol.geom.SimpleGeometry.prototype.getLayout = function() {
/**
* @inheritDoc
*/
-ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry =
- function(squaredTolerance) {
+ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {
if (this.simplifiedGeometryRevision != this.getRevision()) {
- goog.object.clear(this.simplifiedGeometryCache);
+ ol.object.clear(this.simplifiedGeometryCache);
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
this.simplifiedGeometryRevision = this.getRevision();
}
@@ -20088,8 +13383,7 @@ ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry =
* @return {ol.geom.SimpleGeometry} Simplified geometry.
* @protected
*/
-ol.geom.SimpleGeometry.prototype.getSimplifiedGeometryInternal =
- function(squaredTolerance) {
+ol.geom.SimpleGeometry.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
return this;
};
@@ -20107,8 +13401,7 @@ ol.geom.SimpleGeometry.prototype.getStride = function() {
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @protected
*/
-ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal =
- function(layout, flatCoordinates) {
+ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal = function(layout, flatCoordinates) {
this.stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
this.layout = layout;
this.flatCoordinates = flatCoordinates;
@@ -20128,8 +13421,7 @@ ol.geom.SimpleGeometry.prototype.setCoordinates = goog.abstractMethod;
* @param {number} nesting Nesting.
* @protected
*/
-ol.geom.SimpleGeometry.prototype.setLayout =
- function(layout, coordinates, nesting) {
+ol.geom.SimpleGeometry.prototype.setLayout = function(layout, coordinates, nesting) {
/** @type {number} */
var stride;
if (layout) {
@@ -20145,7 +13437,7 @@ ol.geom.SimpleGeometry.prototype.setLayout =
coordinates = /** @type {Array} */ (coordinates[0]);
}
}
- stride = (/** @type {Array} */ (coordinates)).length;
+ stride = coordinates.length;
layout = ol.geom.SimpleGeometry.getLayoutForStride_(stride);
}
this.layout = layout;
@@ -20167,6 +13459,22 @@ ol.geom.SimpleGeometry.prototype.applyTransform = function(transformFn) {
/**
* @inheritDoc
+ * @api
+ */
+ol.geom.SimpleGeometry.prototype.rotate = function(angle, anchor) {
+ var flatCoordinates = this.getFlatCoordinates();
+ if (flatCoordinates) {
+ var stride = this.getStride();
+ ol.geom.flat.transform.rotate(
+ flatCoordinates, 0, flatCoordinates.length,
+ stride, angle, anchor, flatCoordinates);
+ this.changed();
+ }
+};
+
+
+/**
+ * @inheritDoc
* @api stable
*/
ol.geom.SimpleGeometry.prototype.translate = function(deltaX, deltaY) {
@@ -20187,8 +13495,7 @@ ol.geom.SimpleGeometry.prototype.translate = function(deltaX, deltaY) {
* @param {Array.<number>=} opt_dest Destination.
* @return {Array.<number>} Transformed flat coordinates.
*/
-ol.geom.transformSimpleGeometry2D =
- function(simpleGeometry, transform, opt_dest) {
+ol.geom.transformSimpleGeometry2D = function(simpleGeometry, transform, opt_dest) {
var flatCoordinates = simpleGeometry.getFlatCoordinates();
if (!flatCoordinates) {
return null;
@@ -20232,8 +13539,7 @@ ol.geom.flat.area.linearRing = function(flatCoordinates, offset, end, stride) {
* @param {number} stride Stride.
* @return {number} Area.
*/
-ol.geom.flat.area.linearRings =
- function(flatCoordinates, offset, ends, stride) {
+ol.geom.flat.area.linearRings = function(flatCoordinates, offset, ends, stride) {
var area = 0;
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
@@ -20252,8 +13558,7 @@ ol.geom.flat.area.linearRings =
* @param {number} stride Stride.
* @return {number} Area.
*/
-ol.geom.flat.area.linearRingss =
- function(flatCoordinates, offset, endss, stride) {
+ol.geom.flat.area.linearRingss = function(flatCoordinates, offset, endss, stride) {
var area = 0;
var i, ii;
for (i = 0, ii = endss.length; i < ii; ++i) {
@@ -20268,7 +13573,6 @@ ol.geom.flat.area.linearRingss =
goog.provide('ol.geom.flat.closest');
goog.require('goog.asserts');
-goog.require('goog.math');
goog.require('ol.math');
@@ -20284,8 +13588,7 @@ goog.require('ol.math');
* @param {number} y Y.
* @param {Array.<number>} closestPoint Closest point.
*/
-ol.geom.flat.closest.point =
- function(flatCoordinates, offset1, offset2, stride, x, y, closestPoint) {
+ol.geom.flat.closest.point = function(flatCoordinates, offset1, offset2, stride, x, y, closestPoint) {
var x1 = flatCoordinates[offset1];
var y1 = flatCoordinates[offset1 + 1];
var dx = flatCoordinates[offset2] - x1;
@@ -20299,7 +13602,7 @@ ol.geom.flat.closest.point =
offset = offset2;
} else if (t > 0) {
for (i = 0; i < stride; ++i) {
- closestPoint[i] = goog.math.lerp(flatCoordinates[offset1 + i],
+ closestPoint[i] = ol.math.lerp(flatCoordinates[offset1 + i],
flatCoordinates[offset2 + i], t);
}
closestPoint.length = stride;
@@ -20325,8 +13628,7 @@ ol.geom.flat.closest.point =
* @param {number} maxSquaredDelta Max squared delta.
* @return {number} Max squared delta.
*/
-ol.geom.flat.closest.getMaxSquaredDelta =
- function(flatCoordinates, offset, end, stride, maxSquaredDelta) {
+ol.geom.flat.closest.getMaxSquaredDelta = function(flatCoordinates, offset, end, stride, maxSquaredDelta) {
var x1 = flatCoordinates[offset];
var y1 = flatCoordinates[offset + 1];
for (offset += stride; offset < end; offset += stride) {
@@ -20351,8 +13653,7 @@ ol.geom.flat.closest.getMaxSquaredDelta =
* @param {number} maxSquaredDelta Max squared delta.
* @return {number} Max squared delta.
*/
-ol.geom.flat.closest.getsMaxSquaredDelta =
- function(flatCoordinates, offset, ends, stride, maxSquaredDelta) {
+ol.geom.flat.closest.getsMaxSquaredDelta = function(flatCoordinates, offset, ends, stride, maxSquaredDelta) {
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
var end = ends[i];
@@ -20372,8 +13673,7 @@ ol.geom.flat.closest.getsMaxSquaredDelta =
* @param {number} maxSquaredDelta Max squared delta.
* @return {number} Max squared delta.
*/
-ol.geom.flat.closest.getssMaxSquaredDelta =
- function(flatCoordinates, offset, endss, stride, maxSquaredDelta) {
+ol.geom.flat.closest.getssMaxSquaredDelta = function(flatCoordinates, offset, endss, stride, maxSquaredDelta) {
var i, ii;
for (i = 0, ii = endss.length; i < ii; ++i) {
var ends = endss[i];
@@ -20538,8 +13838,7 @@ goog.require('goog.asserts');
* @param {number} stride Stride.
* @return {number} offset Offset.
*/
-ol.geom.flat.deflate.coordinate =
- function(flatCoordinates, offset, coordinate, stride) {
+ol.geom.flat.deflate.coordinate = function(flatCoordinates, offset, coordinate, stride) {
goog.asserts.assert(coordinate.length == stride,
'length of the coordinate array should match stride');
var i, ii;
@@ -20557,8 +13856,7 @@ ol.geom.flat.deflate.coordinate =
* @param {number} stride Stride.
* @return {number} offset Offset.
*/
-ol.geom.flat.deflate.coordinates =
- function(flatCoordinates, offset, coordinates, stride) {
+ol.geom.flat.deflate.coordinates = function(flatCoordinates, offset, coordinates, stride) {
var i, ii;
for (i = 0, ii = coordinates.length; i < ii; ++i) {
var coordinate = coordinates[i];
@@ -20581,8 +13879,7 @@ ol.geom.flat.deflate.coordinates =
* @param {Array.<number>=} opt_ends Ends.
* @return {Array.<number>} Ends.
*/
-ol.geom.flat.deflate.coordinatess =
- function(flatCoordinates, offset, coordinatess, stride, opt_ends) {
+ol.geom.flat.deflate.coordinatess = function(flatCoordinates, offset, coordinatess, stride, opt_ends) {
var ends = opt_ends ? opt_ends : [];
var i = 0;
var j, jj;
@@ -20605,8 +13902,7 @@ ol.geom.flat.deflate.coordinatess =
* @param {Array.<Array.<number>>=} opt_endss Endss.
* @return {Array.<Array.<number>>} Endss.
*/
-ol.geom.flat.deflate.coordinatesss =
- function(flatCoordinates, offset, coordinatesss, stride, opt_endss) {
+ol.geom.flat.deflate.coordinatesss = function(flatCoordinates, offset, coordinatesss, stride, opt_endss) {
var endss = opt_endss ? opt_endss : [];
var i = 0;
var j, jj;
@@ -20631,8 +13927,7 @@ goog.provide('ol.geom.flat.inflate');
* @param {Array.<ol.Coordinate>=} opt_coordinates Coordinates.
* @return {Array.<ol.Coordinate>} Coordinates.
*/
-ol.geom.flat.inflate.coordinates =
- function(flatCoordinates, offset, end, stride, opt_coordinates) {
+ol.geom.flat.inflate.coordinates = function(flatCoordinates, offset, end, stride, opt_coordinates) {
var coordinates = opt_coordinates !== undefined ? opt_coordinates : [];
var i = 0;
var j;
@@ -20652,8 +13947,7 @@ ol.geom.flat.inflate.coordinates =
* @param {Array.<Array.<ol.Coordinate>>=} opt_coordinatess Coordinatess.
* @return {Array.<Array.<ol.Coordinate>>} Coordinatess.
*/
-ol.geom.flat.inflate.coordinatess =
- function(flatCoordinates, offset, ends, stride, opt_coordinatess) {
+ol.geom.flat.inflate.coordinatess = function(flatCoordinates, offset, ends, stride, opt_coordinatess) {
var coordinatess = opt_coordinatess !== undefined ? opt_coordinatess : [];
var i = 0;
var j, jj;
@@ -20677,8 +13971,7 @@ ol.geom.flat.inflate.coordinatess =
* Coordinatesss.
* @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinatesss.
*/
-ol.geom.flat.inflate.coordinatesss =
- function(flatCoordinates, offset, endss, stride, opt_coordinatesss) {
+ol.geom.flat.inflate.coordinatesss = function(flatCoordinates, offset, endss, stride, opt_coordinatesss) {
var coordinatesss = opt_coordinatesss !== undefined ? opt_coordinatesss : [];
var i = 0;
var j, jj;
@@ -21106,7 +14399,6 @@ goog.require('ol.geom.flat.inflate');
goog.require('ol.geom.flat.simplify');
-
/**
* @classdesc
* Linear ring geometry. Only used as part of polygon; cannot be rendered
@@ -21155,8 +14447,7 @@ ol.geom.LinearRing.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.LinearRing.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.LinearRing.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance <
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
@@ -21197,8 +14488,7 @@ ol.geom.LinearRing.prototype.getCoordinates = function() {
/**
* @inheritDoc
*/
-ol.geom.LinearRing.prototype.getSimplifiedGeometryInternal =
- function(squaredTolerance) {
+ol.geom.LinearRing.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
var simplifiedFlatCoordinates = [];
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
@@ -21225,8 +14515,7 @@ ol.geom.LinearRing.prototype.getType = function() {
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
* @api stable
*/
-ol.geom.LinearRing.prototype.setCoordinates =
- function(coordinates, opt_layout) {
+ol.geom.LinearRing.prototype.setCoordinates = function(coordinates, opt_layout) {
if (!coordinates) {
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
} else {
@@ -21245,8 +14534,7 @@ ol.geom.LinearRing.prototype.setCoordinates =
* @param {ol.geom.GeometryLayout} layout Layout.
* @param {Array.<number>} flatCoordinates Flat coordinates.
*/
-ol.geom.LinearRing.prototype.setFlatCoordinates =
- function(layout, flatCoordinates) {
+ol.geom.LinearRing.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
this.setFlatCoordinatesInternal(layout, flatCoordinates);
this.changed();
};
@@ -21261,7 +14549,6 @@ goog.require('ol.geom.flat.deflate');
goog.require('ol.math');
-
/**
* @classdesc
* Point geometry.
@@ -21294,8 +14581,7 @@ ol.geom.Point.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.Point.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.Point.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
var flatCoordinates = this.flatCoordinates;
var squaredDistance = ol.math.squaredDistance(
x, y, flatCoordinates[0], flatCoordinates[1]);
@@ -21394,11 +14680,11 @@ goog.require('ol.extent');
* @param {ol.Extent} extent Extent.
* @return {boolean} Contains extent.
*/
-ol.geom.flat.contains.linearRingContainsExtent =
- function(flatCoordinates, offset, end, stride, extent) {
+ol.geom.flat.contains.linearRingContainsExtent = function(flatCoordinates, offset, end, stride, extent) {
var outside = ol.extent.forEachCorner(extent,
/**
* @param {ol.Coordinate} coordinate Coordinate.
+ * @return {boolean} Contains (x, y).
*/
function(coordinate) {
return !ol.geom.flat.contains.linearRingContainsXY(flatCoordinates,
@@ -21417,8 +14703,7 @@ ol.geom.flat.contains.linearRingContainsExtent =
* @param {number} y Y.
* @return {boolean} Contains (x, y).
*/
-ol.geom.flat.contains.linearRingContainsXY =
- function(flatCoordinates, offset, end, stride, x, y) {
+ol.geom.flat.contains.linearRingContainsXY = function(flatCoordinates, offset, end, stride, x, y) {
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
var contains = false;
var x1 = flatCoordinates[end - stride];
@@ -21447,8 +14732,7 @@ ol.geom.flat.contains.linearRingContainsXY =
* @param {number} y Y.
* @return {boolean} Contains (x, y).
*/
-ol.geom.flat.contains.linearRingsContainsXY =
- function(flatCoordinates, offset, ends, stride, x, y) {
+ol.geom.flat.contains.linearRingsContainsXY = function(flatCoordinates, offset, ends, stride, x, y) {
goog.asserts.assert(ends.length > 0, 'ends should not be an empty array');
if (ends.length === 0) {
return false;
@@ -21477,8 +14761,7 @@ ol.geom.flat.contains.linearRingsContainsXY =
* @param {number} y Y.
* @return {boolean} Contains (x, y).
*/
-ol.geom.flat.contains.linearRingssContainsXY =
- function(flatCoordinates, offset, endss, stride, x, y) {
+ol.geom.flat.contains.linearRingssContainsXY = function(flatCoordinates, offset, endss, stride, x, y) {
goog.asserts.assert(endss.length > 0, 'endss should not be an empty array');
if (endss.length === 0) {
return false;
@@ -21575,8 +14858,7 @@ ol.geom.flat.interiorpoint.linearRings = function(flatCoordinates, offset,
* @param {Array.<number>} flatCenters Flat centers.
* @return {Array.<number>} Interior points.
*/
-ol.geom.flat.interiorpoint.linearRingss =
- function(flatCoordinates, offset, endss, stride, flatCenters) {
+ol.geom.flat.interiorpoint.linearRingss = function(flatCoordinates, offset, endss, stride, flatCenters) {
goog.asserts.assert(2 * endss.length == flatCenters.length,
'endss.length times 2 should be flatCenters.length');
var interiorPoints = [];
@@ -21608,8 +14890,7 @@ goog.provide('ol.geom.flat.segments');
* @return {T|boolean} Value.
* @template T,S
*/
-ol.geom.flat.segments.forEach =
- function(flatCoordinates, offset, end, stride, callback, opt_this) {
+ol.geom.flat.segments.forEach = function(flatCoordinates, offset, end, stride, callback, opt_this) {
var point1 = [flatCoordinates[offset], flatCoordinates[offset + 1]];
var point2 = [];
var ret;
@@ -21642,8 +14923,7 @@ goog.require('ol.geom.flat.segments');
* @param {ol.Extent} extent Extent.
* @return {boolean} True if the geometry and the extent intersect.
*/
-ol.geom.flat.intersectsextent.lineString =
- function(flatCoordinates, offset, end, stride, extent) {
+ol.geom.flat.intersectsextent.lineString = function(flatCoordinates, offset, end, stride, extent) {
var coordinatesExtent = ol.extent.extendFlatCoordinates(
ol.extent.createEmpty(), flatCoordinates, offset, end, stride);
if (!ol.extent.intersects(extent, coordinatesExtent)) {
@@ -21681,8 +14961,7 @@ ol.geom.flat.intersectsextent.lineString =
* @param {ol.Extent} extent Extent.
* @return {boolean} True if the geometry and the extent intersect.
*/
-ol.geom.flat.intersectsextent.lineStrings =
- function(flatCoordinates, offset, ends, stride, extent) {
+ol.geom.flat.intersectsextent.lineStrings = function(flatCoordinates, offset, ends, stride, extent) {
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
if (ol.geom.flat.intersectsextent.lineString(
@@ -21703,8 +14982,7 @@ ol.geom.flat.intersectsextent.lineStrings =
* @param {ol.Extent} extent Extent.
* @return {boolean} True if the geometry and the extent intersect.
*/
-ol.geom.flat.intersectsextent.linearRing =
- function(flatCoordinates, offset, end, stride, extent) {
+ol.geom.flat.intersectsextent.linearRing = function(flatCoordinates, offset, end, stride, extent) {
if (ol.geom.flat.intersectsextent.lineString(
flatCoordinates, offset, end, stride, extent)) {
return true;
@@ -21737,8 +15015,7 @@ ol.geom.flat.intersectsextent.linearRing =
* @param {ol.Extent} extent Extent.
* @return {boolean} True if the geometry and the extent intersect.
*/
-ol.geom.flat.intersectsextent.linearRings =
- function(flatCoordinates, offset, ends, stride, extent) {
+ol.geom.flat.intersectsextent.linearRings = function(flatCoordinates, offset, ends, stride, extent) {
goog.asserts.assert(ends.length > 0, 'ends should not be an empty array');
if (!ol.geom.flat.intersectsextent.linearRing(
flatCoordinates, offset, ends[0], stride, extent)) {
@@ -21766,8 +15043,7 @@ ol.geom.flat.intersectsextent.linearRings =
* @param {ol.Extent} extent Extent.
* @return {boolean} True if the geometry and the extent intersect.
*/
-ol.geom.flat.intersectsextent.linearRingss =
- function(flatCoordinates, offset, endss, stride, extent) {
+ol.geom.flat.intersectsextent.linearRingss = function(flatCoordinates, offset, endss, stride, extent) {
goog.asserts.assert(endss.length > 0, 'endss should not be an empty array');
var i, ii;
for (i = 0, ii = endss.length; i < ii; ++i) {
@@ -21790,8 +15066,7 @@ goog.provide('ol.geom.flat.reverse');
* @param {number} end End.
* @param {number} stride Stride.
*/
-ol.geom.flat.reverse.coordinates =
- function(flatCoordinates, offset, end, stride) {
+ol.geom.flat.reverse.coordinates = function(flatCoordinates, offset, end, stride) {
while (offset < end - stride) {
var i;
for (i = 0; i < stride; ++i) {
@@ -21817,8 +15092,7 @@ goog.require('ol.geom.flat.reverse');
* @param {number} stride Stride.
* @return {boolean} Is clockwise.
*/
-ol.geom.flat.orient.linearRingIsClockwise =
- function(flatCoordinates, offset, end, stride) {
+ol.geom.flat.orient.linearRingIsClockwise = function(flatCoordinates, offset, end, stride) {
// http://tinyurl.com/clockwise-method
// https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp
var edge = 0;
@@ -21848,8 +15122,7 @@ ol.geom.flat.orient.linearRingIsClockwise =
* (counter-clockwise exterior ring and clockwise interior rings).
* @return {boolean} Rings are correctly oriented.
*/
-ol.geom.flat.orient.linearRingsAreOriented =
- function(flatCoordinates, offset, ends, stride, opt_right) {
+ol.geom.flat.orient.linearRingsAreOriented = function(flatCoordinates, offset, ends, stride, opt_right) {
var right = opt_right !== undefined ? opt_right : false;
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
@@ -21884,8 +15157,7 @@ ol.geom.flat.orient.linearRingsAreOriented =
* (counter-clockwise exterior ring and clockwise interior rings).
* @return {boolean} Rings are correctly oriented.
*/
-ol.geom.flat.orient.linearRingssAreOriented =
- function(flatCoordinates, offset, endss, stride, opt_right) {
+ol.geom.flat.orient.linearRingssAreOriented = function(flatCoordinates, offset, endss, stride, opt_right) {
var i, ii;
for (i = 0, ii = endss.length; i < ii; ++i) {
if (!ol.geom.flat.orient.linearRingsAreOriented(
@@ -21910,8 +15182,7 @@ ol.geom.flat.orient.linearRingssAreOriented =
* @param {boolean=} opt_right Follow the right-hand rule for orientation.
* @return {number} End.
*/
-ol.geom.flat.orient.orientLinearRings =
- function(flatCoordinates, offset, ends, stride, opt_right) {
+ol.geom.flat.orient.orientLinearRings = function(flatCoordinates, offset, ends, stride, opt_right) {
var right = opt_right !== undefined ? opt_right : false;
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
@@ -21943,8 +15214,7 @@ ol.geom.flat.orient.orientLinearRings =
* @param {boolean=} opt_right Follow the right-hand rule for orientation.
* @return {number} End.
*/
-ol.geom.flat.orient.orientLinearRingss =
- function(flatCoordinates, offset, endss, stride, opt_right) {
+ol.geom.flat.orient.orientLinearRingss = function(flatCoordinates, offset, endss, stride, opt_right) {
var i, ii;
for (i = 0, ii = endss.length; i < ii; ++i) {
offset = ol.geom.flat.orient.orientLinearRings(
@@ -21955,10 +15225,9 @@ ol.geom.flat.orient.orientLinearRingss =
goog.provide('ol.geom.Polygon');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.math');
goog.require('ol');
+goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.geom.GeometryLayout');
goog.require('ol.geom.GeometryType');
@@ -21974,7 +15243,7 @@ goog.require('ol.geom.flat.interiorpoint');
goog.require('ol.geom.flat.intersectsextent');
goog.require('ol.geom.flat.orient');
goog.require('ol.geom.flat.simplify');
-
+goog.require('ol.math');
/**
@@ -22050,7 +15319,7 @@ ol.geom.Polygon.prototype.appendLinearRing = function(linearRing) {
if (!this.flatCoordinates) {
this.flatCoordinates = linearRing.getFlatCoordinates().slice();
} else {
- goog.array.extend(this.flatCoordinates, linearRing.getFlatCoordinates());
+ ol.array.extend(this.flatCoordinates, linearRing.getFlatCoordinates());
}
this.ends_.push(this.flatCoordinates.length);
this.changed();
@@ -22073,8 +15342,7 @@ ol.geom.Polygon.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.Polygon.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.Polygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance <
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
@@ -22253,8 +15521,7 @@ ol.geom.Polygon.prototype.getOrientedFlatCoordinates = function() {
/**
* @inheritDoc
*/
-ol.geom.Polygon.prototype.getSimplifiedGeometryInternal =
- function(squaredTolerance) {
+ol.geom.Polygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
var simplifiedFlatCoordinates = [];
var simplifiedEnds = [];
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizes(
@@ -22314,8 +15581,7 @@ ol.geom.Polygon.prototype.setCoordinates = function(coordinates, opt_layout) {
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {Array.<number>} ends Ends.
*/
-ol.geom.Polygon.prototype.setFlatCoordinates =
- function(layout, flatCoordinates, ends) {
+ol.geom.Polygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) {
if (!flatCoordinates) {
goog.asserts.assert(ends && ends.length === 0,
'ends must be an empty array');
@@ -22349,7 +15615,7 @@ ol.geom.Polygon.circular = function(sphere, center, radius, opt_n) {
var flatCoordinates = [];
var i;
for (i = 0; i < n; ++i) {
- goog.array.extend(
+ ol.array.extend(
flatCoordinates, sphere.offset(center, radius, 2 * Math.PI * i / n));
}
flatCoordinates.push(flatCoordinates[0], flatCoordinates[1]);
@@ -22394,7 +15660,11 @@ ol.geom.Polygon.fromCircle = function(circle, opt_sides, opt_angle) {
var stride = circle.getStride();
var layout = circle.getLayout();
var polygon = new ol.geom.Polygon(null, layout);
- var flatCoordinates = goog.array.repeat(0, stride * (sides + 1));
+ var arrayLength = stride * (sides + 1);
+ var flatCoordinates = new Array(arrayLength);
+ for (var i = 0; i < arrayLength; i++) {
+ flatCoordinates[i] = 0;
+ }
var ends = [flatCoordinates.length];
polygon.setFlatCoordinates(layout, flatCoordinates, ends);
ol.geom.Polygon.makeRegular(
@@ -22422,7 +15692,7 @@ ol.geom.Polygon.makeRegular = function(polygon, center, radius, opt_angle) {
var angle, offset;
for (var i = 0; i <= sides; ++i) {
offset = i * stride;
- angle = startAngle + (goog.math.modulo(i, sides) * 2 * Math.PI / sides);
+ angle = startAngle + (ol.math.modulo(i, sides) * 2 * Math.PI / sides);
flatCoordinates[offset] = center[0] + (radius * Math.cos(angle));
flatCoordinates[offset + 1] = center[1] + (radius * Math.sin(angle));
}
@@ -22440,8 +15710,6 @@ goog.require('ol.Constraints');
goog.require('ol.Object');
goog.require('ol.ResolutionConstraint');
goog.require('ol.RotationConstraint');
-goog.require('ol.RotationConstraintType');
-goog.require('ol.Size');
goog.require('ol.coordinate');
goog.require('ol.extent');
goog.require('ol.geom.Polygon');
@@ -22471,7 +15739,6 @@ ol.ViewHint = {
};
-
/**
* @classdesc
* An ol.View object represents a simple 2D view of the map.
@@ -22570,6 +15837,12 @@ ol.View = function(opt_options) {
/**
* @private
+ * @type {Array.<number>|undefined}
+ */
+ this.resolutions_ = options.resolutions;
+
+ /**
+ * @private
* @type {number}
*/
this.minZoom_ = resolutionConstraintInfo.minZoom;
@@ -22688,10 +15961,17 @@ ol.View.prototype.getCenter = function() {
/**
+ * @param {Array.<number>=} opt_hints Destination array.
* @return {Array.<number>} Hint.
*/
-ol.View.prototype.getHints = function() {
- return this.hints_.slice();
+ol.View.prototype.getHints = function(opt_hints) {
+ if (opt_hints !== undefined) {
+ opt_hints[0] = this.hints_[0];
+ opt_hints[1] = this.hints_[1];
+ return opt_hints;
+ } else {
+ return this.hints_.slice();
+ }
};
@@ -22741,6 +16021,17 @@ ol.View.prototype.getResolution = function() {
/**
+ * Get the resolutions for the view. This returns the array of resolutions
+ * passed to the constructor of the {ol.View}, or undefined if none were given.
+ * @return {Array.<number>|undefined} The resolutions of the view.
+ * @api stable
+ */
+ol.View.prototype.getResolutions = function() {
+ return this.resolutions_;
+};
+
+
+/**
* Get the resolution for a provided extent (in map units) and size (in pixels).
* @param {ol.Extent} extent Extent.
* @param {ol.Size} size Box pixel size.
@@ -22879,7 +16170,7 @@ ol.View.prototype.getZoom = function() {
*/
ol.View.prototype.fit = function(geometry, size, opt_options) {
if (!(geometry instanceof ol.geom.SimpleGeometry)) {
- goog.asserts.assert(goog.isArray(geometry),
+ goog.asserts.assert(Array.isArray(geometry),
'invalid extent or geometry');
goog.asserts.assert(!ol.extent.isEmpty(geometry),
'cannot fit empty extent');
@@ -23064,7 +16355,7 @@ ol.View.prototype.setZoom = function(zoom) {
/**
* @param {olx.ViewOptions} options View options.
* @private
- * @return {ol.CenterConstraintType}
+ * @return {ol.CenterConstraintType} The constraint.
*/
ol.View.createCenterConstraint_ = function(options) {
if (options.extent !== undefined) {
@@ -23079,7 +16370,7 @@ ol.View.createCenterConstraint_ = function(options) {
* @private
* @param {olx.ViewOptions} options View options.
* @return {{constraint: ol.ResolutionConstraintType, maxResolution: number,
- * minResolution: number}}
+ * minResolution: number}} The constraint.
*/
ol.View.createResolutionConstraint_ = function(options) {
var resolutionConstraint;
@@ -23113,7 +16404,7 @@ ol.View.createResolutionConstraint_ = function(options) {
var size = !extent ?
// use an extent that can fit the whole world if need be
360 * ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] /
- ol.proj.METERS_PER_UNIT[projection.getUnits()] :
+ projection.getMetersPerUnit() :
Math.max(ol.extent.getWidth(extent), ol.extent.getHeight(extent));
var defaultMaxResolution = size / ol.DEFAULT_TILE_SIZE / Math.pow(
@@ -23249,7 +16540,6 @@ ol.easing.upAndDown = function(t) {
goog.provide('ol.animation');
goog.require('ol');
-goog.require('ol.PreRenderFunction');
goog.require('ol.ViewHint');
goog.require('ol.coordinate');
goog.require('ol.easing');
@@ -23272,6 +16562,7 @@ ol.animation.bounce = function(options) {
/**
* @param {ol.Map} map Map.
* @param {?olx.FrameState} frameState Frame state.
+ * @return {boolean} Run this function in the next frame.
*/
function(map, frameState) {
if (frameState.time < start) {
@@ -23310,6 +16601,7 @@ ol.animation.pan = function(options) {
/**
* @param {ol.Map} map Map.
* @param {?olx.FrameState} frameState Frame state.
+ * @return {boolean} Run this function in the next frame.
*/
function(map, frameState) {
if (frameState.time < start) {
@@ -23351,6 +16643,7 @@ ol.animation.rotate = function(options) {
/**
* @param {ol.Map} map Map.
* @param {?olx.FrameState} frameState Frame state.
+ * @return {boolean} Run this function in the next frame.
*/
function(map, frameState) {
if (frameState.time < start) {
@@ -23394,6 +16687,7 @@ ol.animation.zoom = function(options) {
/**
* @param {ol.Map} map Map.
* @param {?olx.FrameState} frameState Frame state.
+ * @return {boolean} Run this function in the next frame.
*/
function(map, frameState) {
if (frameState.time < start) {
@@ -23414,174 +16708,9 @@ ol.animation.zoom = function(options) {
});
};
-goog.provide('ol.TileCoord');
-goog.provide('ol.tilecoord');
-
-goog.require('goog.asserts');
-goog.require('ol.extent');
-
-
-/**
- * An array of three numbers representing the location of a tile in a tile
- * grid. The order is `z`, `x`, and `y`. `z` is the zoom level.
- * @typedef {Array.<number>} ol.TileCoord
- * @api
- */
-ol.TileCoord;
-
-
-/**
- * @enum {number}
- */
-ol.QuadKeyCharCode = {
- ZERO: '0'.charCodeAt(0),
- ONE: '1'.charCodeAt(0),
- TWO: '2'.charCodeAt(0),
- THREE: '3'.charCodeAt(0)
-};
-
-
-/**
- * @param {string} str String that follows pattern “z/x/y” where x, y and z are
- * numbers.
- * @return {ol.TileCoord} Tile coord.
- */
-ol.tilecoord.createFromString = function(str) {
- var v = str.split('/');
- goog.asserts.assert(v.length === 3,
- 'must provide a string in "z/x/y" format, got "%s"', str);
- return v.map(function(e) {
- return parseInt(e, 10);
- });
-};
-
-
-/**
- * @param {number} z Z.
- * @param {number} x X.
- * @param {number} y Y.
- * @param {ol.TileCoord=} opt_tileCoord Tile coordinate.
- * @return {ol.TileCoord} Tile coordinate.
- */
-ol.tilecoord.createOrUpdate = function(z, x, y, opt_tileCoord) {
- if (opt_tileCoord !== undefined) {
- opt_tileCoord[0] = z;
- opt_tileCoord[1] = x;
- opt_tileCoord[2] = y;
- return opt_tileCoord;
- } else {
- return [z, x, y];
- }
-};
-
-
-/**
- * @param {number} z Z.
- * @param {number} x X.
- * @param {number} y Y.
- * @return {string} Key.
- */
-ol.tilecoord.getKeyZXY = function(z, x, y) {
- return z + '/' + x + '/' + y;
-};
-
-
-/**
- * @param {ol.TileCoord} tileCoord Tile coord.
- * @return {number} Hash.
- */
-ol.tilecoord.hash = function(tileCoord) {
- return (tileCoord[1] << tileCoord[0]) + tileCoord[2];
-};
-
-
-/**
- * @param {ol.TileCoord} tileCoord Tile coord.
- * @return {string} Quad key.
- */
-ol.tilecoord.quadKey = function(tileCoord) {
- var z = tileCoord[0];
- var digits = new Array(z);
- var mask = 1 << (z - 1);
- var i, charCode;
- for (i = 0; i < z; ++i) {
- charCode = ol.QuadKeyCharCode.ZERO;
- if (tileCoord[1] & mask) {
- charCode += 1;
- }
- if (tileCoord[2] & mask) {
- charCode += 2;
- }
- digits[i] = String.fromCharCode(charCode);
- mask >>= 1;
- }
- return digits.join('');
-};
-
-
-/**
- * @param {ol.TileCoord} tileCoord Tile coord.
- * @return {string} String.
- */
-ol.tilecoord.toString = function(tileCoord) {
- return ol.tilecoord.getKeyZXY(tileCoord[0], tileCoord[1], tileCoord[2]);
-};
-
-
-/**
- * @param {ol.TileCoord} tileCoord Tile coordinate.
- * @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
- * @param {ol.proj.Projection} projection Projection.
- * @return {ol.TileCoord} Tile coordinate.
- */
-ol.tilecoord.wrapX = function(tileCoord, tileGrid, projection) {
- var z = tileCoord[0];
- var center = tileGrid.getTileCoordCenter(tileCoord);
- var projectionExtent = ol.tilegrid.extentFromProjection(projection);
- if (!ol.extent.containsCoordinate(projectionExtent, center)) {
- var worldWidth = ol.extent.getWidth(projectionExtent);
- var worldsAway = Math.ceil((projectionExtent[0] - center[0]) / worldWidth);
- center[0] += worldWidth * worldsAway;
- return tileGrid.getTileCoordForCoordAndZ(center, z);
- } else {
- return tileCoord;
- }
-};
-
-
-/**
- * @param {ol.TileCoord} tileCoord Tile coordinate.
- * @param {!ol.tilegrid.TileGrid} tileGrid Tile grid.
- * @return {boolean} Tile coordinate is within extent and zoom level range.
- */
-ol.tilecoord.withinExtentAndZ = function(tileCoord, tileGrid) {
- var z = tileCoord[0];
- var x = tileCoord[1];
- var y = tileCoord[2];
-
- if (tileGrid.getMinZoom() > z || z > tileGrid.getMaxZoom()) {
- return false;
- }
- var extent = tileGrid.getExtent();
- var tileRange;
- if (!extent) {
- tileRange = tileGrid.getFullTileRange(z);
- } else {
- tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
- }
- if (!tileRange) {
- return true;
- } else {
- return tileRange.containsXY(x, y);
- }
-};
-
goog.provide('ol.TileRange');
goog.require('goog.asserts');
-goog.require('ol.Size');
-goog.require('ol.TileCoord');
-
/**
@@ -23764,9 +16893,8 @@ ol.TileRange.prototype.intersects = function(tileRange) {
goog.provide('ol.Attribution');
-goog.require('goog.math');
goog.require('ol.TileRange');
-
+goog.require('ol.math');
/**
@@ -23823,8 +16951,7 @@ ol.Attribution.prototype.getHTML = function() {
* @param {!ol.proj.Projection} projection Projection.
* @return {boolean} Intersects any tile range.
*/
-ol.Attribution.prototype.intersectsAnyTileRange =
- function(tileRanges, tileGrid, projection) {
+ol.Attribution.prototype.intersectsAnyTileRange = function(tileRanges, tileGrid, projection) {
if (!this.tileRanges_) {
return true;
}
@@ -23841,13 +16968,13 @@ ol.Attribution.prototype.intersectsAnyTileRange =
return true;
}
var extentTileRange = tileGrid.getTileRangeForExtentAndZ(
- projection.getExtent(), parseInt(zKey, 10));
+ ol.tilegrid.extentFromProjection(projection), parseInt(zKey, 10));
var width = extentTileRange.getWidth();
if (tileRange.minX < extentTileRange.minX ||
tileRange.maxX > extentTileRange.maxX) {
if (testTileRange.intersects(new ol.TileRange(
- goog.math.modulo(tileRange.minX, width),
- goog.math.modulo(tileRange.maxX, width),
+ ol.math.modulo(tileRange.minX, width),
+ ol.math.modulo(tileRange.maxX, width),
tileRange.minY, tileRange.maxY))) {
return true;
}
@@ -23861,24 +16988,6 @@ ol.Attribution.prototype.intersectsAnyTileRange =
return false;
};
-goog.provide('ol.CanvasFunctionType');
-
-
-/**
- * A function returning the canvas element (`{HTMLCanvasElement}`)
- * used by the source as an image. The arguments passed to the function are:
- * {@link ol.Extent} the image extent, `{number}` the image resolution,
- * `{number}` the device pixel ratio, {@link ol.Size} the image size, and
- * {@link ol.proj.Projection} the image projection. The canvas returned by
- * this function is cached by the source. The this keyword inside the function
- * references the {@link ol.source.ImageCanvas}.
- *
- * @typedef {function(this:ol.source.ImageCanvas, ol.Extent, number,
- * number, ol.Size, ol.proj.Projection): HTMLCanvasElement}
- * @api
- */
-ol.CanvasFunctionType;
-
/**
* An implementation of Google Maps' MVCArray.
* @see https://developers.google.com/maps/documentation/javascript/reference
@@ -23888,8 +16997,7 @@ goog.provide('ol.Collection');
goog.provide('ol.CollectionEvent');
goog.provide('ol.CollectionEventType');
-goog.require('goog.array');
-goog.require('goog.events.Event');
+goog.require('ol.events.Event');
goog.require('ol.Object');
@@ -23912,14 +17020,13 @@ ol.CollectionEventType = {
};
-
/**
* @classdesc
* Events emitted by {@link ol.Collection} instances are instances of this
* type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.CollectionEvent}
* @param {ol.CollectionEventType} type Type.
* @param {*=} opt_element Element.
@@ -23937,7 +17044,7 @@ ol.CollectionEvent = function(type, opt_element, opt_target) {
this.element = opt_element;
};
-goog.inherits(ol.CollectionEvent, goog.events.Event);
+goog.inherits(ol.CollectionEvent, ol.events.Event);
/**
@@ -23948,7 +17055,6 @@ ol.CollectionProperty = {
};
-
/**
* @classdesc
* An expanded version of standard JS Array, adding convenience methods for
@@ -24063,7 +17169,7 @@ ol.Collection.prototype.getLength = function() {
* @api stable
*/
ol.Collection.prototype.insertAt = function(index, elem) {
- goog.array.insertAt(this.array_, elem, index);
+ this.array_.splice(index, 0, elem);
this.updateLength_();
this.dispatchEvent(
new ol.CollectionEvent(ol.CollectionEventType.ADD, elem, this));
@@ -24121,7 +17227,7 @@ ol.Collection.prototype.remove = function(elem) {
*/
ol.Collection.prototype.removeAt = function(index) {
var prev = this.array_[index];
- goog.array.removeAt(this.array_, index);
+ this.array_.splice(index, 1);
this.updateLength_();
this.dispatchEvent(
new ol.CollectionEvent(ol.CollectionEventType.REMOVE, prev, this));
@@ -24355,6 +17461,2100 @@ goog.color.names = {
// limitations under the License.
/**
+ * @fileoverview Utilities for manipulating arrays.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.array');
+
+goog.require('goog.asserts');
+
+
+/**
+ * @define {boolean} NATIVE_ARRAY_PROTOTYPES indicates whether the code should
+ * rely on Array.prototype functions, if available.
+ *
+ * The Array.prototype functions can be defined by external libraries like
+ * Prototype and setting this flag to false forces closure to use its own
+ * goog.array implementation.
+ *
+ * If your javascript can be loaded by a third party site and you are wary about
+ * relying on the prototype functions, specify
+ * "--define goog.NATIVE_ARRAY_PROTOTYPES=false" to the JSCompiler.
+ *
+ * Setting goog.TRUSTED_SITE to false will automatically set
+ * NATIVE_ARRAY_PROTOTYPES to false.
+ */
+goog.define('goog.NATIVE_ARRAY_PROTOTYPES', goog.TRUSTED_SITE);
+
+
+/**
+ * @define {boolean} If true, JSCompiler will use the native implementation of
+ * array functions where appropriate (e.g., {@code Array#filter}) and remove the
+ * unused pure JS implementation.
+ */
+goog.define('goog.array.ASSUME_NATIVE_FUNCTIONS', false);
+
+
+/**
+ * Returns the last element in an array without removing it.
+ * Same as goog.array.last.
+ * @param {IArrayLike<T>|string} array The array.
+ * @return {T} Last item in array.
+ * @template T
+ */
+goog.array.peek = function(array) {
+ return array[array.length - 1];
+};
+
+
+/**
+ * Returns the last element in an array without removing it.
+ * Same as goog.array.peek.
+ * @param {IArrayLike<T>|string} array The array.
+ * @return {T} Last item in array.
+ * @template T
+ */
+goog.array.last = goog.array.peek;
+
+// NOTE(arv): Since most of the array functions are generic it allows you to
+// pass an array-like object. Strings have a length and are considered array-
+// like. However, the 'in' operator does not work on strings so we cannot just
+// use the array path even if the browser supports indexing into strings. We
+// therefore end up splitting the string.
+
+
+/**
+ * Returns the index of the first element of an array with a specified value, or
+ * -1 if the element is not present in the array.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-indexof}
+ *
+ * @param {IArrayLike<T>|string} arr The array to be searched.
+ * @param {T} obj The object for which we are searching.
+ * @param {number=} opt_fromIndex The index at which to start the search. If
+ * omitted the search starts at index 0.
+ * @return {number} The index of the first matching array element.
+ * @template T
+ */
+goog.array.indexOf = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.indexOf) ?
+ function(arr, obj, opt_fromIndex) {
+ goog.asserts.assert(arr.length != null);
+
+ return Array.prototype.indexOf.call(arr, obj, opt_fromIndex);
+ } :
+ function(arr, obj, opt_fromIndex) {
+ var fromIndex = opt_fromIndex == null ?
+ 0 :
+ (opt_fromIndex < 0 ? Math.max(0, arr.length + opt_fromIndex) :
+ opt_fromIndex);
+
+ if (goog.isString(arr)) {
+ // Array.prototype.indexOf uses === so only strings should be found.
+ if (!goog.isString(obj) || obj.length != 1) {
+ return -1;
+ }
+ return arr.indexOf(obj, fromIndex);
+ }
+
+ for (var i = fromIndex; i < arr.length; i++) {
+ if (i in arr && arr[i] === obj) return i;
+ }
+ return -1;
+ };
+
+
+/**
+ * Returns the index of the last element of an array with a specified value, or
+ * -1 if the element is not present in the array.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-lastindexof}
+ *
+ * @param {!IArrayLike<T>|string} arr The array to be searched.
+ * @param {T} obj The object for which we are searching.
+ * @param {?number=} opt_fromIndex The index at which to start the search. If
+ * omitted the search starts at the end of the array.
+ * @return {number} The index of the last matching array element.
+ * @template T
+ */
+goog.array.lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.lastIndexOf) ?
+ function(arr, obj, opt_fromIndex) {
+ goog.asserts.assert(arr.length != null);
+
+ // Firefox treats undefined and null as 0 in the fromIndex argument which
+ // leads it to always return -1
+ var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
+ return Array.prototype.lastIndexOf.call(arr, obj, fromIndex);
+ } :
+ function(arr, obj, opt_fromIndex) {
+ var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
+
+ if (fromIndex < 0) {
+ fromIndex = Math.max(0, arr.length + fromIndex);
+ }
+
+ if (goog.isString(arr)) {
+ // Array.prototype.lastIndexOf uses === so only strings should be found.
+ if (!goog.isString(obj) || obj.length != 1) {
+ return -1;
+ }
+ return arr.lastIndexOf(obj, fromIndex);
+ }
+
+ for (var i = fromIndex; i >= 0; i--) {
+ if (i in arr && arr[i] === obj) return i;
+ }
+ return -1;
+ };
+
+
+/**
+ * Calls a function for each element in an array. Skips holes in the array.
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-foreach}
+ *
+ * @param {IArrayLike<T>|string} arr Array or array like object over
+ * which to iterate.
+ * @param {?function(this: S, T, number, ?): ?} f The function to call for every
+ * element. This function takes 3 arguments (the element, the index and the
+ * array). The return value is ignored.
+ * @param {S=} opt_obj The object to be used as the value of 'this' within f.
+ * @template T,S
+ */
+goog.array.forEach = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.forEach) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ Array.prototype.forEach.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2) {
+ f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);
+ }
+ }
+ };
+
+
+/**
+ * Calls a function for each element in an array, starting from the last
+ * element rather than the first.
+ *
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this: S, T, number, ?): ?} f The function to call for every
+ * element. This function
+ * takes 3 arguments (the element, the index and the array). The return
+ * value is ignored.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @template T,S
+ */
+goog.array.forEachRight = function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = l - 1; i >= 0; --i) {
+ if (i in arr2) {
+ f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);
+ }
+ }
+};
+
+
+/**
+ * Calls a function for each element in an array, and if the function returns
+ * true adds the element to a new array.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-filter}
+ *
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?):boolean} f The function to call for
+ * every element. This function
+ * takes 3 arguments (the element, the index and the array) and must
+ * return a Boolean. If the return value is true the element is added to the
+ * result array. If it is false the element is not included.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {!Array<T>} a new array in which only elements that passed the test
+ * are present.
+ * @template T,S
+ */
+goog.array.filter = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.filter) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ return Array.prototype.filter.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var res = [];
+ var resLength = 0;
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2) {
+ var val = arr2[i]; // in case f mutates arr2
+ if (f.call(/** @type {?} */ (opt_obj), val, i, arr)) {
+ res[resLength++] = val;
+ }
+ }
+ }
+ return res;
+ };
+
+
+/**
+ * Calls a function for each element in an array and inserts the result into a
+ * new array.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-map}
+ *
+ * @param {IArrayLike<VALUE>|string} arr Array or array like object
+ * over which to iterate.
+ * @param {function(this:THIS, VALUE, number, ?): RESULT} f The function to call
+ * for every element. This function takes 3 arguments (the element,
+ * the index and the array) and should return something. The result will be
+ * inserted into a new array.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within f.
+ * @return {!Array<RESULT>} a new array with the results from f.
+ * @template THIS, VALUE, RESULT
+ */
+goog.array.map = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.map) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ return Array.prototype.map.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var res = new Array(l);
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2) {
+ res[i] = f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);
+ }
+ }
+ return res;
+ };
+
+
+/**
+ * Passes every element of an array into a function and accumulates the result.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-reduce}
+ *
+ * For example:
+ * var a = [1, 2, 3, 4];
+ * goog.array.reduce(a, function(r, v, i, arr) {return r + v;}, 0);
+ * returns 10
+ *
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {function(this:S, R, T, number, ?) : R} f The function to call for
+ * every element. This function
+ * takes 4 arguments (the function's previous result or the initial value,
+ * the value of the current array element, the current array index, and the
+ * array itself)
+ * function(previousValue, currentValue, index, array).
+ * @param {?} val The initial value to pass into the function on the first call.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {R} Result of evaluating f repeatedly across the values of the array.
+ * @template T,S,R
+ */
+goog.array.reduce = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduce) ?
+ function(arr, f, val, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+ if (opt_obj) {
+ f = goog.bind(f, opt_obj);
+ }
+ return Array.prototype.reduce.call(arr, f, val);
+ } :
+ function(arr, f, val, opt_obj) {
+ var rval = val;
+ goog.array.forEach(arr, function(val, index) {
+ rval = f.call(/** @type {?} */ (opt_obj), rval, val, index, arr);
+ });
+ return rval;
+ };
+
+
+/**
+ * Passes every element of an array into a function and accumulates the result,
+ * starting from the last element and working towards the first.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-reduceright}
+ *
+ * For example:
+ * var a = ['a', 'b', 'c'];
+ * goog.array.reduceRight(a, function(r, v, i, arr) {return r + v;}, '');
+ * returns 'cba'
+ *
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, R, T, number, ?) : R} f The function to call for
+ * every element. This function
+ * takes 4 arguments (the function's previous result or the initial value,
+ * the value of the current array element, the current array index, and the
+ * array itself)
+ * function(previousValue, currentValue, index, array).
+ * @param {?} val The initial value to pass into the function on the first call.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {R} Object returned as a result of evaluating f repeatedly across the
+ * values of the array.
+ * @template T,S,R
+ */
+goog.array.reduceRight = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduceRight) ?
+ function(arr, f, val, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+ goog.asserts.assert(f != null);
+ if (opt_obj) {
+ f = goog.bind(f, opt_obj);
+ }
+ return Array.prototype.reduceRight.call(arr, f, val);
+ } :
+ function(arr, f, val, opt_obj) {
+ var rval = val;
+ goog.array.forEachRight(arr, function(val, index) {
+ rval = f.call(/** @type {?} */ (opt_obj), rval, val, index, arr);
+ });
+ return rval;
+ };
+
+
+/**
+ * Calls f for each element of an array. If any call returns true, some()
+ * returns true (without checking the remaining elements). If all calls
+ * return false, some() returns false.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-some}
+ *
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
+ * for every element. This function takes 3 arguments (the element, the
+ * index and the array) and should return a boolean.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {boolean} true if any element passes the test.
+ * @template T,S
+ */
+goog.array.some = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.some) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ return Array.prototype.some.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+
+/**
+ * Call f for each element of an array. If all calls return true, every()
+ * returns true. If any call returns false, every() returns false and
+ * does not continue to check the remaining elements.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-every}
+ *
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
+ * for every element. This function takes 3 arguments (the element, the
+ * index and the array) and should return a boolean.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {boolean} false if any element fails the test.
+ * @template T,S
+ */
+goog.array.every = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.every) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ return Array.prototype.every.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2 && !f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+
+/**
+ * Counts the array elements that fulfill the predicate, i.e. for which the
+ * callback function returns true. Skips holes in the array.
+ *
+ * @param {!IArrayLike<T>|string} arr Array or array like object
+ * over which to iterate.
+ * @param {function(this: S, T, number, ?): boolean} f The function to call for
+ * every element. Takes 3 arguments (the element, the index and the array).
+ * @param {S=} opt_obj The object to be used as the value of 'this' within f.
+ * @return {number} The number of the matching elements.
+ * @template T,S
+ */
+goog.array.count = function(arr, f, opt_obj) {
+ var count = 0;
+ goog.array.forEach(arr, function(element, index, arr) {
+ if (f.call(/** @type {?} */ (opt_obj), element, index, arr)) {
+ ++count;
+ }
+ }, opt_obj);
+ return count;
+};
+
+
+/**
+ * Search an array for the first element that satisfies a given condition and
+ * return that element.
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function takes 3 arguments (the element, the
+ * index and the array) and should return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {T|null} The first array element that passes the test, or null if no
+ * element is found.
+ * @template T,S
+ */
+goog.array.find = function(arr, f, opt_obj) {
+ var i = goog.array.findIndex(arr, f, opt_obj);
+ return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];
+};
+
+
+/**
+ * Search an array for the first element that satisfies a given condition and
+ * return its index.
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
+ * every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {number} The index of the first array element that passes the test,
+ * or -1 if no element is found.
+ * @template T,S
+ */
+goog.array.findIndex = function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+
+/**
+ * Search an array (in reverse order) for the last element that satisfies a
+ * given condition and return that element.
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {T|null} The last array element that passes the test, or null if no
+ * element is found.
+ * @template T,S
+ */
+goog.array.findRight = function(arr, f, opt_obj) {
+ var i = goog.array.findIndexRight(arr, f, opt_obj);
+ return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];
+};
+
+
+/**
+ * Search an array (in reverse order) for the last element that satisfies a
+ * given condition and return its index.
+ * @param {IArrayLike<T>|string} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {number} The index of the last array element that passes the test,
+ * or -1 if no element is found.
+ * @template T,S
+ */
+goog.array.findIndexRight = function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = l - 1; i >= 0; i--) {
+ if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+
+/**
+ * Whether the array contains the given object.
+ * @param {IArrayLike<?>|string} arr The array to test for the presence of the
+ * element.
+ * @param {*} obj The object for which to test.
+ * @return {boolean} true if obj is present.
+ */
+goog.array.contains = function(arr, obj) {
+ return goog.array.indexOf(arr, obj) >= 0;
+};
+
+
+/**
+ * Whether the array is empty.
+ * @param {IArrayLike<?>|string} arr The array to test.
+ * @return {boolean} true if empty.
+ */
+goog.array.isEmpty = function(arr) {
+ return arr.length == 0;
+};
+
+
+/**
+ * Clears the array.
+ * @param {IArrayLike<?>} arr Array or array like object to clear.
+ */
+goog.array.clear = function(arr) {
+ // For non real arrays we don't have the magic length so we delete the
+ // indices.
+ if (!goog.isArray(arr)) {
+ for (var i = arr.length - 1; i >= 0; i--) {
+ delete arr[i];
+ }
+ }
+ arr.length = 0;
+};
+
+
+/**
+ * Pushes an item into an array, if it's not already in the array.
+ * @param {Array<T>} arr Array into which to insert the item.
+ * @param {T} obj Value to add.
+ * @template T
+ */
+goog.array.insert = function(arr, obj) {
+ if (!goog.array.contains(arr, obj)) {
+ arr.push(obj);
+ }
+};
+
+
+/**
+ * Inserts an object at the given index of the array.
+ * @param {IArrayLike<?>} arr The array to modify.
+ * @param {*} obj The object to insert.
+ * @param {number=} opt_i The index at which to insert the object. If omitted,
+ * treated as 0. A negative index is counted from the end of the array.
+ */
+goog.array.insertAt = function(arr, obj, opt_i) {
+ goog.array.splice(arr, opt_i, 0, obj);
+};
+
+
+/**
+ * Inserts at the given index of the array, all elements of another array.
+ * @param {IArrayLike<?>} arr The array to modify.
+ * @param {IArrayLike<?>} elementsToAdd The array of elements to add.
+ * @param {number=} opt_i The index at which to insert the object. If omitted,
+ * treated as 0. A negative index is counted from the end of the array.
+ */
+goog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) {
+ goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd);
+};
+
+
+/**
+ * Inserts an object into an array before a specified object.
+ * @param {Array<T>} arr The array to modify.
+ * @param {T} obj The object to insert.
+ * @param {T=} opt_obj2 The object before which obj should be inserted. If obj2
+ * is omitted or not found, obj is inserted at the end of the array.
+ * @template T
+ */
+goog.array.insertBefore = function(arr, obj, opt_obj2) {
+ var i;
+ if (arguments.length == 2 || (i = goog.array.indexOf(arr, opt_obj2)) < 0) {
+ arr.push(obj);
+ } else {
+ goog.array.insertAt(arr, obj, i);
+ }
+};
+
+
+/**
+ * Removes the first occurrence of a particular value from an array.
+ * @param {IArrayLike<T>} arr Array from which to remove
+ * value.
+ * @param {T} obj Object to remove.
+ * @return {boolean} True if an element was removed.
+ * @template T
+ */
+goog.array.remove = function(arr, obj) {
+ var i = goog.array.indexOf(arr, obj);
+ var rv;
+ if ((rv = i >= 0)) {
+ goog.array.removeAt(arr, i);
+ }
+ return rv;
+};
+
+
+/**
+ * Removes the last occurrence of a particular value from an array.
+ * @param {!IArrayLike<T>} arr Array from which to remove value.
+ * @param {T} obj Object to remove.
+ * @return {boolean} True if an element was removed.
+ * @template T
+ */
+goog.array.removeLast = function(arr, obj) {
+ var i = goog.array.lastIndexOf(arr, obj);
+ if (i >= 0) {
+ goog.array.removeAt(arr, i);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes from an array the element at index i
+ * @param {IArrayLike<?>} arr Array or array like object from which to
+ * remove value.
+ * @param {number} i The index to remove.
+ * @return {boolean} True if an element was removed.
+ */
+goog.array.removeAt = function(arr, i) {
+ goog.asserts.assert(arr.length != null);
+
+ // use generic form of splice
+ // splice returns the removed items and if successful the length of that
+ // will be 1
+ return Array.prototype.splice.call(arr, i, 1).length == 1;
+};
+
+
+/**
+ * Removes the first value that satisfies the given condition.
+ * @param {IArrayLike<T>} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {boolean} True if an element was removed.
+ * @template T,S
+ */
+goog.array.removeIf = function(arr, f, opt_obj) {
+ var i = goog.array.findIndex(arr, f, opt_obj);
+ if (i >= 0) {
+ goog.array.removeAt(arr, i);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes all values that satisfy the given condition.
+ * @param {IArrayLike<T>} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {number} The number of items removed
+ * @template T,S
+ */
+goog.array.removeAllIf = function(arr, f, opt_obj) {
+ var removedCount = 0;
+ goog.array.forEachRight(arr, function(val, index) {
+ if (f.call(/** @type {?} */ (opt_obj), val, index, arr)) {
+ if (goog.array.removeAt(arr, index)) {
+ removedCount++;
+ }
+ }
+ });
+ return removedCount;
+};
+
+
+/**
+ * Returns a new array that is the result of joining the arguments. If arrays
+ * are passed then their items are added, however, if non-arrays are passed they
+ * will be added to the return array as is.
+ *
+ * Note that ArrayLike objects will be added as is, rather than having their
+ * items added.
+ *
+ * goog.array.concat([1, 2], [3, 4]) -> [1, 2, 3, 4]
+ * goog.array.concat(0, [1, 2]) -> [0, 1, 2]
+ * goog.array.concat([1, 2], null) -> [1, 2, null]
+ *
+ * There is bug in all current versions of IE (6, 7 and 8) where arrays created
+ * in an iframe become corrupted soon (not immediately) after the iframe is
+ * destroyed. This is common if loading data via goog.net.IframeIo, for example.
+ * This corruption only affects the concat method which will start throwing
+ * Catastrophic Errors (#-2147418113).
+ *
+ * See http://endoflow.com/scratch/corrupted-arrays.html for a test case.
+ *
+ * Internally goog.array should use this, so that all methods will continue to
+ * work on these broken array objects.
+ *
+ * @param {...*} var_args Items to concatenate. Arrays will have each item
+ * added, while primitives and objects will be added as is.
+ * @return {!Array<?>} The new resultant array.
+ */
+goog.array.concat = function(var_args) {
+ return Array.prototype.concat.apply(Array.prototype, arguments);
+};
+
+
+/**
+ * Returns a new array that contains the contents of all the arrays passed.
+ * @param {...!Array<T>} var_args
+ * @return {!Array<T>}
+ * @template T
+ */
+goog.array.join = function(var_args) {
+ return Array.prototype.concat.apply(Array.prototype, arguments);
+};
+
+
+/**
+ * Converts an object to an array.
+ * @param {IArrayLike<T>|string} object The object to convert to an
+ * array.
+ * @return {!Array<T>} The object converted into an array. If object has a
+ * length property, every property indexed with a non-negative number
+ * less than length will be included in the result. If object does not
+ * have a length property, an empty array will be returned.
+ * @template T
+ */
+goog.array.toArray = function(object) {
+ var length = object.length;
+
+ // If length is not a number the following it false. This case is kept for
+ // backwards compatibility since there are callers that pass objects that are
+ // not array like.
+ if (length > 0) {
+ var rv = new Array(length);
+ for (var i = 0; i < length; i++) {
+ rv[i] = object[i];
+ }
+ return rv;
+ }
+ return [];
+};
+
+
+/**
+ * Does a shallow copy of an array.
+ * @param {IArrayLike<T>|string} arr Array or array-like object to
+ * clone.
+ * @return {!Array<T>} Clone of the input array.
+ * @template T
+ */
+goog.array.clone = goog.array.toArray;
+
+
+/**
+ * Extends an array with another array, element, or "array like" object.
+ * This function operates 'in-place', it does not create a new Array.
+ *
+ * Example:
+ * var a = [];
+ * goog.array.extend(a, [0, 1]);
+ * a; // [0, 1]
+ * goog.array.extend(a, 2);
+ * a; // [0, 1, 2]
+ *
+ * @param {Array<VALUE>} arr1 The array to modify.
+ * @param {...(Array<VALUE>|VALUE)} var_args The elements or arrays of elements
+ * to add to arr1.
+ * @template VALUE
+ */
+goog.array.extend = function(arr1, var_args) {
+ for (var i = 1; i < arguments.length; i++) {
+ var arr2 = arguments[i];
+ if (goog.isArrayLike(arr2)) {
+ var len1 = arr1.length || 0;
+ var len2 = arr2.length || 0;
+ arr1.length = len1 + len2;
+ for (var j = 0; j < len2; j++) {
+ arr1[len1 + j] = arr2[j];
+ }
+ } else {
+ arr1.push(arr2);
+ }
+ }
+};
+
+
+/**
+ * Adds or removes elements from an array. This is a generic version of Array
+ * splice. This means that it might work on other objects similar to arrays,
+ * such as the arguments object.
+ *
+ * @param {IArrayLike<T>} arr The array to modify.
+ * @param {number|undefined} index The index at which to start changing the
+ * array. If not defined, treated as 0.
+ * @param {number} howMany How many elements to remove (0 means no removal. A
+ * value below 0 is treated as zero and so is any other non number. Numbers
+ * are floored).
+ * @param {...T} var_args Optional, additional elements to insert into the
+ * array.
+ * @return {!Array<T>} the removed elements.
+ * @template T
+ */
+goog.array.splice = function(arr, index, howMany, var_args) {
+ goog.asserts.assert(arr.length != null);
+
+ return Array.prototype.splice.apply(arr, goog.array.slice(arguments, 1));
+};
+
+
+/**
+ * Returns a new array from a segment of an array. This is a generic version of
+ * Array slice. This means that it might work on other objects similar to
+ * arrays, such as the arguments object.
+ *
+ * @param {IArrayLike<T>|string} arr The array from
+ * which to copy a segment.
+ * @param {number} start The index of the first element to copy.
+ * @param {number=} opt_end The index after the last element to copy.
+ * @return {!Array<T>} A new array containing the specified segment of the
+ * original array.
+ * @template T
+ */
+goog.array.slice = function(arr, start, opt_end) {
+ goog.asserts.assert(arr.length != null);
+
+ // passing 1 arg to slice is not the same as passing 2 where the second is
+ // null or undefined (in that case the second argument is treated as 0).
+ // we could use slice on the arguments object and then use apply instead of
+ // testing the length
+ if (arguments.length <= 2) {
+ return Array.prototype.slice.call(arr, start);
+ } else {
+ return Array.prototype.slice.call(arr, start, opt_end);
+ }
+};
+
+
+/**
+ * Removes all duplicates from an array (retaining only the first
+ * occurrence of each array element). This function modifies the
+ * array in place and doesn't change the order of the non-duplicate items.
+ *
+ * For objects, duplicates are identified as having the same unique ID as
+ * defined by {@link goog.getUid}.
+ *
+ * Alternatively you can specify a custom hash function that returns a unique
+ * value for each item in the array it should consider unique.
+ *
+ * Runtime: N,
+ * Worstcase space: 2N (no dupes)
+ *
+ * @param {IArrayLike<T>} arr The array from which to remove
+ * duplicates.
+ * @param {Array=} opt_rv An optional array in which to return the results,
+ * instead of performing the removal inplace. If specified, the original
+ * array will remain unchanged.
+ * @param {function(T):string=} opt_hashFn An optional function to use to
+ * apply to every item in the array. This function should return a unique
+ * value for each item in the array it should consider unique.
+ * @template T
+ */
+goog.array.removeDuplicates = function(arr, opt_rv, opt_hashFn) {
+ var returnArray = opt_rv || arr;
+ var defaultHashFn = function(item) {
+ // Prefix each type with a single character representing the type to
+ // prevent conflicting keys (e.g. true and 'true').
+ return goog.isObject(item) ? 'o' + goog.getUid(item) :
+ (typeof item).charAt(0) + item;
+ };
+ var hashFn = opt_hashFn || defaultHashFn;
+
+ var seen = {}, cursorInsert = 0, cursorRead = 0;
+ while (cursorRead < arr.length) {
+ var current = arr[cursorRead++];
+ var key = hashFn(current);
+ if (!Object.prototype.hasOwnProperty.call(seen, key)) {
+ seen[key] = true;
+ returnArray[cursorInsert++] = current;
+ }
+ }
+ returnArray.length = cursorInsert;
+};
+
+
+/**
+ * Searches the specified array for the specified target using the binary
+ * search algorithm. If no opt_compareFn is specified, elements are compared
+ * using <code>goog.array.defaultCompare</code>, which compares the elements
+ * using the built in < and > operators. This will produce the expected
+ * behavior for homogeneous arrays of String(s) and Number(s). The array
+ * specified <b>must</b> be sorted in ascending order (as defined by the
+ * comparison function). If the array is not sorted, results are undefined.
+ * If the array contains multiple instances of the specified target value, any
+ * of these instances may be found.
+ *
+ * Runtime: O(log n)
+ *
+ * @param {IArrayLike<VALUE>} arr The array to be searched.
+ * @param {TARGET} target The sought value.
+ * @param {function(TARGET, VALUE): number=} opt_compareFn Optional comparison
+ * function by which the array is ordered. Should take 2 arguments to
+ * compare, and return a negative number, zero, or a positive number
+ * depending on whether the first argument is less than, equal to, or
+ * greater than the second.
+ * @return {number} Lowest index of the target value if found, otherwise
+ * (-(insertion point) - 1). The insertion point is where the value should
+ * be inserted into arr to preserve the sorted property. Return value >= 0
+ * iff target is found.
+ * @template TARGET, VALUE
+ */
+goog.array.binarySearch = function(arr, target, opt_compareFn) {
+ return goog.array.binarySearch_(
+ arr, opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */,
+ target);
+};
+
+
+/**
+ * Selects an index in the specified array using the binary search algorithm.
+ * The evaluator receives an element and determines whether the desired index
+ * is before, at, or after it. The evaluator must be consistent (formally,
+ * goog.array.map(goog.array.map(arr, evaluator, opt_obj), goog.math.sign)
+ * must be monotonically non-increasing).
+ *
+ * Runtime: O(log n)
+ *
+ * @param {IArrayLike<VALUE>} arr The array to be searched.
+ * @param {function(this:THIS, VALUE, number, ?): number} evaluator
+ * Evaluator function that receives 3 arguments (the element, the index and
+ * the array). Should return a negative number, zero, or a positive number
+ * depending on whether the desired index is before, at, or after the
+ * element passed to it.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this'
+ * within evaluator.
+ * @return {number} Index of the leftmost element matched by the evaluator, if
+ * such exists; otherwise (-(insertion point) - 1). The insertion point is
+ * the index of the first element for which the evaluator returns negative,
+ * or arr.length if no such element exists. The return value is non-negative
+ * iff a match is found.
+ * @template THIS, VALUE
+ */
+goog.array.binarySelect = function(arr, evaluator, opt_obj) {
+ return goog.array.binarySearch_(
+ arr, evaluator, true /* isEvaluator */, undefined /* opt_target */,
+ opt_obj);
+};
+
+
+/**
+ * Implementation of a binary search algorithm which knows how to use both
+ * comparison functions and evaluators. If an evaluator is provided, will call
+ * the evaluator with the given optional data object, conforming to the
+ * interface defined in binarySelect. Otherwise, if a comparison function is
+ * provided, will call the comparison function against the given data object.
+ *
+ * This implementation purposefully does not use goog.bind or goog.partial for
+ * performance reasons.
+ *
+ * Runtime: O(log n)
+ *
+ * @param {IArrayLike<?>} arr The array to be searched.
+ * @param {function(?, ?, ?): number | function(?, ?): number} compareFn
+ * Either an evaluator or a comparison function, as defined by binarySearch
+ * and binarySelect above.
+ * @param {boolean} isEvaluator Whether the function is an evaluator or a
+ * comparison function.
+ * @param {?=} opt_target If the function is a comparison function, then
+ * this is the target to binary search for.
+ * @param {Object=} opt_selfObj If the function is an evaluator, this is an
+ * optional this object for the evaluator.
+ * @return {number} Lowest index of the target value if found, otherwise
+ * (-(insertion point) - 1). The insertion point is where the value should
+ * be inserted into arr to preserve the sorted property. Return value >= 0
+ * iff target is found.
+ * @private
+ */
+goog.array.binarySearch_ = function(
+ arr, compareFn, isEvaluator, opt_target, opt_selfObj) {
+ var left = 0; // inclusive
+ var right = arr.length; // exclusive
+ var found;
+ while (left < right) {
+ var middle = (left + right) >> 1;
+ var compareResult;
+ if (isEvaluator) {
+ compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr);
+ } else {
+ // NOTE(dimvar): To avoid this cast, we'd have to use function overloading
+ // for the type of binarySearch_, which the type system can't express yet.
+ compareResult = /** @type {function(?, ?): number} */ (compareFn)(
+ opt_target, arr[middle]);
+ }
+ if (compareResult > 0) {
+ left = middle + 1;
+ } else {
+ right = middle;
+ // We are looking for the lowest index so we can't return immediately.
+ found = !compareResult;
+ }
+ }
+ // left is the index if found, or the insertion point otherwise.
+ // ~left is a shorthand for -left - 1.
+ return found ? left : ~left;
+};
+
+
+/**
+ * Sorts the specified array into ascending order. If no opt_compareFn is
+ * specified, elements are compared using
+ * <code>goog.array.defaultCompare</code>, which compares the elements using
+ * the built in < and > operators. This will produce the expected behavior
+ * for homogeneous arrays of String(s) and Number(s), unlike the native sort,
+ * but will give unpredictable results for heterogenous lists of strings and
+ * numbers with different numbers of digits.
+ *
+ * This sort is not guaranteed to be stable.
+ *
+ * Runtime: Same as <code>Array.prototype.sort</code>
+ *
+ * @param {Array<T>} arr The array to be sorted.
+ * @param {?function(T,T):number=} opt_compareFn Optional comparison
+ * function by which the
+ * array is to be ordered. Should take 2 arguments to compare, and return a
+ * negative number, zero, or a positive number depending on whether the
+ * first argument is less than, equal to, or greater than the second.
+ * @template T
+ */
+goog.array.sort = function(arr, opt_compareFn) {
+ // TODO(arv): Update type annotation since null is not accepted.
+ arr.sort(opt_compareFn || goog.array.defaultCompare);
+};
+
+
+/**
+ * Sorts the specified array into ascending order in a stable way. If no
+ * opt_compareFn is specified, elements are compared using
+ * <code>goog.array.defaultCompare</code>, which compares the elements using
+ * the built in < and > operators. This will produce the expected behavior
+ * for homogeneous arrays of String(s) and Number(s).
+ *
+ * Runtime: Same as <code>Array.prototype.sort</code>, plus an additional
+ * O(n) overhead of copying the array twice.
+ *
+ * @param {Array<T>} arr The array to be sorted.
+ * @param {?function(T, T): number=} opt_compareFn Optional comparison function
+ * by which the array is to be ordered. Should take 2 arguments to compare,
+ * and return a negative number, zero, or a positive number depending on
+ * whether the first argument is less than, equal to, or greater than the
+ * second.
+ * @template T
+ */
+goog.array.stableSort = function(arr, opt_compareFn) {
+ var compArr = new Array(arr.length);
+ for (var i = 0; i < arr.length; i++) {
+ compArr[i] = {index: i, value: arr[i]};
+ }
+ var valueCompareFn = opt_compareFn || goog.array.defaultCompare;
+ function stableCompareFn(obj1, obj2) {
+ return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index;
+ }
+ goog.array.sort(compArr, stableCompareFn);
+ for (var i = 0; i < arr.length; i++) {
+ arr[i] = compArr[i].value;
+ }
+};
+
+
+/**
+ * Sort the specified array into ascending order based on item keys
+ * returned by the specified key function.
+ * If no opt_compareFn is specified, the keys are compared in ascending order
+ * using <code>goog.array.defaultCompare</code>.
+ *
+ * Runtime: O(S(f(n)), where S is runtime of <code>goog.array.sort</code>
+ * and f(n) is runtime of the key function.
+ *
+ * @param {Array<T>} arr The array to be sorted.
+ * @param {function(T): K} keyFn Function taking array element and returning
+ * a key used for sorting this element.
+ * @param {?function(K, K): number=} opt_compareFn Optional comparison function
+ * by which the keys are to be ordered. Should take 2 arguments to compare,
+ * and return a negative number, zero, or a positive number depending on
+ * whether the first argument is less than, equal to, or greater than the
+ * second.
+ * @template T,K
+ */
+goog.array.sortByKey = function(arr, keyFn, opt_compareFn) {
+ var keyCompareFn = opt_compareFn || goog.array.defaultCompare;
+ goog.array.sort(
+ arr, function(a, b) { return keyCompareFn(keyFn(a), keyFn(b)); });
+};
+
+
+/**
+ * Sorts an array of objects by the specified object key and compare
+ * function. If no compare function is provided, the key values are
+ * compared in ascending order using <code>goog.array.defaultCompare</code>.
+ * This won't work for keys that get renamed by the compiler. So use
+ * {'foo': 1, 'bar': 2} rather than {foo: 1, bar: 2}.
+ * @param {Array<Object>} arr An array of objects to sort.
+ * @param {string} key The object key to sort by.
+ * @param {Function=} opt_compareFn The function to use to compare key
+ * values.
+ */
+goog.array.sortObjectsByKey = function(arr, key, opt_compareFn) {
+ goog.array.sortByKey(arr, function(obj) { return obj[key]; }, opt_compareFn);
+};
+
+
+/**
+ * Tells if the array is sorted.
+ * @param {!Array<T>} arr The array.
+ * @param {?function(T,T):number=} opt_compareFn Function to compare the
+ * array elements.
+ * Should take 2 arguments to compare, and return a negative number, zero,
+ * or a positive number depending on whether the first argument is less
+ * than, equal to, or greater than the second.
+ * @param {boolean=} opt_strict If true no equal elements are allowed.
+ * @return {boolean} Whether the array is sorted.
+ * @template T
+ */
+goog.array.isSorted = function(arr, opt_compareFn, opt_strict) {
+ var compare = opt_compareFn || goog.array.defaultCompare;
+ for (var i = 1; i < arr.length; i++) {
+ var compareResult = compare(arr[i - 1], arr[i]);
+ if (compareResult > 0 || compareResult == 0 && opt_strict) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Compares two arrays for equality. Two arrays are considered equal if they
+ * have the same length and their corresponding elements are equal according to
+ * the comparison function.
+ *
+ * @param {IArrayLike<?>} arr1 The first array to compare.
+ * @param {IArrayLike<?>} arr2 The second array to compare.
+ * @param {Function=} opt_equalsFn Optional comparison function.
+ * Should take 2 arguments to compare, and return true if the arguments
+ * are equal. Defaults to {@link goog.array.defaultCompareEquality} which
+ * compares the elements using the built-in '===' operator.
+ * @return {boolean} Whether the two arrays are equal.
+ */
+goog.array.equals = function(arr1, arr2, opt_equalsFn) {
+ if (!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) ||
+ arr1.length != arr2.length) {
+ return false;
+ }
+ var l = arr1.length;
+ var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
+ for (var i = 0; i < l; i++) {
+ if (!equalsFn(arr1[i], arr2[i])) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * 3-way array compare function.
+ * @param {!IArrayLike<VALUE>} arr1 The first array to
+ * compare.
+ * @param {!IArrayLike<VALUE>} arr2 The second array to
+ * compare.
+ * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
+ * function by which the array is to be ordered. Should take 2 arguments to
+ * compare, and return a negative number, zero, or a positive number
+ * depending on whether the first argument is less than, equal to, or
+ * greater than the second.
+ * @return {number} Negative number, zero, or a positive number depending on
+ * whether the first argument is less than, equal to, or greater than the
+ * second.
+ * @template VALUE
+ */
+goog.array.compare3 = function(arr1, arr2, opt_compareFn) {
+ var compare = opt_compareFn || goog.array.defaultCompare;
+ var l = Math.min(arr1.length, arr2.length);
+ for (var i = 0; i < l; i++) {
+ var result = compare(arr1[i], arr2[i]);
+ if (result != 0) {
+ return result;
+ }
+ }
+ return goog.array.defaultCompare(arr1.length, arr2.length);
+};
+
+
+/**
+ * Compares its two arguments for order, using the built in < and >
+ * operators.
+ * @param {VALUE} a The first object to be compared.
+ * @param {VALUE} b The second object to be compared.
+ * @return {number} A negative number, zero, or a positive number as the first
+ * argument is less than, equal to, or greater than the second,
+ * respectively.
+ * @template VALUE
+ */
+goog.array.defaultCompare = function(a, b) {
+ return a > b ? 1 : a < b ? -1 : 0;
+};
+
+
+/**
+ * Compares its two arguments for inverse order, using the built in < and >
+ * operators.
+ * @param {VALUE} a The first object to be compared.
+ * @param {VALUE} b The second object to be compared.
+ * @return {number} A negative number, zero, or a positive number as the first
+ * argument is greater than, equal to, or less than the second,
+ * respectively.
+ * @template VALUE
+ */
+goog.array.inverseDefaultCompare = function(a, b) {
+ return -goog.array.defaultCompare(a, b);
+};
+
+
+/**
+ * Compares its two arguments for equality, using the built in === operator.
+ * @param {*} a The first object to compare.
+ * @param {*} b The second object to compare.
+ * @return {boolean} True if the two arguments are equal, false otherwise.
+ */
+goog.array.defaultCompareEquality = function(a, b) {
+ return a === b;
+};
+
+
+/**
+ * Inserts a value into a sorted array. The array is not modified if the
+ * value is already present.
+ * @param {IArrayLike<VALUE>} array The array to modify.
+ * @param {VALUE} value The object to insert.
+ * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
+ * function by which the array is ordered. Should take 2 arguments to
+ * compare, and return a negative number, zero, or a positive number
+ * depending on whether the first argument is less than, equal to, or
+ * greater than the second.
+ * @return {boolean} True if an element was inserted.
+ * @template VALUE
+ */
+goog.array.binaryInsert = function(array, value, opt_compareFn) {
+ var index = goog.array.binarySearch(array, value, opt_compareFn);
+ if (index < 0) {
+ goog.array.insertAt(array, value, -(index + 1));
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes a value from a sorted array.
+ * @param {!IArrayLike<VALUE>} array The array to modify.
+ * @param {VALUE} value The object to remove.
+ * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
+ * function by which the array is ordered. Should take 2 arguments to
+ * compare, and return a negative number, zero, or a positive number
+ * depending on whether the first argument is less than, equal to, or
+ * greater than the second.
+ * @return {boolean} True if an element was removed.
+ * @template VALUE
+ */
+goog.array.binaryRemove = function(array, value, opt_compareFn) {
+ var index = goog.array.binarySearch(array, value, opt_compareFn);
+ return (index >= 0) ? goog.array.removeAt(array, index) : false;
+};
+
+
+/**
+ * Splits an array into disjoint buckets according to a splitting function.
+ * @param {Array<T>} array The array.
+ * @param {function(this:S, T,number,Array<T>):?} sorter Function to call for
+ * every element. This takes 3 arguments (the element, the index and the
+ * array) and must return a valid object key (a string, number, etc), or
+ * undefined, if that object should not be placed in a bucket.
+ * @param {S=} opt_obj The object to be used as the value of 'this' within
+ * sorter.
+ * @return {!Object} An object, with keys being all of the unique return values
+ * of sorter, and values being arrays containing the items for
+ * which the splitter returned that key.
+ * @template T,S
+ */
+goog.array.bucket = function(array, sorter, opt_obj) {
+ var buckets = {};
+
+ for (var i = 0; i < array.length; i++) {
+ var value = array[i];
+ var key = sorter.call(/** @type {?} */ (opt_obj), value, i, array);
+ if (goog.isDef(key)) {
+ // Push the value to the right bucket, creating it if necessary.
+ var bucket = buckets[key] || (buckets[key] = []);
+ bucket.push(value);
+ }
+ }
+
+ return buckets;
+};
+
+
+/**
+ * Creates a new object built from the provided array and the key-generation
+ * function.
+ * @param {IArrayLike<T>} arr Array or array like object over
+ * which to iterate whose elements will be the values in the new object.
+ * @param {?function(this:S, T, number, ?) : string} keyFunc The function to
+ * call for every element. This function takes 3 arguments (the element, the
+ * index and the array) and should return a string that will be used as the
+ * key for the element in the new object. If the function returns the same
+ * key for more than one element, the value for that key is
+ * implementation-defined.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within keyFunc.
+ * @return {!Object<T>} The new object.
+ * @template T,S
+ */
+goog.array.toObject = function(arr, keyFunc, opt_obj) {
+ var ret = {};
+ goog.array.forEach(arr, function(element, index) {
+ ret[keyFunc.call(/** @type {?} */ (opt_obj), element, index, arr)] =
+ element;
+ });
+ return ret;
+};
+
+
+/**
+ * Creates a range of numbers in an arithmetic progression.
+ *
+ * Range takes 1, 2, or 3 arguments:
+ * <pre>
+ * range(5) is the same as range(0, 5, 1) and produces [0, 1, 2, 3, 4]
+ * range(2, 5) is the same as range(2, 5, 1) and produces [2, 3, 4]
+ * range(-2, -5, -1) produces [-2, -3, -4]
+ * range(-2, -5, 1) produces [], since stepping by 1 wouldn't ever reach -5.
+ * </pre>
+ *
+ * @param {number} startOrEnd The starting value of the range if an end argument
+ * is provided. Otherwise, the start value is 0, and this is the end value.
+ * @param {number=} opt_end The optional end value of the range.
+ * @param {number=} opt_step The step size between range values. Defaults to 1
+ * if opt_step is undefined or 0.
+ * @return {!Array<number>} An array of numbers for the requested range. May be
+ * an empty array if adding the step would not converge toward the end
+ * value.
+ */
+goog.array.range = function(startOrEnd, opt_end, opt_step) {
+ var array = [];
+ var start = 0;
+ var end = startOrEnd;
+ var step = opt_step || 1;
+ if (opt_end !== undefined) {
+ start = startOrEnd;
+ end = opt_end;
+ }
+
+ if (step * (end - start) < 0) {
+ // Sign mismatch: start + step will never reach the end value.
+ return [];
+ }
+
+ if (step > 0) {
+ for (var i = start; i < end; i += step) {
+ array.push(i);
+ }
+ } else {
+ for (var i = start; i > end; i += step) {
+ array.push(i);
+ }
+ }
+ return array;
+};
+
+
+/**
+ * Returns an array consisting of the given value repeated N times.
+ *
+ * @param {VALUE} value The value to repeat.
+ * @param {number} n The repeat count.
+ * @return {!Array<VALUE>} An array with the repeated value.
+ * @template VALUE
+ */
+goog.array.repeat = function(value, n) {
+ var array = [];
+ for (var i = 0; i < n; i++) {
+ array[i] = value;
+ }
+ return array;
+};
+
+
+/**
+ * Returns an array consisting of every argument with all arrays
+ * expanded in-place recursively.
+ *
+ * @param {...*} var_args The values to flatten.
+ * @return {!Array<?>} An array containing the flattened values.
+ */
+goog.array.flatten = function(var_args) {
+ var CHUNK_SIZE = 8192;
+
+ var result = [];
+ for (var i = 0; i < arguments.length; i++) {
+ var element = arguments[i];
+ if (goog.isArray(element)) {
+ for (var c = 0; c < element.length; c += CHUNK_SIZE) {
+ var chunk = goog.array.slice(element, c, c + CHUNK_SIZE);
+ var recurseResult = goog.array.flatten.apply(null, chunk);
+ for (var r = 0; r < recurseResult.length; r++) {
+ result.push(recurseResult[r]);
+ }
+ }
+ } else {
+ result.push(element);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Rotates an array in-place. After calling this method, the element at
+ * index i will be the element previously at index (i - n) %
+ * array.length, for all values of i between 0 and array.length - 1,
+ * inclusive.
+ *
+ * For example, suppose list comprises [t, a, n, k, s]. After invoking
+ * rotate(array, 1) (or rotate(array, -4)), array will comprise [s, t, a, n, k].
+ *
+ * @param {!Array<T>} array The array to rotate.
+ * @param {number} n The amount to rotate.
+ * @return {!Array<T>} The array.
+ * @template T
+ */
+goog.array.rotate = function(array, n) {
+ goog.asserts.assert(array.length != null);
+
+ if (array.length) {
+ n %= array.length;
+ if (n > 0) {
+ Array.prototype.unshift.apply(array, array.splice(-n, n));
+ } else if (n < 0) {
+ Array.prototype.push.apply(array, array.splice(0, -n));
+ }
+ }
+ return array;
+};
+
+
+/**
+ * Moves one item of an array to a new position keeping the order of the rest
+ * of the items. Example use case: keeping a list of JavaScript objects
+ * synchronized with the corresponding list of DOM elements after one of the
+ * elements has been dragged to a new position.
+ * @param {!IArrayLike<?>} arr The array to modify.
+ * @param {number} fromIndex Index of the item to move between 0 and
+ * {@code arr.length - 1}.
+ * @param {number} toIndex Target index between 0 and {@code arr.length - 1}.
+ */
+goog.array.moveItem = function(arr, fromIndex, toIndex) {
+ goog.asserts.assert(fromIndex >= 0 && fromIndex < arr.length);
+ goog.asserts.assert(toIndex >= 0 && toIndex < arr.length);
+ // Remove 1 item at fromIndex.
+ var removedItems = Array.prototype.splice.call(arr, fromIndex, 1);
+ // Insert the removed item at toIndex.
+ Array.prototype.splice.call(arr, toIndex, 0, removedItems[0]);
+ // We don't use goog.array.insertAt and goog.array.removeAt, because they're
+ // significantly slower than splice.
+};
+
+
+/**
+ * Creates a new array for which the element at position i is an array of the
+ * ith element of the provided arrays. The returned array will only be as long
+ * as the shortest array provided; additional values are ignored. For example,
+ * the result of zipping [1, 2] and [3, 4, 5] is [[1,3], [2, 4]].
+ *
+ * This is similar to the zip() function in Python. See {@link
+ * http://docs.python.org/library/functions.html#zip}
+ *
+ * @param {...!IArrayLike<?>} var_args Arrays to be combined.
+ * @return {!Array<!Array<?>>} A new array of arrays created from
+ * provided arrays.
+ */
+goog.array.zip = function(var_args) {
+ if (!arguments.length) {
+ return [];
+ }
+ var result = [];
+ var minLen = arguments[0].length;
+ for (var i = 1; i < arguments.length; i++) {
+ if (arguments[i].length < minLen) {
+ minLen = arguments[i].length;
+ }
+ }
+ for (var i = 0; i < minLen; i++) {
+ var value = [];
+ for (var j = 0; j < arguments.length; j++) {
+ value.push(arguments[j][i]);
+ }
+ result.push(value);
+ }
+ return result;
+};
+
+
+/**
+ * Shuffles the values in the specified array using the Fisher-Yates in-place
+ * shuffle (also known as the Knuth Shuffle). By default, calls Math.random()
+ * and so resets the state of that random number generator. Similarly, may reset
+ * the state of the any other specified random number generator.
+ *
+ * Runtime: O(n)
+ *
+ * @param {!Array<?>} arr The array to be shuffled.
+ * @param {function():number=} opt_randFn Optional random function to use for
+ * shuffling.
+ * Takes no arguments, and returns a random number on the interval [0, 1).
+ * Defaults to Math.random() using JavaScript's built-in Math library.
+ */
+goog.array.shuffle = function(arr, opt_randFn) {
+ var randFn = opt_randFn || Math.random;
+
+ for (var i = arr.length - 1; i > 0; i--) {
+ // Choose a random array index in [0, i] (inclusive with i).
+ var j = Math.floor(randFn() * (i + 1));
+
+ var tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+};
+
+
+/**
+ * Returns a new array of elements from arr, based on the indexes of elements
+ * provided by index_arr. For example, the result of index copying
+ * ['a', 'b', 'c'] with index_arr [1,0,0,2] is ['b', 'a', 'a', 'c'].
+ *
+ * @param {!Array<T>} arr The array to get a indexed copy from.
+ * @param {!Array<number>} index_arr An array of indexes to get from arr.
+ * @return {!Array<T>} A new array of elements from arr in index_arr order.
+ * @template T
+ */
+goog.array.copyByIndex = function(arr, index_arr) {
+ var result = [];
+ goog.array.forEach(index_arr, function(index) { result.push(arr[index]); });
+ return result;
+};
+
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Additional mathematical functions.
+ */
+
+goog.provide('goog.math');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+
+
+/**
+ * Returns a random integer greater than or equal to 0 and less than {@code a}.
+ * @param {number} a The upper bound for the random integer (exclusive).
+ * @return {number} A random integer N such that 0 <= N < a.
+ */
+goog.math.randomInt = function(a) {
+ return Math.floor(Math.random() * a);
+};
+
+
+/**
+ * Returns a random number greater than or equal to {@code a} and less than
+ * {@code b}.
+ * @param {number} a The lower bound for the random number (inclusive).
+ * @param {number} b The upper bound for the random number (exclusive).
+ * @return {number} A random number N such that a <= N < b.
+ */
+goog.math.uniformRandom = function(a, b) {
+ return a + Math.random() * (b - a);
+};
+
+
+/**
+ * Takes a number and clamps it to within the provided bounds.
+ * @param {number} value The input number.
+ * @param {number} min The minimum value to return.
+ * @param {number} max The maximum value to return.
+ * @return {number} The input number if it is within bounds, or the nearest
+ * number within the bounds.
+ */
+goog.math.clamp = function(value, min, max) {
+ return Math.min(Math.max(value, min), max);
+};
+
+
+/**
+ * The % operator in JavaScript returns the remainder of a / b, but differs from
+ * some other languages in that the result will have the same sign as the
+ * dividend. For example, -1 % 8 == -1, whereas in some other languages
+ * (such as Python) the result would be 7. This function emulates the more
+ * correct modulo behavior, which is useful for certain applications such as
+ * calculating an offset index in a circular list.
+ *
+ * @param {number} a The dividend.
+ * @param {number} b The divisor.
+ * @return {number} a % b where the result is between 0 and b (either 0 <= x < b
+ * or b < x <= 0, depending on the sign of b).
+ */
+goog.math.modulo = function(a, b) {
+ var r = a % b;
+ // If r and b differ in sign, add b to wrap the result to the correct sign.
+ return (r * b < 0) ? r + b : r;
+};
+
+
+/**
+ * Performs linear interpolation between values a and b. Returns the value
+ * between a and b proportional to x (when x is between 0 and 1. When x is
+ * outside this range, the return value is a linear extrapolation).
+ * @param {number} a A number.
+ * @param {number} b A number.
+ * @param {number} x The proportion between a and b.
+ * @return {number} The interpolated value between a and b.
+ */
+goog.math.lerp = function(a, b, x) {
+ return a + x * (b - a);
+};
+
+
+/**
+ * Tests whether the two values are equal to each other, within a certain
+ * tolerance to adjust for floating point errors.
+ * @param {number} a A number.
+ * @param {number} b A number.
+ * @param {number=} opt_tolerance Optional tolerance range. Defaults
+ * to 0.000001. If specified, should be greater than 0.
+ * @return {boolean} Whether {@code a} and {@code b} are nearly equal.
+ */
+goog.math.nearlyEquals = function(a, b, opt_tolerance) {
+ return Math.abs(a - b) <= (opt_tolerance || 0.000001);
+};
+
+
+// TODO(user): Rename to normalizeAngle, retaining old name as deprecated
+// alias.
+/**
+ * Normalizes an angle to be in range [0-360). Angles outside this range will
+ * be normalized to be the equivalent angle with that range.
+ * @param {number} angle Angle in degrees.
+ * @return {number} Standardized angle.
+ */
+goog.math.standardAngle = function(angle) {
+ return goog.math.modulo(angle, 360);
+};
+
+
+/**
+ * Normalizes an angle to be in range [0-2*PI). Angles outside this range will
+ * be normalized to be the equivalent angle with that range.
+ * @param {number} angle Angle in radians.
+ * @return {number} Standardized angle.
+ */
+goog.math.standardAngleInRadians = function(angle) {
+ return goog.math.modulo(angle, 2 * Math.PI);
+};
+
+
+/**
+ * Converts degrees to radians.
+ * @param {number} angleDegrees Angle in degrees.
+ * @return {number} Angle in radians.
+ */
+goog.math.toRadians = function(angleDegrees) {
+ return angleDegrees * Math.PI / 180;
+};
+
+
+/**
+ * Converts radians to degrees.
+ * @param {number} angleRadians Angle in radians.
+ * @return {number} Angle in degrees.
+ */
+goog.math.toDegrees = function(angleRadians) {
+ return angleRadians * 180 / Math.PI;
+};
+
+
+/**
+ * For a given angle and radius, finds the X portion of the offset.
+ * @param {number} degrees Angle in degrees (zero points in +X direction).
+ * @param {number} radius Radius.
+ * @return {number} The x-distance for the angle and radius.
+ */
+goog.math.angleDx = function(degrees, radius) {
+ return radius * Math.cos(goog.math.toRadians(degrees));
+};
+
+
+/**
+ * For a given angle and radius, finds the Y portion of the offset.
+ * @param {number} degrees Angle in degrees (zero points in +X direction).
+ * @param {number} radius Radius.
+ * @return {number} The y-distance for the angle and radius.
+ */
+goog.math.angleDy = function(degrees, radius) {
+ return radius * Math.sin(goog.math.toRadians(degrees));
+};
+
+
+/**
+ * Computes the angle between two points (x1,y1) and (x2,y2).
+ * Angle zero points in the +X direction, 90 degrees points in the +Y
+ * direction (down) and from there we grow clockwise towards 360 degrees.
+ * @param {number} x1 x of first point.
+ * @param {number} y1 y of first point.
+ * @param {number} x2 x of second point.
+ * @param {number} y2 y of second point.
+ * @return {number} Standardized angle in degrees of the vector from
+ * x1,y1 to x2,y2.
+ */
+goog.math.angle = function(x1, y1, x2, y2) {
+ return goog.math.standardAngle(
+ goog.math.toDegrees(Math.atan2(y2 - y1, x2 - x1)));
+};
+
+
+/**
+ * Computes the difference between startAngle and endAngle (angles in degrees).
+ * @param {number} startAngle Start angle in degrees.
+ * @param {number} endAngle End angle in degrees.
+ * @return {number} The number of degrees that when added to
+ * startAngle will result in endAngle. Positive numbers mean that the
+ * direction is clockwise. Negative numbers indicate a counter-clockwise
+ * direction.
+ * The shortest route (clockwise vs counter-clockwise) between the angles
+ * is used.
+ * When the difference is 180 degrees, the function returns 180 (not -180)
+ * angleDifference(30, 40) is 10, and angleDifference(40, 30) is -10.
+ * angleDifference(350, 10) is 20, and angleDifference(10, 350) is -20.
+ */
+goog.math.angleDifference = function(startAngle, endAngle) {
+ var d =
+ goog.math.standardAngle(endAngle) - goog.math.standardAngle(startAngle);
+ if (d > 180) {
+ d = d - 360;
+ } else if (d <= -180) {
+ d = 360 + d;
+ }
+ return d;
+};
+
+
+/**
+ * Returns the sign of a number as per the "sign" or "signum" function.
+ * @param {number} x The number to take the sign of.
+ * @return {number} -1 when negative, 1 when positive, 0 when 0. Preserves
+ * signed zeros and NaN.
+ */
+goog.math.sign = Math.sign || function(x) {
+ if (x > 0) {
+ return 1;
+ }
+ if (x < 0) {
+ return -1;
+ }
+ return x; // Preserves signed zeros and NaN.
+};
+
+
+/**
+ * JavaScript implementation of Longest Common Subsequence problem.
+ * http://en.wikipedia.org/wiki/Longest_common_subsequence
+ *
+ * Returns the longest possible array that is subarray of both of given arrays.
+ *
+ * @param {IArrayLike<S>} array1 First array of objects.
+ * @param {IArrayLike<T>} array2 Second array of objects.
+ * @param {Function=} opt_compareFn Function that acts as a custom comparator
+ * for the array ojects. Function should return true if objects are equal,
+ * otherwise false.
+ * @param {Function=} opt_collectorFn Function used to decide what to return
+ * as a result subsequence. It accepts 2 arguments: index of common element
+ * in the first array and index in the second. The default function returns
+ * element from the first array.
+ * @return {!Array<S|T>} A list of objects that are common to both arrays
+ * such that there is no common subsequence with size greater than the
+ * length of the list.
+ * @template S,T
+ */
+goog.math.longestCommonSubsequence = function(
+ array1, array2, opt_compareFn, opt_collectorFn) {
+
+ var compare = opt_compareFn || function(a, b) { return a == b; };
+
+ var collect = opt_collectorFn || function(i1, i2) { return array1[i1]; };
+
+ var length1 = array1.length;
+ var length2 = array2.length;
+
+ var arr = [];
+ for (var i = 0; i < length1 + 1; i++) {
+ arr[i] = [];
+ arr[i][0] = 0;
+ }
+
+ for (var j = 0; j < length2 + 1; j++) {
+ arr[0][j] = 0;
+ }
+
+ for (i = 1; i <= length1; i++) {
+ for (j = 1; j <= length2; j++) {
+ if (compare(array1[i - 1], array2[j - 1])) {
+ arr[i][j] = arr[i - 1][j - 1] + 1;
+ } else {
+ arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
+ }
+ }
+ }
+
+ // Backtracking
+ var result = [];
+ var i = length1, j = length2;
+ while (i > 0 && j > 0) {
+ if (compare(array1[i - 1], array2[j - 1])) {
+ result.unshift(collect(i - 1, j - 1));
+ i--;
+ j--;
+ } else {
+ if (arr[i - 1][j] > arr[i][j - 1]) {
+ i--;
+ } else {
+ j--;
+ }
+ }
+ }
+
+ return result;
+};
+
+
+/**
+ * Returns the sum of the arguments.
+ * @param {...number} var_args Numbers to add.
+ * @return {number} The sum of the arguments (0 if no arguments were provided,
+ * {@code NaN} if any of the arguments is not a valid number).
+ */
+goog.math.sum = function(var_args) {
+ return /** @type {number} */ (
+ goog.array.reduce(
+ arguments, function(sum, value) { return sum + value; }, 0));
+};
+
+
+/**
+ * Returns the arithmetic mean of the arguments.
+ * @param {...number} var_args Numbers to average.
+ * @return {number} The average of the arguments ({@code NaN} if no arguments
+ * were provided or any of the arguments is not a valid number).
+ */
+goog.math.average = function(var_args) {
+ return goog.math.sum.apply(null, arguments) / arguments.length;
+};
+
+
+/**
+ * Returns the unbiased sample variance of the arguments. For a definition,
+ * see e.g. http://en.wikipedia.org/wiki/Variance
+ * @param {...number} var_args Number samples to analyze.
+ * @return {number} The unbiased sample variance of the arguments (0 if fewer
+ * than two samples were provided, or {@code NaN} if any of the samples is
+ * not a valid number).
+ */
+goog.math.sampleVariance = function(var_args) {
+ var sampleSize = arguments.length;
+ if (sampleSize < 2) {
+ return 0;
+ }
+
+ var mean = goog.math.average.apply(null, arguments);
+ var variance =
+ goog.math.sum.apply(null, goog.array.map(arguments, function(val) {
+ return Math.pow(val - mean, 2);
+ })) / (sampleSize - 1);
+
+ return variance;
+};
+
+
+/**
+ * Returns the sample standard deviation of the arguments. For a definition of
+ * sample standard deviation, see e.g.
+ * http://en.wikipedia.org/wiki/Standard_deviation
+ * @param {...number} var_args Number samples to analyze.
+ * @return {number} The sample standard deviation of the arguments (0 if fewer
+ * than two samples were provided, or {@code NaN} if any of the samples is
+ * not a valid number).
+ */
+goog.math.standardDeviation = function(var_args) {
+ return Math.sqrt(goog.math.sampleVariance.apply(null, arguments));
+};
+
+
+/**
+ * Returns whether the supplied number represents an integer, i.e. that is has
+ * no fractional component. No range-checking is performed on the number.
+ * @param {number} num The number to test.
+ * @return {boolean} Whether {@code num} is an integer.
+ */
+goog.math.isInt = function(num) {
+ return isFinite(num) && num % 1 == 0;
+};
+
+
+/**
+ * Returns whether the supplied number is finite and not NaN.
+ * @param {number} num The number to test.
+ * @return {boolean} Whether {@code num} is a finite number.
+ */
+goog.math.isFiniteNumber = function(num) {
+ return isFinite(num) && !isNaN(num);
+};
+
+
+/**
+ * @param {number} num The number to test.
+ * @return {boolean} Whether it is negative zero.
+ */
+goog.math.isNegativeZero = function(num) {
+ return num == 0 && 1 / num < 0;
+};
+
+
+/**
+ * Returns the precise value of floor(log10(num)).
+ * Simpler implementations didn't work because of floating point rounding
+ * errors. For example
+ * <ul>
+ * <li>Math.floor(Math.log(num) / Math.LN10) is off by one for num == 1e+3.
+ * <li>Math.floor(Math.log(num) * Math.LOG10E) is off by one for num == 1e+15.
+ * <li>Math.floor(Math.log10(num)) is off by one for num == 1e+15 - 1.
+ * </ul>
+ * @param {number} num A floating point number.
+ * @return {number} Its logarithm to base 10 rounded down to the nearest
+ * integer if num > 0. -Infinity if num == 0. NaN if num < 0.
+ */
+goog.math.log10Floor = function(num) {
+ if (num > 0) {
+ var x = Math.round(Math.log(num) * Math.LOG10E);
+ return x - (parseFloat('1e' + x) > num ? 1 : 0);
+ }
+ return num == 0 ? -Infinity : NaN;
+};
+
+
+/**
+ * A tweaked variant of {@code Math.floor} which tolerates if the passed number
+ * is infinitesimally smaller than the closest integer. It often happens with
+ * the results of floating point calculations because of the finite precision
+ * of the intermediate results. For example {@code Math.floor(Math.log(1000) /
+ * Math.LN10) == 2}, not 3 as one would expect.
+ * @param {number} num A number.
+ * @param {number=} opt_epsilon An infinitesimally small positive number, the
+ * rounding error to tolerate.
+ * @return {number} The largest integer less than or equal to {@code num}.
+ */
+goog.math.safeFloor = function(num, opt_epsilon) {
+ goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
+ return Math.floor(num + (opt_epsilon || 2e-15));
+};
+
+
+/**
+ * A tweaked variant of {@code Math.ceil}. See {@code goog.math.safeFloor} for
+ * details.
+ * @param {number} num A number.
+ * @param {number=} opt_epsilon An infinitesimally small positive number, the
+ * rounding error to tolerate.
+ * @return {number} The smallest integer greater than or equal to {@code num}.
+ */
+goog.math.safeCeil = function(num, opt_epsilon) {
+ goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
+ return Math.ceil(num - (opt_epsilon || 2e-15));
+};
+
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
* @fileoverview Utilities related to color and color conversion.
*/
@@ -24439,9 +19639,10 @@ goog.color.parse = function(str) {
*/
goog.color.isValidColor = function(str) {
var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
- return !!(goog.color.isValidHexColor_(maybeHex) ||
- goog.color.isValidRgbColor_(str).length ||
- goog.color.names && goog.color.names[str.toLowerCase()]);
+ return !!(
+ goog.color.isValidHexColor_(maybeHex) ||
+ goog.color.isValidRgbColor_(str).length ||
+ goog.color.names && goog.color.names[str.toLowerCase()]);
};
@@ -24490,7 +19691,7 @@ goog.color.normalizeHex = function(hexColor) {
if (!goog.color.isValidHexColor_(hexColor)) {
throw Error("'" + hexColor + "' is not a valid hex color");
}
- if (hexColor.length == 4) { // of the form #RGB
+ if (hexColor.length == 4) { // of the form #RGB
hexColor = hexColor.replace(goog.color.hexTripletRe_, '#$1$1$2$2$3$3');
}
return hexColor.toLowerCase();
@@ -24523,9 +19724,7 @@ goog.color.rgbToHex = function(r, g, b) {
r = Number(r);
g = Number(g);
b = Number(b);
- if (isNaN(r) || r < 0 || r > 255 ||
- isNaN(g) || g < 0 || g > 255 ||
- isNaN(b) || b < 0 || b > 255) {
+ if (r != (r & 255) || g != (g & 255) || b != (b & 255)) {
throw Error('"(' + r + ',' + g + ',' + b + '") is not a valid RGB color');
}
var hexR = goog.color.prependZeroIfNecessaryHelper(r.toString(16));
@@ -24636,7 +19835,7 @@ goog.color.hslToRgb = function(h, s, l) {
var r = 0;
var g = 0;
var b = 0;
- var normH = h / 360; // normalize h to fall in [0, 1]
+ var normH = h / 360; // normalize h to fall in [0, 1]
if (s == 0) {
r = g = b = l * 255;
@@ -24737,9 +19936,7 @@ goog.color.isValidRgbColor_ = function(str) {
var r = Number(regExpResultArray[1]);
var g = Number(regExpResultArray[2]);
var b = Number(regExpResultArray[3]);
- if (r >= 0 && r <= 255 &&
- g >= 0 && g <= 255 &&
- b >= 0 && b <= 255) {
+ if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
return [r, g, b];
}
}
@@ -24998,8 +20195,8 @@ goog.color.hslDistance = function(hsl1, hsl2) {
var h1 = hsl1[0] / 360.0;
var h2 = hsl2[0] / 360.0;
var dh = (h1 - h2) * 2.0 * Math.PI;
- return (hsl1[2] - hsl2[2]) * (hsl1[2] - hsl2[2]) +
- sl1 * sl1 + sl2 * sl2 - 2 * sl1 * sl2 * Math.cos(dh);
+ return (hsl1[2] - hsl2[2]) * (hsl1[2] - hsl2[2]) + sl1 * sl1 + sl2 * sl2 -
+ 2 * sl1 * sl2 * Math.cos(dh);
};
@@ -25070,9 +20267,7 @@ goog.color.highContrast = function(prime, suggestions) {
goog.color.colorDiff_(suggestions[i], prime)
});
}
- suggestionsWithDiff.sort(function(a, b) {
- return b.diff - a.diff;
- });
+ suggestionsWithDiff.sort(function(a, b) { return b.diff - a.diff; });
return suggestionsWithDiff[0].color;
};
@@ -25099,8 +20294,8 @@ goog.color.yiqBrightness_ = function(rgb) {
* @private
*/
goog.color.yiqBrightnessDiff_ = function(rgb1, rgb2) {
- return Math.abs(goog.color.yiqBrightness_(rgb1) -
- goog.color.yiqBrightness_(rgb2));
+ return Math.abs(
+ goog.color.yiqBrightness_(rgb1) - goog.color.yiqBrightness_(rgb2));
};
@@ -25122,28 +20317,16 @@ goog.color.colorDiff_ = function(rgb1, rgb2) {
// causes occasional loss of precision and rounding errors, especially in the
// alpha channel.
-goog.provide('ol.Color');
goog.provide('ol.color');
goog.require('goog.asserts');
goog.require('goog.color');
goog.require('goog.color.names');
-goog.require('goog.vec.Mat4');
goog.require('ol');
goog.require('ol.math');
/**
- * A color represented as a short array [red, green, blue, alpha].
- * red, green, and blue should be integers in the range 0..255 inclusive.
- * alpha should be a float in the range 0..1 inclusive.
- * @typedef {Array.<number>}
- * @api
- */
-ol.Color;
-
-
-/**
* This RegExp matches # followed by 3 or 6 hex digits.
* @const
* @type {RegExp}
@@ -25173,48 +20356,6 @@ ol.color.rgbaColorRe_ =
/**
- * @param {ol.Color} dst Destination.
- * @param {ol.Color} src Source.
- * @param {ol.Color=} opt_color Color.
- * @return {ol.Color} Color.
- */
-ol.color.blend = function(dst, src, opt_color) {
- // http://en.wikipedia.org/wiki/Alpha_compositing
- // FIXME do we need to scale by 255?
- var out = opt_color ? opt_color : [];
- var dstA = dst[3];
- var srcA = src[3];
- if (dstA == 1) {
- out[0] = (src[0] * srcA + dst[0] * (1 - srcA) + 0.5) | 0;
- out[1] = (src[1] * srcA + dst[1] * (1 - srcA) + 0.5) | 0;
- out[2] = (src[2] * srcA + dst[2] * (1 - srcA) + 0.5) | 0;
- out[3] = 1;
- } else if (srcA === 0) {
- out[0] = dst[0];
- out[1] = dst[1];
- out[2] = dst[2];
- out[3] = dstA;
- } else {
- var outA = srcA + dstA * (1 - srcA);
- if (outA === 0) {
- out[0] = 0;
- out[1] = 0;
- out[2] = 0;
- out[3] = 0;
- } else {
- out[0] = ((src[0] * srcA + dst[0] * dstA * (1 - srcA)) / outA + 0.5) | 0;
- out[1] = ((src[1] * srcA + dst[1] * dstA * (1 - srcA)) / outA + 0.5) | 0;
- out[2] = ((src[2] * srcA + dst[2] * dstA * (1 - srcA)) / outA + 0.5) | 0;
- out[3] = outA;
- }
- }
- goog.asserts.assert(ol.color.isValid(out),
- 'Output color of blend should be a valid color');
- return out;
-};
-
-
-/**
* Return the color as an array. This function maintains a cache of calculated
* arrays which means the result should not be modified.
* @param {ol.Color|string} color Color.
@@ -25222,10 +20363,10 @@ ol.color.blend = function(dst, src, opt_color) {
* @api
*/
ol.color.asArray = function(color) {
- if (goog.isArray(color)) {
+ if (Array.isArray(color)) {
return color;
} else {
- goog.asserts.assert(goog.isString(color), 'Color should be a string');
+ goog.asserts.assert(typeof color === 'string', 'Color should be a string');
return ol.color.fromString(color);
}
};
@@ -25238,35 +20379,20 @@ ol.color.asArray = function(color) {
* @api
*/
ol.color.asString = function(color) {
- if (goog.isString(color)) {
+ if (typeof color === 'string') {
return color;
} else {
- goog.asserts.assert(goog.isArray(color), 'Color should be an array');
+ goog.asserts.assert(Array.isArray(color), 'Color should be an array');
return ol.color.toString(color);
}
};
/**
- * @param {ol.Color} color1 Color1.
- * @param {ol.Color} color2 Color2.
- * @return {boolean} Equals.
- */
-ol.color.equals = function(color1, color2) {
- return color1 === color2 || (
- color1[0] == color2[0] && color1[1] == color2[1] &&
- color1[2] == color2[2] && color1[3] == color2[3]);
-};
-
-
-/**
* @param {string} s String.
* @return {ol.Color} Color.
*/
ol.color.fromString = (
- /**
- * @return {function(string): ol.Color}
- */
function() {
// We maintain a small cache of parsed strings. To provide cheap LRU-like
@@ -25415,44 +20541,2082 @@ ol.color.toString = function(color) {
if (b != (b | 0)) {
b = (b + 0.5) | 0;
}
- var a = color[3];
+ var a = color[3] === undefined ? 1 : color[3];
return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
};
+goog.provide('ol.colorlike');
+
+goog.require('ol.color');
+
/**
- * @param {!ol.Color} color Color.
- * @param {goog.vec.Mat4.Number} transform Transform.
- * @param {!ol.Color=} opt_color Color.
- * @return {ol.Color} Transformed color.
+ * @param {ol.Color|ol.ColorLike} color Color.
+ * @return {ol.ColorLike} The color as an ol.ColorLike
+ * @api
*/
-ol.color.transform = function(color, transform, opt_color) {
- var result = opt_color ? opt_color : [];
- result = goog.vec.Mat4.multVec3(transform, color, result);
- goog.asserts.assert(goog.isArray(result), 'result should be an array');
- result[3] = color[3];
- return ol.color.normalize(result, result);
+ol.colorlike.asColorLike = function(color) {
+ if (ol.colorlike.isColorLike(color)) {
+ return /** @type {string|CanvasPattern|CanvasGradient} */ (color);
+ } else {
+ return ol.color.asString(/** @type {ol.Color} */ (color));
+ }
};
/**
- * @param {ol.Color|string} color1 Color2.
- * @param {ol.Color|string} color2 Color2.
- * @return {boolean} Equals.
+ * @param {?} color The value that is potentially an ol.ColorLike
+ * @return {boolean} Whether the color is an ol.ColorLike
*/
-ol.color.stringOrColorEquals = function(color1, color2) {
- if (color1 === color2 || color1 == color2) {
- return true;
+ol.colorlike.isColorLike = function(color) {
+ return (
+ typeof color === 'string' ||
+ color instanceof CanvasPattern ||
+ color instanceof CanvasGradient
+ );
+};
+
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Utilities used by goog.labs.userAgent tools. These functions
+ * should not be used outside of goog.labs.userAgent.*.
+ *
+ *
+ * @author nnaze@google.com (Nathan Naze)
+ */
+
+goog.provide('goog.labs.userAgent.util');
+
+goog.require('goog.string');
+
+
+/**
+ * Gets the native userAgent string from navigator if it exists.
+ * If navigator or navigator.userAgent string is missing, returns an empty
+ * string.
+ * @return {string}
+ * @private
+ */
+goog.labs.userAgent.util.getNativeUserAgentString_ = function() {
+ var navigator = goog.labs.userAgent.util.getNavigator_();
+ if (navigator) {
+ var userAgent = navigator.userAgent;
+ if (userAgent) {
+ return userAgent;
+ }
+ }
+ return '';
+};
+
+
+/**
+ * Getter for the native navigator.
+ * This is a separate function so it can be stubbed out in testing.
+ * @return {Navigator}
+ * @private
+ */
+goog.labs.userAgent.util.getNavigator_ = function() {
+ return goog.global.navigator;
+};
+
+
+/**
+ * A possible override for applications which wish to not check
+ * navigator.userAgent but use a specified value for detection instead.
+ * @private {string}
+ */
+goog.labs.userAgent.util.userAgent_ =
+ goog.labs.userAgent.util.getNativeUserAgentString_();
+
+
+/**
+ * Applications may override browser detection on the built in
+ * navigator.userAgent object by setting this string. Set to null to use the
+ * browser object instead.
+ * @param {?string=} opt_userAgent The User-Agent override.
+ */
+goog.labs.userAgent.util.setUserAgent = function(opt_userAgent) {
+ goog.labs.userAgent.util.userAgent_ =
+ opt_userAgent || goog.labs.userAgent.util.getNativeUserAgentString_();
+};
+
+
+/**
+ * @return {string} The user agent string.
+ */
+goog.labs.userAgent.util.getUserAgent = function() {
+ return goog.labs.userAgent.util.userAgent_;
+};
+
+
+/**
+ * @param {string} str
+ * @return {boolean} Whether the user agent contains the given string, ignoring
+ * case.
+ */
+goog.labs.userAgent.util.matchUserAgent = function(str) {
+ var userAgent = goog.labs.userAgent.util.getUserAgent();
+ return goog.string.contains(userAgent, str);
+};
+
+
+/**
+ * @param {string} str
+ * @return {boolean} Whether the user agent contains the given string.
+ */
+goog.labs.userAgent.util.matchUserAgentIgnoreCase = function(str) {
+ var userAgent = goog.labs.userAgent.util.getUserAgent();
+ return goog.string.caseInsensitiveContains(userAgent, str);
+};
+
+
+/**
+ * Parses the user agent into tuples for each section.
+ * @param {string} userAgent
+ * @return {!Array<!Array<string>>} Tuples of key, version, and the contents
+ * of the parenthetical.
+ */
+goog.labs.userAgent.util.extractVersionTuples = function(userAgent) {
+ // Matches each section of a user agent string.
+ // Example UA:
+ // Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us)
+ // AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405
+ // This has three version tuples: Mozilla, AppleWebKit, and Mobile.
+
+ var versionRegExp = new RegExp(
+ // Key. Note that a key may have a space.
+ // (i.e. 'Mobile Safari' in 'Mobile Safari/5.0')
+ '(\\w[\\w ]+)' +
+
+ '/' + // slash
+ '([^\\s]+)' + // version (i.e. '5.0b')
+ '\\s*' + // whitespace
+ '(?:\\((.*?)\\))?', // parenthetical info. parentheses not matched.
+ 'g');
+
+ var data = [];
+ var match;
+
+ // Iterate and collect the version tuples. Each iteration will be the
+ // next regex match.
+ while (match = versionRegExp.exec(userAgent)) {
+ data.push([
+ match[1], // key
+ match[2], // value
+ // || undefined as this is not undefined in IE7 and IE8
+ match[3] || undefined // info
+ ]);
+ }
+
+ return data;
+};
+
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Utilities for manipulating objects/maps/hashes.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.object');
+
+
+/**
+ * Calls a function for each element in an object/map/hash.
+ *
+ * @param {Object<K,V>} obj The object over which to iterate.
+ * @param {function(this:T,V,?,Object<K,V>):?} f The function to call
+ * for every element. This function takes 3 arguments (the value, the
+ * key and the object) and the return value is ignored.
+ * @param {T=} opt_obj This is used as the 'this' object within f.
+ * @template T,K,V
+ */
+goog.object.forEach = function(obj, f, opt_obj) {
+ for (var key in obj) {
+ f.call(/** @type {?} */ (opt_obj), obj[key], key, obj);
+ }
+};
+
+
+/**
+ * Calls a function for each element in an object/map/hash. If that call returns
+ * true, adds the element to a new object.
+ *
+ * @param {Object<K,V>} obj The object over which to iterate.
+ * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to call
+ * for every element. This
+ * function takes 3 arguments (the value, the key and the object)
+ * and should return a boolean. If the return value is true the
+ * element is added to the result object. If it is false the
+ * element is not included.
+ * @param {T=} opt_obj This is used as the 'this' object within f.
+ * @return {!Object<K,V>} a new object in which only elements that passed the
+ * test are present.
+ * @template T,K,V
+ */
+goog.object.filter = function(obj, f, opt_obj) {
+ var res = {};
+ for (var key in obj) {
+ if (f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {
+ res[key] = obj[key];
+ }
+ }
+ return res;
+};
+
+
+/**
+ * For every element in an object/map/hash calls a function and inserts the
+ * result into a new object.
+ *
+ * @param {Object<K,V>} obj The object over which to iterate.
+ * @param {function(this:T,V,?,Object<K,V>):R} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the value, the key and the object)
+ * and should return something. The result will be inserted
+ * into a new object.
+ * @param {T=} opt_obj This is used as the 'this' object within f.
+ * @return {!Object<K,R>} a new object with the results from f.
+ * @template T,K,V,R
+ */
+goog.object.map = function(obj, f, opt_obj) {
+ var res = {};
+ for (var key in obj) {
+ res[key] = f.call(/** @type {?} */ (opt_obj), obj[key], key, obj);
+ }
+ return res;
+};
+
+
+/**
+ * Calls a function for each element in an object/map/hash. If any
+ * call returns true, returns true (without checking the rest). If
+ * all calls return false, returns false.
+ *
+ * @param {Object<K,V>} obj The object to check.
+ * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to
+ * call for every element. This function
+ * takes 3 arguments (the value, the key and the object) and should
+ * return a boolean.
+ * @param {T=} opt_obj This is used as the 'this' object within f.
+ * @return {boolean} true if any element passes the test.
+ * @template T,K,V
+ */
+goog.object.some = function(obj, f, opt_obj) {
+ for (var key in obj) {
+ if (f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Calls a function for each element in an object/map/hash. If
+ * all calls return true, returns true. If any call returns false, returns
+ * false at this point and does not continue to check the remaining elements.
+ *
+ * @param {Object<K,V>} obj The object to check.
+ * @param {?function(this:T,V,?,Object<K,V>):boolean} f The function to
+ * call for every element. This function
+ * takes 3 arguments (the value, the key and the object) and should
+ * return a boolean.
+ * @param {T=} opt_obj This is used as the 'this' object within f.
+ * @return {boolean} false if any element fails the test.
+ * @template T,K,V
+ */
+goog.object.every = function(obj, f, opt_obj) {
+ for (var key in obj) {
+ if (!f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Returns the number of key-value pairs in the object map.
+ *
+ * @param {Object} obj The object for which to get the number of key-value
+ * pairs.
+ * @return {number} The number of key-value pairs in the object map.
+ */
+goog.object.getCount = function(obj) {
+ // JS1.5 has __count__ but it has been deprecated so it raises a warning...
+ // in other words do not use. Also __count__ only includes the fields on the
+ // actual object and not in the prototype chain.
+ var rv = 0;
+ for (var key in obj) {
+ rv++;
}
- if (goog.isString(color1)) {
- color1 = ol.color.fromString(color1);
+ return rv;
+};
+
+
+/**
+ * Returns one key from the object map, if any exists.
+ * For map literals the returned key will be the first one in most of the
+ * browsers (a know exception is Konqueror).
+ *
+ * @param {Object} obj The object to pick a key from.
+ * @return {string|undefined} The key or undefined if the object is empty.
+ */
+goog.object.getAnyKey = function(obj) {
+ for (var key in obj) {
+ return key;
}
- if (goog.isString(color2)) {
- color2 = ol.color.fromString(color2);
+};
+
+
+/**
+ * Returns one value from the object map, if any exists.
+ * For map literals the returned value will be the first one in most of the
+ * browsers (a know exception is Konqueror).
+ *
+ * @param {Object<K,V>} obj The object to pick a value from.
+ * @return {V|undefined} The value or undefined if the object is empty.
+ * @template K,V
+ */
+goog.object.getAnyValue = function(obj) {
+ for (var key in obj) {
+ return obj[key];
}
- return ol.color.equals(color1, color2);
};
+
+/**
+ * Whether the object/hash/map contains the given object as a value.
+ * An alias for goog.object.containsValue(obj, val).
+ *
+ * @param {Object<K,V>} obj The object in which to look for val.
+ * @param {V} val The object for which to check.
+ * @return {boolean} true if val is present.
+ * @template K,V
+ */
+goog.object.contains = function(obj, val) {
+ return goog.object.containsValue(obj, val);
+};
+
+
+/**
+ * Returns the values of the object/map/hash.
+ *
+ * @param {Object<K,V>} obj The object from which to get the values.
+ * @return {!Array<V>} The values in the object/map/hash.
+ * @template K,V
+ */
+goog.object.getValues = function(obj) {
+ var res = [];
+ var i = 0;
+ for (var key in obj) {
+ res[i++] = obj[key];
+ }
+ return res;
+};
+
+
+/**
+ * Returns the keys of the object/map/hash.
+ *
+ * @param {Object} obj The object from which to get the keys.
+ * @return {!Array<string>} Array of property keys.
+ */
+goog.object.getKeys = function(obj) {
+ var res = [];
+ var i = 0;
+ for (var key in obj) {
+ res[i++] = key;
+ }
+ return res;
+};
+
+
+/**
+ * Get a value from an object multiple levels deep. This is useful for
+ * pulling values from deeply nested objects, such as JSON responses.
+ * Example usage: getValueByKeys(jsonObj, 'foo', 'entries', 3)
+ *
+ * @param {!Object} obj An object to get the value from. Can be array-like.
+ * @param {...(string|number|!IArrayLike<number|string>)}
+ * var_args A number of keys
+ * (as strings, or numbers, for array-like objects). Can also be
+ * specified as a single array of keys.
+ * @return {*} The resulting value. If, at any point, the value for a key
+ * is undefined, returns undefined.
+ */
+goog.object.getValueByKeys = function(obj, var_args) {
+ var isArrayLike = goog.isArrayLike(var_args);
+ var keys = isArrayLike ? var_args : arguments;
+
+ // Start with the 2nd parameter for the variable parameters syntax.
+ for (var i = isArrayLike ? 0 : 1; i < keys.length; i++) {
+ obj = obj[keys[i]];
+ if (!goog.isDef(obj)) {
+ break;
+ }
+ }
+
+ return obj;
+};
+
+
+/**
+ * Whether the object/map/hash contains the given key.
+ *
+ * @param {Object} obj The object in which to look for key.
+ * @param {?} key The key for which to check.
+ * @return {boolean} true If the map contains the key.
+ */
+goog.object.containsKey = function(obj, key) {
+ return obj !== null && key in obj;
+};
+
+
+/**
+ * Whether the object/map/hash contains the given value. This is O(n).
+ *
+ * @param {Object<K,V>} obj The object in which to look for val.
+ * @param {V} val The value for which to check.
+ * @return {boolean} true If the map contains the value.
+ * @template K,V
+ */
+goog.object.containsValue = function(obj, val) {
+ for (var key in obj) {
+ if (obj[key] == val) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Searches an object for an element that satisfies the given condition and
+ * returns its key.
+ * @param {Object<K,V>} obj The object to search in.
+ * @param {function(this:T,V,string,Object<K,V>):boolean} f The
+ * function to call for every element. Takes 3 arguments (the value,
+ * the key and the object) and should return a boolean.
+ * @param {T=} opt_this An optional "this" context for the function.
+ * @return {string|undefined} The key of an element for which the function
+ * returns true or undefined if no such element is found.
+ * @template T,K,V
+ */
+goog.object.findKey = function(obj, f, opt_this) {
+ for (var key in obj) {
+ if (f.call(/** @type {?} */ (opt_this), obj[key], key, obj)) {
+ return key;
+ }
+ }
+ return undefined;
+};
+
+
+/**
+ * Searches an object for an element that satisfies the given condition and
+ * returns its value.
+ * @param {Object<K,V>} obj The object to search in.
+ * @param {function(this:T,V,string,Object<K,V>):boolean} f The function
+ * to call for every element. Takes 3 arguments (the value, the key
+ * and the object) and should return a boolean.
+ * @param {T=} opt_this An optional "this" context for the function.
+ * @return {V} The value of an element for which the function returns true or
+ * undefined if no such element is found.
+ * @template T,K,V
+ */
+goog.object.findValue = function(obj, f, opt_this) {
+ var key = goog.object.findKey(obj, f, opt_this);
+ return key && obj[key];
+};
+
+
+/**
+ * Whether the object/map/hash is empty.
+ *
+ * @param {Object} obj The object to test.
+ * @return {boolean} true if obj is empty.
+ */
+goog.object.isEmpty = function(obj) {
+ for (var key in obj) {
+ return false;
+ }
+ return true;
+};
+
+
+/**
+ * Removes all key value pairs from the object/map/hash.
+ *
+ * @param {Object} obj The object to clear.
+ */
+goog.object.clear = function(obj) {
+ for (var i in obj) {
+ delete obj[i];
+ }
+};
+
+
+/**
+ * Removes a key-value pair based on the key.
+ *
+ * @param {Object} obj The object from which to remove the key.
+ * @param {?} key The key to remove.
+ * @return {boolean} Whether an element was removed.
+ */
+goog.object.remove = function(obj, key) {
+ var rv;
+ if (rv = key in /** @type {!Object} */ (obj)) {
+ delete obj[key];
+ }
+ return rv;
+};
+
+
+/**
+ * Adds a key-value pair to the object. Throws an exception if the key is
+ * already in use. Use set if you want to change an existing pair.
+ *
+ * @param {Object<K,V>} obj The object to which to add the key-value pair.
+ * @param {string} key The key to add.
+ * @param {V} val The value to add.
+ * @template K,V
+ */
+goog.object.add = function(obj, key, val) {
+ if (obj !== null && key in obj) {
+ throw Error('The object already contains the key "' + key + '"');
+ }
+ goog.object.set(obj, key, val);
+};
+
+
+/**
+ * Returns the value for the given key.
+ *
+ * @param {Object<K,V>} obj The object from which to get the value.
+ * @param {string} key The key for which to get the value.
+ * @param {R=} opt_val The value to return if no item is found for the given
+ * key (default is undefined).
+ * @return {V|R|undefined} The value for the given key.
+ * @template K,V,R
+ */
+goog.object.get = function(obj, key, opt_val) {
+ if (obj !== null && key in obj) {
+ return obj[key];
+ }
+ return opt_val;
+};
+
+
+/**
+ * Adds a key-value pair to the object/map/hash.
+ *
+ * @param {Object<K,V>} obj The object to which to add the key-value pair.
+ * @param {string} key The key to add.
+ * @param {V} value The value to add.
+ * @template K,V
+ */
+goog.object.set = function(obj, key, value) {
+ obj[key] = value;
+};
+
+
+/**
+ * Adds a key-value pair to the object/map/hash if it doesn't exist yet.
+ *
+ * @param {Object<K,V>} obj The object to which to add the key-value pair.
+ * @param {string} key The key to add.
+ * @param {V} value The value to add if the key wasn't present.
+ * @return {V} The value of the entry at the end of the function.
+ * @template K,V
+ */
+goog.object.setIfUndefined = function(obj, key, value) {
+ return key in /** @type {!Object} */ (obj) ? obj[key] : (obj[key] = value);
+};
+
+
+/**
+ * Sets a key and value to an object if the key is not set. The value will be
+ * the return value of the given function. If the key already exists, the
+ * object will not be changed and the function will not be called (the function
+ * will be lazily evaluated -- only called if necessary).
+ *
+ * This function is particularly useful for use with a map used a as a cache.
+ *
+ * @param {!Object<K,V>} obj The object to which to add the key-value pair.
+ * @param {string} key The key to add.
+ * @param {function():V} f The value to add if the key wasn't present.
+ * @return {V} The value of the entry at the end of the function.
+ * @template K,V
+ */
+goog.object.setWithReturnValueIfNotSet = function(obj, key, f) {
+ if (key in obj) {
+ return obj[key];
+ }
+
+ var val = f();
+ obj[key] = val;
+ return val;
+};
+
+
+/**
+ * Compares two objects for equality using === on the values.
+ *
+ * @param {!Object<K,V>} a
+ * @param {!Object<K,V>} b
+ * @return {boolean}
+ * @template K,V
+ */
+goog.object.equals = function(a, b) {
+ for (var k in a) {
+ if (!(k in b) || a[k] !== b[k]) {
+ return false;
+ }
+ }
+ for (var k in b) {
+ if (!(k in a)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Does a flat clone of the object.
+ *
+ * @param {Object<K,V>} obj Object to clone.
+ * @return {!Object<K,V>} Clone of the input object.
+ * @template K,V
+ */
+goog.object.clone = function(obj) {
+ // We cannot use the prototype trick because a lot of methods depend on where
+ // the actual key is set.
+
+ var res = {};
+ for (var key in obj) {
+ res[key] = obj[key];
+ }
+ return res;
+ // We could also use goog.mixin but I wanted this to be independent from that.
+};
+
+
+/**
+ * Clones a value. The input may be an Object, Array, or basic type. Objects and
+ * arrays will be cloned recursively.
+ *
+ * WARNINGS:
+ * <code>goog.object.unsafeClone</code> does not detect reference loops. Objects
+ * that refer to themselves will cause infinite recursion.
+ *
+ * <code>goog.object.unsafeClone</code> is unaware of unique identifiers, and
+ * copies UIDs created by <code>getUid</code> into cloned results.
+ *
+ * @param {*} obj The value to clone.
+ * @return {*} A clone of the input value.
+ */
+goog.object.unsafeClone = function(obj) {
+ var type = goog.typeOf(obj);
+ if (type == 'object' || type == 'array') {
+ if (goog.isFunction(obj.clone)) {
+ return obj.clone();
+ }
+ var clone = type == 'array' ? [] : {};
+ for (var key in obj) {
+ clone[key] = goog.object.unsafeClone(obj[key]);
+ }
+ return clone;
+ }
+
+ return obj;
+};
+
+
+/**
+ * Returns a new object in which all the keys and values are interchanged
+ * (keys become values and values become keys). If multiple keys map to the
+ * same value, the chosen transposed value is implementation-dependent.
+ *
+ * @param {Object} obj The object to transpose.
+ * @return {!Object} The transposed object.
+ */
+goog.object.transpose = function(obj) {
+ var transposed = {};
+ for (var key in obj) {
+ transposed[obj[key]] = key;
+ }
+ return transposed;
+};
+
+
+/**
+ * The names of the fields that are defined on Object.prototype.
+ * @type {Array<string>}
+ * @private
+ */
+goog.object.PROTOTYPE_FIELDS_ = [
+ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
+ 'toLocaleString', 'toString', 'valueOf'
+];
+
+
+/**
+ * Extends an object with another object.
+ * This operates 'in-place'; it does not create a new Object.
+ *
+ * Example:
+ * var o = {};
+ * goog.object.extend(o, {a: 0, b: 1});
+ * o; // {a: 0, b: 1}
+ * goog.object.extend(o, {b: 2, c: 3});
+ * o; // {a: 0, b: 2, c: 3}
+ *
+ * @param {Object} target The object to modify. Existing properties will be
+ * overwritten if they are also present in one of the objects in
+ * {@code var_args}.
+ * @param {...Object} var_args The objects from which values will be copied.
+ */
+goog.object.extend = function(target, var_args) {
+ var key, source;
+ for (var i = 1; i < arguments.length; i++) {
+ source = arguments[i];
+ for (key in source) {
+ target[key] = source[key];
+ }
+
+ // For IE the for-in-loop does not contain any properties that are not
+ // enumerable on the prototype object (for example isPrototypeOf from
+ // Object.prototype) and it will also not include 'replace' on objects that
+ // extend String and change 'replace' (not that it is common for anyone to
+ // extend anything except Object).
+
+ for (var j = 0; j < goog.object.PROTOTYPE_FIELDS_.length; j++) {
+ key = goog.object.PROTOTYPE_FIELDS_[j];
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+};
+
+
+/**
+ * Creates a new object built from the key-value pairs provided as arguments.
+ * @param {...*} var_args If only one argument is provided and it is an array
+ * then this is used as the arguments, otherwise even arguments are used as
+ * the property names and odd arguments are used as the property values.
+ * @return {!Object} The new object.
+ * @throws {Error} If there are uneven number of arguments or there is only one
+ * non array argument.
+ */
+goog.object.create = function(var_args) {
+ var argLength = arguments.length;
+ if (argLength == 1 && goog.isArray(arguments[0])) {
+ return goog.object.create.apply(null, arguments[0]);
+ }
+
+ if (argLength % 2) {
+ throw Error('Uneven number of arguments');
+ }
+
+ var rv = {};
+ for (var i = 0; i < argLength; i += 2) {
+ rv[arguments[i]] = arguments[i + 1];
+ }
+ return rv;
+};
+
+
+/**
+ * Creates a new object where the property names come from the arguments but
+ * the value is always set to true
+ * @param {...*} var_args If only one argument is provided and it is an array
+ * then this is used as the arguments, otherwise the arguments are used
+ * as the property names.
+ * @return {!Object} The new object.
+ */
+goog.object.createSet = function(var_args) {
+ var argLength = arguments.length;
+ if (argLength == 1 && goog.isArray(arguments[0])) {
+ return goog.object.createSet.apply(null, arguments[0]);
+ }
+
+ var rv = {};
+ for (var i = 0; i < argLength; i++) {
+ rv[arguments[i]] = true;
+ }
+ return rv;
+};
+
+
+/**
+ * Creates an immutable view of the underlying object, if the browser
+ * supports immutable objects.
+ *
+ * In default mode, writes to this view will fail silently. In strict mode,
+ * they will throw an error.
+ *
+ * @param {!Object<K,V>} obj An object.
+ * @return {!Object<K,V>} An immutable view of that object, or the
+ * original object if this browser does not support immutables.
+ * @template K,V
+ */
+goog.object.createImmutableView = function(obj) {
+ var result = obj;
+ if (Object.isFrozen && !Object.isFrozen(obj)) {
+ result = Object.create(obj);
+ Object.freeze(result);
+ }
+ return result;
+};
+
+
+/**
+ * @param {!Object} obj An object.
+ * @return {boolean} Whether this is an immutable view of the object.
+ */
+goog.object.isImmutableView = function(obj) {
+ return !!Object.isFrozen && Object.isFrozen(obj);
+};
+
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Closure user agent detection (Browser).
+ * @see <a href="http://www.useragentstring.com/">User agent strings</a>
+ * For more information on rendering engine, platform, or device see the other
+ * sub-namespaces in goog.labs.userAgent, goog.labs.userAgent.platform,
+ * goog.labs.userAgent.device respectively.)
+ *
+ * @author martone@google.com (Andy Martone)
+ */
+
+goog.provide('goog.labs.userAgent.browser');
+
+goog.require('goog.array');
+goog.require('goog.labs.userAgent.util');
+goog.require('goog.object');
+goog.require('goog.string');
+
+
+// TODO(nnaze): Refactor to remove excessive exclusion logic in matching
+// functions.
+
+
+/**
+ * @return {boolean} Whether the user's browser is Opera.
+ * @private
+ */
+goog.labs.userAgent.browser.matchOpera_ = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Opera') ||
+ goog.labs.userAgent.util.matchUserAgent('OPR');
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is IE.
+ * @private
+ */
+goog.labs.userAgent.browser.matchIE_ = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Trident') ||
+ goog.labs.userAgent.util.matchUserAgent('MSIE');
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is Edge.
+ * @private
+ */
+goog.labs.userAgent.browser.matchEdge_ = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Edge');
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is Firefox.
+ * @private
+ */
+goog.labs.userAgent.browser.matchFirefox_ = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Firefox');
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is Safari.
+ * @private
+ */
+goog.labs.userAgent.browser.matchSafari_ = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Safari') &&
+ !(goog.labs.userAgent.browser.matchChrome_() ||
+ goog.labs.userAgent.browser.matchCoast_() ||
+ goog.labs.userAgent.browser.matchOpera_() ||
+ goog.labs.userAgent.browser.matchEdge_() ||
+ goog.labs.userAgent.browser.isSilk() ||
+ goog.labs.userAgent.util.matchUserAgent('Android'));
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based
+ * iOS browser).
+ * @private
+ */
+goog.labs.userAgent.browser.matchCoast_ = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Coast');
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is iOS Webview.
+ * @private
+ */
+goog.labs.userAgent.browser.matchIosWebview_ = function() {
+ // iOS Webview does not show up as Chrome or Safari. Also check for Opera's
+ // WebKit-based iOS browser, Coast.
+ return (goog.labs.userAgent.util.matchUserAgent('iPad') ||
+ goog.labs.userAgent.util.matchUserAgent('iPhone')) &&
+ !goog.labs.userAgent.browser.matchSafari_() &&
+ !goog.labs.userAgent.browser.matchChrome_() &&
+ !goog.labs.userAgent.browser.matchCoast_() &&
+ goog.labs.userAgent.util.matchUserAgent('AppleWebKit');
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is Chrome.
+ * @private
+ */
+goog.labs.userAgent.browser.matchChrome_ = function() {
+ return (goog.labs.userAgent.util.matchUserAgent('Chrome') ||
+ goog.labs.userAgent.util.matchUserAgent('CriOS')) &&
+ !goog.labs.userAgent.browser.matchOpera_() &&
+ !goog.labs.userAgent.browser.matchEdge_();
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is the Android browser.
+ * @private
+ */
+goog.labs.userAgent.browser.matchAndroidBrowser_ = function() {
+ // Android can appear in the user agent string for Chrome on Android.
+ // This is not the Android standalone browser if it does.
+ return goog.labs.userAgent.util.matchUserAgent('Android') &&
+ !(goog.labs.userAgent.browser.isChrome() ||
+ goog.labs.userAgent.browser.isFirefox() ||
+ goog.labs.userAgent.browser.isOpera() ||
+ goog.labs.userAgent.browser.isSilk());
+};
+
+
+/**
+ * @return {boolean} Whether the user's browser is Opera.
+ */
+goog.labs.userAgent.browser.isOpera = goog.labs.userAgent.browser.matchOpera_;
+
+
+/**
+ * @return {boolean} Whether the user's browser is IE.
+ */
+goog.labs.userAgent.browser.isIE = goog.labs.userAgent.browser.matchIE_;
+
+
+/**
+ * @return {boolean} Whether the user's browser is Edge.
+ */
+goog.labs.userAgent.browser.isEdge = goog.labs.userAgent.browser.matchEdge_;
+
+
+/**
+ * @return {boolean} Whether the user's browser is Firefox.
+ */
+goog.labs.userAgent.browser.isFirefox =
+ goog.labs.userAgent.browser.matchFirefox_;
+
+
+/**
+ * @return {boolean} Whether the user's browser is Safari.
+ */
+goog.labs.userAgent.browser.isSafari = goog.labs.userAgent.browser.matchSafari_;
+
+
+/**
+ * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based
+ * iOS browser).
+ */
+goog.labs.userAgent.browser.isCoast = goog.labs.userAgent.browser.matchCoast_;
+
+
+/**
+ * @return {boolean} Whether the user's browser is iOS Webview.
+ */
+goog.labs.userAgent.browser.isIosWebview =
+ goog.labs.userAgent.browser.matchIosWebview_;
+
+
+/**
+ * @return {boolean} Whether the user's browser is Chrome.
+ */
+goog.labs.userAgent.browser.isChrome = goog.labs.userAgent.browser.matchChrome_;
+
+
+/**
+ * @return {boolean} Whether the user's browser is the Android browser.
+ */
+goog.labs.userAgent.browser.isAndroidBrowser =
+ goog.labs.userAgent.browser.matchAndroidBrowser_;
+
+
+/**
+ * For more information, see:
+ * http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
+ * @return {boolean} Whether the user's browser is Silk.
+ */
+goog.labs.userAgent.browser.isSilk = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Silk');
+};
+
+
+/**
+ * @return {string} The browser version or empty string if version cannot be
+ * determined. Note that for Internet Explorer, this returns the version of
+ * the browser, not the version of the rendering engine. (IE 8 in
+ * compatibility mode will return 8.0 rather than 7.0. To determine the
+ * rendering engine version, look at document.documentMode instead. See
+ * http://msdn.microsoft.com/en-us/library/cc196988(v=vs.85).aspx for more
+ * details.)
+ */
+goog.labs.userAgent.browser.getVersion = function() {
+ var userAgentString = goog.labs.userAgent.util.getUserAgent();
+ // Special case IE since IE's version is inside the parenthesis and
+ // without the '/'.
+ if (goog.labs.userAgent.browser.isIE()) {
+ return goog.labs.userAgent.browser.getIEVersion_(userAgentString);
+ }
+
+ var versionTuples =
+ goog.labs.userAgent.util.extractVersionTuples(userAgentString);
+
+ // Construct a map for easy lookup.
+ var versionMap = {};
+ goog.array.forEach(versionTuples, function(tuple) {
+ // Note that the tuple is of length three, but we only care about the
+ // first two.
+ var key = tuple[0];
+ var value = tuple[1];
+ versionMap[key] = value;
+ });
+
+ var versionMapHasKey = goog.partial(goog.object.containsKey, versionMap);
+
+ // Gives the value with the first key it finds, otherwise empty string.
+ function lookUpValueWithKeys(keys) {
+ var key = goog.array.find(keys, versionMapHasKey);
+ return versionMap[key] || '';
+ }
+
+ // Check Opera before Chrome since Opera 15+ has "Chrome" in the string.
+ // See
+ // http://my.opera.com/ODIN/blog/2013/07/15/opera-user-agent-strings-opera-15-and-beyond
+ if (goog.labs.userAgent.browser.isOpera()) {
+ // Opera 10 has Version/10.0 but Opera/9.8, so look for "Version" first.
+ // Opera uses 'OPR' for more recent UAs.
+ return lookUpValueWithKeys(['Version', 'Opera', 'OPR']);
+ }
+
+ // Check Edge before Chrome since it has Chrome in the string.
+ if (goog.labs.userAgent.browser.isEdge()) {
+ return lookUpValueWithKeys(['Edge']);
+ }
+
+ if (goog.labs.userAgent.browser.isChrome()) {
+ return lookUpValueWithKeys(['Chrome', 'CriOS']);
+ }
+
+ // Usually products browser versions are in the third tuple after "Mozilla"
+ // and the engine.
+ var tuple = versionTuples[2];
+ return tuple && tuple[1] || '';
+};
+
+
+/**
+ * @param {string|number} version The version to check.
+ * @return {boolean} Whether the browser version is higher or the same as the
+ * given version.
+ */
+goog.labs.userAgent.browser.isVersionOrHigher = function(version) {
+ return goog.string.compareVersions(
+ goog.labs.userAgent.browser.getVersion(), version) >= 0;
+};
+
+
+/**
+ * Determines IE version. More information:
+ * http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx#uaString
+ * http://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
+ * http://blogs.msdn.com/b/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx
+ * http://blogs.msdn.com/b/ie/archive/2009/01/09/the-internet-explorer-8-user-agent-string-updated-edition.aspx
+ *
+ * @param {string} userAgent the User-Agent.
+ * @return {string}
+ * @private
+ */
+goog.labs.userAgent.browser.getIEVersion_ = function(userAgent) {
+ // IE11 may identify itself as MSIE 9.0 or MSIE 10.0 due to an IE 11 upgrade
+ // bug. Example UA:
+ // Mozilla/5.0 (MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)
+ // like Gecko.
+ // See http://www.whatismybrowser.com/developers/unknown-user-agent-fragments.
+ var rv = /rv: *([\d\.]*)/.exec(userAgent);
+ if (rv && rv[1]) {
+ return rv[1];
+ }
+
+ var version = '';
+ var msie = /MSIE +([\d\.]+)/.exec(userAgent);
+ if (msie && msie[1]) {
+ // IE in compatibility mode usually identifies itself as MSIE 7.0; in this
+ // case, use the Trident version to determine the version of IE. For more
+ // details, see the links above.
+ var tridentVersion = /Trident\/(\d.\d)/.exec(userAgent);
+ if (msie[1] == '7.0') {
+ if (tridentVersion && tridentVersion[1]) {
+ switch (tridentVersion[1]) {
+ case '4.0':
+ version = '8.0';
+ break;
+ case '5.0':
+ version = '9.0';
+ break;
+ case '6.0':
+ version = '10.0';
+ break;
+ case '7.0':
+ version = '11.0';
+ break;
+ }
+ } else {
+ version = '7.0';
+ }
+ } else {
+ version = msie[1];
+ }
+ }
+ return version;
+};
+
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Closure user agent detection.
+ * @see http://en.wikipedia.org/wiki/User_agent
+ * For more information on browser brand, platform, or device see the other
+ * sub-namespaces in goog.labs.userAgent (browser, platform, and device).
+ *
+ */
+
+goog.provide('goog.labs.userAgent.engine');
+
+goog.require('goog.array');
+goog.require('goog.labs.userAgent.util');
+goog.require('goog.string');
+
+
+/**
+ * @return {boolean} Whether the rendering engine is Presto.
+ */
+goog.labs.userAgent.engine.isPresto = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Presto');
+};
+
+
+/**
+ * @return {boolean} Whether the rendering engine is Trident.
+ */
+goog.labs.userAgent.engine.isTrident = function() {
+ // IE only started including the Trident token in IE8.
+ return goog.labs.userAgent.util.matchUserAgent('Trident') ||
+ goog.labs.userAgent.util.matchUserAgent('MSIE');
+};
+
+
+/**
+ * @return {boolean} Whether the rendering engine is Edge.
+ */
+goog.labs.userAgent.engine.isEdge = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Edge');
+};
+
+
+/**
+ * @return {boolean} Whether the rendering engine is WebKit.
+ */
+goog.labs.userAgent.engine.isWebKit = function() {
+ return goog.labs.userAgent.util.matchUserAgentIgnoreCase('WebKit') &&
+ !goog.labs.userAgent.engine.isEdge();
+};
+
+
+/**
+ * @return {boolean} Whether the rendering engine is Gecko.
+ */
+goog.labs.userAgent.engine.isGecko = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Gecko') &&
+ !goog.labs.userAgent.engine.isWebKit() &&
+ !goog.labs.userAgent.engine.isTrident() &&
+ !goog.labs.userAgent.engine.isEdge();
+};
+
+
+/**
+ * @return {string} The rendering engine's version or empty string if version
+ * can't be determined.
+ */
+goog.labs.userAgent.engine.getVersion = function() {
+ var userAgentString = goog.labs.userAgent.util.getUserAgent();
+ if (userAgentString) {
+ var tuples = goog.labs.userAgent.util.extractVersionTuples(userAgentString);
+
+ var engineTuple = goog.labs.userAgent.engine.getEngineTuple_(tuples);
+ if (engineTuple) {
+ // In Gecko, the version string is either in the browser info or the
+ // Firefox version. See Gecko user agent string reference:
+ // http://goo.gl/mULqa
+ if (engineTuple[0] == 'Gecko') {
+ return goog.labs.userAgent.engine.getVersionForKey_(tuples, 'Firefox');
+ }
+
+ return engineTuple[1];
+ }
+
+ // MSIE has only one version identifier, and the Trident version is
+ // specified in the parenthetical. IE Edge is covered in the engine tuple
+ // detection.
+ var browserTuple = tuples[0];
+ var info;
+ if (browserTuple && (info = browserTuple[2])) {
+ var match = /Trident\/([^\s;]+)/.exec(info);
+ if (match) {
+ return match[1];
+ }
+ }
+ }
+ return '';
+};
+
+
+/**
+ * @param {!Array<!Array<string>>} tuples Extracted version tuples.
+ * @return {!Array<string>|undefined} The engine tuple or undefined if not
+ * found.
+ * @private
+ */
+goog.labs.userAgent.engine.getEngineTuple_ = function(tuples) {
+ if (!goog.labs.userAgent.engine.isEdge()) {
+ return tuples[1];
+ }
+ for (var i = 0; i < tuples.length; i++) {
+ var tuple = tuples[i];
+ if (tuple[0] == 'Edge') {
+ return tuple;
+ }
+ }
+};
+
+
+/**
+ * @param {string|number} version The version to check.
+ * @return {boolean} Whether the rendering engine version is higher or the same
+ * as the given version.
+ */
+goog.labs.userAgent.engine.isVersionOrHigher = function(version) {
+ return goog.string.compareVersions(
+ goog.labs.userAgent.engine.getVersion(), version) >= 0;
+};
+
+
+/**
+ * @param {!Array<!Array<string>>} tuples Version tuples.
+ * @param {string} key The key to look for.
+ * @return {string} The version string of the given key, if present.
+ * Otherwise, the empty string.
+ * @private
+ */
+goog.labs.userAgent.engine.getVersionForKey_ = function(tuples, key) {
+ // TODO(nnaze): Move to util if useful elsewhere.
+
+ var pair = goog.array.find(tuples, function(pair) { return key == pair[0]; });
+
+ return pair && pair[1] || '';
+};
+
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Closure user agent platform detection.
+ * @see <a href="http://www.useragentstring.com/">User agent strings</a>
+ * For more information on browser brand, rendering engine, or device see the
+ * other sub-namespaces in goog.labs.userAgent (browser, engine, and device
+ * respectively).
+ *
+ */
+
+goog.provide('goog.labs.userAgent.platform');
+
+goog.require('goog.labs.userAgent.util');
+goog.require('goog.string');
+
+
+/**
+ * @return {boolean} Whether the platform is Android.
+ */
+goog.labs.userAgent.platform.isAndroid = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Android');
+};
+
+
+/**
+ * @return {boolean} Whether the platform is iPod.
+ */
+goog.labs.userAgent.platform.isIpod = function() {
+ return goog.labs.userAgent.util.matchUserAgent('iPod');
+};
+
+
+/**
+ * @return {boolean} Whether the platform is iPhone.
+ */
+goog.labs.userAgent.platform.isIphone = function() {
+ return goog.labs.userAgent.util.matchUserAgent('iPhone') &&
+ !goog.labs.userAgent.util.matchUserAgent('iPod') &&
+ !goog.labs.userAgent.util.matchUserAgent('iPad');
+};
+
+
+/**
+ * @return {boolean} Whether the platform is iPad.
+ */
+goog.labs.userAgent.platform.isIpad = function() {
+ return goog.labs.userAgent.util.matchUserAgent('iPad');
+};
+
+
+/**
+ * @return {boolean} Whether the platform is iOS.
+ */
+goog.labs.userAgent.platform.isIos = function() {
+ return goog.labs.userAgent.platform.isIphone() ||
+ goog.labs.userAgent.platform.isIpad() ||
+ goog.labs.userAgent.platform.isIpod();
+};
+
+
+/**
+ * @return {boolean} Whether the platform is Mac.
+ */
+goog.labs.userAgent.platform.isMacintosh = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Macintosh');
+};
+
+
+/**
+ * Note: ChromeOS is not considered to be Linux as it does not report itself
+ * as Linux in the user agent string.
+ * @return {boolean} Whether the platform is Linux.
+ */
+goog.labs.userAgent.platform.isLinux = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Linux');
+};
+
+
+/**
+ * @return {boolean} Whether the platform is Windows.
+ */
+goog.labs.userAgent.platform.isWindows = function() {
+ return goog.labs.userAgent.util.matchUserAgent('Windows');
+};
+
+
+/**
+ * @return {boolean} Whether the platform is ChromeOS.
+ */
+goog.labs.userAgent.platform.isChromeOS = function() {
+ return goog.labs.userAgent.util.matchUserAgent('CrOS');
+};
+
+
+/**
+ * The version of the platform. We only determine the version for Windows,
+ * Mac, and Chrome OS. It doesn't make much sense on Linux. For Windows, we only
+ * look at the NT version. Non-NT-based versions (e.g. 95, 98, etc.) are given
+ * version 0.0.
+ *
+ * @return {string} The platform version or empty string if version cannot be
+ * determined.
+ */
+goog.labs.userAgent.platform.getVersion = function() {
+ var userAgentString = goog.labs.userAgent.util.getUserAgent();
+ var version = '', re;
+ if (goog.labs.userAgent.platform.isWindows()) {
+ re = /Windows (?:NT|Phone) ([0-9.]+)/;
+ var match = re.exec(userAgentString);
+ if (match) {
+ version = match[1];
+ } else {
+ version = '0.0';
+ }
+ } else if (goog.labs.userAgent.platform.isIos()) {
+ re = /(?:iPhone|iPod|iPad|CPU)\s+OS\s+(\S+)/;
+ var match = re.exec(userAgentString);
+ // Report the version as x.y.z and not x_y_z
+ version = match && match[1].replace(/_/g, '.');
+ } else if (goog.labs.userAgent.platform.isMacintosh()) {
+ re = /Mac OS X ([0-9_.]+)/;
+ var match = re.exec(userAgentString);
+ // Note: some old versions of Camino do not report an OSX version.
+ // Default to 10.
+ version = match ? match[1].replace(/_/g, '.') : '10';
+ } else if (goog.labs.userAgent.platform.isAndroid()) {
+ re = /Android\s+([^\);]+)(\)|;)/;
+ var match = re.exec(userAgentString);
+ version = match && match[1];
+ } else if (goog.labs.userAgent.platform.isChromeOS()) {
+ re = /(?:CrOS\s+(?:i686|x86_64)\s+([0-9.]+))/;
+ var match = re.exec(userAgentString);
+ version = match && match[1];
+ }
+ return version || '';
+};
+
+
+/**
+ * @param {string|number} version The version to check.
+ * @return {boolean} Whether the browser version is higher or the same as the
+ * given version.
+ */
+goog.labs.userAgent.platform.isVersionOrHigher = function(version) {
+ return goog.string.compareVersions(
+ goog.labs.userAgent.platform.getVersion(), version) >= 0;
+};
+
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Rendering engine detection.
+ * @see <a href="http://www.useragentstring.com/">User agent strings</a>
+ * For information on the browser brand (such as Safari versus Chrome), see
+ * goog.userAgent.product.
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/useragent.html
+ */
+
+goog.provide('goog.userAgent');
+
+goog.require('goog.labs.userAgent.browser');
+goog.require('goog.labs.userAgent.engine');
+goog.require('goog.labs.userAgent.platform');
+goog.require('goog.labs.userAgent.util');
+goog.require('goog.string');
+
+
+/**
+ * @define {boolean} Whether we know at compile-time that the browser is IE.
+ */
+goog.define('goog.userAgent.ASSUME_IE', false);
+
+
+/**
+ * @define {boolean} Whether we know at compile-time that the browser is EDGE.
+ */
+goog.define('goog.userAgent.ASSUME_EDGE', false);
+
+
+/**
+ * @define {boolean} Whether we know at compile-time that the browser is GECKO.
+ */
+goog.define('goog.userAgent.ASSUME_GECKO', false);
+
+
+/**
+ * @define {boolean} Whether we know at compile-time that the browser is WEBKIT.
+ */
+goog.define('goog.userAgent.ASSUME_WEBKIT', false);
+
+
+/**
+ * @define {boolean} Whether we know at compile-time that the browser is a
+ * mobile device running WebKit e.g. iPhone or Android.
+ */
+goog.define('goog.userAgent.ASSUME_MOBILE_WEBKIT', false);
+
+
+/**
+ * @define {boolean} Whether we know at compile-time that the browser is OPERA.
+ */
+goog.define('goog.userAgent.ASSUME_OPERA', false);
+
+
+/**
+ * @define {boolean} Whether the
+ * {@code goog.userAgent.isVersionOrHigher}
+ * function will return true for any version.
+ */
+goog.define('goog.userAgent.ASSUME_ANY_VERSION', false);
+
+
+/**
+ * Whether we know the browser engine at compile-time.
+ * @type {boolean}
+ * @private
+ */
+goog.userAgent.BROWSER_KNOWN_ = goog.userAgent.ASSUME_IE ||
+ goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_GECKO ||
+ goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.ASSUME_WEBKIT ||
+ goog.userAgent.ASSUME_OPERA;
+
+
+/**
+ * Returns the userAgent string for the current browser.
+ *
+ * @return {string} The userAgent string.
+ */
+goog.userAgent.getUserAgentString = function() {
+ return goog.labs.userAgent.util.getUserAgent();
+};
+
+
+/**
+ * TODO(nnaze): Change type to "Navigator" and update compilation targets.
+ * @return {Object} The native navigator object.
+ */
+goog.userAgent.getNavigator = function() {
+ // Need a local navigator reference instead of using the global one,
+ // to avoid the rare case where they reference different objects.
+ // (in a WorkerPool, for example).
+ return goog.global['navigator'] || null;
+};
+
+
+/**
+ * Whether the user agent is Opera.
+ * @type {boolean}
+ */
+goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ?
+ goog.userAgent.ASSUME_OPERA :
+ goog.labs.userAgent.browser.isOpera();
+
+
+/**
+ * Whether the user agent is Internet Explorer.
+ * @type {boolean}
+ */
+goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ?
+ goog.userAgent.ASSUME_IE :
+ goog.labs.userAgent.browser.isIE();
+
+
+/**
+ * Whether the user agent is Microsoft Edge.
+ * @type {boolean}
+ */
+goog.userAgent.EDGE = goog.userAgent.BROWSER_KNOWN_ ?
+ goog.userAgent.ASSUME_EDGE :
+ goog.labs.userAgent.engine.isEdge();
+
+
+/**
+ * Whether the user agent is MS Internet Explorer or MS Edge.
+ * @type {boolean}
+ */
+goog.userAgent.EDGE_OR_IE = goog.userAgent.EDGE || goog.userAgent.IE;
+
+
+/**
+ * Whether the user agent is Gecko. Gecko is the rendering engine used by
+ * Mozilla, Firefox, and others.
+ * @type {boolean}
+ */
+goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ?
+ goog.userAgent.ASSUME_GECKO :
+ goog.labs.userAgent.engine.isGecko();
+
+
+/**
+ * Whether the user agent is WebKit. WebKit is the rendering engine that
+ * Safari, Android and others use.
+ * @type {boolean}
+ */
+goog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ?
+ goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT :
+ goog.labs.userAgent.engine.isWebKit();
+
+
+/**
+ * Whether the user agent is running on a mobile device.
+ *
+ * This is a separate function so that the logic can be tested.
+ *
+ * TODO(nnaze): Investigate swapping in goog.labs.userAgent.device.isMobile().
+ *
+ * @return {boolean} Whether the user agent is running on a mobile device.
+ * @private
+ */
+goog.userAgent.isMobile_ = function() {
+ return goog.userAgent.WEBKIT &&
+ goog.labs.userAgent.util.matchUserAgent('Mobile');
+};
+
+
+/**
+ * Whether the user agent is running on a mobile device.
+ *
+ * TODO(nnaze): Consider deprecating MOBILE when labs.userAgent
+ * is promoted as the gecko/webkit logic is likely inaccurate.
+ *
+ * @type {boolean}
+ */
+goog.userAgent.MOBILE =
+ goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.isMobile_();
+
+
+/**
+ * Used while transitioning code to use WEBKIT instead.
+ * @type {boolean}
+ * @deprecated Use {@link goog.userAgent.product.SAFARI} instead.
+ * TODO(nicksantos): Delete this from goog.userAgent.
+ */
+goog.userAgent.SAFARI = goog.userAgent.WEBKIT;
+
+
+/**
+ * @return {string} the platform (operating system) the user agent is running
+ * on. Default to empty string because navigator.platform may not be defined
+ * (on Rhino, for example).
+ * @private
+ */
+goog.userAgent.determinePlatform_ = function() {
+ var navigator = goog.userAgent.getNavigator();
+ return navigator && navigator.platform || '';
+};
+
+
+/**
+ * The platform (operating system) the user agent is running on. Default to
+ * empty string because navigator.platform may not be defined (on Rhino, for
+ * example).
+ * @type {string}
+ */
+goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();
+
+
+/**
+ * @define {boolean} Whether the user agent is running on a Macintosh operating
+ * system.
+ */
+goog.define('goog.userAgent.ASSUME_MAC', false);
+
+
+/**
+ * @define {boolean} Whether the user agent is running on a Windows operating
+ * system.
+ */
+goog.define('goog.userAgent.ASSUME_WINDOWS', false);
+
+
+/**
+ * @define {boolean} Whether the user agent is running on a Linux operating
+ * system.
+ */
+goog.define('goog.userAgent.ASSUME_LINUX', false);
+
+
+/**
+ * @define {boolean} Whether the user agent is running on a X11 windowing
+ * system.
+ */
+goog.define('goog.userAgent.ASSUME_X11', false);
+
+
+/**
+ * @define {boolean} Whether the user agent is running on Android.
+ */
+goog.define('goog.userAgent.ASSUME_ANDROID', false);
+
+
+/**
+ * @define {boolean} Whether the user agent is running on an iPhone.
+ */
+goog.define('goog.userAgent.ASSUME_IPHONE', false);
+
+
+/**
+ * @define {boolean} Whether the user agent is running on an iPad.
+ */
+goog.define('goog.userAgent.ASSUME_IPAD', false);
+
+
+/**
+ * @type {boolean}
+ * @private
+ */
+goog.userAgent.PLATFORM_KNOWN_ = goog.userAgent.ASSUME_MAC ||
+ goog.userAgent.ASSUME_WINDOWS || goog.userAgent.ASSUME_LINUX ||
+ goog.userAgent.ASSUME_X11 || goog.userAgent.ASSUME_ANDROID ||
+ goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD;
+
+
+/**
+ * Whether the user agent is running on a Macintosh operating system.
+ * @type {boolean}
+ */
+goog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ?
+ goog.userAgent.ASSUME_MAC :
+ goog.labs.userAgent.platform.isMacintosh();
+
+
+/**
+ * Whether the user agent is running on a Windows operating system.
+ * @type {boolean}
+ */
+goog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ?
+ goog.userAgent.ASSUME_WINDOWS :
+ goog.labs.userAgent.platform.isWindows();
+
+
+/**
+ * Whether the user agent is Linux per the legacy behavior of
+ * goog.userAgent.LINUX, which considered ChromeOS to also be
+ * Linux.
+ * @return {boolean}
+ * @private
+ */
+goog.userAgent.isLegacyLinux_ = function() {
+ return goog.labs.userAgent.platform.isLinux() ||
+ goog.labs.userAgent.platform.isChromeOS();
+};
+
+
+/**
+ * Whether the user agent is running on a Linux operating system.
+ *
+ * Note that goog.userAgent.LINUX considers ChromeOS to be Linux,
+ * while goog.labs.userAgent.platform considers ChromeOS and
+ * Linux to be different OSes.
+ *
+ * @type {boolean}
+ */
+goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ?
+ goog.userAgent.ASSUME_LINUX :
+ goog.userAgent.isLegacyLinux_();
+
+
+/**
+ * @return {boolean} Whether the user agent is an X11 windowing system.
+ * @private
+ */
+goog.userAgent.isX11_ = function() {
+ var navigator = goog.userAgent.getNavigator();
+ return !!navigator &&
+ goog.string.contains(navigator['appVersion'] || '', 'X11');
+};
+
+
+/**
+ * Whether the user agent is running on a X11 windowing system.
+ * @type {boolean}
+ */
+goog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ?
+ goog.userAgent.ASSUME_X11 :
+ goog.userAgent.isX11_();
+
+
+/**
+ * Whether the user agent is running on Android.
+ * @type {boolean}
+ */
+goog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_ ?
+ goog.userAgent.ASSUME_ANDROID :
+ goog.labs.userAgent.platform.isAndroid();
+
+
+/**
+ * Whether the user agent is running on an iPhone.
+ * @type {boolean}
+ */
+goog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_ ?
+ goog.userAgent.ASSUME_IPHONE :
+ goog.labs.userAgent.platform.isIphone();
+
+
+/**
+ * Whether the user agent is running on an iPad.
+ * @type {boolean}
+ */
+goog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_ ?
+ goog.userAgent.ASSUME_IPAD :
+ goog.labs.userAgent.platform.isIpad();
+
+
+/**
+ * @return {string} The string that describes the version number of the user
+ * agent.
+ * @private
+ */
+goog.userAgent.determineVersion_ = function() {
+ // All browsers have different ways to detect the version and they all have
+ // different naming schemes.
+ // version is a string rather than a number because it may contain 'b', 'a',
+ // and so on.
+ var version = '';
+ var arr = goog.userAgent.getVersionRegexResult_();
+ if (arr) {
+ version = arr ? arr[1] : '';
+ }
+
+ if (goog.userAgent.IE) {
+ // IE9 can be in document mode 9 but be reporting an inconsistent user agent
+ // version. If it is identifying as a version lower than 9 we take the
+ // documentMode as the version instead. IE8 has similar behavior.
+ // It is recommended to set the X-UA-Compatible header to ensure that IE9
+ // uses documentMode 9.
+ var docMode = goog.userAgent.getDocumentMode_();
+ if (docMode != null && docMode > parseFloat(version)) {
+ return String(docMode);
+ }
+ }
+
+ return version;
+};
+
+
+/**
+ * @return {?Array|undefined} The version regex matches from parsing the user
+ * agent string. These regex statements must be executed inline so they can
+ * be compiled out by the closure compiler with the rest of the useragent
+ * detection logic when ASSUME_* is specified.
+ * @private
+ */
+goog.userAgent.getVersionRegexResult_ = function() {
+ var userAgent = goog.userAgent.getUserAgentString();
+ if (goog.userAgent.GECKO) {
+ return /rv\:([^\);]+)(\)|;)/.exec(userAgent);
+ }
+ if (goog.userAgent.EDGE) {
+ return /Edge\/([\d\.]+)/.exec(userAgent);
+ }
+ if (goog.userAgent.IE) {
+ return /\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(userAgent);
+ }
+ if (goog.userAgent.WEBKIT) {
+ // WebKit/125.4
+ return /WebKit\/(\S+)/.exec(userAgent);
+ }
+ if (goog.userAgent.OPERA) {
+ // If none of the above browsers were detected but the browser is Opera, the
+ // only string that is of interest is 'Version/<number>'.
+ return /(?:Version)[ \/]?(\S+)/.exec(userAgent);
+ }
+ return undefined;
+};
+
+
+/**
+ * @return {number|undefined} Returns the document mode (for testing).
+ * @private
+ */
+goog.userAgent.getDocumentMode_ = function() {
+ // NOTE(user): goog.userAgent may be used in context where there is no DOM.
+ var doc = goog.global['document'];
+ return doc ? doc['documentMode'] : undefined;
+};
+
+
+/**
+ * The version of the user agent. This is a string because it might contain
+ * 'b' (as in beta) as well as multiple dots.
+ * @type {string}
+ */
+goog.userAgent.VERSION = goog.userAgent.determineVersion_();
+
+
+/**
+ * Compares two version numbers.
+ *
+ * @param {string} v1 Version of first item.
+ * @param {string} v2 Version of second item.
+ *
+ * @return {number} 1 if first argument is higher
+ * 0 if arguments are equal
+ * -1 if second argument is higher.
+ * @deprecated Use goog.string.compareVersions.
+ */
+goog.userAgent.compare = function(v1, v2) {
+ return goog.string.compareVersions(v1, v2);
+};
+
+
+/**
+ * Cache for {@link goog.userAgent.isVersionOrHigher}.
+ * Calls to compareVersions are surprisingly expensive and, as a browser's
+ * version number is unlikely to change during a session, we cache the results.
+ * @const
+ * @private
+ */
+goog.userAgent.isVersionOrHigherCache_ = {};
+
+
+/**
+ * Whether the user agent version is higher or the same as the given version.
+ * NOTE: When checking the version numbers for Firefox and Safari, be sure to
+ * use the engine's version, not the browser's version number. For example,
+ * Firefox 3.0 corresponds to Gecko 1.9 and Safari 3.0 to Webkit 522.11.
+ * Opera and Internet Explorer versions match the product release number.<br>
+ * @see <a href="http://en.wikipedia.org/wiki/Safari_version_history">
+ * Webkit</a>
+ * @see <a href="http://en.wikipedia.org/wiki/Gecko_engine">Gecko</a>
+ *
+ * @param {string|number} version The version to check.
+ * @return {boolean} Whether the user agent version is higher or the same as
+ * the given version.
+ */
+goog.userAgent.isVersionOrHigher = function(version) {
+ return goog.userAgent.ASSUME_ANY_VERSION ||
+ goog.userAgent.isVersionOrHigherCache_[version] ||
+ (goog.userAgent.isVersionOrHigherCache_[version] =
+ goog.string.compareVersions(goog.userAgent.VERSION, version) >= 0);
+};
+
+
+/**
+ * Deprecated alias to {@code goog.userAgent.isVersionOrHigher}.
+ * @param {string|number} version The version to check.
+ * @return {boolean} Whether the user agent version is higher or the same as
+ * the given version.
+ * @deprecated Use goog.userAgent.isVersionOrHigher().
+ */
+goog.userAgent.isVersion = goog.userAgent.isVersionOrHigher;
+
+
+/**
+ * Whether the IE effective document mode is higher or the same as the given
+ * document mode version.
+ * NOTE: Only for IE, return false for another browser.
+ *
+ * @param {number} documentMode The document mode version to check.
+ * @return {boolean} Whether the IE effective document mode is higher or the
+ * same as the given version.
+ */
+goog.userAgent.isDocumentModeOrHigher = function(documentMode) {
+ return Number(goog.userAgent.DOCUMENT_MODE) >= documentMode;
+};
+
+
+/**
+ * Deprecated alias to {@code goog.userAgent.isDocumentModeOrHigher}.
+ * @param {number} version The version to check.
+ * @return {boolean} Whether the IE effective document mode is higher or the
+ * same as the given version.
+ * @deprecated Use goog.userAgent.isDocumentModeOrHigher().
+ */
+goog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher;
+
+
+/**
+ * For IE version < 7, documentMode is undefined, so attempt to use the
+ * CSS1Compat property to see if we are in standards mode. If we are in
+ * standards mode, treat the browser version as the document mode. Otherwise,
+ * IE is emulating version 5.
+ * @type {number|undefined}
+ * @const
+ */
+goog.userAgent.DOCUMENT_MODE = (function() {
+ var doc = goog.global['document'];
+ var mode = goog.userAgent.getDocumentMode_();
+ if (!doc || !goog.userAgent.IE) {
+ return undefined;
+ }
+ return mode || (doc['compatMode'] == 'CSS1Compat' ?
+ parseInt(goog.userAgent.VERSION, 10) :
+ 5);
+})();
+
// Copyright 2010 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -25487,8 +22651,8 @@ goog.dom.BrowserFeature = {
* Whether attributes 'name' and 'type' can be added to an element after it's
* created. False in Internet Explorer prior to version 9.
*/
- CAN_ADD_NAME_OR_TYPE_ATTRIBUTES: !goog.userAgent.IE ||
- goog.userAgent.isDocumentModeOrHigher(9),
+ CAN_ADD_NAME_OR_TYPE_ATTRIBUTES:
+ !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9),
/**
* Whether we can use element.children to access an element's Element
@@ -25503,15 +22667,15 @@ goog.dom.BrowserFeature = {
* Opera, Safari 3, and Internet Explorer 9 all support innerText but they
* include text nodes in script and style tags. Not document-mode-dependent.
*/
- CAN_USE_INNER_TEXT: (
- goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')),
+ CAN_USE_INNER_TEXT:
+ (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')),
/**
* MSIE, Opera, and Safari>=4 support element.parentElement to access an
* element's parent if it is an Element.
*/
- CAN_USE_PARENT_ELEMENT_PROPERTY: goog.userAgent.IE || goog.userAgent.OPERA ||
- goog.userAgent.WEBKIT,
+ CAN_USE_PARENT_ELEMENT_PROPERTY:
+ goog.userAgent.IE || goog.userAgent.OPERA || goog.userAgent.WEBKIT,
/**
* Whether NoScope elements need a scoped element written before them in
@@ -25523,7 +22687,8 @@ goog.dom.BrowserFeature = {
/**
* Whether we use legacy IE range API.
*/
- LEGACY_IE_RANGES: goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)
+ LEGACY_IE_RANGES:
+ goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)
};
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
@@ -25877,8 +23042,8 @@ goog.string.Const.prototype.getTypedStringValue = function() {
*/
goog.string.Const.prototype.toString = function() {
return 'Const{' +
- this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ +
- '}';
+ this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ +
+ '}';
};
@@ -25900,11 +23065,11 @@ goog.string.Const.unwrap = function(stringConst) {
stringConst.constructor === goog.string.Const &&
stringConst.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ ===
goog.string.Const.TYPE_MARKER_) {
- return stringConst.
- stringConstValueWithSecurityContract__googStringSecurityPrivate_;
+ return stringConst
+ .stringConstValueWithSecurityContract__googStringSecurityPrivate_;
} else {
- goog.asserts.fail('expected object of type Const, got \'' +
- stringConst + '\'');
+ goog.asserts.fail(
+ 'expected object of type Const, got \'' + stringConst + '\'');
return 'type_error:Const';
}
};
@@ -26138,11 +23303,13 @@ goog.html.SafeStyle.fromConstant = function(style) {
return goog.html.SafeStyle.EMPTY;
}
goog.html.SafeStyle.checkStyle_(styleString);
- goog.asserts.assert(goog.string.endsWith(styleString, ';'),
+ goog.asserts.assert(
+ goog.string.endsWith(styleString, ';'),
'Last character of style string is not \';\': ' + styleString);
- goog.asserts.assert(goog.string.contains(styleString, ':'),
+ goog.asserts.assert(
+ goog.string.contains(styleString, ':'),
'Style string must contain at least one \':\', to ' +
- 'specify a "name: value" pair: ' + styleString);
+ 'specify a "name: value" pair: ' + styleString);
return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
styleString);
};
@@ -26154,8 +23321,8 @@ goog.html.SafeStyle.fromConstant = function(style) {
* @private
*/
goog.html.SafeStyle.checkStyle_ = function(style) {
- goog.asserts.assert(!/[<>]/.test(style),
- 'Forbidden characters in style string: ' + style);
+ goog.asserts.assert(
+ !/[<>]/.test(style), 'Forbidden characters in style string: ' + style);
};
@@ -26196,8 +23363,8 @@ if (goog.DEBUG) {
* @override
*/
goog.html.SafeStyle.prototype.toString = function() {
- return 'SafeStyle{' +
- this.privateDoNotAccessOrElseSafeStyleWrappedValue_ + '}';
+ return 'SafeStyle{' + this.privateDoNotAccessOrElseSafeStyleWrappedValue_ +
+ '}';
};
}
@@ -26229,8 +23396,8 @@ goog.html.SafeStyle.unwrap = function(safeStyle) {
goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
return safeStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;
} else {
- goog.asserts.fail(
- 'expected object of type SafeStyle, got \'' + safeStyle + '\'');
+ goog.asserts.fail('expected object of type SafeStyle, got \'' +
+ safeStyle + '\' of type ' + goog.typeOf(safeStyle));
return 'type_error:SafeStyle';
}
};
@@ -26243,8 +23410,8 @@ goog.html.SafeStyle.unwrap = function(safeStyle) {
* @return {!goog.html.SafeStyle} The initialized SafeStyle object.
* @package
*/
-goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse =
- function(style) {
+goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse = function(
+ style) {
return new goog.html.SafeStyle().initSecurityPrivateDoNotAccessOrElse_(style);
};
@@ -26318,7 +23485,8 @@ goog.html.SafeStyle.create = function(map) {
goog.asserts.assert(!/[{;}]/.test(value), 'Value does not allow [{;}].');
} else if (!goog.html.SafeStyle.VALUE_RE_.test(value)) {
goog.asserts.fail(
- 'String value allows only [-,."\'%_!# a-zA-Z0-9], got: ' + value);
+ 'String value allows only [-,."\'%_!# a-zA-Z0-9], rgb() and ' +
+ 'rgba(), got: ' + value);
value = goog.html.SafeStyle.INNOCUOUS_STRING;
} else if (!goog.html.SafeStyle.hasBalancedQuotes_(value)) {
goog.asserts.fail('String value requires balanced quotes, got: ' + value);
@@ -26370,10 +23538,14 @@ goog.html.SafeStyle.hasBalancedQuotes_ = function(value) {
* ',' allows multiple values to be assigned to the same property
* (e.g. background-attachment or font-family) and hence could allow
* multiple values to get injected, but that should pose no risk of XSS.
+ *
+ * The rgb() and rgba() expression checks only for XSS safety, not for CSS
+ * validity.
* @const {!RegExp}
* @private
*/
-goog.html.SafeStyle.VALUE_RE_ = /^[-,."'%_!# a-zA-Z0-9]+$/;
+goog.html.SafeStyle.VALUE_RE_ =
+ /^([-,."'%_!# a-zA-Z0-9]+|(?:rgb|hsl)a?\([0-9.%, ]+\))$/;
/**
@@ -26468,7 +23640,8 @@ goog.require('goog.string.TypedString');
* style element and {@code evil} would execute. Also note that within an HTML
* style (raw text) element, HTML character references, such as
* {@code &amp;lt;}, are not allowed. See
- * http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements
+ *
+ http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements
* (similar considerations apply to the style element).
*
* @see goog.html.SafeStyleSheet#fromConstant
@@ -26492,7 +23665,7 @@ goog.html.SafeStyleSheet = function() {
* @const
* @private
*/
- this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
+ this.SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
};
@@ -26558,10 +23731,11 @@ goog.html.SafeStyleSheet.fromConstant = function(styleSheet) {
}
// > is a valid character in CSS selectors and there's no strict need to
// block it if we already block <.
- goog.asserts.assert(!goog.string.contains(styleSheetString, '<'),
+ goog.asserts.assert(
+ !goog.string.contains(styleSheetString, '<'),
"Forbidden '<' character in style sheet string: " + styleSheetString);
- return goog.html.SafeStyleSheet.
- createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheetString);
+ return goog.html.SafeStyleSheet
+ .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheetString);
};
@@ -26631,13 +23805,13 @@ goog.html.SafeStyleSheet.unwrap = function(safeStyleSheet) {
// to stand out in code reviews.
if (safeStyleSheet instanceof goog.html.SafeStyleSheet &&
safeStyleSheet.constructor === goog.html.SafeStyleSheet &&
- safeStyleSheet.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
+ safeStyleSheet
+ .SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
return safeStyleSheet.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_;
} else {
- goog.asserts.fail(
- "expected object of type SafeStyleSheet, got '" + safeStyleSheet +
- "'");
+ goog.asserts.fail('expected object of type SafeStyleSheet, got \'' +
+ safeStyleSheet + '\' of type ' + goog.typeOf(safeStyleSheet));
return 'type_error:SafeStyleSheet';
}
};
@@ -26678,8 +23852,8 @@ goog.html.SafeStyleSheet.prototype.initSecurityPrivateDoNotAccessOrElse_ =
* @const {!goog.html.SafeStyleSheet}
*/
goog.html.SafeStyleSheet.EMPTY =
- goog.html.SafeStyleSheet.
- createSafeStyleSheetSecurityPrivateDoNotAccessOrElse('');
+ goog.html.SafeStyleSheet
+ .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse('');
// Copyright 2015 The Closure Library Authors. All Rights Reserved.
//
@@ -26768,11 +23942,12 @@ goog.fs.url.findUrlObject_ = function() {
if (goog.isDef(goog.global.URL) &&
goog.isDef(goog.global.URL.createObjectURL)) {
return /** @type {goog.fs.url.UrlObject_} */ (goog.global.URL);
- // This is what Chrome does (as of 10.0.648.6 dev)
- } else if (goog.isDef(goog.global.webkitURL) &&
- goog.isDef(goog.global.webkitURL.createObjectURL)) {
+ // This is what Chrome does (as of 10.0.648.6 dev)
+ } else if (
+ goog.isDef(goog.global.webkitURL) &&
+ goog.isDef(goog.global.webkitURL.createObjectURL)) {
return /** @type {goog.fs.url.UrlObject_} */ (goog.global.webkitURL);
- // This is what the spec used to say to do
+ // This is what the spec used to say to do
} else if (goog.isDef(goog.global.createObjectURL)) {
return /** @type {goog.fs.url.UrlObject_} */ (goog.global);
} else {
@@ -26853,26 +24028,21 @@ goog.define('goog.i18n.bidi.FORCE_RTL', false);
* TODO(user): write a test that checks that this is a compile-time constant.
*/
goog.i18n.bidi.IS_RTL = goog.i18n.bidi.FORCE_RTL ||
- (
- (goog.LOCALE.substring(0, 2).toLowerCase() == 'ar' ||
- goog.LOCALE.substring(0, 2).toLowerCase() == 'fa' ||
- goog.LOCALE.substring(0, 2).toLowerCase() == 'he' ||
- goog.LOCALE.substring(0, 2).toLowerCase() == 'iw' ||
- goog.LOCALE.substring(0, 2).toLowerCase() == 'ps' ||
- goog.LOCALE.substring(0, 2).toLowerCase() == 'sd' ||
- goog.LOCALE.substring(0, 2).toLowerCase() == 'ug' ||
- goog.LOCALE.substring(0, 2).toLowerCase() == 'ur' ||
- goog.LOCALE.substring(0, 2).toLowerCase() == 'yi') &&
- (goog.LOCALE.length == 2 ||
- goog.LOCALE.substring(2, 3) == '-' ||
- goog.LOCALE.substring(2, 3) == '_')
- ) || (
- goog.LOCALE.length >= 3 &&
- goog.LOCALE.substring(0, 3).toLowerCase() == 'ckb' &&
- (goog.LOCALE.length == 3 ||
- goog.LOCALE.substring(3, 4) == '-' ||
- goog.LOCALE.substring(3, 4) == '_')
- );
+ ((goog.LOCALE.substring(0, 2).toLowerCase() == 'ar' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'fa' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'he' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'iw' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'ps' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'sd' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'ug' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'ur' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'yi') &&
+ (goog.LOCALE.length == 2 || goog.LOCALE.substring(2, 3) == '-' ||
+ goog.LOCALE.substring(2, 3) == '_')) ||
+ (goog.LOCALE.length >= 3 &&
+ goog.LOCALE.substring(0, 3).toLowerCase() == 'ckb' &&
+ (goog.LOCALE.length == 3 || goog.LOCALE.substring(3, 4) == '-' ||
+ goog.LOCALE.substring(3, 4) == '_'));
/**
@@ -26933,16 +24103,16 @@ goog.i18n.bidi.LEFT = 'left';
* 'left' if locale is RTL, 'right' if not.
* @type {string}
*/
-goog.i18n.bidi.I18N_RIGHT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.LEFT :
- goog.i18n.bidi.RIGHT;
+goog.i18n.bidi.I18N_RIGHT =
+ goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.LEFT : goog.i18n.bidi.RIGHT;
/**
* 'right' if locale is RTL, 'left' if not.
* @type {string}
*/
-goog.i18n.bidi.I18N_LEFT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.RIGHT :
- goog.i18n.bidi.LEFT;
+goog.i18n.bidi.I18N_LEFT =
+ goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT;
/**
@@ -26965,9 +24135,9 @@ goog.i18n.bidi.I18N_LEFT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.RIGHT :
goog.i18n.bidi.toDir = function(givenDir, opt_noNeutral) {
if (typeof givenDir == 'number') {
// This includes the non-null goog.i18n.bidi.Dir case.
- return givenDir > 0 ? goog.i18n.bidi.Dir.LTR :
- givenDir < 0 ? goog.i18n.bidi.Dir.RTL :
- opt_noNeutral ? null : goog.i18n.bidi.Dir.NEUTRAL;
+ return givenDir > 0 ? goog.i18n.bidi.Dir.LTR : givenDir < 0 ?
+ goog.i18n.bidi.Dir.RTL :
+ opt_noNeutral ? null : goog.i18n.bidi.Dir.NEUTRAL;
} else if (givenDir == null) {
return null;
} else {
@@ -27024,8 +24194,7 @@ goog.i18n.bidi.htmlSkipReg_ = /<[^>]*>|&[^;]+;/g;
* @private
*/
goog.i18n.bidi.stripHtmlIfNeeded_ = function(str, opt_isStripNeeded) {
- return opt_isStripNeeded ? str.replace(goog.i18n.bidi.htmlSkipReg_, '') :
- str;
+ return opt_isStripNeeded ? str.replace(goog.i18n.bidi.htmlSkipReg_, '') : str;
};
@@ -27053,8 +24222,8 @@ goog.i18n.bidi.ltrCharReg_ = new RegExp('[' + goog.i18n.bidi.ltrChars_ + ']');
* @return {boolean} Whether the string contains RTL characters.
*/
goog.i18n.bidi.hasAnyRtl = function(str, opt_isHtml) {
- return goog.i18n.bidi.rtlCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
- str, opt_isHtml));
+ return goog.i18n.bidi.rtlCharReg_.test(
+ goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
@@ -27075,8 +24244,8 @@ goog.i18n.bidi.hasRtlChar = goog.i18n.bidi.hasAnyRtl;
* @return {boolean} Whether the string contains LTR characters.
*/
goog.i18n.bidi.hasAnyLtr = function(str, opt_isHtml) {
- return goog.i18n.bidi.ltrCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
- str, opt_isHtml));
+ return goog.i18n.bidi.ltrCharReg_.test(
+ goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
@@ -27157,8 +24326,8 @@ goog.i18n.bidi.rtlDirCheckRe_ = new RegExp(
* strongly-directional character method.
*/
goog.i18n.bidi.startsWithRtl = function(str, opt_isHtml) {
- return goog.i18n.bidi.rtlDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
- str, opt_isHtml));
+ return goog.i18n.bidi.rtlDirCheckRe_.test(
+ goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
@@ -27183,8 +24352,8 @@ goog.i18n.bidi.isRtlText = goog.i18n.bidi.startsWithRtl;
* strongly-directional character method.
*/
goog.i18n.bidi.startsWithLtr = function(str, opt_isHtml) {
- return goog.i18n.bidi.ltrDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
- str, opt_isHtml));
+ return goog.i18n.bidi.ltrDirCheckRe_.test(
+ goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
@@ -27306,8 +24475,8 @@ goog.i18n.bidi.isRtlExitText = goog.i18n.bidi.endsWithRtl;
*/
goog.i18n.bidi.rtlLocalesRe_ = new RegExp(
'^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|' +
- '.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))' +
- '(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)',
+ '.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))' +
+ '(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)',
'i');
@@ -27339,15 +24508,6 @@ goog.i18n.bidi.isRtlLanguage = function(lang) {
/**
- * Regular expression for bracket guard replacement in html.
- * @type {RegExp}
- * @private
- */
-goog.i18n.bidi.bracketGuardHtmlRe_ =
- /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(&lt;.*?(&gt;)+)/g;
-
-
-/**
* Regular expression for bracket guard replacement in text.
* @type {RegExp}
* @private
@@ -27357,38 +24517,19 @@ goog.i18n.bidi.bracketGuardTextRe_ =
/**
- * Apply bracket guard using html span tag. This is to address the problem of
- * messy bracket display frequently happens in RTL layout.
- * @param {string} s The string that need to be processed.
- * @param {boolean=} opt_isRtlContext specifies default direction (usually
- * direction of the UI).
- * @return {string} The processed string, with all bracket guarded.
- */
-goog.i18n.bidi.guardBracketInHtml = function(s, opt_isRtlContext) {
- var useRtl = opt_isRtlContext === undefined ?
- goog.i18n.bidi.hasAnyRtl(s) : opt_isRtlContext;
- if (useRtl) {
- return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_,
- '<span dir=rtl>$&</span>');
- }
- return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_,
- '<span dir=ltr>$&</span>');
-};
-
-
-/**
* Apply bracket guard using LRM and RLM. This is to address the problem of
* messy bracket display frequently happens in RTL layout.
- * This version works for both plain text and html. But it does not work as
- * good as guardBracketInHtml in some cases.
+ * This function works for plain text, not for HTML. In HTML, the opening
+ * bracket might be in a different context than the closing bracket (such as
+ * an attribute value).
* @param {string} s The string that need to be processed.
* @param {boolean=} opt_isRtlContext specifies default direction (usually
* direction of the UI).
* @return {string} The processed string, with all bracket guarded.
*/
goog.i18n.bidi.guardBracketInText = function(s, opt_isRtlContext) {
- var useRtl = opt_isRtlContext === undefined ?
- goog.i18n.bidi.hasAnyRtl(s) : opt_isRtlContext;
+ var useRtl = opt_isRtlContext === undefined ? goog.i18n.bidi.hasAnyRtl(s) :
+ opt_isRtlContext;
var mark = useRtl ? goog.i18n.bidi.Format.RLM : goog.i18n.bidi.Format.LRM;
return s.replace(goog.i18n.bidi.bracketGuardTextRe_, mark + '$&' + mark);
};
@@ -27496,12 +24637,14 @@ goog.i18n.bidi.tempRe_ = /%%%%/g;
* @return {string} Processed CSS specification string.
*/
goog.i18n.bidi.mirrorCSS = function(cssStr) {
- return cssStr.
+ return cssStr
+ .
// reverse dimensions
- replace(goog.i18n.bidi.dimensionsRe_, ':$1 $4 $3 $2').
- replace(goog.i18n.bidi.leftRe_, '%%%%'). // swap left and right
- replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT).
- replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT);
+ replace(goog.i18n.bidi.dimensionsRe_, ':$1 $4 $3 $2')
+ .replace(goog.i18n.bidi.leftRe_, '%%%%')
+ . // swap left and right
+ replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT)
+ .replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT);
};
@@ -27530,9 +24673,8 @@ goog.i18n.bidi.singleQuoteSubstituteRe_ = /([\u0591-\u05f2])'/g;
* @return {string} Processed string with double/single quote replaced.
*/
goog.i18n.bidi.normalizeHebrewQuote = function(str) {
- return str.
- replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, '$1\u05f4').
- replace(goog.i18n.bidi.singleQuoteSubstituteRe_, '$1\u05f3');
+ return str.replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, '$1\u05f4')
+ .replace(goog.i18n.bidi.singleQuoteSubstituteRe_, '$1\u05f3');
};
@@ -27589,8 +24731,8 @@ goog.i18n.bidi.estimateDirection = function(str, opt_isHtml) {
var rtlCount = 0;
var totalCount = 0;
var hasWeaklyLtr = false;
- var tokens = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml).
- split(goog.i18n.bidi.wordSeparatorRe_);
+ var tokens = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)
+ .split(goog.i18n.bidi.wordSeparatorRe_);
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (goog.i18n.bidi.startsWithRtl(token)) {
@@ -27608,7 +24750,8 @@ goog.i18n.bidi.estimateDirection = function(str, opt_isHtml) {
return totalCount == 0 ?
(hasWeaklyLtr ? goog.i18n.bidi.Dir.LTR : goog.i18n.bidi.Dir.NEUTRAL) :
(rtlCount / totalCount > goog.i18n.bidi.rtlDetectionThreshold_ ?
- goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR);
+ goog.i18n.bidi.Dir.RTL :
+ goog.i18n.bidi.Dir.LTR);
};
@@ -27642,9 +24785,9 @@ goog.i18n.bidi.setElementDirAndAlign = function(element, dir) {
if (element) {
dir = goog.i18n.bidi.toDir(dir);
if (dir) {
- element.style.textAlign =
- dir == goog.i18n.bidi.Dir.RTL ?
- goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT;
+ element.style.textAlign = dir == goog.i18n.bidi.Dir.RTL ?
+ goog.i18n.bidi.RIGHT :
+ goog.i18n.bidi.LEFT;
element.dir = dir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr';
}
}
@@ -27690,8 +24833,8 @@ goog.i18n.bidi.DirectionalString = function() {};
* property to {@code true}.
* @type {boolean}
*/
-goog.i18n.bidi.DirectionalString.prototype.
- implementsGoogI18nBidiDirectionalString;
+goog.i18n.bidi.DirectionalString.prototype
+ .implementsGoogI18nBidiDirectionalString;
/**
@@ -27726,6 +24869,7 @@ goog.require('goog.asserts');
goog.require('goog.fs.url');
goog.require('goog.i18n.bidi.Dir');
goog.require('goog.i18n.bidi.DirectionalString');
+goog.require('goog.string');
goog.require('goog.string.Const');
goog.require('goog.string.TypedString');
@@ -27918,9 +25062,8 @@ goog.html.SafeUrl.unwrap = function(safeUrl) {
return safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
} else {
goog.asserts.fail('expected object of type SafeUrl, got \'' +
- safeUrl + '\'');
+ safeUrl + '\' of type ' + goog.typeOf(safeUrl));
return 'type_error:SafeUrl';
-
}
};
@@ -27966,7 +25109,8 @@ goog.html.SAFE_MIME_TYPE_PATTERN_ =
*/
goog.html.SafeUrl.fromBlob = function(blob) {
var url = goog.html.SAFE_MIME_TYPE_PATTERN_.test(blob.type) ?
- goog.fs.url.createObjectUrl(blob) : goog.html.SafeUrl.INNOCUOUS_STRING;
+ goog.fs.url.createObjectUrl(blob) :
+ goog.html.SafeUrl.INNOCUOUS_STRING;
return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
};
@@ -28002,6 +25146,25 @@ goog.html.SafeUrl.fromDataUrl = function(dataUrl) {
/**
+ * Creates a SafeUrl wrapping a tel: URL.
+ *
+ * @param {string} telUrl A tel URL.
+ * @return {!goog.html.SafeUrl} A matching safe URL, or {@link INNOCUOUS_STRING}
+ * wrapped as a SafeUrl if it does not pass.
+ */
+goog.html.SafeUrl.fromTelUrl = function(telUrl) {
+ // There's a risk that a tel: URL could immediately place a call once
+ // clicked, without requiring user confirmation. For that reason it is
+ // handled in this separate function.
+ if (!goog.string.caseInsensitiveStartsWith(telUrl, 'tel:')) {
+ telUrl = goog.html.SafeUrl.INNOCUOUS_STRING;
+ }
+ return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(
+ telUrl);
+};
+
+
+/**
* A pattern that recognizes a commonly useful subset of URLs that satisfy
* the SafeUrl contract.
*
@@ -28036,26 +25199,12 @@ goog.html.SAFE_URL_PATTERN_ =
/**
* Creates a SafeUrl object from {@code url}. If {@code url} is a
* goog.html.SafeUrl then it is simply returned. Otherwise the input string is
- * validated to match a pattern of commonly used safe URLs. The string is
- * converted to UTF-8 and non-whitelisted characters are percent-encoded. The
- * string wrapped by the created SafeUrl will thus contain only ASCII printable
- * characters.
+ * validated to match a pattern of commonly used safe URLs.
*
* {@code url} may be a URL with the http, https, mailto or ftp scheme,
* or a relative URL (i.e., a URL without a scheme; specifically, a
* scheme-relative, absolute-path-relative, or path-relative URL).
*
- * {@code url} is converted to UTF-8 and non-whitelisted characters are
- * percent-encoded. Whitelisted characters are '%' and, from RFC 3986,
- * unreserved characters and reserved characters, with the exception of '\'',
- * '(' and ')'. This ensures the the SafeUrl contains only ASCII-printable
- * characters and reduces the chance of security bugs were it to be
- * interpolated into a specific context without the necessary escaping.
- *
- * If {@code url} fails validation or does not UTF-16 decode correctly
- * (JavaScript strings are UTF-16 encoded), this function returns a SafeUrl
- * object containing an innocuous string, goog.html.SafeUrl.INNOCUOUS_STRING.
- *
* @see http://url.spec.whatwg.org/#concept-relative-url
* @param {string|!goog.string.TypedString} url The URL to validate.
* @return {!goog.html.SafeUrl} The validated URL, wrapped as a SafeUrl.
@@ -28063,8 +25212,7 @@ goog.html.SAFE_URL_PATTERN_ =
goog.html.SafeUrl.sanitize = function(url) {
if (url instanceof goog.html.SafeUrl) {
return url;
- }
- else if (url.implementsGoogStringTypedString) {
+ } else if (url.implementsGoogStringTypedString) {
url = url.getTypedStringValue();
} else {
url = String(url);
@@ -28099,6 +25247,15 @@ goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse = function(
return safeUrl;
};
+
+/**
+ * A SafeUrl corresponding to the special about:blank url.
+ * @const {!goog.html.SafeUrl}
+ */
+goog.html.SafeUrl.ABOUT_BLANK =
+ goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(
+ 'about:blank');
+
// Copyright 2013 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -28266,16 +25423,15 @@ goog.html.TrustedResourceUrl.unwrap = function(trustedResourceUrl) {
if (trustedResourceUrl instanceof goog.html.TrustedResourceUrl &&
trustedResourceUrl.constructor === goog.html.TrustedResourceUrl &&
trustedResourceUrl
- .TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
- goog.html.TrustedResourceUrl
- .TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
+ .TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
+ goog.html.TrustedResourceUrl
+ .TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
return trustedResourceUrl
.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
} else {
goog.asserts.fail('expected object of type TrustedResourceUrl, got \'' +
- trustedResourceUrl + '\'');
+ trustedResourceUrl + '\' of type ' + goog.typeOf(trustedResourceUrl));
return 'type_error:TrustedResourceUrl';
-
}
};
@@ -28299,6 +25455,27 @@ goog.html.TrustedResourceUrl.fromConstant = function(url) {
/**
+ * Creates a TrustedResourceUrl object from a compile-time constant strings.
+ *
+ * Compile-time constant strings are inherently program-controlled and hence
+ * trusted.
+ *
+ * @param {!Array<!goog.string.Const>} parts Compile-time-constant strings from
+ * which to create a TrustedResourceUrl.
+ * @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object
+ * initialized to concatenation of {@code parts}.
+ */
+goog.html.TrustedResourceUrl.fromConstants = function(parts) {
+ var unwrapped = '';
+ for (var i = 0; i < parts.length; i++) {
+ unwrapped += goog.string.Const.unwrap(parts[i]);
+ }
+ return goog.html.TrustedResourceUrl
+ .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(unwrapped);
+};
+
+
+/**
* Type marker for the TrustedResourceUrl type, used to implement additional
* run-time type checking.
* @const {!Object}
@@ -28316,8 +25493,8 @@ goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
* object.
* @package
*/
-goog.html.TrustedResourceUrl.
- createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) {
+goog.html.TrustedResourceUrl
+ .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) {
var trustedResourceUrl = new goog.html.TrustedResourceUrl();
trustedResourceUrl.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ =
url;
@@ -28357,6 +25534,7 @@ goog.require('goog.html.SafeUrl');
goog.require('goog.html.TrustedResourceUrl');
goog.require('goog.i18n.bidi.Dir');
goog.require('goog.i18n.bidi.DirectionalString');
+goog.require('goog.labs.userAgent.browser');
goog.require('goog.object');
goog.require('goog.string');
goog.require('goog.string.Const');
@@ -28437,7 +25615,7 @@ goog.html.SafeHtml.prototype.implementsGoogStringTypedString = true;
/**
- * Returns this SafeHtml's value a string.
+ * Returns this SafeHtml's value as string.
*
* IMPORTANT: In code where it is security relevant that an object's type is
* indeed {@code SafeHtml}, use {@code goog.html.SafeHtml.unwrap} instead of
@@ -28505,7 +25683,7 @@ goog.html.SafeHtml.unwrap = function(safeHtml) {
return safeHtml.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
} else {
goog.asserts.fail('expected object of type SafeHtml, got \'' +
- safeHtml + '\'');
+ safeHtml + '\' of type ' + goog.typeOf(safeHtml));
return 'type_error:SafeHtml';
}
};
@@ -28623,8 +25801,9 @@ goog.html.SafeHtml.VALID_NAMES_IN_TAG_ = /^[a-zA-Z0-9-]+$/;
* http://www.w3.org/TR/html5/index.html#attributes-1.
* @private @const {!Object<string,boolean>}
*/
-goog.html.SafeHtml.URL_ATTRIBUTES_ = goog.object.createSet('action', 'cite',
- 'data', 'formaction', 'href', 'manifest', 'poster', 'src');
+goog.html.SafeHtml.URL_ATTRIBUTES_ = goog.object.createSet(
+ 'action', 'cite', 'data', 'formaction', 'href', 'manifest', 'poster',
+ 'src');
/**
@@ -28635,17 +25814,17 @@ goog.html.SafeHtml.URL_ATTRIBUTES_ = goog.object.createSet('action', 'cite',
* @private @const {!Object<string,boolean>}
*/
goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_ = goog.object.createSet(
- goog.dom.TagName.EMBED, goog.dom.TagName.IFRAME, goog.dom.TagName.LINK,
- goog.dom.TagName.OBJECT, goog.dom.TagName.SCRIPT, goog.dom.TagName.STYLE,
- goog.dom.TagName.TEMPLATE);
+ goog.dom.TagName.APPLET, goog.dom.TagName.BASE, goog.dom.TagName.EMBED,
+ goog.dom.TagName.IFRAME, goog.dom.TagName.LINK, goog.dom.TagName.MATH,
+ goog.dom.TagName.META, goog.dom.TagName.OBJECT, goog.dom.TagName.SCRIPT,
+ goog.dom.TagName.STYLE, goog.dom.TagName.SVG, goog.dom.TagName.TEMPLATE);
/**
* @typedef {string|number|goog.string.TypedString|
* goog.html.SafeStyle.PropertyMap}
- * @private
*/
-goog.html.SafeHtml.AttributeValue_;
+goog.html.SafeHtml.AttributeValue;
/**
@@ -28679,16 +25858,17 @@ goog.html.SafeHtml.AttributeValue_;
* - For attributes which are interpreted as URLs (e.g. src, href) a
* goog.html.SafeUrl, goog.string.Const or string is required. If a string
* is passed, it will be sanitized with SafeUrl.sanitize().
- * - For tags which can load code, more specific goog.html.SafeHtml.create*()
- * functions must be used. Tags which can load code and are not supported by
- * this function are embed, iframe, link, object, script, style, and template.
+ * - For tags which can load code or set security relevant page metadata,
+ * more specific goog.html.SafeHtml.create*() functions must be used. Tags
+ * which are not supported by this function are applet, base, embed, iframe,
+ * link, math, object, script, style, svg, and template.
*
* @param {string} tagName The name of the tag. Only tag names consisting of
* [a-zA-Z0-9-] are allowed. Tag names documented above are disallowed.
- * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
- * opt_attributes Mapping from attribute names to their values. Only
- * attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
- * undefined causes the attribute to be omitted.
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes
+ * Mapping from attribute names to their values. Only attribute names
+ * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes
+ * the attribute to be omitted.
* @param {!goog.html.SafeHtml.TextOrHtml_|
* !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to
* HTML-escape and put inside the tag. This must be empty for void tags
@@ -28699,34 +25879,50 @@ goog.html.SafeHtml.AttributeValue_;
* @throws {goog.asserts.AssertionError} If content for void tag is provided.
*/
goog.html.SafeHtml.create = function(tagName, opt_attributes, opt_content) {
+ goog.html.SafeHtml.verifyTagName(tagName);
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ tagName, opt_attributes, opt_content);
+};
+
+
+/**
+ * Verifies if the tag name is valid and if it doesn't change the context.
+ * E.g. STRONG is fine but SCRIPT throws because it changes context. See
+ * goog.html.SafeHtml.create for an explanation of allowed tags.
+ * @param {string} tagName
+ * @throws {Error} If invalid tag name is provided.
+ * @package
+ */
+goog.html.SafeHtml.verifyTagName = function(tagName) {
if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(tagName)) {
throw Error('Invalid tag name <' + tagName + '>.');
}
if (tagName.toUpperCase() in goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_) {
throw Error('Tag name <' + tagName + '> is not allowed for SafeHtml.');
}
- return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
- tagName, opt_attributes, opt_content);
};
/**
* Creates a SafeHtml representing an iframe tag.
*
- * By default the sandbox attribute is set to an empty value, which is the most
- * secure option, as it confers the iframe the least privileges. If this
- * is too restrictive then granting individual privileges is the preferable
- * option. Unsetting the attribute entirely is the least secure option and
- * should never be done unless it's stricly necessary.
+ * This by default restricts the iframe as much as possible by setting the
+ * sandbox attribute to the empty string. If the iframe requires less
+ * restrictions, set the sandbox attribute as tight as possible, but do not rely
+ * on the sandbox as a security feature because it is not supported by older
+ * browsers. If a sandbox is essential to security (e.g. for third-party
+ * frames), use createSandboxIframe which checks for browser support.
+ *
+ * @see https://developer.mozilla.org/en/docs/Web/HTML/Element/iframe#attr-sandbox
*
* @param {goog.html.TrustedResourceUrl=} opt_src The value of the src
* attribute. If null or undefined src will not be set.
* @param {goog.html.SafeHtml=} opt_srcdoc The value of the srcdoc attribute.
* If null or undefined srcdoc will not be set.
- * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
- * opt_attributes Mapping from attribute names to their values. Only
- * attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
- * undefined causes the attribute to be omitted.
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes
+ * Mapping from attribute names to their values. Only attribute names
+ * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes
+ * the attribute to be omitted.
* @param {!goog.html.SafeHtml.TextOrHtml_|
* !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to
* HTML-escape and put inside the tag. Array elements are concatenated.
@@ -28736,9 +25932,15 @@ goog.html.SafeHtml.create = function(tagName, opt_attributes, opt_content) {
*/
goog.html.SafeHtml.createIframe = function(
opt_src, opt_srcdoc, opt_attributes, opt_content) {
+ if (opt_src) {
+ // Check whether this is really TrustedResourceUrl.
+ goog.html.TrustedResourceUrl.unwrap(opt_src);
+ }
+
var fixedAttributes = {};
fixedAttributes['src'] = opt_src || null;
- fixedAttributes['srcdoc'] = opt_srcdoc || null;
+ fixedAttributes['srcdoc'] =
+ opt_srcdoc && goog.html.SafeHtml.unwrap(opt_srcdoc);
var defaultAttributes = {'sandbox': ''};
var attributes = goog.html.SafeHtml.combineAttributes(
fixedAttributes, defaultAttributes, opt_attributes);
@@ -28748,15 +25950,106 @@ goog.html.SafeHtml.createIframe = function(
/**
+ * Creates a SafeHtml representing a sandboxed iframe tag.
+ *
+ * The sandbox attribute is enforced in its most restrictive mode, an empty
+ * string. Consequently, the security requirements for the src and srcdoc
+ * attributes are relaxed compared to SafeHtml.createIframe. This function
+ * will throw on browsers that do not support the sandbox attribute, as
+ * determined by SafeHtml.canUseSandboxIframe.
+ *
+ * The SafeHtml returned by this function can trigger downloads with no
+ * user interaction on Chrome (though only a few, further attempts are blocked).
+ * Firefox and IE will block all downloads from the sandbox.
+ *
+ * @see https://developer.mozilla.org/en/docs/Web/HTML/Element/iframe#attr-sandbox
+ * @see https://lists.w3.org/Archives/Public/public-whatwg-archive/2013Feb/0112.html
+ *
+ * @param {string|!goog.html.SafeUrl=} opt_src The value of the src
+ * attribute. If null or undefined src will not be set.
+ * @param {string=} opt_srcdoc The value of the srcdoc attribute.
+ * If null or undefined srcdoc will not be set. Will not be sanitized.
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes
+ * Mapping from attribute names to their values. Only attribute names
+ * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes
+ * the attribute to be omitted.
+ * @param {!goog.html.SafeHtml.TextOrHtml_|
+ * !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to
+ * HTML-escape and put inside the tag. Array elements are concatenated.
+ * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
+ * @throws {Error} If invalid tag name, attribute name, or attribute value is
+ * provided. If opt_attributes contains the src, srcdoc or sandbox
+ * attributes. If browser does not support the sandbox attribute on iframe.
+ */
+goog.html.SafeHtml.createSandboxIframe = function(
+ opt_src, opt_srcdoc, opt_attributes, opt_content) {
+ if (!goog.html.SafeHtml.canUseSandboxIframe()) {
+ throw new Error('The browser does not support sandboxed iframes.');
+ }
+
+ var fixedAttributes = {};
+ if (opt_src) {
+ // Note that sanitize is a no-op on SafeUrl.
+ fixedAttributes['src'] =
+ goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(opt_src));
+ } else {
+ fixedAttributes['src'] = null;
+ }
+ fixedAttributes['srcdoc'] = opt_srcdoc || null;
+ fixedAttributes['sandbox'] = '';
+ var attributes =
+ goog.html.SafeHtml.combineAttributes(fixedAttributes, {}, opt_attributes);
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'iframe', attributes, opt_content);
+};
+
+
+/**
+ * Checks if the user agent supports sandboxed iframes.
+ * @return {boolean}
+ */
+goog.html.SafeHtml.canUseSandboxIframe = function() {
+ return goog.global['HTMLIFrameElement'] &&
+ ('sandbox' in goog.global['HTMLIFrameElement'].prototype);
+};
+
+
+/**
+ * Creates a SafeHtml representing a script tag with the src attribute.
+ * @param {!goog.html.TrustedResourceUrl} src The value of the src
+ * attribute.
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=}
+ * opt_attributes
+ * Mapping from attribute names to their values. Only attribute names
+ * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined
+ * causes the attribute to be omitted.
+ * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
+ * @throws {Error} If invalid attribute name or value is provided. If
+ * opt_attributes contains the src attribute.
+ */
+goog.html.SafeHtml.createScriptSrc = function(src, opt_attributes) {
+ // Check whether this is really TrustedResourceUrl.
+ goog.html.TrustedResourceUrl.unwrap(src);
+
+ var fixedAttributes = {'src': src};
+ var defaultAttributes = {};
+ var attributes = goog.html.SafeHtml.combineAttributes(
+ fixedAttributes, defaultAttributes, opt_attributes);
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'script', attributes);
+};
+
+
+/**
* Creates a SafeHtml representing a style tag. The type attribute is set
* to "text/css".
* @param {!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>}
* styleSheet Content to put inside the tag. Array elements are
* concatenated.
- * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
- * opt_attributes Mapping from attribute names to their values. Only
- * attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
- * undefined causes the attribute to be omitted.
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes
+ * Mapping from attribute names to their values. Only attribute names
+ * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes
+ * the attribute to be omitted.
* @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
* @throws {Error} If invalid attribute name or attribute value is provided. If
* opt_attributes contains the type attribute.
@@ -28772,9 +26065,10 @@ goog.html.SafeHtml.createStyle = function(styleSheet, opt_attributes) {
for (var i = 0; i < styleSheet.length; i++) {
content += goog.html.SafeStyleSheet.unwrap(styleSheet[i]);
}
- // Convert to SafeHtml so that it's not HTML-escaped.
- var htmlContent = goog.html.SafeHtml
- .createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ // Convert to SafeHtml so that it's not HTML-escaped. This is safe because
+ // as part of its contract, SafeStyleSheet should have no dangerous '<'.
+ var htmlContent =
+ goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
content, goog.i18n.bidi.Dir.NEUTRAL);
return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
'style', attributes, htmlContent);
@@ -28782,9 +26076,54 @@ goog.html.SafeHtml.createStyle = function(styleSheet, opt_attributes) {
/**
+ * Creates a SafeHtml representing a meta refresh tag.
+ * @param {!goog.html.SafeUrl|string} url Where to redirect. If a string is
+ * passed, it will be sanitized with SafeUrl.sanitize().
+ * @param {number=} opt_secs Number of seconds until the page should be
+ * reloaded. Will be set to 0 if unspecified.
+ * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
+ */
+goog.html.SafeHtml.createMetaRefresh = function(url, opt_secs) {
+
+ // Note that sanitize is a no-op on SafeUrl.
+ var unwrappedUrl = goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(url));
+
+ if (goog.labs.userAgent.browser.isIE() ||
+ goog.labs.userAgent.browser.isEdge()) {
+ // IE/EDGE can't parse the content attribute if the url contains a
+ // semicolon. We can fix this by adding quotes around the url, but then we
+ // can't parse quotes in the URL correctly. Also, it seems that IE/EDGE
+ // did not unescape semicolons in these URLs at some point in the past. We
+ // take a best-effort approach.
+ //
+ // If the URL has semicolons (which may happen in some cases, see
+ // http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.2
+ // for instance), wrap it in single quotes to protect the semicolons.
+ // If the URL has semicolons and single quotes, url-encode the single quotes
+ // as well.
+ //
+ // This is imperfect. Notice that both ' and ; are reserved characters in
+ // URIs, so this could do the wrong thing, but at least it will do the wrong
+ // thing in only rare cases.
+ if (goog.string.contains(unwrappedUrl, ';')) {
+ unwrappedUrl = "'" + unwrappedUrl.replace(/'/g, '%27') + "'";
+ }
+ }
+ var attributes = {
+ 'http-equiv': 'refresh',
+ 'content': (opt_secs || 0) + '; url=' + unwrappedUrl
+ };
+
+ // This function will handle the HTML escaping for attributes.
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'meta', attributes);
+};
+
+
+/**
* @param {string} tagName The tag name.
* @param {string} name The attribute name.
- * @param {!goog.html.SafeHtml.AttributeValue_} value The attribute value.
+ * @param {!goog.html.SafeHtml.AttributeValue} value The attribute value.
* @return {string} A "name=value" string.
* @throws {Error} If attribute value is unsafe for the given tag and attribute.
* @private
@@ -28797,9 +26136,10 @@ goog.html.SafeHtml.getAttrNameAndValue_ = function(tagName, name, value) {
value = goog.html.SafeHtml.getStyleValue_(value);
} else if (/^on/i.test(name)) {
// TODO(jakubvrana): Disallow more attributes with a special meaning.
- throw Error('Attribute "' + name +
- '" requires goog.string.Const value, "' + value + '" given.');
- // URL attributes handled differently accroding to tag.
+ throw Error(
+ 'Attribute "' + name + '" requires goog.string.Const value, "' + value +
+ '" given.');
+ // URL attributes handled differently accroding to tag.
} else if (name.toLowerCase() in goog.html.SafeHtml.URL_ATTRIBUTES_) {
if (value instanceof goog.html.TrustedResourceUrl) {
value = goog.html.TrustedResourceUrl.unwrap(value);
@@ -28808,7 +26148,8 @@ goog.html.SafeHtml.getAttrNameAndValue_ = function(tagName, name, value) {
} else if (goog.isString(value)) {
value = goog.html.SafeUrl.sanitize(value).getTypedStringValue();
} else {
- throw Error('Attribute "' + name + '" on tag "' + tagName +
+ throw Error(
+ 'Attribute "' + name + '" on tag "' + tagName +
'" requires goog.html.SafeUrl, goog.string.Const, or string,' +
' value "' + value + '" given.');
}
@@ -28822,16 +26163,17 @@ goog.html.SafeHtml.getAttrNameAndValue_ = function(tagName, name, value) {
value = value.getTypedStringValue();
}
- goog.asserts.assert(goog.isString(value) || goog.isNumber(value),
- 'String or number value expected, got ' +
- (typeof value) + ' with value: ' + value);
+ goog.asserts.assert(
+ goog.isString(value) || goog.isNumber(value),
+ 'String or number value expected, got ' + (typeof value) +
+ ' with value: ' + value);
return name + '="' + goog.string.htmlEscape(String(value)) + '"';
};
/**
* Gets value allowed in "style" attribute.
- * @param {goog.html.SafeHtml.AttributeValue_} value It could be SafeStyle or a
+ * @param {!goog.html.SafeHtml.AttributeValue} value It could be SafeStyle or a
* map which will be passed to goog.html.SafeStyle.create.
* @return {string} Unwrapped value.
* @throws {Error} If string value is given.
@@ -28839,7 +26181,8 @@ goog.html.SafeHtml.getAttrNameAndValue_ = function(tagName, name, value) {
*/
goog.html.SafeHtml.getStyleValue_ = function(value) {
if (!goog.isObject(value)) {
- throw Error('The "style" attribute requires goog.html.SafeStyle or map ' +
+ throw Error(
+ 'The "style" attribute requires goog.html.SafeStyle or map ' +
'of style properties, ' + (typeof value) + ' given: ' + value);
}
if (!(value instanceof goog.html.SafeStyle)) {
@@ -28855,13 +26198,13 @@ goog.html.SafeHtml.getStyleValue_ = function(value) {
* optional attributes and optional content.
* @param {!goog.i18n.bidi.Dir} dir Directionality.
* @param {string} tagName
- * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=} opt_attributes
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes
* @param {!goog.html.SafeHtml.TextOrHtml_|
* !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content
* @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
*/
-goog.html.SafeHtml.createWithDir = function(dir, tagName, opt_attributes,
- opt_content) {
+goog.html.SafeHtml.createWithDir = function(
+ dir, tagName, opt_attributes, opt_content) {
var html = goog.html.SafeHtml.create(tagName, opt_attributes, opt_content);
html.dir_ = dir;
return html;
@@ -28965,7 +26308,7 @@ goog.html.SafeHtml.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
* Like create() but does not restrict which tags can be constructed.
*
* @param {string} tagName Tag name. Set or validated by caller.
- * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=} opt_attributes
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes
* @param {(!goog.html.SafeHtml.TextOrHtml_|
* !Array<!goog.html.SafeHtml.TextOrHtml_>)=} opt_content
* @return {!goog.html.SafeHtml}
@@ -28973,24 +26316,11 @@ goog.html.SafeHtml.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
* @throws {goog.asserts.AssertionError} If content for void tag is provided.
* @package
*/
-goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse =
- function(tagName, opt_attributes, opt_content) {
+goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse = function(
+ tagName, opt_attributes, opt_content) {
var dir = null;
var result = '<' + tagName;
-
- if (opt_attributes) {
- for (var name in opt_attributes) {
- if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(name)) {
- throw Error('Invalid attribute name "' + name + '".');
- }
- var value = opt_attributes[name];
- if (!goog.isDefAndNotNull(value)) {
- continue;
- }
- result += ' ' +
- goog.html.SafeHtml.getAttrNameAndValue_(tagName, name, value);
- }
- }
+ result += goog.html.SafeHtml.stringifyAttributes(tagName, opt_attributes);
var content = opt_content;
if (!goog.isDefAndNotNull(content)) {
@@ -29000,8 +26330,8 @@ goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse =
}
if (goog.dom.tags.isVoidTag(tagName.toLowerCase())) {
- goog.asserts.assert(!content.length,
- 'Void tag <' + tagName + '> does not allow content.');
+ goog.asserts.assert(
+ !content.length, 'Void tag <' + tagName + '> does not allow content.');
result += '>';
} else {
var html = goog.html.SafeHtml.concat(content);
@@ -29026,11 +26356,39 @@ goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse =
/**
+ * Creates a string with attributes to insert after tagName.
+ * @param {string} tagName
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes
+ * @return {string} Returns an empty string if there are no attributes, returns
+ * a string starting with a space otherwise.
+ * @throws {Error} If attribute value is unsafe for the given tag and attribute.
+ * @package
+ */
+goog.html.SafeHtml.stringifyAttributes = function(tagName, opt_attributes) {
+ var result = '';
+ if (opt_attributes) {
+ for (var name in opt_attributes) {
+ if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(name)) {
+ throw Error('Invalid attribute name "' + name + '".');
+ }
+ var value = opt_attributes[name];
+ if (!goog.isDefAndNotNull(value)) {
+ continue;
+ }
+ result +=
+ ' ' + goog.html.SafeHtml.getAttrNameAndValue_(tagName, name, value);
+ }
+ }
+ return result;
+}
+
+
+/**
* @param {!Object<string, string>} fixedAttributes
* @param {!Object<string, string>} defaultAttributes
- * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
- * opt_attributes Optional attributes passed to create*().
- * @return {!Object<string, goog.html.SafeHtml.AttributeValue_>}
+ * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes
+ * Optional attributes passed to create*().
+ * @return {!Object<string, ?goog.html.SafeHtml.AttributeValue>}
* @throws {Error} If opt_attributes contains an attribute with the same name
* as an attribute in fixedAttributes.
* @package
@@ -29052,8 +26410,9 @@ goog.html.SafeHtml.combineAttributes = function(
for (name in opt_attributes) {
var nameLower = name.toLowerCase();
if (nameLower in fixedAttributes) {
- throw Error('Cannot override "' + nameLower + '" attribute, got "' +
- name + '" with value "' + opt_attributes[name] + '"');
+ throw Error(
+ 'Cannot override "' + nameLower + '" attribute, got "' + name +
+ '" with value "' + opt_attributes[name] + '"');
}
if (nameLower in defaultAttributes) {
delete combinedAttributes[nameLower];
@@ -29082,6 +26441,15 @@ goog.html.SafeHtml.EMPTY =
goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
'', goog.i18n.bidi.Dir.NEUTRAL);
+
+/**
+ * A SafeHtml instance corresponding to the <br> tag.
+ * @const {!goog.html.SafeHtml}
+ */
+goog.html.SafeHtml.BR =
+ goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ '<br>', goog.i18n.bidi.Dir.NEUTRAL);
+
// Copyright 2013 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -29215,6 +26583,30 @@ goog.dom.safe.setAnchorHref = function(anchor, url) {
/**
+ * Safely assigns a URL to an image element's src property.
+ *
+ * If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
+ * image's src property. If url is of type string however, it is first
+ * sanitized using goog.html.SafeUrl.sanitize.
+ *
+ * @param {!HTMLImageElement} imageElement The image element whose src property
+ * is to be assigned to.
+ * @param {string|!goog.html.SafeUrl} url The URL to assign.
+ * @see goog.html.SafeUrl#sanitize
+ */
+goog.dom.safe.setImageSrc = function(imageElement, url) {
+ /** @type {!goog.html.SafeUrl} */
+ var safeUrl;
+ if (url instanceof goog.html.SafeUrl) {
+ safeUrl = url;
+ } else {
+ safeUrl = goog.html.SafeUrl.sanitize(url);
+ }
+ imageElement.src = goog.html.SafeUrl.unwrap(safeUrl);
+};
+
+
+/**
* Safely assigns a URL to an embed element's src property.
*
* Example usage:
@@ -29421,13 +26813,192 @@ goog.dom.safe.openInWindow = function(
safeUrl = goog.html.SafeUrl.sanitize(url);
}
var win = opt_openerWin || window;
- return win.open(goog.html.SafeUrl.unwrap(safeUrl),
+ return win.open(
+ goog.html.SafeUrl.unwrap(safeUrl),
// If opt_name is undefined, simply passing that in to open() causes IE to
// reuse the current window instead of opening a new one. Thus we pass ''
// in instead, which according to spec opens a new window. See
// https://html.spec.whatwg.org/multipage/browsers.html#dom-open .
- opt_name ? goog.string.Const.unwrap(opt_name) : '',
- opt_specs, opt_replace);
+ opt_name ? goog.string.Const.unwrap(opt_name) : '', opt_specs,
+ opt_replace);
+};
+
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Transitional utilities to unsafely trust random strings as
+ * goog.html types. Intended for temporary use when upgrading a library that
+ * used to accept plain strings to use safe types, but where it's not
+ * practical to transitively update callers.
+ *
+ * IMPORTANT: No new code should use the conversion functions in this file,
+ * they are intended for refactoring old code to use goog.html types. New code
+ * should construct goog.html types via their APIs, template systems or
+ * sanitizers. If that’s not possible it should use
+ * goog.html.uncheckedconversions and undergo security review.
+
+ *
+ * The semantics of the conversions in goog.html.legacyconversions are very
+ * different from the ones provided by goog.html.uncheckedconversions. The
+ * latter are for use in code where it has been established through manual
+ * security review that the value produced by a piece of code will always
+ * satisfy the SafeHtml contract (e.g., the output of a secure HTML sanitizer).
+ * In uses of goog.html.legacyconversions, this guarantee is not given -- the
+ * value in question originates in unreviewed legacy code and there is no
+ * guarantee that it satisfies the SafeHtml contract.
+ *
+ * There are only three valid uses of legacyconversions:
+ *
+ * 1. Introducing a goog.html version of a function which currently consumes
+ * string and passes that string to a DOM API which can execute script - and
+ * hence cause XSS - like innerHTML. For example, Dialog might expose a
+ * setContent method which takes a string and sets the innerHTML property of
+ * an element with it. In this case a setSafeHtmlContent function could be
+ * added, consuming goog.html.SafeHtml instead of string, and using
+ * goog.dom.safe.setInnerHtml instead of directly setting innerHTML.
+ * setContent could then internally use legacyconversions to create a SafeHtml
+ * from string and pass the SafeHtml to setSafeHtmlContent. In this scenario
+ * remember to document the use of legacyconversions in the modified setContent
+ * and consider deprecating it as well.
+ *
+ * 2. Automated refactoring of application code which handles HTML as string
+ * but needs to call a function which only takes goog.html types. For example,
+ * in the Dialog scenario from (1) an alternative option would be to refactor
+ * setContent to accept goog.html.SafeHtml instead of string and then refactor
+ * all current callers to use legacyconversions to pass SafeHtml. This is
+ * generally preferable to (1) because it keeps the library clean of
+ * legacyconversions, and makes code sites in application code that are
+ * potentially vulnerable to XSS more apparent.
+ *
+ * 3. Old code which needs to call APIs which consume goog.html types and for
+ * which it is prohibitively expensive to refactor to use goog.html types.
+ * Generally, this is code where safety from XSS is either hopeless or
+ * unimportant.
+ *
+ * @visibility {//closure/goog/html:approved_for_legacy_conversion}
+ * @visibility {//closure/goog/bin/sizetests:__pkg__}
+ */
+
+
+goog.provide('goog.html.legacyconversions');
+
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.SafeStyle');
+goog.require('goog.html.SafeStyleSheet');
+goog.require('goog.html.SafeUrl');
+goog.require('goog.html.TrustedResourceUrl');
+
+
+/**
+ * Performs an "unchecked conversion" from string to SafeHtml for legacy API
+ * purposes.
+ *
+ * Please read fileoverview documentation before using.
+ *
+ * @param {string} html A string to be converted to SafeHtml.
+ * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml
+ * object.
+ */
+goog.html.legacyconversions.safeHtmlFromString = function(html) {
+ goog.html.legacyconversions.reportCallback_();
+ return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ html, null /* dir */);
+};
+
+
+/**
+ * Performs an "unchecked conversion" from string to SafeStyle for legacy API
+ * purposes.
+ *
+ * Please read fileoverview documentation before using.
+ *
+ * @param {string} style A string to be converted to SafeStyle.
+ * @return {!goog.html.SafeStyle} The value of style, wrapped in a SafeStyle
+ * object.
+ */
+goog.html.legacyconversions.safeStyleFromString = function(style) {
+ goog.html.legacyconversions.reportCallback_();
+ return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
+ style);
+};
+
+
+/**
+ * Performs an "unchecked conversion" from string to SafeStyleSheet for legacy
+ * API purposes.
+ *
+ * Please read fileoverview documentation before using.
+ *
+ * @param {string} styleSheet A string to be converted to SafeStyleSheet.
+ * @return {!goog.html.SafeStyleSheet} The value of style sheet, wrapped in
+ * a SafeStyleSheet object.
+ */
+goog.html.legacyconversions.safeStyleSheetFromString = function(styleSheet) {
+ goog.html.legacyconversions.reportCallback_();
+ return goog.html.SafeStyleSheet
+ .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet);
+};
+
+
+/**
+ * Performs an "unchecked conversion" from string to SafeUrl for legacy API
+ * purposes.
+ *
+ * Please read fileoverview documentation before using.
+ *
+ * @param {string} url A string to be converted to SafeUrl.
+ * @return {!goog.html.SafeUrl} The value of url, wrapped in a SafeUrl
+ * object.
+ */
+goog.html.legacyconversions.safeUrlFromString = function(url) {
+ goog.html.legacyconversions.reportCallback_();
+ return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
+};
+
+
+/**
+ * Performs an "unchecked conversion" from string to TrustedResourceUrl for
+ * legacy API purposes.
+ *
+ * Please read fileoverview documentation before using.
+ *
+ * @param {string} url A string to be converted to TrustedResourceUrl.
+ * @return {!goog.html.TrustedResourceUrl} The value of url, wrapped in a
+ * TrustedResourceUrl object.
+ */
+goog.html.legacyconversions.trustedResourceUrlFromString = function(url) {
+ goog.html.legacyconversions.reportCallback_();
+ return goog.html.TrustedResourceUrl
+ .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url);
+};
+
+/**
+ * @private {function(): undefined}
+ */
+goog.html.legacyconversions.reportCallback_ = goog.nullFunction;
+
+
+/**
+ * Sets a function that will be called every time a legacy conversion is
+ * performed. The function is called with no parameters but it can use
+ * goog.debug.getStacktrace to get a stacktrace.
+ *
+ * @param {function(): undefined} callback Error callback as defined above.
+ */
+goog.html.legacyconversions.setReportCallback = function(callback) {
+ goog.html.legacyconversions.reportCallback_ = callback;
};
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
@@ -29641,7 +27212,7 @@ goog.math.Coordinate.prototype.translate = function(tx, opt_ty) {
this.x += tx.x;
this.y += tx.y;
} else {
- this.x += tx;
+ this.x += Number(tx);
if (goog.isNumber(opt_ty)) {
this.y += opt_ty;
}
@@ -29969,6 +27540,7 @@ goog.require('goog.dom.NodeType');
goog.require('goog.dom.TagName');
goog.require('goog.dom.safe');
goog.require('goog.html.SafeHtml');
+goog.require('goog.html.legacyconversions');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Size');
goog.require('goog.object');
@@ -30010,13 +27582,13 @@ goog.dom.getDomHelper = function(opt_element) {
return opt_element ?
new goog.dom.DomHelper(goog.dom.getOwnerDocument(opt_element)) :
(goog.dom.defaultDomHelper_ ||
- (goog.dom.defaultDomHelper_ = new goog.dom.DomHelper()));
+ (goog.dom.defaultDomHelper_ = new goog.dom.DomHelper()));
};
/**
* Cached default DOM helper.
- * @type {goog.dom.DomHelper}
+ * @type {!goog.dom.DomHelper|undefined}
* @private
*/
goog.dom.defaultDomHelper_;
@@ -30053,9 +27625,7 @@ goog.dom.getElement = function(element) {
* @private
*/
goog.dom.getElementHelper_ = function(doc, element) {
- return goog.isString(element) ?
- doc.getElementById(element) :
- element;
+ return goog.isString(element) ? doc.getElementById(element) : element;
};
@@ -30085,8 +27655,8 @@ goog.dom.getRequiredElementHelper_ = function(doc, id) {
// To prevent users passing in Elements as is permitted in getElement().
goog.asserts.assertString(id);
var element = goog.dom.getElementHelper_(doc, id);
- element = goog.asserts.assertElement(element,
- 'No element found with id: ' + id);
+ element =
+ goog.asserts.assertElement(element, 'No element found with id: ' + id);
return element;
};
@@ -30122,12 +27692,12 @@ goog.dom.$ = goog.dom.getElement;
* @param {?string=} opt_tag Element tag name.
* @param {?string=} opt_class Optional class name.
* @param {(Document|Element)=} opt_el Optional element to look in.
- * @return { {length: number} } Array-like list of elements (only a length
+ * @return {!IArrayLike<!Element>} Array-like list of elements (only a length
* property and numerical indices are guaranteed to exist).
*/
goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {
- return goog.dom.getElementsByTagNameAndClass_(document, opt_tag, opt_class,
- opt_el);
+ return goog.dom.getElementsByTagNameAndClass_(
+ document, opt_tag, opt_class, opt_el);
};
@@ -30137,7 +27707,7 @@ goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {
* @see {goog.dom.query}
* @param {string} className the name of the class to look for.
* @param {(Document|Element)=} opt_el Optional element to look in.
- * @return { {length: number} } The items found with the class name provided.
+ * @return {!IArrayLike<!Element>} The items found with the class name provided.
*/
goog.dom.getElementsByClass = function(className, opt_el) {
var parent = opt_el || document;
@@ -30183,8 +27753,8 @@ goog.dom.getElementByClass = function(className, opt_el) {
*/
goog.dom.getRequiredElementByClass = function(className, opt_root) {
var retValue = goog.dom.getElementByClass(className, opt_root);
- return goog.asserts.assert(retValue,
- 'No element found with className: ' + className);
+ return goog.asserts.assert(
+ retValue, 'No element found with className: ' + className);
};
@@ -30206,17 +27776,16 @@ goog.dom.canUseQuerySelector_ = function(parent) {
* @param {?string=} opt_tag Element tag name.
* @param {?string=} opt_class Optional class name.
* @param {(Document|Element)=} opt_el Optional element to look in.
- * @return { {length: number} } Array-like list of elements (only a length
+ * @return {!IArrayLike<!Element>} Array-like list of elements (only a length
* property and numerical indices are guaranteed to exist).
* @private
*/
-goog.dom.getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class,
- opt_el) {
+goog.dom.getElementsByTagNameAndClass_ = function(
+ doc, opt_tag, opt_class, opt_el) {
var parent = opt_el || doc;
var tagName = (opt_tag && opt_tag != '*') ? opt_tag.toUpperCase() : '';
- if (goog.dom.canUseQuerySelector_(parent) &&
- (tagName || opt_class)) {
+ if (goog.dom.canUseQuerySelector_(parent) && (tagName || opt_class)) {
var query = tagName + (opt_class ? '.' + opt_class : '');
return parent.querySelectorAll(query);
}
@@ -30239,7 +27808,7 @@ goog.dom.getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class,
}
arrayLike.length = len;
- return arrayLike;
+ return /** @type {!IArrayLike<!Element>} */ (arrayLike);
} else {
return els;
}
@@ -30259,7 +27828,7 @@ goog.dom.getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class,
}
}
arrayLike.length = len;
- return arrayLike;
+ return /** @type {!IArrayLike<!Element>} */ (arrayLike);
} else {
return els;
}
@@ -30271,7 +27840,7 @@ goog.dom.getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class,
* @param {?string=} opt_tag Element tag name.
* @param {?string=} opt_class Optional class name.
* @param {Element=} opt_el Optional element to look in.
- * @return { {length: number} } Array-like list of elements (only a length
+ * @return {!IArrayLike<!Element>} Array-like list of elements (only a length
* property and numerical indices are guaranteed to exist).
* @deprecated Use {@link goog.dom.getElementsByTagNameAndClass} instead.
*/
@@ -30293,7 +27862,8 @@ goog.dom.setProperties = function(element, properties) {
element.htmlFor = val;
} else if (goog.dom.DIRECT_ATTRIBUTE_MAP_.hasOwnProperty(key)) {
element.setAttribute(goog.dom.DIRECT_ATTRIBUTE_MAP_[key], val);
- } else if (goog.string.startsWith(key, 'aria-') ||
+ } else if (
+ goog.string.startsWith(key, 'aria-') ||
goog.string.startsWith(key, 'data-')) {
element.setAttribute(key, val);
} else {
@@ -30318,6 +27888,7 @@ goog.dom.DIRECT_ATTRIBUTE_MAP_ = {
'frameborder': 'frameBorder',
'height': 'height',
'maxlength': 'maxLength',
+ 'nonce': 'nonce',
'role': 'role',
'rowspan': 'rowSpan',
'type': 'type',
@@ -30420,6 +27991,15 @@ goog.dom.getDocumentHeight = function() {
return goog.dom.getDocumentHeight_(window);
};
+/**
+ * Calculates the height of the document of the given window.
+ *
+ * @param {!Window} win The window whose document height to retrieve.
+ * @return {number} The height of the document of the given window.
+ */
+goog.dom.getDocumentHeightForWindow = function(win) {
+ return goog.dom.getDocumentHeight_(win);
+};
/**
* Calculates the height of the document of the given window.
@@ -30463,8 +28043,8 @@ goog.dom.getDocumentHeight_ = function(win) {
// document.documentElement.offsetHeight
// Based on studying the values output by different browsers,
// use the value that's NOT equal to the viewport height found above.
- height = docEl.scrollHeight != vh ?
- docEl.scrollHeight : docEl.offsetHeight;
+ height =
+ docEl.scrollHeight != vh ? docEl.scrollHeight : docEl.offsetHeight;
} else {
// In Quirks mode:
// documentElement.clientHeight is equal to documentElement.offsetHeight
@@ -30538,8 +28118,8 @@ goog.dom.getDocumentScroll_ = function(doc) {
// offsets.
return new goog.math.Coordinate(el.scrollLeft, el.scrollTop);
}
- return new goog.math.Coordinate(win.pageXOffset || el.scrollLeft,
- win.pageYOffset || el.scrollTop);
+ return new goog.math.Coordinate(
+ win.pageXOffset || el.scrollLeft, win.pageYOffset || el.scrollTop);
};
@@ -30694,8 +28274,8 @@ goog.dom.append_ = function(doc, parent, args, startIndex) {
function childHandler(child) {
// TODO(user): More coercion, ala MochiKit?
if (child) {
- parent.appendChild(goog.isString(child) ?
- doc.createTextNode(child) : child);
+ parent.appendChild(
+ goog.isString(child) ? doc.createTextNode(child) : child);
}
}
@@ -30705,8 +28285,8 @@ goog.dom.append_ = function(doc, parent, args, startIndex) {
if (goog.isArrayLike(arg) && !goog.dom.isNodeLike(arg)) {
// If the argument is a node list, not a real array, use a clone,
// because forEach can't be used to mutate a NodeList.
- goog.array.forEach(goog.dom.isNodeList(arg) ?
- goog.array.toArray(arg) : arg,
+ goog.array.forEach(
+ goog.dom.isNodeList(arg) ? goog.array.toArray(arg) : arg,
childHandler);
} else {
childHandler(arg);
@@ -30817,8 +28397,8 @@ goog.dom.safeHtmlToNode = function(html) {
goog.dom.safeHtmlToNode_ = function(doc, html) {
var tempDiv = doc.createElement(goog.dom.TagName.DIV);
if (goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT) {
- goog.dom.safe.setInnerHtml(tempDiv,
- goog.html.SafeHtml.concat(goog.html.SafeHtml.create('br'), html));
+ goog.dom.safe.setInnerHtml(
+ tempDiv, goog.html.SafeHtml.concat(goog.html.SafeHtml.BR, html));
tempDiv.removeChild(tempDiv.firstChild);
} else {
goog.dom.safe.setInnerHtml(tempDiv, html);
@@ -30839,35 +28419,17 @@ goog.dom.safeHtmlToNode_ = function(doc, html) {
*
* @param {string} htmlString The HTML string to convert.
* @return {!Node} The resulting document fragment.
+ * @deprecated Use {@link goog.dom.safeHtmlToNode} instead.
*/
goog.dom.htmlToDocumentFragment = function(htmlString) {
- return goog.dom.htmlToDocumentFragment_(document, htmlString);
-};
-
-
-// TODO(jakubvrana): Merge with {@code safeHtmlToNode_}.
-/**
- * Helper for {@code htmlToDocumentFragment}.
- *
- * @param {!Document} doc The document.
- * @param {string} htmlString The HTML string to convert.
- * @return {!Node} The resulting document fragment.
- * @private
- */
-goog.dom.htmlToDocumentFragment_ = function(doc, htmlString) {
- var tempDiv = doc.createElement(goog.dom.TagName.DIV);
- if (goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT) {
- tempDiv.innerHTML = '<br>' + htmlString;
- tempDiv.removeChild(tempDiv.firstChild);
- } else {
- tempDiv.innerHTML = htmlString;
- }
- return goog.dom.childrenToNode_(doc, tempDiv);
+ return goog.dom.safeHtmlToNode_(document,
+ // For now, we are blindly trusting that the HTML is safe.
+ goog.html.legacyconversions.safeHtmlFromString(htmlString));
};
/**
- * Helper for {@code htmlToDocumentFragment_}.
+ * Helper for {@code safeHtmlToNode_}.
* @param {!Document} doc The document.
* @param {!Node} tempDiv The input node.
* @return {!Node} The resulting node.
@@ -31109,8 +28671,8 @@ goog.dom.flattenElement = function(element) {
/**
* Returns an array containing just the element children of the given element.
* @param {Element} element The element whose element children we want.
- * @return {!(Array|NodeList)} An array or array-like list of just the element
- * children of the given element.
+ * @return {!(Array<!Element>|NodeList<!Element>)} An array or array-like list
+ * of just the element children of the given element.
*/
goog.dom.getChildren = function(element) {
// We check if the children attribute is supported for child elements
@@ -31133,7 +28695,7 @@ goog.dom.getChildren = function(element) {
*/
goog.dom.getFirstElementChild = function(node) {
if (goog.isDef(node.firstElementChild)) {
- return /** @type {!Element} */(node).firstElementChild;
+ return /** @type {!Element} */ (node).firstElementChild;
}
return goog.dom.getNextElementNode_(node.firstChild, true);
};
@@ -31146,7 +28708,7 @@ goog.dom.getFirstElementChild = function(node) {
*/
goog.dom.getLastElementChild = function(node) {
if (goog.isDef(node.lastElementChild)) {
- return /** @type {!Element} */(node).lastElementChild;
+ return /** @type {!Element} */ (node).lastElementChild;
}
return goog.dom.getNextElementNode_(node.lastChild, false);
};
@@ -31159,7 +28721,7 @@ goog.dom.getLastElementChild = function(node) {
*/
goog.dom.getNextElementSibling = function(node) {
if (goog.isDef(node.nextElementSibling)) {
- return /** @type {!Element} */(node).nextElementSibling;
+ return /** @type {!Element} */ (node).nextElementSibling;
}
return goog.dom.getNextElementNode_(node.nextSibling, true);
};
@@ -31173,7 +28735,7 @@ goog.dom.getNextElementSibling = function(node) {
*/
goog.dom.getPreviousElementSibling = function(node) {
if (goog.isDef(node.previousElementSibling)) {
- return /** @type {!Element} */(node).previousElementSibling;
+ return /** @type {!Element} */ (node).previousElementSibling;
}
return goog.dom.getNextElementNode_(node.previousSibling, false);
};
@@ -31282,13 +28844,12 @@ goog.dom.isWindow = function(obj) {
goog.dom.getParentElement = function(element) {
var parent;
if (goog.dom.BrowserFeature.CAN_USE_PARENT_ELEMENT_PROPERTY) {
- var isIe9 = goog.userAgent.IE &&
- goog.userAgent.isVersionOrHigher('9') &&
+ var isIe9 = goog.userAgent.IE && goog.userAgent.isVersionOrHigher('9') &&
!goog.userAgent.isVersionOrHigher('10');
// SVG elements in IE9 can't use the parentElement property.
// goog.global['SVGElement'] is not defined in IE9 quirks mode.
if (!(isIe9 && goog.global['SVGElement'] &&
- element instanceof goog.global['SVGElement'])) {
+ element instanceof goog.global['SVGElement'])) {
parent = element.parentElement;
if (parent) {
return parent;
@@ -31302,11 +28863,14 @@ goog.dom.getParentElement = function(element) {
/**
* Whether a node contains another node.
- * @param {Node} parent The node that should contain the other node.
- * @param {Node} descendant The node to test presence of.
+ * @param {?Node} parent The node that should contain the other node.
+ * @param {?Node} descendant The node to test presence of.
* @return {boolean} Whether the parent node contains the descendent node.
*/
goog.dom.contains = function(parent, descendant) {
+ if (!parent || !descendant) {
+ return false;
+ }
// We use browser specific methods for this if available since it is faster
// that way.
@@ -31390,7 +28954,7 @@ goog.dom.compareNodeOrder = function(node1, node2) {
}
return (isElement1 ? node1.sourceIndex : parent1.sourceIndex) -
- (isElement2 ? node2.sourceIndex : parent2.sourceIndex);
+ (isElement2 ? node2.sourceIndex : parent2.sourceIndex);
}
}
@@ -31406,8 +28970,8 @@ goog.dom.compareNodeOrder = function(node1, node2) {
range2.selectNode(node2);
range2.collapse(true);
- return range1.compareBoundaryPoints(goog.global['Range'].START_TO_END,
- range2);
+ return range1.compareBoundaryPoints(
+ goog.global['Range'].START_TO_END, range2);
};
@@ -31509,8 +29073,8 @@ goog.dom.getOwnerDocument = function(node) {
// TODO(nnaze): Update param signature to be non-nullable.
goog.asserts.assert(node, 'Node cannot be null or undefined.');
return /** @type {!Document} */ (
- node.nodeType == goog.dom.NodeType.DOCUMENT ? node :
- node.ownerDocument || node.document);
+ node.nodeType == goog.dom.NodeType.DOCUMENT ? node : node.ownerDocument ||
+ node.document);
};
@@ -31520,19 +29084,29 @@ goog.dom.getOwnerDocument = function(node) {
* @return {!Document} The frame content document.
*/
goog.dom.getFrameContentDocument = function(frame) {
- var doc = frame.contentDocument || frame.contentWindow.document;
- return doc;
+ return frame.contentDocument ||
+ /** @type {!HTMLFrameElement} */ (frame).contentWindow.document;
};
/**
* Cross-browser function for getting the window of a frame or iframe.
* @param {Element} frame Frame element.
- * @return {Window} The window associated with the given frame.
+ * @return {Window} The window associated with the given frame, or null if none
+ * exists.
*/
goog.dom.getFrameContentWindow = function(frame) {
- return frame.contentWindow ||
- goog.dom.getWindow(goog.dom.getFrameContentDocument(frame));
+ try {
+ return frame.contentWindow ||
+ (frame.contentDocument ? goog.dom.getWindow(frame.contentDocument) :
+ null);
+ } catch (e) {
+ // NOTE(user): In IE8, checking the contentWindow or contentDocument
+ // properties will throw a "Unspecified Error" exception if the iframe is
+ // not inserted in the DOM. If we get this we can be sure that no window
+ // exists, so return null.
+ }
+ return null;
};
@@ -31542,15 +29116,16 @@ goog.dom.getFrameContentWindow = function(frame) {
* @param {string|number} text The value that should replace the node's content.
*/
goog.dom.setTextContent = function(node, text) {
- goog.asserts.assert(node != null,
+ goog.asserts.assert(
+ node != null,
'goog.dom.setTextContent expects a non-null value for node');
if ('textContent' in node) {
node.textContent = text;
} else if (node.nodeType == goog.dom.NodeType.TEXT) {
node.data = text;
- } else if (node.firstChild &&
- node.firstChild.nodeType == goog.dom.NodeType.TEXT) {
+ } else if (
+ node.firstChild && node.firstChild.nodeType == goog.dom.NodeType.TEXT) {
// If the first child is a text node we just change its data and remove the
// rest of the children.
while (node.lastChild != node.firstChild) {
@@ -31572,6 +29147,9 @@ goog.dom.setTextContent = function(node, text) {
* @return {string} The outerHTML of the given element.
*/
goog.dom.getOuterHtml = function(element) {
+ goog.asserts.assert(
+ element !== null,
+ 'goog.dom.getOuterHtml expects a non-null value for element');
// IE, Opera and WebKit all have outerHTML.
if ('outerHTML' in element) {
return element.outerHTML;
@@ -31673,7 +29251,10 @@ goog.dom.TAGS_TO_IGNORE_ = {
* @private {!Object<string, string>}
* @const
*/
-goog.dom.PREDEFINED_TAG_VALUES_ = {'IMG': ' ', 'BR': '\n'};
+goog.dom.PREDEFINED_TAG_VALUES_ = {
+ 'IMG': ' ',
+ 'BR': '\n'
+};
/**
@@ -31683,11 +29264,10 @@ goog.dom.PREDEFINED_TAG_VALUES_ = {'IMG': ' ', 'BR': '\n'};
* @param {!Element} element Element to check.
* @return {boolean} Whether the element has a tab index that allows keyboard
* focus.
- * @see http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
*/
goog.dom.isFocusableTabIndex = function(element) {
return goog.dom.hasSpecifiedTabIndex_(element) &&
- goog.dom.isTabIndexFocusable_(element);
+ goog.dom.isTabIndexFocusable_(element);
};
@@ -31709,7 +29289,7 @@ goog.dom.setFocusableTabIndex = function(element, enable) {
// without setting it to -1 first, the element remains keyboard focusable
// despite not having a tabIndex attribute anymore.
element.tabIndex = -1;
- element.removeAttribute('tabIndex'); // Must be camelCase!
+ element.removeAttribute('tabIndex'); // Must be camelCase!
}
};
@@ -31736,7 +29316,8 @@ goog.dom.isFocusable = function(element) {
// IE requires elements to be visible in order to focus them.
return focusable && goog.userAgent.IE ?
- goog.dom.hasNonZeroBoundingRect_(element) : focusable;
+ goog.dom.hasNonZeroBoundingRect_(/** @type {!HTMLElement} */ (element)) :
+ focusable;
};
@@ -31750,7 +29331,7 @@ goog.dom.hasSpecifiedTabIndex_ = function(element) {
// IE returns 0 for an unset tabIndex, so we must use getAttributeNode(),
// which returns an object with a 'specified' property if tabIndex is
// specified. This works on other browsers, too.
- var attrNode = element.getAttributeNode('tabindex'); // Must be lowercase!
+ var attrNode = element.getAttributeNode('tabindex'); // Must be lowercase!
return goog.isDefAndNotNull(attrNode) && attrNode.specified;
};
@@ -31762,7 +29343,7 @@ goog.dom.hasSpecifiedTabIndex_ = function(element) {
* @private
*/
goog.dom.isTabIndexFocusable_ = function(element) {
- var index = element.tabIndex;
+ var index = /** @type {!HTMLElement} */ (element).tabIndex;
// NOTE: IE9 puts tabIndex in 16-bit int, e.g. -2 is 65534.
return goog.isNumber(index) && index >= 0 && index < 32768;
};
@@ -31776,24 +29357,29 @@ goog.dom.isTabIndexFocusable_ = function(element) {
*/
goog.dom.nativelySupportsFocus_ = function(element) {
return element.tagName == goog.dom.TagName.A ||
- element.tagName == goog.dom.TagName.INPUT ||
- element.tagName == goog.dom.TagName.TEXTAREA ||
- element.tagName == goog.dom.TagName.SELECT ||
- element.tagName == goog.dom.TagName.BUTTON;
+ element.tagName == goog.dom.TagName.INPUT ||
+ element.tagName == goog.dom.TagName.TEXTAREA ||
+ element.tagName == goog.dom.TagName.SELECT ||
+ element.tagName == goog.dom.TagName.BUTTON;
};
/**
* Returns true if the element has a bounding rectangle that would be visible
* (i.e. its width and height are greater than zero).
- * @param {!Element} element Element to check.
+ * @param {!HTMLElement} element Element to check.
* @return {boolean} Whether the element has a non-zero bounding rectangle.
* @private
*/
goog.dom.hasNonZeroBoundingRect_ = function(element) {
- var rect = goog.isFunction(element['getBoundingClientRect']) ?
- element.getBoundingClientRect() :
- {'height': element.offsetHeight, 'width': element.offsetWidth};
+ var rect;
+ if (!goog.isFunction(element['getBoundingClientRect']) ||
+ // In IE, getBoundingClientRect throws on detached nodes.
+ (goog.userAgent.IE && element.parentElement == null)) {
+ rect = {'height': element.offsetHeight, 'width': element.offsetWidth};
+ } else {
+ rect = element.getBoundingClientRect();
+ }
return goog.isDefAndNotNull(rect) && rect.height > 0 && rect.width > 0;
};
@@ -31813,7 +29399,8 @@ goog.dom.getTextContent = function(node) {
var textContent;
// Note(arv): IE9, Opera, and Safari 3 support innerText but they include
// text nodes in script tags. So we revert to use a user agent test here.
- if (goog.dom.BrowserFeature.CAN_USE_INNER_TEXT && ('innerText' in node)) {
+ if (goog.dom.BrowserFeature.CAN_USE_INNER_TEXT && node !== null &&
+ ('innerText' in node)) {
textContent = goog.string.canonicalizeNewlines(node.innerText);
// Unfortunately .innerText() returns text with &shy; symbols
// We need to filter it out and then remove duplicate whitespaces
@@ -32007,18 +29594,18 @@ goog.dom.isNodeList = function(val) {
* @return {Element} The first ancestor that matches the passed criteria, or
* null if no match is found.
*/
-goog.dom.getAncestorByTagNameAndClass = function(element, opt_tag, opt_class,
- opt_maxSearchSteps) {
+goog.dom.getAncestorByTagNameAndClass = function(
+ element, opt_tag, opt_class, opt_maxSearchSteps) {
if (!opt_tag && !opt_class) {
return null;
}
var tagName = opt_tag ? opt_tag.toUpperCase() : null;
- return /** @type {Element} */ (goog.dom.getAncestor(element,
- function(node) {
- return (!tagName || node.nodeName == tagName) &&
- (!opt_class || goog.isString(node.className) &&
- goog.array.contains(node.className.split(/\s+/), opt_class));
- }, true, opt_maxSearchSteps));
+ return /** @type {Element} */ (goog.dom.getAncestor(element, function(node) {
+ return (!tagName || node.nodeName == tagName) &&
+ (!opt_class ||
+ goog.isString(node.className) &&
+ goog.array.contains(node.className.split(/\s+/), opt_class));
+ }, true, opt_maxSearchSteps));
};
@@ -32034,8 +29621,8 @@ goog.dom.getAncestorByTagNameAndClass = function(element, opt_tag, opt_class,
* null if none match.
*/
goog.dom.getAncestorByClass = function(element, className, opt_maxSearchSteps) {
- return goog.dom.getAncestorByTagNameAndClass(element, null, className,
- opt_maxSearchSteps);
+ return goog.dom.getAncestorByTagNameAndClass(
+ element, null, className, opt_maxSearchSteps);
};
@@ -32058,9 +29645,9 @@ goog.dom.getAncestor = function(
if (!opt_includeNode) {
element = element.parentNode;
}
- var ignoreSearchSteps = opt_maxSearchSteps == null;
var steps = 0;
- while (element && (ignoreSearchSteps || steps <= opt_maxSearchSteps)) {
+ while (element &&
+ (opt_maxSearchSteps == null || steps <= opt_maxSearchSteps)) {
goog.asserts.assert(element.name != 'parentNode');
if (matcher(element)) {
return element;
@@ -32115,9 +29702,8 @@ goog.dom.getPixelRatio = function() {
return win.devicePixelRatio;
} else if (win.matchMedia) {
return goog.dom.matchesPixelRatio_(.75) ||
- goog.dom.matchesPixelRatio_(1.5) ||
- goog.dom.matchesPixelRatio_(2) ||
- goog.dom.matchesPixelRatio_(3) || 1;
+ goog.dom.matchesPixelRatio_(1.5) || goog.dom.matchesPixelRatio_(2) ||
+ goog.dom.matchesPixelRatio_(3) || 1;
}
return 1;
};
@@ -32132,9 +29718,10 @@ goog.dom.getPixelRatio = function() {
*/
goog.dom.matchesPixelRatio_ = function(pixelRatio) {
var win = goog.dom.getWindow();
- var query = ('(-webkit-min-device-pixel-ratio: ' + pixelRatio + '),' +
- '(min--moz-device-pixel-ratio: ' + pixelRatio + '),' +
- '(min-resolution: ' + pixelRatio + 'dppx)');
+ var query =
+ ('(-webkit-min-device-pixel-ratio: ' + pixelRatio + '),' +
+ '(min--moz-device-pixel-ratio: ' + pixelRatio + '),' +
+ '(min-resolution: ' + pixelRatio + 'dppx)');
return win.matchMedia(query).matches ? pixelRatio : 0;
};
@@ -32227,14 +29814,13 @@ goog.dom.DomHelper.prototype.$ = goog.dom.DomHelper.prototype.getElement;
* @param {?string=} opt_tag Element tag name or * for all tags.
* @param {?string=} opt_class Optional class name.
* @param {(Document|Element)=} opt_el Optional element to look in.
- * @return { {length: number} } Array-like list of elements (only a length
+ * @return {!IArrayLike<!Element>} Array-like list of elements (only a length
* property and numerical indices are guaranteed to exist).
*/
-goog.dom.DomHelper.prototype.getElementsByTagNameAndClass = function(opt_tag,
- opt_class,
- opt_el) {
- return goog.dom.getElementsByTagNameAndClass_(this.document_, opt_tag,
- opt_class, opt_el);
+goog.dom.DomHelper.prototype.getElementsByTagNameAndClass = function(
+ opt_tag, opt_class, opt_el) {
+ return goog.dom.getElementsByTagNameAndClass_(
+ this.document_, opt_tag, opt_class, opt_el);
};
@@ -32243,7 +29829,7 @@ goog.dom.DomHelper.prototype.getElementsByTagNameAndClass = function(opt_tag,
* @see {goog.dom.query}
* @param {string} className the name of the class to look for.
* @param {Element|Document=} opt_el Optional element to look in.
- * @return { {length: number} } The items found with the class name provided.
+ * @return {!IArrayLike<!Element>} The items found with the class name provided.
*/
goog.dom.DomHelper.prototype.getElementsByClass = function(className, opt_el) {
var doc = opt_el || this.document_;
@@ -32274,8 +29860,8 @@ goog.dom.DomHelper.prototype.getElementByClass = function(className, opt_el) {
* @return {!Element} The first item found with the class name provided.
* @throws {goog.asserts.AssertionError} Thrown if no element is found.
*/
-goog.dom.DomHelper.prototype.getRequiredElementByClass = function(className,
- opt_root) {
+goog.dom.DomHelper.prototype.getRequiredElementByClass = function(
+ className, opt_root) {
var root = opt_root || this.document_;
return goog.dom.getRequiredElementByClass(className, root);
};
@@ -32289,7 +29875,7 @@ goog.dom.DomHelper.prototype.getRequiredElementByClass = function(className,
* @param {?string=} opt_tag Element tag name.
* @param {?string=} opt_class Optional class name.
* @param {Element=} opt_el Optional element to look in.
- * @return { {length: number} } Array-like list of elements (only a length
+ * @return {!IArrayLike<!Element>} Array-like list of elements (only a length
* property and numerical indices are guaranteed to exist).
*/
goog.dom.DomHelper.prototype.$$ =
@@ -32358,9 +29944,8 @@ goog.dom.Appendable;
* NodeList, its elements will be added as childNodes instead.
* @return {!Element} Reference to a DOM node.
*/
-goog.dom.DomHelper.prototype.createDom = function(tagName,
- opt_attributes,
- var_args) {
+goog.dom.DomHelper.prototype.createDom = function(
+ tagName, opt_attributes, var_args) {
return goog.dom.createDom_(this.document_, arguments);
};
@@ -32408,10 +29993,10 @@ goog.dom.DomHelper.prototype.createTextNode = function(content) {
* {@code goog.string.Unicode.NBSP} characters.
* @return {!HTMLElement} The created table.
*/
-goog.dom.DomHelper.prototype.createTable = function(rows, columns,
- opt_fillWithNbsp) {
- return goog.dom.createTable_(this.document_, rows, columns,
- !!opt_fillWithNbsp);
+goog.dom.DomHelper.prototype.createTable = function(
+ rows, columns, opt_fillWithNbsp) {
+ return goog.dom.createTable_(
+ this.document_, rows, columns, !!opt_fillWithNbsp);
};
@@ -32435,9 +30020,11 @@ goog.dom.DomHelper.prototype.safeHtmlToNode = function(html) {
*
* @param {string} htmlString The HTML string to convert.
* @return {!Node} The resulting node.
+ * @deprecated Use {@link goog.dom.DomHelper.prototype.safeHtmlToNode} instead.
*/
goog.dom.DomHelper.prototype.htmlToDocumentFragment = function(htmlString) {
- return goog.dom.htmlToDocumentFragment_(this.document_, htmlString);
+ return goog.dom.safeHtmlToNode_(this.document_,
+ goog.html.legacyconversions.safeHtmlFromString(htmlString));
};
@@ -32584,8 +30171,8 @@ goog.dom.DomHelper.prototype.flattenElement = goog.dom.flattenElement;
/**
* Returns an array containing just the element children of the given element.
* @param {Element} element The element whose element children we want.
- * @return {!(Array|NodeList)} An array or array-like list of just the element
- * children of the given element.
+ * @return {!(Array<!Element>|NodeList<!Element>)} An array or array-like list
+ * of just the element children of the given element.
*/
goog.dom.DomHelper.prototype.getChildren = goog.dom.getChildren;
@@ -32899,8 +30486,7 @@ goog.dom.DomHelper.prototype.getAncestorByTagNameAndClass =
* @return {Element} The first ancestor that matches the passed criteria, or
* null if none match.
*/
-goog.dom.DomHelper.prototype.getAncestorByClass =
- goog.dom.getAncestorByClass;
+goog.dom.DomHelper.prototype.getAncestorByClass = goog.dom.getAncestorByClass;
/**
@@ -32934,284 +30520,6 @@ goog.dom.DomHelper.prototype.getAncestor = goog.dom.getAncestor;
// limitations under the License.
/**
- * @fileoverview Utilities for detecting, adding and removing classes. Prefer
- * this over goog.dom.classes for new code since it attempts to use classList
- * (DOMTokenList: http://dom.spec.whatwg.org/#domtokenlist) which is faster
- * and requires less code.
- *
- * Note: these utilities are meant to operate on HTMLElements
- * and may have unexpected behavior on elements with differing interfaces
- * (such as SVGElements).
- */
-
-
-goog.provide('goog.dom.classlist');
-
-goog.require('goog.array');
-
-
-/**
- * Override this define at build-time if you know your target supports it.
- * @define {boolean} Whether to use the classList property (DOMTokenList).
- */
-goog.define('goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST', false);
-
-
-/**
- * Gets an array-like object of class names on an element.
- * @param {Element} element DOM node to get the classes of.
- * @return {!goog.array.ArrayLike} Class names on {@code element}.
- */
-goog.dom.classlist.get = function(element) {
- if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
- return element.classList;
- }
-
- var className = element.className;
- // Some types of elements don't have a className in IE (e.g. iframes).
- // Furthermore, in Firefox, className is not a string when the element is
- // an SVG element.
- return goog.isString(className) && className.match(/\S+/g) || [];
-};
-
-
-/**
- * Sets the entire class name of an element.
- * @param {Element} element DOM node to set class of.
- * @param {string} className Class name(s) to apply to element.
- */
-goog.dom.classlist.set = function(element, className) {
- element.className = className;
-};
-
-
-/**
- * Returns true if an element has a class. This method may throw a DOM
- * exception for an invalid or empty class name if DOMTokenList is used.
- * @param {Element} element DOM node to test.
- * @param {string} className Class name to test for.
- * @return {boolean} Whether element has the class.
- */
-goog.dom.classlist.contains = function(element, className) {
- if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
- return element.classList.contains(className);
- }
- return goog.array.contains(goog.dom.classlist.get(element), className);
-};
-
-
-/**
- * Adds a class to an element. Does not add multiples of class names. This
- * method may throw a DOM exception for an invalid or empty class name if
- * DOMTokenList is used.
- * @param {Element} element DOM node to add class to.
- * @param {string} className Class name to add.
- */
-goog.dom.classlist.add = function(element, className) {
- if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
- element.classList.add(className);
- return;
- }
-
- if (!goog.dom.classlist.contains(element, className)) {
- // Ensure we add a space if this is not the first class name added.
- element.className += element.className.length > 0 ?
- (' ' + className) : className;
- }
-};
-
-
-/**
- * Convenience method to add a number of class names at once.
- * @param {Element} element The element to which to add classes.
- * @param {goog.array.ArrayLike<string>} classesToAdd An array-like object
- * containing a collection of class names to add to the element.
- * This method may throw a DOM exception if classesToAdd contains invalid
- * or empty class names.
- */
-goog.dom.classlist.addAll = function(element, classesToAdd) {
- if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
- goog.array.forEach(classesToAdd, function(className) {
- goog.dom.classlist.add(element, className);
- });
- return;
- }
-
- var classMap = {};
-
- // Get all current class names into a map.
- goog.array.forEach(goog.dom.classlist.get(element),
- function(className) {
- classMap[className] = true;
- });
-
- // Add new class names to the map.
- goog.array.forEach(classesToAdd,
- function(className) {
- classMap[className] = true;
- });
-
- // Flatten the keys of the map into the className.
- element.className = '';
- for (var className in classMap) {
- element.className += element.className.length > 0 ?
- (' ' + className) : className;
- }
-};
-
-
-/**
- * Removes a class from an element. This method may throw a DOM exception
- * for an invalid or empty class name if DOMTokenList is used.
- * @param {Element} element DOM node to remove class from.
- * @param {string} className Class name to remove.
- */
-goog.dom.classlist.remove = function(element, className) {
- if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
- element.classList.remove(className);
- return;
- }
-
- if (goog.dom.classlist.contains(element, className)) {
- // Filter out the class name.
- element.className = goog.array.filter(
- goog.dom.classlist.get(element),
- function(c) {
- return c != className;
- }).join(' ');
- }
-};
-
-
-/**
- * Removes a set of classes from an element. Prefer this call to
- * repeatedly calling {@code goog.dom.classlist.remove} if you want to remove
- * a large set of class names at once.
- * @param {Element} element The element from which to remove classes.
- * @param {goog.array.ArrayLike<string>} classesToRemove An array-like object
- * containing a collection of class names to remove from the element.
- * This method may throw a DOM exception if classesToRemove contains invalid
- * or empty class names.
- */
-goog.dom.classlist.removeAll = function(element, classesToRemove) {
- if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
- goog.array.forEach(classesToRemove, function(className) {
- goog.dom.classlist.remove(element, className);
- });
- return;
- }
- // Filter out those classes in classesToRemove.
- element.className = goog.array.filter(
- goog.dom.classlist.get(element),
- function(className) {
- // If this class is not one we are trying to remove,
- // add it to the array of new class names.
- return !goog.array.contains(classesToRemove, className);
- }).join(' ');
-};
-
-
-/**
- * Adds or removes a class depending on the enabled argument. This method
- * may throw a DOM exception for an invalid or empty class name if DOMTokenList
- * is used.
- * @param {Element} element DOM node to add or remove the class on.
- * @param {string} className Class name to add or remove.
- * @param {boolean} enabled Whether to add or remove the class (true adds,
- * false removes).
- */
-goog.dom.classlist.enable = function(element, className, enabled) {
- if (enabled) {
- goog.dom.classlist.add(element, className);
- } else {
- goog.dom.classlist.remove(element, className);
- }
-};
-
-
-/**
- * Adds or removes a set of classes depending on the enabled argument. This
- * method may throw a DOM exception for an invalid or empty class name if
- * DOMTokenList is used.
- * @param {!Element} element DOM node to add or remove the class on.
- * @param {goog.array.ArrayLike<string>} classesToEnable An array-like object
- * containing a collection of class names to add or remove from the element.
- * @param {boolean} enabled Whether to add or remove the classes (true adds,
- * false removes).
- */
-goog.dom.classlist.enableAll = function(element, classesToEnable, enabled) {
- var f = enabled ? goog.dom.classlist.addAll :
- goog.dom.classlist.removeAll;
- f(element, classesToEnable);
-};
-
-
-/**
- * Switches a class on an element from one to another without disturbing other
- * classes. If the fromClass isn't removed, the toClass won't be added. This
- * method may throw a DOM exception if the class names are empty or invalid.
- * @param {Element} element DOM node to swap classes on.
- * @param {string} fromClass Class to remove.
- * @param {string} toClass Class to add.
- * @return {boolean} Whether classes were switched.
- */
-goog.dom.classlist.swap = function(element, fromClass, toClass) {
- if (goog.dom.classlist.contains(element, fromClass)) {
- goog.dom.classlist.remove(element, fromClass);
- goog.dom.classlist.add(element, toClass);
- return true;
- }
- return false;
-};
-
-
-/**
- * Removes a class if an element has it, and adds it the element doesn't have
- * it. Won't affect other classes on the node. This method may throw a DOM
- * exception if the class name is empty or invalid.
- * @param {Element} element DOM node to toggle class on.
- * @param {string} className Class to toggle.
- * @return {boolean} True if class was added, false if it was removed
- * (in other words, whether element has the class after this function has
- * been called).
- */
-goog.dom.classlist.toggle = function(element, className) {
- var add = !goog.dom.classlist.contains(element, className);
- goog.dom.classlist.enable(element, className, add);
- return add;
-};
-
-
-/**
- * Adds and removes a class of an element. Unlike
- * {@link goog.dom.classlist.swap}, this method adds the classToAdd regardless
- * of whether the classToRemove was present and had been removed. This method
- * may throw a DOM exception if the class names are empty or invalid.
- *
- * @param {Element} element DOM node to swap classes on.
- * @param {string} classToRemove Class to remove.
- * @param {string} classToAdd Class to add.
- */
-goog.dom.classlist.addRemove = function(element, classToRemove, classToAdd) {
- goog.dom.classlist.remove(element, classToRemove);
- goog.dom.classlist.add(element, classToAdd);
-};
-
-// Copyright 2012 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
* @fileoverview Vendor prefix getters.
*/
@@ -33279,7 +30587,8 @@ goog.dom.vendor.getPrefixedPropertyName = function(propertyName, opt_object) {
prefix = prefix.toLowerCase();
var prefixedPropertyName = prefix + goog.string.toTitleCase(propertyName);
return (!goog.isDef(opt_object) || prefixedPropertyName in opt_object) ?
- prefixedPropertyName : null;
+ prefixedPropertyName :
+ null;
}
return null;
};
@@ -33315,6 +30624,7 @@ goog.dom.vendor.getPrefixedEventType = function(eventType) {
goog.provide('goog.math.Box');
+goog.require('goog.asserts');
goog.require('goog.math.Coordinate');
@@ -33367,8 +30677,8 @@ goog.math.Box = function(top, right, bottom, left) {
* @return {!goog.math.Box} A Box containing all the specified Coordinates.
*/
goog.math.Box.boundingBox = function(var_args) {
- var box = new goog.math.Box(arguments[0].y, arguments[0].x,
- arguments[0].y, arguments[0].x);
+ var box = new goog.math.Box(
+ arguments[0].y, arguments[0].x, arguments[0].y, arguments[0].x);
for (var i = 1; i < arguments.length; i++) {
box.expandToIncludeCoordinate(arguments[i]);
}
@@ -33409,7 +30719,7 @@ if (goog.DEBUG) {
*/
goog.math.Box.prototype.toString = function() {
return '(' + this.top + 't, ' + this.right + 'r, ' + this.bottom + 'b, ' +
- this.left + 'l)';
+ this.left + 'l)';
};
}
@@ -33434,18 +30744,18 @@ goog.math.Box.prototype.contains = function(other) {
* @param {number=} opt_left Left margin.
* @return {!goog.math.Box} A reference to this Box.
*/
-goog.math.Box.prototype.expand = function(top, opt_right, opt_bottom,
- opt_left) {
+goog.math.Box.prototype.expand = function(
+ top, opt_right, opt_bottom, opt_left) {
if (goog.isObject(top)) {
this.top -= top.top;
this.right += top.right;
this.bottom += top.bottom;
this.left -= top.left;
} else {
- this.top -= top;
- this.right += opt_right;
- this.bottom += opt_bottom;
- this.left -= opt_left;
+ this.top -= /** @type {number} */ (top);
+ this.right += Number(opt_right);
+ this.bottom += Number(opt_bottom);
+ this.left -= Number(opt_left);
}
return this;
@@ -33493,8 +30803,8 @@ goog.math.Box.equals = function(a, b) {
if (!a || !b) {
return false;
}
- return a.top == b.top && a.right == b.right &&
- a.bottom == b.bottom && a.left == b.left;
+ return a.top == b.top && a.right == b.right && a.bottom == b.bottom &&
+ a.left == b.left;
};
@@ -33516,8 +30826,8 @@ goog.math.Box.contains = function(box, other) {
}
// other is a Coordinate.
- return other.x >= box.left && other.x <= box.right &&
- other.y >= box.top && other.y <= box.bottom;
+ return other.x >= box.left && other.x <= box.right && other.y >= box.top &&
+ other.y <= box.bottom;
};
@@ -33584,8 +30894,9 @@ goog.math.Box.distance = function(box, coord) {
* @return {boolean} Whether the boxes intersect.
*/
goog.math.Box.intersects = function(a, b) {
- return (a.left <= b.right && b.left <= a.right &&
- a.top <= b.bottom && b.top <= a.bottom);
+ return (
+ a.left <= b.right && b.left <= a.right && a.top <= b.bottom &&
+ b.top <= a.bottom);
};
@@ -33598,8 +30909,9 @@ goog.math.Box.intersects = function(a, b) {
* @return {boolean} Whether the boxes intersect.
*/
goog.math.Box.intersectsWithPadding = function(a, b, padding) {
- return (a.left <= b.right + padding && b.left <= a.right + padding &&
- a.top <= b.bottom + padding && b.top <= a.bottom + padding);
+ return (
+ a.left <= b.right + padding && b.left <= a.right + padding &&
+ a.top <= b.bottom + padding && b.top <= a.bottom + padding);
};
@@ -33664,6 +30976,7 @@ goog.math.Box.prototype.translate = function(tx, opt_ty) {
this.top += tx.y;
this.bottom += tx.y;
} else {
+ goog.asserts.assertNumber(tx);
this.left += tx;
this.right += tx;
if (goog.isNumber(opt_ty)) {
@@ -33713,6 +31026,7 @@ goog.math.Box.prototype.scale = function(sx, opt_sy) {
goog.provide('goog.math.Rect');
+goog.require('goog.asserts');
goog.require('goog.math.Box');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Size');
@@ -33759,10 +31073,7 @@ goog.math.Rect.prototype.clone = function() {
goog.math.Rect.prototype.toBox = function() {
var right = this.left + this.width;
var bottom = this.top + this.height;
- return new goog.math.Box(this.top,
- right,
- bottom,
- this.left);
+ return new goog.math.Box(this.top, right, bottom, this.left);
};
@@ -33786,8 +31097,8 @@ goog.math.Rect.createFromPositionAndSize = function(position, size) {
* and size.
*/
goog.math.Rect.createFromBox = function(box) {
- return new goog.math.Rect(box.left, box.top,
- box.right - box.left, box.bottom - box.top);
+ return new goog.math.Rect(
+ box.left, box.top, box.right - box.left, box.bottom - box.top);
};
@@ -33799,7 +31110,7 @@ if (goog.DEBUG) {
*/
goog.math.Rect.prototype.toString = function() {
return '(' + this.left + ', ' + this.top + ' - ' + this.width + 'w x ' +
- this.height + 'h)';
+ this.height + 'h)';
};
}
@@ -33818,8 +31129,8 @@ goog.math.Rect.equals = function(a, b) {
if (!a || !b) {
return false;
}
- return a.left == b.left && a.width == b.width &&
- a.top == b.top && a.height == b.height;
+ return a.left == b.left && a.width == b.width && a.top == b.top &&
+ a.height == b.height;
};
@@ -33888,7 +31199,8 @@ goog.math.Rect.intersection = function(a, b) {
* @return {boolean} Whether a and b intersect.
*/
goog.math.Rect.intersects = function(a, b) {
- return (a.left <= b.left + b.width && b.left <= a.left + a.width &&
+ return (
+ a.left <= b.left + b.width && b.left <= a.left + a.width &&
a.top <= b.top + b.height && b.top <= a.top + a.height);
};
@@ -34015,14 +31327,12 @@ goog.math.Rect.boundingRect = function(a, b) {
goog.math.Rect.prototype.contains = function(another) {
if (another instanceof goog.math.Rect) {
return this.left <= another.left &&
- this.left + this.width >= another.left + another.width &&
- this.top <= another.top &&
- this.top + this.height >= another.top + another.height;
- } else { // (another instanceof goog.math.Coordinate)
- return another.x >= this.left &&
- another.x <= this.left + this.width &&
- another.y >= this.top &&
- another.y <= this.top + this.height;
+ this.left + this.width >= another.left + another.width &&
+ this.top <= another.top &&
+ this.top + this.height >= another.top + another.height;
+ } else { // (another instanceof goog.math.Coordinate)
+ return another.x >= this.left && another.x <= this.left + this.width &&
+ another.y >= this.top && another.y <= this.top + this.height;
}
};
@@ -34035,9 +31345,10 @@ goog.math.Rect.prototype.contains = function(another) {
*/
goog.math.Rect.prototype.squaredDistance = function(point) {
var dx = point.x < this.left ?
- this.left - point.x : Math.max(point.x - (this.left + this.width), 0);
- var dy = point.y < this.top ?
- this.top - point.y : Math.max(point.y - (this.top + this.height), 0);
+ this.left - point.x :
+ Math.max(point.x - (this.left + this.width), 0);
+ var dy = point.y < this.top ? this.top - point.y :
+ Math.max(point.y - (this.top + this.height), 0);
return dx * dx + dy * dy;
};
@@ -34143,7 +31454,7 @@ goog.math.Rect.prototype.translate = function(tx, opt_ty) {
this.left += tx.x;
this.top += tx.y;
} else {
- this.left += tx;
+ this.left += goog.asserts.assertNumber(tx);
if (goog.isNumber(opt_ty)) {
this.top += opt_ty;
}
@@ -34170,6 +31481,126 @@ goog.math.Rect.prototype.scale = function(sx, opt_sy) {
return this;
};
+// Copyright 2009 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Useful compiler idioms.
+ *
+ * @author johnlenz@google.com (John Lenz)
+ */
+
+goog.provide('goog.reflect');
+
+
+/**
+ * Syntax for object literal casts.
+ * @see http://go/jscompiler-renaming
+ * @see https://goo.gl/CRs09P
+ *
+ * Use this if you have an object literal whose keys need to have the same names
+ * as the properties of some class even after they are renamed by the compiler.
+ *
+ * @param {!Function} type Type to cast to.
+ * @param {Object} object Object literal to cast.
+ * @return {Object} The object literal.
+ */
+goog.reflect.object = function(type, object) {
+ return object;
+};
+
+
+/**
+ * To assert to the compiler that an operation is needed when it would
+ * otherwise be stripped. For example:
+ * <code>
+ * // Force a layout
+ * goog.reflect.sinkValue(dialog.offsetHeight);
+ * </code>
+ * @param {T} x
+ * @return {T}
+ * @template T
+ */
+goog.reflect.sinkValue = function(x) {
+ goog.reflect.sinkValue[' '](x);
+ return x;
+};
+
+
+/**
+ * The compiler should optimize this function away iff no one ever uses
+ * goog.reflect.sinkValue.
+ */
+goog.reflect.sinkValue[' '] = goog.nullFunction;
+
+
+/**
+ * Check if a property can be accessed without throwing an exception.
+ * @param {Object} obj The owner of the property.
+ * @param {string} prop The property name.
+ * @return {boolean} Whether the property is accessible. Will also return true
+ * if obj is null.
+ */
+goog.reflect.canAccessProperty = function(obj, prop) {
+ /** @preserveTry */
+ try {
+ goog.reflect.sinkValue(obj[prop]);
+ return true;
+ } catch (e) {
+ }
+ return false;
+};
+
+
+/**
+ * Retrieves a value from a cache given a key. The compiler provides special
+ * consideration for this call such that it is generally considered side-effect
+ * free. However, if the {@code opt_keyFn} or {@code valueFn} have side-effects
+ * then the entire call is considered to have side-effects.
+ *
+ * Conventionally storing the value on the cache would be considered a
+ * side-effect and preclude unused calls from being pruned, ie. even if
+ * the value was never used, it would still always be stored in the cache.
+ *
+ * Providing a side-effect free {@code valueFn} and {@code opt_keyFn}
+ * allows unused calls to {@code goog.cache} to be pruned.
+ *
+ * @param {!Object<K, V>} cacheObj The object that contains the cached values.
+ * @param {?} key The key to lookup in the cache. If it is not string or number
+ * then a {@code opt_keyFn} should be provided. The key is also used as the
+ * parameter to the {@code valueFn}.
+ * @param {!function(?):V} valueFn The value provider to use to calculate the
+ * value to store in the cache. This function should be side-effect free
+ * to take advantage of the optimization.
+ * @param {function(?):K=} opt_keyFn The key provider to determine the cache
+ * map key. This should be used if the given key is not a string or number.
+ * If not provided then the given key is used. This function should be
+ * side-effect free to take advantage of the optimization.
+ * @return {V} The cached or calculated value.
+ * @template K
+ * @template V
+ */
+goog.reflect.cache = function(cacheObj, key, valueFn, opt_keyFn) {
+ var storedKey = opt_keyFn ? opt_keyFn(key) : key;
+
+ if (storedKey in cacheObj) {
+ return cacheObj[storedKey];
+ }
+
+ return (cacheObj[storedKey] = valueFn(key));
+};
+
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -34203,11 +31634,14 @@ goog.require('goog.dom');
goog.require('goog.dom.NodeType');
goog.require('goog.dom.TagName');
goog.require('goog.dom.vendor');
+goog.require('goog.html.SafeStyleSheet');
+goog.require('goog.html.legacyconversions');
goog.require('goog.math.Box');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Rect');
goog.require('goog.math.Size');
goog.require('goog.object');
+goog.require('goog.reflect');
goog.require('goog.string');
goog.require('goog.userAgent');
@@ -34407,8 +31841,8 @@ goog.style.getCascadedStyle = function(element, style) {
*/
goog.style.getStyle_ = function(element, style) {
return goog.style.getComputedStyle(element, style) ||
- goog.style.getCascadedStyle(element, style) ||
- (element.style && element.style[style]);
+ goog.style.getCascadedStyle(element, style) ||
+ (element.style && element.style[style]);
};
@@ -34631,7 +32065,6 @@ goog.style.getBoundingClientRect_ = function(el) {
// Patch the result in IE only, so that this function can be inlined if
// compiled for non-IE.
if (goog.userAgent.IE && el.ownerDocument.body) {
-
// In IE, most of the time, 2 extra pixels are added to the top and left
// due to the implicit 2-pixel inset border. In IE6/7 quirks mode and
// IE6 standards mode, this border can be overridden by setting the
@@ -34663,6 +32096,7 @@ goog.style.getOffsetParent = function(element) {
// browsers it only includes elements with position absolute, relative or
// fixed, not elements with overflow set to auto or scroll.
if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(8)) {
+ goog.asserts.assert(element && 'offsetParent' in element);
return element.offsetParent;
}
@@ -34672,19 +32106,18 @@ goog.style.getOffsetParent = function(element) {
for (var parent = element.parentNode; parent && parent != doc;
parent = parent.parentNode) {
// Skip shadowDOM roots.
- if (parent.nodeType == goog.dom.NodeType.DOCUMENT_FRAGMENT &&
- parent.host) {
+ if (parent.nodeType == goog.dom.NodeType.DOCUMENT_FRAGMENT && parent.host) {
parent = parent.host;
}
positionStyle =
goog.style.getStyle_(/** @type {!Element} */ (parent), 'position');
skipStatic = skipStatic && positionStyle == 'static' &&
- parent != doc.documentElement && parent != doc.body;
- if (!skipStatic && (parent.scrollWidth > parent.clientWidth ||
- parent.scrollHeight > parent.clientHeight ||
- positionStyle == 'fixed' ||
- positionStyle == 'absolute' ||
- positionStyle == 'relative')) {
+ parent != doc.documentElement && parent != doc.body;
+ if (!skipStatic &&
+ (parent.scrollWidth > parent.clientWidth ||
+ parent.scrollHeight > parent.clientHeight ||
+ positionStyle == 'fixed' || positionStyle == 'absolute' ||
+ positionStyle == 'relative')) {
return /** @type {!Element} */ (parent);
}
}
@@ -34710,7 +32143,7 @@ goog.style.getVisibleRectForElement = function(element) {
// Determine the size of the visible rect by climbing the dom accounting for
// all scrollable containers.
- for (var el = element; el = goog.style.getOffsetParent(el); ) {
+ for (var el = element; el = goog.style.getOffsetParent(el);) {
// clientWidth is zero for inline block elements in IE.
// on WEBKIT, body element can have clientHeight = 0 and scrollHeight > 0
if ((!goog.userAgent.IE || el.clientWidth != 0) &&
@@ -34719,17 +32152,16 @@ goog.style.getVisibleRectForElement = function(element) {
// viewport. In some browsers, el.offsetParent may be
// document.documentElement, so check for that too.
(el != body && el != documentElement &&
- goog.style.getStyle_(el, 'overflow') != 'visible')) {
+ goog.style.getStyle_(el, 'overflow') != 'visible')) {
var pos = goog.style.getPageOffset(el);
var client = goog.style.getClientLeftTop(el);
pos.x += client.x;
pos.y += client.y;
visibleRect.top = Math.max(visibleRect.top, pos.y);
- visibleRect.right = Math.min(visibleRect.right,
- pos.x + el.clientWidth);
- visibleRect.bottom = Math.min(visibleRect.bottom,
- pos.y + el.clientHeight);
+ visibleRect.right = Math.min(visibleRect.right, pos.x + el.clientWidth);
+ visibleRect.bottom =
+ Math.min(visibleRect.bottom, pos.y + el.clientHeight);
visibleRect.left = Math.max(visibleRect.left, pos.x);
}
}
@@ -34742,9 +32174,10 @@ goog.style.getVisibleRectForElement = function(element) {
visibleRect.right = Math.min(visibleRect.right, scrollX + winSize.width);
visibleRect.bottom = Math.min(visibleRect.bottom, scrollY + winSize.height);
return visibleRect.top >= 0 && visibleRect.left >= 0 &&
- visibleRect.bottom > visibleRect.top &&
- visibleRect.right > visibleRect.left ?
- visibleRect : null;
+ visibleRect.bottom > visibleRect.top &&
+ visibleRect.right > visibleRect.left ?
+ visibleRect :
+ null;
};
@@ -34762,8 +32195,8 @@ goog.style.getVisibleRectForElement = function(element) {
* @return {!goog.math.Coordinate} The new scroll position of the container,
* in form of goog.math.Coordinate(scrollLeft, scrollTop).
*/
-goog.style.getContainerOffsetToScrollInto =
- function(element, opt_container, opt_center) {
+goog.style.getContainerOffsetToScrollInto = function(
+ element, opt_container, opt_center) {
var container = opt_container || goog.dom.getDocumentScrollElement();
// Absolute position of the element's border's top left corner.
var elementPos = goog.style.getPageOffset(element);
@@ -34829,8 +32262,8 @@ goog.style.getContainerOffsetToScrollInto =
* @param {boolean=} opt_center Whether to center the element in the container.
* Defaults to false.
*/
-goog.style.scrollIntoContainerView =
- function(element, opt_container, opt_center) {
+goog.style.scrollIntoContainerView = function(
+ element, opt_container, opt_center) {
var container = opt_container || goog.dom.getDocumentScrollElement();
var offset =
goog.style.getContainerOffsetToScrollInto(element, container, opt_center);
@@ -34930,6 +32363,13 @@ goog.style.getFramedPageOffset = function(el, relativeWin) {
// Iterate up the ancestor frame chain, keeping track of the current window
// and the current element in that window.
var currentWin = goog.dom.getWindow(goog.dom.getOwnerDocument(el));
+
+ // MS Edge throws when accessing "parent" if el's containing iframe has been
+ // deleted.
+ if (!goog.reflect.canAccessProperty(currentWin, 'parent')) {
+ return position;
+ }
+
var currentEl = el;
do {
// if we're at the top window, we want to get the page offset.
@@ -34938,15 +32378,14 @@ goog.style.getFramedPageOffset = function(el, relativeWin) {
// the outer window.
var offset = currentWin == relativeWin ?
goog.style.getPageOffset(currentEl) :
- goog.style.getClientPositionForElement_(
- goog.asserts.assert(currentEl));
+ goog.style.getClientPositionForElement_(goog.asserts.assert(currentEl));
position.x += offset.x;
position.y += offset.y;
} while (currentWin && currentWin != relativeWin &&
- currentWin != currentWin.parent &&
- (currentEl = currentWin.frameElement) &&
- (currentWin = currentWin.parent));
+ currentWin != currentWin.parent &&
+ (currentEl = currentWin.frameElement) &&
+ (currentWin = currentWin.parent));
return position;
};
@@ -35025,9 +32464,7 @@ goog.style.getClientPosition = function(el) {
/** @type {!Element} */ (el));
} else {
var targetEvent = el.changedTouches ? el.changedTouches[0] : el;
- return new goog.math.Coordinate(
- targetEvent.clientX,
- targetEvent.clientY);
+ return new goog.math.Coordinate(targetEvent.clientX, targetEvent.clientY);
}
};
@@ -35053,12 +32490,13 @@ goog.style.setPageOffset = function(el, x, opt_y) {
// require us to manually transform between different units
// Work out deltas
- var dx = x - cur.x;
- var dy = opt_y - cur.y;
+ var dx = goog.asserts.assertNumber(x) - cur.x;
+ var dy = Number(opt_y) - cur.y;
// Set position to current left/top + delta
- goog.style.setPosition(el, /** @type {!HTMLElement} */ (el).offsetLeft + dx,
- /** @type {!HTMLElement} */ (el).offsetTop + dy);
+ goog.style.setPosition(
+ el, /** @type {!HTMLElement} */ (el).offsetLeft + dx,
+ /** @type {!HTMLElement} */ (el).offsetTop + dy);
};
@@ -35206,8 +32644,8 @@ goog.style.getSizeWithDisplay_ = function(element) {
// will still return 0 on Webkit prior to 534.8, see
// http://trac.webkit.org/changeset/67252.
var clientRect = goog.style.getBoundingClientRect_(element);
- return new goog.math.Size(clientRect.right - clientRect.left,
- clientRect.bottom - clientRect.top);
+ return new goog.math.Size(
+ clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
}
return new goog.math.Size(offsetWidth, offsetHeight);
};
@@ -35235,8 +32673,8 @@ goog.style.getTransformedSize = function(element) {
var clientRect = goog.style.evaluateWithTemporaryDisplay_(
goog.style.getBoundingClientRect_, element);
- return new goog.math.Size(clientRect.right - clientRect.left,
- clientRect.bottom - clientRect.top);
+ return new goog.math.Size(
+ clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
};
@@ -35283,6 +32721,7 @@ goog.style.toSelectorCase = function(selector) {
* if the opacity is not set.
*/
goog.style.getOpacity = function(el) {
+ goog.asserts.assert(el);
var style = el.style;
var result = '';
if ('opacity' in style) {
@@ -35306,6 +32745,7 @@ goog.style.getOpacity = function(el) {
* {@code ''} to clear the opacity.
*/
goog.style.setOpacity = function(el, alpha) {
+ goog.asserts.assert(el);
var style = el.style;
if ('opacity' in style) {
style.opacity = alpha;
@@ -35316,7 +32756,7 @@ goog.style.setOpacity = function(el, alpha) {
if (alpha === '') {
style.filter = '';
} else {
- style.filter = 'alpha(opacity=' + alpha * 100 + ')';
+ style.filter = 'alpha(opacity=' + (Number(alpha) * 100) + ')';
}
}
};
@@ -35439,14 +32879,30 @@ goog.style.isElementShown = function(el) {
/**
- * Installs the styles string into the window that contains opt_element. If
- * opt_element is null, the main window is used.
+ * Installs the styles string into the window that contains opt_node. If
+ * opt_node is null, the main window is used.
* @param {string} stylesString The style string to install.
* @param {Node=} opt_node Node whose parent document should have the
* styles installed.
- * @return {Element|StyleSheet} The style element created.
+ * @return {!Element|!StyleSheet} The style element created.
+ * @deprecated Use {@link #installSafeStyleSheet} instead.
*/
goog.style.installStyles = function(stylesString, opt_node) {
+ return goog.style.installSafeStyleSheet(
+ goog.html.legacyconversions.safeStyleSheetFromString(stylesString),
+ opt_node);
+};
+
+
+/**
+ * Installs the style sheet into the window that contains opt_node. If
+ * opt_node is null, the main window is used.
+ * @param {!goog.html.SafeStyleSheet} safeStyleSheet The style sheet to install.
+ * @param {?Node=} opt_node Node whose parent document should have the
+ * styles installed.
+ * @return {!Element|!StyleSheet} The style element created.
+ */
+goog.style.installSafeStyleSheet = function(safeStyleSheet, opt_node) {
var dh = goog.dom.getDomHelper(opt_node);
var styleSheet = null;
@@ -35455,7 +32911,7 @@ goog.style.installStyles = function(stylesString, opt_node) {
var doc = dh.getDocument();
if (goog.userAgent.IE && doc.createStyleSheet) {
styleSheet = doc.createStyleSheet();
- goog.style.setStyles(styleSheet, stylesString);
+ goog.style.setSafeStyleSheet(styleSheet, safeStyleSheet);
} else {
var head = dh.getElementsByTagNameAndClass(goog.dom.TagName.HEAD)[0];
@@ -35471,7 +32927,7 @@ goog.style.installStyles = function(stylesString, opt_node) {
// to the head results in a nasty Webkit bug in certain scenarios. Please
// refer to https://bugs.webkit.org/show_bug.cgi?id=26307 for additional
// details.
- goog.style.setStyles(styleSheet, stylesString);
+ goog.style.setSafeStyleSheet(styleSheet, safeStyleSheet);
dh.appendChild(head, styleSheet);
}
return styleSheet;
@@ -35493,21 +32949,39 @@ goog.style.uninstallStyles = function(styleSheet) {
/**
* Sets the content of a style element. The style element can be any valid
* style element. This element will have its content completely replaced by
- * the new stylesString.
+ * the stylesString.
* @param {Element|StyleSheet} element A stylesheet element as returned by
* installStyles.
* @param {string} stylesString The new content of the stylesheet.
+ * @deprecated Use {@link #setSafeStyleSheet} instead.
*/
goog.style.setStyles = function(element, stylesString) {
+ goog.style.setSafeStyleSheet(/** @type {!Element|!StyleSheet} */ (element),
+ goog.html.legacyconversions.safeStyleSheetFromString(stylesString));
+};
+
+
+/**
+ * Sets the content of a style element. The style element can be any valid
+ * style element. This element will have its content completely replaced by
+ * the safeStyleSheet.
+ * @param {!Element|!StyleSheet} element A stylesheet element as returned by
+ * installStyles.
+ * @param {!goog.html.SafeStyleSheet} safeStyleSheet The new content of the
+ * stylesheet.
+ */
+goog.style.setSafeStyleSheet = function(element, safeStyleSheet) {
+ var stylesString = goog.html.SafeStyleSheet.unwrap(safeStyleSheet);
if (goog.userAgent.IE && goog.isDef(element.cssText)) {
// Adding the selectors individually caused the browser to hang if the
// selector was invalid or there were CSS comments. Setting the cssText of
// the style node works fine and ignores CSS that IE doesn't understand.
// However IE >= 11 doesn't support cssText any more, so we make sure that
- // cssText is a defined property and otherwise fall back to innerHTML.
+ // cssText is a defined property and otherwise fall back to setTextContent.
element.cssText = stylesString;
} else {
- element.innerHTML = stylesString;
+ // NOTE: We could also set textContent directly here.
+ goog.dom.setTextContent(/** @type {!Element} */ (element), stylesString);
}
};
@@ -35575,14 +33049,14 @@ goog.style.isRightToLeft = function(el) {
/**
* The CSS style property corresponding to an element being
* unselectable on the current browser platform (null if none).
- * Opera and IE instead use a DOM attribute 'unselectable'.
+ * Opera and IE instead use a DOM attribute 'unselectable'. MS Edge uses
+ * the Webkit prefix.
* @type {?string}
* @private
*/
-goog.style.unselectableStyle_ =
- goog.userAgent.GECKO ? 'MozUserSelect' :
- goog.userAgent.WEBKIT ? 'WebkitUserSelect' :
- null;
+goog.style.unselectableStyle_ = goog.userAgent.GECKO ?
+ 'MozUserSelect' :
+ goog.userAgent.WEBKIT || goog.userAgent.EDGE ? 'WebkitUserSelect' : null;
/**
@@ -35668,17 +33142,16 @@ goog.style.setBorderBoxSize = function(element, size) {
var doc = goog.dom.getOwnerDocument(element);
var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode();
- if (goog.userAgent.IE &&
- !goog.userAgent.isVersionOrHigher('10') &&
+ if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10') &&
(!isCss1CompatMode || !goog.userAgent.isVersionOrHigher('8'))) {
var style = element.style;
if (isCss1CompatMode) {
var paddingBox = goog.style.getPaddingBox(element);
var borderBox = goog.style.getBorderBox(element);
style.pixelWidth = size.width - borderBox.left - paddingBox.left -
- paddingBox.right - borderBox.right;
+ paddingBox.right - borderBox.right;
style.pixelHeight = size.height - borderBox.top - paddingBox.top -
- paddingBox.bottom - borderBox.bottom;
+ paddingBox.bottom - borderBox.bottom;
} else {
style.pixelWidth = size.width;
style.pixelHeight = size.height;
@@ -35698,27 +33171,25 @@ goog.style.setBorderBoxSize = function(element, size) {
goog.style.getContentBoxSize = function(element) {
var doc = goog.dom.getOwnerDocument(element);
var ieCurrentStyle = goog.userAgent.IE && element.currentStyle;
- if (ieCurrentStyle &&
- goog.dom.getDomHelper(doc).isCss1CompatMode() &&
+ if (ieCurrentStyle && goog.dom.getDomHelper(doc).isCss1CompatMode() &&
ieCurrentStyle.width != 'auto' && ieCurrentStyle.height != 'auto' &&
!ieCurrentStyle.boxSizing) {
// If IE in CSS1Compat mode than just use the width and height.
// If we have a boxSizing then fall back on measuring the borders etc.
- var width = goog.style.getIePixelValue_(element, ieCurrentStyle.width,
- 'width', 'pixelWidth');
- var height = goog.style.getIePixelValue_(element, ieCurrentStyle.height,
- 'height', 'pixelHeight');
+ var width = goog.style.getIePixelValue_(
+ element, ieCurrentStyle.width, 'width', 'pixelWidth');
+ var height = goog.style.getIePixelValue_(
+ element, ieCurrentStyle.height, 'height', 'pixelHeight');
return new goog.math.Size(width, height);
} else {
var borderBoxSize = goog.style.getBorderBoxSize(element);
var paddingBox = goog.style.getPaddingBox(element);
var borderBox = goog.style.getBorderBox(element);
- return new goog.math.Size(borderBoxSize.width -
- borderBox.left - paddingBox.left -
- paddingBox.right - borderBox.right,
- borderBoxSize.height -
- borderBox.top - paddingBox.top -
- paddingBox.bottom - borderBox.bottom);
+ return new goog.math.Size(
+ borderBoxSize.width - borderBox.left - paddingBox.left -
+ paddingBox.right - borderBox.right,
+ borderBoxSize.height - borderBox.top - paddingBox.top -
+ paddingBox.bottom - borderBox.bottom);
}
};
@@ -35732,8 +33203,7 @@ goog.style.getContentBoxSize = function(element) {
goog.style.setContentBoxSize = function(element, size) {
var doc = goog.dom.getOwnerDocument(element);
var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode();
- if (goog.userAgent.IE &&
- !goog.userAgent.isVersionOrHigher('10') &&
+ if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10') &&
(!isCss1CompatMode || !goog.userAgent.isVersionOrHigher('8'))) {
var style = element.style;
if (isCss1CompatMode) {
@@ -35743,9 +33213,9 @@ goog.style.setContentBoxSize = function(element, size) {
var paddingBox = goog.style.getPaddingBox(element);
var borderBox = goog.style.getBorderBox(element);
style.pixelWidth = size.width + borderBox.left + paddingBox.left +
- paddingBox.right + borderBox.right;
+ paddingBox.right + borderBox.right;
style.pixelHeight = size.height + borderBox.top + paddingBox.top +
- paddingBox.bottom + borderBox.bottom;
+ paddingBox.bottom + borderBox.bottom;
}
} else {
goog.style.setBoxSizingSize_(element, size, 'content-box');
@@ -35820,7 +33290,8 @@ goog.style.getIePixelValue_ = function(element, value, name, pixelName) {
goog.style.getIePixelDistance_ = function(element, propName) {
var value = goog.style.getCascadedStyle(element, propName);
return value ?
- goog.style.getIePixelValue_(element, value, 'left', 'pixelLeft') : 0;
+ goog.style.getIePixelValue_(element, value, 'left', 'pixelLeft') :
+ 0;
};
@@ -35837,8 +33308,8 @@ goog.style.getBox_ = function(element, stylePrefix) {
var left = goog.style.getIePixelDistance_(element, stylePrefix + 'Left');
var right = goog.style.getIePixelDistance_(element, stylePrefix + 'Right');
var top = goog.style.getIePixelDistance_(element, stylePrefix + 'Top');
- var bottom = goog.style.getIePixelDistance_(
- element, stylePrefix + 'Bottom');
+ var bottom =
+ goog.style.getIePixelDistance_(element, stylePrefix + 'Bottom');
return new goog.math.Box(top, right, bottom, left);
} else {
// On non-IE browsers, getComputedStyle is always non-null.
@@ -35849,10 +33320,9 @@ goog.style.getBox_ = function(element, stylePrefix) {
// NOTE(arv): Gecko can return floating point numbers for the computed
// style values.
- return new goog.math.Box(parseFloat(top),
- parseFloat(right),
- parseFloat(bottom),
- parseFloat(left));
+ return new goog.math.Box(
+ parseFloat(top), parseFloat(right), parseFloat(bottom),
+ parseFloat(left));
}
};
@@ -35879,7 +33349,7 @@ goog.style.getMarginBox = function(element) {
/**
* A map used to map the border width keywords to a pixel width.
- * @type {Object}
+ * @type {!Object}
* @private
*/
goog.style.ieBorderWidthKeywords_ = {
@@ -35927,10 +33397,9 @@ goog.style.getBorderBox = function(element) {
var top = goog.style.getComputedStyle(element, 'borderTopWidth');
var bottom = goog.style.getComputedStyle(element, 'borderBottomWidth');
- return new goog.math.Box(parseFloat(top),
- parseFloat(right),
- parseFloat(bottom),
- parseFloat(left));
+ return new goog.math.Box(
+ parseFloat(top), parseFloat(right), parseFloat(bottom),
+ parseFloat(left));
}
};
@@ -36002,15 +33471,15 @@ goog.style.getLengthUnits = function(value) {
/**
* Map of absolute CSS length units
- * @type {Object}
+ * @type {!Object}
* @private
*/
goog.style.ABSOLUTE_CSS_LENGTH_UNITS_ = {
- 'cm' : 1,
- 'in' : 1,
- 'mm' : 1,
- 'pc' : 1,
- 'pt' : 1
+ 'cm': 1,
+ 'in': 1,
+ 'mm': 1,
+ 'pc': 1,
+ 'pt': 1
};
@@ -36018,12 +33487,12 @@ goog.style.ABSOLUTE_CSS_LENGTH_UNITS_ = {
* Map of relative CSS length units that can be accurately converted to px
* font-size values using getIePixelValue_. Only units that are defined in
* relation to a font size are convertible (%, small, etc. are not).
- * @type {Object}
+ * @type {!Object}
* @private
*/
goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_ = {
- 'em' : 1,
- 'ex' : 1
+ 'em': 1,
+ 'ex': 1
};
@@ -36049,25 +33518,20 @@ goog.style.getFontSize = function(el) {
// (em, ex) are applied relative to the element's parentNode and can also
// be converted.
if (goog.userAgent.IE) {
- if (sizeUnits in goog.style.ABSOLUTE_CSS_LENGTH_UNITS_) {
- return goog.style.getIePixelValue_(el,
- fontSize,
- 'left',
- 'pixelLeft');
- } else if (el.parentNode &&
- el.parentNode.nodeType == goog.dom.NodeType.ELEMENT &&
- sizeUnits in goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_) {
+ if (String(sizeUnits) in goog.style.ABSOLUTE_CSS_LENGTH_UNITS_) {
+ return goog.style.getIePixelValue_(el, fontSize, 'left', 'pixelLeft');
+ } else if (
+ el.parentNode && el.parentNode.nodeType == goog.dom.NodeType.ELEMENT &&
+ String(sizeUnits) in goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_) {
// Check the parent size - if it is the same it means the relative size
// value is inherited and we therefore don't want to count it twice. If
// it is different, this element either has explicit style or has a CSS
// rule applying to it.
var parentElement = /** @type {!Element} */ (el.parentNode);
var parentSize = goog.style.getStyle_(parentElement, 'fontSize');
- return goog.style.getIePixelValue_(parentElement,
- fontSize == parentSize ?
- '1em' : fontSize,
- 'left',
- 'pixelLeft');
+ return goog.style.getIePixelValue_(
+ parentElement, fontSize == parentSize ? '1em' : fontSize, 'left',
+ 'pixelLeft');
}
}
@@ -36076,10 +33540,10 @@ goog.style.getFontSize = function(el) {
// an invisible, absolutely-positioned span sized to be the height of an 'M'
// rendered in its parent's (i.e., our target element's) font size. This is
// the definition of CSS's font size attribute.
- var sizeElement = goog.dom.createDom(
- goog.dom.TagName.SPAN,
- {'style': 'visibility:hidden;position:absolute;' +
- 'line-height:0;padding:0;margin:0;border:0;height:1em;'});
+ var sizeElement = goog.dom.createDom(goog.dom.TagName.SPAN, {
+ 'style': 'visibility:hidden;position:absolute;' +
+ 'line-height:0;padding:0;margin:0;border:0;height:1em;'
+ });
goog.dom.appendChild(el, sizeElement);
fontSize = sizeElement.offsetHeight;
goog.dom.removeNode(sizeElement);
@@ -36182,10 +33646,10 @@ goog.style.getScrollbarWidth = function(opt_className) {
* @const
* @private
*/
-goog.style.MATRIX_TRANSLATION_REGEX_ =
- new RegExp('matrix\\([0-9\\.\\-]+, [0-9\\.\\-]+, ' +
- '[0-9\\.\\-]+, [0-9\\.\\-]+, ' +
- '([0-9\\.\\-]+)p?x?, ([0-9\\.\\-]+)p?x?\\)');
+goog.style.MATRIX_TRANSLATION_REGEX_ = new RegExp(
+ 'matrix\\([0-9\\.\\-]+, [0-9\\.\\-]+, ' +
+ '[0-9\\.\\-]+, [0-9\\.\\-]+, ' +
+ '([0-9\\.\\-]+)p?x?, ([0-9\\.\\-]+)p?x?\\)');
/**
@@ -36204,14 +33668,14 @@ goog.style.getCssTranslation = function(element) {
if (!matches) {
return new goog.math.Coordinate(0, 0);
}
- return new goog.math.Coordinate(parseFloat(matches[1]),
- parseFloat(matches[2]));
+ return new goog.math.Coordinate(
+ parseFloat(matches[1]), parseFloat(matches[2]));
};
goog.provide('ol.MapEvent');
goog.provide('ol.MapEventType');
-goog.require('goog.events.Event');
+goog.require('ol.events.Event');
/**
@@ -36236,14 +33700,13 @@ ol.MapEventType = {
};
-
/**
* @classdesc
* Events emitted as map events are instances of this type.
* See {@link ol.Map} for which events trigger a map event.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.MapEvent}
* @param {string} type Event type.
* @param {ol.Map} map Map.
@@ -36268,18 +33731,17 @@ ol.MapEvent = function(type, map, opt_frameState) {
this.frameState = opt_frameState !== undefined ? opt_frameState : null;
};
-goog.inherits(ol.MapEvent, goog.events.Event);
+goog.inherits(ol.MapEvent, ol.events.Event);
goog.provide('ol.control.Control');
goog.require('goog.dom');
-goog.require('goog.events');
+goog.require('ol.events');
goog.require('ol');
goog.require('ol.MapEventType');
goog.require('ol.Object');
-
/**
* @classdesc
* A control is a visible widget with a DOM element in a fixed position on the
@@ -36333,7 +33795,7 @@ ol.control.Control = function(options) {
/**
* @protected
- * @type {!Array.<?number>}
+ * @type {!Array.<ol.events.Key>}
*/
this.listenerKeys = [];
@@ -36380,18 +33842,18 @@ ol.control.Control.prototype.setMap = function(map) {
if (this.map_) {
goog.dom.removeNode(this.element);
}
- if (this.listenerKeys.length > 0) {
- this.listenerKeys.forEach(goog.events.unlistenByKey);
- this.listenerKeys.length = 0;
+ for (var i = 0, ii = this.listenerKeys.length; i < ii; ++i) {
+ ol.events.unlistenByKey(this.listenerKeys[i]);
}
+ this.listenerKeys.length = 0;
this.map_ = map;
if (this.map_) {
var target = this.target_ ?
this.target_ : map.getOverlayContainerStopEvent();
target.appendChild(this.element);
if (this.render !== ol.nullFunction) {
- this.listenerKeys.push(goog.events.listen(map,
- ol.MapEventType.POSTRENDER, this.render, false, this));
+ this.listenerKeys.push(ol.events.listen(map,
+ ol.MapEventType.POSTRENDER, this.render, this));
}
map.render();
}
@@ -36452,8 +33914,7 @@ ol.css.CLASS_CONTROL = 'ol-control';
goog.provide('ol.structs.LRUCache');
goog.require('goog.asserts');
-goog.require('goog.object');
-
+goog.require('ol.object');
/**
@@ -36474,19 +33935,19 @@ ol.structs.LRUCache = function() {
/**
* @private
- * @type {Object.<string, ol.structs.LRUCacheEntry>}
+ * @type {!Object.<string, ol.LRUCacheEntry>}
*/
this.entries_ = {};
/**
* @private
- * @type {?ol.structs.LRUCacheEntry}
+ * @type {?ol.LRUCacheEntry}
*/
this.oldest_ = null;
/**
* @private
- * @type {?ol.structs.LRUCacheEntry}
+ * @type {?ol.LRUCacheEntry}
*/
this.newest_ = null;
@@ -36498,14 +33959,14 @@ ol.structs.LRUCache = function() {
*/
ol.structs.LRUCache.prototype.assertValid = function() {
if (this.count_ === 0) {
- goog.asserts.assert(goog.object.isEmpty(this.entries_),
+ goog.asserts.assert(ol.object.isEmpty(this.entries_),
'entries must be an empty object (count = 0)');
goog.asserts.assert(!this.oldest_,
'oldest must be null (count = 0)');
goog.asserts.assert(!this.newest_,
'newest must be null (count = 0)');
} else {
- goog.asserts.assert(goog.object.getCount(this.entries_) == this.count_,
+ goog.asserts.assert(Object.keys(this.entries_).length == this.count_,
'number of entries matches count');
goog.asserts.assert(this.oldest_,
'we have an oldest entry');
@@ -36712,24 +34173,156 @@ ol.structs.LRUCache.prototype.set = function(key, value) {
++this.count_;
};
+goog.provide('ol.tilecoord');
+
+goog.require('goog.asserts');
+goog.require('ol.extent');
+
/**
- * @typedef {{key_: string,
- * newer: ol.structs.LRUCacheEntry,
- * older: ol.structs.LRUCacheEntry,
- * value_: *}}
+ * @enum {number}
*/
-ol.structs.LRUCacheEntry;
+ol.QuadKeyCharCode = {
+ ZERO: '0'.charCodeAt(0),
+ ONE: '1'.charCodeAt(0),
+ TWO: '2'.charCodeAt(0),
+ THREE: '3'.charCodeAt(0)
+};
+
+
+/**
+ * @param {string} str String that follows pattern “z/x/y” where x, y and z are
+ * numbers.
+ * @return {ol.TileCoord} Tile coord.
+ */
+ol.tilecoord.createFromString = function(str) {
+ var v = str.split('/');
+ goog.asserts.assert(v.length === 3,
+ 'must provide a string in "z/x/y" format, got "%s"', str);
+ return v.map(function(e) {
+ return parseInt(e, 10);
+ });
+};
+
+
+/**
+ * @param {number} z Z.
+ * @param {number} x X.
+ * @param {number} y Y.
+ * @param {ol.TileCoord=} opt_tileCoord Tile coordinate.
+ * @return {ol.TileCoord} Tile coordinate.
+ */
+ol.tilecoord.createOrUpdate = function(z, x, y, opt_tileCoord) {
+ if (opt_tileCoord !== undefined) {
+ opt_tileCoord[0] = z;
+ opt_tileCoord[1] = x;
+ opt_tileCoord[2] = y;
+ return opt_tileCoord;
+ } else {
+ return [z, x, y];
+ }
+};
+
+
+/**
+ * @param {number} z Z.
+ * @param {number} x X.
+ * @param {number} y Y.
+ * @return {string} Key.
+ */
+ol.tilecoord.getKeyZXY = function(z, x, y) {
+ return z + '/' + x + '/' + y;
+};
+
+
+/**
+ * @param {ol.TileCoord} tileCoord Tile coord.
+ * @return {number} Hash.
+ */
+ol.tilecoord.hash = function(tileCoord) {
+ return (tileCoord[1] << tileCoord[0]) + tileCoord[2];
+};
+
+
+/**
+ * @param {ol.TileCoord} tileCoord Tile coord.
+ * @return {string} Quad key.
+ */
+ol.tilecoord.quadKey = function(tileCoord) {
+ var z = tileCoord[0];
+ var digits = new Array(z);
+ var mask = 1 << (z - 1);
+ var i, charCode;
+ for (i = 0; i < z; ++i) {
+ charCode = ol.QuadKeyCharCode.ZERO;
+ if (tileCoord[1] & mask) {
+ charCode += 1;
+ }
+ if (tileCoord[2] & mask) {
+ charCode += 2;
+ }
+ digits[i] = String.fromCharCode(charCode);
+ mask >>= 1;
+ }
+ return digits.join('');
+};
+
+
+/**
+ * @param {ol.TileCoord} tileCoord Tile coordinate.
+ * @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
+ * @param {ol.proj.Projection} projection Projection.
+ * @return {ol.TileCoord} Tile coordinate.
+ */
+ol.tilecoord.wrapX = function(tileCoord, tileGrid, projection) {
+ var z = tileCoord[0];
+ var center = tileGrid.getTileCoordCenter(tileCoord);
+ var projectionExtent = ol.tilegrid.extentFromProjection(projection);
+ if (!ol.extent.containsCoordinate(projectionExtent, center)) {
+ var worldWidth = ol.extent.getWidth(projectionExtent);
+ var worldsAway = Math.ceil((projectionExtent[0] - center[0]) / worldWidth);
+ center[0] += worldWidth * worldsAway;
+ return tileGrid.getTileCoordForCoordAndZ(center, z);
+ } else {
+ return tileCoord;
+ }
+};
+
+
+/**
+ * @param {ol.TileCoord} tileCoord Tile coordinate.
+ * @param {!ol.tilegrid.TileGrid} tileGrid Tile grid.
+ * @return {boolean} Tile coordinate is within extent and zoom level range.
+ */
+ol.tilecoord.withinExtentAndZ = function(tileCoord, tileGrid) {
+ var z = tileCoord[0];
+ var x = tileCoord[1];
+ var y = tileCoord[2];
+
+ if (tileGrid.getMinZoom() > z || z > tileGrid.getMaxZoom()) {
+ return false;
+ }
+ var extent = tileGrid.getExtent();
+ var tileRange;
+ if (!extent) {
+ tileRange = tileGrid.getFullTileRange(z);
+ } else {
+ tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
+ }
+ if (!tileRange) {
+ return true;
+ } else {
+ return tileRange.containsXY(x, y);
+ }
+};
goog.provide('ol.TileCache');
-goog.require('ol');
goog.require('ol.TileRange');
goog.require('ol.structs.LRUCache');
goog.require('ol.tilecoord');
-
/**
* @constructor
* @extends {ol.structs.LRUCache.<ol.Tile>}
@@ -36744,8 +34337,7 @@ ol.TileCache = function(opt_highWaterMark) {
* @private
* @type {number}
*/
- this.highWaterMark_ = opt_highWaterMark !== undefined ?
- opt_highWaterMark : ol.DEFAULT_TILE_CACHE_HIGH_WATER_MARK;
+ this.highWaterMark_ = opt_highWaterMark !== undefined ? opt_highWaterMark : 2048;
};
goog.inherits(ol.TileCache, ol.structs.LRUCache);
@@ -36796,10 +34388,9 @@ ol.TileCache.prototype.pruneTileRange = function(tileRange) {
goog.provide('ol.Tile');
goog.provide('ol.TileState');
-goog.require('goog.events');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
-goog.require('ol.TileCoord');
+goog.require('ol.events');
+goog.require('ol.events.EventTarget');
+goog.require('ol.events.EventType');
/**
@@ -36810,17 +34401,17 @@ ol.TileState = {
LOADING: 1,
LOADED: 2,
ERROR: 3,
- EMPTY: 4
+ EMPTY: 4,
+ ABORT: 5
};
-
/**
* @classdesc
* Base class for tiles.
*
* @constructor
- * @extends {goog.events.EventTarget}
+ * @extends {ol.events.EventTarget}
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {ol.TileState} state State.
*/
@@ -36856,14 +34447,14 @@ ol.Tile = function(tileCoord, state) {
this.key = '';
};
-goog.inherits(ol.Tile, goog.events.EventTarget);
+goog.inherits(ol.Tile, ol.events.EventTarget);
/**
* @protected
*/
ol.Tile.prototype.changed = function() {
- this.dispatchEvent(goog.events.EventType.CHANGE);
+ this.dispatchEvent(ol.events.EventType.CHANGE);
};
@@ -36886,7 +34477,7 @@ ol.Tile.prototype.getKey = function() {
/**
* Get the tile coordinate for this tile.
- * @return {ol.TileCoord}
+ * @return {ol.TileCoord} The tile coordinate.
* @api
*/
ol.Tile.prototype.getTileCoord = function() {
@@ -36907,6 +34498,91 @@ ol.Tile.prototype.getState = function() {
*/
ol.Tile.prototype.load = goog.abstractMethod;
+goog.provide('ol.size');
+
+
+goog.require('goog.asserts');
+
+
+/**
+ * Returns a buffered size.
+ * @param {ol.Size} size Size.
+ * @param {number} buffer Buffer.
+ * @param {ol.Size=} opt_size Optional reusable size array.
+ * @return {ol.Size} The buffered size.
+ */
+ol.size.buffer = function(size, buffer, opt_size) {
+ if (opt_size === undefined) {
+ opt_size = [0, 0];
+ }
+ opt_size[0] = size[0] + 2 * buffer;
+ opt_size[1] = size[1] + 2 * buffer;
+ return opt_size;
+};
+
+
+/**
+ * Compares sizes for equality.
+ * @param {ol.Size} a Size.
+ * @param {ol.Size} b Size.
+ * @return {boolean} Equals.
+ */
+ol.size.equals = function(a, b) {
+ return a[0] == b[0] && a[1] == b[1];
+};
+
+
+/**
+ * Determines if a size has a positive area.
+ * @param {ol.Size} size The size to test.
+ * @return {boolean} The size has a positive area.
+ */
+ol.size.hasArea = function(size) {
+ return size[0] > 0 && size[1] > 0;
+};
+
+
+/**
+ * Returns a size scaled by a ratio. The result will be an array of integers.
+ * @param {ol.Size} size Size.
+ * @param {number} ratio Ratio.
+ * @param {ol.Size=} opt_size Optional reusable size array.
+ * @return {ol.Size} The scaled size.
+ */
+ol.size.scale = function(size, ratio, opt_size) {
+ if (opt_size === undefined) {
+ opt_size = [0, 0];
+ }
+ opt_size[0] = (size[0] * ratio + 0.5) | 0;
+ opt_size[1] = (size[1] * ratio + 0.5) | 0;
+ return opt_size;
+};
+
+
+/**
+ * Returns an `ol.Size` array for the passed in number (meaning: square) or
+ * `ol.Size` array.
+ * (meaning: non-square),
+ * @param {number|ol.Size} size Width and height.
+ * @param {ol.Size=} opt_size Optional reusable size array.
+ * @return {ol.Size} Size.
+ * @api stable
+ */
+ol.size.toSize = function(size, opt_size) {
+ if (Array.isArray(size)) {
+ return size;
+ } else {
+ goog.asserts.assert(goog.isNumber(size));
+ if (opt_size === undefined) {
+ opt_size = [size, size];
+ } else {
+ opt_size[0] = size;
+ opt_size[1] = size;
+ }
+ return opt_size;
+ }
+};
+
goog.provide('ol.source.Source');
goog.provide('ol.source.State');
@@ -36930,17 +34606,6 @@ ol.source.State = {
/**
- * @typedef {{attributions: (Array.<ol.Attribution>|undefined),
- * logo: (string|olx.LogoOptions|undefined),
- * projection: ol.proj.ProjectionLike,
- * state: (ol.source.State|undefined),
- * wrapX: (boolean|undefined)}}
- */
-ol.source.SourceOptions;
-
-
-
-/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
* instantiated in apps.
@@ -36950,7 +34615,7 @@ ol.source.SourceOptions;
*
* @constructor
* @extends {ol.Object}
- * @param {ol.source.SourceOptions} options Source options.
+ * @param {ol.SourceSourceOptions} options Source options.
* @api stable
*/
ol.source.Source = function(options) {
@@ -36967,8 +34632,7 @@ ol.source.Source = function(options) {
* @private
* @type {Array.<ol.Attribution>}
*/
- this.attributions_ = options.attributions !== undefined ?
- options.attributions : null;
+ this.attributions_ = ol.source.Source.toAttributionsArray_(options.attributions);
/**
* @private
@@ -36992,6 +34656,37 @@ ol.source.Source = function(options) {
};
goog.inherits(ol.source.Source, ol.Object);
+/**
+ * Turns various ways of defining an attribution to an array of `ol.Attributions`.
+ *
+ * @param {ol.AttributionLike|undefined}
+ * attributionLike The attributions as string, array of strings,
+ * `ol.Attribution`, array of `ol.Attribution` or undefined.
+ * @return {Array.<ol.Attribution>} The array of `ol.Attribution` or null if
+ * `undefined` was given.
+ */
+ol.source.Source.toAttributionsArray_ = function(attributionLike) {
+ if (typeof attributionLike === 'string') {
+ return [new ol.Attribution({html: attributionLike})];
+ } else if (attributionLike instanceof ol.Attribution) {
+ return [attributionLike];
+ } else if (Array.isArray(attributionLike)) {
+ var len = attributionLike.length;
+ var attributions = new Array(len);
+ for (var i = 0; i < len; i++) {
+ var item = attributionLike[i];
+ if (typeof item === 'string') {
+ attributions[i] = new ol.Attribution({html: item});
+ } else {
+ attributions[i] = item;
+ }
+ }
+ return attributions;
+ } else {
+ return null;
+ }
+}
+
/**
* @param {ol.Coordinate} coordinate Coordinate.
@@ -37061,12 +34756,23 @@ ol.source.Source.prototype.getWrapX = function() {
/**
+ * Refreshes the source and finally dispatches a 'change' event.
+ * @api
+ */
+ol.source.Source.prototype.refresh = function() {
+ this.changed();
+};
+
+
+/**
* Set the attributions of the source.
- * @param {Array.<ol.Attribution>} attributions Attributions.
+ * @param {ol.AttributionLike|undefined} attributions Attributions.
+ * Can be passed as `string`, `Array<string>`, `{@link ol.Attribution}`,
+ * `Array<{@link ol.Attribution}>` or `undefined`.
* @api
*/
ol.source.Source.prototype.setAttributions = function(attributions) {
- this.attributions_ = attributions;
+ this.attributions_ = ol.source.Source.toAttributionsArray_(attributions);
this.changed();
};
@@ -37090,28 +34796,16 @@ ol.source.Source.prototype.setState = function(state) {
this.changed();
};
-
-/**
- * Set the projection of the source.
- * @param {ol.proj.Projection} projection Projection.
- */
-ol.source.Source.prototype.setProjection = function(projection) {
- this.projection_ = projection;
-};
-
goog.provide('ol.tilegrid.TileGrid');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('ol');
-goog.require('ol.Coordinate');
-goog.require('ol.TileCoord');
goog.require('ol.TileRange');
goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.extent.Corner');
goog.require('ol.math');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.proj.METERS_PER_UNIT');
goog.require('ol.proj.Projection');
@@ -37120,7 +34814,6 @@ goog.require('ol.size');
goog.require('ol.tilecoord');
-
/**
* @classdesc
* Base class for setting the grid pattern for sources accessing tiled-image
@@ -37144,7 +34837,7 @@ ol.tilegrid.TileGrid = function(options) {
* @type {!Array.<number>}
*/
this.resolutions_ = options.resolutions;
- goog.asserts.assert(goog.array.isSorted(this.resolutions_, function(a, b) {
+ goog.asserts.assert(ol.array.isSorted(this.resolutions_, function(a, b) {
return b - a;
}, true), 'resolutions must be sorted in descending order');
@@ -37219,6 +34912,12 @@ ol.tilegrid.TileGrid = function(options) {
*/
this.fullTileRanges_ = null;
+ /**
+ * @private
+ * @type {ol.Size}
+ */
+ this.tmpSize_ = [0, 0];
+
if (options.sizes !== undefined) {
goog.asserts.assert(options.sizes.length == this.resolutions_.length,
'number of sizes and resolutions must be equal');
@@ -37239,12 +34938,6 @@ ol.tilegrid.TileGrid = function(options) {
this.calculateTileRanges_(extent);
}
- /**
- * @private
- * @type {ol.Size}
- */
- this.tmpSize_ = [0, 0];
-
};
@@ -37264,8 +34957,7 @@ ol.tilegrid.TileGrid.tmpTileCoord_ = [0, 0, 0];
* @return {boolean} Callback succeeded.
* @template T
*/
-ol.tilegrid.TileGrid.prototype.forEachTileCoordParentTileRange =
- function(tileCoord, callback, opt_this, opt_tileRange, opt_extent) {
+ol.tilegrid.TileGrid.prototype.forEachTileCoordParentTileRange = function(tileCoord, callback, opt_this, opt_tileRange, opt_extent) {
var tileCoordExtent = this.getTileCoordExtent(tileCoord, opt_extent);
var z = tileCoord[0] - 1;
while (z >= this.minZoom) {
@@ -37358,8 +35050,7 @@ ol.tilegrid.TileGrid.prototype.getResolutions = function() {
* @param {ol.Extent=} opt_extent Temporary ol.Extent object.
* @return {ol.TileRange} Tile range.
*/
-ol.tilegrid.TileGrid.prototype.getTileCoordChildTileRange =
- function(tileCoord, opt_tileRange, opt_extent) {
+ol.tilegrid.TileGrid.prototype.getTileCoordChildTileRange = function(tileCoord, opt_tileRange, opt_extent) {
if (tileCoord[0] < this.maxZoom) {
var tileCoordExtent = this.getTileCoordExtent(tileCoord, opt_extent);
return this.getTileRangeForExtentAndZ(
@@ -37376,8 +35067,7 @@ ol.tilegrid.TileGrid.prototype.getTileCoordChildTileRange =
* @param {ol.Extent=} opt_extent Temporary ol.Extent object.
* @return {ol.Extent} Extent.
*/
-ol.tilegrid.TileGrid.prototype.getTileRangeExtent =
- function(z, tileRange, opt_extent) {
+ol.tilegrid.TileGrid.prototype.getTileRangeExtent = function(z, tileRange, opt_extent) {
var origin = this.getOrigin(z);
var resolution = this.getResolution(z);
var tileSize = ol.size.toSize(this.getTileSize(z), this.tmpSize_);
@@ -37395,8 +35085,7 @@ ol.tilegrid.TileGrid.prototype.getTileRangeExtent =
* @param {ol.TileRange=} opt_tileRange Temporary tile range object.
* @return {ol.TileRange} Tile range.
*/
-ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndResolution =
- function(extent, resolution, opt_tileRange) {
+ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndResolution = function(extent, resolution, opt_tileRange) {
var tileCoord = ol.tilegrid.TileGrid.tmpTileCoord_;
this.getTileCoordForXYAndResolution_(
extent[0], extent[1], resolution, false, tileCoord);
@@ -37415,8 +35104,7 @@ ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndResolution =
* @param {ol.TileRange=} opt_tileRange Temporary tile range object.
* @return {ol.TileRange} Tile range.
*/
-ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndZ =
- function(extent, z, opt_tileRange) {
+ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndZ = function(extent, z, opt_tileRange) {
var resolution = this.getResolution(z);
return this.getTileRangeForExtentAndResolution(
extent, resolution, opt_tileRange);
@@ -37446,8 +35134,7 @@ ol.tilegrid.TileGrid.prototype.getTileCoordCenter = function(tileCoord) {
* @return {ol.Extent} Extent.
* @api
*/
-ol.tilegrid.TileGrid.prototype.getTileCoordExtent =
- function(tileCoord, opt_extent) {
+ol.tilegrid.TileGrid.prototype.getTileCoordExtent = function(tileCoord, opt_extent) {
var origin = this.getOrigin(tileCoord[0]);
var resolution = this.getResolution(tileCoord[0]);
var tileSize = ol.size.toSize(this.getTileSize(tileCoord[0]), this.tmpSize_);
@@ -37470,8 +35157,7 @@ ol.tilegrid.TileGrid.prototype.getTileCoordExtent =
* @return {ol.TileCoord} Tile coordinate.
* @api
*/
-ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution =
- function(coordinate, resolution, opt_tileCoord) {
+ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution = function(coordinate, resolution, opt_tileCoord) {
return this.getTileCoordForXYAndResolution_(
coordinate[0], coordinate[1], resolution, false, opt_tileCoord);
};
@@ -37522,8 +35208,7 @@ ol.tilegrid.TileGrid.prototype.getTileCoordForXYAndResolution_ = function(
* @return {ol.TileCoord} Tile coordinate.
* @api
*/
-ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndZ =
- function(coordinate, z, opt_tileCoord) {
+ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndZ = function(coordinate, z, opt_tileCoord) {
var resolution = this.getResolution(z);
return this.getTileCoordForXYAndResolution_(
coordinate[0], coordinate[1], resolution, false, opt_tileCoord);
@@ -37583,10 +35268,15 @@ ol.tilegrid.TileGrid.prototype.getFullTileRange = function(z) {
/**
* @param {number} resolution Resolution.
+ * @param {number=} opt_direction If 0, the nearest resolution will be used.
+ * If 1, the nearest lower resolution will be used. If -1, the nearest
+ * higher resolution will be used. Default is 0.
* @return {number} Z.
*/
-ol.tilegrid.TileGrid.prototype.getZForResolution = function(resolution) {
- var z = ol.array.linearFindNearest(this.resolutions_, resolution, 0);
+ol.tilegrid.TileGrid.prototype.getZForResolution = function(
+ resolution, opt_direction) {
+ var z = ol.array.linearFindNearest(this.resolutions_, resolution,
+ opt_direction || 0);
return ol.math.clamp(z, this.minZoom, this.maxZoom);
};
@@ -37629,8 +35319,7 @@ ol.tilegrid.getForProjection = function(projection) {
* ol.extent.Corner.TOP_LEFT).
* @return {ol.tilegrid.TileGrid} TileGrid instance.
*/
-ol.tilegrid.createForExtent =
- function(extent, opt_maxZoom, opt_tileSize, opt_corner) {
+ol.tilegrid.createForExtent = function(extent, opt_maxZoom, opt_tileSize, opt_corner) {
var corner = opt_corner !== undefined ?
opt_corner : ol.extent.Corner.TOP_LEFT;
@@ -37654,7 +35343,7 @@ ol.tilegrid.createForExtent =
*/
ol.tilegrid.createXYZ = function(opt_options) {
var options = /** @type {olx.tilegrid.TileGridOptions} */ ({});
- goog.object.extend(options, opt_options !== undefined ?
+ ol.object.assign(options, opt_options !== undefined ?
opt_options : /** @type {olx.tilegrid.XYZOptions} */ ({}));
if (options.extent === undefined) {
options.extent = ol.proj.get('EPSG:3857').getExtent();
@@ -37676,8 +35365,7 @@ ol.tilegrid.createXYZ = function(opt_options) {
* ol.DEFAULT_TILE_SIZE).
* @return {!Array.<number>} Resolutions array.
*/
-ol.tilegrid.resolutionsFromExtent =
- function(extent, opt_maxZoom, opt_tileSize) {
+ol.tilegrid.resolutionsFromExtent = function(extent, opt_maxZoom, opt_tileSize) {
var maxZoom = opt_maxZoom !== undefined ?
opt_maxZoom : ol.DEFAULT_MAX_ZOOM;
@@ -37707,8 +35395,7 @@ ol.tilegrid.resolutionsFromExtent =
* ol.extent.Corner.BOTTOM_LEFT).
* @return {ol.tilegrid.TileGrid} TileGrid instance.
*/
-ol.tilegrid.createForProjection =
- function(projection, opt_maxZoom, opt_tileSize, opt_corner) {
+ol.tilegrid.createForProjection = function(projection, opt_maxZoom, opt_tileSize, opt_corner) {
var extent = ol.tilegrid.extentFromProjection(projection);
return ol.tilegrid.createForExtent(
extent, opt_maxZoom, opt_tileSize, opt_corner);
@@ -37734,13 +35421,10 @@ ol.tilegrid.extentFromProjection = function(projection) {
goog.provide('ol.source.Tile');
goog.provide('ol.source.TileEvent');
-goog.provide('ol.source.TileOptions');
goog.require('goog.asserts');
-goog.require('goog.events.Event');
+goog.require('ol.events.Event');
goog.require('ol');
-goog.require('ol.Attribution');
-goog.require('ol.Extent');
goog.require('ol.TileCache');
goog.require('ol.TileRange');
goog.require('ol.TileState');
@@ -37752,22 +35436,6 @@ goog.require('ol.tilegrid.TileGrid');
/**
- * @typedef {{attributions: (Array.<ol.Attribution>|undefined),
- * cacheSize: (number|undefined),
- * extent: (ol.Extent|undefined),
- * logo: (string|olx.LogoOptions|undefined),
- * opaque: (boolean|undefined),
- * tilePixelRatio: (number|undefined),
- * projection: ol.proj.ProjectionLike,
- * state: (ol.source.State|undefined),
- * tileGrid: (ol.tilegrid.TileGrid|undefined),
- * wrapX: (boolean|undefined)}}
- */
-ol.source.TileOptions;
-
-
-
-/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
* instantiated in apps.
@@ -37775,7 +35443,7 @@ ol.source.TileOptions;
*
* @constructor
* @extends {ol.source.Source}
- * @param {ol.source.TileOptions} options Tile source options.
+ * @param {ol.SourceTileOptions} options Tile source options.
* @api
*/
ol.source.Tile = function(options) {
@@ -37820,6 +35488,12 @@ ol.source.Tile = function(options) {
*/
this.tmpSize = [0, 0];
+ /**
+ * @private
+ * @type {string}
+ */
+ this.key_ = '';
+
};
goog.inherits(ol.source.Tile, ol.source.Source);
@@ -37853,8 +35527,7 @@ ol.source.Tile.prototype.expireCache = function(projection, usedTiles) {
* considered loaded.
* @return {boolean} The tile range is fully covered with loaded tiles.
*/
-ol.source.Tile.prototype.forEachLoadedTile =
- function(projection, z, tileRange, callback) {
+ol.source.Tile.prototype.forEachLoadedTile = function(projection, z, tileRange, callback) {
var tileCache = this.getTileCacheForProjection(projection);
if (!tileCache) {
return false;
@@ -37883,21 +35556,34 @@ ol.source.Tile.prototype.forEachLoadedTile =
/**
+ * @param {ol.proj.Projection} projection Projection.
* @return {number} Gutter.
*/
-ol.source.Tile.prototype.getGutter = function() {
+ol.source.Tile.prototype.getGutter = function(projection) {
return 0;
};
/**
- * Return the "parameters" key, a string composed of the source's
- * parameters/dimensions.
- * @return {string} The parameters key.
+ * Return the key to be used for all tiles in the source.
+ * @return {string} The key for all tiles.
* @protected
*/
-ol.source.Tile.prototype.getKeyParams = function() {
- return '';
+ol.source.Tile.prototype.getKey = function() {
+ return this.key_;
+};
+
+
+/**
+ * Set the value to be used as the key for all tiles in the source.
+ * @param {string} key The key for tiles.
+ * @protected
+ */
+ol.source.Tile.prototype.setKey = function(key) {
+ if (this.key_ !== key) {
+ this.key_ = key;
+ this.changed();
+ }
};
@@ -37912,9 +35598,10 @@ ol.source.Tile.prototype.getKeyZXY = ol.tilecoord.getKeyZXY;
/**
+ * @param {ol.proj.Projection} projection Projection.
* @return {boolean} Opaque.
*/
-ol.source.Tile.prototype.getOpaque = function() {
+ol.source.Tile.prototype.getOpaque = function(projection) {
return this.opaque_;
};
@@ -37977,9 +35664,10 @@ ol.source.Tile.prototype.getTileCacheForProjection = function(projection) {
/**
+ * @param {number} pixelRatio Pixel ratio.
* @return {number} Tile pixel ratio.
*/
-ol.source.Tile.prototype.getTilePixelRatio = function() {
+ol.source.Tile.prototype.getTilePixelRatio = function(pixelRatio) {
return this.tilePixelRatio_;
};
@@ -37990,11 +35678,15 @@ ol.source.Tile.prototype.getTilePixelRatio = function() {
* @param {ol.proj.Projection} projection Projection.
* @return {ol.Size} Tile size.
*/
-ol.source.Tile.prototype.getTilePixelSize =
- function(z, pixelRatio, projection) {
+ol.source.Tile.prototype.getTilePixelSize = function(z, pixelRatio, projection) {
var tileGrid = this.getTileGridForProjection(projection);
- return ol.size.scale(ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize),
- this.tilePixelRatio_, this.tmpSize);
+ var tilePixelRatio = this.getTilePixelRatio(pixelRatio);
+ var tileSize = ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize);
+ if (tilePixelRatio == 1) {
+ return tileSize;
+ } else {
+ return ol.size.scale(tileSize, tilePixelRatio, this.tmpSize);
+ }
};
@@ -38007,8 +35699,7 @@ ol.source.Tile.prototype.getTilePixelSize =
* @return {ol.TileCoord} Tile coordinate to be passed to the tileUrlFunction or
* null if no tile URL should be created for the passed `tileCoord`.
*/
-ol.source.Tile.prototype.getTileCoordForTileUrlFunction =
- function(tileCoord, opt_projection) {
+ol.source.Tile.prototype.getTileCoordForTileUrlFunction = function(tileCoord, opt_projection) {
var projection = opt_projection !== undefined ?
opt_projection : this.getProjection();
var tileGrid = this.getTileGridForProjection(projection);
@@ -38021,6 +35712,15 @@ ol.source.Tile.prototype.getTileCoordForTileUrlFunction =
/**
+ * @inheritDoc
+ */
+ol.source.Tile.prototype.refresh = function() {
+ this.tileCache.clear();
+ this.changed();
+};
+
+
+/**
* Marks a tile coord as being used, without triggering a load.
* @param {number} z Tile coordinate z.
* @param {number} x Tile coordinate x.
@@ -38030,14 +35730,13 @@ ol.source.Tile.prototype.getTileCoordForTileUrlFunction =
ol.source.Tile.prototype.useTile = ol.nullFunction;
-
/**
* @classdesc
* Events emitted by {@link ol.source.Tile} instances are instances of this
* type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.source.TileEvent}
* @param {string} type Type.
* @param {ol.Tile} tile The tile.
@@ -38054,7 +35753,7 @@ ol.source.TileEvent = function(type, tile) {
this.tile = tile;
};
-goog.inherits(ol.source.TileEvent, goog.events.Event);
+goog.inherits(ol.source.TileEvent, ol.events.Event);
/**
@@ -38091,19 +35790,17 @@ goog.provide('ol.control.Attribution');
goog.require('goog.asserts');
goog.require('goog.dom');
-goog.require('goog.dom.classlist');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('goog.style');
goog.require('ol');
goog.require('ol.Attribution');
goog.require('ol.control.Control');
goog.require('ol.css');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
+goog.require('ol.object');
goog.require('ol.source.Tile');
-
/**
* @classdesc
* Control to show all the attributions associated with the layer sources
@@ -38152,27 +35849,27 @@ ol.control.Attribution = function(opt_options) {
this.collapsed_ = false;
}
- var className = options.className ? options.className : 'ol-attribution';
+ var className = options.className !== undefined ? options.className : 'ol-attribution';
- var tipLabel = options.tipLabel ? options.tipLabel : 'Attributions';
+ var tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Attributions';
- var collapseLabel = options.collapseLabel ? options.collapseLabel : '\u00BB';
+ var collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00BB';
/**
* @private
* @type {Node}
*/
- this.collapseLabel_ = goog.isString(collapseLabel) ?
+ this.collapseLabel_ = typeof collapseLabel === 'string' ?
goog.dom.createDom('SPAN', {}, collapseLabel) :
collapseLabel;
- var label = options.label ? options.label : 'i';
+ var label = options.label !== undefined ? options.label : 'i';
/**
* @private
* @type {Node}
*/
- this.label_ = goog.isString(label) ?
+ this.label_ = typeof label === 'string' ?
goog.dom.createDom('SPAN', {}, label) :
label;
@@ -38183,8 +35880,7 @@ ol.control.Attribution = function(opt_options) {
'title': tipLabel
}, activeLabel);
- goog.events.listen(button, goog.events.EventType.CLICK,
- this.handleClick_, false, this);
+ ol.events.listen(button, ol.events.EventType.CLICK, this.handleClick_, this);
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
ol.css.CLASS_CONTROL +
@@ -38239,7 +35935,7 @@ ol.control.Attribution.prototype.getSourceAttributions = function(frameState) {
var intersectsTileRange;
var layerStatesArray = frameState.layerStatesArray;
/** @type {Object.<string, ol.Attribution>} */
- var attributions = goog.object.clone(frameState.attributions);
+ var attributions = ol.object.assign({}, frameState.attributions);
/** @type {Object.<string, ol.Attribution>} */
var hiddenAttributions = {};
var projection = frameState.viewState.projection;
@@ -38325,16 +36021,14 @@ ol.control.Attribution.prototype.updateElement_ = function(frameState) {
this.attributionElementRenderedVisible_[attributionKey] = true;
}
delete visibleAttributions[attributionKey];
- }
- else if (attributionKey in hiddenAttributions) {
+ } else if (attributionKey in hiddenAttributions) {
if (this.attributionElementRenderedVisible_[attributionKey]) {
goog.style.setElementShown(
this.attributionElements_[attributionKey], false);
delete this.attributionElementRenderedVisible_[attributionKey];
}
delete hiddenAttributions[attributionKey];
- }
- else {
+ } else {
goog.dom.removeNode(this.attributionElements_[attributionKey]);
delete this.attributionElements_[attributionKey];
delete this.attributionElementRenderedVisible_[attributionKey];
@@ -38358,17 +36052,17 @@ ol.control.Attribution.prototype.updateElement_ = function(frameState) {
}
var renderVisible =
- !goog.object.isEmpty(this.attributionElementRenderedVisible_) ||
- !goog.object.isEmpty(frameState.logos);
+ !ol.object.isEmpty(this.attributionElementRenderedVisible_) ||
+ !ol.object.isEmpty(frameState.logos);
if (this.renderedVisible_ != renderVisible) {
goog.style.setElementShown(this.element, renderVisible);
this.renderedVisible_ = renderVisible;
}
if (renderVisible &&
- goog.object.isEmpty(this.attributionElementRenderedVisible_)) {
- goog.dom.classlist.add(this.element, 'ol-logo-only');
+ ol.object.isEmpty(this.attributionElementRenderedVisible_)) {
+ this.element.classList.add('ol-logo-only');
} else {
- goog.dom.classlist.remove(this.element, 'ol-logo-only');
+ this.element.classList.remove('ol-logo-only');
}
this.insertLogos_(frameState);
@@ -38395,10 +36089,14 @@ ol.control.Attribution.prototype.insertLogos_ = function(frameState) {
var image, logoElement, logoKey;
for (logoKey in logos) {
+ var logoValue = logos[logoKey];
+ if (logoValue instanceof HTMLElement) {
+ this.logoLi_.appendChild(logoValue);
+ logoElements[logoKey] = logoValue;
+ }
if (!(logoKey in logoElements)) {
image = new Image();
image.src = logoKey;
- var logoValue = logos[logoKey];
if (logoValue === '') {
logoElement = image;
} else {
@@ -38412,13 +36110,13 @@ ol.control.Attribution.prototype.insertLogos_ = function(frameState) {
}
}
- goog.style.setElementShown(this.logoLi_, !goog.object.isEmpty(logos));
+ goog.style.setElementShown(this.logoLi_, !ol.object.isEmpty(logos));
};
/**
- * @param {goog.events.BrowserEvent} event The event to handle
+ * @param {Event} event The event to handle
* @private
*/
ol.control.Attribution.prototype.handleClick_ = function(event) {
@@ -38431,7 +36129,7 @@ ol.control.Attribution.prototype.handleClick_ = function(event) {
* @private
*/
ol.control.Attribution.prototype.handleToggle_ = function() {
- goog.dom.classlist.toggle(this.element, 'ol-collapsed');
+ this.element.classList.toggle('ol-collapsed');
if (this.collapsed_) {
goog.dom.replaceNode(this.collapseLabel_, this.label_);
} else {
@@ -38461,7 +36159,7 @@ ol.control.Attribution.prototype.setCollapsible = function(collapsible) {
return;
}
this.collapsible_ = collapsible;
- goog.dom.classlist.toggle(this.element, 'ol-uncollapsible');
+ this.element.classList.toggle('ol-uncollapsible');
if (!collapsible && this.collapsed_) {
this.handleToggle_();
}
@@ -38496,9 +36194,8 @@ ol.control.Attribution.prototype.getCollapsed = function() {
goog.provide('ol.control.Rotate');
goog.require('goog.dom');
-goog.require('goog.dom.classlist');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol');
goog.require('ol.animation');
goog.require('ol.control.Control');
@@ -38506,7 +36203,6 @@ goog.require('ol.css');
goog.require('ol.easing');
-
/**
* @classdesc
* A button control to reset rotation to 0.
@@ -38522,10 +36218,9 @@ ol.control.Rotate = function(opt_options) {
var options = opt_options ? opt_options : {};
- var className = options.className ?
- options.className : 'ol-rotate';
+ var className = options.className !== undefined ? options.className : 'ol-rotate';
- var label = options.label ? options.label : '\u21E7';
+ var label = options.label !== undefined ? options.label : '\u21E7';
/**
* @type {Element}
@@ -38533,12 +36228,12 @@ ol.control.Rotate = function(opt_options) {
*/
this.label_ = null;
- if (goog.isString(label)) {
+ if (typeof label === 'string') {
this.label_ = goog.dom.createDom('SPAN',
'ol-compass', label);
} else {
this.label_ = label;
- goog.dom.classlist.add(this.label_, 'ol-compass');
+ this.label_.classList.add('ol-compass');
}
var tipLabel = options.tipLabel ? options.tipLabel : 'Reset rotation';
@@ -38549,8 +36244,8 @@ ol.control.Rotate = function(opt_options) {
'title': tipLabel
}, this.label_);
- goog.events.listen(button, goog.events.EventType.CLICK,
- ol.control.Rotate.prototype.handleClick_, false, this);
+ ol.events.listen(button, ol.events.EventType.CLICK,
+ ol.control.Rotate.prototype.handleClick_, this);
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
ol.css.CLASS_CONTROL;
@@ -38585,7 +36280,7 @@ ol.control.Rotate = function(opt_options) {
this.rotation_ = undefined;
if (this.autoHide_) {
- goog.dom.classlist.add(this.element, ol.css.CLASS_HIDDEN);
+ this.element.classList.add(ol.css.CLASS_HIDDEN);
}
};
@@ -38593,7 +36288,7 @@ goog.inherits(ol.control.Rotate, ol.control.Control);
/**
- * @param {goog.events.BrowserEvent} event The event to handle
+ * @param {Event} event The event to handle
* @private
*/
ol.control.Rotate.prototype.handleClick_ = function(event) {
@@ -38653,8 +36348,12 @@ ol.control.Rotate.render = function(mapEvent) {
if (rotation != this.rotation_) {
var transform = 'rotate(' + rotation + 'rad)';
if (this.autoHide_) {
- goog.dom.classlist.enable(
- this.element, ol.css.CLASS_HIDDEN, rotation === 0);
+ var contains = this.element.classList.contains(ol.css.CLASS_HIDDEN);
+ if (!contains && rotation === 0) {
+ this.element.classList.add(ol.css.CLASS_HIDDEN);
+ } else if (contains && rotation !== 0) {
+ this.element.classList.remove(ol.css.CLASS_HIDDEN);
+ }
}
this.label_.style.msTransform = transform;
this.label_.style.webkitTransform = transform;
@@ -38666,15 +36365,14 @@ ol.control.Rotate.render = function(mapEvent) {
goog.provide('ol.control.Zoom');
goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.animation');
goog.require('ol.control.Control');
goog.require('ol.css');
goog.require('ol.easing');
-
/**
* @classdesc
* A control with 2 buttons, one for zoom in and one for zoom out.
@@ -38690,16 +36388,16 @@ ol.control.Zoom = function(opt_options) {
var options = opt_options ? opt_options : {};
- var className = options.className ? options.className : 'ol-zoom';
+ var className = options.className !== undefined ? options.className : 'ol-zoom';
- var delta = options.delta ? options.delta : 1;
+ var delta = options.delta !== undefined ? options.delta : 1;
- var zoomInLabel = options.zoomInLabel ? options.zoomInLabel : '+';
- var zoomOutLabel = options.zoomOutLabel ? options.zoomOutLabel : '\u2212';
+ var zoomInLabel = options.zoomInLabel !== undefined ? options.zoomInLabel : '+';
+ var zoomOutLabel = options.zoomOutLabel !== undefined ? options.zoomOutLabel : '\u2212';
- var zoomInTipLabel = options.zoomInTipLabel ?
+ var zoomInTipLabel = options.zoomInTipLabel !== undefined ?
options.zoomInTipLabel : 'Zoom in';
- var zoomOutTipLabel = options.zoomOutTipLabel ?
+ var zoomOutTipLabel = options.zoomOutTipLabel !== undefined ?
options.zoomOutTipLabel : 'Zoom out';
var inElement = goog.dom.createDom('BUTTON', {
@@ -38708,9 +36406,8 @@ ol.control.Zoom = function(opt_options) {
'title': zoomInTipLabel
}, zoomInLabel);
- goog.events.listen(inElement,
- goog.events.EventType.CLICK, goog.partial(
- ol.control.Zoom.prototype.handleClick_, delta), false, this);
+ ol.events.listen(inElement, ol.events.EventType.CLICK,
+ ol.control.Zoom.prototype.handleClick_.bind(this, delta));
var outElement = goog.dom.createDom('BUTTON', {
'class': className + '-out',
@@ -38718,14 +36415,12 @@ ol.control.Zoom = function(opt_options) {
'title': zoomOutTipLabel
}, zoomOutLabel);
- goog.events.listen(outElement,
- goog.events.EventType.CLICK, goog.partial(
- ol.control.Zoom.prototype.handleClick_, -delta), false, this);
+ ol.events.listen(outElement, ol.events.EventType.CLICK,
+ ol.control.Zoom.prototype.handleClick_.bind(this, -delta));
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
ol.css.CLASS_CONTROL;
- var element = goog.dom.createDom('DIV', cssClasses, inElement,
- outElement);
+ var element = goog.dom.createDom('DIV', cssClasses, inElement, outElement);
goog.base(this, {
element: element,
@@ -38744,7 +36439,7 @@ goog.inherits(ol.control.Zoom, ol.control.Control);
/**
* @param {number} delta Zoom delta.
- * @param {goog.events.BrowserEvent} event The event to handle
+ * @param {Event} event The event to handle
* @private
*/
ol.control.Zoom.prototype.handleClick_ = function(delta, event) {
@@ -38884,7 +36579,8 @@ goog.dom.fullscreen.EventType = {
goog.dom.fullscreen.isSupported = function(opt_domHelper) {
var doc = goog.dom.fullscreen.getDocument_(opt_domHelper);
var body = doc.body;
- return !!(body.webkitRequestFullscreen ||
+ return !!(
+ body.webkitRequestFullscreen ||
(body.mozRequestFullScreen && doc.mozFullScreenEnabled) ||
(body.msRequestFullscreen && doc.msFullscreenEnabled) ||
(body.requestFullscreen && doc.fullscreenEnabled));
@@ -38912,8 +36608,7 @@ goog.dom.fullscreen.requestFullScreen = function(element) {
* Requests putting the element in full screen with full keyboard access.
* @param {!Element} element The element to put full screen.
*/
-goog.dom.fullscreen.requestFullScreenWithKeys = function(
- element) {
+goog.dom.fullscreen.requestFullScreenWithKeys = function(element) {
if (element.mozRequestFullScreenWithKeys) {
element.mozRequestFullScreenWithKeys();
} else if (element.webkitRequestFullscreen) {
@@ -38953,8 +36648,9 @@ goog.dom.fullscreen.isFullScreen = function(opt_domHelper) {
var doc = goog.dom.fullscreen.getDocument_(opt_domHelper);
// IE 11 doesn't have similar boolean property, so check whether
// document.msFullscreenElement is null instead.
- return !!(doc.webkitIsFullScreen || doc.mozFullScreen ||
- doc.msFullscreenElement || doc.fullscreenElement);
+ return !!(
+ doc.webkitIsFullScreen || doc.mozFullScreen || doc.msFullscreenElement ||
+ doc.fullscreenElement);
};
@@ -38967,10 +36663,8 @@ goog.dom.fullscreen.isFullScreen = function(opt_domHelper) {
goog.dom.fullscreen.getFullScreenElement = function(opt_domHelper) {
var doc = goog.dom.fullscreen.getDocument_(opt_domHelper);
var element_list = [
- doc.webkitFullscreenElement,
- doc.mozFullScreenElement,
- doc.msFullscreenElement,
- doc.fullscreenElement
+ doc.webkitFullscreenElement, doc.mozFullScreenElement,
+ doc.msFullscreenElement, doc.fullscreenElement
];
for (var i = 0; i < element_list.length; i++) {
if (element_list[i] != null) {
@@ -38989,29 +36683,30 @@ goog.dom.fullscreen.getFullScreenElement = function(opt_domHelper) {
* @private
*/
goog.dom.fullscreen.getDocument_ = function(opt_domHelper) {
- return opt_domHelper ?
- opt_domHelper.getDocument() :
- goog.dom.getDomHelper().getDocument();
+ return opt_domHelper ? opt_domHelper.getDocument() :
+ goog.dom.getDomHelper().getDocument();
};
goog.provide('ol.control.FullScreen');
goog.require('goog.asserts');
goog.require('goog.dom');
-goog.require('goog.dom.classlist');
goog.require('goog.dom.fullscreen');
goog.require('goog.dom.fullscreen.EventType');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol');
goog.require('ol.control.Control');
goog.require('ol.css');
-
/**
* @classdesc
* Provides a button that when clicked fills up the full screen with the map.
+ * The full screen source element is by default the element containing the map viewport unless
+ * overriden by providing the `source` option. In which case, the dom
+ * element introduced using this parameter will be displayed in full screen.
+ *
* When in full screen mode, a close button is shown to exit full screen mode.
* The [Fullscreen API](http://www.w3.org/TR/fullscreen/) is used to
* toggle the map in full screen mode.
@@ -39030,24 +36725,25 @@ ol.control.FullScreen = function(opt_options) {
* @private
* @type {string}
*/
- this.cssClassName_ = options.className ? options.className : 'ol-full-screen';
+ this.cssClassName_ = options.className !== undefined ? options.className :
+ 'ol-full-screen';
- var label = options.label ? options.label : '\u2922';
+ var label = options.label !== undefined ? options.label : '\u2922';
/**
* @private
* @type {Node}
*/
- this.labelNode_ = goog.isString(label) ?
+ this.labelNode_ = typeof label === 'string' ?
document.createTextNode(label) : label;
- var labelActive = options.labelActive ? options.labelActive : '\u00d7';
+ var labelActive = options.labelActive !== undefined ? options.labelActive : '\u00d7';
/**
* @private
* @type {Node}
*/
- this.labelActiveNode_ = goog.isString(labelActive) ?
+ this.labelActiveNode_ = typeof labelActive === 'string' ?
document.createTextNode(labelActive) : labelActive;
var tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
@@ -39057,12 +36753,8 @@ ol.control.FullScreen = function(opt_options) {
'title': tipLabel
}, this.labelNode_);
- goog.events.listen(button, goog.events.EventType.CLICK,
- this.handleClick_, false, this);
-
- goog.events.listen(goog.global.document,
- goog.dom.fullscreen.EventType.CHANGE,
- this.handleFullScreenChange_, false, this);
+ ol.events.listen(button, ol.events.EventType.CLICK,
+ this.handleClick_, this);
var cssClasses = this.cssClassName_ + ' ' + ol.css.CLASS_UNSELECTABLE +
' ' + ol.css.CLASS_CONTROL + ' ' +
@@ -39080,12 +36772,18 @@ ol.control.FullScreen = function(opt_options) {
*/
this.keys_ = options.keys !== undefined ? options.keys : false;
+ /**
+ * @private
+ * @type {Element|string|undefined}
+ */
+ this.source_ = options.source;
+
};
goog.inherits(ol.control.FullScreen, ol.control.Control);
/**
- * @param {goog.events.BrowserEvent} event The event to handle
+ * @param {Event} event The event to handle
* @private
*/
ol.control.FullScreen.prototype.handleClick_ = function(event) {
@@ -39108,9 +36806,8 @@ ol.control.FullScreen.prototype.handleFullScreen_ = function() {
if (goog.dom.fullscreen.isFullScreen()) {
goog.dom.fullscreen.exitFullScreen();
} else {
- var target = map.getTarget();
- goog.asserts.assert(target, 'target should be defined');
- var element = goog.dom.getElement(target);
+ var element = this.source_ ?
+ goog.dom.getElement(this.source_) : map.getTargetElement();
goog.asserts.assert(element, 'element should be defined');
if (this.keys_) {
goog.dom.fullscreen.requestFullScreenWithKeys(element);
@@ -39125,15 +36822,13 @@ ol.control.FullScreen.prototype.handleFullScreen_ = function() {
* @private
*/
ol.control.FullScreen.prototype.handleFullScreenChange_ = function() {
- var opened = this.cssClassName_ + '-true';
- var closed = this.cssClassName_ + '-false';
- var button = goog.dom.getFirstElementChild(this.element);
+ var button = this.element.firstElementChild;
var map = this.getMap();
if (goog.dom.fullscreen.isFullScreen()) {
- goog.dom.classlist.swap(button, closed, opened);
+ button.className = this.cssClassName_ + '-true';
goog.dom.replaceNode(this.labelActiveNode_, this.labelNode_);
} else {
- goog.dom.classlist.swap(button, opened, closed);
+ button.className = this.cssClassName_ + '-false';
goog.dom.replaceNode(this.labelNode_, this.labelActiveNode_);
}
if (map) {
@@ -39141,28 +36836,28 @@ ol.control.FullScreen.prototype.handleFullScreenChange_ = function() {
}
};
-goog.provide('ol.Pixel');
-
/**
- * An array with two elements, representing a pixel. The first element is the
- * x-coordinate, the second the y-coordinate of the pixel.
- * @typedef {Array.<number>}
+ * @inheritDoc
* @api stable
*/
-ol.Pixel;
+ol.control.FullScreen.prototype.setMap = function(map) {
+ goog.base(this, 'setMap', map);
+ if (map) {
+ this.listenerKeys.push(
+ ol.events.listen(ol.global.document, goog.dom.fullscreen.EventType.CHANGE,
+ this.handleFullScreenChange_, this)
+ );
+ }
+};
// FIXME should listen on appropriate pane, once it is defined
goog.provide('ol.control.MousePosition');
-goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('ol.CoordinateFormatType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.Object');
-goog.require('ol.Pixel');
-goog.require('ol.TransformFunction');
goog.require('ol.control.Control');
goog.require('ol.proj');
goog.require('ol.proj.Projection');
@@ -39177,7 +36872,6 @@ ol.control.MousePositionProperty = {
};
-
/**
* @classdesc
* A control to show the 2D coordinates of the mouse cursor. By default, these
@@ -39195,9 +36889,8 @@ ol.control.MousePosition = function(opt_options) {
var options = opt_options ? opt_options : {};
- var className = options.className ? options.className : 'ol-mouse-position';
-
- var element = goog.dom.createDom('DIV', className);
+ var element = document.createElement('DIV');
+ element.className = options.className !== undefined ? options.className : 'ol-mouse-position'
var render = options.render ?
options.render : ol.control.MousePosition.render;
@@ -39208,9 +36901,9 @@ ol.control.MousePosition = function(opt_options) {
target: options.target
});
- goog.events.listen(this,
+ ol.events.listen(this,
ol.Object.getChangeEventType(ol.control.MousePositionProperty.PROJECTION),
- this.handleProjectionChanged_, false, this);
+ this.handleProjectionChanged_, this);
if (options.coordinateFormat) {
this.setCoordinateFormat(options.coordinateFormat);
@@ -39223,7 +36916,7 @@ ol.control.MousePosition = function(opt_options) {
* @private
* @type {string}
*/
- this.undefinedHTML_ = options.undefinedHTML ? options.undefinedHTML : '';
+ this.undefinedHTML_ = options.undefinedHTML !== undefined ? options.undefinedHTML : '';
/**
* @private
@@ -39309,21 +37002,21 @@ ol.control.MousePosition.prototype.getProjection = function() {
/**
- * @param {goog.events.BrowserEvent} browserEvent Browser event.
+ * @param {Event} event Browser event.
* @protected
*/
-ol.control.MousePosition.prototype.handleMouseMove = function(browserEvent) {
+ol.control.MousePosition.prototype.handleMouseMove = function(event) {
var map = this.getMap();
- this.lastMouseMovePixel_ = map.getEventPixel(browserEvent.getBrowserEvent());
+ this.lastMouseMovePixel_ = map.getEventPixel(event);
this.updateHTML_(this.lastMouseMovePixel_);
};
/**
- * @param {goog.events.BrowserEvent} browserEvent Browser event.
+ * @param {Event} event Browser event.
* @protected
*/
-ol.control.MousePosition.prototype.handleMouseOut = function(browserEvent) {
+ol.control.MousePosition.prototype.handleMouseOut = function(event) {
this.updateHTML_(null);
this.lastMouseMovePixel_ = null;
};
@@ -39338,10 +37031,10 @@ ol.control.MousePosition.prototype.setMap = function(map) {
if (map) {
var viewport = map.getViewport();
this.listenerKeys.push(
- goog.events.listen(viewport, goog.events.EventType.MOUSEMOVE,
- this.handleMouseMove, false, this),
- goog.events.listen(viewport, goog.events.EventType.MOUSEOUT,
- this.handleMouseOut, false, this)
+ ol.events.listen(viewport, ol.events.EventType.MOUSEMOVE,
+ this.handleMouseMove, this),
+ ol.events.listen(viewport, ol.events.EventType.MOUSEOUT,
+ this.handleMouseOut, this)
);
}
};
@@ -39405,7 +37098,7 @@ ol.control.MousePosition.prototype.updateHTML_ = function(pixel) {
}
};
-// Copyright 2012 The Closure Library Authors. All Rights Reserved.
+// Copyright 2010 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -39420,1324 +37113,152 @@ ol.control.MousePosition.prototype.updateHTML_ = function(pixel) {
// limitations under the License.
/**
- * @fileoverview A delayed callback that pegs to the next animation frame
- * instead of a user-configurable timeout.
- *
- * @author nicksantos@google.com (Nick Santos)
- */
-
-goog.provide('goog.async.AnimationDelay');
-
-goog.require('goog.Disposable');
-goog.require('goog.events');
-goog.require('goog.functions');
-
-
-
-// TODO(nicksantos): Should we factor out the common code between this and
-// goog.async.Delay? I'm not sure if there's enough code for this to really
-// make sense. Subclassing seems like the wrong approach for a variety of
-// reasons. Maybe there should be a common interface?
-
-
-
-/**
- * A delayed callback that pegs to the next animation frame
- * instead of a user configurable timeout. By design, this should have
- * the same interface as goog.async.Delay.
- *
- * Uses requestAnimationFrame and friends when available, but falls
- * back to a timeout of goog.async.AnimationDelay.TIMEOUT.
+ * @fileoverview A global registry for entry points into a program,
+ * so that they can be instrumented. Each module should register their
+ * entry points with this registry. Designed to be compiled out
+ * if no instrumentation is requested.
*
- * For more on requestAnimationFrame and how you can use it to create smoother
- * animations, see:
- * @see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+ * Entry points may be registered before or after a call to
+ * goog.debug.entryPointRegistry.monitorAll. If an entry point is registered
+ * later, the existing monitor will instrument the new entry point.
*
- * @param {function(number)} listener Function to call when the delay completes.
- * Will be passed the timestamp when it's called, in unix ms.
- * @param {Window=} opt_window The window object to execute the delay in.
- * Defaults to the global object.
- * @param {Object=} opt_handler The object scope to invoke the function in.
- * @constructor
- * @struct
- * @extends {goog.Disposable}
- * @final
+ * @author nicksantos@google.com (Nick Santos)
*/
-goog.async.AnimationDelay = function(listener, opt_window, opt_handler) {
- goog.async.AnimationDelay.base(this, 'constructor');
-
- /**
- * Identifier of the active delay timeout, or event listener,
- * or null when inactive.
- * @private {goog.events.Key|number}
- */
- this.id_ = null;
- /**
- * If we're using dom listeners.
- * @private {?boolean}
- */
- this.usingListeners_ = false;
-
- /**
- * The function that will be invoked after a delay.
- * @private {function(number)}
- */
- this.listener_ = listener;
-
- /**
- * The object context to invoke the callback in.
- * @private {Object|undefined}
- */
- this.handler_ = opt_handler;
+goog.provide('goog.debug.EntryPointMonitor');
+goog.provide('goog.debug.entryPointRegistry');
- /**
- * @private {Window}
- */
- this.win_ = opt_window || window;
+goog.require('goog.asserts');
- /**
- * Cached callback function invoked when the delay finishes.
- * @private {function()}
- */
- this.callback_ = goog.bind(this.doAction_, this);
-};
-goog.inherits(goog.async.AnimationDelay, goog.Disposable);
/**
- * Default wait timeout for animations (in milliseconds). Only used for timed
- * animation, which uses a timer (setTimeout) to schedule animation.
- *
- * @type {number}
- * @const
+ * @interface
*/
-goog.async.AnimationDelay.TIMEOUT = 20;
+goog.debug.EntryPointMonitor = function() {};
/**
- * Name of event received from the requestAnimationFrame in Firefox.
+ * Instruments a function.
*
- * @type {string}
- * @const
- * @private
- */
-goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_ = 'MozBeforePaint';
-
-
-/**
- * Starts the delay timer. The provided listener function will be called
- * before the next animation frame.
- */
-goog.async.AnimationDelay.prototype.start = function() {
- this.stop();
- this.usingListeners_ = false;
-
- var raf = this.getRaf_();
- var cancelRaf = this.getCancelRaf_();
- if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) {
- // Because Firefox (Gecko) runs animation in separate threads, it also saves
- // time by running the requestAnimationFrame callbacks in that same thread.
- // Sadly this breaks the assumption of implicit thread-safety in JS, and can
- // thus create thread-based inconsistencies on counters etc.
- //
- // Calling cycleAnimations_ using the MozBeforePaint event instead of as
- // callback fixes this.
- //
- // Trigger this condition only if the mozRequestAnimationFrame is available,
- // but not the W3C requestAnimationFrame function (as in draft) or the
- // equivalent cancel functions.
- this.id_ = goog.events.listen(
- this.win_,
- goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_,
- this.callback_);
- this.win_.mozRequestAnimationFrame(null);
- this.usingListeners_ = true;
- } else if (raf && cancelRaf) {
- this.id_ = raf.call(this.win_, this.callback_);
- } else {
- this.id_ = this.win_.setTimeout(
- // Prior to Firefox 13, Gecko passed a non-standard parameter
- // to the callback that we want to ignore.
- goog.functions.lock(this.callback_),
- goog.async.AnimationDelay.TIMEOUT);
- }
-};
-
-
-/**
- * Stops the delay timer if it is active. No action is taken if the timer is not
- * in use.
- */
-goog.async.AnimationDelay.prototype.stop = function() {
- if (this.isActive()) {
- var raf = this.getRaf_();
- var cancelRaf = this.getCancelRaf_();
- if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) {
- goog.events.unlistenByKey(this.id_);
- } else if (raf && cancelRaf) {
- cancelRaf.call(this.win_, /** @type {number} */ (this.id_));
- } else {
- this.win_.clearTimeout(/** @type {number} */ (this.id_));
- }
- }
- this.id_ = null;
-};
-
-
-/**
- * Fires delay's action even if timer has already gone off or has not been
- * started yet; guarantees action firing. Stops the delay timer.
- */
-goog.async.AnimationDelay.prototype.fire = function() {
- this.stop();
- this.doAction_();
-};
-
-
-/**
- * Fires delay's action only if timer is currently active. Stops the delay
- * timer.
- */
-goog.async.AnimationDelay.prototype.fireIfActive = function() {
- if (this.isActive()) {
- this.fire();
- }
-};
-
-
-/**
- * @return {boolean} True if the delay is currently active, false otherwise.
- */
-goog.async.AnimationDelay.prototype.isActive = function() {
- return this.id_ != null;
-};
-
-
-/**
- * Invokes the callback function after the delay successfully completes.
- * @private
- */
-goog.async.AnimationDelay.prototype.doAction_ = function() {
- if (this.usingListeners_ && this.id_) {
- goog.events.unlistenByKey(this.id_);
- }
- this.id_ = null;
-
- // We are not using the timestamp returned by requestAnimationFrame
- // because it may be either a Date.now-style time or a
- // high-resolution time (depending on browser implementation). Using
- // goog.now() will ensure that the timestamp used is consistent and
- // compatible with goog.fx.Animation.
- this.listener_.call(this.handler_, goog.now());
-};
-
-
-/** @override */
-goog.async.AnimationDelay.prototype.disposeInternal = function() {
- this.stop();
- goog.async.AnimationDelay.base(this, 'disposeInternal');
-};
-
-
-/**
- * @return {?function(function(number)): number} The requestAnimationFrame
- * function, or null if not available on this browser.
- * @private
- */
-goog.async.AnimationDelay.prototype.getRaf_ = function() {
- var win = this.win_;
- return win.requestAnimationFrame ||
- win.webkitRequestAnimationFrame ||
- win.mozRequestAnimationFrame ||
- win.oRequestAnimationFrame ||
- win.msRequestAnimationFrame ||
- null;
-};
-
-
-/**
- * @return {?function(number): number} The cancelAnimationFrame function,
- * or null if not available on this browser.
- * @private
+ * @param {!Function} fn A function to instrument.
+ * @return {!Function} The instrumented function.
*/
-goog.async.AnimationDelay.prototype.getCancelRaf_ = function() {
- var win = this.win_;
- return win.cancelAnimationFrame ||
- win.cancelRequestAnimationFrame ||
- win.webkitCancelRequestAnimationFrame ||
- win.mozCancelRequestAnimationFrame ||
- win.oCancelRequestAnimationFrame ||
- win.msCancelRequestAnimationFrame ||
- null;
-};
+goog.debug.EntryPointMonitor.prototype.wrap;
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Provides a function to schedule running a function as soon
- * as possible after the current JS execution stops and yields to the event
- * loop.
+ * Try to remove an instrumentation wrapper created by this monitor.
+ * If the function passed to unwrap is not a wrapper created by this
+ * monitor, then we will do nothing.
*
- */
-
-goog.provide('goog.async.nextTick');
-goog.provide('goog.async.throwException');
-
-goog.require('goog.debug.entryPointRegistry');
-goog.require('goog.dom.TagName');
-goog.require('goog.functions');
-goog.require('goog.labs.userAgent.browser');
-goog.require('goog.labs.userAgent.engine');
-
-
-/**
- * Throw an item without interrupting the current execution context. For
- * example, if processing a group of items in a loop, sometimes it is useful
- * to report an error while still allowing the rest of the batch to be
- * processed.
- * @param {*} exception
- */
-goog.async.throwException = function(exception) {
- // Each throw needs to be in its own context.
- goog.global.setTimeout(function() { throw exception; }, 0);
-};
-
-
-/**
- * Fires the provided callbacks as soon as possible after the current JS
- * execution context. setTimeout(…, 0) takes at least 4ms when called from
- * within another setTimeout(…, 0) for legacy reasons.
+ * Notice that some wrappers may not be unwrappable. For example, if other
+ * monitors have applied their own wrappers, then it will be impossible to
+ * unwrap them because their wrappers will have captured our wrapper.
*
- * This will not schedule the callback as a microtask (i.e. a task that can
- * preempt user input or networking callbacks). It is meant to emulate what
- * setTimeout(_, 0) would do if it were not throttled. If you desire microtask
- * behavior, use {@see goog.Promise} instead.
+ * So it is important that entry points are unwrapped in the reverse
+ * order that they were wrapped.
*
- * @param {function(this:SCOPE)} callback Callback function to fire as soon as
- * possible.
- * @param {SCOPE=} opt_context Object in whose scope to call the listener.
- * @param {boolean=} opt_useSetImmediate Avoid the IE workaround that
- * ensures correctness at the cost of speed. See comments for details.
- * @template SCOPE
- */
-goog.async.nextTick = function(callback, opt_context, opt_useSetImmediate) {
- var cb = callback;
- if (opt_context) {
- cb = goog.bind(callback, opt_context);
- }
- cb = goog.async.nextTick.wrapCallback_(cb);
- // window.setImmediate was introduced and currently only supported by IE10+,
- // but due to a bug in the implementation it is not guaranteed that
- // setImmediate is faster than setTimeout nor that setImmediate N is before
- // setImmediate N+1. That is why we do not use the native version if
- // available. We do, however, call setImmediate if it is a normal function
- // because that indicates that it has been replaced by goog.testing.MockClock
- // which we do want to support.
- // See
- // http://connect.microsoft.com/IE/feedback/details/801823/setimmediate-and-messagechannel-are-broken-in-ie10
- //
- // Note we do allow callers to also request setImmediate if they are willing
- // to accept the possible tradeoffs of incorrectness in exchange for speed.
- // The IE fallback of readystate change is much slower.
- if (goog.isFunction(goog.global.setImmediate) &&
- // Opt in.
- (opt_useSetImmediate ||
- // or it isn't a browser or the environment is weird
- !goog.global.Window || !goog.global.Window.prototype ||
- // or something redefined setImmediate in which case we (YOLO) decide
- // to use it (This is so that we use the mockClock setImmediate. sigh).
- goog.global.Window.prototype.setImmediate != goog.global.setImmediate)) {
- goog.global.setImmediate(cb);
- return;
- }
-
- // Look for and cache the custom fallback version of setImmediate.
- if (!goog.async.nextTick.setImmediate_) {
- goog.async.nextTick.setImmediate_ =
- goog.async.nextTick.getSetImmediateEmulator_();
- }
- goog.async.nextTick.setImmediate_(cb);
-};
-
-
-/**
- * Cache for the setImmediate implementation.
- * @type {function(function())}
- * @private
- */
-goog.async.nextTick.setImmediate_;
-
-
-/**
- * Determines the best possible implementation to run a function as soon as
- * the JS event loop is idle.
- * @return {function(function())} The "setImmediate" implementation.
- * @private
+ * @param {!Function} fn A function to unwrap.
+ * @return {!Function} The unwrapped function, or {@code fn} if it was not
+ * a wrapped function created by this monitor.
*/
-goog.async.nextTick.getSetImmediateEmulator_ = function() {
- // Create a private message channel and use it to postMessage empty messages
- // to ourselves.
- var Channel = goog.global['MessageChannel'];
- // If MessageChannel is not available and we are in a browser, implement
- // an iframe based polyfill in browsers that have postMessage and
- // document.addEventListener. The latter excludes IE8 because it has a
- // synchronous postMessage implementation.
- if (typeof Channel === 'undefined' && typeof window !== 'undefined' &&
- window.postMessage && window.addEventListener &&
- // Presto (The old pre-blink Opera engine) has problems with iframes
- // and contentWindow.
- !goog.labs.userAgent.engine.isPresto()) {
- /** @constructor */
- Channel = function() {
- // Make an empty, invisible iframe.
- var iframe = document.createElement(goog.dom.TagName.IFRAME);
- iframe.style.display = 'none';
- iframe.src = '';
- document.documentElement.appendChild(iframe);
- var win = iframe.contentWindow;
- var doc = win.document;
- doc.open();
- doc.write('');
- doc.close();
- // Do not post anything sensitive over this channel, as the workaround for
- // pages with file: origin could allow that information to be modified or
- // intercepted.
- var message = 'callImmediate' + Math.random();
- // The same origin policy rejects attempts to postMessage from file: urls
- // unless the origin is '*'.
- // TODO(b/16335441): Use '*' origin for data: and other similar protocols.
- var origin = win.location.protocol == 'file:' ?
- '*' : win.location.protocol + '//' + win.location.host;
- var onmessage = goog.bind(function(e) {
- // Validate origin and message to make sure that this message was
- // intended for us. If the origin is set to '*' (see above) only the
- // message needs to match since, for example, '*' != 'file://'. Allowing
- // the wildcard is ok, as we are not concerned with security here.
- if ((origin != '*' && e.origin != origin) || e.data != message) {
- return;
- }
- this['port1'].onmessage();
- }, this);
- win.addEventListener('message', onmessage, false);
- this['port1'] = {};
- this['port2'] = {
- postMessage: function() {
- win.postMessage(message, origin);
- }
- };
- };
- }
- if (typeof Channel !== 'undefined' &&
- (!goog.labs.userAgent.browser.isIE())) {
- // Exclude all of IE due to
- // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/
- // which allows starving postMessage with a busy setTimeout loop.
- // This currently affects IE10 and IE11 which would otherwise be able
- // to use the postMessage based fallbacks.
- var channel = new Channel();
- // Use a fifo linked list to call callbacks in the right order.
- var head = {};
- var tail = head;
- channel['port1'].onmessage = function() {
- if (goog.isDef(head.next)) {
- head = head.next;
- var cb = head.cb;
- head.cb = null;
- cb();
- }
- };
- return function(cb) {
- tail.next = {
- cb: cb
- };
- tail = tail.next;
- channel['port2'].postMessage(0);
- };
- }
- // Implementation for IE6+: Script elements fire an asynchronous
- // onreadystatechange event when inserted into the DOM.
- if (typeof document !== 'undefined' && 'onreadystatechange' in
- document.createElement(goog.dom.TagName.SCRIPT)) {
- return function(cb) {
- var script = document.createElement(goog.dom.TagName.SCRIPT);
- script.onreadystatechange = function() {
- // Clean up and call the callback.
- script.onreadystatechange = null;
- script.parentNode.removeChild(script);
- script = null;
- cb();
- cb = null;
- };
- document.documentElement.appendChild(script);
- };
- }
- // Fall back to setTimeout with 0. In browsers this creates a delay of 5ms
- // or more.
- return function(cb) {
- goog.global.setTimeout(cb, 0);
- };
-};
+goog.debug.EntryPointMonitor.prototype.unwrap;
/**
- * Helper function that is overrided to protect callbacks with entry point
- * monitor if the application monitors entry points.
- * @param {function()} callback Callback function to fire as soon as possible.
- * @return {function()} The wrapped callback.
+ * An array of entry point callbacks.
+ * @type {!Array<function(!Function)>}
* @private
*/
-goog.async.nextTick.wrapCallback_ = goog.functions.identity;
-
-
-// Register the callback function as an entry point, so that it can be
-// monitored for exception handling, etc. This has to be done in this file
-// since it requires special code to handle all browsers.
-goog.debug.entryPointRegistry.register(
- /**
- * @param {function(!Function): !Function} transformer The transforming
- * function.
- */
- function(transformer) {
- goog.async.nextTick.wrapCallback_ = transformer;
- });
-
-// Copyright 2014 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview The SafeScript type and its builders.
- *
- * TODO(xtof): Link to document stating type contract.
- */
-
-goog.provide('goog.html.SafeScript');
-
-goog.require('goog.asserts');
-goog.require('goog.string.Const');
-goog.require('goog.string.TypedString');
-
-
-
-/**
- * A string-like object which represents JavaScript code and that carries the
- * security type contract that its value, as a string, will not cause execution
- * of unconstrained attacker controlled code (XSS) when evaluated as JavaScript
- * in a browser.
- *
- * Instances of this type must be created via the factory method
- * {@code goog.html.SafeScript.fromConstant} and not by invoking its
- * constructor. The constructor intentionally takes no parameters and the type
- * is immutable; hence only a default instance corresponding to the empty string
- * can be obtained via constructor invocation.
- *
- * A SafeScript's string representation can safely be interpolated as the
- * content of a script element within HTML. The SafeScript string should not be
- * escaped before interpolation.
- *
- * Note that the SafeScript might contain text that is attacker-controlled but
- * that text should have been interpolated with appropriate escaping,
- * sanitization and/or validation into the right location in the script, such
- * that it is highly constrained in its effect (for example, it had to match a
- * set of whitelisted words).
- *
- * A SafeScript can be constructed via security-reviewed unchecked
- * conversions. In this case producers of SafeScript must ensure themselves that
- * the SafeScript does not contain unsafe script. Note in particular that
- * {@code &lt;} is dangerous, even when inside JavaScript strings, and so should
- * always be forbidden or JavaScript escaped in user controlled input. For
- * example, if {@code &lt;/script&gt;&lt;script&gt;evil&lt;/script&gt;"} were
- * interpolated inside a JavaScript string, it would break out of the context
- * of the original script element and {@code evil} would execute. Also note
- * that within an HTML script (raw text) element, HTML character references,
- * such as "&lt;" are not allowed. See
- * http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements.
- *
- * @see goog.html.SafeScript#fromConstant
- * @constructor
- * @final
- * @struct
- * @implements {goog.string.TypedString}
- */
-goog.html.SafeScript = function() {
- /**
- * The contained value of this SafeScript. The field has a purposely
- * ugly name to make (non-compiled) code that attempts to directly access this
- * field stand out.
- * @private {string}
- */
- this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = '';
-
- /**
- * A type marker used to implement additional run-time type checking.
- * @see goog.html.SafeScript#unwrap
- * @const
- * @private
- */
- this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
- goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
-};
-
-
-/**
- * @override
- * @const
- */
-goog.html.SafeScript.prototype.implementsGoogStringTypedString = true;
+goog.debug.entryPointRegistry.refList_ = [];
/**
- * Type marker for the SafeScript type, used to implement additional
- * run-time type checking.
- * @const {!Object}
+ * Monitors that should wrap all the entry points.
+ * @type {!Array<!goog.debug.EntryPointMonitor>}
* @private
*/
-goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
-
-
-/**
- * Creates a SafeScript object from a compile-time constant string.
- *
- * @param {!goog.string.Const} script A compile-time-constant string from which
- * to create a SafeScript.
- * @return {!goog.html.SafeScript} A SafeScript object initialized to
- * {@code script}.
- */
-goog.html.SafeScript.fromConstant = function(script) {
- var scriptString = goog.string.Const.unwrap(script);
- if (scriptString.length === 0) {
- return goog.html.SafeScript.EMPTY;
- }
- return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(
- scriptString);
-};
-
-
-/**
- * Returns this SafeScript's value as a string.
- *
- * IMPORTANT: In code where it is security relevant that an object's type is
- * indeed {@code SafeScript}, use {@code goog.html.SafeScript.unwrap} instead of
- * this method. If in doubt, assume that it's security relevant. In particular,
- * note that goog.html functions which return a goog.html type do not guarantee
- * the returned instance is of the right type. For example:
- *
- * <pre>
- * var fakeSafeHtml = new String('fake');
- * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
- * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
- * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
- * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
- * // instanceof goog.html.SafeHtml.
- * </pre>
- *
- * @see goog.html.SafeScript#unwrap
- * @override
- */
-goog.html.SafeScript.prototype.getTypedStringValue = function() {
- return this.privateDoNotAccessOrElseSafeScriptWrappedValue_;
-};
-
-
-if (goog.DEBUG) {
- /**
- * Returns a debug string-representation of this value.
- *
- * To obtain the actual string value wrapped in a SafeScript, use
- * {@code goog.html.SafeScript.unwrap}.
- *
- * @see goog.html.SafeScript#unwrap
- * @override
- */
- goog.html.SafeScript.prototype.toString = function() {
- return 'SafeScript{' +
- this.privateDoNotAccessOrElseSafeScriptWrappedValue_ + '}';
- };
-}
-
-
-/**
- * Performs a runtime check that the provided object is indeed a
- * SafeScript object, and returns its value.
- *
- * @param {!goog.html.SafeScript} safeScript The object to extract from.
- * @return {string} The safeScript object's contained string, unless
- * the run-time type check fails. In that case, {@code unwrap} returns an
- * innocuous string, or, if assertions are enabled, throws
- * {@code goog.asserts.AssertionError}.
- */
-goog.html.SafeScript.unwrap = function(safeScript) {
- // Perform additional Run-time type-checking to ensure that
- // safeScript is indeed an instance of the expected type. This
- // provides some additional protection against security bugs due to
- // application code that disables type checks.
- // Specifically, the following checks are performed:
- // 1. The object is an instance of the expected type.
- // 2. The object is not an instance of a subclass.
- // 3. The object carries a type marker for the expected type. "Faking" an
- // object requires a reference to the type marker, which has names intended
- // to stand out in code reviews.
- if (safeScript instanceof goog.html.SafeScript &&
- safeScript.constructor === goog.html.SafeScript &&
- safeScript.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
- goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
- return safeScript.privateDoNotAccessOrElseSafeScriptWrappedValue_;
- } else {
- goog.asserts.fail(
- 'expected object of type SafeScript, got \'' + safeScript + '\'');
- return 'type_error:SafeScript';
- }
-};
-
-
-/**
- * Package-internal utility method to create SafeScript instances.
- *
- * @param {string} script The string to initialize the SafeScript object with.
- * @return {!goog.html.SafeScript} The initialized SafeScript object.
- * @package
- */
-goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse =
- function(script) {
- return new goog.html.SafeScript().initSecurityPrivateDoNotAccessOrElse_(
- script);
-};
+goog.debug.entryPointRegistry.monitors_ = [];
/**
- * Called from createSafeScriptSecurityPrivateDoNotAccessOrElse(). This
- * method exists only so that the compiler can dead code eliminate static
- * fields (like EMPTY) when they're not accessed.
- * @param {string} script
- * @return {!goog.html.SafeScript}
+ * Whether goog.debug.entryPointRegistry.monitorAll has ever been called.
+ * Checking this allows the compiler to optimize out the registrations.
+ * @type {boolean}
* @private
*/
-goog.html.SafeScript.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
- script) {
- this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = script;
- return this;
-};
-
-
-/**
- * A SafeScript instance corresponding to the empty string.
- * @const {!goog.html.SafeScript}
- */
-goog.html.SafeScript.EMPTY =
- goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse('');
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Unchecked conversions to create values of goog.html types from
- * plain strings. Use of these functions could potentially result in instances
- * of goog.html types that violate their type contracts, and hence result in
- * security vulnerabilties.
- *
- * Therefore, all uses of the methods herein must be carefully security
- * reviewed. Avoid use of the methods in this file whenever possible; instead
- * prefer to create instances of goog.html types using inherently safe builders
- * or template systems.
- *
- *
- *
- * @visibility {//closure/goog/html:approved_for_unchecked_conversion}
- * @visibility {//closure/goog/bin/sizetests:__pkg__}
- */
-
-
-goog.provide('goog.html.uncheckedconversions');
-
-goog.require('goog.asserts');
-goog.require('goog.html.SafeHtml');
-goog.require('goog.html.SafeScript');
-goog.require('goog.html.SafeStyle');
-goog.require('goog.html.SafeStyleSheet');
-goog.require('goog.html.SafeUrl');
-goog.require('goog.html.TrustedResourceUrl');
-goog.require('goog.string');
-goog.require('goog.string.Const');
-
-
-/**
- * Performs an "unchecked conversion" to SafeHtml from a plain string that is
- * known to satisfy the SafeHtml type contract.
- *
- * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
- * that the value of {@code html} satisfies the SafeHtml type contract in all
- * possible program states.
- *
- *
- * @param {!goog.string.Const} justification A constant string explaining why
- * this use of this method is safe. May include a security review ticket
- * number.
- * @param {string} html A string that is claimed to adhere to the SafeHtml
- * contract.
- * @param {?goog.i18n.bidi.Dir=} opt_dir The optional directionality of the
- * SafeHtml to be constructed. A null or undefined value signifies an
- * unknown directionality.
- * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml
- * object.
- * @suppress {visibility} For access to SafeHtml.create... Note that this
- * use is appropriate since this method is intended to be "package private"
- * withing goog.html. DO NOT call SafeHtml.create... from outside this
- * package; use appropriate wrappers instead.
- */
-goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract =
- function(justification, html, opt_dir) {
- // unwrap() called inside an assert so that justification can be optimized
- // away in production code.
- goog.asserts.assertString(goog.string.Const.unwrap(justification),
- 'must provide justification');
- goog.asserts.assert(
- !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
- 'must provide non-empty justification');
- return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
- html, opt_dir || null);
-};
-
-
-/**
- * Performs an "unchecked conversion" to SafeScript from a plain string that is
- * known to satisfy the SafeScript type contract.
- *
- * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
- * that the value of {@code script} satisfies the SafeScript type contract in
- * all possible program states.
- *
- *
- * @param {!goog.string.Const} justification A constant string explaining why
- * this use of this method is safe. May include a security review ticket
- * number.
- * @param {string} script The string to wrap as a SafeScript.
- * @return {!goog.html.SafeScript} The value of {@code script}, wrapped in a
- * SafeScript object.
- */
-goog.html.uncheckedconversions.safeScriptFromStringKnownToSatisfyTypeContract =
- function(justification, script) {
- // unwrap() called inside an assert so that justification can be optimized
- // away in production code.
- goog.asserts.assertString(goog.string.Const.unwrap(justification),
- 'must provide justification');
- goog.asserts.assert(
- !goog.string.isEmpty(goog.string.Const.unwrap(justification)),
- 'must provide non-empty justification');
- return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(
- script);
-};
-
-
-/**
- * Performs an "unchecked conversion" to SafeStyle from a plain string that is
- * known to satisfy the SafeStyle type contract.
- *
- * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
- * that the value of {@code style} satisfies the SafeUrl type contract in all
- * possible program states.
- *
- *
- * @param {!goog.string.Const} justification A constant string explaining why
- * this use of this method is safe. May include a security review ticket
- * number.
- * @param {string} style The string to wrap as a SafeStyle.
- * @return {!goog.html.SafeStyle} The value of {@code style}, wrapped in a
- * SafeStyle object.
- */
-goog.html.uncheckedconversions.safeStyleFromStringKnownToSatisfyTypeContract =
- function(justification, style) {
- // unwrap() called inside an assert so that justification can be optimized
- // away in production code.
- goog.asserts.assertString(goog.string.Const.unwrap(justification),
- 'must provide justification');
- goog.asserts.assert(
- !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
- 'must provide non-empty justification');
- return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
- style);
-};
-
-
-/**
- * Performs an "unchecked conversion" to SafeStyleSheet from a plain string
- * that is known to satisfy the SafeStyleSheet type contract.
- *
- * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
- * that the value of {@code styleSheet} satisfies the SafeUrl type contract in
- * all possible program states.
- *
- *
- * @param {!goog.string.Const} justification A constant string explaining why
- * this use of this method is safe. May include a security review ticket
- * number.
- * @param {string} styleSheet The string to wrap as a SafeStyleSheet.
- * @return {!goog.html.SafeStyleSheet} The value of {@code styleSheet}, wrapped
- * in a SafeStyleSheet object.
- */
-goog.html.uncheckedconversions.
- safeStyleSheetFromStringKnownToSatisfyTypeContract =
- function(justification, styleSheet) {
- // unwrap() called inside an assert so that justification can be optimized
- // away in production code.
- goog.asserts.assertString(goog.string.Const.unwrap(justification),
- 'must provide justification');
- goog.asserts.assert(
- !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
- 'must provide non-empty justification');
- return goog.html.SafeStyleSheet.
- createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet);
-};
-
-
-/**
- * Performs an "unchecked conversion" to SafeUrl from a plain string that is
- * known to satisfy the SafeUrl type contract.
- *
- * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
- * that the value of {@code url} satisfies the SafeUrl type contract in all
- * possible program states.
- *
- *
- * @param {!goog.string.Const} justification A constant string explaining why
- * this use of this method is safe. May include a security review ticket
- * number.
- * @param {string} url The string to wrap as a SafeUrl.
- * @return {!goog.html.SafeUrl} The value of {@code url}, wrapped in a SafeUrl
- * object.
- */
-goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract =
- function(justification, url) {
- // unwrap() called inside an assert so that justification can be optimized
- // away in production code.
- goog.asserts.assertString(goog.string.Const.unwrap(justification),
- 'must provide justification');
- goog.asserts.assert(
- !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
- 'must provide non-empty justification');
- return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
-};
-
-
-/**
- * Performs an "unchecked conversion" to TrustedResourceUrl from a plain string
- * that is known to satisfy the TrustedResourceUrl type contract.
- *
- * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
- * that the value of {@code url} satisfies the TrustedResourceUrl type contract
- * in all possible program states.
- *
- *
- * @param {!goog.string.Const} justification A constant string explaining why
- * this use of this method is safe. May include a security review ticket
- * number.
- * @param {string} url The string to wrap as a TrustedResourceUrl.
- * @return {!goog.html.TrustedResourceUrl} The value of {@code url}, wrapped in
- * a TrustedResourceUrl object.
- */
-goog.html.uncheckedconversions.
- trustedResourceUrlFromStringKnownToSatisfyTypeContract =
- function(justification, url) {
- // unwrap() called inside an assert so that justification can be optimized
- // away in production code.
- goog.asserts.assertString(goog.string.Const.unwrap(justification),
- 'must provide justification');
- goog.asserts.assert(
- !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
- 'must provide non-empty justification');
- return goog.html.TrustedResourceUrl.
- createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url);
-};
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Generics method for collection-like classes and objects.
- *
- * @author arv@google.com (Erik Arvidsson)
- *
- * This file contains functions to work with collections. It supports using
- * Map, Set, Array and Object and other classes that implement collection-like
- * methods.
- */
-
-
-goog.provide('goog.structs');
-
-goog.require('goog.array');
-goog.require('goog.object');
-
-
-// We treat an object as a dictionary if it has getKeys or it is an object that
-// isn't arrayLike.
-
-
-/**
- * Returns the number of values in the collection-like object.
- * @param {Object} col The collection-like object.
- * @return {number} The number of values in the collection-like object.
- */
-goog.structs.getCount = function(col) {
- if (typeof col.getCount == 'function') {
- return col.getCount();
- }
- if (goog.isArrayLike(col) || goog.isString(col)) {
- return col.length;
- }
- return goog.object.getCount(col);
-};
-
-
-/**
- * Returns the values of the collection-like object.
- * @param {Object} col The collection-like object.
- * @return {!Array<?>} The values in the collection-like object.
- */
-goog.structs.getValues = function(col) {
- if (typeof col.getValues == 'function') {
- return col.getValues();
- }
- if (goog.isString(col)) {
- return col.split('');
- }
- if (goog.isArrayLike(col)) {
- var rv = [];
- var l = col.length;
- for (var i = 0; i < l; i++) {
- rv.push(col[i]);
- }
- return rv;
- }
- return goog.object.getValues(col);
-};
-
-
-/**
- * Returns the keys of the collection. Some collections have no notion of
- * keys/indexes and this function will return undefined in those cases.
- * @param {Object} col The collection-like object.
- * @return {!Array|undefined} The keys in the collection.
- */
-goog.structs.getKeys = function(col) {
- if (typeof col.getKeys == 'function') {
- return col.getKeys();
- }
- // if we have getValues but no getKeys we know this is a key-less collection
- if (typeof col.getValues == 'function') {
- return undefined;
- }
- if (goog.isArrayLike(col) || goog.isString(col)) {
- var rv = [];
- var l = col.length;
- for (var i = 0; i < l; i++) {
- rv.push(i);
- }
- return rv;
- }
-
- return goog.object.getKeys(col);
-};
-
-
-/**
- * Whether the collection contains the given value. This is O(n) and uses
- * equals (==) to test the existence.
- * @param {Object} col The collection-like object.
- * @param {*} val The value to check for.
- * @return {boolean} True if the map contains the value.
- */
-goog.structs.contains = function(col, val) {
- if (typeof col.contains == 'function') {
- return col.contains(val);
- }
- if (typeof col.containsValue == 'function') {
- return col.containsValue(val);
- }
- if (goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.contains(/** @type {!Array<?>} */ (col), val);
- }
- return goog.object.containsValue(col, val);
-};
-
-
-/**
- * Whether the collection is empty.
- * @param {Object} col The collection-like object.
- * @return {boolean} True if empty.
- */
-goog.structs.isEmpty = function(col) {
- if (typeof col.isEmpty == 'function') {
- return col.isEmpty();
- }
-
- // We do not use goog.string.isEmptyOrWhitespace because here we treat the string as
- // collection and as such even whitespace matters
-
- if (goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.isEmpty(/** @type {!Array<?>} */ (col));
- }
- return goog.object.isEmpty(col);
-};
-
-
-/**
- * Removes all the elements from the collection.
- * @param {Object} col The collection-like object.
- */
-goog.structs.clear = function(col) {
- // NOTE(arv): This should not contain strings because strings are immutable
- if (typeof col.clear == 'function') {
- col.clear();
- } else if (goog.isArrayLike(col)) {
- goog.array.clear(/** @type {goog.array.ArrayLike} */ (col));
- } else {
- goog.object.clear(col);
- }
-};
+goog.debug.entryPointRegistry.monitorsMayExist_ = false;
/**
- * Calls a function for each value in a collection. The function takes
- * three arguments; the value, the key and the collection.
- *
- * NOTE: This will be deprecated soon! Please use a more specific method if
- * possible, e.g. goog.array.forEach, goog.object.forEach, etc.
+ * Register an entry point with this module.
*
- * @param {S} col The collection-like object.
- * @param {function(this:T,?,?,S):?} f The function to call for every value.
- * This function takes
- * 3 arguments (the value, the key or undefined if the collection has no
- * notion of keys, and the collection) and the return value is irrelevant.
- * @param {T=} opt_obj The object to be used as the value of 'this'
- * within {@code f}.
- * @template T,S
- */
-goog.structs.forEach = function(col, f, opt_obj) {
- if (typeof col.forEach == 'function') {
- col.forEach(f, opt_obj);
- } else if (goog.isArrayLike(col) || goog.isString(col)) {
- goog.array.forEach(/** @type {!Array<?>} */ (col), f, opt_obj);
- } else {
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- for (var i = 0; i < l; i++) {
- f.call(opt_obj, values[i], keys && keys[i], col);
- }
- }
-};
-
-
-/**
- * Calls a function for every value in the collection. When a call returns true,
- * adds the value to a new collection (Array is returned by default).
+ * The entry point will be instrumented when a monitor is passed to
+ * goog.debug.entryPointRegistry.monitorAll. If this has already occurred, the
+ * entry point is instrumented immediately.
*
- * @param {S} col The collection-like object.
- * @param {function(this:T,?,?,S):boolean} f The function to call for every
- * value. This function takes
- * 3 arguments (the value, the key or undefined if the collection has no
- * notion of keys, and the collection) and should return a Boolean. If the
- * return value is true the value is added to the result collection. If it
- * is false the value is not included.
- * @param {T=} opt_obj The object to be used as the value of 'this'
- * within {@code f}.
- * @return {!Object|!Array<?>} A new collection where the passed values are
- * present. If col is a key-less collection an array is returned. If col
- * has keys and values a plain old JS object is returned.
- * @template T,S
+ * @param {function(!Function)} callback A callback function which is called
+ * with a transforming function to instrument the entry point. The callback
+ * is responsible for wrapping the relevant entry point with the
+ * transforming function.
*/
-goog.structs.filter = function(col, f, opt_obj) {
- if (typeof col.filter == 'function') {
- return col.filter(f, opt_obj);
- }
- if (goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.filter(/** @type {!Array<?>} */ (col), f, opt_obj);
- }
-
- var rv;
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- if (keys) {
- rv = {};
- for (var i = 0; i < l; i++) {
- if (f.call(opt_obj, values[i], keys[i], col)) {
- rv[keys[i]] = values[i];
- }
- }
- } else {
- // We should not use goog.array.filter here since we want to make sure that
- // the index is undefined as well as make sure that col is passed to the
- // function.
- rv = [];
- for (var i = 0; i < l; i++) {
- if (f.call(opt_obj, values[i], undefined, col)) {
- rv.push(values[i]);
- }
+goog.debug.entryPointRegistry.register = function(callback) {
+ // Don't use push(), so that this can be compiled out.
+ goog.debug.entryPointRegistry
+ .refList_[goog.debug.entryPointRegistry.refList_.length] = callback;
+ // If no one calls monitorAll, this can be compiled out.
+ if (goog.debug.entryPointRegistry.monitorsMayExist_) {
+ var monitors = goog.debug.entryPointRegistry.monitors_;
+ for (var i = 0; i < monitors.length; i++) {
+ callback(goog.bind(monitors[i].wrap, monitors[i]));
}
}
- return rv;
};
/**
- * Calls a function for every value in the collection and adds the result into a
- * new collection (defaults to creating a new Array).
+ * Configures a monitor to wrap all entry points.
*
- * @param {S} col The collection-like object.
- * @param {function(this:T,?,?,S):V} f The function to call for every value.
- * This function takes 3 arguments (the value, the key or undefined if the
- * collection has no notion of keys, and the collection) and should return
- * something. The result will be used as the value in the new collection.
- * @param {T=} opt_obj The object to be used as the value of 'this'
- * within {@code f}.
- * @return {!Object<V>|!Array<V>} A new collection with the new values. If
- * col is a key-less collection an array is returned. If col has keys and
- * values a plain old JS object is returned.
- * @template T,S,V
- */
-goog.structs.map = function(col, f, opt_obj) {
- if (typeof col.map == 'function') {
- return col.map(f, opt_obj);
- }
- if (goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.map(/** @type {!Array<?>} */ (col), f, opt_obj);
- }
-
- var rv;
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- if (keys) {
- rv = {};
- for (var i = 0; i < l; i++) {
- rv[keys[i]] = f.call(opt_obj, values[i], keys[i], col);
- }
- } else {
- // We should not use goog.array.map here since we want to make sure that
- // the index is undefined as well as make sure that col is passed to the
- // function.
- rv = [];
- for (var i = 0; i < l; i++) {
- rv[i] = f.call(opt_obj, values[i], undefined, col);
- }
- }
- return rv;
-};
-
-
-/**
- * Calls f for each value in a collection. If any call returns true this returns
- * true (without checking the rest). If all returns false this returns false.
+ * Entry points that have already been registered are immediately wrapped by
+ * the monitor. When an entry point is registered in the future, it will also
+ * be wrapped by the monitor when it is registered.
*
- * @param {S} col The collection-like object.
- * @param {function(this:T,?,?,S):boolean} f The function to call for every
- * value. This function takes 3 arguments (the value, the key or undefined
- * if the collection has no notion of keys, and the collection) and should
- * return a boolean.
- * @param {T=} opt_obj The object to be used as the value of 'this'
- * within {@code f}.
- * @return {boolean} True if any value passes the test.
- * @template T,S
+ * @param {!goog.debug.EntryPointMonitor} monitor An entry point monitor.
*/
-goog.structs.some = function(col, f, opt_obj) {
- if (typeof col.some == 'function') {
- return col.some(f, opt_obj);
- }
- if (goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.some(/** @type {!Array<?>} */ (col), f, opt_obj);
- }
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- for (var i = 0; i < l; i++) {
- if (f.call(opt_obj, values[i], keys && keys[i], col)) {
- return true;
- }
+goog.debug.entryPointRegistry.monitorAll = function(monitor) {
+ goog.debug.entryPointRegistry.monitorsMayExist_ = true;
+ var transformer = goog.bind(monitor.wrap, monitor);
+ for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
+ goog.debug.entryPointRegistry.refList_[i](transformer);
}
- return false;
+ goog.debug.entryPointRegistry.monitors_.push(monitor);
};
/**
- * Calls f for each value in a collection. If all calls return true this return
- * true this returns true. If any returns false this returns false at this point
- * and does not continue to check the remaining values.
+ * Try to unmonitor all the entry points that have already been registered. If
+ * an entry point is registered in the future, it will not be wrapped by the
+ * monitor when it is registered. Note that this may fail if the entry points
+ * have additional wrapping.
*
- * @param {S} col The collection-like object.
- * @param {function(this:T,?,?,S):boolean} f The function to call for every
- * value. This function takes 3 arguments (the value, the key or
- * undefined if the collection has no notion of keys, and the collection)
- * and should return a boolean.
- * @param {T=} opt_obj The object to be used as the value of 'this'
- * within {@code f}.
- * @return {boolean} True if all key-value pairs pass the test.
- * @template T,S
+ * @param {!goog.debug.EntryPointMonitor} monitor The last monitor to wrap
+ * the entry points.
+ * @throws {Error} If the monitor is not the most recently configured monitor.
*/
-goog.structs.every = function(col, f, opt_obj) {
- if (typeof col.every == 'function') {
- return col.every(f, opt_obj);
- }
- if (goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.every(/** @type {!Array<?>} */ (col), f, opt_obj);
- }
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- for (var i = 0; i < l; i++) {
- if (!f.call(opt_obj, values[i], keys && keys[i], col)) {
- return false;
- }
+goog.debug.entryPointRegistry.unmonitorAllIfPossible = function(monitor) {
+ var monitors = goog.debug.entryPointRegistry.monitors_;
+ goog.asserts.assert(
+ monitor == monitors[monitors.length - 1],
+ 'Only the most recent monitor can be unwrapped.');
+ var transformer = goog.bind(monitor.unwrap, monitor);
+ for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
+ goog.debug.entryPointRegistry.refList_[i](transformer);
}
- return true;
+ monitors.length--;
};
-// Copyright 2011 The Closure Library Authors. All Rights Reserved.
+// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -40752,4093 +37273,449 @@ goog.structs.every = function(col, f, opt_obj) {
// limitations under the License.
/**
- * @fileoverview Defines the collection interface.
+ * @fileoverview Utilities for creating functions. Loosely inspired by the
+ * java classes: http://goo.gl/GM0Hmu and http://goo.gl/6k7nI8.
*
- * @author nnaze@google.com (Nathan Naze)
+ * @author nicksantos@google.com (Nick Santos)
*/
-goog.provide('goog.structs.Collection');
+goog.provide('goog.functions');
/**
- * An interface for a collection of values.
- * @interface
+ * Creates a function that always returns the same value.
+ * @param {T} retValue The value to return.
+ * @return {function():T} The new function.
* @template T
*/
-goog.structs.Collection = function() {};
-
-
-/**
- * @param {T} value Value to add to the collection.
- */
-goog.structs.Collection.prototype.add;
-
-
-/**
- * @param {T} value Value to remove from the collection.
- */
-goog.structs.Collection.prototype.remove;
-
-
-/**
- * @param {T} value Value to find in the collection.
- * @return {boolean} Whether the collection contains the specified value.
- */
-goog.structs.Collection.prototype.contains;
-
-
-/**
- * @return {number} The number of values stored in the collection.
- */
-goog.structs.Collection.prototype.getCount;
-
-
-// Copyright 2007 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Python style iteration utilities.
- * @author arv@google.com (Erik Arvidsson)
- */
-
-
-goog.provide('goog.iter');
-goog.provide('goog.iter.Iterable');
-goog.provide('goog.iter.Iterator');
-goog.provide('goog.iter.StopIteration');
-
-goog.require('goog.array');
-goog.require('goog.asserts');
-goog.require('goog.functions');
-goog.require('goog.math');
-
-
-/**
- * @typedef {goog.iter.Iterator|{length:number}|{__iterator__}}
- */
-goog.iter.Iterable;
+goog.functions.constant = function(retValue) {
+ return function() { return retValue; };
+};
/**
- * Singleton Error object that is used to terminate iterations.
- * @const {!Error}
+ * Always returns false.
+ * @type {function(...): boolean}
*/
-goog.iter.StopIteration = ('StopIteration' in goog.global) ?
- // For script engines that support legacy iterators.
- goog.global['StopIteration'] :
- { message: 'StopIteration', stack: ''};
-
+goog.functions.FALSE = goog.functions.constant(false);
/**
- * Class/interface for iterators. An iterator needs to implement a {@code next}
- * method and it needs to throw a {@code goog.iter.StopIteration} when the
- * iteration passes beyond the end. Iterators have no {@code hasNext} method.
- * It is recommended to always use the helper functions to iterate over the
- * iterator or in case you are only targeting JavaScript 1.7 for in loops.
- * @constructor
- * @template VALUE
+ * Always returns true.
+ * @type {function(...): boolean}
*/
-goog.iter.Iterator = function() {};
+goog.functions.TRUE = goog.functions.constant(true);
/**
- * Returns the next value of the iteration. This will throw the object
- * {@see goog.iter#StopIteration} when the iteration passes the end.
- * @return {VALUE} Any object or value.
+ * Always returns NULL.
+ * @type {function(...): null}
*/
-goog.iter.Iterator.prototype.next = function() {
- throw goog.iter.StopIteration;
-};
+goog.functions.NULL = goog.functions.constant(null);
/**
- * Returns the {@code Iterator} object itself. This is used to implement
- * the iterator protocol in JavaScript 1.7
- * @param {boolean=} opt_keys Whether to return the keys or values. Default is
- * to only return the values. This is being used by the for-in loop (true)
- * and the for-each-in loop (false). Even though the param gives a hint
- * about what the iterator will return there is no guarantee that it will
- * return the keys when true is passed.
- * @return {!goog.iter.Iterator<VALUE>} The object itself.
+ * A simple function that returns the first argument of whatever is passed
+ * into it.
+ * @param {T=} opt_returnValue The single value that will be returned.
+ * @param {...*} var_args Optional trailing arguments. These are ignored.
+ * @return {T} The first argument passed in, or undefined if nothing was passed.
+ * @template T
*/
-goog.iter.Iterator.prototype.__iterator__ = function(opt_keys) {
- return this;
+goog.functions.identity = function(opt_returnValue, var_args) {
+ return opt_returnValue;
};
/**
- * Returns an iterator that knows how to iterate over the values in the object.
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable If the
- * object is an iterator it will be returned as is. If the object has an
- * {@code __iterator__} method that will be called to get the value
- * iterator. If the object is an array-like object we create an iterator
- * for that.
- * @return {!goog.iter.Iterator<VALUE>} An iterator that knows how to iterate
- * over the values in {@code iterable}.
- * @template VALUE
+ * Creates a function that always throws an error with the given message.
+ * @param {string} message The error message.
+ * @return {!Function} The error-throwing function.
*/
-goog.iter.toIterator = function(iterable) {
- if (iterable instanceof goog.iter.Iterator) {
- return iterable;
- }
- if (typeof iterable.__iterator__ == 'function') {
- return iterable.__iterator__(false);
- }
- if (goog.isArrayLike(iterable)) {
- var i = 0;
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- while (true) {
- if (i >= iterable.length) {
- throw goog.iter.StopIteration;
- }
- // Don't include deleted elements.
- if (!(i in iterable)) {
- i++;
- continue;
- }
- return iterable[i++];
- }
- };
- return newIter;
- }
-
-
- // TODO(arv): Should we fall back on goog.structs.getValues()?
- throw Error('Not implemented');
+goog.functions.error = function(message) {
+ return function() { throw Error(message); };
};
/**
- * Calls a function for each element in the iterator with the element of the
- * iterator passed as argument.
- *
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * to iterate over. If the iterable is an object {@code toIterator} will be
- * called on it.
- * @param {function(this:THIS,VALUE,?,!goog.iter.Iterator<VALUE>)} f
- * The function to call for every element. This function takes 3 arguments
- * (the element, undefined, and the iterator) and the return value is
- * irrelevant. The reason for passing undefined as the second argument is
- * so that the same function can be used in {@see goog.array#forEach} as
- * well as others. The third parameter is of type "number" for
- * arraylike objects, undefined, otherwise.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * {@code f}.
- * @template THIS, VALUE
+ * Creates a function that throws the given object.
+ * @param {*} err An object to be thrown.
+ * @return {!Function} The error-throwing function.
*/
-goog.iter.forEach = function(iterable, f, opt_obj) {
- if (goog.isArrayLike(iterable)) {
- /** @preserveTry */
- try {
- // NOTES: this passes the index number to the second parameter
- // of the callback contrary to the documentation above.
- goog.array.forEach(/** @type {goog.array.ArrayLike} */(iterable), f,
- opt_obj);
- } catch (ex) {
- if (ex !== goog.iter.StopIteration) {
- throw ex;
- }
- }
- } else {
- iterable = goog.iter.toIterator(iterable);
- /** @preserveTry */
- try {
- while (true) {
- f.call(opt_obj, iterable.next(), undefined, iterable);
- }
- } catch (ex) {
- if (ex !== goog.iter.StopIteration) {
- throw ex;
- }
- }
- }
+goog.functions.fail = function(err) {
+ return function() { throw err; }
};
/**
- * Calls a function for every element in the iterator, and if the function
- * returns true adds the element to a new iterator.
- *
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * to iterate over.
- * @param {
- * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
- * The function to call for every element. This function takes 3 arguments
- * (the element, undefined, and the iterator) and should return a boolean.
- * If the return value is true the element will be included in the returned
- * iterator. If it is false the element is not included.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * {@code f}.
- * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements
- * that passed the test are present.
- * @template THIS, VALUE
+ * Given a function, create a function that keeps opt_numArgs arguments and
+ * silently discards all additional arguments.
+ * @param {Function} f The original function.
+ * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.
+ * @return {!Function} A version of f that only keeps the first opt_numArgs
+ * arguments.
*/
-goog.iter.filter = function(iterable, f, opt_obj) {
- var iterator = goog.iter.toIterator(iterable);
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- while (true) {
- var val = iterator.next();
- if (f.call(opt_obj, val, undefined, iterator)) {
- return val;
- }
- }
+goog.functions.lock = function(f, opt_numArgs) {
+ opt_numArgs = opt_numArgs || 0;
+ return function() {
+ return f.apply(this, Array.prototype.slice.call(arguments, 0, opt_numArgs));
};
- return newIter;
};
/**
- * Calls a function for every element in the iterator, and if the function
- * returns false adds the element to a new iterator.
- *
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * to iterate over.
- * @param {
- * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
- * The function to call for every element. This function takes 3 arguments
- * (the element, undefined, and the iterator) and should return a boolean.
- * If the return value is false the element will be included in the returned
- * iterator. If it is true the element is not included.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * {@code f}.
- * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements
- * that did not pass the test are present.
- * @template THIS, VALUE
+ * Creates a function that returns its nth argument.
+ * @param {number} n The position of the return argument.
+ * @return {!Function} A new function.
*/
-goog.iter.filterFalse = function(iterable, f, opt_obj) {
- return goog.iter.filter(iterable, goog.functions.not(f), opt_obj);
+goog.functions.nth = function(n) {
+ return function() { return arguments[n]; };
};
/**
- * Creates a new iterator that returns the values in a range. This function
- * can take 1, 2 or 3 arguments:
- * <pre>
- * range(5) same as range(0, 5, 1)
- * range(2, 5) same as range(2, 5, 1)
- * </pre>
+ * Like goog.partial(), except that arguments are added after arguments to the
+ * returned function.
*
- * @param {number} startOrStop The stop value if only one argument is provided.
- * The start value if 2 or more arguments are provided. If only one
- * argument is used the start value is 0.
- * @param {number=} opt_stop The stop value. If left out then the first
- * argument is used as the stop value.
- * @param {number=} opt_step The number to increment with between each call to
- * next. This can be negative.
- * @return {!goog.iter.Iterator<number>} A new iterator that returns the values
- * in the range.
- */
-goog.iter.range = function(startOrStop, opt_stop, opt_step) {
- var start = 0;
- var stop = startOrStop;
- var step = opt_step || 1;
- if (arguments.length > 1) {
- start = startOrStop;
- stop = opt_stop;
- }
- if (step == 0) {
- throw Error('Range step argument must not be zero');
- }
-
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- if (step > 0 && start >= stop || step < 0 && start <= stop) {
- throw goog.iter.StopIteration;
- }
- var rv = start;
- start += step;
- return rv;
- };
- return newIter;
-};
-
-
-/**
- * Joins the values in a iterator with a delimiter.
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * to get the values from.
- * @param {string} deliminator The text to put between the values.
- * @return {string} The joined value string.
- * @template VALUE
- */
-goog.iter.join = function(iterable, deliminator) {
- return goog.iter.toArray(iterable).join(deliminator);
-};
-
-
-/**
- * For every element in the iterator call a function and return a new iterator
- * with that value.
+ * Usage:
+ * function f(arg1, arg2, arg3, arg4) { ... }
+ * var g = goog.functions.partialRight(f, arg3, arg4);
+ * g(arg1, arg2);
*
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterator to iterate over.
- * @param {
- * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):RESULT} f
- * The function to call for every element. This function takes 3 arguments
- * (the element, undefined, and the iterator) and should return a new value.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * {@code f}.
- * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the
- * results of applying the function to each element in the original
- * iterator.
- * @template THIS, VALUE, RESULT
+ * @param {!Function} fn A function to partially apply.
+ * @param {...*} var_args Additional arguments that are partially applied to fn
+ * at the end.
+ * @return {!Function} A partially-applied form of the function goog.partial()
+ * was invoked as a method of.
*/
-goog.iter.map = function(iterable, f, opt_obj) {
- var iterator = goog.iter.toIterator(iterable);
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- var val = iterator.next();
- return f.call(opt_obj, val, undefined, iterator);
+goog.functions.partialRight = function(fn, var_args) {
+ var rightArgs = Array.prototype.slice.call(arguments, 1);
+ return function() {
+ var newArgs = Array.prototype.slice.call(arguments);
+ newArgs.push.apply(newArgs, rightArgs);
+ return fn.apply(this, newArgs);
};
- return newIter;
};
/**
- * Passes every element of an iterator into a function and accumulates the
- * result.
- *
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * to iterate over.
- * @param {function(this:THIS,VALUE,VALUE):VALUE} f The function to call for
- * every element. This function takes 2 arguments (the function's previous
- * result or the initial value, and the value of the current element).
- * function(previousValue, currentElement) : newValue.
- * @param {VALUE} val The initial value to pass into the function on the first
- * call.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * f.
- * @return {VALUE} Result of evaluating f repeatedly across the values of
- * the iterator.
- * @template THIS, VALUE
+ * Given a function, create a new function that swallows its return value
+ * and replaces it with a new one.
+ * @param {Function} f A function.
+ * @param {T} retValue A new return value.
+ * @return {function(...?):T} A new function.
+ * @template T
*/
-goog.iter.reduce = function(iterable, f, val, opt_obj) {
- var rval = val;
- goog.iter.forEach(iterable, function(val) {
- rval = f.call(opt_obj, rval, val);
- });
- return rval;
+goog.functions.withReturnValue = function(f, retValue) {
+ return goog.functions.sequence(f, goog.functions.constant(retValue));
};
/**
- * Goes through the values in the iterator. Calls f for each of these, and if
- * any of them returns true, this returns true (without checking the rest). If
- * all return false this will return false.
+ * Creates a function that returns whether its arguement equals the given value.
*
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * object.
- * @param {
- * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
- * The function to call for every value. This function takes 3 arguments
- * (the value, undefined, and the iterator) and should return a boolean.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * {@code f}.
- * @return {boolean} true if any value passes the test.
- * @template THIS, VALUE
- */
-goog.iter.some = function(iterable, f, opt_obj) {
- iterable = goog.iter.toIterator(iterable);
- /** @preserveTry */
- try {
- while (true) {
- if (f.call(opt_obj, iterable.next(), undefined, iterable)) {
- return true;
- }
- }
- } catch (ex) {
- if (ex !== goog.iter.StopIteration) {
- throw ex;
- }
- }
- return false;
-};
-
-
-/**
- * Goes through the values in the iterator. Calls f for each of these and if any
- * of them returns false this returns false (without checking the rest). If all
- * return true this will return true.
+ * Example:
+ * var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));
*
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * object.
- * @param {
- * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
- * The function to call for every value. This function takes 3 arguments
- * (the value, undefined, and the iterator) and should return a boolean.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * {@code f}.
- * @return {boolean} true if every value passes the test.
- * @template THIS, VALUE
- */
-goog.iter.every = function(iterable, f, opt_obj) {
- iterable = goog.iter.toIterator(iterable);
- /** @preserveTry */
- try {
- while (true) {
- if (!f.call(opt_obj, iterable.next(), undefined, iterable)) {
- return false;
- }
- }
- } catch (ex) {
- if (ex !== goog.iter.StopIteration) {
- throw ex;
- }
- }
- return true;
-};
-
-
-/**
- * Takes zero or more iterables and returns one iterator that will iterate over
- * them in the order chained.
- * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
- * number of iterable objects.
- * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will
- * iterate over all the given iterables' contents.
- * @template VALUE
- */
-goog.iter.chain = function(var_args) {
- return goog.iter.chainFromIterable(arguments);
-};
-
-
-/**
- * Takes a single iterable containing zero or more iterables and returns one
- * iterator that will iterate over each one in the order given.
- * @see http://docs.python.org/2/library/itertools.html#itertools.chain.from_iterable
- * @param {goog.iter.Iterable} iterable The iterable of iterables to chain.
- * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will
- * iterate over all the contents of the iterables contained within
- * {@code iterable}.
- * @template VALUE
- */
-goog.iter.chainFromIterable = function(iterable) {
- var iterator = goog.iter.toIterator(iterable);
- var iter = new goog.iter.Iterator();
- var current = null;
-
- iter.next = function() {
- while (true) {
- if (current == null) {
- var it = iterator.next();
- current = goog.iter.toIterator(it);
- }
- try {
- return current.next();
- } catch (ex) {
- if (ex !== goog.iter.StopIteration) {
- throw ex;
- }
- current = null;
- }
- }
- };
-
- return iter;
-};
-
-
-/**
- * Builds a new iterator that iterates over the original, but skips elements as
- * long as a supplied function returns true.
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * object.
- * @param {
- * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
- * The function to call for every value. This function takes 3 arguments
- * (the value, undefined, and the iterator) and should return a boolean.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * {@code f}.
- * @return {!goog.iter.Iterator<VALUE>} A new iterator that drops elements from
- * the original iterator as long as {@code f} is true.
- * @template THIS, VALUE
- */
-goog.iter.dropWhile = function(iterable, f, opt_obj) {
- var iterator = goog.iter.toIterator(iterable);
- var newIter = new goog.iter.Iterator;
- var dropping = true;
- newIter.next = function() {
- while (true) {
- var val = iterator.next();
- if (dropping && f.call(opt_obj, val, undefined, iterator)) {
- continue;
- } else {
- dropping = false;
- }
- return val;
- }
- };
- return newIter;
-};
-
-
-/**
- * Builds a new iterator that iterates over the original, but only as long as a
- * supplied function returns true.
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * object.
- * @param {
- * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
- * The function to call for every value. This function takes 3 arguments
- * (the value, undefined, and the iterator) and should return a boolean.
- * @param {THIS=} opt_obj This is used as the 'this' object in f when called.
- * @return {!goog.iter.Iterator<VALUE>} A new iterator that keeps elements in
- * the original iterator as long as the function is true.
- * @template THIS, VALUE
+ * @param {*} value The value to compare to.
+ * @param {boolean=} opt_useLooseComparison Whether to use a loose (==)
+ * comparison rather than a strict (===) one. Defaults to false.
+ * @return {function(*):boolean} The new function.
*/
-goog.iter.takeWhile = function(iterable, f, opt_obj) {
- var iterator = goog.iter.toIterator(iterable);
- var iter = new goog.iter.Iterator();
- iter.next = function() {
- var val = iterator.next();
- if (f.call(opt_obj, val, undefined, iterator)) {
- return val;
- }
- throw goog.iter.StopIteration;
+goog.functions.equalTo = function(value, opt_useLooseComparison) {
+ return function(other) {
+ return opt_useLooseComparison ? (value == other) : (value === other);
};
- return iter;
-};
-
-
-/**
- * Converts the iterator to an array
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
- * to convert to an array.
- * @return {!Array<VALUE>} An array of the elements the iterator iterates over.
- * @template VALUE
- */
-goog.iter.toArray = function(iterable) {
- // Fast path for array-like.
- if (goog.isArrayLike(iterable)) {
- return goog.array.toArray(/** @type {!goog.array.ArrayLike} */(iterable));
- }
- iterable = goog.iter.toIterator(iterable);
- var array = [];
- goog.iter.forEach(iterable, function(val) {
- array.push(val);
- });
- return array;
-};
-
-
-/**
- * Iterates over two iterables and returns true if they contain the same
- * sequence of elements and have the same length.
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable1 The first
- * iterable object.
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable2 The second
- * iterable object.
- * @param {function(VALUE,VALUE):boolean=} opt_equalsFn Optional comparison
- * function.
- * Should take two arguments to compare, and return true if the arguments
- * are equal. Defaults to {@link goog.array.defaultCompareEquality} which
- * compares the elements using the built-in '===' operator.
- * @return {boolean} true if the iterables contain the same sequence of elements
- * and have the same length.
- * @template VALUE
- */
-goog.iter.equals = function(iterable1, iterable2, opt_equalsFn) {
- var fillValue = {};
- var pairs = goog.iter.zipLongest(fillValue, iterable1, iterable2);
- var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
- return goog.iter.every(pairs, function(pair) {
- return equalsFn(pair[0], pair[1]);
- });
};
/**
- * Advances the iterator to the next position, returning the given default value
- * instead of throwing an exception if the iterator has no more entries.
- * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterable
- * object.
- * @param {VALUE} defaultValue The value to return if the iterator is empty.
- * @return {VALUE} The next item in the iteration, or defaultValue if the
- * iterator was empty.
- * @template VALUE
+ * Creates the composition of the functions passed in.
+ * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
+ * @param {function(...?):T} fn The final function.
+ * @param {...Function} var_args A list of functions.
+ * @return {function(...?):T} The composition of all inputs.
+ * @template T
*/
-goog.iter.nextOrValue = function(iterable, defaultValue) {
- try {
- return goog.iter.toIterator(iterable).next();
- } catch (e) {
- if (e != goog.iter.StopIteration) {
- throw e;
+goog.functions.compose = function(fn, var_args) {
+ var functions = arguments;
+ var length = functions.length;
+ return function() {
+ var result;
+ if (length) {
+ result = functions[length - 1].apply(this, arguments);
}
- return defaultValue;
- }
-};
-
-
-/**
- * Cartesian product of zero or more sets. Gives an iterator that gives every
- * combination of one element chosen from each set. For example,
- * ([1, 2], [3, 4]) gives ([1, 3], [1, 4], [2, 3], [2, 4]).
- * @see http://docs.python.org/library/itertools.html#itertools.product
- * @param {...!goog.array.ArrayLike<VALUE>} var_args Zero or more sets, as
- * arrays.
- * @return {!goog.iter.Iterator<!Array<VALUE>>} An iterator that gives each
- * n-tuple (as an array).
- * @template VALUE
- */
-goog.iter.product = function(var_args) {
- var someArrayEmpty = goog.array.some(arguments, function(arr) {
- return !arr.length;
- });
-
- // An empty set in a cartesian product gives an empty set.
- if (someArrayEmpty || !arguments.length) {
- return new goog.iter.Iterator();
- }
-
- var iter = new goog.iter.Iterator();
- var arrays = arguments;
-
- // The first indices are [0, 0, ...]
- var indicies = goog.array.repeat(0, arrays.length);
-
- iter.next = function() {
-
- if (indicies) {
- var retVal = goog.array.map(indicies, function(valueIndex, arrayIndex) {
- return arrays[arrayIndex][valueIndex];
- });
- // Generate the next-largest indices for the next call.
- // Increase the rightmost index. If it goes over, increase the next
- // rightmost (like carry-over addition).
- for (var i = indicies.length - 1; i >= 0; i--) {
- // Assertion prevents compiler warning below.
- goog.asserts.assert(indicies);
- if (indicies[i] < arrays[i].length - 1) {
- indicies[i]++;
- break;
- }
-
- // We're at the last indices (the last element of every array), so
- // the iteration is over on the next call.
- if (i == 0) {
- indicies = null;
- break;
- }
- // Reset the index in this column and loop back to increment the
- // next one.
- indicies[i] = 0;
- }
- return retVal;
+ for (var i = length - 2; i >= 0; i--) {
+ result = functions[i].call(this, result);
}
-
- throw goog.iter.StopIteration;
+ return result;
};
-
- return iter;
};
/**
- * Create an iterator to cycle over the iterable's elements indefinitely.
- * For example, ([1, 2, 3]) would return : 1, 2, 3, 1, 2, 3, ...
- * @see: http://docs.python.org/library/itertools.html#itertools.cycle.
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable object.
- * @return {!goog.iter.Iterator<VALUE>} An iterator that iterates indefinitely
- * over the values in {@code iterable}.
- * @template VALUE
+ * Creates a function that calls the functions passed in in sequence, and
+ * returns the value of the last function. For example,
+ * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).
+ * @param {...Function} var_args A list of functions.
+ * @return {!Function} A function that calls all inputs in sequence.
*/
-goog.iter.cycle = function(iterable) {
- var baseIterator = goog.iter.toIterator(iterable);
-
- // We maintain a cache to store the iterable elements as we iterate
- // over them. The cache is used to return elements once we have
- // iterated over the iterable once.
- var cache = [];
- var cacheIndex = 0;
-
- var iter = new goog.iter.Iterator();
-
- // This flag is set after the iterable is iterated over once
- var useCache = false;
-
- iter.next = function() {
- var returnElement = null;
-
- // Pull elements off the original iterator if not using cache
- if (!useCache) {
- try {
- // Return the element from the iterable
- returnElement = baseIterator.next();
- cache.push(returnElement);
- return returnElement;
- } catch (e) {
- // If an exception other than StopIteration is thrown
- // or if there are no elements to iterate over (the iterable was empty)
- // throw an exception
- if (e != goog.iter.StopIteration || goog.array.isEmpty(cache)) {
- throw e;
- }
- // set useCache to true after we know that a 'StopIteration' exception
- // was thrown and the cache is not empty (to handle the 'empty iterable'
- // use case)
- useCache = true;
- }
+goog.functions.sequence = function(var_args) {
+ var functions = arguments;
+ var length = functions.length;
+ return function() {
+ var result;
+ for (var i = 0; i < length; i++) {
+ result = functions[i].apply(this, arguments);
}
-
- returnElement = cache[cacheIndex];
- cacheIndex = (cacheIndex + 1) % cache.length;
-
- return returnElement;
- };
-
- return iter;
-};
-
-
-/**
- * Creates an iterator that counts indefinitely from a starting value.
- * @see http://docs.python.org/2/library/itertools.html#itertools.count
- * @param {number=} opt_start The starting value. Default is 0.
- * @param {number=} opt_step The number to increment with between each call to
- * next. Negative and floating point numbers are allowed. Default is 1.
- * @return {!goog.iter.Iterator<number>} A new iterator that returns the values
- * in the series.
- */
-goog.iter.count = function(opt_start, opt_step) {
- var counter = opt_start || 0;
- var step = goog.isDef(opt_step) ? opt_step : 1;
- var iter = new goog.iter.Iterator();
-
- iter.next = function() {
- var returnValue = counter;
- counter += step;
- return returnValue;
- };
-
- return iter;
-};
-
-
-/**
- * Creates an iterator that returns the same object or value repeatedly.
- * @param {VALUE} value Any object or value to repeat.
- * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the
- * repeated value.
- * @template VALUE
- */
-goog.iter.repeat = function(value) {
- var iter = new goog.iter.Iterator();
-
- iter.next = goog.functions.constant(value);
-
- return iter;
-};
-
-
-/**
- * Creates an iterator that returns running totals from the numbers in
- * {@code iterable}. For example, the array {@code [1, 2, 3, 4, 5]} yields
- * {@code 1 -> 3 -> 6 -> 10 -> 15}.
- * @see http://docs.python.org/3.2/library/itertools.html#itertools.accumulate
- * @param {!goog.iter.Iterable<number>} iterable The iterable of numbers to
- * accumulate.
- * @return {!goog.iter.Iterator<number>} A new iterator that returns the
- * numbers in the series.
- */
-goog.iter.accumulate = function(iterable) {
- var iterator = goog.iter.toIterator(iterable);
- var total = 0;
- var iter = new goog.iter.Iterator();
-
- iter.next = function() {
- total += iterator.next();
- return total;
+ return result;
};
-
- return iter;
-};
-
-
-/**
- * Creates an iterator that returns arrays containing the ith elements from the
- * provided iterables. The returned arrays will be the same size as the number
- * of iterables given in {@code var_args}. Once the shortest iterable is
- * exhausted, subsequent calls to {@code next()} will throw
- * {@code goog.iter.StopIteration}.
- * @see http://docs.python.org/2/library/itertools.html#itertools.izip
- * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
- * number of iterable objects.
- * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns
- * arrays of elements from the provided iterables.
- * @template VALUE
- */
-goog.iter.zip = function(var_args) {
- var args = arguments;
- var iter = new goog.iter.Iterator();
-
- if (args.length > 0) {
- var iterators = goog.array.map(args, goog.iter.toIterator);
- iter.next = function() {
- var arr = goog.array.map(iterators, function(it) {
- return it.next();
- });
- return arr;
- };
- }
-
- return iter;
-};
-
-
-/**
- * Creates an iterator that returns arrays containing the ith elements from the
- * provided iterables. The returned arrays will be the same size as the number
- * of iterables given in {@code var_args}. Shorter iterables will be extended
- * with {@code fillValue}. Once the longest iterable is exhausted, subsequent
- * calls to {@code next()} will throw {@code goog.iter.StopIteration}.
- * @see http://docs.python.org/2/library/itertools.html#itertools.izip_longest
- * @param {VALUE} fillValue The object or value used to fill shorter iterables.
- * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
- * number of iterable objects.
- * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns
- * arrays of elements from the provided iterables.
- * @template VALUE
- */
-goog.iter.zipLongest = function(fillValue, var_args) {
- var args = goog.array.slice(arguments, 1);
- var iter = new goog.iter.Iterator();
-
- if (args.length > 0) {
- var iterators = goog.array.map(args, goog.iter.toIterator);
-
- iter.next = function() {
- var iteratorsHaveValues = false; // false when all iterators are empty.
- var arr = goog.array.map(iterators, function(it) {
- var returnValue;
- try {
- returnValue = it.next();
- // Iterator had a value, so we've not exhausted the iterators.
- // Set flag accordingly.
- iteratorsHaveValues = true;
- } catch (ex) {
- if (ex !== goog.iter.StopIteration) {
- throw ex;
- }
- returnValue = fillValue;
- }
- return returnValue;
- });
-
- if (!iteratorsHaveValues) {
- throw goog.iter.StopIteration;
- }
- return arr;
- };
- }
-
- return iter;
};
/**
- * Creates an iterator that filters {@code iterable} based on a series of
- * {@code selectors}. On each call to {@code next()}, one item is taken from
- * both the {@code iterable} and {@code selectors} iterators. If the item from
- * {@code selectors} evaluates to true, the item from {@code iterable} is given.
- * Otherwise, it is skipped. Once either {@code iterable} or {@code selectors}
- * is exhausted, subsequent calls to {@code next()} will throw
- * {@code goog.iter.StopIteration}.
- * @see http://docs.python.org/2/library/itertools.html#itertools.compress
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to filter.
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} selectors An
- * iterable of items to be evaluated in a boolean context to determine if
- * the corresponding element in {@code iterable} should be included in the
- * result.
- * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the
- * filtered values.
- * @template VALUE
- */
-goog.iter.compress = function(iterable, selectors) {
- var selectorIterator = goog.iter.toIterator(selectors);
-
- return goog.iter.filter(iterable, function() {
- return !!selectorIterator.next();
- });
-};
-
-
-
-/**
- * Implements the {@code goog.iter.groupBy} iterator.
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to group.
- * @param {function(...VALUE): KEY=} opt_keyFunc Optional function for
- * determining the key value for each group in the {@code iterable}. Default
- * is the identity function.
- * @constructor
- * @extends {goog.iter.Iterator<!Array<?>>}
- * @template KEY, VALUE
- * @private
- */
-goog.iter.GroupByIterator_ = function(iterable, opt_keyFunc) {
-
- /**
- * The iterable to group, coerced to an iterator.
- * @type {!goog.iter.Iterator}
- */
- this.iterator = goog.iter.toIterator(iterable);
-
- /**
- * A function for determining the key value for each element in the iterable.
- * If no function is provided, the identity function is used and returns the
- * element unchanged.
- * @type {function(...VALUE): KEY}
- */
- this.keyFunc = opt_keyFunc || goog.functions.identity;
-
- /**
- * The target key for determining the start of a group.
- * @type {KEY}
- */
- this.targetKey;
-
- /**
- * The current key visited during iteration.
- * @type {KEY}
- */
- this.currentKey;
-
- /**
- * The current value being added to the group.
- * @type {VALUE}
- */
- this.currentValue;
-};
-goog.inherits(goog.iter.GroupByIterator_, goog.iter.Iterator);
-
-
-/** @override */
-goog.iter.GroupByIterator_.prototype.next = function() {
- while (this.currentKey == this.targetKey) {
- this.currentValue = this.iterator.next(); // Exits on StopIteration
- this.currentKey = this.keyFunc(this.currentValue);
- }
- this.targetKey = this.currentKey;
- return [this.currentKey, this.groupItems_(this.targetKey)];
-};
-
-
-/**
- * Performs the grouping of objects using the given key.
- * @param {KEY} targetKey The target key object for the group.
- * @return {!Array<VALUE>} An array of grouped objects.
- * @private
+ * Creates a function that returns true if each of its components evaluates
+ * to true. The components are evaluated in order, and the evaluation will be
+ * short-circuited as soon as a function returns false.
+ * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).
+ * @param {...Function} var_args A list of functions.
+ * @return {function(...?):boolean} A function that ANDs its component
+ * functions.
*/
-goog.iter.GroupByIterator_.prototype.groupItems_ = function(targetKey) {
- var arr = [];
- while (this.currentKey == targetKey) {
- arr.push(this.currentValue);
- try {
- this.currentValue = this.iterator.next();
- } catch (ex) {
- if (ex !== goog.iter.StopIteration) {
- throw ex;
+goog.functions.and = function(var_args) {
+ var functions = arguments;
+ var length = functions.length;
+ return function() {
+ for (var i = 0; i < length; i++) {
+ if (!functions[i].apply(this, arguments)) {
+ return false;
}
- break;
}
- this.currentKey = this.keyFunc(this.currentValue);
- }
- return arr;
-};
-
-
-/**
- * Creates an iterator that returns arrays containing elements from the
- * {@code iterable} grouped by a key value. For iterables with repeated
- * elements (i.e. sorted according to a particular key function), this function
- * has a {@code uniq}-like effect. For example, grouping the array:
- * {@code [A, B, B, C, C, A]} produces
- * {@code [A, [A]], [B, [B, B]], [C, [C, C]], [A, [A]]}.
- * @see http://docs.python.org/2/library/itertools.html#itertools.groupby
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to group.
- * @param {function(...VALUE): KEY=} opt_keyFunc Optional function for
- * determining the key value for each group in the {@code iterable}. Default
- * is the identity function.
- * @return {!goog.iter.Iterator<!Array<?>>} A new iterator that returns
- * arrays of consecutive key and groups.
- * @template KEY, VALUE
- */
-goog.iter.groupBy = function(iterable, opt_keyFunc) {
- return new goog.iter.GroupByIterator_(iterable, opt_keyFunc);
-};
-
-
-/**
- * Gives an iterator that gives the result of calling the given function
- * <code>f</code> with the arguments taken from the next element from
- * <code>iterable</code> (the elements are expected to also be iterables).
- *
- * Similar to {@see goog.iter#map} but allows the function to accept multiple
- * arguments from the iterable.
- *
- * @param {!goog.iter.Iterable<!goog.iter.Iterable>} iterable The iterable of
- * iterables to iterate over.
- * @param {function(this:THIS,...*):RESULT} f The function to call for every
- * element. This function takes N+2 arguments, where N represents the
- * number of items from the next element of the iterable. The two
- * additional arguments passed to the function are undefined and the
- * iterator itself. The function should return a new value.
- * @param {THIS=} opt_obj The object to be used as the value of 'this' within
- * {@code f}.
- * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the
- * results of applying the function to each element in the original
- * iterator.
- * @template THIS, RESULT
- */
-goog.iter.starMap = function(iterable, f, opt_obj) {
- var iterator = goog.iter.toIterator(iterable);
- var iter = new goog.iter.Iterator();
-
- iter.next = function() {
- var args = goog.iter.toArray(iterator.next());
- return f.apply(opt_obj, goog.array.concat(args, undefined, iterator));
+ return true;
};
-
- return iter;
};
/**
- * Returns an array of iterators each of which can iterate over the values in
- * {@code iterable} without advancing the others.
- * @see http://docs.python.org/2/library/itertools.html#itertools.tee
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to tee.
- * @param {number=} opt_num The number of iterators to create. Default is 2.
- * @return {!Array<goog.iter.Iterator<VALUE>>} An array of iterators.
- * @template VALUE
+ * Creates a function that returns true if any of its components evaluates
+ * to true. The components are evaluated in order, and the evaluation will be
+ * short-circuited as soon as a function returns true.
+ * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).
+ * @param {...Function} var_args A list of functions.
+ * @return {function(...?):boolean} A function that ORs its component
+ * functions.
*/
-goog.iter.tee = function(iterable, opt_num) {
- var iterator = goog.iter.toIterator(iterable);
- var num = goog.isNumber(opt_num) ? opt_num : 2;
- var buffers = goog.array.map(goog.array.range(num), function() {
- return [];
- });
-
- var addNextIteratorValueToBuffers = function() {
- var val = iterator.next();
- goog.array.forEach(buffers, function(buffer) {
- buffer.push(val);
- });
- };
-
- var createIterator = function(buffer) {
- // Each tee'd iterator has an associated buffer (initially empty). When a
- // tee'd iterator's buffer is empty, it calls
- // addNextIteratorValueToBuffers(), adding the next value to all tee'd
- // iterators' buffers, and then returns that value. This allows each
- // iterator to be advanced independently.
- var iter = new goog.iter.Iterator();
-
- iter.next = function() {
- if (goog.array.isEmpty(buffer)) {
- addNextIteratorValueToBuffers();
+goog.functions.or = function(var_args) {
+ var functions = arguments;
+ var length = functions.length;
+ return function() {
+ for (var i = 0; i < length; i++) {
+ if (functions[i].apply(this, arguments)) {
+ return true;
}
- goog.asserts.assert(!goog.array.isEmpty(buffer));
- return buffer.shift();
- };
-
- return iter;
- };
-
- return goog.array.map(buffers, createIterator);
-};
-
-
-/**
- * Creates an iterator that returns arrays containing a count and an element
- * obtained from the given {@code iterable}.
- * @see http://docs.python.org/2/library/functions.html#enumerate
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to enumerate.
- * @param {number=} opt_start Optional starting value. Default is 0.
- * @return {!goog.iter.Iterator<!Array<?>>} A new iterator containing
- * count/item pairs.
- * @template VALUE
- */
-goog.iter.enumerate = function(iterable, opt_start) {
- return goog.iter.zip(goog.iter.count(opt_start), iterable);
-};
-
-
-/**
- * Creates an iterator that returns the first {@code limitSize} elements from an
- * iterable. If this number is greater than the number of elements in the
- * iterable, all the elements are returned.
- * @see http://goo.gl/V0sihp Inspired by the limit iterator in Guava.
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to limit.
- * @param {number} limitSize The maximum number of elements to return.
- * @return {!goog.iter.Iterator<VALUE>} A new iterator containing
- * {@code limitSize} elements.
- * @template VALUE
- */
-goog.iter.limit = function(iterable, limitSize) {
- goog.asserts.assert(goog.math.isInt(limitSize) && limitSize >= 0);
-
- var iterator = goog.iter.toIterator(iterable);
-
- var iter = new goog.iter.Iterator();
- var remaining = limitSize;
-
- iter.next = function() {
- if (remaining-- > 0) {
- return iterator.next();
}
- throw goog.iter.StopIteration;
+ return false;
};
-
- return iter;
-};
-
-
-/**
- * Creates an iterator that is advanced {@code count} steps ahead. Consumed
- * values are silently discarded. If {@code count} is greater than the number
- * of elements in {@code iterable}, an empty iterator is returned. Subsequent
- * calls to {@code next()} will throw {@code goog.iter.StopIteration}.
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to consume.
- * @param {number} count The number of elements to consume from the iterator.
- * @return {!goog.iter.Iterator<VALUE>} An iterator advanced zero or more steps
- * ahead.
- * @template VALUE
- */
-goog.iter.consume = function(iterable, count) {
- goog.asserts.assert(goog.math.isInt(count) && count >= 0);
-
- var iterator = goog.iter.toIterator(iterable);
-
- while (count-- > 0) {
- goog.iter.nextOrValue(iterator, null);
- }
-
- return iterator;
-};
-
-
-/**
- * Creates an iterator that returns a range of elements from an iterable.
- * Similar to {@see goog.array#slice} but does not support negative indexes.
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to slice.
- * @param {number} start The index of the first element to return.
- * @param {number=} opt_end The index after the last element to return. If
- * defined, must be greater than or equal to {@code start}.
- * @return {!goog.iter.Iterator<VALUE>} A new iterator containing a slice of
- * the original.
- * @template VALUE
- */
-goog.iter.slice = function(iterable, start, opt_end) {
- goog.asserts.assert(goog.math.isInt(start) && start >= 0);
-
- var iterator = goog.iter.consume(iterable, start);
-
- if (goog.isNumber(opt_end)) {
- goog.asserts.assert(goog.math.isInt(opt_end) && opt_end >= start);
- iterator = goog.iter.limit(iterator, opt_end - start /* limitSize */);
- }
-
- return iterator;
-};
-
-
-/**
- * Checks an array for duplicate elements.
- * @param {Array<VALUE>|goog.array.ArrayLike} arr The array to check for
- * duplicates.
- * @return {boolean} True, if the array contains duplicates, false otherwise.
- * @private
- * @template VALUE
- */
-// TODO(user): Consider moving this into goog.array as a public function.
-goog.iter.hasDuplicates_ = function(arr) {
- var deduped = [];
- goog.array.removeDuplicates(arr, deduped);
- return arr.length != deduped.length;
-};
-
-
-/**
- * Creates an iterator that returns permutations of elements in
- * {@code iterable}.
- *
- * Permutations are obtained by taking the Cartesian product of
- * {@code opt_length} iterables and filtering out those with repeated
- * elements. For example, the permutations of {@code [1,2,3]} are
- * {@code [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]}.
- * @see http://docs.python.org/2/library/itertools.html#itertools.permutations
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable from which to generate permutations.
- * @param {number=} opt_length Length of each permutation. If omitted, defaults
- * to the length of {@code iterable}.
- * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing the
- * permutations of {@code iterable}.
- * @template VALUE
- */
-goog.iter.permutations = function(iterable, opt_length) {
- var elements = goog.iter.toArray(iterable);
- var length = goog.isNumber(opt_length) ? opt_length : elements.length;
-
- var sets = goog.array.repeat(elements, length);
- var product = goog.iter.product.apply(undefined, sets);
-
- return goog.iter.filter(product, function(arr) {
- return !goog.iter.hasDuplicates_(arr);
- });
};
/**
- * Creates an iterator that returns combinations of elements from
- * {@code iterable}.
- *
- * Combinations are obtained by taking the {@see goog.iter#permutations} of
- * {@code iterable} and filtering those whose elements appear in the order they
- * are encountered in {@code iterable}. For example, the 3-length combinations
- * of {@code [0,1,2,3]} are {@code [[0,1,2], [0,1,3], [0,2,3], [1,2,3]]}.
- * @see http://docs.python.org/2/library/itertools.html#itertools.combinations
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable from which to generate combinations.
- * @param {number} length The length of each combination.
- * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing
- * combinations from the {@code iterable}.
- * @template VALUE
+ * Creates a function that returns the Boolean opposite of a provided function.
+ * For example, (goog.functions.not(f))(x) is equivalent to !f(x).
+ * @param {!Function} f The original function.
+ * @return {function(...?):boolean} A function that delegates to f and returns
+ * opposite.
*/
-goog.iter.combinations = function(iterable, length) {
- var elements = goog.iter.toArray(iterable);
- var indexes = goog.iter.range(elements.length);
- var indexIterator = goog.iter.permutations(indexes, length);
- // sortedIndexIterator will now give arrays of with the given length that
- // indicate what indexes into "elements" should be returned on each iteration.
- var sortedIndexIterator = goog.iter.filter(indexIterator, function(arr) {
- return goog.array.isSorted(arr);
- });
-
- var iter = new goog.iter.Iterator();
-
- function getIndexFromElements(index) {
- return elements[index];
- }
-
- iter.next = function() {
- return goog.array.map(sortedIndexIterator.next(), getIndexFromElements);
- };
-
- return iter;
+goog.functions.not = function(f) {
+ return function() { return !f.apply(this, arguments); };
};
/**
- * Creates an iterator that returns combinations of elements from
- * {@code iterable}, with repeated elements possible.
+ * Generic factory function to construct an object given the constructor
+ * and the arguments. Intended to be bound to create object factories.
*
- * Combinations are obtained by taking the Cartesian product of {@code length}
- * iterables and filtering those whose elements appear in the order they are
- * encountered in {@code iterable}. For example, the 2-length combinations of
- * {@code [1,2,3]} are {@code [[1,1], [1,2], [1,3], [2,2], [2,3], [3,3]]}.
- * @see http://docs.python.org/2/library/itertools.html#itertools.combinations_with_replacement
- * @see http://en.wikipedia.org/wiki/Combination#Number_of_combinations_with_repetition
- * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
- * iterable to combine.
- * @param {number} length The length of each combination.
- * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing
- * combinations from the {@code iterable}.
- * @template VALUE
- */
-goog.iter.combinationsWithReplacement = function(iterable, length) {
- var elements = goog.iter.toArray(iterable);
- var indexes = goog.array.range(elements.length);
- var sets = goog.array.repeat(indexes, length);
- var indexIterator = goog.iter.product.apply(undefined, sets);
- // sortedIndexIterator will now give arrays of with the given length that
- // indicate what indexes into "elements" should be returned on each iteration.
- var sortedIndexIterator = goog.iter.filter(indexIterator, function(arr) {
- return goog.array.isSorted(arr);
- });
-
- var iter = new goog.iter.Iterator();
-
- function getIndexFromElements(index) {
- return elements[index];
- }
-
- iter.next = function() {
- return goog.array.map(
- /** @type {!Array<number>} */
- (sortedIndexIterator.next()), getIndexFromElements);
- };
-
- return iter;
-};
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Datastructure: Hash Map.
+ * Example:
*
- * @author arv@google.com (Erik Arvidsson)
+ * var factory = goog.partial(goog.functions.create, Class);
*
- * This file contains an implementation of a Map structure. It implements a lot
- * of the methods used in goog.structs so those functions work on hashes. This
- * is best suited for complex key types. For simple keys such as numbers and
- * strings consider using the lighter-weight utilities in goog.object.
- */
-
-
-goog.provide('goog.structs.Map');
-
-goog.require('goog.iter.Iterator');
-goog.require('goog.iter.StopIteration');
-goog.require('goog.object');
-
-
-
-/**
- * Class for Hash Map datastructure.
- * @param {*=} opt_map Map or Object to initialize the map with.
- * @param {...*} var_args If 2 or more arguments are present then they
- * will be used as key-value pairs.
- * @constructor
- * @template K, V
+ * @param {function(new:T, ...)} constructor The constructor for the Object.
+ * @param {...*} var_args The arguments to be passed to the constructor.
+ * @return {T} A new instance of the class given in {@code constructor}.
+ * @template T
*/
-goog.structs.Map = function(opt_map, var_args) {
-
- /**
- * Underlying JS object used to implement the map.
- * @private {!Object}
- */
- this.map_ = {};
-
- /**
- * An array of keys. This is necessary for two reasons:
- * 1. Iterating the keys using for (var key in this.map_) allocates an
- * object for every key in IE which is really bad for IE6 GC perf.
- * 2. Without a side data structure, we would need to escape all the keys
- * as that would be the only way we could tell during iteration if the
- * key was an internal key or a property of the object.
- *
- * This array can contain deleted keys so it's necessary to check the map
- * as well to see if the key is still in the map (this doesn't require a
- * memory allocation in IE).
- * @private {!Array<string>}
- */
- this.keys_ = [];
-
- /**
- * The number of key value pairs in the map.
- * @private {number}
- */
- this.count_ = 0;
-
+goog.functions.create = function(constructor, var_args) {
/**
- * Version used to detect changes while iterating.
- * @private {number}
+ * @constructor
+ * @final
*/
- this.version_ = 0;
-
- var argLength = arguments.length;
-
- if (argLength > 1) {
- if (argLength % 2) {
- throw Error('Uneven number of arguments');
- }
- for (var i = 0; i < argLength; i += 2) {
- this.set(arguments[i], arguments[i + 1]);
- }
- } else if (opt_map) {
- this.addAll(/** @type {Object} */ (opt_map));
- }
-};
-
-
-/**
- * @return {number} The number of key-value pairs in the map.
- */
-goog.structs.Map.prototype.getCount = function() {
- return this.count_;
-};
-
-
-/**
- * Returns the values of the map.
- * @return {!Array<V>} The values in the map.
- */
-goog.structs.Map.prototype.getValues = function() {
- this.cleanupKeysArray_();
-
- var rv = [];
- for (var i = 0; i < this.keys_.length; i++) {
- var key = this.keys_[i];
- rv.push(this.map_[key]);
- }
- return rv;
-};
-
-
-/**
- * Returns the keys of the map.
- * @return {!Array<string>} Array of string values.
- */
-goog.structs.Map.prototype.getKeys = function() {
- this.cleanupKeysArray_();
- return /** @type {!Array<string>} */ (this.keys_.concat());
-};
-
-
-/**
- * Whether the map contains the given key.
- * @param {*} key The key to check for.
- * @return {boolean} Whether the map contains the key.
- */
-goog.structs.Map.prototype.containsKey = function(key) {
- return goog.structs.Map.hasKey_(this.map_, key);
-};
-
-
-/**
- * Whether the map contains the given value. This is O(n).
- * @param {V} val The value to check for.
- * @return {boolean} Whether the map contains the value.
- */
-goog.structs.Map.prototype.containsValue = function(val) {
- for (var i = 0; i < this.keys_.length; i++) {
- var key = this.keys_[i];
- if (goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Whether this map is equal to the argument map.
- * @param {goog.structs.Map} otherMap The map against which to test equality.
- * @param {function(V, V): boolean=} opt_equalityFn Optional equality function
- * to test equality of values. If not specified, this will test whether
- * the values contained in each map are identical objects.
- * @return {boolean} Whether the maps are equal.
- */
-goog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) {
- if (this === otherMap) {
- return true;
- }
-
- if (this.count_ != otherMap.getCount()) {
- return false;
- }
-
- var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals;
-
- this.cleanupKeysArray_();
- for (var key, i = 0; key = this.keys_[i]; i++) {
- if (!equalityFn(this.get(key), otherMap.get(key))) {
- return false;
- }
- }
-
- return true;
-};
-
-
-/**
- * Default equality test for values.
- * @param {*} a The first value.
- * @param {*} b The second value.
- * @return {boolean} Whether a and b reference the same object.
- */
-goog.structs.Map.defaultEquals = function(a, b) {
- return a === b;
-};
-
-
-/**
- * @return {boolean} Whether the map is empty.
- */
-goog.structs.Map.prototype.isEmpty = function() {
- return this.count_ == 0;
-};
-
-
-/**
- * Removes all key-value pairs from the map.
- */
-goog.structs.Map.prototype.clear = function() {
- this.map_ = {};
- this.keys_.length = 0;
- this.count_ = 0;
- this.version_ = 0;
-};
-
-
-/**
- * Removes a key-value pair based on the key. This is O(logN) amortized due to
- * updating the keys array whenever the count becomes half the size of the keys
- * in the keys array.
- * @param {*} key The key to remove.
- * @return {boolean} Whether object was removed.
- */
-goog.structs.Map.prototype.remove = function(key) {
- if (goog.structs.Map.hasKey_(this.map_, key)) {
- delete this.map_[key];
- this.count_--;
- this.version_++;
-
- // clean up the keys array if the threshhold is hit
- if (this.keys_.length > 2 * this.count_) {
- this.cleanupKeysArray_();
- }
-
- return true;
- }
- return false;
-};
-
-
-/**
- * Cleans up the temp keys array by removing entries that are no longer in the
- * map.
- * @private
- */
-goog.structs.Map.prototype.cleanupKeysArray_ = function() {
- if (this.count_ != this.keys_.length) {
- // First remove keys that are no longer in the map.
- var srcIndex = 0;
- var destIndex = 0;
- while (srcIndex < this.keys_.length) {
- var key = this.keys_[srcIndex];
- if (goog.structs.Map.hasKey_(this.map_, key)) {
- this.keys_[destIndex++] = key;
- }
- srcIndex++;
- }
- this.keys_.length = destIndex;
- }
-
- if (this.count_ != this.keys_.length) {
- // If the count still isn't correct, that means we have duplicates. This can
- // happen when the same key is added and removed multiple times. Now we have
- // to allocate one extra Object to remove the duplicates. This could have
- // been done in the first pass, but in the common case, we can avoid
- // allocating an extra object by only doing this when necessary.
- var seen = {};
- var srcIndex = 0;
- var destIndex = 0;
- while (srcIndex < this.keys_.length) {
- var key = this.keys_[srcIndex];
- if (!(goog.structs.Map.hasKey_(seen, key))) {
- this.keys_[destIndex++] = key;
- seen[key] = 1;
- }
- srcIndex++;
- }
- this.keys_.length = destIndex;
- }
-};
-
-
-/**
- * Returns the value for the given key. If the key is not found and the default
- * value is not given this will return {@code undefined}.
- * @param {*} key The key to get the value for.
- * @param {DEFAULT=} opt_val The value to return if no item is found for the
- * given key, defaults to undefined.
- * @return {V|DEFAULT} The value for the given key.
- * @template DEFAULT
- */
-goog.structs.Map.prototype.get = function(key, opt_val) {
- if (goog.structs.Map.hasKey_(this.map_, key)) {
- return this.map_[key];
- }
- return opt_val;
-};
-
-
-/**
- * Adds a key-value pair to the map.
- * @param {*} key The key.
- * @param {V} value The value to add.
- * @return {*} Some subclasses return a value.
- */
-goog.structs.Map.prototype.set = function(key, value) {
- if (!(goog.structs.Map.hasKey_(this.map_, key))) {
- this.count_++;
- this.keys_.push(key);
- // Only change the version if we add a new key.
- this.version_++;
- }
- this.map_[key] = value;
-};
-
-
-/**
- * Adds multiple key-value pairs from another goog.structs.Map or Object.
- * @param {Object} map Object containing the data to add.
- */
-goog.structs.Map.prototype.addAll = function(map) {
- var keys, values;
- if (map instanceof goog.structs.Map) {
- keys = map.getKeys();
- values = map.getValues();
- } else {
- keys = goog.object.getKeys(map);
- values = goog.object.getValues(map);
- }
- // we could use goog.array.forEach here but I don't want to introduce that
- // dependency just for this.
- for (var i = 0; i < keys.length; i++) {
- this.set(keys[i], values[i]);
- }
-};
-
-
-/**
- * Calls the given function on each entry in the map.
- * @param {function(this:T, V, K, goog.structs.Map<K,V>)} f
- * @param {T=} opt_obj The value of "this" inside f.
- * @template T
- */
-goog.structs.Map.prototype.forEach = function(f, opt_obj) {
- var keys = this.getKeys();
- for (var i = 0; i < keys.length; i++) {
- var key = keys[i];
- var value = this.get(key);
- f.call(opt_obj, value, key, this);
- }
-};
-
-
-/**
- * Clones a map and returns a new map.
- * @return {!goog.structs.Map} A new map with the same key-value pairs.
- */
-goog.structs.Map.prototype.clone = function() {
- return new goog.structs.Map(this);
-};
-
-
-/**
- * Returns a new map in which all the keys and values are interchanged
- * (keys become values and values become keys). If multiple keys map to the
- * same value, the chosen transposed value is implementation-dependent.
- *
- * It acts very similarly to {goog.object.transpose(Object)}.
- *
- * @return {!goog.structs.Map} The transposed map.
- */
-goog.structs.Map.prototype.transpose = function() {
- var transposed = new goog.structs.Map();
- for (var i = 0; i < this.keys_.length; i++) {
- var key = this.keys_[i];
- var value = this.map_[key];
- transposed.set(value, key);
- }
-
- return transposed;
-};
+ var temp = function() {};
+ temp.prototype = constructor.prototype;
+ // obj will have constructor's prototype in its chain and
+ // 'obj instanceof constructor' will be true.
+ var obj = new temp();
-/**
- * @return {!Object} Object representation of the map.
- */
-goog.structs.Map.prototype.toObject = function() {
- this.cleanupKeysArray_();
- var obj = {};
- for (var i = 0; i < this.keys_.length; i++) {
- var key = this.keys_[i];
- obj[key] = this.map_[key];
- }
+ // obj is initialized by constructor.
+ // arguments is only array-like so lacks shift(), but can be used with
+ // the Array prototype function.
+ constructor.apply(obj, Array.prototype.slice.call(arguments, 1));
return obj;
};
/**
- * Returns an iterator that iterates over the keys in the map. Removal of keys
- * while iterating might have undesired side effects.
- * @return {!goog.iter.Iterator} An iterator over the keys in the map.
- */
-goog.structs.Map.prototype.getKeyIterator = function() {
- return this.__iterator__(true);
-};
-
-
-/**
- * Returns an iterator that iterates over the values in the map. Removal of
- * keys while iterating might have undesired side effects.
- * @return {!goog.iter.Iterator} An iterator over the values in the map.
- */
-goog.structs.Map.prototype.getValueIterator = function() {
- return this.__iterator__(false);
-};
-
-
-/**
- * Returns an iterator that iterates over the values or the keys in the map.
- * This throws an exception if the map was mutated since the iterator was
- * created.
- * @param {boolean=} opt_keys True to iterate over the keys. False to iterate
- * over the values. The default value is false.
- * @return {!goog.iter.Iterator} An iterator over the values or keys in the map.
- */
-goog.structs.Map.prototype.__iterator__ = function(opt_keys) {
- // Clean up keys to minimize the risk of iterating over dead keys.
- this.cleanupKeysArray_();
-
- var i = 0;
- var version = this.version_;
- var selfObj = this;
-
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- if (version != selfObj.version_) {
- throw Error('The map has changed since the iterator was created');
- }
- if (i >= selfObj.keys_.length) {
- throw goog.iter.StopIteration;
- }
- var key = selfObj.keys_[i++];
- return opt_keys ? key : selfObj.map_[key];
- };
- return newIter;
-};
-
-
-/**
- * Safe way to test for hasOwnProperty. It even allows testing for
- * 'hasOwnProperty'.
- * @param {Object} obj The object to test for presence of the given key.
- * @param {*} key The key to check for.
- * @return {boolean} Whether the object has the key.
- * @private
+ * @define {boolean} Whether the return value cache should be used.
+ * This should only be used to disable caches when testing.
*/
-goog.structs.Map.hasKey_ = function(obj, key) {
- return Object.prototype.hasOwnProperty.call(obj, key);
-};
+goog.define('goog.functions.CACHE_RETURN_VALUE', true);
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Datastructure: Set.
+ * Gives a wrapper function that caches the return value of a parameterless
+ * function when first called.
*
- * @author arv@google.com (Erik Arvidsson)
+ * When called for the first time, the given function is called and its
+ * return value is cached (thus this is only appropriate for idempotent
+ * functions). Subsequent calls will return the cached return value. This
+ * allows the evaluation of expensive functions to be delayed until first used.
*
- * This class implements a set data structure. Adding and removing is O(1). It
- * supports both object and primitive values. Be careful because you can add
- * both 1 and new Number(1), because these are not the same. You can even add
- * multiple new Number(1) because these are not equal.
- */
-
-
-goog.provide('goog.structs.Set');
-
-goog.require('goog.structs');
-goog.require('goog.structs.Collection');
-goog.require('goog.structs.Map');
-
-
-
-/**
- * A set that can contain both primitives and objects. Adding and removing
- * elements is O(1). Primitives are treated as identical if they have the same
- * type and convert to the same string. Objects are treated as identical only
- * if they are references to the same object. WARNING: A goog.structs.Set can
- * contain both 1 and (new Number(1)), because they are not the same. WARNING:
- * Adding (new Number(1)) twice will yield two distinct elements, because they
- * are two different objects. WARNING: Any object that is added to a
- * goog.structs.Set will be modified! Because goog.getUid() is used to
- * identify objects, every object in the set will be mutated.
- * @param {Array<T>|Object<?,T>=} opt_values Initial values to start with.
- * @constructor
- * @implements {goog.structs.Collection<T>}
- * @final
- * @template T
- */
-goog.structs.Set = function(opt_values) {
- this.map_ = new goog.structs.Map;
- if (opt_values) {
- this.addAll(opt_values);
- }
-};
-
-
-/**
- * Obtains a unique key for an element of the set. Primitives will yield the
- * same key if they have the same type and convert to the same string. Object
- * references will yield the same key only if they refer to the same object.
- * @param {*} val Object or primitive value to get a key for.
- * @return {string} A unique key for this value/object.
- * @private
- */
-goog.structs.Set.getKey_ = function(val) {
- var type = typeof val;
- if (type == 'object' && val || type == 'function') {
- return 'o' + goog.getUid(/** @type {Object} */ (val));
- } else {
- return type.substr(0, 1) + val;
- }
-};
-
-
-/**
- * @return {number} The number of elements in the set.
- * @override
- */
-goog.structs.Set.prototype.getCount = function() {
- return this.map_.getCount();
-};
-
-
-/**
- * Add a primitive or an object to the set.
- * @param {T} element The primitive or object to add.
- * @override
- */
-goog.structs.Set.prototype.add = function(element) {
- this.map_.set(goog.structs.Set.getKey_(element), element);
-};
-
-
-/**
- * Adds all the values in the given collection to this set.
- * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection
- * containing the elements to add.
- */
-goog.structs.Set.prototype.addAll = function(col) {
- var values = goog.structs.getValues(col);
- var l = values.length;
- for (var i = 0; i < l; i++) {
- this.add(values[i]);
- }
-};
-
-
-/**
- * Removes all values in the given collection from this set.
- * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection
- * containing the elements to remove.
- */
-goog.structs.Set.prototype.removeAll = function(col) {
- var values = goog.structs.getValues(col);
- var l = values.length;
- for (var i = 0; i < l; i++) {
- this.remove(values[i]);
- }
-};
-
-
-/**
- * Removes the given element from this set.
- * @param {T} element The primitive or object to remove.
- * @return {boolean} Whether the element was found and removed.
- * @override
- */
-goog.structs.Set.prototype.remove = function(element) {
- return this.map_.remove(goog.structs.Set.getKey_(element));
-};
-
-
-/**
- * Removes all elements from this set.
- */
-goog.structs.Set.prototype.clear = function() {
- this.map_.clear();
-};
-
-
-/**
- * Tests whether this set is empty.
- * @return {boolean} True if there are no elements in this set.
- */
-goog.structs.Set.prototype.isEmpty = function() {
- return this.map_.isEmpty();
-};
-
-
-/**
- * Tests whether this set contains the given element.
- * @param {T} element The primitive or object to test for.
- * @return {boolean} True if this set contains the given element.
- * @override
- */
-goog.structs.Set.prototype.contains = function(element) {
- return this.map_.containsKey(goog.structs.Set.getKey_(element));
-};
-
-
-/**
- * Tests whether this set contains all the values in a given collection.
- * Repeated elements in the collection are ignored, e.g. (new
- * goog.structs.Set([1, 2])).containsAll([1, 1]) is True.
- * @param {goog.structs.Collection<T>|Object} col A collection-like object.
- * @return {boolean} True if the set contains all elements.
- */
-goog.structs.Set.prototype.containsAll = function(col) {
- return goog.structs.every(col, this.contains, this);
-};
-
-
-/**
- * Finds all values that are present in both this set and the given collection.
- * @param {Array<S>|Object<?,S>} col A collection.
- * @return {!goog.structs.Set<T|S>} A new set containing all the values
- * (primitives or objects) present in both this set and the given
- * collection.
- * @template S
- */
-goog.structs.Set.prototype.intersection = function(col) {
- var result = new goog.structs.Set();
-
- var values = goog.structs.getValues(col);
- for (var i = 0; i < values.length; i++) {
- var value = values[i];
- if (this.contains(value)) {
- result.add(value);
- }
- }
-
- return result;
-};
-
-
-/**
- * Finds all values that are present in this set and not in the given
- * collection.
- * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection.
- * @return {!goog.structs.Set} A new set containing all the values
- * (primitives or objects) present in this set but not in the given
- * collection.
- */
-goog.structs.Set.prototype.difference = function(col) {
- var result = this.clone();
- result.removeAll(col);
- return result;
-};
-
-
-/**
- * Returns an array containing all the elements in this set.
- * @return {!Array<T>} An array containing all the elements in this set.
- */
-goog.structs.Set.prototype.getValues = function() {
- return this.map_.getValues();
-};
-
-
-/**
- * Creates a shallow clone of this set.
- * @return {!goog.structs.Set<T>} A new set containing all the same elements as
- * this set.
- */
-goog.structs.Set.prototype.clone = function() {
- return new goog.structs.Set(this);
-};
-
-
-/**
- * Tests whether the given collection consists of the same elements as this set,
- * regardless of order, without repetition. Primitives are treated as equal if
- * they have the same type and convert to the same string; objects are treated
- * as equal if they are references to the same object. This operation is O(n).
- * @param {goog.structs.Collection<T>|Object} col A collection.
- * @return {boolean} True if the given collection consists of the same elements
- * as this set, regardless of order, without repetition.
- */
-goog.structs.Set.prototype.equals = function(col) {
- return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);
-};
-
-
-/**
- * Tests whether the given collection contains all the elements in this set.
- * Primitives are treated as equal if they have the same type and convert to the
- * same string; objects are treated as equal if they are references to the same
- * object. This operation is O(n).
- * @param {goog.structs.Collection<T>|Object} col A collection.
- * @return {boolean} True if this set is a subset of the given collection.
- */
-goog.structs.Set.prototype.isSubsetOf = function(col) {
- var colCount = goog.structs.getCount(col);
- if (this.getCount() > colCount) {
- return false;
- }
- // TODO(user) Find the minimal collection size where the conversion makes
- // the contains() method faster.
- if (!(col instanceof goog.structs.Set) && colCount > 5) {
- // Convert to a goog.structs.Set so that goog.structs.contains runs in
- // O(1) time instead of O(n) time.
- col = new goog.structs.Set(col);
- }
- return goog.structs.every(this, function(value) {
- return goog.structs.contains(col, value);
- });
-};
-
-
-/**
- * Returns an iterator that iterates over the elements in this set.
- * @param {boolean=} opt_keys This argument is ignored.
- * @return {!goog.iter.Iterator} An iterator over the elements in this set.
- */
-goog.structs.Set.prototype.__iterator__ = function(opt_keys) {
- return this.map_.__iterator__(false);
-};
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Logging and debugging utilities.
+ * To cache the return values of functions with parameters, see goog.memoize.
*
- * @see ../demos/debug.html
- */
-
-goog.provide('goog.debug');
-
-goog.require('goog.array');
-goog.require('goog.html.SafeHtml');
-goog.require('goog.html.SafeUrl');
-goog.require('goog.html.uncheckedconversions');
-goog.require('goog.string.Const');
-goog.require('goog.structs.Set');
-goog.require('goog.userAgent');
-
-
-/** @define {boolean} Whether logging should be enabled. */
-goog.define('goog.debug.LOGGING_ENABLED', goog.DEBUG);
-
-
-/**
- * Catches onerror events fired by windows and similar objects.
- * @param {function(Object)} logFunc The function to call with the error
- * information.
- * @param {boolean=} opt_cancel Whether to stop the error from reaching the
- * browser.
- * @param {Object=} opt_target Object that fires onerror events.
- */
-goog.debug.catchErrors = function(logFunc, opt_cancel, opt_target) {
- var target = opt_target || goog.global;
- var oldErrorHandler = target.onerror;
- var retVal = !!opt_cancel;
-
- // Chrome interprets onerror return value backwards (http://crbug.com/92062)
- // until it was fixed in webkit revision r94061 (Webkit 535.3). This
- // workaround still needs to be skipped in Safari after the webkit change
- // gets pushed out in Safari.
- // See https://bugs.webkit.org/show_bug.cgi?id=67119
- if (goog.userAgent.WEBKIT &&
- !goog.userAgent.isVersionOrHigher('535.3')) {
- retVal = !retVal;
- }
-
- /**
- * New onerror handler for this target. This onerror handler follows the spec
- * according to
- * http://www.whatwg.org/specs/web-apps/current-work/#runtime-script-errors
- * The spec was changed in August 2013 to support receiving column information
- * and an error object for all scripts on the same origin or cross origin
- * scripts with the proper headers. See
- * https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror
- *
- * @param {string} message The error message. For cross-origin errors, this
- * will be scrubbed to just "Script error.". For new browsers that have
- * updated to follow the latest spec, errors that come from origins that
- * have proper cross origin headers will not be scrubbed.
- * @param {string} url The URL of the script that caused the error. The URL
- * will be scrubbed to "" for cross origin scripts unless the script has
- * proper cross origin headers and the browser has updated to the latest
- * spec.
- * @param {number} line The line number in the script that the error
- * occurred on.
- * @param {number=} opt_col The optional column number that the error
- * occurred on. Only browsers that have updated to the latest spec will
- * include this.
- * @param {Error=} opt_error The optional actual error object for this
- * error that should include the stack. Only browsers that have updated
- * to the latest spec will inlude this parameter.
- * @return {boolean} Whether to prevent the error from reaching the browser.
- */
- target.onerror = function(message, url, line, opt_col, opt_error) {
- if (oldErrorHandler) {
- oldErrorHandler(message, url, line, opt_col, opt_error);
- }
- logFunc({
- message: message,
- fileName: url,
- line: line,
- col: opt_col,
- error: opt_error
- });
- return retVal;
- };
-};
-
-
-/**
- * Creates a string representing an object and all its properties.
- * @param {Object|null|undefined} obj Object to expose.
- * @param {boolean=} opt_showFn Show the functions as well as the properties,
- * default is false.
- * @return {string} The string representation of {@code obj}.
- */
-goog.debug.expose = function(obj, opt_showFn) {
- if (typeof obj == 'undefined') {
- return 'undefined';
- }
- if (obj == null) {
- return 'NULL';
- }
- var str = [];
-
- for (var x in obj) {
- if (!opt_showFn && goog.isFunction(obj[x])) {
- continue;
- }
- var s = x + ' = ';
- /** @preserveTry */
- try {
- s += obj[x];
- } catch (e) {
- s += '*** ' + e + ' ***';
- }
- str.push(s);
- }
- return str.join('\n');
-};
-
-
-/**
- * Creates a string representing a given primitive or object, and for an
- * object, all its properties and nested objects. WARNING: If an object is
- * given, it and all its nested objects will be modified. To detect reference
- * cycles, this method identifies objects using goog.getUid() which mutates the
- * object.
- * @param {*} obj Object to expose.
- * @param {boolean=} opt_showFn Also show properties that are functions (by
- * default, functions are omitted).
- * @return {string} A string representation of {@code obj}.
- */
-goog.debug.deepExpose = function(obj, opt_showFn) {
- var str = [];
-
- var helper = function(obj, space, parentSeen) {
- var nestspace = space + ' ';
- var seen = new goog.structs.Set(parentSeen);
-
- var indentMultiline = function(str) {
- return str.replace(/\n/g, '\n' + space);
- };
-
- /** @preserveTry */
- try {
- if (!goog.isDef(obj)) {
- str.push('undefined');
- } else if (goog.isNull(obj)) {
- str.push('NULL');
- } else if (goog.isString(obj)) {
- str.push('"' + indentMultiline(obj) + '"');
- } else if (goog.isFunction(obj)) {
- str.push(indentMultiline(String(obj)));
- } else if (goog.isObject(obj)) {
- if (seen.contains(obj)) {
- str.push('*** reference loop detected ***');
- } else {
- seen.add(obj);
- str.push('{');
- for (var x in obj) {
- if (!opt_showFn && goog.isFunction(obj[x])) {
- continue;
- }
- str.push('\n');
- str.push(nestspace);
- str.push(x + ' = ');
- helper(obj[x], nestspace, seen);
- }
- str.push('\n' + space + '}');
- }
- } else {
- str.push(obj);
- }
- } catch (e) {
- str.push('*** ' + e + ' ***');
- }
- };
-
- helper(obj, '', new goog.structs.Set());
- return str.join('');
-};
-
-
-/**
- * Recursively outputs a nested array as a string.
- * @param {Array<?>} arr The array.
- * @return {string} String representing nested array.
- */
-goog.debug.exposeArray = function(arr) {
- var str = [];
- for (var i = 0; i < arr.length; i++) {
- if (goog.isArray(arr[i])) {
- str.push(goog.debug.exposeArray(arr[i]));
- } else {
- str.push(arr[i]);
- }
- }
- return '[ ' + str.join(', ') + ' ]';
-};
-
-
-/**
- * Exposes an exception that has been caught by a try...catch and outputs the
- * error as HTML with a stack trace.
- * @param {Object} err Error object or string.
- * @param {Function=} opt_fn Optional function to start stack trace from.
- * @return {string} Details of exception, as HTML.
- */
-goog.debug.exposeException = function(err, opt_fn) {
- var html = goog.debug.exposeExceptionAsHtml(err, opt_fn);
- return goog.html.SafeHtml.unwrap(html);
-};
-
-
-/**
- * Exposes an exception that has been caught by a try...catch and outputs the
- * error with a stack trace.
- * @param {Object} err Error object or string.
- * @param {Function=} opt_fn Optional function to start stack trace from.
- * @return {!goog.html.SafeHtml} Details of exception.
- */
-goog.debug.exposeExceptionAsHtml = function(err, opt_fn) {
- /** @preserveTry */
- try {
- var e = goog.debug.normalizeErrorObject(err);
- // Create the error message
- var viewSourceUrl = goog.debug.createViewSourceUrl_(e.fileName);
- var error = goog.html.SafeHtml.concat(
- goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- 'Message: ' + e.message + '\nUrl: '),
- goog.html.SafeHtml.create('a',
- {href: viewSourceUrl, target: '_new'}, e.fileName),
- goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- '\nLine: ' + e.lineNumber + '\n\nBrowser stack:\n' +
- e.stack + '-> ' + '[end]\n\nJS stack traversal:\n' +
- goog.debug.getStacktrace(opt_fn) + '-> '));
- return error;
- } catch (e2) {
- return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- 'Exception trying to expose exception! You win, we lose. ' + e2);
- }
-};
-
-
-/**
- * @param {?string=} opt_fileName
- * @return {!goog.html.SafeUrl} SafeUrl with view-source scheme, pointing at
- * fileName.
- * @private
- */
-goog.debug.createViewSourceUrl_ = function(opt_fileName) {
- if (!goog.isDefAndNotNull(opt_fileName)) {
- opt_fileName = '';
- }
- if (!/^https?:\/\//i.test(opt_fileName)) {
- return goog.html.SafeUrl.fromConstant(
- goog.string.Const.from('sanitizedviewsrc'));
- }
- var sanitizedFileName = goog.html.SafeUrl.sanitize(opt_fileName);
- return goog.html.uncheckedconversions.
- safeUrlFromStringKnownToSatisfyTypeContract(
- goog.string.Const.from('view-source scheme plus HTTP/HTTPS URL'),
- 'view-source:' + goog.html.SafeUrl.unwrap(sanitizedFileName));
-};
-
-
-/**
- * Normalizes the error/exception object between browsers.
- * @param {Object} err Raw error object.
- * @return {!Object} Normalized error object.
- */
-goog.debug.normalizeErrorObject = function(err) {
- var href = goog.getObjectByName('window.location.href');
- if (goog.isString(err)) {
- return {
- 'message': err,
- 'name': 'Unknown error',
- 'lineNumber': 'Not available',
- 'fileName': href,
- 'stack': 'Not available'
- };
- }
-
- var lineNumber, fileName;
- var threwError = false;
-
- try {
- lineNumber = err.lineNumber || err.line || 'Not available';
- } catch (e) {
- // Firefox 2 sometimes throws an error when accessing 'lineNumber':
- // Message: Permission denied to get property UnnamedClass.lineNumber
- lineNumber = 'Not available';
- threwError = true;
- }
-
- try {
- fileName = err.fileName || err.filename || err.sourceURL ||
- // $googDebugFname may be set before a call to eval to set the filename
- // that the eval is supposed to present.
- goog.global['$googDebugFname'] || href;
- } catch (e) {
- // Firefox 2 may also throw an error when accessing 'filename'.
- fileName = 'Not available';
- threwError = true;
- }
-
- // The IE Error object contains only the name and the message.
- // The Safari Error object uses the line and sourceURL fields.
- if (threwError || !err.lineNumber || !err.fileName || !err.stack ||
- !err.message || !err.name) {
- return {
- 'message': err.message || 'Not available',
- 'name': err.name || 'UnknownError',
- 'lineNumber': lineNumber,
- 'fileName': fileName,
- 'stack': err.stack || 'Not available'
- };
- }
-
- // Standards error object
- return err;
-};
-
-
-/**
- * Converts an object to an Error if it's a String,
- * adds a stacktrace if there isn't one,
- * and optionally adds an extra message.
- * @param {Error|string} err the original thrown object or string.
- * @param {string=} opt_message optional additional message to add to the
- * error.
- * @return {!Error} If err is a string, it is used to create a new Error,
- * which is enhanced and returned. Otherwise err itself is enhanced
- * and returned.
- */
-goog.debug.enhanceError = function(err, opt_message) {
- var error;
- if (typeof err == 'string') {
- error = Error(err);
- if (Error.captureStackTrace) {
- // Trim this function off the call stack, if we can.
- Error.captureStackTrace(error, goog.debug.enhanceError);
- }
- } else {
- error = err;
- }
-
- if (!error.stack) {
- error.stack = goog.debug.getStacktrace(goog.debug.enhanceError);
- }
- if (opt_message) {
- // find the first unoccupied 'messageX' property
- var x = 0;
- while (error['message' + x]) {
- ++x;
- }
- error['message' + x] = String(opt_message);
- }
- return error;
-};
-
-
-/**
- * Gets the current stack trace. Simple and iterative - doesn't worry about
- * catching circular references or getting the args.
- * @param {number=} opt_depth Optional maximum depth to trace back to.
- * @return {string} A string with the function names of all functions in the
- * stack, separated by \n.
- * @suppress {es5Strict}
- */
-goog.debug.getStacktraceSimple = function(opt_depth) {
- if (goog.STRICT_MODE_COMPATIBLE) {
- var stack = goog.debug.getNativeStackTrace_(goog.debug.getStacktraceSimple);
- if (stack) {
- return stack;
- }
- // NOTE: browsers that have strict mode support also have native "stack"
- // properties. Fall-through for legacy browser support.
- }
-
- var sb = [];
- var fn = arguments.callee.caller;
- var depth = 0;
-
- while (fn && (!opt_depth || depth < opt_depth)) {
- sb.push(goog.debug.getFunctionName(fn));
- sb.push('()\n');
- /** @preserveTry */
- try {
- fn = fn.caller;
- } catch (e) {
- sb.push('[exception trying to get caller]\n');
- break;
- }
- depth++;
- if (depth >= goog.debug.MAX_STACK_DEPTH) {
- sb.push('[...long stack...]');
- break;
- }
- }
- if (opt_depth && depth >= opt_depth) {
- sb.push('[...reached max depth limit...]');
- } else {
- sb.push('[end]');
- }
-
- return sb.join('');
-};
-
-
-/**
- * Max length of stack to try and output
- * @type {number}
- */
-goog.debug.MAX_STACK_DEPTH = 50;
-
-
-/**
- * @param {Function} fn The function to start getting the trace from.
- * @return {?string}
- * @private
- */
-goog.debug.getNativeStackTrace_ = function(fn) {
- var tempErr = new Error();
- if (Error.captureStackTrace) {
- Error.captureStackTrace(tempErr, fn);
- return String(tempErr.stack);
- } else {
- // IE10, only adds stack traces when an exception is thrown.
- try {
- throw tempErr;
- } catch (e) {
- tempErr = e;
- }
- var stack = tempErr.stack;
- if (stack) {
- return String(stack);
- }
- }
- return null;
-};
-
-
-/**
- * Gets the current stack trace, either starting from the caller or starting
- * from a specified function that's currently on the call stack.
- * @param {Function=} opt_fn Optional function to start getting the trace from.
- * If not provided, defaults to the function that called this.
- * @return {string} Stack trace.
- * @suppress {es5Strict}
- */
-goog.debug.getStacktrace = function(opt_fn) {
- var stack;
- if (goog.STRICT_MODE_COMPATIBLE) {
- // Try to get the stack trace from the environment if it is available.
- var contextFn = opt_fn || goog.debug.getStacktrace;
- stack = goog.debug.getNativeStackTrace_(contextFn);
- }
- if (!stack) {
- // NOTE: browsers that have strict mode support also have native "stack"
- // properties. This function will throw in strict mode.
- stack = goog.debug.getStacktraceHelper_(
- opt_fn || arguments.callee.caller, []);
- }
- return stack;
-};
-
-
-/**
- * Private helper for getStacktrace().
- * @param {Function} fn Function to start getting the trace from.
- * @param {Array<!Function>} visited List of functions visited so far.
- * @return {string} Stack trace starting from function fn.
- * @suppress {es5Strict}
- * @private
- */
-goog.debug.getStacktraceHelper_ = function(fn, visited) {
- var sb = [];
-
- // Circular reference, certain functions like bind seem to cause a recursive
- // loop so we need to catch circular references
- if (goog.array.contains(visited, fn)) {
- sb.push('[...circular reference...]');
-
- // Traverse the call stack until function not found or max depth is reached
- } else if (fn && visited.length < goog.debug.MAX_STACK_DEPTH) {
- sb.push(goog.debug.getFunctionName(fn) + '(');
- var args = fn.arguments;
- // Args may be null for some special functions such as host objects or eval.
- for (var i = 0; args && i < args.length; i++) {
- if (i > 0) {
- sb.push(', ');
- }
- var argDesc;
- var arg = args[i];
- switch (typeof arg) {
- case 'object':
- argDesc = arg ? 'object' : 'null';
- break;
-
- case 'string':
- argDesc = arg;
- break;
-
- case 'number':
- argDesc = String(arg);
- break;
-
- case 'boolean':
- argDesc = arg ? 'true' : 'false';
- break;
-
- case 'function':
- argDesc = goog.debug.getFunctionName(arg);
- argDesc = argDesc ? argDesc : '[fn]';
- break;
-
- case 'undefined':
- default:
- argDesc = typeof arg;
- break;
- }
-
- if (argDesc.length > 40) {
- argDesc = argDesc.substr(0, 40) + '...';
- }
- sb.push(argDesc);
- }
- visited.push(fn);
- sb.push(')\n');
- /** @preserveTry */
- try {
- sb.push(goog.debug.getStacktraceHelper_(fn.caller, visited));
- } catch (e) {
- sb.push('[exception trying to get caller]\n');
- }
-
- } else if (fn) {
- sb.push('[...long stack...]');
- } else {
- sb.push('[end]');
- }
- return sb.join('');
-};
-
-
-/**
- * Set a custom function name resolver.
- * @param {function(Function): string} resolver Resolves functions to their
- * names.
+ * @param {!function():T} fn A function to lazily evaluate.
+ * @return {!function():T} A wrapped version the function.
+ * @template T
*/
-goog.debug.setFunctionResolver = function(resolver) {
- goog.debug.fnNameResolver_ = resolver;
-};
-
+goog.functions.cacheReturnValue = function(fn) {
+ var called = false;
+ var value;
-/**
- * Gets a function name
- * @param {Function} fn Function to get name of.
- * @return {string} Function's name.
- */
-goog.debug.getFunctionName = function(fn) {
- if (goog.debug.fnNameCache_[fn]) {
- return goog.debug.fnNameCache_[fn];
- }
- if (goog.debug.fnNameResolver_) {
- var name = goog.debug.fnNameResolver_(fn);
- if (name) {
- goog.debug.fnNameCache_[fn] = name;
- return name;
+ return function() {
+ if (!goog.functions.CACHE_RETURN_VALUE) {
+ return fn();
}
- }
- // Heuristically determine function name based on code.
- var functionSource = String(fn);
- if (!goog.debug.fnNameCache_[functionSource]) {
- var matches = /function ([^\(]+)/.exec(functionSource);
- if (matches) {
- var method = matches[1];
- goog.debug.fnNameCache_[functionSource] = method;
- } else {
- goog.debug.fnNameCache_[functionSource] = '[Anonymous]';
+ if (!called) {
+ value = fn();
+ called = true;
}
- }
-
- return goog.debug.fnNameCache_[functionSource];
-};
-
-
-/**
- * Makes whitespace visible by replacing it with printable characters.
- * This is useful in finding diffrences between the expected and the actual
- * output strings of a testcase.
- * @param {string} string whose whitespace needs to be made visible.
- * @return {string} string whose whitespace is made visible.
- */
-goog.debug.makeWhitespaceVisible = function(string) {
- return string.replace(/ /g, '[_]')
- .replace(/\f/g, '[f]')
- .replace(/\n/g, '[n]\n')
- .replace(/\r/g, '[r]')
- .replace(/\t/g, '[t]');
-};
-
-
-/**
- * Returns the type of a value. If a constructor is passed, and a suitable
- * string cannot be found, 'unknown type name' will be returned.
- *
- * <p>Forked rather than moved from {@link goog.asserts.getType_}
- * to avoid adding a dependency to goog.asserts.
- * @param {*} value A constructor, object, or primitive.
- * @return {string} The best display name for the value, or 'unknown type name'.
- */
-goog.debug.runtimeType = function(value) {
- if (value instanceof Function) {
- return value.displayName || value.name || 'unknown type name';
- } else if (value instanceof Object) {
- return value.constructor.displayName || value.constructor.name ||
- Object.prototype.toString.call(value);
- } else {
- return value === null ? 'null' : typeof value;
- }
-};
-
-/**
- * Hash map for storing function names that have already been looked up.
- * @type {Object}
- * @private
- */
-goog.debug.fnNameCache_ = {};
-
-
-/**
- * Resolves functions to their names. Resolved function names will be cached.
- * @type {function(Function):string}
- * @private
- */
-goog.debug.fnNameResolver_;
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Definition of the LogRecord class. Please minimize
- * dependencies this file has on other closure classes as any dependency it
- * takes won't be able to use the logging infrastructure.
- *
- */
-
-goog.provide('goog.debug.LogRecord');
-
-
-
-/**
- * LogRecord objects are used to pass logging requests between
- * the logging framework and individual log Handlers.
- * @constructor
- * @param {goog.debug.Logger.Level} level One of the level identifiers.
- * @param {string} msg The string message.
- * @param {string} loggerName The name of the source logger.
- * @param {number=} opt_time Time this log record was created if other than now.
- * If 0, we use #goog.now.
- * @param {number=} opt_sequenceNumber Sequence number of this log record. This
- * should only be passed in when restoring a log record from persistence.
- */
-goog.debug.LogRecord = function(level, msg, loggerName,
- opt_time, opt_sequenceNumber) {
- this.reset(level, msg, loggerName, opt_time, opt_sequenceNumber);
-};
-
-
-/**
- * Time the LogRecord was created.
- * @type {number}
- * @private
- */
-goog.debug.LogRecord.prototype.time_;
-
-
-/**
- * Level of the LogRecord
- * @type {goog.debug.Logger.Level}
- * @private
- */
-goog.debug.LogRecord.prototype.level_;
-
-
-/**
- * Message associated with the record
- * @type {string}
- * @private
- */
-goog.debug.LogRecord.prototype.msg_;
-
-
-/**
- * Name of the logger that created the record.
- * @type {string}
- * @private
- */
-goog.debug.LogRecord.prototype.loggerName_;
-
-
-/**
- * Sequence number for the LogRecord. Each record has a unique sequence number
- * that is greater than all log records created before it.
- * @type {number}
- * @private
- */
-goog.debug.LogRecord.prototype.sequenceNumber_ = 0;
-
-
-/**
- * Exception associated with the record
- * @type {Object}
- * @private
- */
-goog.debug.LogRecord.prototype.exception_ = null;
-
-
-/**
- * @define {boolean} Whether to enable log sequence numbers.
- */
-goog.define('goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS', true);
-
-
-/**
- * A sequence counter for assigning increasing sequence numbers to LogRecord
- * objects.
- * @type {number}
- * @private
- */
-goog.debug.LogRecord.nextSequenceNumber_ = 0;
-
-
-/**
- * Sets all fields of the log record.
- * @param {goog.debug.Logger.Level} level One of the level identifiers.
- * @param {string} msg The string message.
- * @param {string} loggerName The name of the source logger.
- * @param {number=} opt_time Time this log record was created if other than now.
- * If 0, we use #goog.now.
- * @param {number=} opt_sequenceNumber Sequence number of this log record. This
- * should only be passed in when restoring a log record from persistence.
- */
-goog.debug.LogRecord.prototype.reset = function(level, msg, loggerName,
- opt_time, opt_sequenceNumber) {
- if (goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS) {
- this.sequenceNumber_ = typeof opt_sequenceNumber == 'number' ?
- opt_sequenceNumber : goog.debug.LogRecord.nextSequenceNumber_++;
+ return value;
}
-
- this.time_ = opt_time || goog.now();
- this.level_ = level;
- this.msg_ = msg;
- this.loggerName_ = loggerName;
- delete this.exception_;
-};
-
-
-/**
- * Get the source Logger's name.
- *
- * @return {string} source logger name (may be null).
- */
-goog.debug.LogRecord.prototype.getLoggerName = function() {
- return this.loggerName_;
-};
-
-
-/**
- * Get the exception that is part of the log record.
- *
- * @return {Object} the exception.
- */
-goog.debug.LogRecord.prototype.getException = function() {
- return this.exception_;
-};
-
-
-/**
- * Set the exception that is part of the log record.
- *
- * @param {Object} exception the exception.
- */
-goog.debug.LogRecord.prototype.setException = function(exception) {
- this.exception_ = exception;
-};
-
-
-/**
- * Get the source Logger's name.
- *
- * @param {string} loggerName source logger name (may be null).
- */
-goog.debug.LogRecord.prototype.setLoggerName = function(loggerName) {
- this.loggerName_ = loggerName;
-};
-
-
-/**
- * Get the logging message level, for example Level.SEVERE.
- * @return {goog.debug.Logger.Level} the logging message level.
- */
-goog.debug.LogRecord.prototype.getLevel = function() {
- return this.level_;
-};
-
-
-/**
- * Set the logging message level, for example Level.SEVERE.
- * @param {goog.debug.Logger.Level} level the logging message level.
- */
-goog.debug.LogRecord.prototype.setLevel = function(level) {
- this.level_ = level;
};
/**
- * Get the "raw" log message, before localization or formatting.
- *
- * @return {string} the raw message string.
- */
-goog.debug.LogRecord.prototype.getMessage = function() {
- return this.msg_;
-};
-
-
-/**
- * Set the "raw" log message, before localization or formatting.
+ * Wraps a function to allow it to be called, at most, once. All
+ * additional calls are no-ops.
*
- * @param {string} msg the raw message string.
- */
-goog.debug.LogRecord.prototype.setMessage = function(msg) {
- this.msg_ = msg;
-};
-
-
-/**
- * Get event time in milliseconds since 1970.
+ * This is particularly useful for initialization functions
+ * that should be called, at most, once.
*
- * @return {number} event time in millis since 1970.
+ * @param {function():*} f Function to call.
+ * @return {function():undefined} Wrapped function.
*/
-goog.debug.LogRecord.prototype.getMillis = function() {
- return this.time_;
+goog.functions.once = function(f) {
+ // Keep a reference to the function that we null out when we're done with
+ // it -- that way, the function can be GC'd when we're done with it.
+ var inner = f;
+ return function() {
+ if (inner) {
+ var tmp = inner;
+ inner = null;
+ tmp();
+ }
+ };
};
/**
- * Set event time in milliseconds since 1970.
+ * Wraps a function to allow it to be called, at most, once for each sequence of
+ * calls fired repeatedly so long as they are fired less than a specified
+ * interval apart (in milliseconds). Whether it receives one signal or multiple,
+ * it will always wait until a full interval has elapsed since the last signal
+ * before performing the action, passing the arguments from the last call of the
+ * debouncing decorator into the decorated function.
*
- * @param {number} time event time in millis since 1970.
- */
-goog.debug.LogRecord.prototype.setMillis = function(time) {
- this.time_ = time;
-};
-
-
-/**
- * Get the sequence number.
- * <p>
- * Sequence numbers are normally assigned in the LogRecord
- * constructor, which assigns unique sequence numbers to
- * each new LogRecord in increasing order.
- * @return {number} the sequence number.
- */
-goog.debug.LogRecord.prototype.getSequenceNumber = function() {
- return this.sequenceNumber_;
-};
-
-
-// Copyright 2010 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview A buffer for log records. The purpose of this is to improve
- * logging performance by re-using old objects when the buffer becomes full and
- * to eliminate the need for each app to implement their own log buffer. The
- * disadvantage to doing this is that log handlers cannot maintain references to
- * log records and expect that they are not overwriten at a later point.
+ * This is particularly useful for bulking up repeated user actions (e.g. only
+ * refreshing a view once a user finishes typing rather than updating with every
+ * keystroke). For more stateful debouncing with support for pausing, resuming,
+ * and canceling debounced actions, use {@code goog.async.Debouncer}.
*
- * @author agrieve@google.com (Andrew Grieve)
- */
-
-goog.provide('goog.debug.LogBuffer');
-
-goog.require('goog.asserts');
-goog.require('goog.debug.LogRecord');
-
-
-
-/**
- * Creates the log buffer.
- * @constructor
- * @final
- */
-goog.debug.LogBuffer = function() {
- goog.asserts.assert(goog.debug.LogBuffer.isBufferingEnabled(),
- 'Cannot use goog.debug.LogBuffer without defining ' +
- 'goog.debug.LogBuffer.CAPACITY.');
- this.clear();
-};
-
-
-/**
- * A static method that always returns the same instance of LogBuffer.
- * @return {!goog.debug.LogBuffer} The LogBuffer singleton instance.
- */
-goog.debug.LogBuffer.getInstance = function() {
- if (!goog.debug.LogBuffer.instance_) {
- // This function is written with the return statement after the assignment
- // to avoid the jscompiler StripCode bug described in http://b/2608064.
- // After that bug is fixed this can be refactored.
- goog.debug.LogBuffer.instance_ = new goog.debug.LogBuffer();
- }
- return goog.debug.LogBuffer.instance_;
-};
-
-
-/**
- * @define {number} The number of log records to buffer. 0 means disable
- * buffering.
- */
-goog.define('goog.debug.LogBuffer.CAPACITY', 0);
-
-
-/**
- * The array to store the records.
- * @type {!Array<!goog.debug.LogRecord|undefined>}
- * @private
- */
-goog.debug.LogBuffer.prototype.buffer_;
-
-
-/**
- * The index of the most recently added record or -1 if there are no records.
- * @type {number}
- * @private
- */
-goog.debug.LogBuffer.prototype.curIndex_;
-
-
-/**
- * Whether the buffer is at capacity.
- * @type {boolean}
- * @private
- */
-goog.debug.LogBuffer.prototype.isFull_;
-
-
-/**
- * Adds a log record to the buffer, possibly overwriting the oldest record.
- * @param {goog.debug.Logger.Level} level One of the level identifiers.
- * @param {string} msg The string message.
- * @param {string} loggerName The name of the source logger.
- * @return {!goog.debug.LogRecord} The log record.
- */
-goog.debug.LogBuffer.prototype.addRecord = function(level, msg, loggerName) {
- var curIndex = (this.curIndex_ + 1) % goog.debug.LogBuffer.CAPACITY;
- this.curIndex_ = curIndex;
- if (this.isFull_) {
- var ret = this.buffer_[curIndex];
- ret.reset(level, msg, loggerName);
- return ret;
- }
- this.isFull_ = curIndex == goog.debug.LogBuffer.CAPACITY - 1;
- return this.buffer_[curIndex] =
- new goog.debug.LogRecord(level, msg, loggerName);
-};
-
-
-/**
- * @return {boolean} Whether the log buffer is enabled.
- */
-goog.debug.LogBuffer.isBufferingEnabled = function() {
- return goog.debug.LogBuffer.CAPACITY > 0;
-};
-
-
-/**
- * Removes all buffered log records.
- */
-goog.debug.LogBuffer.prototype.clear = function() {
- this.buffer_ = new Array(goog.debug.LogBuffer.CAPACITY);
- this.curIndex_ = -1;
- this.isFull_ = false;
-};
-
-
-/**
- * Calls the given function for each buffered log record, starting with the
- * oldest one.
- * @param {function(!goog.debug.LogRecord)} func The function to call.
+ * @param {function(this:SCOPE, ...?)} f Function to call.
+ * @param {number} interval Interval over which to debounce. The function will
+ * only be called after the full interval has elapsed since the last call.
+ * @param {SCOPE=} opt_scope Object in whose scope to call the function.
+ * @return {function(...?): undefined} Wrapped function.
+ * @template SCOPE
*/
-goog.debug.LogBuffer.prototype.forEachRecord = function(func) {
- var buffer = this.buffer_;
- // Corner case: no records.
- if (!buffer[0]) {
- return;
+goog.functions.debounce = function(f, interval, opt_scope) {
+ if (opt_scope) {
+ f = goog.bind(f, opt_scope);
}
- var curIndex = this.curIndex_;
- var i = this.isFull_ ? curIndex : -1;
- do {
- i = (i + 1) % goog.debug.LogBuffer.CAPACITY;
- func(/** @type {!goog.debug.LogRecord} */ (buffer[i]));
- } while (i != curIndex);
-};
-
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Definition of the Logger class. Please minimize dependencies
- * this file has on other closure classes as any dependency it takes won't be
- * able to use the logging infrastructure.
- *
- * @see ../demos/debug.html
- */
-
-goog.provide('goog.debug.LogManager');
-goog.provide('goog.debug.Loggable');
-goog.provide('goog.debug.Logger');
-goog.provide('goog.debug.Logger.Level');
-
-goog.require('goog.array');
-goog.require('goog.asserts');
-goog.require('goog.debug');
-goog.require('goog.debug.LogBuffer');
-goog.require('goog.debug.LogRecord');
-
-
-/**
- * A message value that can be handled by a Logger.
- *
- * Functions are treated like callbacks, but are only called when the event's
- * log level is enabled. This is useful for logging messages that are expensive
- * to construct.
- *
- * @typedef {string|function(): string}
- */
-goog.debug.Loggable;
-
-
-
-/**
- * The Logger is an object used for logging debug messages. Loggers are
- * normally named, using a hierarchical dot-separated namespace. Logger names
- * can be arbitrary strings, but they should normally be based on the package
- * name or class name of the logged component, such as goog.net.BrowserChannel.
- *
- * The Logger object is loosely based on the java class
- * java.util.logging.Logger. It supports different levels of filtering for
- * different loggers.
- *
- * The logger object should never be instantiated by application code. It
- * should always use the goog.debug.Logger.getLogger function.
- *
- * @constructor
- * @param {string} name The name of the Logger.
- * @final
- */
-goog.debug.Logger = function(name) {
- /**
- * Name of the Logger. Generally a dot-separated namespace
- * @private {string}
- */
- this.name_ = name;
-
- /**
- * Parent Logger.
- * @private {goog.debug.Logger}
- */
- this.parent_ = null;
-
- /**
- * Level that this logger only filters above. Null indicates it should
- * inherit from the parent.
- * @private {goog.debug.Logger.Level}
- */
- this.level_ = null;
-
- /**
- * Map of children loggers. The keys are the leaf names of the children and
- * the values are the child loggers.
- * @private {Object}
- */
- this.children_ = null;
-
- /**
- * Handlers that are listening to this logger.
- * @private {Array<Function>}
- */
- this.handlers_ = null;
+ var timeout = null;
+ return /** @type {function(...?)} */ (function(var_args) {
+ goog.global.clearTimeout(timeout);
+ var args = arguments;
+ timeout =
+ goog.global.setTimeout(function() { f.apply(null, args); }, interval);
+ });
};
-/** @const */
-goog.debug.Logger.ROOT_LOGGER_NAME = '';
-
-
-/**
- * @define {boolean} Toggles whether loggers other than the root logger can have
- * log handlers attached to them and whether they can have their log level
- * set. Logging is a bit faster when this is set to false.
- */
-goog.define('goog.debug.Logger.ENABLE_HIERARCHY', true);
-
-
-if (!goog.debug.Logger.ENABLE_HIERARCHY) {
- /**
- * @type {!Array<Function>}
- * @private
- */
- goog.debug.Logger.rootHandlers_ = [];
-
-
- /**
- * @type {goog.debug.Logger.Level}
- * @private
- */
- goog.debug.Logger.rootLevel_;
-}
-
-
-
/**
- * The Level class defines a set of standard logging levels that
- * can be used to control logging output. The logging Level objects
- * are ordered and are specified by ordered integers. Enabling logging
- * at a given level also enables logging at all higher levels.
- * <p>
- * Clients should normally use the predefined Level constants such
- * as Level.SEVERE.
- * <p>
- * The levels in descending order are:
- * <ul>
- * <li>SEVERE (highest value)
- * <li>WARNING
- * <li>INFO
- * <li>CONFIG
- * <li>FINE
- * <li>FINER
- * <li>FINEST (lowest value)
- * </ul>
- * In addition there is a level OFF that can be used to turn
- * off logging, and a level ALL that can be used to enable
- * logging of all messages.
+ * Wraps a function to allow it to be called, at most, once per interval
+ * (specified in milliseconds). If it is called multiple times while it is
+ * waiting, it will only perform the action once at the end of the interval,
+ * passing the arguments from the last call of the throttling decorator into the
+ * decorated function.
*
- * @param {string} name The name of the level.
- * @param {number} value The numeric value of the level.
- * @constructor
- * @final
- */
-goog.debug.Logger.Level = function(name, value) {
- /**
- * The name of the level
- * @type {string}
- */
- this.name = name;
-
- /**
- * The numeric value of the level
- * @type {number}
- */
- this.value = value;
-};
-
-
-/**
- * @return {string} String representation of the logger level.
- * @override
- */
-goog.debug.Logger.Level.prototype.toString = function() {
- return this.name;
-};
-
-
-/**
- * OFF is a special level that can be used to turn off logging.
- * This level is initialized to <CODE>Infinity</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.OFF =
- new goog.debug.Logger.Level('OFF', Infinity);
-
-
-/**
- * SHOUT is a message level for extra debugging loudness.
- * This level is initialized to <CODE>1200</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.SHOUT = new goog.debug.Logger.Level('SHOUT', 1200);
-
-
-/**
- * SEVERE is a message level indicating a serious failure.
- * This level is initialized to <CODE>1000</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.SEVERE = new goog.debug.Logger.Level('SEVERE', 1000);
-
-
-/**
- * WARNING is a message level indicating a potential problem.
- * This level is initialized to <CODE>900</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.WARNING = new goog.debug.Logger.Level('WARNING', 900);
-
-
-/**
- * INFO is a message level for informational messages.
- * This level is initialized to <CODE>800</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.INFO = new goog.debug.Logger.Level('INFO', 800);
-
-
-/**
- * CONFIG is a message level for static configuration messages.
- * This level is initialized to <CODE>700</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.CONFIG = new goog.debug.Logger.Level('CONFIG', 700);
-
-
-/**
- * FINE is a message level providing tracing information.
- * This level is initialized to <CODE>500</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.FINE = new goog.debug.Logger.Level('FINE', 500);
-
-
-/**
- * FINER indicates a fairly detailed tracing message.
- * This level is initialized to <CODE>400</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.FINER = new goog.debug.Logger.Level('FINER', 400);
-
-/**
- * FINEST indicates a highly detailed tracing message.
- * This level is initialized to <CODE>300</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-
-goog.debug.Logger.Level.FINEST = new goog.debug.Logger.Level('FINEST', 300);
-
-
-/**
- * ALL indicates that all messages should be logged.
- * This level is initialized to <CODE>0</CODE>.
- * @type {!goog.debug.Logger.Level}
- */
-goog.debug.Logger.Level.ALL = new goog.debug.Logger.Level('ALL', 0);
-
-
-/**
- * The predefined levels.
- * @type {!Array<!goog.debug.Logger.Level>}
- * @final
- */
-goog.debug.Logger.Level.PREDEFINED_LEVELS = [
- goog.debug.Logger.Level.OFF,
- goog.debug.Logger.Level.SHOUT,
- goog.debug.Logger.Level.SEVERE,
- goog.debug.Logger.Level.WARNING,
- goog.debug.Logger.Level.INFO,
- goog.debug.Logger.Level.CONFIG,
- goog.debug.Logger.Level.FINE,
- goog.debug.Logger.Level.FINER,
- goog.debug.Logger.Level.FINEST,
- goog.debug.Logger.Level.ALL];
-
-
-/**
- * A lookup map used to find the level object based on the name or value of
- * the level object.
- * @type {Object}
- * @private
- */
-goog.debug.Logger.Level.predefinedLevelsCache_ = null;
-
-
-/**
- * Creates the predefined levels cache and populates it.
- * @private
- */
-goog.debug.Logger.Level.createPredefinedLevelsCache_ = function() {
- goog.debug.Logger.Level.predefinedLevelsCache_ = {};
- for (var i = 0, level; level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
- i++) {
- goog.debug.Logger.Level.predefinedLevelsCache_[level.value] = level;
- goog.debug.Logger.Level.predefinedLevelsCache_[level.name] = level;
- }
-};
-
-
-/**
- * Gets the predefined level with the given name.
- * @param {string} name The name of the level.
- * @return {goog.debug.Logger.Level} The level, or null if none found.
- */
-goog.debug.Logger.Level.getPredefinedLevel = function(name) {
- if (!goog.debug.Logger.Level.predefinedLevelsCache_) {
- goog.debug.Logger.Level.createPredefinedLevelsCache_();
- }
-
- return goog.debug.Logger.Level.predefinedLevelsCache_[name] || null;
-};
-
-
-/**
- * Gets the highest predefined level <= #value.
- * @param {number} value Level value.
- * @return {goog.debug.Logger.Level} The level, or null if none found.
- */
-goog.debug.Logger.Level.getPredefinedLevelByValue = function(value) {
- if (!goog.debug.Logger.Level.predefinedLevelsCache_) {
- goog.debug.Logger.Level.createPredefinedLevelsCache_();
- }
-
- if (value in goog.debug.Logger.Level.predefinedLevelsCache_) {
- return goog.debug.Logger.Level.predefinedLevelsCache_[value];
- }
-
- for (var i = 0; i < goog.debug.Logger.Level.PREDEFINED_LEVELS.length; ++i) {
- var level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
- if (level.value <= value) {
- return level;
- }
- }
- return null;
-};
-
-
-/**
- * Finds or creates a logger for a named subsystem. If a logger has already been
- * created with the given name it is returned. Otherwise a new logger is
- * created. If a new logger is created its log level will be configured based
- * on the LogManager configuration and it will configured to also send logging
- * output to its parent's handlers. It will be registered in the LogManager
- * global namespace.
+ * This is particularly useful for limiting repeated user requests (e.g.
+ * preventing a user from spamming a server with frequent view refreshes). For
+ * more stateful throttling with support for pausing, resuming, and canceling
+ * throttled actions, use {@code goog.async.Throttle}.
*
- * @param {string} name A name for the logger. This should be a dot-separated
- * name and should normally be based on the package name or class name of the
- * subsystem, such as goog.net.BrowserChannel.
- * @return {!goog.debug.Logger} The named logger.
- * @deprecated use goog.log instead. http://go/goog-debug-logger-deprecated
- */
-goog.debug.Logger.getLogger = function(name) {
- return goog.debug.LogManager.getLogger(name);
-};
-
-
-/**
- * Logs a message to profiling tools, if available.
- * {@see https://developers.google.com/web-toolkit/speedtracer/logging-api}
- * {@see http://msdn.microsoft.com/en-us/library/dd433074(VS.85).aspx}
- * @param {string} msg The message to log.
+ * @param {function(this:SCOPE, ...?)} f Function to call.
+ * @param {number} interval Interval over which to throttle. The function can
+ * only be called once per interval.
+ * @param {SCOPE=} opt_scope Object in whose scope to call the function.
+ * @return {function(...?): undefined} Wrapped function.
+ * @template SCOPE
*/
-goog.debug.Logger.logToProfilers = function(msg) {
- // Using goog.global, as loggers might be used in window-less contexts.
- if (goog.global['console']) {
- if (goog.global['console']['timeStamp']) {
- // Logs a message to Firebug, Web Inspector, SpeedTracer, etc.
- goog.global['console']['timeStamp'](msg);
- } else if (goog.global['console']['markTimeline']) {
- // TODO(user): markTimeline is deprecated. Drop this else clause entirely
- // after Chrome M14 hits stable.
- goog.global['console']['markTimeline'](msg);
- }
- }
-
- if (goog.global['msWriteProfilerMark']) {
- // Logs a message to the Microsoft profiler
- goog.global['msWriteProfilerMark'](msg);
+goog.functions.throttle = function(f, interval, opt_scope) {
+ if (opt_scope) {
+ f = goog.bind(f, opt_scope);
}
-};
-
-
-/**
- * Gets the name of this logger.
- * @return {string} The name of this logger.
- */
-goog.debug.Logger.prototype.getName = function() {
- return this.name_;
-};
-
+ var timeout = null;
+ var shouldFire = false;
+ var args = [];
-/**
- * Adds a handler to the logger. This doesn't use the event system because
- * we want to be able to add logging to the event system.
- * @param {Function} handler Handler function to add.
- */
-goog.debug.Logger.prototype.addHandler = function(handler) {
- if (goog.debug.LOGGING_ENABLED) {
- if (goog.debug.Logger.ENABLE_HIERARCHY) {
- if (!this.handlers_) {
- this.handlers_ = [];
- }
- this.handlers_.push(handler);
- } else {
- goog.asserts.assert(!this.name_,
- 'Cannot call addHandler on a non-root logger when ' +
- 'goog.debug.Logger.ENABLE_HIERARCHY is false.');
- goog.debug.Logger.rootHandlers_.push(handler);
+ var handleTimeout = function() {
+ timeout = null;
+ if (shouldFire) {
+ shouldFire = false;
+ fire();
}
- }
-};
-
-
-/**
- * Removes a handler from the logger. This doesn't use the event system because
- * we want to be able to add logging to the event system.
- * @param {Function} handler Handler function to remove.
- * @return {boolean} Whether the handler was removed.
- */
-goog.debug.Logger.prototype.removeHandler = function(handler) {
- if (goog.debug.LOGGING_ENABLED) {
- var handlers = goog.debug.Logger.ENABLE_HIERARCHY ? this.handlers_ :
- goog.debug.Logger.rootHandlers_;
- return !!handlers && goog.array.remove(handlers, handler);
- } else {
- return false;
- }
-};
-
-
-/**
- * Returns the parent of this logger.
- * @return {goog.debug.Logger} The parent logger or null if this is the root.
- */
-goog.debug.Logger.prototype.getParent = function() {
- return this.parent_;
-};
-
-
-/**
- * Returns the children of this logger as a map of the child name to the logger.
- * @return {!Object} The map where the keys are the child leaf names and the
- * values are the Logger objects.
- */
-goog.debug.Logger.prototype.getChildren = function() {
- if (!this.children_) {
- this.children_ = {};
- }
- return this.children_;
-};
+ };
+ var fire = function() {
+ timeout = goog.global.setTimeout(handleTimeout, interval);
+ f.apply(null, args);
+ };
-/**
- * Set the log level specifying which message levels will be logged by this
- * logger. Message levels lower than this value will be discarded.
- * The level value Level.OFF can be used to turn off logging. If the new level
- * is null, it means that this node should inherit its level from its nearest
- * ancestor with a specific (non-null) level value.
- *
- * @param {goog.debug.Logger.Level} level The new level.
- */
-goog.debug.Logger.prototype.setLevel = function(level) {
- if (goog.debug.LOGGING_ENABLED) {
- if (goog.debug.Logger.ENABLE_HIERARCHY) {
- this.level_ = level;
+ return /** @type {function(...?)} */ (function(var_args) {
+ args = arguments;
+ if (!timeout) {
+ fire();
} else {
- goog.asserts.assert(!this.name_,
- 'Cannot call setLevel() on a non-root logger when ' +
- 'goog.debug.Logger.ENABLE_HIERARCHY is false.');
- goog.debug.Logger.rootLevel_ = level;
- }
- }
-};
-
-
-/**
- * Gets the log level specifying which message levels will be logged by this
- * logger. Message levels lower than this value will be discarded.
- * The level value Level.OFF can be used to turn off logging. If the level
- * is null, it means that this node should inherit its level from its nearest
- * ancestor with a specific (non-null) level value.
- *
- * @return {goog.debug.Logger.Level} The level.
- */
-goog.debug.Logger.prototype.getLevel = function() {
- return goog.debug.LOGGING_ENABLED ?
- this.level_ : goog.debug.Logger.Level.OFF;
-};
-
-
-/**
- * Returns the effective level of the logger based on its ancestors' levels.
- * @return {goog.debug.Logger.Level} The level.
- */
-goog.debug.Logger.prototype.getEffectiveLevel = function() {
- if (!goog.debug.LOGGING_ENABLED) {
- return goog.debug.Logger.Level.OFF;
- }
-
- if (!goog.debug.Logger.ENABLE_HIERARCHY) {
- return goog.debug.Logger.rootLevel_;
- }
- if (this.level_) {
- return this.level_;
- }
- if (this.parent_) {
- return this.parent_.getEffectiveLevel();
- }
- goog.asserts.fail('Root logger has no level set.');
- return null;
-};
-
-
-/**
- * Checks if a message of the given level would actually be logged by this
- * logger. This check is based on the Loggers effective level, which may be
- * inherited from its parent.
- * @param {goog.debug.Logger.Level} level The level to check.
- * @return {boolean} Whether the message would be logged.
- */
-goog.debug.Logger.prototype.isLoggable = function(level) {
- return goog.debug.LOGGING_ENABLED &&
- level.value >= this.getEffectiveLevel().value;
-};
-
-
-/**
- * Logs a message. If the logger is currently enabled for the
- * given message level then the given message is forwarded to all the
- * registered output Handler objects.
- * @param {goog.debug.Logger.Level} level One of the level identifiers.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error|Object=} opt_exception An exception associated with the
- * message.
- */
-goog.debug.Logger.prototype.log = function(level, msg, opt_exception) {
- // java caches the effective level, not sure it's necessary here
- if (goog.debug.LOGGING_ENABLED && this.isLoggable(level)) {
- // Message callbacks can be useful when a log message is expensive to build.
- if (goog.isFunction(msg)) {
- msg = msg();
- }
-
- this.doLogRecord_(this.getLogRecord(level, msg, opt_exception));
- }
-};
-
-
-/**
- * Creates a new log record and adds the exception (if present) to it.
- * @param {goog.debug.Logger.Level} level One of the level identifiers.
- * @param {string} msg The string message.
- * @param {Error|Object=} opt_exception An exception associated with the
- * message.
- * @return {!goog.debug.LogRecord} A log record.
- * @suppress {es5Strict}
- */
-goog.debug.Logger.prototype.getLogRecord = function(
- level, msg, opt_exception) {
- if (goog.debug.LogBuffer.isBufferingEnabled()) {
- var logRecord =
- goog.debug.LogBuffer.getInstance().addRecord(level, msg, this.name_);
- } else {
- logRecord = new goog.debug.LogRecord(level, String(msg), this.name_);
- }
- if (opt_exception) {
- logRecord.setException(opt_exception);
- }
- return logRecord;
-};
-
-
-/**
- * Logs a message at the Logger.Level.SHOUT level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.debug.Logger.prototype.shout = function(msg, opt_exception) {
- if (goog.debug.LOGGING_ENABLED) {
- this.log(goog.debug.Logger.Level.SHOUT, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Logger.Level.SEVERE level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.debug.Logger.prototype.severe = function(msg, opt_exception) {
- if (goog.debug.LOGGING_ENABLED) {
- this.log(goog.debug.Logger.Level.SEVERE, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Logger.Level.WARNING level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.debug.Logger.prototype.warning = function(msg, opt_exception) {
- if (goog.debug.LOGGING_ENABLED) {
- this.log(goog.debug.Logger.Level.WARNING, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Logger.Level.INFO level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.debug.Logger.prototype.info = function(msg, opt_exception) {
- if (goog.debug.LOGGING_ENABLED) {
- this.log(goog.debug.Logger.Level.INFO, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Logger.Level.CONFIG level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.debug.Logger.prototype.config = function(msg, opt_exception) {
- if (goog.debug.LOGGING_ENABLED) {
- this.log(goog.debug.Logger.Level.CONFIG, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Logger.Level.FINE level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.debug.Logger.prototype.fine = function(msg, opt_exception) {
- if (goog.debug.LOGGING_ENABLED) {
- this.log(goog.debug.Logger.Level.FINE, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Logger.Level.FINER level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.debug.Logger.prototype.finer = function(msg, opt_exception) {
- if (goog.debug.LOGGING_ENABLED) {
- this.log(goog.debug.Logger.Level.FINER, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Logger.Level.FINEST level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.debug.Logger.prototype.finest = function(msg, opt_exception) {
- if (goog.debug.LOGGING_ENABLED) {
- this.log(goog.debug.Logger.Level.FINEST, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a LogRecord. If the logger is currently enabled for the
- * given message level then the given message is forwarded to all the
- * registered output Handler objects.
- * @param {goog.debug.LogRecord} logRecord A log record to log.
- */
-goog.debug.Logger.prototype.logRecord = function(logRecord) {
- if (goog.debug.LOGGING_ENABLED && this.isLoggable(logRecord.getLevel())) {
- this.doLogRecord_(logRecord);
- }
-};
-
-
-/**
- * Logs a LogRecord.
- * @param {goog.debug.LogRecord} logRecord A log record to log.
- * @private
- */
-goog.debug.Logger.prototype.doLogRecord_ = function(logRecord) {
- goog.debug.Logger.logToProfilers('log:' + logRecord.getMessage());
- if (goog.debug.Logger.ENABLE_HIERARCHY) {
- var target = this;
- while (target) {
- target.callPublish_(logRecord);
- target = target.getParent();
- }
- } else {
- for (var i = 0, handler; handler = goog.debug.Logger.rootHandlers_[i++]; ) {
- handler(logRecord);
- }
- }
-};
-
-
-/**
- * Calls the handlers for publish.
- * @param {goog.debug.LogRecord} logRecord The log record to publish.
- * @private
- */
-goog.debug.Logger.prototype.callPublish_ = function(logRecord) {
- if (this.handlers_) {
- for (var i = 0, handler; handler = this.handlers_[i]; i++) {
- handler(logRecord);
+ shouldFire = true;
}
- }
-};
-
-
-/**
- * Sets the parent of this logger. This is used for setting up the logger tree.
- * @param {goog.debug.Logger} parent The parent logger.
- * @private
- */
-goog.debug.Logger.prototype.setParent_ = function(parent) {
- this.parent_ = parent;
-};
-
-
-/**
- * Adds a child to this logger. This is used for setting up the logger tree.
- * @param {string} name The leaf name of the child.
- * @param {goog.debug.Logger} logger The child logger.
- * @private
- */
-goog.debug.Logger.prototype.addChild_ = function(name, logger) {
- this.getChildren()[name] = logger;
-};
-
-
-/**
- * There is a single global LogManager object that is used to maintain a set of
- * shared state about Loggers and log services. This is loosely based on the
- * java class java.util.logging.LogManager.
- * @const
- */
-goog.debug.LogManager = {};
-
-
-/**
- * Map of logger names to logger objects.
- *
- * @type {!Object<string, !goog.debug.Logger>}
- * @private
- */
-goog.debug.LogManager.loggers_ = {};
-
-
-/**
- * The root logger which is the root of the logger tree.
- * @type {goog.debug.Logger}
- * @private
- */
-goog.debug.LogManager.rootLogger_ = null;
-
-
-/**
- * Initializes the LogManager if not already initialized.
- */
-goog.debug.LogManager.initialize = function() {
- if (!goog.debug.LogManager.rootLogger_) {
- goog.debug.LogManager.rootLogger_ = new goog.debug.Logger(
- goog.debug.Logger.ROOT_LOGGER_NAME);
- goog.debug.LogManager.loggers_[goog.debug.Logger.ROOT_LOGGER_NAME] =
- goog.debug.LogManager.rootLogger_;
- goog.debug.LogManager.rootLogger_.setLevel(goog.debug.Logger.Level.CONFIG);
- }
-};
-
-
-/**
- * Returns all the loggers.
- * @return {!Object<string, !goog.debug.Logger>} Map of logger names to logger
- * objects.
- */
-goog.debug.LogManager.getLoggers = function() {
- return goog.debug.LogManager.loggers_;
-};
-
-
-/**
- * Returns the root of the logger tree namespace, the logger with the empty
- * string as its name.
- *
- * @return {!goog.debug.Logger} The root logger.
- */
-goog.debug.LogManager.getRoot = function() {
- goog.debug.LogManager.initialize();
- return /** @type {!goog.debug.Logger} */ (goog.debug.LogManager.rootLogger_);
-};
-
-
-/**
- * Finds a named logger.
- *
- * @param {string} name A name for the logger. This should be a dot-separated
- * name and should normally be based on the package name or class name of the
- * subsystem, such as goog.net.BrowserChannel.
- * @return {!goog.debug.Logger} The named logger.
- */
-goog.debug.LogManager.getLogger = function(name) {
- goog.debug.LogManager.initialize();
- var ret = goog.debug.LogManager.loggers_[name];
- return ret || goog.debug.LogManager.createLogger_(name);
-};
-
-
-/**
- * Creates a function that can be passed to goog.debug.catchErrors. The function
- * will log all reported errors using the given logger.
- * @param {goog.debug.Logger=} opt_logger The logger to log the errors to.
- * Defaults to the root logger.
- * @return {function(Object)} The created function.
- */
-goog.debug.LogManager.createFunctionForCatchErrors = function(opt_logger) {
- return function(info) {
- var logger = opt_logger || goog.debug.LogManager.getRoot();
- logger.severe('Error: ' + info.message + ' (' + info.fileName +
- ' @ Line: ' + info.line + ')');
- };
-};
-
-
-/**
- * Creates the named logger. Will also create the parents of the named logger
- * if they don't yet exist.
- * @param {string} name The name of the logger.
- * @return {!goog.debug.Logger} The named logger.
- * @private
- */
-goog.debug.LogManager.createLogger_ = function(name) {
- // find parent logger
- var logger = new goog.debug.Logger(name);
- if (goog.debug.Logger.ENABLE_HIERARCHY) {
- var lastDotIndex = name.lastIndexOf('.');
- var parentName = name.substr(0, lastDotIndex);
- var leafName = name.substr(lastDotIndex + 1);
- var parentLogger = goog.debug.LogManager.getLogger(parentName);
-
- // tell the parent about the child and the child about the parent
- parentLogger.addChild_(leafName, logger);
- logger.setParent_(parentLogger);
- }
-
- goog.debug.LogManager.loggers_[name] = logger;
- return logger;
-};
-
-// Copyright 2007 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Definition the goog.debug.RelativeTimeProvider class.
- *
- */
-
-goog.provide('goog.debug.RelativeTimeProvider');
-
-
-
-/**
- * A simple object to keep track of a timestamp considered the start of
- * something. The main use is for the logger system to maintain a start time
- * that is occasionally reset. For example, in Gmail, we reset this relative
- * time at the start of a user action so that timings are offset from the
- * beginning of the action. This class also provides a singleton as the default
- * behavior for most use cases is to share the same start time.
- *
- * @constructor
- * @final
- */
-goog.debug.RelativeTimeProvider = function() {
- /**
- * The start time.
- * @type {number}
- * @private
- */
- this.relativeTimeStart_ = goog.now();
-};
-
-
-/**
- * Default instance.
- * @type {goog.debug.RelativeTimeProvider}
- * @private
- */
-goog.debug.RelativeTimeProvider.defaultInstance_ =
- new goog.debug.RelativeTimeProvider();
-
-
-/**
- * Sets the start time to the specified time.
- * @param {number} timeStamp The start time.
- */
-goog.debug.RelativeTimeProvider.prototype.set = function(timeStamp) {
- this.relativeTimeStart_ = timeStamp;
-};
-
-
-/**
- * Resets the start time to now.
- */
-goog.debug.RelativeTimeProvider.prototype.reset = function() {
- this.set(goog.now());
-};
-
-
-/**
- * @return {number} The start time.
- */
-goog.debug.RelativeTimeProvider.prototype.get = function() {
- return this.relativeTimeStart_;
-};
-
-
-/**
- * @return {goog.debug.RelativeTimeProvider} The default instance.
- */
-goog.debug.RelativeTimeProvider.getDefaultInstance = function() {
- return goog.debug.RelativeTimeProvider.defaultInstance_;
+ });
};
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -44853,2232 +37730,253 @@ goog.debug.RelativeTimeProvider.getDefaultInstance = function() {
// limitations under the License.
/**
- * @fileoverview Definition of various formatters for logging. Please minimize
- * dependencies this file has on other closure classes as any dependency it
- * takes won't be able to use the logging infrastructure.
- *
- */
-
-goog.provide('goog.debug.Formatter');
-goog.provide('goog.debug.HtmlFormatter');
-goog.provide('goog.debug.TextFormatter');
-
-goog.require('goog.debug');
-goog.require('goog.debug.Logger');
-goog.require('goog.debug.RelativeTimeProvider');
-goog.require('goog.html.SafeHtml');
-
-
-
-/**
- * Base class for Formatters. A Formatter is used to format a LogRecord into
- * something that can be displayed to the user.
- *
- * @param {string=} opt_prefix The prefix to place before text records.
- * @constructor
- */
-goog.debug.Formatter = function(opt_prefix) {
- this.prefix_ = opt_prefix || '';
-
- /**
- * A provider that returns the relative start time.
- * @type {goog.debug.RelativeTimeProvider}
- * @private
- */
- this.startTimeProvider_ =
- goog.debug.RelativeTimeProvider.getDefaultInstance();
-};
-
-
-/**
- * Whether to append newlines to the end of formatted log records.
- * @type {boolean}
- */
-goog.debug.Formatter.prototype.appendNewline = true;
-
-
-/**
- * Whether to show absolute time in the DebugWindow.
- * @type {boolean}
- */
-goog.debug.Formatter.prototype.showAbsoluteTime = true;
-
-
-/**
- * Whether to show relative time in the DebugWindow.
- * @type {boolean}
- */
-goog.debug.Formatter.prototype.showRelativeTime = true;
-
-
-/**
- * Whether to show the logger name in the DebugWindow.
- * @type {boolean}
- */
-goog.debug.Formatter.prototype.showLoggerName = true;
-
-
-/**
- * Whether to show the logger exception text.
- * @type {boolean}
- */
-goog.debug.Formatter.prototype.showExceptionText = false;
-
-
-/**
- * Whether to show the severity level.
- * @type {boolean}
- */
-goog.debug.Formatter.prototype.showSeverityLevel = false;
-
-
-/**
- * Formats a record.
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {string} The formatted string.
- */
-goog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;
-
-
-/**
- * Formats a record as SafeHtml.
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {!goog.html.SafeHtml} The formatted string as SafeHtml.
- */
-goog.debug.Formatter.prototype.formatRecordAsHtml = goog.abstractMethod;
-
-
-/**
- * Sets the start time provider. By default, this is the default instance
- * but can be changed.
- * @param {goog.debug.RelativeTimeProvider} provider The provider to use.
- */
-goog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {
- this.startTimeProvider_ = provider;
-};
-
-
-/**
- * Returns the start time provider. By default, this is the default instance
- * but can be changed.
- * @return {goog.debug.RelativeTimeProvider} The start time provider.
- */
-goog.debug.Formatter.prototype.getStartTimeProvider = function() {
- return this.startTimeProvider_;
-};
-
-
-/**
- * Resets the start relative time.
- */
-goog.debug.Formatter.prototype.resetRelativeTimeStart = function() {
- this.startTimeProvider_.reset();
-};
-
-
-/**
- * Returns a string for the time/date of the LogRecord.
- * @param {goog.debug.LogRecord} logRecord The record to get a time stamp for.
- * @return {string} A string representation of the time/date of the LogRecord.
- * @private
- */
-goog.debug.Formatter.getDateTimeStamp_ = function(logRecord) {
- var time = new Date(logRecord.getMillis());
- return goog.debug.Formatter.getTwoDigitString_((time.getFullYear() - 2000)) +
- goog.debug.Formatter.getTwoDigitString_((time.getMonth() + 1)) +
- goog.debug.Formatter.getTwoDigitString_(time.getDate()) + ' ' +
- goog.debug.Formatter.getTwoDigitString_(time.getHours()) + ':' +
- goog.debug.Formatter.getTwoDigitString_(time.getMinutes()) + ':' +
- goog.debug.Formatter.getTwoDigitString_(time.getSeconds()) + '.' +
- goog.debug.Formatter.getTwoDigitString_(
- Math.floor(time.getMilliseconds() / 10));
-};
-
-
-/**
- * Returns the number as a two-digit string, meaning it prepends a 0 if the
- * number if less than 10.
- * @param {number} n The number to format.
- * @return {string} A two-digit string representation of {@code n}.
- * @private
- */
-goog.debug.Formatter.getTwoDigitString_ = function(n) {
- if (n < 10) {
- return '0' + n;
- }
- return String(n);
-};
-
-
-/**
- * Returns a string for the number of seconds relative to the start time.
- * Prepads with spaces so that anything less than 1000 seconds takes up the
- * same number of characters for better formatting.
- * @param {goog.debug.LogRecord} logRecord The log to compare time to.
- * @param {number} relativeTimeStart The start time to compare to.
- * @return {string} The number of seconds of the LogRecord relative to the
- * start time.
- * @private
- */
-goog.debug.Formatter.getRelativeTime_ = function(logRecord,
- relativeTimeStart) {
- var ms = logRecord.getMillis() - relativeTimeStart;
- var sec = ms / 1000;
- var str = sec.toFixed(3);
-
- var spacesToPrepend = 0;
- if (sec < 1) {
- spacesToPrepend = 2;
- } else {
- while (sec < 100) {
- spacesToPrepend++;
- sec *= 10;
- }
- }
- while (spacesToPrepend-- > 0) {
- str = ' ' + str;
- }
- return str;
-};
-
-
-
-/**
- * Formatter that returns formatted html. See formatRecord for the classes
- * it uses for various types of formatted output.
- *
- * @param {string=} opt_prefix The prefix to place before text records.
- * @constructor
- * @extends {goog.debug.Formatter}
- */
-goog.debug.HtmlFormatter = function(opt_prefix) {
- goog.debug.Formatter.call(this, opt_prefix);
-};
-goog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);
-
-
-/**
- * Whether to show the logger exception text
- * @type {boolean}
- * @override
- */
-goog.debug.HtmlFormatter.prototype.showExceptionText = true;
-
-
-/**
- * Formats a record
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {string} The formatted string as html.
- * @override
- */
-goog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {
- if (!logRecord) {
- return '';
- }
- // OK not to use goog.html.SafeHtml.unwrap() here.
- return this.formatRecordAsHtml(logRecord).getTypedStringValue();
-};
-
-
-/**
- * Formats a record.
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {!goog.html.SafeHtml} The formatted string as SafeHtml.
- * @override
- */
-goog.debug.HtmlFormatter.prototype.formatRecordAsHtml = function(logRecord) {
- if (!logRecord) {
- return goog.html.SafeHtml.EMPTY;
- }
-
- var className;
- switch (logRecord.getLevel().value) {
- case goog.debug.Logger.Level.SHOUT.value:
- className = 'dbg-sh';
- break;
- case goog.debug.Logger.Level.SEVERE.value:
- className = 'dbg-sev';
- break;
- case goog.debug.Logger.Level.WARNING.value:
- className = 'dbg-w';
- break;
- case goog.debug.Logger.Level.INFO.value:
- className = 'dbg-i';
- break;
- case goog.debug.Logger.Level.FINE.value:
- default:
- className = 'dbg-f';
- break;
- }
-
- // HTML for user defined prefix, time, logger name, and severity.
- var sb = [];
- sb.push(this.prefix_, ' ');
- if (this.showAbsoluteTime) {
- sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
- }
- if (this.showRelativeTime) {
- sb.push('[',
- goog.debug.Formatter.getRelativeTime_(
- logRecord, this.startTimeProvider_.get()),
- 's] ');
- }
- if (this.showLoggerName) {
- sb.push('[', logRecord.getLoggerName(), '] ');
- }
- if (this.showSeverityLevel) {
- sb.push('[', logRecord.getLevel().name, '] ');
- }
- var fullPrefixHtml =
- goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(sb.join(''));
-
- // HTML for exception text and log record.
- var exceptionHtml = goog.html.SafeHtml.EMPTY;
- if (this.showExceptionText && logRecord.getException()) {
- exceptionHtml = goog.html.SafeHtml.concat(
- goog.html.SafeHtml.create('br'),
- goog.debug.exposeExceptionAsHtml(logRecord.getException()));
- }
- var logRecordHtml = goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- logRecord.getMessage());
- var recordAndExceptionHtml = goog.html.SafeHtml.create(
- 'span',
- {'class': className},
- goog.html.SafeHtml.concat(logRecordHtml, exceptionHtml));
-
-
- // Combine both pieces of HTML and, if needed, append a final newline.
- var html;
- if (this.appendNewline) {
- html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml,
- goog.html.SafeHtml.create('br'));
- } else {
- html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml);
- }
- return html;
-};
-
-
-
-/**
- * Formatter that returns formatted plain text
+ * @fileoverview Provides a function to schedule running a function as soon
+ * as possible after the current JS execution stops and yields to the event
+ * loop.
*
- * @param {string=} opt_prefix The prefix to place before text records.
- * @constructor
- * @extends {goog.debug.Formatter}
- * @final
*/
-goog.debug.TextFormatter = function(opt_prefix) {
- goog.debug.Formatter.call(this, opt_prefix);
-};
-goog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);
+goog.provide('goog.async.nextTick');
+goog.provide('goog.async.throwException');
-/**
- * Formats a record as text
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {string} The formatted string.
- * @override
- */
-goog.debug.TextFormatter.prototype.formatRecord = function(logRecord) {
- var sb = [];
- sb.push(this.prefix_, ' ');
- if (this.showAbsoluteTime) {
- sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
- }
- if (this.showRelativeTime) {
- sb.push('[', goog.debug.Formatter.getRelativeTime_(logRecord,
- this.startTimeProvider_.get()), 's] ');
- }
-
- if (this.showLoggerName) {
- sb.push('[', logRecord.getLoggerName(), '] ');
- }
- if (this.showSeverityLevel) {
- sb.push('[', logRecord.getLevel().name, '] ');
- }
- sb.push(logRecord.getMessage());
- if (this.showExceptionText) {
- var exception = logRecord.getException();
- if (exception) {
- var exceptionText = exception instanceof Error ?
- exception.message :
- exception.toString();
- sb.push('\n', exceptionText);
- }
- }
- if (this.appendNewline) {
- sb.push('\n');
- }
- return sb.join('');
-};
+goog.require('goog.debug.entryPointRegistry');
+goog.require('goog.dom.TagName');
+goog.require('goog.functions');
+goog.require('goog.labs.userAgent.browser');
+goog.require('goog.labs.userAgent.engine');
/**
- * Formats a record as text
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {!goog.html.SafeHtml} The formatted string as SafeHtml. This is
- * just an HTML-escaped version of the text obtained from formatRecord().
- * @override
+ * Throw an item without interrupting the current execution context. For
+ * example, if processing a group of items in a loop, sometimes it is useful
+ * to report an error while still allowing the rest of the batch to be
+ * processed.
+ * @param {*} exception
*/
-goog.debug.TextFormatter.prototype.formatRecordAsHtml = function(logRecord) {
- return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- goog.debug.TextFormatter.prototype.formatRecord(logRecord));
+goog.async.throwException = function(exception) {
+ // Each throw needs to be in its own context.
+ goog.global.setTimeout(function() { throw exception; }, 0);
};
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
/**
- * @fileoverview Simple logger that logs to the window console if available.
+ * Fires the provided callbacks as soon as possible after the current JS
+ * execution context. setTimeout(…, 0) takes at least 4ms when called from
+ * within another setTimeout(…, 0) for legacy reasons.
*
- * Has an autoInstall option which can be put into initialization code, which
- * will start logging if "Debug=true" is in document.location.href
+ * This will not schedule the callback as a microtask (i.e. a task that can
+ * preempt user input or networking callbacks). It is meant to emulate what
+ * setTimeout(_, 0) would do if it were not throttled. If you desire microtask
+ * behavior, use {@see goog.Promise} instead.
*
+ * @param {function(this:SCOPE)} callback Callback function to fire as soon as
+ * possible.
+ * @param {SCOPE=} opt_context Object in whose scope to call the listener.
+ * @param {boolean=} opt_useSetImmediate Avoid the IE workaround that
+ * ensures correctness at the cost of speed. See comments for details.
+ * @template SCOPE
*/
-
-goog.provide('goog.debug.Console');
-
-goog.require('goog.debug.LogManager');
-goog.require('goog.debug.Logger');
-goog.require('goog.debug.TextFormatter');
-
-
-
-/**
- * Create and install a log handler that logs to window.console if available
- * @constructor
- */
-goog.debug.Console = function() {
- this.publishHandler_ = goog.bind(this.addLogRecord, this);
-
- /**
- * Formatter for formatted output.
- * @type {!goog.debug.TextFormatter}
- * @private
- */
- this.formatter_ = new goog.debug.TextFormatter();
- this.formatter_.showAbsoluteTime = false;
- this.formatter_.showExceptionText = false;
- // The console logging methods automatically append a newline.
- this.formatter_.appendNewline = false;
-
- this.isCapturing_ = false;
- this.logBuffer_ = '';
-
- /**
- * Loggers that we shouldn't output.
- * @type {!Object<boolean>}
- * @private
- */
- this.filteredLoggers_ = {};
-};
-
-
-/**
- * Returns the text formatter used by this console
- * @return {!goog.debug.TextFormatter} The text formatter.
- */
-goog.debug.Console.prototype.getFormatter = function() {
- return this.formatter_;
-};
-
-
-/**
- * Sets whether we are currently capturing logger output.
- * @param {boolean} capturing Whether to capture logger output.
- */
-goog.debug.Console.prototype.setCapturing = function(capturing) {
- if (capturing == this.isCapturing_) {
- return;
- }
-
- // attach or detach handler from the root logger
- var rootLogger = goog.debug.LogManager.getRoot();
- if (capturing) {
- rootLogger.addHandler(this.publishHandler_);
- } else {
- rootLogger.removeHandler(this.publishHandler_);
- this.logBuffer = '';
+goog.async.nextTick = function(callback, opt_context, opt_useSetImmediate) {
+ var cb = callback;
+ if (opt_context) {
+ cb = goog.bind(callback, opt_context);
}
- this.isCapturing_ = capturing;
-};
-
-
-/**
- * Adds a log record.
- * @param {goog.debug.LogRecord} logRecord The log entry.
- */
-goog.debug.Console.prototype.addLogRecord = function(logRecord) {
-
- // Check to see if the log record is filtered or not.
- if (this.filteredLoggers_[logRecord.getLoggerName()]) {
+ cb = goog.async.nextTick.wrapCallback_(cb);
+ // Note we do allow callers to also request setImmediate if they are willing
+ // to accept the possible tradeoffs of incorrectness in exchange for speed.
+ // The IE fallback of readystate change is much slower. See useSetImmediate_
+ // for details.
+ if (goog.isFunction(goog.global.setImmediate) &&
+ (opt_useSetImmediate || goog.async.nextTick.useSetImmediate_())) {
+ goog.global.setImmediate(cb);
return;
}
- var record = this.formatter_.formatRecord(logRecord);
- var console = goog.debug.Console.console_;
- if (console) {
- switch (logRecord.getLevel()) {
- case goog.debug.Logger.Level.SHOUT:
- goog.debug.Console.logToConsole_(console, 'info', record);
- break;
- case goog.debug.Logger.Level.SEVERE:
- goog.debug.Console.logToConsole_(console, 'error', record);
- break;
- case goog.debug.Logger.Level.WARNING:
- goog.debug.Console.logToConsole_(console, 'warn', record);
- break;
- default:
- goog.debug.Console.logToConsole_(console, 'debug', record);
- break;
- }
- } else {
- this.logBuffer_ += record;
- }
-};
-
-
-/**
- * Adds a logger name to be filtered.
- * @param {string} loggerName the logger name to add.
- */
-goog.debug.Console.prototype.addFilter = function(loggerName) {
- this.filteredLoggers_[loggerName] = true;
-};
-
-
-/**
- * Removes a logger name to be filtered.
- * @param {string} loggerName the logger name to remove.
- */
-goog.debug.Console.prototype.removeFilter = function(loggerName) {
- delete this.filteredLoggers_[loggerName];
-};
-
-
-/**
- * Global console logger instance
- * @type {goog.debug.Console}
- */
-goog.debug.Console.instance = null;
-
-
-/**
- * The console to which to log. This is a property so it can be mocked out in
- * this unit test for goog.debug.Console. Using goog.global, as console might be
- * used in window-less contexts.
- * @type {Object}
- * @private
- */
-goog.debug.Console.console_ = goog.global['console'];
-
-
-/**
- * Sets the console to which to log.
- * @param {!Object} console The console to which to log.
- */
-goog.debug.Console.setConsole = function(console) {
- goog.debug.Console.console_ = console;
-};
-
-
-/**
- * Install the console and start capturing if "Debug=true" is in the page URL
- */
-goog.debug.Console.autoInstall = function() {
- if (!goog.debug.Console.instance) {
- goog.debug.Console.instance = new goog.debug.Console();
- }
-
- if (goog.global.location &&
- goog.global.location.href.indexOf('Debug=true') != -1) {
- goog.debug.Console.instance.setCapturing(true);
- }
-};
-
-
-/**
- * Show an alert with all of the captured debug information.
- * Information is only captured if console is not available
- */
-goog.debug.Console.show = function() {
- alert(goog.debug.Console.instance.logBuffer_);
-};
-
-
-/**
- * Logs the record to the console using the given function. If the function is
- * not available on the console object, the log function is used instead.
- * @param {!Object} console The console object.
- * @param {string} fnName The name of the function to use.
- * @param {string} record The record to log.
- * @private
- */
-goog.debug.Console.logToConsole_ = function(console, fnName, record) {
- if (console[fnName]) {
- console[fnName](record);
- } else {
- console.log(record);
+ // Look for and cache the custom fallback version of setImmediate.
+ if (!goog.async.nextTick.setImmediate_) {
+ goog.async.nextTick.setImmediate_ =
+ goog.async.nextTick.getSetImmediateEmulator_();
}
+ goog.async.nextTick.setImmediate_(cb);
};
-// Copyright 2007 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Utility class that monitors viewport size changes.
- *
- * @author attila@google.com (Attila Bodis)
- * @see ../demos/viewportsizemonitor.html
- */
-
-goog.provide('goog.dom.ViewportSizeMonitor');
-
-goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
-goog.require('goog.math.Size');
-
-
/**
- * This class can be used to monitor changes in the viewport size. Instances
- * dispatch a {@link goog.events.EventType.RESIZE} event when the viewport size
- * changes. Handlers can call {@link goog.dom.ViewportSizeMonitor#getSize} to
- * get the new viewport size.
- *
- * Use this class if you want to execute resize/reflow logic each time the
- * user resizes the browser window. This class is guaranteed to only dispatch
- * {@code RESIZE} events when the pixel dimensions of the viewport change.
- * (Internet Explorer fires resize events if any element on the page is resized,
- * even if the viewport dimensions are unchanged, which can lead to infinite
- * resize loops.)
+ * Returns whether should use setImmediate implementation currently on window.
*
- * Example usage:
- * <pre>
- * var vsm = new goog.dom.ViewportSizeMonitor();
- * goog.events.listen(vsm, goog.events.EventType.RESIZE, function(e) {
- * alert('Viewport size changed to ' + vsm.getSize());
- * });
- * </pre>
- *
- * Manually verified on IE6, IE7, FF2, Opera 11, Safari 4 and Chrome.
+ * window.setImmediate was introduced and currently only supported by IE10+,
+ * but due to a bug in the implementation it is not guaranteed that
+ * setImmediate is faster than setTimeout nor that setImmediate N is before
+ * setImmediate N+1. That is why we do not use the native version if
+ * available. We do, however, call setImmediate if it is a non-native function
+ * because that indicates that it has been replaced by goog.testing.MockClock
+ * which we do want to support.
+ * See
+ * http://connect.microsoft.com/IE/feedback/details/801823/setimmediate-and-messagechannel-are-broken-in-ie10
*
- * @param {Window=} opt_window The window to monitor; defaults to the window in
- * which this code is executing.
- * @constructor
- * @extends {goog.events.EventTarget}
- */
-goog.dom.ViewportSizeMonitor = function(opt_window) {
- goog.dom.ViewportSizeMonitor.base(this, 'constructor');
-
- /**
- * The window to monitor. Defaults to the window in which the code is running.
- * @private {Window}
- */
- this.window_ = opt_window || window;
-
- /**
- * Event listener key for window the window resize handler, as returned by
- * {@link goog.events.listen}.
- * @private {goog.events.Key}
- */
- this.listenerKey_ = goog.events.listen(this.window_,
- goog.events.EventType.RESIZE, this.handleResize_, false, this);
-
- /**
- * The most recently recorded size of the viewport, in pixels.
- * @private {goog.math.Size}
- */
- this.size_ = goog.dom.getViewportSize(this.window_);
-};
-goog.inherits(goog.dom.ViewportSizeMonitor, goog.events.EventTarget);
-
-
-/**
- * Returns a viewport size monitor for the given window. A new one is created
- * if it doesn't exist already. This prevents the unnecessary creation of
- * multiple spooling monitors for a window.
- * @param {Window=} opt_window The window to monitor; defaults to the window in
- * which this code is executing.
- * @return {!goog.dom.ViewportSizeMonitor} Monitor for the given window.
- */
-goog.dom.ViewportSizeMonitor.getInstanceForWindow = function(opt_window) {
- var currentWindow = opt_window || window;
- var uid = goog.getUid(currentWindow);
-
- return goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] =
- goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] ||
- new goog.dom.ViewportSizeMonitor(currentWindow);
-};
-
-
-/**
- * Removes and disposes a viewport size monitor for the given window if one
- * exists.
- * @param {Window=} opt_window The window whose monitor should be removed;
- * defaults to the window in which this code is executing.
- */
-goog.dom.ViewportSizeMonitor.removeInstanceForWindow = function(opt_window) {
- var uid = goog.getUid(opt_window || window);
-
- goog.dispose(goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid]);
- delete goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid];
-};
-
-
-/**
- * Map of window hash code to viewport size monitor for that window, if
- * created.
- * @type {Object<number,goog.dom.ViewportSizeMonitor>}
+ * @return {boolean} Whether to use the implementation of setImmediate defined
+ * on Window.
* @private
*/
-goog.dom.ViewportSizeMonitor.windowInstanceMap_ = {};
-
-
-/**
- * Returns the most recently recorded size of the viewport, in pixels. May
- * return null if no window resize event has been handled yet.
- * @return {goog.math.Size} The viewport dimensions, in pixels.
- */
-goog.dom.ViewportSizeMonitor.prototype.getSize = function() {
- // Return a clone instead of the original to preserve encapsulation.
- return this.size_ ? this.size_.clone() : null;
-};
-
-
-/** @override */
-goog.dom.ViewportSizeMonitor.prototype.disposeInternal = function() {
- goog.dom.ViewportSizeMonitor.superClass_.disposeInternal.call(this);
-
- if (this.listenerKey_) {
- goog.events.unlistenByKey(this.listenerKey_);
- this.listenerKey_ = null;
- }
-
- this.window_ = null;
- this.size_ = null;
-};
-
-
-/**
- * Handles window resize events by measuring the dimensions of the
- * viewport and dispatching a {@link goog.events.EventType.RESIZE} event if the
- * current dimensions are different from the previous ones.
- * @param {goog.events.Event} event The window resize event to handle.
- * @private
- */
-goog.dom.ViewportSizeMonitor.prototype.handleResize_ = function(event) {
- var size = goog.dom.getViewportSize(this.window_);
- if (!goog.math.Size.equals(size, this.size_)) {
- this.size_ = size;
- this.dispatchEvent(goog.events.EventType.RESIZE);
- }
-};
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Constant declarations for common key codes.
- *
- * @author eae@google.com (Emil A Eklund)
- * @see ../demos/keyhandler.html
- */
-
-goog.provide('goog.events.KeyCodes');
-
-goog.require('goog.userAgent');
-
-goog.forwardDeclare('goog.events.BrowserEvent');
-
-
-/**
- * Key codes for common characters.
- *
- * This list is not localized and therefore some of the key codes are not
- * correct for non US keyboard layouts. See comments below.
- *
- * @enum {number}
- */
-goog.events.KeyCodes = {
- WIN_KEY_FF_LINUX: 0,
- MAC_ENTER: 3,
- BACKSPACE: 8,
- TAB: 9,
- NUM_CENTER: 12, // NUMLOCK on FF/Safari Mac
- ENTER: 13,
- SHIFT: 16,
- CTRL: 17,
- ALT: 18,
- PAUSE: 19,
- CAPS_LOCK: 20,
- ESC: 27,
- SPACE: 32,
- PAGE_UP: 33, // also NUM_NORTH_EAST
- PAGE_DOWN: 34, // also NUM_SOUTH_EAST
- END: 35, // also NUM_SOUTH_WEST
- HOME: 36, // also NUM_NORTH_WEST
- LEFT: 37, // also NUM_WEST
- UP: 38, // also NUM_NORTH
- RIGHT: 39, // also NUM_EAST
- DOWN: 40, // also NUM_SOUTH
- PLUS_SIGN: 43, // NOT numpad plus
- PRINT_SCREEN: 44,
- INSERT: 45, // also NUM_INSERT
- DELETE: 46, // also NUM_DELETE
- ZERO: 48,
- ONE: 49,
- TWO: 50,
- THREE: 51,
- FOUR: 52,
- FIVE: 53,
- SIX: 54,
- SEVEN: 55,
- EIGHT: 56,
- NINE: 57,
- FF_SEMICOLON: 59, // Firefox (Gecko) fires this for semicolon instead of 186
- FF_EQUALS: 61, // Firefox (Gecko) fires this for equals instead of 187
- FF_DASH: 173, // Firefox (Gecko) fires this for dash instead of 189
- QUESTION_MARK: 63, // needs localization
- AT_SIGN: 64,
- A: 65,
- B: 66,
- C: 67,
- D: 68,
- E: 69,
- F: 70,
- G: 71,
- H: 72,
- I: 73,
- J: 74,
- K: 75,
- L: 76,
- M: 77,
- N: 78,
- O: 79,
- P: 80,
- Q: 81,
- R: 82,
- S: 83,
- T: 84,
- U: 85,
- V: 86,
- W: 87,
- X: 88,
- Y: 89,
- Z: 90,
- META: 91, // WIN_KEY_LEFT
- WIN_KEY_RIGHT: 92,
- CONTEXT_MENU: 93,
- NUM_ZERO: 96,
- NUM_ONE: 97,
- NUM_TWO: 98,
- NUM_THREE: 99,
- NUM_FOUR: 100,
- NUM_FIVE: 101,
- NUM_SIX: 102,
- NUM_SEVEN: 103,
- NUM_EIGHT: 104,
- NUM_NINE: 105,
- NUM_MULTIPLY: 106,
- NUM_PLUS: 107,
- NUM_MINUS: 109,
- NUM_PERIOD: 110,
- NUM_DIVISION: 111,
- F1: 112,
- F2: 113,
- F3: 114,
- F4: 115,
- F5: 116,
- F6: 117,
- F7: 118,
- F8: 119,
- F9: 120,
- F10: 121,
- F11: 122,
- F12: 123,
- NUMLOCK: 144,
- SCROLL_LOCK: 145,
-
- // OS-specific media keys like volume controls and browser controls.
- FIRST_MEDIA_KEY: 166,
- LAST_MEDIA_KEY: 183,
-
- SEMICOLON: 186, // needs localization
- DASH: 189, // needs localization
- EQUALS: 187, // needs localization
- COMMA: 188, // needs localization
- PERIOD: 190, // needs localization
- SLASH: 191, // needs localization
- APOSTROPHE: 192, // needs localization
- TILDE: 192, // needs localization
- SINGLE_QUOTE: 222, // needs localization
- OPEN_SQUARE_BRACKET: 219, // needs localization
- BACKSLASH: 220, // needs localization
- CLOSE_SQUARE_BRACKET: 221, // needs localization
- WIN_KEY: 224,
- MAC_FF_META: 224, // Firefox (Gecko) fires this for the meta key instead of 91
- MAC_WK_CMD_LEFT: 91, // WebKit Left Command key fired, same as META
- MAC_WK_CMD_RIGHT: 93, // WebKit Right Command key fired, different from META
- WIN_IME: 229,
-
- // "Reserved for future use". Some programs (e.g. the SlingPlayer 2.4 ActiveX
- // control) fire this as a hacky way to disable screensavers.
- VK_NONAME: 252,
-
- // We've seen users whose machines fire this keycode at regular one
- // second intervals. The common thread among these users is that
- // they're all using Dell Inspiron laptops, so we suspect that this
- // indicates a hardware/bios problem.
- // http://en.community.dell.com/support-forums/laptop/f/3518/p/19285957/19523128.aspx
- PHANTOM: 255
-};
-
-
-/**
- * Returns true if the event contains a text modifying key.
- * @param {goog.events.BrowserEvent} e A key event.
- * @return {boolean} Whether it's a text modifying key.
- */
-goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) {
- if (e.altKey && !e.ctrlKey ||
- e.metaKey ||
- // Function keys don't generate text
- e.keyCode >= goog.events.KeyCodes.F1 &&
- e.keyCode <= goog.events.KeyCodes.F12) {
- return false;
- }
-
- // The following keys are quite harmless, even in combination with
- // CTRL, ALT or SHIFT.
- switch (e.keyCode) {
- case goog.events.KeyCodes.ALT:
- case goog.events.KeyCodes.CAPS_LOCK:
- case goog.events.KeyCodes.CONTEXT_MENU:
- case goog.events.KeyCodes.CTRL:
- case goog.events.KeyCodes.DOWN:
- case goog.events.KeyCodes.END:
- case goog.events.KeyCodes.ESC:
- case goog.events.KeyCodes.HOME:
- case goog.events.KeyCodes.INSERT:
- case goog.events.KeyCodes.LEFT:
- case goog.events.KeyCodes.MAC_FF_META:
- case goog.events.KeyCodes.META:
- case goog.events.KeyCodes.NUMLOCK:
- case goog.events.KeyCodes.NUM_CENTER:
- case goog.events.KeyCodes.PAGE_DOWN:
- case goog.events.KeyCodes.PAGE_UP:
- case goog.events.KeyCodes.PAUSE:
- case goog.events.KeyCodes.PHANTOM:
- case goog.events.KeyCodes.PRINT_SCREEN:
- case goog.events.KeyCodes.RIGHT:
- case goog.events.KeyCodes.SCROLL_LOCK:
- case goog.events.KeyCodes.SHIFT:
- case goog.events.KeyCodes.UP:
- case goog.events.KeyCodes.VK_NONAME:
- case goog.events.KeyCodes.WIN_KEY:
- case goog.events.KeyCodes.WIN_KEY_RIGHT:
- return false;
- case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
- return !goog.userAgent.GECKO;
- default:
- return e.keyCode < goog.events.KeyCodes.FIRST_MEDIA_KEY ||
- e.keyCode > goog.events.KeyCodes.LAST_MEDIA_KEY;
- }
-};
-
-
-/**
- * Returns true if the key fires a keypress event in the current browser.
- *
- * Accoridng to MSDN [1] IE only fires keypress events for the following keys:
- * - Letters: A - Z (uppercase and lowercase)
- * - Numerals: 0 - 9
- * - Symbols: ! @ # $ % ^ & * ( ) _ - + = < [ ] { } , . / ? \ | ' ` " ~
- * - System: ESC, SPACEBAR, ENTER
- *
- * That's not entirely correct though, for instance there's no distinction
- * between upper and lower case letters.
- *
- * [1] http://msdn2.microsoft.com/en-us/library/ms536939(VS.85).aspx)
- *
- * Safari is similar to IE, but does not fire keypress for ESC.
- *
- * Additionally, IE6 does not fire keydown or keypress events for letters when
- * the control or alt keys are held down and the shift key is not. IE7 does
- * fire keydown in these cases, though, but not keypress.
- *
- * @param {number} keyCode A key code.
- * @param {number=} opt_heldKeyCode Key code of a currently-held key.
- * @param {boolean=} opt_shiftKey Whether the shift key is held down.
- * @param {boolean=} opt_ctrlKey Whether the control key is held down.
- * @param {boolean=} opt_altKey Whether the alt key is held down.
- * @return {boolean} Whether it's a key that fires a keypress event.
- */
-goog.events.KeyCodes.firesKeyPressEvent = function(keyCode, opt_heldKeyCode,
- opt_shiftKey, opt_ctrlKey, opt_altKey) {
- if (!goog.userAgent.IE && !goog.userAgent.EDGE &&
- !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'))) {
- return true;
- }
-
- if (goog.userAgent.MAC && opt_altKey) {
- return goog.events.KeyCodes.isCharacterKey(keyCode);
- }
-
- // Alt but not AltGr which is represented as Alt+Ctrl.
- if (opt_altKey && !opt_ctrlKey) {
- return false;
- }
-
- // Saves Ctrl or Alt + key for IE and WebKit 525+, which won't fire keypress.
- // Non-IE browsers and WebKit prior to 525 won't get this far so no need to
- // check the user agent.
- if (goog.isNumber(opt_heldKeyCode)) {
- opt_heldKeyCode = goog.events.KeyCodes.normalizeKeyCode(opt_heldKeyCode);
- }
- if (!opt_shiftKey &&
- (opt_heldKeyCode == goog.events.KeyCodes.CTRL ||
- opt_heldKeyCode == goog.events.KeyCodes.ALT ||
- goog.userAgent.MAC &&
- opt_heldKeyCode == goog.events.KeyCodes.META)) {
- return false;
- }
-
- // Some keys with Ctrl/Shift do not issue keypress in WEBKIT.
- if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) &&
- opt_ctrlKey && opt_shiftKey) {
- switch (keyCode) {
- case goog.events.KeyCodes.BACKSLASH:
- case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
- case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
- case goog.events.KeyCodes.TILDE:
- case goog.events.KeyCodes.SEMICOLON:
- case goog.events.KeyCodes.DASH:
- case goog.events.KeyCodes.EQUALS:
- case goog.events.KeyCodes.COMMA:
- case goog.events.KeyCodes.PERIOD:
- case goog.events.KeyCodes.SLASH:
- case goog.events.KeyCodes.APOSTROPHE:
- case goog.events.KeyCodes.SINGLE_QUOTE:
- return false;
- }
- }
-
- // When Ctrl+<somekey> is held in IE, it only fires a keypress once, but it
- // continues to fire keydown events as the event repeats.
- if (goog.userAgent.IE && opt_ctrlKey && opt_heldKeyCode == keyCode) {
- return false;
- }
-
- switch (keyCode) {
- case goog.events.KeyCodes.ENTER:
- return true;
- case goog.events.KeyCodes.ESC:
- return !(goog.userAgent.WEBKIT || goog.userAgent.EDGE);
- }
-
- return goog.events.KeyCodes.isCharacterKey(keyCode);
-};
-
-
-/**
- * Returns true if the key produces a character.
- * This does not cover characters on non-US keyboards (Russian, Hebrew, etc.).
- *
- * @param {number} keyCode A key code.
- * @return {boolean} Whether it's a character key.
- */
-goog.events.KeyCodes.isCharacterKey = function(keyCode) {
- if (keyCode >= goog.events.KeyCodes.ZERO &&
- keyCode <= goog.events.KeyCodes.NINE) {
- return true;
- }
-
- if (keyCode >= goog.events.KeyCodes.NUM_ZERO &&
- keyCode <= goog.events.KeyCodes.NUM_MULTIPLY) {
- return true;
- }
-
- if (keyCode >= goog.events.KeyCodes.A &&
- keyCode <= goog.events.KeyCodes.Z) {
+goog.async.nextTick.useSetImmediate_ = function() {
+ // Not a browser environment.
+ if (!goog.global.Window || !goog.global.Window.prototype) {
return true;
}
- // Safari sends zero key code for non-latin characters.
- if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && keyCode == 0) {
+ // MS Edge has window.setImmediate natively, but it's not on Window.prototype.
+ // Also, there's no clean way to detect if the goog.global.setImmediate has
+ // been replaced by mockClock as its replacement also shows up as "[native
+ // code]" when using toString. Therefore, just always use
+ // goog.global.setImmediate for Edge. It's unclear if it suffers the same
+ // issues as IE10/11, but based on
+ // https://dev.modern.ie/testdrive/demos/setimmediatesorting/
+ // it seems they've been working to ensure it's WAI.
+ if (goog.labs.userAgent.browser.isEdge() ||
+ goog.global.Window.prototype.setImmediate != goog.global.setImmediate) {
+ // Something redefined setImmediate in which case we decide to use it (This
+ // is so that we use the mockClock setImmediate).
return true;
}
- switch (keyCode) {
- case goog.events.KeyCodes.SPACE:
- case goog.events.KeyCodes.PLUS_SIGN:
- case goog.events.KeyCodes.QUESTION_MARK:
- case goog.events.KeyCodes.AT_SIGN:
- case goog.events.KeyCodes.NUM_PLUS:
- case goog.events.KeyCodes.NUM_MINUS:
- case goog.events.KeyCodes.NUM_PERIOD:
- case goog.events.KeyCodes.NUM_DIVISION:
- case goog.events.KeyCodes.SEMICOLON:
- case goog.events.KeyCodes.FF_SEMICOLON:
- case goog.events.KeyCodes.DASH:
- case goog.events.KeyCodes.EQUALS:
- case goog.events.KeyCodes.FF_EQUALS:
- case goog.events.KeyCodes.COMMA:
- case goog.events.KeyCodes.PERIOD:
- case goog.events.KeyCodes.SLASH:
- case goog.events.KeyCodes.APOSTROPHE:
- case goog.events.KeyCodes.SINGLE_QUOTE:
- case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
- case goog.events.KeyCodes.BACKSLASH:
- case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
- return true;
- default:
- return false;
- }
-};
-
-
-/**
- * Normalizes key codes from OS/Browser-specific value to the general one.
- * @param {number} keyCode The native key code.
- * @return {number} The normalized key code.
- */
-goog.events.KeyCodes.normalizeKeyCode = function(keyCode) {
- if (goog.userAgent.GECKO) {
- return goog.events.KeyCodes.normalizeGeckoKeyCode(keyCode);
- } else if (goog.userAgent.MAC && goog.userAgent.WEBKIT) {
- return goog.events.KeyCodes.normalizeMacWebKitKeyCode(keyCode);
- } else {
- return keyCode;
- }
-};
-
-
-/**
- * Normalizes key codes from their Gecko-specific value to the general one.
- * @param {number} keyCode The native key code.
- * @return {number} The normalized key code.
- */
-goog.events.KeyCodes.normalizeGeckoKeyCode = function(keyCode) {
- switch (keyCode) {
- case goog.events.KeyCodes.FF_EQUALS:
- return goog.events.KeyCodes.EQUALS;
- case goog.events.KeyCodes.FF_SEMICOLON:
- return goog.events.KeyCodes.SEMICOLON;
- case goog.events.KeyCodes.FF_DASH:
- return goog.events.KeyCodes.DASH;
- case goog.events.KeyCodes.MAC_FF_META:
- return goog.events.KeyCodes.META;
- case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
- return goog.events.KeyCodes.WIN_KEY;
- default:
- return keyCode;
- }
-};
-
-
-/**
- * Normalizes key codes from their Mac WebKit-specific value to the general one.
- * @param {number} keyCode The native key code.
- * @return {number} The normalized key code.
- */
-goog.events.KeyCodes.normalizeMacWebKitKeyCode = function(keyCode) {
- switch (keyCode) {
- case goog.events.KeyCodes.MAC_WK_CMD_RIGHT: // 93
- return goog.events.KeyCodes.META; // 91
- default:
- return keyCode;
- }
-};
-
-// Copyright 2007 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview This file contains a class for working with keyboard events
- * that repeat consistently across browsers and platforms. It also unifies the
- * key code so that it is the same in all browsers and platforms.
- *
- * Different web browsers have very different keyboard event handling. Most
- * importantly is that only certain browsers repeat keydown events:
- * IE, Opera, FF/Win32, and Safari 3 repeat keydown events.
- * FF/Mac and Safari 2 do not.
- *
- * For the purposes of this code, "Safari 3" means WebKit 525+, when WebKit
- * decided that they should try to match IE's key handling behavior.
- * Safari 3.0.4, which shipped with Leopard (WebKit 523), has the
- * Safari 2 behavior.
- *
- * Firefox, Safari, Opera prevent on keypress
- *
- * IE prevents on keydown
- *
- * Firefox does not fire keypress for shift, ctrl, alt
- * Firefox does fire keydown for shift, ctrl, alt, meta
- * Firefox does not repeat keydown for shift, ctrl, alt, meta
- *
- * Firefox does not fire keypress for up and down in an input
- *
- * Opera fires keypress for shift, ctrl, alt, meta
- * Opera does not repeat keypress for shift, ctrl, alt, meta
- *
- * Safari 2 and 3 do not fire keypress for shift, ctrl, alt
- * Safari 2 does not fire keydown for shift, ctrl, alt
- * Safari 3 *does* fire keydown for shift, ctrl, alt
- *
- * IE provides the keycode for keyup/down events and the charcode (in the
- * keycode field) for keypress.
- *
- * Mozilla provides the keycode for keyup/down and the charcode for keypress
- * unless it's a non text modifying key in which case the keycode is provided.
- *
- * Safari 3 provides the keycode and charcode for all events.
- *
- * Opera provides the keycode for keyup/down event and either the charcode or
- * the keycode (in the keycode field) for keypress events.
- *
- * Firefox x11 doesn't fire keydown events if a another key is already held down
- * until the first key is released. This can cause a key event to be fired with
- * a keyCode for the first key and a charCode for the second key.
- *
- * Safari in keypress
- *
- * charCode keyCode which
- * ENTER: 13 13 13
- * F1: 63236 63236 63236
- * F8: 63243 63243 63243
- * ...
- * p: 112 112 112
- * P: 80 80 80
- *
- * Firefox, keypress:
- *
- * charCode keyCode which
- * ENTER: 0 13 13
- * F1: 0 112 0
- * F8: 0 119 0
- * ...
- * p: 112 0 112
- * P: 80 0 80
- *
- * Opera, Mac+Win32, keypress:
- *
- * charCode keyCode which
- * ENTER: undefined 13 13
- * F1: undefined 112 0
- * F8: undefined 119 0
- * ...
- * p: undefined 112 112
- * P: undefined 80 80
- *
- * IE7, keydown
- *
- * charCode keyCode which
- * ENTER: undefined 13 undefined
- * F1: undefined 112 undefined
- * F8: undefined 119 undefined
- * ...
- * p: undefined 80 undefined
- * P: undefined 80 undefined
- *
- * @author arv@google.com (Erik Arvidsson)
- * @author eae@google.com (Emil A Eklund)
- * @see ../demos/keyhandler.html
- */
-
-goog.provide('goog.events.KeyEvent');
-goog.provide('goog.events.KeyHandler');
-goog.provide('goog.events.KeyHandler.EventType');
-
-goog.require('goog.events');
-goog.require('goog.events.BrowserEvent');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
-goog.require('goog.events.KeyCodes');
-goog.require('goog.userAgent');
-
-
-
-/**
- * A wrapper around an element that you want to listen to keyboard events on.
- * @param {Element|Document=} opt_element The element or document to listen on.
- * @param {boolean=} opt_capture Whether to listen for browser events in
- * capture phase (defaults to false).
- * @constructor
- * @extends {goog.events.EventTarget}
- * @final
- */
-goog.events.KeyHandler = function(opt_element, opt_capture) {
- goog.events.EventTarget.call(this);
-
- if (opt_element) {
- this.attach(opt_element, opt_capture);
- }
+ return false;
};
-goog.inherits(goog.events.KeyHandler, goog.events.EventTarget);
-
-
-/**
- * This is the element that we will listen to the real keyboard events on.
- * @type {Element|Document|null}
- * @private
- */
-goog.events.KeyHandler.prototype.element_ = null;
-
-
-/**
- * The key for the key press listener.
- * @type {goog.events.Key}
- * @private
- */
-goog.events.KeyHandler.prototype.keyPressKey_ = null;
-
-
-/**
- * The key for the key down listener.
- * @type {goog.events.Key}
- * @private
- */
-goog.events.KeyHandler.prototype.keyDownKey_ = null;
-
-
-/**
- * The key for the key up listener.
- * @type {goog.events.Key}
- * @private
- */
-goog.events.KeyHandler.prototype.keyUpKey_ = null;
-
-
-/**
- * Used to detect keyboard repeat events.
- * @private
- * @type {number}
- */
-goog.events.KeyHandler.prototype.lastKey_ = -1;
-
-
-/**
- * Keycode recorded for key down events. As most browsers don't report the
- * keycode in the key press event we need to record it in the key down phase.
- * @private
- * @type {number}
- */
-goog.events.KeyHandler.prototype.keyCode_ = -1;
-
-
-/**
- * Alt key recorded for key down events. FF on Mac does not report the alt key
- * flag in the key press event, we need to record it in the key down phase.
- * @type {boolean}
- * @private
- */
-goog.events.KeyHandler.prototype.altKey_ = false;
-
-
-/**
- * Enum type for the events fired by the key handler
- * @enum {string}
- */
-goog.events.KeyHandler.EventType = {
- KEY: 'key'
-};
-
-
-/**
- * An enumeration of key codes that Safari 2 does incorrectly
- * @type {Object}
- * @private
- */
-goog.events.KeyHandler.safariKey_ = {
- '3': goog.events.KeyCodes.ENTER, // 13
- '12': goog.events.KeyCodes.NUMLOCK, // 144
- '63232': goog.events.KeyCodes.UP, // 38
- '63233': goog.events.KeyCodes.DOWN, // 40
- '63234': goog.events.KeyCodes.LEFT, // 37
- '63235': goog.events.KeyCodes.RIGHT, // 39
- '63236': goog.events.KeyCodes.F1, // 112
- '63237': goog.events.KeyCodes.F2, // 113
- '63238': goog.events.KeyCodes.F3, // 114
- '63239': goog.events.KeyCodes.F4, // 115
- '63240': goog.events.KeyCodes.F5, // 116
- '63241': goog.events.KeyCodes.F6, // 117
- '63242': goog.events.KeyCodes.F7, // 118
- '63243': goog.events.KeyCodes.F8, // 119
- '63244': goog.events.KeyCodes.F9, // 120
- '63245': goog.events.KeyCodes.F10, // 121
- '63246': goog.events.KeyCodes.F11, // 122
- '63247': goog.events.KeyCodes.F12, // 123
- '63248': goog.events.KeyCodes.PRINT_SCREEN, // 44
- '63272': goog.events.KeyCodes.DELETE, // 46
- '63273': goog.events.KeyCodes.HOME, // 36
- '63275': goog.events.KeyCodes.END, // 35
- '63276': goog.events.KeyCodes.PAGE_UP, // 33
- '63277': goog.events.KeyCodes.PAGE_DOWN, // 34
- '63289': goog.events.KeyCodes.NUMLOCK, // 144
- '63302': goog.events.KeyCodes.INSERT // 45
-};
-
-
-/**
- * An enumeration of key identifiers currently part of the W3C draft for DOM3
- * and their mappings to keyCodes.
- * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set
- * This is currently supported in Safari and should be platform independent.
- * @type {Object}
- * @private
- */
-goog.events.KeyHandler.keyIdentifier_ = {
- 'Up': goog.events.KeyCodes.UP, // 38
- 'Down': goog.events.KeyCodes.DOWN, // 40
- 'Left': goog.events.KeyCodes.LEFT, // 37
- 'Right': goog.events.KeyCodes.RIGHT, // 39
- 'Enter': goog.events.KeyCodes.ENTER, // 13
- 'F1': goog.events.KeyCodes.F1, // 112
- 'F2': goog.events.KeyCodes.F2, // 113
- 'F3': goog.events.KeyCodes.F3, // 114
- 'F4': goog.events.KeyCodes.F4, // 115
- 'F5': goog.events.KeyCodes.F5, // 116
- 'F6': goog.events.KeyCodes.F6, // 117
- 'F7': goog.events.KeyCodes.F7, // 118
- 'F8': goog.events.KeyCodes.F8, // 119
- 'F9': goog.events.KeyCodes.F9, // 120
- 'F10': goog.events.KeyCodes.F10, // 121
- 'F11': goog.events.KeyCodes.F11, // 122
- 'F12': goog.events.KeyCodes.F12, // 123
- 'U+007F': goog.events.KeyCodes.DELETE, // 46
- 'Home': goog.events.KeyCodes.HOME, // 36
- 'End': goog.events.KeyCodes.END, // 35
- 'PageUp': goog.events.KeyCodes.PAGE_UP, // 33
- 'PageDown': goog.events.KeyCodes.PAGE_DOWN, // 34
- 'Insert': goog.events.KeyCodes.INSERT // 45
-};
-
-
-/**
- * If true, the KeyEvent fires on keydown. Otherwise, it fires on keypress.
- *
- * @type {boolean}
- * @private
- */
-goog.events.KeyHandler.USES_KEYDOWN_ = goog.userAgent.IE ||
- goog.userAgent.EDGE ||
- goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525');
/**
- * If true, the alt key flag is saved during the key down and reused when
- * handling the key press. FF on Mac does not set the alt flag in the key press
- * event.
- * @type {boolean}
+ * Cache for the setImmediate implementation.
+ * @type {function(function())}
* @private
*/
-goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_ = goog.userAgent.MAC &&
- goog.userAgent.GECKO;
+goog.async.nextTick.setImmediate_;
/**
- * Records the keycode for browsers that only returns the keycode for key up/
- * down events. For browser/key combinations that doesn't trigger a key pressed
- * event it also fires the patched key event.
- * @param {goog.events.BrowserEvent} e The key down event.
+ * Determines the best possible implementation to run a function as soon as
+ * the JS event loop is idle.
+ * @return {function(function())} The "setImmediate" implementation.
* @private
*/
-goog.events.KeyHandler.prototype.handleKeyDown_ = function(e) {
- // Ctrl-Tab and Alt-Tab can cause the focus to be moved to another window
- // before we've caught a key-up event. If the last-key was one of these we
- // reset the state.
- if (goog.userAgent.WEBKIT || goog.userAgent.EDGE) {
- if (this.lastKey_ == goog.events.KeyCodes.CTRL && !e.ctrlKey ||
- this.lastKey_ == goog.events.KeyCodes.ALT && !e.altKey ||
- goog.userAgent.MAC &&
- this.lastKey_ == goog.events.KeyCodes.META && !e.metaKey) {
- this.resetState();
- }
- }
-
- if (this.lastKey_ == -1) {
- if (e.ctrlKey && e.keyCode != goog.events.KeyCodes.CTRL) {
- this.lastKey_ = goog.events.KeyCodes.CTRL;
- } else if (e.altKey && e.keyCode != goog.events.KeyCodes.ALT) {
- this.lastKey_ = goog.events.KeyCodes.ALT;
- } else if (e.metaKey && e.keyCode != goog.events.KeyCodes.META) {
- this.lastKey_ = goog.events.KeyCodes.META;
- }
- }
-
- if (goog.events.KeyHandler.USES_KEYDOWN_ &&
- !goog.events.KeyCodes.firesKeyPressEvent(e.keyCode,
- this.lastKey_, e.shiftKey, e.ctrlKey, e.altKey)) {
- this.handleEvent(e);
- } else {
- this.keyCode_ = goog.events.KeyCodes.normalizeKeyCode(e.keyCode);
- if (goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_) {
- this.altKey_ = e.altKey;
- }
+goog.async.nextTick.getSetImmediateEmulator_ = function() {
+ // Create a private message channel and use it to postMessage empty messages
+ // to ourselves.
+ var Channel = goog.global['MessageChannel'];
+ // If MessageChannel is not available and we are in a browser, implement
+ // an iframe based polyfill in browsers that have postMessage and
+ // document.addEventListener. The latter excludes IE8 because it has a
+ // synchronous postMessage implementation.
+ if (typeof Channel === 'undefined' && typeof window !== 'undefined' &&
+ window.postMessage && window.addEventListener &&
+ // Presto (The old pre-blink Opera engine) has problems with iframes
+ // and contentWindow.
+ !goog.labs.userAgent.engine.isPresto()) {
+ /** @constructor */
+ Channel = function() {
+ // Make an empty, invisible iframe.
+ var iframe = /** @type {!HTMLIFrameElement} */ (
+ document.createElement(goog.dom.TagName.IFRAME));
+ iframe.style.display = 'none';
+ iframe.src = '';
+ document.documentElement.appendChild(iframe);
+ var win = iframe.contentWindow;
+ var doc = win.document;
+ doc.open();
+ doc.write('');
+ doc.close();
+ // Do not post anything sensitive over this channel, as the workaround for
+ // pages with file: origin could allow that information to be modified or
+ // intercepted.
+ var message = 'callImmediate' + Math.random();
+ // The same origin policy rejects attempts to postMessage from file: urls
+ // unless the origin is '*'.
+ // TODO(b/16335441): Use '*' origin for data: and other similar protocols.
+ var origin = win.location.protocol == 'file:' ?
+ '*' :
+ win.location.protocol + '//' + win.location.host;
+ var onmessage = goog.bind(function(e) {
+ // Validate origin and message to make sure that this message was
+ // intended for us. If the origin is set to '*' (see above) only the
+ // message needs to match since, for example, '*' != 'file://'. Allowing
+ // the wildcard is ok, as we are not concerned with security here.
+ if ((origin != '*' && e.origin != origin) || e.data != message) {
+ return;
+ }
+ this['port1'].onmessage();
+ }, this);
+ win.addEventListener('message', onmessage, false);
+ this['port1'] = {};
+ this['port2'] = {
+ postMessage: function() { win.postMessage(message, origin); }
+ };
+ };
}
-};
-
-
-/**
- * Resets the stored previous values. Needed to be called for webkit which will
- * not generate a key up for meta key operations. This should only be called
- * when having finished with repeat key possiblities.
- */
-goog.events.KeyHandler.prototype.resetState = function() {
- this.lastKey_ = -1;
- this.keyCode_ = -1;
-};
-
-
-/**
- * Clears the stored previous key value, resetting the key repeat status. Uses
- * -1 because the Safari 3 Windows beta reports 0 for certain keys (like Home
- * and End.)
- * @param {goog.events.BrowserEvent} e The keyup event.
- * @private
- */
-goog.events.KeyHandler.prototype.handleKeyup_ = function(e) {
- this.resetState();
- this.altKey_ = e.altKey;
-};
-
-
-/**
- * Handles the events on the element.
- * @param {goog.events.BrowserEvent} e The keyboard event sent from the
- * browser.
- */
-goog.events.KeyHandler.prototype.handleEvent = function(e) {
- var be = e.getBrowserEvent();
- var keyCode, charCode;
- var altKey = be.altKey;
-
- // IE reports the character code in the keyCode field for keypress events.
- // There are two exceptions however, Enter and Escape.
- if (goog.userAgent.IE && e.type == goog.events.EventType.KEYPRESS) {
- keyCode = this.keyCode_;
- charCode = keyCode != goog.events.KeyCodes.ENTER &&
- keyCode != goog.events.KeyCodes.ESC ?
- be.keyCode : 0;
-
- // Safari reports the character code in the keyCode field for keypress
- // events but also has a charCode field.
- } else if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) &&
- e.type == goog.events.EventType.KEYPRESS) {
- keyCode = this.keyCode_;
- charCode = be.charCode >= 0 && be.charCode < 63232 &&
- goog.events.KeyCodes.isCharacterKey(keyCode) ?
- be.charCode : 0;
-
- // Opera reports the keycode or the character code in the keyCode field.
- } else if (goog.userAgent.OPERA && !goog.userAgent.WEBKIT) {
- keyCode = this.keyCode_;
- charCode = goog.events.KeyCodes.isCharacterKey(keyCode) ?
- be.keyCode : 0;
-
- // Mozilla reports the character code in the charCode field.
- } else {
- keyCode = be.keyCode || this.keyCode_;
- charCode = be.charCode || 0;
- if (goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_) {
- altKey = this.altKey_;
- }
- // On the Mac, shift-/ triggers a question mark char code and no key code
- // (normalized to WIN_KEY), so we synthesize the latter.
- if (goog.userAgent.MAC &&
- charCode == goog.events.KeyCodes.QUESTION_MARK &&
- keyCode == goog.events.KeyCodes.WIN_KEY) {
- keyCode = goog.events.KeyCodes.SLASH;
- }
- }
-
- keyCode = goog.events.KeyCodes.normalizeKeyCode(keyCode);
- var key = keyCode;
- var keyIdentifier = be.keyIdentifier;
-
- // Correct the key value for certain browser-specific quirks.
- if (keyCode) {
- if (keyCode >= 63232 && keyCode in goog.events.KeyHandler.safariKey_) {
- // NOTE(nicksantos): Safari 3 has fixed this problem,
- // this is only needed for Safari 2.
- key = goog.events.KeyHandler.safariKey_[keyCode];
- } else {
-
- // Safari returns 25 for Shift+Tab instead of 9.
- if (keyCode == 25 && e.shiftKey) {
- key = 9;
+ if (typeof Channel !== 'undefined' && (!goog.labs.userAgent.browser.isIE())) {
+ // Exclude all of IE due to
+ // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/
+ // which allows starving postMessage with a busy setTimeout loop.
+ // This currently affects IE10 and IE11 which would otherwise be able
+ // to use the postMessage based fallbacks.
+ var channel = new Channel();
+ // Use a fifo linked list to call callbacks in the right order.
+ var head = {};
+ var tail = head;
+ channel['port1'].onmessage = function() {
+ if (goog.isDef(head.next)) {
+ head = head.next;
+ var cb = head.cb;
+ head.cb = null;
+ cb();
}
- }
- } else if (keyIdentifier &&
- keyIdentifier in goog.events.KeyHandler.keyIdentifier_) {
- // This is needed for Safari Windows because it currently doesn't give a
- // keyCode/which for non printable keys.
- key = goog.events.KeyHandler.keyIdentifier_[keyIdentifier];
- }
-
- // If we get the same keycode as a keydown/keypress without having seen a
- // keyup event, then this event was caused by key repeat.
- var repeat = key == this.lastKey_;
- this.lastKey_ = key;
-
- var event = new goog.events.KeyEvent(key, charCode, repeat, be);
- event.altKey = altKey;
- this.dispatchEvent(event);
-};
-
-
-/**
- * Returns the element listened on for the real keyboard events.
- * @return {Element|Document|null} The element listened on for the real
- * keyboard events.
- */
-goog.events.KeyHandler.prototype.getElement = function() {
- return this.element_;
-};
-
-
-/**
- * Adds the proper key event listeners to the element.
- * @param {Element|Document} element The element to listen on.
- * @param {boolean=} opt_capture Whether to listen for browser events in
- * capture phase (defaults to false).
- */
-goog.events.KeyHandler.prototype.attach = function(element, opt_capture) {
- if (this.keyUpKey_) {
- this.detach();
- }
-
- this.element_ = element;
-
- this.keyPressKey_ = goog.events.listen(this.element_,
- goog.events.EventType.KEYPRESS,
- this,
- opt_capture);
-
- // Most browsers (Safari 2 being the notable exception) doesn't include the
- // keyCode in keypress events (IE has the char code in the keyCode field and
- // Mozilla only included the keyCode if there's no charCode). Thus we have to
- // listen for keydown to capture the keycode.
- this.keyDownKey_ = goog.events.listen(this.element_,
- goog.events.EventType.KEYDOWN,
- this.handleKeyDown_,
- opt_capture,
- this);
-
-
- this.keyUpKey_ = goog.events.listen(this.element_,
- goog.events.EventType.KEYUP,
- this.handleKeyup_,
- opt_capture,
- this);
-};
-
-
-/**
- * Removes the listeners that may exist.
- */
-goog.events.KeyHandler.prototype.detach = function() {
- if (this.keyPressKey_) {
- goog.events.unlistenByKey(this.keyPressKey_);
- goog.events.unlistenByKey(this.keyDownKey_);
- goog.events.unlistenByKey(this.keyUpKey_);
- this.keyPressKey_ = null;
- this.keyDownKey_ = null;
- this.keyUpKey_ = null;
- }
- this.element_ = null;
- this.lastKey_ = -1;
- this.keyCode_ = -1;
-};
-
-
-/** @override */
-goog.events.KeyHandler.prototype.disposeInternal = function() {
- goog.events.KeyHandler.superClass_.disposeInternal.call(this);
- this.detach();
-};
-
-
-
-/**
- * This class is used for the goog.events.KeyHandler.EventType.KEY event and
- * it overrides the key code with the fixed key code.
- * @param {number} keyCode The adjusted key code.
- * @param {number} charCode The unicode character code.
- * @param {boolean} repeat Whether this event was generated by keyboard repeat.
- * @param {Event} browserEvent Browser event object.
- * @constructor
- * @extends {goog.events.BrowserEvent}
- * @final
- */
-goog.events.KeyEvent = function(keyCode, charCode, repeat, browserEvent) {
- goog.events.BrowserEvent.call(this, browserEvent);
- this.type = goog.events.KeyHandler.EventType.KEY;
-
- /**
- * Keycode of key press.
- * @type {number}
- */
- this.keyCode = keyCode;
-
- /**
- * Unicode character code.
- * @type {number}
- */
- this.charCode = charCode;
-
- /**
- * True if this event was generated by keyboard auto-repeat (i.e., the user is
- * holding the key down.)
- * @type {boolean}
- */
- this.repeat = repeat;
-};
-goog.inherits(goog.events.KeyEvent, goog.events.BrowserEvent);
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview This event wrapper will dispatch an event when the user uses
- * the mouse wheel to scroll an element. You can get the direction by checking
- * the deltaX and deltaY properties of the event.
- *
- * This class aims to smooth out inconsistencies between browser platforms with
- * regards to mousewheel events, but we do not cover every possible
- * software/hardware combination out there, some of which occasionally produce
- * very large deltas in mousewheel events. If your application wants to guard
- * against extremely large deltas, use the setMaxDeltaX and setMaxDeltaY APIs
- * to set maximum values that make sense for your application.
- *
- * @author arv@google.com (Erik Arvidsson)
- * @see ../demos/mousewheelhandler.html
- */
-
-goog.provide('goog.events.MouseWheelEvent');
-goog.provide('goog.events.MouseWheelHandler');
-goog.provide('goog.events.MouseWheelHandler.EventType');
-
-goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.BrowserEvent');
-goog.require('goog.events.EventTarget');
-goog.require('goog.math');
-goog.require('goog.style');
-goog.require('goog.userAgent');
-
-
-
-/**
- * This event handler allows you to catch mouse wheel events in a consistent
- * manner.
- * @param {Element|Document} element The element to listen to the mouse wheel
- * event on.
- * @param {boolean=} opt_capture Whether to handle the mouse wheel event in
- * capture phase.
- * @constructor
- * @extends {goog.events.EventTarget}
- */
-goog.events.MouseWheelHandler = function(element, opt_capture) {
- goog.events.EventTarget.call(this);
-
- /**
- * This is the element that we will listen to the real mouse wheel events on.
- * @type {Element|Document}
- * @private
- */
- this.element_ = element;
-
- var rtlElement = goog.dom.isElement(this.element_) ?
- /** @type {Element} */ (this.element_) :
- (this.element_ ? /** @type {Document} */ (this.element_).body : null);
-
- /**
- * True if the element exists and is RTL, false otherwise.
- * @type {boolean}
- * @private
- */
- this.isRtl_ = !!rtlElement && goog.style.isRightToLeft(rtlElement);
-
- var type = goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel';
-
- /**
- * The key returned from the goog.events.listen.
- * @type {goog.events.Key}
- * @private
- */
- this.listenKey_ = goog.events.listen(this.element_, type, this, opt_capture);
-};
-goog.inherits(goog.events.MouseWheelHandler, goog.events.EventTarget);
-
-
-/**
- * Enum type for the events fired by the mouse wheel handler.
- * @enum {string}
- */
-goog.events.MouseWheelHandler.EventType = {
- MOUSEWHEEL: 'mousewheel'
-};
-
-
-/**
- * Optional maximum magnitude for x delta on each mousewheel event.
- * @type {number|undefined}
- * @private
- */
-goog.events.MouseWheelHandler.prototype.maxDeltaX_;
-
-
-/**
- * Optional maximum magnitude for y delta on each mousewheel event.
- * @type {number|undefined}
- * @private
- */
-goog.events.MouseWheelHandler.prototype.maxDeltaY_;
-
-
-/**
- * @param {number} maxDeltaX Maximum magnitude for x delta on each mousewheel
- * event. Should be non-negative.
- */
-goog.events.MouseWheelHandler.prototype.setMaxDeltaX = function(maxDeltaX) {
- this.maxDeltaX_ = maxDeltaX;
-};
-
-
-/**
- * @param {number} maxDeltaY Maximum magnitude for y delta on each mousewheel
- * event. Should be non-negative.
- */
-goog.events.MouseWheelHandler.prototype.setMaxDeltaY = function(maxDeltaY) {
- this.maxDeltaY_ = maxDeltaY;
-};
-
-
-/**
- * Handles the events on the element.
- * @param {goog.events.BrowserEvent} e The underlying browser event.
- */
-goog.events.MouseWheelHandler.prototype.handleEvent = function(e) {
- var deltaX = 0;
- var deltaY = 0;
- var detail = 0;
- var be = e.getBrowserEvent();
- if (be.type == 'mousewheel') {
- var wheelDeltaScaleFactor = 1;
- if (goog.userAgent.IE ||
- goog.userAgent.WEBKIT &&
- (goog.userAgent.WINDOWS || goog.userAgent.isVersionOrHigher('532.0'))) {
- // In IE we get a multiple of 120; we adjust to a multiple of 3 to
- // represent number of lines scrolled (like Gecko).
- // Newer versions of Webkit match IE behavior, and WebKit on
- // Windows also matches IE behavior.
- // See bug https://bugs.webkit.org/show_bug.cgi?id=24368
- wheelDeltaScaleFactor = 40;
- }
-
- detail = goog.events.MouseWheelHandler.smartScale_(
- -be.wheelDelta, wheelDeltaScaleFactor);
- if (goog.isDef(be.wheelDeltaX)) {
- // Webkit has two properties to indicate directional scroll, and
- // can scroll both directions at once.
- deltaX = goog.events.MouseWheelHandler.smartScale_(
- -be.wheelDeltaX, wheelDeltaScaleFactor);
- deltaY = goog.events.MouseWheelHandler.smartScale_(
- -be.wheelDeltaY, wheelDeltaScaleFactor);
- } else {
- deltaY = detail;
- }
-
- // Historical note: Opera (pre 9.5) used to negate the detail value.
- } else { // Gecko
- // Gecko returns multiple of 3 (representing the number of lines scrolled)
- detail = be.detail;
-
- // Gecko sometimes returns really big values if the user changes settings to
- // scroll a whole page per scroll
- if (detail > 100) {
- detail = 3;
- } else if (detail < -100) {
- detail = -3;
- }
-
- // Firefox 3.1 adds an axis field to the event to indicate direction of
- // scroll. See https://developer.mozilla.org/en/Gecko-Specific_DOM_Events
- if (goog.isDef(be.axis) && be.axis === be.HORIZONTAL_AXIS) {
- deltaX = detail;
- } else {
- deltaY = detail;
- }
- }
-
- if (goog.isNumber(this.maxDeltaX_)) {
- deltaX = goog.math.clamp(deltaX, -this.maxDeltaX_, this.maxDeltaX_);
- }
- if (goog.isNumber(this.maxDeltaY_)) {
- deltaY = goog.math.clamp(deltaY, -this.maxDeltaY_, this.maxDeltaY_);
+ };
+ return function(cb) {
+ tail.next = {cb: cb};
+ tail = tail.next;
+ channel['port2'].postMessage(0);
+ };
}
- // Don't clamp 'detail', since it could be ambiguous which axis it refers to
- // and because it's informally deprecated anyways.
-
- // For horizontal scrolling we need to flip the value for RTL grids.
- if (this.isRtl_) {
- deltaX = -deltaX;
+ // Implementation for IE6 to IE10: Script elements fire an asynchronous
+ // onreadystatechange event when inserted into the DOM.
+ if (typeof document !== 'undefined' &&
+ 'onreadystatechange' in document.createElement(goog.dom.TagName.SCRIPT)) {
+ return function(cb) {
+ var script = document.createElement(goog.dom.TagName.SCRIPT);
+ script.onreadystatechange = function() {
+ // Clean up and call the callback.
+ script.onreadystatechange = null;
+ script.parentNode.removeChild(script);
+ script = null;
+ cb();
+ cb = null;
+ };
+ document.documentElement.appendChild(script);
+ };
}
- var newEvent = new goog.events.MouseWheelEvent(detail, be, deltaX, deltaY);
- this.dispatchEvent(newEvent);
+ // Fall back to setTimeout with 0. In browsers this creates a delay of 5ms
+ // or more.
+ // NOTE(user): This fallback is used for IE11.
+ return function(cb) { goog.global.setTimeout(cb, 0); };
};
/**
- * Helper for scaling down a mousewheel delta by a scale factor, if appropriate.
- * @param {number} mouseWheelDelta Delta from a mouse wheel event. Expected to
- * be an integer.
- * @param {number} scaleFactor Factor to scale the delta down by. Expected to
- * be an integer.
- * @return {number} Scaled-down delta value, or the original delta if the
- * scaleFactor does not appear to be applicable.
+ * Helper function that is overrided to protect callbacks with entry point
+ * monitor if the application monitors entry points.
+ * @param {function()} callback Callback function to fire as soon as possible.
+ * @return {function()} The wrapped callback.
* @private
*/
-goog.events.MouseWheelHandler.smartScale_ = function(mouseWheelDelta,
- scaleFactor) {
- // The basic problem here is that in Webkit on Mac and Linux, we can get two
- // very different types of mousewheel events: from continuous devices
- // (touchpads, Mighty Mouse) or non-continuous devices (normal wheel mice).
- //
- // Non-continuous devices in Webkit get their wheel deltas scaled up to
- // behave like IE. Continuous devices return much smaller unscaled values
- // (which most of the time will not be cleanly divisible by the IE scale
- // factor), so we should not try to normalize them down.
- //
- // Detailed discussion:
- // https://bugs.webkit.org/show_bug.cgi?id=29601
- // http://trac.webkit.org/browser/trunk/WebKit/chromium/src/mac/WebInputEventFactory.mm#L1063
- if (goog.userAgent.WEBKIT &&
- (goog.userAgent.MAC || goog.userAgent.LINUX) &&
- (mouseWheelDelta % scaleFactor) != 0) {
- return mouseWheelDelta;
- } else {
- return mouseWheelDelta / scaleFactor;
- }
-};
-
-
-/** @override */
-goog.events.MouseWheelHandler.prototype.disposeInternal = function() {
- goog.events.MouseWheelHandler.superClass_.disposeInternal.call(this);
- goog.events.unlistenByKey(this.listenKey_);
- this.listenKey_ = null;
-};
-
-
-
-/**
- * A base class for mouse wheel events. This is used with the
- * MouseWheelHandler.
- *
- * @param {number} detail The number of rows the user scrolled.
- * @param {Event} browserEvent Browser event object.
- * @param {number} deltaX The number of rows the user scrolled in the X
- * direction.
- * @param {number} deltaY The number of rows the user scrolled in the Y
- * direction.
- * @constructor
- * @extends {goog.events.BrowserEvent}
- * @final
- */
-goog.events.MouseWheelEvent = function(detail, browserEvent, deltaX, deltaY) {
- goog.events.BrowserEvent.call(this, browserEvent);
-
- this.type = goog.events.MouseWheelHandler.EventType.MOUSEWHEEL;
-
- /**
- * The number of lines the user scrolled
- * @type {number}
- * NOTE: Informally deprecated. Use deltaX and deltaY instead, they provide
- * more information.
- */
- this.detail = detail;
-
- /**
- * The number of "lines" scrolled in the X direction.
- *
- * Note that not all browsers provide enough information to distinguish
- * horizontal and vertical scroll events, so for these unsupported browsers,
- * we will always have a deltaX of 0, even if the user scrolled their mouse
- * wheel or trackpad sideways.
- *
- * Currently supported browsers are Webkit and Firefox 3.1 or later.
- *
- * @type {number}
- */
- this.deltaX = deltaX;
-
- /**
- * The number of lines scrolled in the Y direction.
- * @type {number}
- */
- this.deltaY = deltaY;
-};
-goog.inherits(goog.events.MouseWheelEvent, goog.events.BrowserEvent);
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Basic strippable logging definitions.
- * @see http://go/closurelogging
- *
- * @author johnlenz@google.com (John Lenz)
- */
-
-goog.provide('goog.log');
-goog.provide('goog.log.Level');
-goog.provide('goog.log.LogRecord');
-goog.provide('goog.log.Logger');
-
-goog.require('goog.debug');
-goog.require('goog.debug.LogManager');
-goog.require('goog.debug.LogRecord');
-goog.require('goog.debug.Logger');
-
-
-/** @define {boolean} Whether logging is enabled. */
-goog.define('goog.log.ENABLED', goog.debug.LOGGING_ENABLED);
-
-
-/** @const */
-goog.log.ROOT_LOGGER_NAME = goog.debug.Logger.ROOT_LOGGER_NAME;
-
-
-
-/**
- * @constructor
- * @final
- */
-goog.log.Logger = goog.debug.Logger;
-
-
-
-/**
- * @constructor
- * @final
- */
-goog.log.Level = goog.debug.Logger.Level;
-
-
-
-/**
- * @constructor
- * @final
- */
-goog.log.LogRecord = goog.debug.LogRecord;
-
-
-/**
- * Finds or creates a logger for a named subsystem. If a logger has already been
- * created with the given name it is returned. Otherwise a new logger is
- * created. If a new logger is created its log level will be configured based
- * on the goog.debug.LogManager configuration and it will configured to also
- * send logging output to its parent's handlers.
- * @see goog.debug.LogManager
- *
- * @param {string} name A name for the logger. This should be a dot-separated
- * name and should normally be based on the package name or class name of
- * the subsystem, such as goog.net.BrowserChannel.
- * @param {goog.log.Level=} opt_level If provided, override the
- * default logging level with the provided level.
- * @return {goog.log.Logger} The named logger or null if logging is disabled.
- */
-goog.log.getLogger = function(name, opt_level) {
- if (goog.log.ENABLED) {
- var logger = goog.debug.LogManager.getLogger(name);
- if (opt_level && logger) {
- logger.setLevel(opt_level);
- }
- return logger;
- } else {
- return null;
- }
-};
-
-
-// TODO(johnlenz): try to tighten the types to these functions.
-/**
- * Adds a handler to the logger. This doesn't use the event system because
- * we want to be able to add logging to the event system.
- * @param {goog.log.Logger} logger
- * @param {Function} handler Handler function to add.
- */
-goog.log.addHandler = function(logger, handler) {
- if (goog.log.ENABLED && logger) {
- logger.addHandler(handler);
- }
-};
-
-
-/**
- * Removes a handler from the logger. This doesn't use the event system because
- * we want to be able to add logging to the event system.
- * @param {goog.log.Logger} logger
- * @param {Function} handler Handler function to remove.
- * @return {boolean} Whether the handler was removed.
- */
-goog.log.removeHandler = function(logger, handler) {
- if (goog.log.ENABLED && logger) {
- return logger.removeHandler(handler);
- } else {
- return false;
- }
-};
-
-
-/**
- * Logs a message. If the logger is currently enabled for the
- * given message level then the given message is forwarded to all the
- * registered output Handler objects.
- * @param {goog.log.Logger} logger
- * @param {goog.log.Level} level One of the level identifiers.
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error|Object=} opt_exception An exception associated with the
- * message.
- */
-goog.log.log = function(logger, level, msg, opt_exception) {
- if (goog.log.ENABLED && logger) {
- logger.log(level, msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Level.SEVERE level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.log.Logger} logger
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.log.error = function(logger, msg, opt_exception) {
- if (goog.log.ENABLED && logger) {
- logger.severe(msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Level.WARNING level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.log.Logger} logger
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.log.warning = function(logger, msg, opt_exception) {
- if (goog.log.ENABLED && logger) {
- logger.warning(msg, opt_exception);
- }
-};
-
-
-/**
- * Logs a message at the Level.INFO level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.log.Logger} logger
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.log.info = function(logger, msg, opt_exception) {
- if (goog.log.ENABLED && logger) {
- logger.info(msg, opt_exception);
- }
-};
+goog.async.nextTick.wrapCallback_ = goog.functions.identity;
-/**
- * Logs a message at the Level.Fine level.
- * If the logger is currently enabled for the given message level then the
- * given message is forwarded to all the registered output Handler objects.
- * @param {goog.log.Logger} logger
- * @param {goog.debug.Loggable} msg The message to log.
- * @param {Error=} opt_exception An exception associated with the message.
- */
-goog.log.fine = function(logger, msg, opt_exception) {
- if (goog.log.ENABLED && logger) {
- logger.fine(msg, opt_exception);
- }
-};
+// Register the callback function as an entry point, so that it can be
+// monitored for exception handling, etc. This has to be done in this file
+// since it requires special code to handle all browsers.
+goog.debug.entryPointRegistry.register(
+ /**
+ * @param {function(!Function): !Function} transformer The transforming
+ * function.
+ */
+ function(transformer) { goog.async.nextTick.wrapCallback_ = transformer; });
// Based on https://github.com/Polymer/PointerEvents
@@ -47113,9 +38011,8 @@ goog.log.fine = function(logger, msg, opt_exception) {
goog.provide('ol.pointer.PointerEvent');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-
+goog.require('ol.events');
+goog.require('ol.events.Event');
/**
@@ -47125,20 +38022,20 @@ goog.require('goog.events.Event');
* touch events and even native pointer events.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @param {string} type The type of the event to create.
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Event} originalEvent The event.
* @param {Object.<string, ?>=} opt_eventDict An optional dictionary of
* initial event properties.
*/
-ol.pointer.PointerEvent = function(type, browserEvent, opt_eventDict) {
+ol.pointer.PointerEvent = function(type, originalEvent, opt_eventDict) {
goog.base(this, type);
/**
* @const
- * @type {goog.events.BrowserEvent}
+ * @type {Event}
*/
- this.browserEvent = browserEvent;
+ this.originalEvent = originalEvent;
var eventDict = opt_eventDict ? opt_eventDict : {};
@@ -47269,19 +38166,19 @@ ol.pointer.PointerEvent = function(type, browserEvent, opt_eventDict) {
this.isPrimary = 'isPrimary' in eventDict ? eventDict['isPrimary'] : false;
// keep the semantics of preventDefault
- if (browserEvent.preventDefault) {
+ if (originalEvent.preventDefault) {
this.preventDefault = function() {
- browserEvent.preventDefault();
+ originalEvent.preventDefault();
};
}
};
-goog.inherits(ol.pointer.PointerEvent, goog.events.Event);
+goog.inherits(ol.pointer.PointerEvent, ol.events.Event);
/**
* @private
- * @param {Object.<string, ?>} eventDict
- * @return {number}
+ * @param {Object.<string, ?>} eventDict The event dictionary.
+ * @return {number} Button indicator.
*/
ol.pointer.PointerEvent.prototype.getButtons_ = function(eventDict) {
// According to the w3c spec,
@@ -47322,9 +38219,9 @@ ol.pointer.PointerEvent.prototype.getButtons_ = function(eventDict) {
/**
* @private
- * @param {Object.<string, ?>} eventDict
- * @param {number} buttons
- * @return {number}
+ * @param {Object.<string, ?>} eventDict The event dictionary.
+ * @param {number} buttons Button indicator.
+ * @return {number} The pressure.
*/
ol.pointer.PointerEvent.prototype.getPressure_ = function(eventDict, buttons) {
// Spec requires that pointers without pressure specified use 0.5 for down
@@ -47354,16 +38251,13 @@ ol.pointer.PointerEvent.HAS_BUTTONS = false;
var ev = new MouseEvent('click', {buttons: 1});
ol.pointer.PointerEvent.HAS_BUTTONS = ev.buttons === 1;
} catch (e) {
+ // pass
}
})();
-// FIXME add tests for browser features (Modernizr?)
-
goog.provide('ol.dom');
-goog.provide('ol.dom.BrowserFeature');
goog.require('goog.asserts');
-goog.require('goog.dom');
goog.require('goog.userAgent');
goog.require('goog.vec.Mat4');
goog.require('ol');
@@ -47373,7 +38267,7 @@ goog.require('ol');
* Create an html canvas element and returns its 2d context.
* @param {number=} opt_width Canvas width.
* @param {number=} opt_height Canvas height.
- * @return {CanvasRenderingContext2D}
+ * @return {CanvasRenderingContext2D} The context.
*/
ol.dom.createCanvasContext2D = function(opt_width, opt_height) {
var canvas = document.createElement('CANVAS');
@@ -47399,31 +38293,29 @@ ol.dom.canUseCssTransform = (function() {
if (canUseCssTransform === undefined) {
goog.asserts.assert(document.body,
'document.body should not be null');
- if (!goog.global.getComputedStyle) {
- // this browser is ancient
- canUseCssTransform = false;
- } else {
- var el = document.createElement('P'),
- has2d,
- transforms = {
- 'webkitTransform': '-webkit-transform',
- 'OTransform': '-o-transform',
- 'msTransform': '-ms-transform',
- 'MozTransform': '-moz-transform',
- 'transform': 'transform'
- };
- document.body.appendChild(el);
- for (var t in transforms) {
- if (t in el.style) {
- el.style[t] = 'translate(1px,1px)';
- has2d = goog.global.getComputedStyle(el).getPropertyValue(
- transforms[t]);
- }
+ goog.asserts.assert(ol.global.getComputedStyle,
+ 'getComputedStyle is required (unsupported browser?)');
+
+ var el = document.createElement('P'),
+ has2d,
+ transforms = {
+ 'webkitTransform': '-webkit-transform',
+ 'OTransform': '-o-transform',
+ 'msTransform': '-ms-transform',
+ 'MozTransform': '-moz-transform',
+ 'transform': 'transform'
+ };
+ document.body.appendChild(el);
+ for (var t in transforms) {
+ if (t in el.style) {
+ el.style[t] = 'translate(1px,1px)';
+ has2d = ol.global.getComputedStyle(el).getPropertyValue(
+ transforms[t]);
}
- goog.dom.removeNode(el);
-
- canUseCssTransform = (has2d && has2d !== 'none');
}
+ document.body.removeChild(el);
+
+ canUseCssTransform = (has2d && has2d !== 'none');
}
return canUseCssTransform;
};
@@ -47442,31 +38334,29 @@ ol.dom.canUseCssTransform3D = (function() {
if (canUseCssTransform3D === undefined) {
goog.asserts.assert(document.body,
'document.body should not be null');
- if (!goog.global.getComputedStyle) {
- // this browser is ancient
- canUseCssTransform3D = false;
- } else {
- var el = document.createElement('P'),
- has3d,
- transforms = {
- 'webkitTransform': '-webkit-transform',
- 'OTransform': '-o-transform',
- 'msTransform': '-ms-transform',
- 'MozTransform': '-moz-transform',
- 'transform': 'transform'
- };
- document.body.appendChild(el);
- for (var t in transforms) {
- if (t in el.style) {
- el.style[t] = 'translate3d(1px,1px,1px)';
- has3d = goog.global.getComputedStyle(el).getPropertyValue(
- transforms[t]);
- }
+ goog.asserts.assert(ol.global.getComputedStyle,
+ 'getComputedStyle is required (unsupported browser?)');
+
+ var el = document.createElement('P'),
+ has3d,
+ transforms = {
+ 'webkitTransform': '-webkit-transform',
+ 'OTransform': '-o-transform',
+ 'msTransform': '-ms-transform',
+ 'MozTransform': '-moz-transform',
+ 'transform': 'transform'
+ };
+ document.body.appendChild(el);
+ for (var t in transforms) {
+ if (t in el.style) {
+ el.style[t] = 'translate3d(1px,1px,1px)';
+ has3d = ol.global.getComputedStyle(el).getPropertyValue(
+ transforms[t]);
}
- goog.dom.removeNode(el);
-
- canUseCssTransform3D = (has3d && has3d !== 'none');
}
+ document.body.removeChild(el);
+
+ canUseCssTransform3D = (has3d && has3d !== 'none');
}
return canUseCssTransform3D;
};
@@ -47555,11 +38445,11 @@ ol.dom.transformElement2D = function(element, transform, opt_precision) {
* padding and border.
* Equivalent to jQuery's `$(el).outerWidth(true)`.
* @param {!Element} element Element.
- * @return {number}
+ * @return {number} The width.
*/
ol.dom.outerWidth = function(element) {
var width = element.offsetWidth;
- var style = element.currentStyle || window.getComputedStyle(element);
+ var style = element.currentStyle || ol.global.getComputedStyle(element);
width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
return width;
@@ -47571,11 +38461,11 @@ ol.dom.outerWidth = function(element) {
* padding and border.
* Equivalent to jQuery's `$(el).outerHeight(true)`.
* @param {!Element} element Element.
- * @return {number}
+ * @return {number} The height.
*/
ol.dom.outerHeight = function(element) {
var height = element.offsetHeight;
- var style = element.currentStyle || window.getComputedStyle(element);
+ var style = element.currentStyle || ol.global.getComputedStyle(element);
height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
return height;
@@ -47621,6 +38511,7 @@ ol.webgl.getContext = function(canvas, opt_attributes) {
return /** @type {!WebGLRenderingContext} */ (context);
}
} catch (e) {
+ // pass
}
}
return null;
@@ -47633,6 +38524,28 @@ goog.require('ol.dom');
goog.require('ol.webgl');
+var ua = typeof navigator !== 'undefined' ?
+ navigator.userAgent.toLowerCase() : '';
+
+/**
+ * User agent string says we are dealing with Firefox as browser.
+ * @type {boolean}
+ */
+ol.has.FIREFOX = ua.indexOf('firefox') !== -1;
+
+/**
+ * User agent string says we are dealing with Safari as browser.
+ * @type {boolean}
+ */
+ol.has.SAFARI = ua.indexOf('safari') !== -1 && ua.indexOf('chrom') === -1;
+
+/**
+ * User agent string says we are dealing with a Mac as platform.
+ * @type {boolean}
+ */
+ol.has.MAC = ua.indexOf('macintosh') !== -1;
+
+
/**
* The ratio between physical pixels and device-independent pixels
* (dips) on the device (`window.devicePixelRatio`).
@@ -47640,7 +38553,7 @@ goog.require('ol.webgl');
* @type {number}
* @api stable
*/
-ol.has.DEVICE_PIXEL_RATIO = goog.global.devicePixelRatio || 1;
+ol.has.DEVICE_PIXEL_RATIO = ol.global.devicePixelRatio || 1;
/**
@@ -47662,7 +38575,7 @@ ol.has.CANVAS = ol.ENABLE_CANVAS && (
* @return {boolean} Canvas supported.
*/
function() {
- if (!('HTMLCanvasElement' in goog.global)) {
+ if (!('HTMLCanvasElement' in ol.global)) {
return false;
}
try {
@@ -47687,7 +38600,7 @@ ol.has.CANVAS = ol.ENABLE_CANVAS && (
* @type {boolean}
* @api stable
*/
-ol.has.DEVICE_ORIENTATION = 'DeviceOrientationEvent' in goog.global;
+ol.has.DEVICE_ORIENTATION = 'DeviceOrientationEvent' in ol.global;
/**
@@ -47704,7 +38617,7 @@ ol.has.DOM = ol.ENABLE_DOM;
* @type {boolean}
* @api stable
*/
-ol.has.GEOLOCATION = 'geolocation' in goog.global.navigator;
+ol.has.GEOLOCATION = 'geolocation' in ol.global.navigator;
/**
@@ -47713,7 +38626,7 @@ ol.has.GEOLOCATION = 'geolocation' in goog.global.navigator;
* @type {boolean}
* @api stable
*/
-ol.has.TOUCH = ol.ASSUME_TOUCH || 'ontouchstart' in goog.global;
+ol.has.TOUCH = ol.ASSUME_TOUCH || 'ontouchstart' in ol.global;
/**
@@ -47721,7 +38634,7 @@ ol.has.TOUCH = ol.ASSUME_TOUCH || 'ontouchstart' in goog.global;
* @const
* @type {boolean}
*/
-ol.has.POINTER = 'PointerEvent' in goog.global;
+ol.has.POINTER = 'PointerEvent' in ol.global;
/**
@@ -47729,7 +38642,7 @@ ol.has.POINTER = 'PointerEvent' in goog.global;
* @const
* @type {boolean}
*/
-ol.has.MSPOINTER = !!(goog.global.navigator.msPointerEnabled);
+ol.has.MSPOINTER = !!(ol.global.navigator.msPointerEnabled);
/**
@@ -47748,7 +38661,7 @@ ol.has.WEBGL;
var textureSize;
var /** @type {Array.<string>} */ extensions = [];
- if ('WebGLRenderingContext' in goog.global) {
+ if ('WebGLRenderingContext' in ol.global) {
try {
var canvas = /** @type {HTMLCanvasElement} */
(document.createElement('CANVAS'));
@@ -47761,7 +38674,9 @@ ol.has.WEBGL;
(gl.getParameter(gl.MAX_TEXTURE_SIZE));
extensions = gl.getSupportedExtensions();
}
- } catch (e) {}
+ } catch (e) {
+ // pass
+ }
}
ol.has.WEBGL = hasWebGL;
ol.WEBGL_EXTENSIONS = extensions;
@@ -47771,13 +38686,11 @@ ol.has.WEBGL;
goog.provide('ol.pointer.EventSource');
-goog.require('goog.events.BrowserEvent');
-
-
/**
- * @param {ol.pointer.PointerEventHandler} dispatcher
- * @param {!Object.<string, function(goog.events.BrowserEvent)>} mapping
+ * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
+ * @param {!Object.<string, function(Event)>} mapping Event
+ * mapping.
* @constructor
*/
ol.pointer.EventSource = function(dispatcher, mapping) {
@@ -47789,7 +38702,7 @@ ol.pointer.EventSource = function(dispatcher, mapping) {
/**
* @private
* @const
- * @type {!Object.<string, function(goog.events.BrowserEvent)>}
+ * @type {!Object.<string, function(Event)>}
*/
this.mapping_ = mapping;
};
@@ -47807,7 +38720,7 @@ ol.pointer.EventSource.prototype.getEvents = function() {
/**
* Returns a mapping between the supported event types and
* the handlers that should handle an event.
- * @return {Object.<string, function(goog.events.BrowserEvent)>}
+ * @return {Object.<string, function(Event)>}
* Event/Handler mapping
*/
ol.pointer.EventSource.prototype.getMapping = function() {
@@ -47817,8 +38730,8 @@ ol.pointer.EventSource.prototype.getMapping = function() {
/**
* Returns the handler that should handle a given event type.
- * @param {string} eventType
- * @return {function(goog.events.BrowserEvent)} Handler
+ * @param {string} eventType The event type.
+ * @return {function(Event)} Handler
*/
ol.pointer.EventSource.prototype.getHandlerForEvent = function(eventType) {
return this.mapping_[eventType];
@@ -47859,9 +38772,8 @@ goog.provide('ol.pointer.MouseSource');
goog.require('ol.pointer.EventSource');
-
/**
- * @param {ol.pointer.PointerEventHandler} dispatcher
+ * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
* @constructor
* @extends {ol.pointer.EventSource}
*/
@@ -47877,7 +38789,7 @@ ol.pointer.MouseSource = function(dispatcher) {
/**
* @const
- * @type {!Object.<string, goog.events.BrowserEvent|Object>}
+ * @type {!Object.<string, Event|Object>}
*/
this.pointerMap = dispatcher.pointerMap;
@@ -47934,11 +38846,10 @@ ol.pointer.MouseSource.DEDUP_DIST = 25;
* or detect that the positions are invalid.
*
* @private
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
* @return {boolean} True, if the event was generated by a touch.
*/
-ol.pointer.MouseSource.prototype.isEventSimulatedFromTouch_ =
- function(inEvent) {
+ol.pointer.MouseSource.prototype.isEventSimulatedFromTouch_ = function(inEvent) {
var lts = this.lastTouches;
var x = inEvent.clientX, y = inEvent.clientY;
for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) {
@@ -47957,12 +38868,12 @@ ol.pointer.MouseSource.prototype.isEventSimulatedFromTouch_ =
* Creates a copy of the original event that will be used
* for the fake pointer event.
*
- * @param {goog.events.BrowserEvent} inEvent
- * @param {ol.pointer.PointerEventHandler} dispatcher
- * @return {Object}
+ * @param {Event} inEvent The in event.
+ * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
+ * @return {Object} The copied event.
*/
ol.pointer.MouseSource.prepareEvent = function(inEvent, dispatcher) {
- var e = dispatcher.cloneEvent(inEvent, inEvent.getBrowserEvent());
+ var e = dispatcher.cloneEvent(inEvent, inEvent);
// forward mouse preventDefault
var pd = e.preventDefault;
@@ -47982,7 +38893,7 @@ ol.pointer.MouseSource.prepareEvent = function(inEvent, dispatcher) {
/**
* Handler for `mousedown`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MouseSource.prototype.mousedown = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
@@ -48001,7 +38912,7 @@ ol.pointer.MouseSource.prototype.mousedown = function(inEvent) {
/**
* Handler for `mousemove`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MouseSource.prototype.mousemove = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
@@ -48014,7 +38925,7 @@ ol.pointer.MouseSource.prototype.mousemove = function(inEvent) {
/**
* Handler for `mouseup`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MouseSource.prototype.mouseup = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
@@ -48032,7 +38943,7 @@ ol.pointer.MouseSource.prototype.mouseup = function(inEvent) {
/**
* Handler for `mouseover`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MouseSource.prototype.mouseover = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
@@ -48045,7 +38956,7 @@ ol.pointer.MouseSource.prototype.mouseover = function(inEvent) {
/**
* Handler for `mouseout`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MouseSource.prototype.mouseout = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
@@ -48058,7 +38969,7 @@ ol.pointer.MouseSource.prototype.mouseout = function(inEvent) {
/**
* Dispatches a `pointercancel` event.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MouseSource.prototype.cancel = function(inEvent) {
var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
@@ -48109,9 +39020,8 @@ goog.provide('ol.pointer.MsSource');
goog.require('ol.pointer.EventSource');
-
/**
- * @param {ol.pointer.PointerEventHandler} dispatcher
+ * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
* @constructor
* @extends {ol.pointer.EventSource}
*/
@@ -48130,7 +39040,7 @@ ol.pointer.MsSource = function(dispatcher) {
/**
* @const
- * @type {!Object.<string, goog.events.BrowserEvent|Object>}
+ * @type {!Object.<string, Event|Object>}
*/
this.pointerMap = dispatcher.pointerMap;
@@ -48154,14 +39064,14 @@ goog.inherits(ol.pointer.MsSource, ol.pointer.EventSource);
* for the fake pointer event.
*
* @private
- * @param {goog.events.BrowserEvent} inEvent
- * @return {Object}
+ * @param {Event} inEvent The in event.
+ * @return {Object} The copied event.
*/
ol.pointer.MsSource.prototype.prepareEvent_ = function(inEvent) {
var e = inEvent;
- if (goog.isNumber(inEvent.getBrowserEvent().pointerType)) {
- e = this.dispatcher.cloneEvent(inEvent, inEvent.getBrowserEvent());
- e.pointerType = this.POINTER_TYPES[inEvent.getBrowserEvent().pointerType];
+ if (goog.isNumber(inEvent.pointerType)) {
+ e = this.dispatcher.cloneEvent(inEvent, inEvent);
+ e.pointerType = this.POINTER_TYPES[inEvent.pointerType];
}
return e;
@@ -48170,7 +39080,7 @@ ol.pointer.MsSource.prototype.prepareEvent_ = function(inEvent) {
/**
* Remove this pointer from the list of active pointers.
- * @param {number} pointerId
+ * @param {number} pointerId Pointer identifier.
*/
ol.pointer.MsSource.prototype.cleanup = function(pointerId) {
delete this.pointerMap[pointerId.toString()];
@@ -48180,10 +39090,10 @@ ol.pointer.MsSource.prototype.cleanup = function(pointerId) {
/**
* Handler for `msPointerDown`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MsSource.prototype.msPointerDown = function(inEvent) {
- this.pointerMap[inEvent.getBrowserEvent().pointerId.toString()] = inEvent;
+ this.pointerMap[inEvent.pointerId.toString()] = inEvent;
var e = this.prepareEvent_(inEvent);
this.dispatcher.down(e, inEvent);
};
@@ -48192,7 +39102,7 @@ ol.pointer.MsSource.prototype.msPointerDown = function(inEvent) {
/**
* Handler for `msPointerMove`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MsSource.prototype.msPointerMove = function(inEvent) {
var e = this.prepareEvent_(inEvent);
@@ -48203,19 +39113,19 @@ ol.pointer.MsSource.prototype.msPointerMove = function(inEvent) {
/**
* Handler for `msPointerUp`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MsSource.prototype.msPointerUp = function(inEvent) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.up(e, inEvent);
- this.cleanup(inEvent.getBrowserEvent().pointerId);
+ this.cleanup(inEvent.pointerId);
};
/**
* Handler for `msPointerOut`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MsSource.prototype.msPointerOut = function(inEvent) {
var e = this.prepareEvent_(inEvent);
@@ -48226,7 +39136,7 @@ ol.pointer.MsSource.prototype.msPointerOut = function(inEvent) {
/**
* Handler for `msPointerOver`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MsSource.prototype.msPointerOver = function(inEvent) {
var e = this.prepareEvent_(inEvent);
@@ -48237,23 +39147,23 @@ ol.pointer.MsSource.prototype.msPointerOver = function(inEvent) {
/**
* Handler for `msPointerCancel`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MsSource.prototype.msPointerCancel = function(inEvent) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.cancel(e, inEvent);
- this.cleanup(inEvent.getBrowserEvent().pointerId);
+ this.cleanup(inEvent.pointerId);
};
/**
* Handler for `msLostPointerCapture`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MsSource.prototype.msLostPointerCapture = function(inEvent) {
var e = this.dispatcher.makeEvent('lostpointercapture',
- inEvent.getBrowserEvent(), inEvent);
+ inEvent, inEvent);
this.dispatcher.dispatchEvent(e);
};
@@ -48261,11 +39171,11 @@ ol.pointer.MsSource.prototype.msLostPointerCapture = function(inEvent) {
/**
* Handler for `msGotPointerCapture`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.MsSource.prototype.msGotPointerCapture = function(inEvent) {
var e = this.dispatcher.makeEvent('gotpointercapture',
- inEvent.getBrowserEvent(), inEvent);
+ inEvent, inEvent);
this.dispatcher.dispatchEvent(e);
};
@@ -48304,9 +39214,8 @@ goog.provide('ol.pointer.NativeSource');
goog.require('ol.pointer.EventSource');
-
/**
- * @param {ol.pointer.PointerEventHandler} dispatcher
+ * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
* @constructor
* @extends {ol.pointer.EventSource}
*/
@@ -48329,7 +39238,7 @@ goog.inherits(ol.pointer.NativeSource, ol.pointer.EventSource);
/**
* Handler for `pointerdown`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.NativeSource.prototype.pointerDown = function(inEvent) {
this.dispatcher.fireNativeEvent(inEvent);
@@ -48339,7 +39248,7 @@ ol.pointer.NativeSource.prototype.pointerDown = function(inEvent) {
/**
* Handler for `pointermove`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.NativeSource.prototype.pointerMove = function(inEvent) {
this.dispatcher.fireNativeEvent(inEvent);
@@ -48349,7 +39258,7 @@ ol.pointer.NativeSource.prototype.pointerMove = function(inEvent) {
/**
* Handler for `pointerup`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.NativeSource.prototype.pointerUp = function(inEvent) {
this.dispatcher.fireNativeEvent(inEvent);
@@ -48359,7 +39268,7 @@ ol.pointer.NativeSource.prototype.pointerUp = function(inEvent) {
/**
* Handler for `pointerout`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.NativeSource.prototype.pointerOut = function(inEvent) {
this.dispatcher.fireNativeEvent(inEvent);
@@ -48369,7 +39278,7 @@ ol.pointer.NativeSource.prototype.pointerOut = function(inEvent) {
/**
* Handler for `pointerover`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.NativeSource.prototype.pointerOver = function(inEvent) {
this.dispatcher.fireNativeEvent(inEvent);
@@ -48379,7 +39288,7 @@ ol.pointer.NativeSource.prototype.pointerOver = function(inEvent) {
/**
* Handler for `pointercancel`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.NativeSource.prototype.pointerCancel = function(inEvent) {
this.dispatcher.fireNativeEvent(inEvent);
@@ -48389,7 +39298,7 @@ ol.pointer.NativeSource.prototype.pointerCancel = function(inEvent) {
/**
* Handler for `lostpointercapture`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.NativeSource.prototype.lostPointerCapture = function(inEvent) {
this.dispatcher.fireNativeEvent(inEvent);
@@ -48399,7 +39308,7 @@ ol.pointer.NativeSource.prototype.lostPointerCapture = function(inEvent) {
/**
* Handler for `gotpointercapture`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.NativeSource.prototype.gotPointerCapture = function(inEvent) {
this.dispatcher.fireNativeEvent(inEvent);
@@ -48437,18 +39346,16 @@ ol.pointer.NativeSource.prototype.gotPointerCapture = function(inEvent) {
goog.provide('ol.pointer.TouchSource');
-goog.require('goog.array');
-goog.require('goog.object');
goog.require('ol');
+goog.require('ol.array');
goog.require('ol.pointer.EventSource');
goog.require('ol.pointer.MouseSource');
-
/**
* @constructor
- * @param {ol.pointer.PointerEventHandler} dispatcher
- * @param {ol.pointer.MouseSource} mouseSource
+ * @param {ol.pointer.PointerEventHandler} dispatcher The event handler.
+ * @param {ol.pointer.MouseSource} mouseSource Mouse source.
* @extends {ol.pointer.EventSource}
*/
ol.pointer.TouchSource = function(dispatcher, mouseSource) {
@@ -48462,7 +39369,7 @@ ol.pointer.TouchSource = function(dispatcher, mouseSource) {
/**
* @const
- * @type {!Object.<string, goog.events.BrowserEvent|Object>}
+ * @type {!Object.<string, Event|Object>}
*/
this.pointerMap = dispatcher.pointerMap;
@@ -48518,7 +39425,7 @@ ol.pointer.TouchSource.POINTER_TYPE = 'touch';
/**
* @private
- * @param {Touch} inTouch
+ * @param {Touch} inTouch The in touch.
* @return {boolean} True, if this is the primary touch.
*/
ol.pointer.TouchSource.prototype.isPrimaryTouch_ = function(inTouch) {
@@ -48528,11 +39435,11 @@ ol.pointer.TouchSource.prototype.isPrimaryTouch_ = function(inTouch) {
/**
* Set primary touch if there are no pointers, or the only pointer is the mouse.
- * @param {Touch} inTouch
+ * @param {Touch} inTouch The in touch.
* @private
*/
ol.pointer.TouchSource.prototype.setPrimaryTouch_ = function(inTouch) {
- var count = goog.object.getCount(this.pointerMap);
+ var count = Object.keys(this.pointerMap).length;
if (count === 0 || (count === 1 &&
ol.pointer.MouseSource.POINTER_ID.toString() in this.pointerMap)) {
this.firstTouchId_ = inTouch.identifier;
@@ -48543,7 +39450,7 @@ ol.pointer.TouchSource.prototype.setPrimaryTouch_ = function(inTouch) {
/**
* @private
- * @param {Object} inPointer
+ * @param {Object} inPointer The in pointer object.
*/
ol.pointer.TouchSource.prototype.removePrimaryPointer_ = function(inPointer) {
if (inPointer.isPrimary) {
@@ -48557,8 +39464,8 @@ ol.pointer.TouchSource.prototype.removePrimaryPointer_ = function(inPointer) {
* @private
*/
ol.pointer.TouchSource.prototype.resetClickCount_ = function() {
- this.resetId_ = goog.global.setTimeout(
- goog.bind(this.resetClickCountHandler_, this),
+ this.resetId_ = ol.global.setTimeout(
+ this.resetClickCountHandler_.bind(this),
ol.pointer.TouchSource.CLICK_COUNT_TIMEOUT);
};
@@ -48577,19 +39484,18 @@ ol.pointer.TouchSource.prototype.resetClickCountHandler_ = function() {
*/
ol.pointer.TouchSource.prototype.cancelResetClickCount_ = function() {
if (this.resetId_ !== undefined) {
- goog.global.clearTimeout(this.resetId_);
+ ol.global.clearTimeout(this.resetId_);
}
};
/**
* @private
- * @param {goog.events.BrowserEvent} browserEvent Browser event
+ * @param {Event} browserEvent Browser event
* @param {Touch} inTouch Touch event
- * @return {Object}
+ * @return {Object} A pointer object.
*/
-ol.pointer.TouchSource.prototype.touchToPointer_ =
- function(browserEvent, inTouch) {
+ol.pointer.TouchSource.prototype.touchToPointer_ = function(browserEvent, inTouch) {
var e = this.dispatcher.cloneEvent(browserEvent, inTouch);
// Spec specifies that pointerId 1 is reserved for Mouse.
// Touch identifiers can start at 0.
@@ -48621,13 +39527,12 @@ ol.pointer.TouchSource.prototype.touchToPointer_ =
/**
* @private
- * @param {goog.events.BrowserEvent} inEvent Touch event
- * @param {function(goog.events.BrowserEvent, Object)} inFunction
+ * @param {Event} inEvent Touch event
+ * @param {function(Event, Object)} inFunction In function.
*/
-ol.pointer.TouchSource.prototype.processTouches_ =
- function(inEvent, inFunction) {
+ol.pointer.TouchSource.prototype.processTouches_ = function(inEvent, inFunction) {
var touches = Array.prototype.slice.call(
- inEvent.getBrowserEvent().changedTouches);
+ inEvent.changedTouches);
var count = touches.length;
function preventDefault() {
inEvent.preventDefault();
@@ -48644,8 +39549,8 @@ ol.pointer.TouchSource.prototype.processTouches_ =
/**
* @private
- * @param {TouchList} touchList
- * @param {number} searchId
+ * @param {TouchList} touchList The touch list.
+ * @param {number} searchId Search identifier.
* @return {boolean} True, if the `Touch` with the given id is in the list.
*/
ol.pointer.TouchSource.prototype.findTouch_ = function(touchList, searchId) {
@@ -48670,10 +39575,10 @@ ol.pointer.TouchSource.prototype.findTouch_ = function(touchList, searchId) {
* this "abandoned" touch
*
* @private
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.TouchSource.prototype.vacuumTouches_ = function(inEvent) {
- var touchList = inEvent.getBrowserEvent().touches;
+ var touchList = inEvent.touches;
// pointerMap.getCount() should be < touchList.length here,
// as the touchstart has not been processed yet.
var keys = Object.keys(this.pointerMap);
@@ -48703,11 +39608,11 @@ ol.pointer.TouchSource.prototype.vacuumTouches_ = function(inEvent) {
* Handler for `touchstart`, triggers `pointerover`,
* `pointerenter` and `pointerdown` events.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.TouchSource.prototype.touchstart = function(inEvent) {
this.vacuumTouches_(inEvent);
- this.setPrimaryTouch_(inEvent.getBrowserEvent().changedTouches[0]);
+ this.setPrimaryTouch_(inEvent.changedTouches[0]);
this.dedupSynthMouse_(inEvent);
this.clickCount_++;
this.processTouches_(inEvent, this.overDown_);
@@ -48716,8 +39621,8 @@ ol.pointer.TouchSource.prototype.touchstart = function(inEvent) {
/**
* @private
- * @param {goog.events.BrowserEvent} browserEvent
- * @param {Object} inPointer
+ * @param {Event} browserEvent The event.
+ * @param {Object} inPointer The in pointer object.
*/
ol.pointer.TouchSource.prototype.overDown_ = function(browserEvent, inPointer) {
this.pointerMap[inPointer.pointerId] = {
@@ -48734,7 +39639,7 @@ ol.pointer.TouchSource.prototype.overDown_ = function(browserEvent, inPointer) {
/**
* Handler for `touchmove`.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.TouchSource.prototype.touchmove = function(inEvent) {
inEvent.preventDefault();
@@ -48744,11 +39649,10 @@ ol.pointer.TouchSource.prototype.touchmove = function(inEvent) {
/**
* @private
- * @param {goog.events.BrowserEvent} browserEvent
- * @param {Object} inPointer
+ * @param {Event} browserEvent The event.
+ * @param {Object} inPointer The in pointer.
*/
-ol.pointer.TouchSource.prototype.moveOverOut_ =
- function(browserEvent, inPointer) {
+ol.pointer.TouchSource.prototype.moveOverOut_ = function(browserEvent, inPointer) {
var event = inPointer;
var pointer = this.pointerMap[event.pointerId];
// a finger drifted off the screen, ignore it
@@ -48782,7 +39686,7 @@ ol.pointer.TouchSource.prototype.moveOverOut_ =
* Handler for `touchend`, triggers `pointerup`,
* `pointerout` and `pointerleave` events.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The event.
*/
ol.pointer.TouchSource.prototype.touchend = function(inEvent) {
this.dedupSynthMouse_(inEvent);
@@ -48792,8 +39696,8 @@ ol.pointer.TouchSource.prototype.touchend = function(inEvent) {
/**
* @private
- * @param {goog.events.BrowserEvent} browserEvent
- * @param {Object} inPointer
+ * @param {Event} browserEvent An event.
+ * @param {Object} inPointer The inPointer object.
*/
ol.pointer.TouchSource.prototype.upOut_ = function(browserEvent, inPointer) {
this.dispatcher.up(inPointer, browserEvent);
@@ -48807,7 +39711,7 @@ ol.pointer.TouchSource.prototype.upOut_ = function(browserEvent, inPointer) {
* Handler for `touchcancel`, triggers `pointercancel`,
* `pointerout` and `pointerleave` events.
*
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.TouchSource.prototype.touchcancel = function(inEvent) {
this.processTouches_(inEvent, this.cancelOut_);
@@ -48816,11 +39720,10 @@ ol.pointer.TouchSource.prototype.touchcancel = function(inEvent) {
/**
* @private
- * @param {goog.events.BrowserEvent} browserEvent
- * @param {Object} inPointer
+ * @param {Event} browserEvent The event.
+ * @param {Object} inPointer The in pointer.
*/
-ol.pointer.TouchSource.prototype.cancelOut_ =
- function(browserEvent, inPointer) {
+ol.pointer.TouchSource.prototype.cancelOut_ = function(browserEvent, inPointer) {
this.dispatcher.cancel(inPointer, browserEvent);
this.dispatcher.out(inPointer, browserEvent);
this.dispatcher.leave(inPointer, browserEvent);
@@ -48830,7 +39733,7 @@ ol.pointer.TouchSource.prototype.cancelOut_ =
/**
* @private
- * @param {Object} inPointer
+ * @param {Object} inPointer The inPointer object.
*/
ol.pointer.TouchSource.prototype.cleanUpPointer_ = function(inPointer) {
delete this.pointerMap[inPointer.pointerId];
@@ -48842,20 +39745,20 @@ ol.pointer.TouchSource.prototype.cleanUpPointer_ = function(inPointer) {
* Prevent synth mouse events from creating pointer events.
*
* @private
- * @param {goog.events.BrowserEvent} inEvent
+ * @param {Event} inEvent The in event.
*/
ol.pointer.TouchSource.prototype.dedupSynthMouse_ = function(inEvent) {
var lts = this.mouseSource.lastTouches;
- var t = inEvent.getBrowserEvent().changedTouches[0];
+ var t = inEvent.changedTouches[0];
// only the primary finger will synth mouse events
if (this.isPrimaryTouch_(t)) {
// remember x/y of last touch
- var lt = /** @type {ol.Pixel} */ ([t.clientX, t.clientY]);
+ var lt = [t.clientX, t.clientY];
lts.push(lt);
- goog.global.setTimeout(function() {
+ ol.global.setTimeout(function() {
// remove touch after timeout
- goog.array.remove(lts, lt);
+ ol.array.remove(lts, lt);
}, ol.pointer.TouchSource.DEDUP_TIMEOUT);
}
};
@@ -48893,9 +39796,8 @@ ol.pointer.TouchSource.prototype.dedupSynthMouse_ = function(inEvent) {
goog.provide('ol.pointer.PointerEventHandler');
goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.BrowserEvent');
-goog.require('goog.events.EventTarget');
+goog.require('ol.events');
+goog.require('ol.events.EventTarget');
goog.require('ol.has');
goog.require('ol.pointer.MouseSource');
@@ -48905,10 +39807,9 @@ goog.require('ol.pointer.PointerEvent');
goog.require('ol.pointer.TouchSource');
-
/**
* @constructor
- * @extends {goog.events.EventTarget}
+ * @extends {ol.events.EventTarget}
* @param {Element|HTMLDocument} element Viewport element.
*/
ol.pointer.PointerEventHandler = function(element) {
@@ -48923,12 +39824,12 @@ ol.pointer.PointerEventHandler = function(element) {
/**
* @const
- * @type {!Object.<string, goog.events.BrowserEvent|Object>}
+ * @type {!Object.<string, Event|Object>}
*/
this.pointerMap = {};
/**
- * @type {Object.<string, function(goog.events.BrowserEvent)>}
+ * @type {Object.<string, function(Event)>}
* @private
*/
this.eventMap_ = {};
@@ -48941,7 +39842,7 @@ ol.pointer.PointerEventHandler = function(element) {
this.registerSources();
};
-goog.inherits(ol.pointer.PointerEventHandler, goog.events.EventTarget);
+goog.inherits(ol.pointer.PointerEventHandler, ol.events.EventTarget);
/**
@@ -48972,10 +39873,9 @@ ol.pointer.PointerEventHandler.prototype.registerSources = function() {
* Add a new event source that will generate pointer events.
*
* @param {string} name A name for the event source
- * @param {ol.pointer.EventSource} source
+ * @param {ol.pointer.EventSource} source The source event.
*/
-ol.pointer.PointerEventHandler.prototype.registerSource =
- function(name, source) {
+ol.pointer.PointerEventHandler.prototype.registerSource = function(name, source) {
var s = source;
var newEvents = s.getEvents();
@@ -48984,7 +39884,7 @@ ol.pointer.PointerEventHandler.prototype.registerSource =
var handler = s.getHandlerForEvent(e);
if (handler) {
- this.eventMap_[e] = goog.bind(handler, s);
+ this.eventMap_[e] = handler.bind(s);
}
}, this);
this.eventSourceList_.push(s);
@@ -49023,7 +39923,7 @@ ol.pointer.PointerEventHandler.prototype.unregister_ = function() {
/**
* Calls the right handler for a new event.
* @private
- * @param {goog.events.BrowserEvent} inEvent Browser event.
+ * @param {Event} inEvent Browser event.
*/
ol.pointer.PointerEventHandler.prototype.eventHandler_ = function(inEvent) {
var type = inEvent.type;
@@ -49041,8 +39941,7 @@ ol.pointer.PointerEventHandler.prototype.eventHandler_ = function(inEvent) {
*/
ol.pointer.PointerEventHandler.prototype.addEvents_ = function(events) {
events.forEach(function(eventName) {
- goog.events.listen(this.element_, eventName,
- this.eventHandler_, false, this);
+ ol.events.listen(this.element_, eventName, this.eventHandler_, this);
}, this);
};
@@ -49054,8 +39953,7 @@ ol.pointer.PointerEventHandler.prototype.addEvents_ = function(events) {
*/
ol.pointer.PointerEventHandler.prototype.removeEvents_ = function(events) {
events.forEach(function(e) {
- goog.events.unlisten(this.element_, e,
- this.eventHandler_, false, this);
+ ol.events.unlisten(this.element_, e, this.eventHandler_, this);
}, this);
};
@@ -49063,21 +39961,17 @@ ol.pointer.PointerEventHandler.prototype.removeEvents_ = function(events) {
/**
* Returns a snapshot of inEvent, with writable properties.
*
- * @param {goog.events.BrowserEvent} browserEvent Browser event.
+ * @param {Event} event Browser event.
* @param {Event|Touch} inEvent An event that contains
* properties to copy.
* @return {Object} An object containing shallow copies of
* `inEvent`'s properties.
*/
-ol.pointer.PointerEventHandler.prototype.cloneEvent =
- function(browserEvent, inEvent) {
+ol.pointer.PointerEventHandler.prototype.cloneEvent = function(event, inEvent) {
var eventCopy = {}, p;
for (var i = 0, ii = ol.pointer.CLONE_PROPS.length; i < ii; i++) {
p = ol.pointer.CLONE_PROPS[i][0];
- eventCopy[p] =
- browserEvent[p] ||
- inEvent[p] ||
- ol.pointer.CLONE_PROPS[i][1];
+ eventCopy[p] = event[p] || inEvent[p] || ol.pointer.CLONE_PROPS[i][1];
}
return eventCopy;
@@ -49089,145 +39983,122 @@ ol.pointer.PointerEventHandler.prototype.cloneEvent =
/**
* Triggers a 'pointerdown' event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.down =
- function(pointerEventData, browserEvent) {
- this.fireEvent(ol.pointer.EventType.POINTERDOWN,
- pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.down = function(data, event) {
+ this.fireEvent(ol.pointer.EventType.POINTERDOWN, data, event);
};
/**
* Triggers a 'pointermove' event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.move =
- function(pointerEventData, browserEvent) {
- this.fireEvent(ol.pointer.EventType.POINTERMOVE,
- pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.move = function(data, event) {
+ this.fireEvent(ol.pointer.EventType.POINTERMOVE, data, event);
};
/**
* Triggers a 'pointerup' event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.up =
- function(pointerEventData, browserEvent) {
- this.fireEvent(ol.pointer.EventType.POINTERUP,
- pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.up = function(data, event) {
+ this.fireEvent(ol.pointer.EventType.POINTERUP, data, event);
};
/**
* Triggers a 'pointerenter' event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.enter =
- function(pointerEventData, browserEvent) {
- pointerEventData.bubbles = false;
- this.fireEvent(ol.pointer.EventType.POINTERENTER,
- pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.enter = function(data, event) {
+ data.bubbles = false;
+ this.fireEvent(ol.pointer.EventType.POINTERENTER, data, event);
};
/**
* Triggers a 'pointerleave' event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.leave =
- function(pointerEventData, browserEvent) {
- pointerEventData.bubbles = false;
- this.fireEvent(ol.pointer.EventType.POINTERLEAVE,
- pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.leave = function(data, event) {
+ data.bubbles = false;
+ this.fireEvent(ol.pointer.EventType.POINTERLEAVE, data, event);
};
/**
* Triggers a 'pointerover' event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.over =
- function(pointerEventData, browserEvent) {
- pointerEventData.bubbles = true;
- this.fireEvent(ol.pointer.EventType.POINTEROVER,
- pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.over = function(data, event) {
+ data.bubbles = true;
+ this.fireEvent(ol.pointer.EventType.POINTEROVER, data, event);
};
/**
* Triggers a 'pointerout' event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.out =
- function(pointerEventData, browserEvent) {
- pointerEventData.bubbles = true;
- this.fireEvent(ol.pointer.EventType.POINTEROUT,
- pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.out = function(data, event) {
+ data.bubbles = true;
+ this.fireEvent(ol.pointer.EventType.POINTEROUT, data, event);
};
/**
* Triggers a 'pointercancel' event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.cancel =
- function(pointerEventData, browserEvent) {
- this.fireEvent(ol.pointer.EventType.POINTERCANCEL,
- pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.cancel = function(data, event) {
+ this.fireEvent(ol.pointer.EventType.POINTERCANCEL, data, event);
};
/**
* Triggers a combination of 'pointerout' and 'pointerleave' events.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.leaveOut =
- function(pointerEventData, browserEvent) {
- this.out(pointerEventData, browserEvent);
- if (!this.contains_(
- pointerEventData.target,
- pointerEventData.relatedTarget)) {
- this.leave(pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.leaveOut = function(data, event) {
+ this.out(data, event);
+ if (!this.contains_(data.target, data.relatedTarget)) {
+ this.leave(data, event);
}
};
/**
* Triggers a combination of 'pointerover' and 'pointerevents' events.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.enterOver =
- function(pointerEventData, browserEvent) {
- this.over(pointerEventData, browserEvent);
- if (!this.contains_(
- pointerEventData.target,
- pointerEventData.relatedTarget)) {
- this.enter(pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.enterOver = function(data, event) {
+ this.over(data, event);
+ if (!this.contains_(data.target, data.relatedTarget)) {
+ this.enter(data, event);
}
};
/**
* @private
- * @param {Element} container
- * @param {Element} contained
+ * @param {Element} container The container element.
+ * @param {Element} contained The contained element.
* @return {boolean} Returns true if the container element
* contains the other element.
*/
-ol.pointer.PointerEventHandler.prototype.contains_ =
- function(container, contained) {
+ol.pointer.PointerEventHandler.prototype.contains_ = function(container, contained) {
if (!contained) {
return false;
}
@@ -49238,28 +40109,26 @@ ol.pointer.PointerEventHandler.prototype.contains_ =
// EVENT CREATION AND TRACKING
/**
* Creates a new Event of type `inType`, based on the information in
- * `pointerEventData`.
+ * `data`.
*
* @param {string} inType A string representing the type of event to create.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
* @return {ol.pointer.PointerEvent} A PointerEvent of type `inType`.
*/
-ol.pointer.PointerEventHandler.prototype.makeEvent =
- function(inType, pointerEventData, browserEvent) {
- return new ol.pointer.PointerEvent(inType, browserEvent, pointerEventData);
+ol.pointer.PointerEventHandler.prototype.makeEvent = function(inType, data, event) {
+ return new ol.pointer.PointerEvent(inType, event, data);
};
/**
* Make and dispatch an event in one call.
* @param {string} inType A string representing the type of event.
- * @param {Object} pointerEventData
- * @param {goog.events.BrowserEvent} browserEvent
+ * @param {Object} data Pointer event data.
+ * @param {Event} event The event.
*/
-ol.pointer.PointerEventHandler.prototype.fireEvent =
- function(inType, pointerEventData, browserEvent) {
- var e = this.makeEvent(inType, pointerEventData, browserEvent);
+ol.pointer.PointerEventHandler.prototype.fireEvent = function(inType, data, event) {
+ var e = this.makeEvent(inType, data, event);
this.dispatchEvent(e);
};
@@ -49267,12 +40136,10 @@ ol.pointer.PointerEventHandler.prototype.fireEvent =
/**
* Creates a pointer event from a native pointer event
* and dispatches this event.
- * @param {goog.events.BrowserEvent} nativeEvent A platform event with a target.
+ * @param {Event} event A platform event with a target.
*/
-ol.pointer.PointerEventHandler.prototype.fireNativeEvent =
- function(nativeEvent) {
- var e = this.makeEvent(nativeEvent.type, nativeEvent.getBrowserEvent(),
- nativeEvent);
+ol.pointer.PointerEventHandler.prototype.fireNativeEvent = function(event) {
+ var e = this.makeEvent(event.type, event, event);
this.dispatchEvent(e);
};
@@ -49281,16 +40148,12 @@ ol.pointer.PointerEventHandler.prototype.fireNativeEvent =
* Wrap a native mouse event into a pointer event.
* This proxy method is required for the legacy IE support.
* @param {string} eventType The pointer event type.
- * @param {goog.events.BrowserEvent} browserEvent
- * @return {ol.pointer.PointerEvent}
+ * @param {Event} event The event.
+ * @return {ol.pointer.PointerEvent} The wrapped event.
*/
-ol.pointer.PointerEventHandler.prototype.wrapMouseEvent =
- function(eventType, browserEvent) {
+ol.pointer.PointerEventHandler.prototype.wrapMouseEvent = function(eventType, event) {
var pointerEvent = this.makeEvent(
- eventType,
- ol.pointer.MouseSource.prepareEvent(browserEvent, this),
- browserEvent
- );
+ eventType, ol.pointer.MouseSource.prepareEvent(event, this), event);
return pointerEvent;
};
@@ -49365,20 +40228,15 @@ goog.provide('ol.MapBrowserEventHandler');
goog.provide('ol.MapBrowserPointerEvent');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.BrowserEvent');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('ol');
-goog.require('ol.Coordinate');
goog.require('ol.MapEvent');
-goog.require('ol.Pixel');
+goog.require('ol.events');
+goog.require('ol.events.EventTarget');
+goog.require('ol.events.EventType');
goog.require('ol.pointer.PointerEvent');
goog.require('ol.pointer.PointerEventHandler');
-
/**
* @classdesc
* Events emitted as map browser events are instances of this type.
@@ -49389,7 +40247,7 @@ goog.require('ol.pointer.PointerEventHandler');
* @implements {oli.MapBrowserEvent}
* @param {string} type Event type.
* @param {ol.Map} map Map.
- * @param {goog.events.BrowserEvent} browserEvent Browser event.
+ * @param {Event} browserEvent Browser event.
* @param {boolean=} opt_dragging Is the map currently being dragged?
* @param {?olx.FrameState=} opt_frameState Frame state.
*/
@@ -49399,25 +40257,19 @@ ol.MapBrowserEvent = function(type, map, browserEvent, opt_dragging,
goog.base(this, type, map, opt_frameState);
/**
- * @const
- * @type {goog.events.BrowserEvent}
- */
- this.browserEvent = browserEvent;
-
- /**
* The original browser event.
* @const
* @type {Event}
* @api stable
*/
- this.originalEvent = browserEvent.getBrowserEvent();
+ this.originalEvent = browserEvent;
/**
* The pixel of the original browser event.
* @type {ol.Pixel}
* @api stable
*/
- this.pixel = map.getEventPixel(this.originalEvent);
+ this.pixel = map.getEventPixel(browserEvent);
/**
* The coordinate of the original browser event.
@@ -49447,7 +40299,7 @@ goog.inherits(ol.MapBrowserEvent, ol.MapEvent);
*/
ol.MapBrowserEvent.prototype.preventDefault = function() {
goog.base(this, 'preventDefault');
- this.browserEvent.preventDefault();
+ this.originalEvent.preventDefault();
};
@@ -49459,11 +40311,10 @@ ol.MapBrowserEvent.prototype.preventDefault = function() {
*/
ol.MapBrowserEvent.prototype.stopPropagation = function() {
goog.base(this, 'stopPropagation');
- this.browserEvent.stopPropagation();
+ this.originalEvent.stopPropagation();
};
-
/**
* @constructor
* @extends {ol.MapBrowserEvent}
@@ -49476,7 +40327,7 @@ ol.MapBrowserEvent.prototype.stopPropagation = function() {
ol.MapBrowserPointerEvent = function(type, map, pointerEvent, opt_dragging,
opt_frameState) {
- goog.base(this, type, map, pointerEvent.browserEvent, opt_dragging,
+ goog.base(this, type, map, pointerEvent.originalEvent, opt_dragging,
opt_frameState);
/**
@@ -49489,11 +40340,10 @@ ol.MapBrowserPointerEvent = function(type, map, pointerEvent, opt_dragging,
goog.inherits(ol.MapBrowserPointerEvent, ol.MapBrowserEvent);
-
/**
* @param {ol.Map} map The map with the viewport to listen to events on.
* @constructor
- * @extends {goog.events.EventTarget}
+ * @extends {ol.events.EventTarget}
*/
ol.MapBrowserEventHandler = function(map) {
@@ -49519,16 +40369,10 @@ ol.MapBrowserEventHandler = function(map) {
this.dragging_ = false;
/**
- * @type {Array.<goog.events.Key>}
- * @private
- */
- this.dragListenerKeys_ = null;
-
- /**
- * @type {goog.events.Key}
+ * @type {!Array.<ol.events.Key>}
* @private
*/
- this.pointerdownListenerKey_ = null;
+ this.dragListenerKeys_ = [];
/**
* The most recent "down" type event (or null if none have occurred).
@@ -49547,7 +40391,7 @@ ol.MapBrowserEventHandler = function(map) {
this.activePointers_ = 0;
/**
- * @type {Object.<number, boolean>}
+ * @type {!Object.<number, boolean>}
* @private
*/
this.trackedTouches_ = {};
@@ -49570,16 +40414,24 @@ ol.MapBrowserEventHandler = function(map) {
*/
this.documentPointerEventHandler_ = null;
- this.pointerdownListenerKey_ = goog.events.listen(this.pointerEventHandler_,
+ /**
+ * @type {?ol.events.Key}
+ * @private
+ */
+ this.pointerdownListenerKey_ = ol.events.listen(this.pointerEventHandler_,
ol.pointer.EventType.POINTERDOWN,
- this.handlePointerDown_, false, this);
+ this.handlePointerDown_, this);
- this.relayedListenerKey_ = goog.events.listen(this.pointerEventHandler_,
+ /**
+ * @type {?ol.events.Key}
+ * @private
+ */
+ this.relayedListenerKey_ = ol.events.listen(this.pointerEventHandler_,
ol.pointer.EventType.POINTERMOVE,
- this.relayEvent_, false, this);
+ this.relayEvent_, this);
};
-goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget);
+goog.inherits(ol.MapBrowserEventHandler, ol.events.EventTarget);
/**
@@ -49593,19 +40445,19 @@ ol.MapBrowserEventHandler.prototype.emulateClick_ = function(pointerEvent) {
this.dispatchEvent(newEvent);
if (this.clickTimeoutId_ !== 0) {
// double-click
- goog.global.clearTimeout(this.clickTimeoutId_);
+ ol.global.clearTimeout(this.clickTimeoutId_);
this.clickTimeoutId_ = 0;
newEvent = new ol.MapBrowserPointerEvent(
ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
} else {
// click
- this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
+ this.clickTimeoutId_ = ol.global.setTimeout(function() {
this.clickTimeoutId_ = 0;
var newEvent = new ol.MapBrowserPointerEvent(
ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
- }, this), 250);
+ }.bind(this), 250);
}
};
@@ -49616,8 +40468,7 @@ ol.MapBrowserEventHandler.prototype.emulateClick_ = function(pointerEvent) {
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @private
*/
-ol.MapBrowserEventHandler.prototype.updateActivePointers_ =
- function(pointerEvent) {
+ol.MapBrowserEventHandler.prototype.updateActivePointers_ = function(pointerEvent) {
var event = pointerEvent;
if (event.type == ol.MapBrowserEvent.EventType.POINTERUP ||
@@ -49626,7 +40477,7 @@ ol.MapBrowserEventHandler.prototype.updateActivePointers_ =
} else if (event.type == ol.MapBrowserEvent.EventType.POINTERDOWN) {
this.trackedTouches_[event.pointerId] = true;
}
- this.activePointers_ = goog.object.getCount(this.trackedTouches_);
+ this.activePointers_ = Object.keys(this.trackedTouches_).length;
};
@@ -49652,11 +40503,11 @@ ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(pointerEvent) {
goog.asserts.assert(this.activePointers_ >= 0,
'this.activePointers_ should be equal to or larger than 0');
if (this.activePointers_ === 0) {
- this.dragListenerKeys_.forEach(goog.events.unlistenByKey);
- this.dragListenerKeys_ = null;
+ this.dragListenerKeys_.forEach(ol.events.unlistenByKey);
+ this.dragListenerKeys_.length = 0;
this.dragging_ = false;
this.down_ = null;
- goog.dispose(this.documentPointerEventHandler_);
+ this.documentPointerEventHandler_.dispose();
this.documentPointerEventHandler_ = null;
}
};
@@ -49667,8 +40518,7 @@ ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(pointerEvent) {
* @return {boolean} If the left mouse button was pressed.
* @private
*/
-ol.MapBrowserEventHandler.prototype.isMouseActionButton_ =
- function(pointerEvent) {
+ol.MapBrowserEventHandler.prototype.isMouseActionButton_ = function(pointerEvent) {
return pointerEvent.button === 0;
};
@@ -49677,8 +40527,7 @@ ol.MapBrowserEventHandler.prototype.isMouseActionButton_ =
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @private
*/
-ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
- function(pointerEvent) {
+ol.MapBrowserEventHandler.prototype.handlePointerDown_ = function(pointerEvent) {
this.updateActivePointers_(pointerEvent);
var newEvent = new ol.MapBrowserPointerEvent(
ol.MapBrowserEvent.EventType.POINTERDOWN, this.map_, pointerEvent);
@@ -49686,7 +40535,7 @@ ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
this.down_ = pointerEvent;
- if (!this.dragListenerKeys_) {
+ if (this.dragListenerKeys_.length === 0) {
/* Set up a pointer event handler on the `document`,
* which is required when the pointer is moved outside
* the viewport when dragging.
@@ -49694,13 +40543,13 @@ ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
this.documentPointerEventHandler_ =
new ol.pointer.PointerEventHandler(document);
- this.dragListenerKeys_ = [
- goog.events.listen(this.documentPointerEventHandler_,
+ this.dragListenerKeys_.push(
+ ol.events.listen(this.documentPointerEventHandler_,
ol.MapBrowserEvent.EventType.POINTERMOVE,
- this.handlePointerMove_, false, this),
- goog.events.listen(this.documentPointerEventHandler_,
+ this.handlePointerMove_, this),
+ ol.events.listen(this.documentPointerEventHandler_,
ol.MapBrowserEvent.EventType.POINTERUP,
- this.handlePointerUp_, false, this),
+ this.handlePointerUp_, this),
/* Note that the listener for `pointercancel is set up on
* `pointerEventHandler_` and not `documentPointerEventHandler_` like
* the `pointerup` and `pointermove` listeners.
@@ -49714,10 +40563,10 @@ ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
* only receive a `touchcancel` from `pointerEventHandler_`, because it is
* only registered there.
*/
- goog.events.listen(this.pointerEventHandler_,
+ ol.events.listen(this.pointerEventHandler_,
ol.MapBrowserEvent.EventType.POINTERCANCEL,
- this.handlePointerUp_, false, this)
- ];
+ this.handlePointerUp_, this)
+ );
}
};
@@ -49726,8 +40575,7 @@ ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @private
*/
-ol.MapBrowserEventHandler.prototype.handlePointerMove_ =
- function(pointerEvent) {
+ol.MapBrowserEventHandler.prototype.handlePointerMove_ = function(pointerEvent) {
// Fix IE10 on windows Surface : When you tap the tablet, it triggers
// multiple pointermove events between pointerdown and pointerup with
// the exact same coordinates of the pointerdown event. To avoid a
@@ -49764,7 +40612,7 @@ ol.MapBrowserEventHandler.prototype.relayEvent_ = function(pointerEvent) {
/**
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
- * @return {boolean}
+ * @return {boolean} Is moving.
* @private
*/
ol.MapBrowserEventHandler.prototype.isMoving_ = function(pointerEvent) {
@@ -49778,23 +40626,23 @@ ol.MapBrowserEventHandler.prototype.isMoving_ = function(pointerEvent) {
*/
ol.MapBrowserEventHandler.prototype.disposeInternal = function() {
if (this.relayedListenerKey_) {
- goog.events.unlistenByKey(this.relayedListenerKey_);
+ ol.events.unlistenByKey(this.relayedListenerKey_);
this.relayedListenerKey_ = null;
}
if (this.pointerdownListenerKey_) {
- goog.events.unlistenByKey(this.pointerdownListenerKey_);
+ ol.events.unlistenByKey(this.pointerdownListenerKey_);
this.pointerdownListenerKey_ = null;
}
- if (this.dragListenerKeys_) {
- this.dragListenerKeys_.forEach(goog.events.unlistenByKey);
- this.dragListenerKeys_ = null;
- }
+
+ this.dragListenerKeys_.forEach(ol.events.unlistenByKey);
+ this.dragListenerKeys_.length = 0;
+
if (this.documentPointerEventHandler_) {
- goog.dispose(this.documentPointerEventHandler_);
+ this.documentPointerEventHandler_.dispose();
this.documentPointerEventHandler_ = null;
}
if (this.pointerEventHandler_) {
- goog.dispose(this.pointerEventHandler_);
+ this.pointerEventHandler_.dispose();
this.pointerEventHandler_ = null;
}
goog.base(this, 'disposeInternal');
@@ -49820,14 +40668,14 @@ ol.MapBrowserEvent.EventType = {
* @event ol.MapBrowserEvent#click
* @api stable
*/
- CLICK: goog.events.EventType.CLICK,
+ CLICK: ol.events.EventType.CLICK,
/**
* A true double click, with no dragging.
* @event ol.MapBrowserEvent#dblclick
* @api stable
*/
- DBLCLICK: goog.events.EventType.DBLCLICK,
+ DBLCLICK: ol.events.EventType.DBLCLICK,
/**
* Triggered when a pointer is dragged.
@@ -49855,12 +40703,11 @@ ol.MapBrowserEvent.EventType = {
goog.provide('ol.layer.Base');
goog.provide('ol.layer.LayerProperty');
-goog.provide('ol.layer.LayerState');
-goog.require('goog.object');
goog.require('ol');
goog.require('ol.Object');
goog.require('ol.math');
+goog.require('ol.object');
goog.require('ol.source.State');
@@ -49879,21 +40726,6 @@ ol.layer.LayerProperty = {
/**
- * @typedef {{layer: ol.layer.Layer,
- * opacity: number,
- * sourceState: ol.source.State,
- * visible: boolean,
- * managed: boolean,
- * extent: (ol.Extent|undefined),
- * zIndex: number,
- * maxResolution: number,
- * minResolution: number}}
- */
-ol.layer.LayerState;
-
-
-
-/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
* instantiated in apps.
@@ -49913,7 +40745,7 @@ ol.layer.Base = function(options) {
/**
* @type {Object.<string, *>}
*/
- var properties = goog.object.clone(options);
+ var properties = ol.object.assign({}, options);
properties[ol.layer.LayerProperty.OPACITY] =
options.opacity !== undefined ? options.opacity : 1;
properties[ol.layer.LayerProperty.VISIBLE] =
@@ -49931,7 +40763,7 @@ goog.inherits(ol.layer.Base, ol.Object);
/**
- * @return {ol.layer.LayerState} Layer state.
+ * @return {ol.LayerState} Layer state.
*/
ol.layer.Base.prototype.getLayerState = function() {
var opacity = this.getOpacity();
@@ -49964,9 +40796,9 @@ ol.layer.Base.prototype.getLayersArray = goog.abstractMethod;
/**
- * @param {Array.<ol.layer.LayerState>=} opt_states Optional list of layer
+ * @param {Array.<ol.LayerState>=} opt_states Optional list of layer
* states (to be modified in place).
- * @return {Array.<ol.layer.LayerState>} List of layer states.
+ * @return {Array.<ol.LayerState>} List of layer states.
*/
ol.layer.Base.prototype.getLayerStatesArray = goog.abstractMethod;
@@ -50118,7 +40950,6 @@ ol.layer.Base.prototype.setZIndex = function(zindex) {
goog.provide('ol.render.VectorContext');
-
/**
* Context for drawing geometries. A vector context is available on render
* events and does not need to be constructed directly.
@@ -50131,17 +40962,26 @@ ol.render.VectorContext = function() {
/**
- * @param {number} zIndex Z index.
- * @param {function(ol.render.VectorContext)} callback Callback.
+ * Render a geometry.
+ *
+ * @param {ol.geom.Geometry} geometry The geometry to render.
+ */
+ol.render.VectorContext.prototype.drawGeometry = goog.abstractMethod;
+
+
+/**
+ * Set the rendering style.
+ *
+ * @param {ol.style.Style} style The rendering style.
*/
-ol.render.VectorContext.prototype.drawAsync = goog.abstractMethod;
+ol.render.VectorContext.prototype.setStyle = goog.abstractMethod;
/**
* @param {ol.geom.Circle} circleGeometry Circle geometry.
* @param {ol.Feature} feature Feature,
*/
-ol.render.VectorContext.prototype.drawCircleGeometry = goog.abstractMethod;
+ol.render.VectorContext.prototype.drawCircle = goog.abstractMethod;
/**
@@ -50156,8 +40996,7 @@ ol.render.VectorContext.prototype.drawFeature = goog.abstractMethod;
* collection.
* @param {ol.Feature} feature Feature.
*/
-ol.render.VectorContext.prototype.drawGeometryCollectionGeometry =
- goog.abstractMethod;
+ol.render.VectorContext.prototype.drawGeometryCollection = goog.abstractMethod;
/**
@@ -50165,8 +41004,7 @@ ol.render.VectorContext.prototype.drawGeometryCollectionGeometry =
* string geometry.
* @param {ol.Feature|ol.render.Feature} feature Feature.
*/
-ol.render.VectorContext.prototype.drawLineStringGeometry =
- goog.abstractMethod;
+ol.render.VectorContext.prototype.drawLineString = goog.abstractMethod;
/**
@@ -50174,8 +41012,7 @@ ol.render.VectorContext.prototype.drawLineStringGeometry =
* MultiLineString geometry.
* @param {ol.Feature|ol.render.Feature} feature Feature.
*/
-ol.render.VectorContext.prototype.drawMultiLineStringGeometry =
- goog.abstractMethod;
+ol.render.VectorContext.prototype.drawMultiLineString = goog.abstractMethod;
/**
@@ -50183,22 +41020,21 @@ ol.render.VectorContext.prototype.drawMultiLineStringGeometry =
* geometry.
* @param {ol.Feature|ol.render.Feature} feature Feature.
*/
-ol.render.VectorContext.prototype.drawMultiPointGeometry = goog.abstractMethod;
+ol.render.VectorContext.prototype.drawMultiPoint = goog.abstractMethod;
/**
* @param {ol.geom.MultiPolygon} multiPolygonGeometry MultiPolygon geometry.
* @param {ol.Feature} feature Feature.
*/
-ol.render.VectorContext.prototype.drawMultiPolygonGeometry =
- goog.abstractMethod;
+ol.render.VectorContext.prototype.drawMultiPolygon = goog.abstractMethod;
/**
* @param {ol.geom.Point|ol.render.Feature} pointGeometry Point geometry.
* @param {ol.Feature|ol.render.Feature} feature Feature.
*/
-ol.render.VectorContext.prototype.drawPointGeometry = goog.abstractMethod;
+ol.render.VectorContext.prototype.drawPoint = goog.abstractMethod;
/**
@@ -50206,7 +41042,7 @@ ol.render.VectorContext.prototype.drawPointGeometry = goog.abstractMethod;
* geometry.
* @param {ol.Feature|ol.render.Feature} feature Feature.
*/
-ol.render.VectorContext.prototype.drawPolygonGeometry = goog.abstractMethod;
+ol.render.VectorContext.prototype.drawPolygon = goog.abstractMethod;
/**
@@ -50241,7 +41077,7 @@ ol.render.VectorContext.prototype.setTextStyle = goog.abstractMethod;
goog.provide('ol.render.Event');
goog.provide('ol.render.EventType');
-goog.require('goog.events.Event');
+goog.require('ol.events.Event');
goog.require('ol.render.VectorContext');
@@ -50267,10 +41103,9 @@ ol.render.EventType = {
};
-
/**
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.render.Event}
* @param {ol.render.EventType} type Type.
* @param {Object=} opt_target Target.
@@ -50316,22 +41151,21 @@ ol.render.Event = function(
this.glContext = opt_glContext;
};
-goog.inherits(ol.render.Event, goog.events.Event);
+goog.inherits(ol.render.Event, ol.events.Event);
goog.provide('ol.layer.Layer');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol');
goog.require('ol.Object');
goog.require('ol.layer.Base');
goog.require('ol.layer.LayerProperty');
+goog.require('ol.object');
goog.require('ol.render.EventType');
goog.require('ol.source.State');
-
/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
@@ -50355,26 +41189,26 @@ goog.require('ol.source.State');
*/
ol.layer.Layer = function(options) {
- var baseOptions = goog.object.clone(options);
+ var baseOptions = ol.object.assign({}, options);
delete baseOptions.source;
- goog.base(this, /** @type {olx.layer.LayerOptions} */ (baseOptions));
+ goog.base(this, /** @type {olx.layer.BaseOptions} */ (baseOptions));
/**
* @private
- * @type {goog.events.Key}
+ * @type {?ol.events.Key}
*/
this.mapPrecomposeKey_ = null;
/**
* @private
- * @type {goog.events.Key}
+ * @type {?ol.events.Key}
*/
this.mapRenderKey_ = null;
/**
* @private
- * @type {goog.events.Key}
+ * @type {?ol.events.Key}
*/
this.sourceChangeKey_ = null;
@@ -50382,9 +41216,9 @@ ol.layer.Layer = function(options) {
this.setMap(options.map);
}
- goog.events.listen(this,
+ ol.events.listen(this,
ol.Object.getChangeEventType(ol.layer.LayerProperty.SOURCE),
- this.handleSourcePropertyChange_, false, this);
+ this.handleSourcePropertyChange_, this);
var source = options.source ? options.source : null;
this.setSource(source);
@@ -50396,7 +41230,7 @@ goog.inherits(ol.layer.Layer, ol.layer.Base);
* Return `true` if the layer is visible, and if the passed resolution is
* between the layer's minResolution and maxResolution. The comparison is
* inclusive for `minResolution` and exclusive for `maxResolution`.
- * @param {ol.layer.LayerState} layerState Layer state.
+ * @param {ol.LayerState} layerState Layer state.
* @param {number} resolution Resolution.
* @return {boolean} The layer is visible at the given resolution.
*/
@@ -50460,13 +41294,13 @@ ol.layer.Layer.prototype.handleSourceChange_ = function() {
*/
ol.layer.Layer.prototype.handleSourcePropertyChange_ = function() {
if (this.sourceChangeKey_) {
- goog.events.unlistenByKey(this.sourceChangeKey_);
+ ol.events.unlistenByKey(this.sourceChangeKey_);
this.sourceChangeKey_ = null;
}
var source = this.getSource();
if (source) {
- this.sourceChangeKey_ = goog.events.listen(source,
- goog.events.EventType.CHANGE, this.handleSourceChange_, false, this);
+ this.sourceChangeKey_ = ol.events.listen(source,
+ ol.events.EventType.CHANGE, this.handleSourceChange_, this);
}
this.changed();
};
@@ -50485,24 +41319,28 @@ ol.layer.Layer.prototype.handleSourcePropertyChange_ = function() {
* @api
*/
ol.layer.Layer.prototype.setMap = function(map) {
- goog.events.unlistenByKey(this.mapPrecomposeKey_);
- this.mapPrecomposeKey_ = null;
+ if (this.mapPrecomposeKey_) {
+ ol.events.unlistenByKey(this.mapPrecomposeKey_);
+ this.mapPrecomposeKey_ = null;
+ }
if (!map) {
this.changed();
}
- goog.events.unlistenByKey(this.mapRenderKey_);
- this.mapRenderKey_ = null;
+ if (this.mapRenderKey_) {
+ ol.events.unlistenByKey(this.mapRenderKey_);
+ this.mapRenderKey_ = null;
+ }
if (map) {
- this.mapPrecomposeKey_ = goog.events.listen(
+ this.mapPrecomposeKey_ = ol.events.listen(
map, ol.render.EventType.PRECOMPOSE, function(evt) {
var layerState = this.getLayerState();
layerState.managed = false;
layerState.zIndex = Infinity;
evt.frameState.layerStatesArray.push(layerState);
evt.frameState.layerStates[goog.getUid(this)] = layerState;
- }, false, this);
- this.mapRenderKey_ = goog.events.listen(
- this, goog.events.EventType.CHANGE, map.render, false, map);
+ }, this);
+ this.mapRenderKey_ = ol.events.listen(
+ this, ol.events.EventType.CHANGE, map.render, map);
this.changed();
}
};
@@ -50522,10 +41360,9 @@ goog.provide('ol.ImageBase');
goog.provide('ol.ImageState');
goog.require('goog.asserts');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
+goog.require('ol.events.EventTarget');
+goog.require('ol.events.EventType');
goog.require('ol.Attribution');
-goog.require('ol.Extent');
/**
@@ -50539,10 +41376,9 @@ ol.ImageState = {
};
-
/**
* @constructor
- * @extends {goog.events.EventTarget}
+ * @extends {ol.events.EventTarget}
* @param {ol.Extent} extent Extent.
* @param {number|undefined} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
@@ -50584,14 +41420,14 @@ ol.ImageBase = function(extent, resolution, pixelRatio, state, attributions) {
this.state = state;
};
-goog.inherits(ol.ImageBase, goog.events.EventTarget);
+goog.inherits(ol.ImageBase, ol.events.EventTarget);
/**
* @protected
*/
ol.ImageBase.prototype.changed = function() {
- this.dispatchEvent(goog.events.EventType.CHANGE);
+ this.dispatchEvent(ol.events.EventType.CHANGE);
};
@@ -50742,10 +41578,10 @@ ol.vec.Mat4.multVec2 = function(mat, vec, resultVec) {
goog.provide('ol.renderer.Layer');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.functions');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol');
+goog.require('ol.functions');
goog.require('ol.ImageState');
goog.require('ol.Observable');
goog.require('ol.TileRange');
@@ -50754,11 +41590,9 @@ goog.require('ol.layer.Layer');
goog.require('ol.source.Source');
goog.require('ol.source.State');
goog.require('ol.source.Tile');
-goog.require('ol.tilecoord');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.Observable}
@@ -50800,14 +41634,13 @@ ol.renderer.Layer.prototype.forEachFeatureAtCoordinate = ol.nullFunction;
* @return {T|undefined} Callback result.
* @template S,T
*/
-ol.renderer.Layer.prototype.forEachLayerAtPixel =
- function(pixel, frameState, callback, thisArg) {
+ol.renderer.Layer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
var coordinate = pixel.slice();
ol.vec.Mat4.multVec2(
frameState.pixelToCoordinateMatrix, coordinate, coordinate);
var hasFeature = this.forEachFeatureAtCoordinate(
- coordinate, frameState, goog.functions.TRUE, this);
+ coordinate, frameState, ol.functions.TRUE, this);
if (hasFeature) {
return callback.call(thisArg, this.layer_);
@@ -50822,7 +41655,7 @@ ol.renderer.Layer.prototype.forEachLayerAtPixel =
* @param {olx.FrameState} frameState Frame state.
* @return {boolean} Is there a feature at the given coordinate?
*/
-ol.renderer.Layer.prototype.hasFeatureAtCoordinate = goog.functions.FALSE;
+ol.renderer.Layer.prototype.hasFeatureAtCoordinate = ol.functions.FALSE;
/**
@@ -50836,8 +41669,7 @@ ol.renderer.Layer.prototype.hasFeatureAtCoordinate = goog.functions.FALSE;
* lookup.
* @protected
*/
-ol.renderer.Layer.prototype.createLoadedTileFinder =
- function(source, projection, tiles) {
+ol.renderer.Layer.prototype.createLoadedTileFinder = function(source, projection, tiles) {
return (
/**
* @param {number} zoom Zoom level.
@@ -50845,13 +41677,13 @@ ol.renderer.Layer.prototype.createLoadedTileFinder =
* @return {boolean} The tile range is fully loaded.
*/
function(zoom, tileRange) {
- return source.forEachLoadedTile(projection, zoom,
- tileRange, function(tile) {
- if (!tiles[zoom]) {
- tiles[zoom] = {};
- }
- tiles[zoom][tile.tileCoord.toString()] = tile;
- });
+ function callback(tile) {
+ if (!tiles[zoom]) {
+ tiles[zoom] = {};
+ }
+ tiles[zoom][tile.tileCoord.toString()] = tile;
+ }
+ return source.forEachLoadedTile(projection, zoom, tileRange, callback);
});
};
@@ -50866,7 +41698,7 @@ ol.renderer.Layer.prototype.getLayer = function() {
/**
* Handle changes in image state.
- * @param {goog.events.Event} event Image change event.
+ * @param {ol.events.Event} event Image change event.
* @private
*/
ol.renderer.Layer.prototype.handleImageChange_ = function(event) {
@@ -50894,8 +41726,8 @@ ol.renderer.Layer.prototype.loadImage = function(image) {
goog.asserts.assert(imageState == ol.ImageState.IDLE ||
imageState == ol.ImageState.LOADING,
'imageState is "idle" or "loading"');
- goog.events.listen(image, goog.events.EventType.CHANGE,
- this.handleImageChange_, false, this);
+ ol.events.listen(image, ol.events.EventType.CHANGE,
+ this.handleImageChange_, this);
}
if (imageState == ol.ImageState.IDLE) {
image.load();
@@ -50924,21 +41756,22 @@ ol.renderer.Layer.prototype.renderIfReadyAndVisible = function() {
* @param {ol.source.Tile} tileSource Tile source.
* @protected
*/
-ol.renderer.Layer.prototype.scheduleExpireCache =
- function(frameState, tileSource) {
+ol.renderer.Layer.prototype.scheduleExpireCache = function(frameState, tileSource) {
if (tileSource.canExpireCache()) {
+ /**
+ * @param {ol.source.Tile} tileSource Tile source.
+ * @param {ol.Map} map Map.
+ * @param {olx.FrameState} frameState Frame state.
+ */
+ var postRenderFunction = function(tileSource, map, frameState) {
+ var tileSourceKey = goog.getUid(tileSource).toString();
+ tileSource.expireCache(frameState.viewState.projection,
+ frameState.usedTiles[tileSourceKey]);
+ }.bind(null, tileSource);
+
frameState.postRenderFunctions.push(
- goog.partial(
- /**
- * @param {ol.source.Tile} tileSource Tile source.
- * @param {ol.Map} map Map.
- * @param {olx.FrameState} frameState Frame state.
- */
- function(tileSource, map, frameState) {
- var tileSourceKey = goog.getUid(tileSource).toString();
- tileSource.expireCache(frameState.viewState.projection,
- frameState.usedTiles[tileSourceKey]);
- }, tileSource));
+ /** @type {ol.PostRenderFunction} */ (postRenderFunction)
+ );
}
};
@@ -50949,8 +41782,7 @@ ol.renderer.Layer.prototype.scheduleExpireCache =
* @param {Array.<ol.Attribution>} attributions Attributions (source).
* @protected
*/
-ol.renderer.Layer.prototype.updateAttributions =
- function(attributionsSet, attributions) {
+ol.renderer.Layer.prototype.updateAttributions = function(attributionsSet, attributions) {
if (attributions) {
var attribution, i, ii;
for (i = 0, ii = attributions.length; i < ii; ++i) {
@@ -50969,7 +41801,7 @@ ol.renderer.Layer.prototype.updateAttributions =
ol.renderer.Layer.prototype.updateLogos = function(frameState, source) {
var logo = source.getLogo();
if (logo !== undefined) {
- if (goog.isString(logo)) {
+ if (typeof logo === 'string') {
frameState.logos[logo] = '';
} else if (goog.isObject(logo)) {
goog.asserts.assertString(logo.href, 'logo.href is a string');
@@ -50987,8 +41819,7 @@ ol.renderer.Layer.prototype.updateLogos = function(frameState, source) {
* @param {ol.TileRange} tileRange Tile range.
* @protected
*/
-ol.renderer.Layer.prototype.updateUsedTiles =
- function(usedTiles, tileSource, z, tileRange) {
+ol.renderer.Layer.prototype.updateUsedTiles = function(usedTiles, tileSource, z, tileRange) {
// FIXME should we use tilesToDrawByZ instead?
var tileSourceKey = goog.getUid(tileSource).toString();
var zKey = z.toString();
@@ -51012,8 +41843,7 @@ ol.renderer.Layer.prototype.updateUsedTiles =
* @protected
* @return {ol.Coordinate} Snapped center.
*/
-ol.renderer.Layer.prototype.snapCenterToPixel =
- function(center, resolution, size) {
+ol.renderer.Layer.prototype.snapCenterToPixel = function(center, resolution, size) {
return [
resolution * (Math.round(center[0] / resolution) + (size[0] % 2) / 2),
resolution * (Math.round(center[1] / resolution) + (size[1] % 2) / 2)
@@ -51060,7 +41890,7 @@ ol.renderer.Layer.prototype.manageTilePyramid = function(
if (currentZ - z <= preload) {
tile = tileSource.getTile(z, x, y, pixelRatio, projection);
if (tile.getState() == ol.TileState.IDLE) {
- wantedTiles[ol.tilecoord.toString(tile.tileCoord)] = true;
+ wantedTiles[tile.tileCoord.toString()] = true;
if (!tileQueue.isKeyQueued(tile.getKey())) {
tileQueue.enqueue([tile, tileSourceKey,
tileGrid.getTileCoordCenter(tile.tileCoord), tileResolution]);
@@ -51093,17 +41923,6 @@ ol.style.ImageState = {
/**
- * @typedef {{opacity: number,
- * rotateWithView: boolean,
- * rotation: number,
- * scale: number,
- * snapToPixel: boolean}}
- */
-ol.style.ImageOptions;
-
-
-
-/**
* @classdesc
* A base class used for creating subclasses and not instantiated in
* apps. Base class for {@link ol.style.Icon}, {@link ol.style.Circle} and
@@ -51311,9 +42130,9 @@ ol.style.Image.prototype.setSnapToPixel = function(snapToPixel) {
/**
- * @param {function(this: T, goog.events.Event)} listener Listener function.
+ * @param {function(this: T, ol.events.Event)} listener Listener function.
* @param {T} thisArg Value to use as `this` when executing `listener`.
- * @return {goog.events.Key|undefined} Listener key.
+ * @return {ol.events.Key|undefined} Listener key.
* @template T
*/
ol.style.Image.prototype.listenImageChange = goog.abstractMethod;
@@ -51326,7 +42145,7 @@ ol.style.Image.prototype.load = goog.abstractMethod;
/**
- * @param {function(this: T, goog.events.Event)} listener Listener function.
+ * @param {function(this: T, ol.events.Event)} listener Listener function.
* @param {T} thisArg Value to use as `this` when executing `listener`.
* @template T
*/
@@ -51338,9 +42157,10 @@ goog.provide('ol.style.IconImageCache');
goog.provide('ol.style.IconOrigin');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventTarget');
+goog.require('ol.events.EventType');
+goog.require('ol.color');
goog.require('ol.dom');
goog.require('ol.style.Image');
goog.require('ol.style.ImageState');
@@ -51370,7 +42190,6 @@ ol.style.IconOrigin = {
};
-
/**
* @classdesc
* Set icon style for vector features.
@@ -51441,9 +42260,6 @@ ol.style.Icon = function(opt_options) {
goog.asserts.assert(!(src !== undefined && image),
'image and src can not provided at the same time');
goog.asserts.assert(
- src === undefined || (src !== undefined && !imgSize),
- 'imgSize should not be set when src is provided');
- goog.asserts.assert(
!image || (image && imgSize),
'imgSize must be set when image is provided');
@@ -51460,11 +42276,17 @@ ol.style.Icon = function(opt_options) {
ol.style.ImageState.IDLE : ol.style.ImageState.LOADED;
/**
+ * @type {ol.Color}
+ */
+ var color = options.color !== undefined ? ol.color.asArray(options.color) :
+ null;
+
+ /**
* @private
* @type {ol.style.IconImage_}
*/
this.iconImage_ = ol.style.IconImage_.get(
- image, src, imgSize, crossOrigin, imageState);
+ image, src, imgSize, crossOrigin, imageState, color);
/**
* @private
@@ -51673,8 +42495,8 @@ ol.style.Icon.prototype.getSize = function() {
* @inheritDoc
*/
ol.style.Icon.prototype.listenImageChange = function(listener, thisArg) {
- return goog.events.listen(this.iconImage_, goog.events.EventType.CHANGE,
- listener, false, thisArg);
+ return ol.events.listen(this.iconImage_, ol.events.EventType.CHANGE,
+ listener, thisArg);
};
@@ -51694,12 +42516,11 @@ ol.style.Icon.prototype.load = function() {
* @inheritDoc
*/
ol.style.Icon.prototype.unlistenImageChange = function(listener, thisArg) {
- goog.events.unlisten(this.iconImage_, goog.events.EventType.CHANGE,
- listener, false, thisArg);
+ ol.events.unlisten(this.iconImage_, ol.events.EventType.CHANGE,
+ listener, thisArg);
};
-
/**
* @constructor
* @param {Image|HTMLCanvasElement} image Image.
@@ -51707,10 +42528,12 @@ ol.style.Icon.prototype.unlistenImageChange = function(listener, thisArg) {
* @param {ol.Size} size Size.
* @param {?string} crossOrigin Cross origin.
* @param {ol.style.ImageState} imageState Image state.
- * @extends {goog.events.EventTarget}
+ * @param {ol.Color} color Color.
+ * @extends {ol.events.EventTarget}
* @private
*/
-ol.style.IconImage_ = function(image, src, size, crossOrigin, imageState) {
+ol.style.IconImage_ = function(image, src, size, crossOrigin, imageState,
+ color) {
goog.base(this);
@@ -51732,7 +42555,21 @@ ol.style.IconImage_ = function(image, src, size, crossOrigin, imageState) {
/**
* @private
- * @type {Array.<goog.events.Key>}
+ * @type {HTMLCanvasElement}
+ */
+ this.canvas_ = color ?
+ /** @type {HTMLCanvasElement} */ (document.createElement('CANVAS')) :
+ null;
+
+ /**
+ * @private
+ * @type {ol.Color}
+ */
+ this.color_ = color;
+
+ /**
+ * @private
+ * @type {Array.<ol.events.Key>}
*/
this.imageListenerKeys_ = null;
@@ -51764,7 +42601,7 @@ ol.style.IconImage_ = function(image, src, size, crossOrigin, imageState) {
}
};
-goog.inherits(ol.style.IconImage_, goog.events.EventTarget);
+goog.inherits(ol.style.IconImage_, ol.events.EventTarget);
/**
@@ -51773,15 +42610,17 @@ goog.inherits(ol.style.IconImage_, goog.events.EventTarget);
* @param {ol.Size} size Size.
* @param {?string} crossOrigin Cross origin.
* @param {ol.style.ImageState} imageState Image state.
+ * @param {ol.Color} color Color.
* @return {ol.style.IconImage_} Icon image.
*/
-ol.style.IconImage_.get = function(image, src, size, crossOrigin, imageState) {
+ol.style.IconImage_.get = function(image, src, size, crossOrigin, imageState,
+ color) {
var iconImageCache = ol.style.IconImageCache.getInstance();
- var iconImage = iconImageCache.get(src, crossOrigin);
+ var iconImage = iconImageCache.get(src, crossOrigin, color);
if (!iconImage) {
iconImage = new ol.style.IconImage_(
- image, src, size, crossOrigin, imageState);
- iconImageCache.set(src, crossOrigin, iconImage);
+ image, src, size, crossOrigin, imageState, color);
+ iconImageCache.set(src, crossOrigin, color, iconImage);
}
return iconImage;
};
@@ -51805,7 +42644,7 @@ ol.style.IconImage_.prototype.determineTainting_ = function() {
* @private
*/
ol.style.IconImage_.prototype.dispatchChangeEvent_ = function() {
- this.dispatchEvent(goog.events.EventType.CHANGE);
+ this.dispatchEvent(ol.events.EventType.CHANGE);
};
@@ -51824,9 +42663,14 @@ ol.style.IconImage_.prototype.handleImageError_ = function() {
*/
ol.style.IconImage_.prototype.handleImageLoad_ = function() {
this.imageState_ = ol.style.ImageState.LOADED;
+ if (this.size_) {
+ this.image_.width = this.size_[0];
+ this.image_.height = this.size_[1];
+ }
this.size_ = [this.image_.width, this.image_.height];
this.unlistenImage_();
this.determineTainting_();
+ this.replaceColor_();
this.dispatchChangeEvent_();
};
@@ -51836,7 +42680,7 @@ ol.style.IconImage_.prototype.handleImageLoad_ = function() {
* @return {Image|HTMLCanvasElement} Image or Canvas element.
*/
ol.style.IconImage_.prototype.getImage = function(pixelRatio) {
- return this.image_;
+ return this.canvas_ ? this.canvas_ : this.image_;
};
@@ -51895,10 +42739,10 @@ ol.style.IconImage_.prototype.load = function() {
'no listener keys existing');
this.imageState_ = ol.style.ImageState.LOADING;
this.imageListenerKeys_ = [
- goog.events.listenOnce(this.image_, goog.events.EventType.ERROR,
- this.handleImageError_, false, this),
- goog.events.listenOnce(this.image_, goog.events.EventType.LOAD,
- this.handleImageLoad_, false, this)
+ ol.events.listenOnce(this.image_, ol.events.EventType.ERROR,
+ this.handleImageError_, this),
+ ol.events.listenOnce(this.image_, ol.events.EventType.LOAD,
+ this.handleImageLoad_, this)
];
try {
this.image_.src = this.src_;
@@ -51910,6 +42754,38 @@ ol.style.IconImage_.prototype.load = function() {
/**
+ * @private
+ */
+ol.style.IconImage_.prototype.replaceColor_ = function() {
+ if (this.tainting_ || this.color_ === null) {
+ return;
+ }
+
+ goog.asserts.assert(this.canvas_ !== null,
+ 'this.canvas_ must not be null');
+
+ this.canvas_.width = this.image_.width;
+ this.canvas_.height = this.image_.height;
+
+ var ctx = this.canvas_.getContext('2d');
+ ctx.drawImage(this.image_, 0, 0);
+
+ var imgData = ctx.getImageData(0, 0, this.image_.width, this.image_.height);
+ var data = imgData.data;
+ var r = this.color_[0] / 255.0;
+ var g = this.color_[1] / 255.0;
+ var b = this.color_[2] / 255.0;
+
+ for (var i = 0, ii = data.length; i < ii; i += 4) {
+ data[i] *= r;
+ data[i + 1] *= g;
+ data[i + 2] *= b;
+ }
+ ctx.putImageData(imgData, 0, 0);
+};
+
+
+/**
* Discards event handlers which listen for load completion or errors.
*
* @private
@@ -51917,12 +42793,11 @@ ol.style.IconImage_.prototype.load = function() {
ol.style.IconImage_.prototype.unlistenImage_ = function() {
goog.asserts.assert(this.imageListenerKeys_,
'we must have listeners registered');
- this.imageListenerKeys_.forEach(goog.events.unlistenByKey);
+ this.imageListenerKeys_.forEach(ol.events.unlistenByKey);
this.imageListenerKeys_ = null;
};
-
/**
* @constructor
*/
@@ -51953,12 +42828,14 @@ goog.addSingletonGetter(ol.style.IconImageCache);
/**
* @param {string} src Src.
* @param {?string} crossOrigin Cross origin.
+ * @param {ol.Color} color Color.
* @return {string} Cache key.
*/
-ol.style.IconImageCache.getKey = function(src, crossOrigin) {
+ol.style.IconImageCache.getKey = function(src, crossOrigin, color) {
goog.asserts.assert(crossOrigin !== undefined,
'argument crossOrigin must be defined');
- return crossOrigin + ':' + src;
+ var colorString = color ? ol.color.asString(color) : 'null';
+ return crossOrigin + ':' + src + ':' + colorString;
};
@@ -51980,7 +42857,7 @@ ol.style.IconImageCache.prototype.expire = function() {
var key, iconImage;
for (key in this.cache_) {
iconImage = this.cache_[key];
- if ((i++ & 3) === 0 && !goog.events.hasListener(iconImage)) {
+ if ((i++ & 3) === 0 && !iconImage.hasListener()) {
delete this.cache_[key];
--this.cacheSize_;
}
@@ -51992,10 +42869,11 @@ ol.style.IconImageCache.prototype.expire = function() {
/**
* @param {string} src Src.
* @param {?string} crossOrigin Cross origin.
+ * @param {ol.Color} color Color.
* @return {ol.style.IconImage_} Icon image.
*/
-ol.style.IconImageCache.prototype.get = function(src, crossOrigin) {
- var key = ol.style.IconImageCache.getKey(src, crossOrigin);
+ol.style.IconImageCache.prototype.get = function(src, crossOrigin, color) {
+ var key = ol.style.IconImageCache.getKey(src, crossOrigin, color);
return key in this.cache_ ? this.cache_[key] : null;
};
@@ -52003,10 +42881,12 @@ ol.style.IconImageCache.prototype.get = function(src, crossOrigin) {
/**
* @param {string} src Src.
* @param {?string} crossOrigin Cross origin.
+ * @param {ol.Color} color Color.
* @param {ol.style.IconImage_} iconImage Icon image.
*/
-ol.style.IconImageCache.prototype.set = function(src, crossOrigin, iconImage) {
- var key = ol.style.IconImageCache.getKey(src, crossOrigin);
+ol.style.IconImageCache.prototype.set = function(src, crossOrigin, color,
+ iconImage) {
+ var key = ol.style.IconImageCache.getKey(src, crossOrigin, color);
this.cache_[key] = iconImage;
++this.cacheSize_;
};
@@ -52014,16 +42894,14 @@ ol.style.IconImageCache.prototype.set = function(src, crossOrigin, iconImage) {
goog.provide('ol.RendererType');
goog.provide('ol.renderer.Map');
-goog.require('goog.Disposable');
goog.require('goog.asserts');
-goog.require('goog.dispose');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.functions');
-goog.require('goog.object');
goog.require('goog.vec.Mat4');
goog.require('ol');
+goog.require('ol.Disposable');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
+goog.require('ol.functions');
goog.require('ol.layer.Layer');
goog.require('ol.renderer.Layer');
goog.require('ol.style.IconImageCache');
@@ -52042,10 +42920,9 @@ ol.RendererType = {
};
-
/**
* @constructor
- * @extends {goog.Disposable}
+ * @extends {ol.Disposable}
* @param {Element} container Container.
* @param {ol.Map} map Map.
* @struct
@@ -52069,12 +42946,12 @@ ol.renderer.Map = function(container, map) {
/**
* @private
- * @type {Object.<string, goog.events.Key>}
+ * @type {Object.<string, ol.events.Key>}
*/
this.layerRendererListeners_ = {};
};
-goog.inherits(ol.renderer.Map, goog.Disposable);
+goog.inherits(ol.renderer.Map, ol.Disposable);
/**
@@ -52109,8 +42986,9 @@ ol.renderer.Map.prototype.createLayerRenderer = goog.abstractMethod;
* @inheritDoc
*/
ol.renderer.Map.prototype.disposeInternal = function() {
- goog.object.forEach(this.layerRenderers_, goog.dispose);
- goog.base(this, 'disposeInternal');
+ for (var id in this.layerRenderers_) {
+ this.layerRenderers_[id].dispose();
+ }
};
@@ -52138,26 +43016,23 @@ ol.renderer.Map.expireIconCache_ = function(map, frameState) {
* @return {T|undefined} Callback result.
* @template S,T,U
*/
-ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg,
+ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg,
layerFilter, thisArg2) {
var result;
var viewState = frameState.viewState;
var viewResolution = viewState.resolution;
- /** @type {Object.<string, boolean>} */
- var features = {};
-
/**
* @param {ol.Feature|ol.render.Feature} feature Feature.
+ * @param {ol.layer.Layer} layer Layer.
* @return {?} Callback result.
*/
- function forEachFeatureAtCoordinate(feature) {
+ function forEachFeatureAtCoordinate(feature, layer) {
goog.asserts.assert(feature !== undefined, 'received a feature');
var key = goog.getUid(feature).toString();
- if (!(key in features)) {
- features[key] = true;
- return callback.call(thisArg, feature, null);
+ var managed = frameState.layerStates[goog.getUid(layer)].managed;
+ if (!(key in frameState.skippedFeatureUids && !managed)) {
+ return callback.call(thisArg, feature, managed ? layer : null);
}
}
@@ -52186,9 +43061,7 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
if (layer.getSource()) {
result = layerRenderer.forEachFeatureAtCoordinate(
layer.getSource().getWrapX() ? translatedCoordinate : coordinate,
- frameState,
- layerState.managed ? callback : forEachFeatureAtCoordinate,
- thisArg);
+ frameState, forEachFeatureAtCoordinate, thisArg);
}
if (result) {
return result;
@@ -52213,8 +43086,7 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
* @return {T|undefined} Callback result.
* @template S,T,U
*/
-ol.renderer.Map.prototype.forEachLayerAtPixel =
- function(pixel, frameState, callback, thisArg,
+ol.renderer.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg,
layerFilter, thisArg2) {
var result;
var viewState = frameState.viewState;
@@ -52251,10 +43123,9 @@ ol.renderer.Map.prototype.forEachLayerAtPixel =
* @return {boolean} Is there a feature at the given coordinate?
* @template U
*/
-ol.renderer.Map.prototype.hasFeatureAtCoordinate =
- function(coordinate, frameState, layerFilter, thisArg) {
+ol.renderer.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, layerFilter, thisArg) {
var hasFeature = this.forEachFeatureAtCoordinate(
- coordinate, frameState, goog.functions.TRUE, this, layerFilter, thisArg);
+ coordinate, frameState, ol.functions.TRUE, this, layerFilter, thisArg);
return hasFeature !== undefined;
};
@@ -52272,9 +43143,8 @@ ol.renderer.Map.prototype.getLayerRenderer = function(layer) {
} else {
var layerRenderer = this.createLayerRenderer(layer);
this.layerRenderers_[layerKey] = layerRenderer;
- this.layerRendererListeners_[layerKey] = goog.events.listen(layerRenderer,
- goog.events.EventType.CHANGE, this.handleLayerRendererChange_,
- false, this);
+ this.layerRendererListeners_[layerKey] = ol.events.listen(layerRenderer,
+ ol.events.EventType.CHANGE, this.handleLayerRendererChange_, this);
return layerRenderer;
}
@@ -52295,7 +43165,7 @@ ol.renderer.Map.prototype.getLayerRendererByKey = function(layerKey) {
/**
* @protected
- * @return {Object.<number, ol.renderer.Layer>} Layer renderers.
+ * @return {Object.<string, ol.renderer.Layer>} Layer renderers.
*/
ol.renderer.Map.prototype.getLayerRenderers = function() {
return this.layerRenderers_;
@@ -52338,7 +43208,7 @@ ol.renderer.Map.prototype.removeLayerRendererByKey_ = function(layerKey) {
goog.asserts.assert(layerKey in this.layerRendererListeners_,
'given layerKey (%s) exists in layerRendererListeners', layerKey);
- goog.events.unlistenByKey(this.layerRendererListeners_[layerKey]);
+ ol.events.unlistenByKey(this.layerRendererListeners_[layerKey]);
delete this.layerRendererListeners_[layerKey];
return layerRenderer;
@@ -52357,12 +43227,11 @@ ol.renderer.Map.prototype.renderFrame = ol.nullFunction;
* @param {olx.FrameState} frameState Frame state.
* @private
*/
-ol.renderer.Map.prototype.removeUnusedLayerRenderers_ =
- function(map, frameState) {
+ol.renderer.Map.prototype.removeUnusedLayerRenderers_ = function(map, frameState) {
var layerKey;
for (layerKey in this.layerRenderers_) {
if (!frameState || !(layerKey in frameState.layerStates)) {
- goog.dispose(this.removeLayerRendererByKey_(layerKey));
+ this.removeLayerRendererByKey_(layerKey).dispose();
}
}
};
@@ -52373,7 +43242,9 @@ ol.renderer.Map.prototype.removeUnusedLayerRenderers_ =
* @protected
*/
ol.renderer.Map.prototype.scheduleExpireIconCache = function(frameState) {
- frameState.postRenderFunctions.push(ol.renderer.Map.expireIconCache_);
+ frameState.postRenderFunctions.push(
+ /** @type {ol.PostRenderFunction} */ (ol.renderer.Map.expireIconCache_)
+ );
};
@@ -52381,13 +43252,13 @@ ol.renderer.Map.prototype.scheduleExpireIconCache = function(frameState) {
* @param {!olx.FrameState} frameState Frame state.
* @protected
*/
-ol.renderer.Map.prototype.scheduleRemoveUnusedLayerRenderers =
- function(frameState) {
+ol.renderer.Map.prototype.scheduleRemoveUnusedLayerRenderers = function(frameState) {
var layerKey;
for (layerKey in this.layerRenderers_) {
if (!(layerKey in frameState.layerStates)) {
frameState.postRenderFunctions.push(
- goog.bind(this.removeUnusedLayerRenderers_, this));
+ /** @type {ol.PostRenderFunction} */ (this.removeUnusedLayerRenderers_.bind(this))
+ );
return;
}
}
@@ -52395,9 +43266,9 @@ ol.renderer.Map.prototype.scheduleRemoveUnusedLayerRenderers =
/**
- * @param {ol.layer.LayerState} state1
- * @param {ol.layer.LayerState} state2
- * @return {number}
+ * @param {ol.LayerState} state1 First layer state.
+ * @param {ol.LayerState} state2 Second layer state.
+ * @return {number} The zIndex difference.
*/
ol.renderer.Map.sortByZIndex = function(state1, state2) {
return state1.zIndex - state2.zIndex;
@@ -52406,8 +43277,7 @@ ol.renderer.Map.sortByZIndex = function(state1, state2) {
goog.provide('ol.structs.PriorityQueue');
goog.require('goog.asserts');
-goog.require('goog.object');
-
+goog.require('ol.object');
/**
@@ -52494,7 +43364,7 @@ ol.structs.PriorityQueue.prototype.assertValid = function() {
ol.structs.PriorityQueue.prototype.clear = function() {
this.elements_.length = 0;
this.priorities_.length = 0;
- goog.object.clear(this.queuedElements_);
+ ol.object.clear(this.queuedElements_);
};
@@ -52705,24 +43575,16 @@ ol.structs.PriorityQueue.prototype.reprioritize = function() {
this.heapify_();
};
-goog.provide('ol.TilePriorityFunction');
goog.provide('ol.TileQueue');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('ol.Coordinate');
+goog.require('goog.asserts');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.TileState');
goog.require('ol.structs.PriorityQueue');
/**
- * @typedef {function(ol.Tile, string, ol.Coordinate, number): number}
- */
-ol.TilePriorityFunction;
-
-
-
-/**
* @constructor
* @extends {ol.structs.PriorityQueue.<Array>}
* @param {ol.TilePriorityFunction} tilePriorityFunction
@@ -52764,7 +43626,7 @@ ol.TileQueue = function(tilePriorityFunction, tileChangeCallback) {
/**
* @private
- * @type {Object.<string,boolean>}
+ * @type {!Object.<string,boolean>}
*/
this.tilesLoadingKeys_ = {};
@@ -52779,8 +43641,8 @@ ol.TileQueue.prototype.enqueue = function(element) {
var added = goog.base(this, 'enqueue', element);
if (added) {
var tile = element[0];
- goog.events.listen(tile, goog.events.EventType.CHANGE,
- this.handleTileChange, false, this);
+ ol.events.listen(tile, ol.events.EventType.CHANGE,
+ this.handleTileChange, this);
}
return added;
};
@@ -52795,16 +43657,16 @@ ol.TileQueue.prototype.getTilesLoading = function() {
/**
- * @param {goog.events.Event} event Event.
+ * @param {ol.events.Event} event Event.
* @protected
*/
ol.TileQueue.prototype.handleTileChange = function(event) {
var tile = /** @type {ol.Tile} */ (event.target);
var state = tile.getState();
if (state === ol.TileState.LOADED || state === ol.TileState.ERROR ||
- state === ol.TileState.EMPTY) {
- goog.events.unlisten(tile, goog.events.EventType.CHANGE,
- this.handleTileChange, false, this);
+ state === ol.TileState.EMPTY || state === ol.TileState.ABORT) {
+ ol.events.unlisten(tile, ol.events.EventType.CHANGE,
+ this.handleTileChange, this);
var tileKey = tile.getKey();
if (tileKey in this.tilesLoadingKeys_) {
delete this.tilesLoadingKeys_[tileKey];
@@ -52812,6 +43674,7 @@ ol.TileQueue.prototype.handleTileChange = function(event) {
}
this.tileChangeCallback_();
}
+ goog.asserts.assert(Object.keys(this.tilesLoadingKeys_).length === this.tilesLoading_);
};
@@ -52821,27 +43684,26 @@ ol.TileQueue.prototype.handleTileChange = function(event) {
*/
ol.TileQueue.prototype.loadMoreTiles = function(maxTotalLoading, maxNewLoads) {
var newLoads = 0;
- var tile;
+ var tile, tileKey;
while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads &&
this.getCount() > 0) {
tile = /** @type {ol.Tile} */ (this.dequeue()[0]);
- if (tile.getState() === ol.TileState.IDLE) {
- tile.load();
- this.tilesLoadingKeys_[tile.getKey()] = true;
+ tileKey = tile.getKey();
+ if (tile.getState() === ol.TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
+ this.tilesLoadingKeys_[tileKey] = true;
++this.tilesLoading_;
++newLoads;
+ tile.load();
}
+ goog.asserts.assert(Object.keys(this.tilesLoadingKeys_).length === this.tilesLoading_);
}
};
goog.provide('ol.Kinetic');
-goog.require('ol.Coordinate');
-goog.require('ol.PreRenderFunction');
goog.require('ol.animation');
-
/**
* @classdesc
* Implementation of inertial deceleration for map movement.
@@ -53014,7 +43876,6 @@ ol.interaction.InteractionProperty = {
};
-
/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
@@ -53127,8 +43988,7 @@ ol.interaction.Interaction.pan = function(map, view, delta, opt_duration) {
* @param {ol.Coordinate=} opt_anchor Anchor coordinate.
* @param {number=} opt_duration Duration.
*/
-ol.interaction.Interaction.rotate =
- function(map, view, rotation, opt_anchor, opt_duration) {
+ol.interaction.Interaction.rotate = function(map, view, rotation, opt_anchor, opt_duration) {
rotation = view.constrainRotation(rotation, 0);
ol.interaction.Interaction.rotateWithoutConstraints(
map, view, rotation, opt_anchor, opt_duration);
@@ -53142,8 +44002,7 @@ ol.interaction.Interaction.rotate =
* @param {ol.Coordinate=} opt_anchor Anchor coordinate.
* @param {number=} opt_duration Duration.
*/
-ol.interaction.Interaction.rotateWithoutConstraints =
- function(map, view, rotation, opt_anchor, opt_duration) {
+ol.interaction.Interaction.rotateWithoutConstraints = function(map, view, rotation, opt_anchor, opt_duration) {
if (rotation !== undefined) {
var currentRotation = view.getRotation();
var currentCenter = view.getCenter();
@@ -53182,8 +44041,7 @@ ol.interaction.Interaction.rotateWithoutConstraints =
* will select the nearest resolution. If not defined 0 is
* assumed.
*/
-ol.interaction.Interaction.zoom =
- function(map, view, resolution, opt_anchor, opt_duration, opt_direction) {
+ol.interaction.Interaction.zoom = function(map, view, resolution, opt_anchor, opt_duration, opt_direction) {
resolution = view.constrainResolution(resolution, 0, opt_direction);
ol.interaction.Interaction.zoomWithoutConstraints(
map, view, resolution, opt_anchor, opt_duration);
@@ -53197,8 +44055,7 @@ ol.interaction.Interaction.zoom =
* @param {ol.Coordinate=} opt_anchor Anchor coordinate.
* @param {number=} opt_duration Duration.
*/
-ol.interaction.Interaction.zoomByDelta =
- function(map, view, delta, opt_anchor, opt_duration) {
+ol.interaction.Interaction.zoomByDelta = function(map, view, delta, opt_anchor, opt_duration) {
var currentResolution = view.getResolution();
var resolution = view.constrainResolution(currentResolution, delta, 0);
ol.interaction.Interaction.zoomWithoutConstraints(
@@ -53213,8 +44070,7 @@ ol.interaction.Interaction.zoomByDelta =
* @param {ol.Coordinate=} opt_anchor Anchor coordinate.
* @param {number=} opt_duration Duration.
*/
-ol.interaction.Interaction.zoomWithoutConstraints =
- function(map, view, resolution, opt_anchor, opt_duration) {
+ol.interaction.Interaction.zoomWithoutConstraints = function(map, view, resolution, opt_anchor, opt_duration) {
if (resolution) {
var currentResolution = view.getResolution();
var currentCenter = view.getCenter();
@@ -53250,7 +44106,6 @@ goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.interaction.Interaction');
-
/**
* @classdesc
* Allows the user to zoom by double-clicking on the map.
@@ -53294,7 +44149,7 @@ goog.inherits(ol.interaction.DoubleClickZoom, ol.interaction.Interaction);
*/
ol.interaction.DoubleClickZoom.handleEvent = function(mapBrowserEvent) {
var stopEvent = false;
- var browserEvent = mapBrowserEvent.browserEvent;
+ var browserEvent = mapBrowserEvent.originalEvent;
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK) {
var map = mapBrowserEvent.map;
var anchor = mapBrowserEvent.coordinate;
@@ -53309,26 +44164,15 @@ ol.interaction.DoubleClickZoom.handleEvent = function(mapBrowserEvent) {
return !stopEvent;
};
-goog.provide('ol.events.ConditionType');
goog.provide('ol.events.condition');
goog.require('goog.asserts');
-goog.require('goog.functions');
+goog.require('ol.functions');
goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.MapBrowserPointerEvent');
/**
- * A function that takes an {@link ol.MapBrowserEvent} and returns a
- * `{boolean}`. If the condition is met, true should be returned.
- *
- * @typedef {function(ol.MapBrowserEvent): boolean}
- * @api stable
- */
-ol.events.ConditionType;
-
-
-/**
* Return `true` if only the alt-key is pressed, `false` otherwise (e.g. when
* additionally the shift-key is pressed).
*
@@ -53337,11 +44181,11 @@ ol.events.ConditionType;
* @api stable
*/
ol.events.condition.altKeyOnly = function(mapBrowserEvent) {
- var browserEvent = mapBrowserEvent.browserEvent;
+ var originalEvent = mapBrowserEvent.originalEvent;
return (
- browserEvent.altKey &&
- !browserEvent.platformModifierKey &&
- !browserEvent.shiftKey);
+ originalEvent.altKey &&
+ !(originalEvent.metaKey || originalEvent.ctrlKey) &&
+ !originalEvent.shiftKey);
};
@@ -53354,11 +44198,11 @@ ol.events.condition.altKeyOnly = function(mapBrowserEvent) {
* @api stable
*/
ol.events.condition.altShiftKeysOnly = function(mapBrowserEvent) {
- var browserEvent = mapBrowserEvent.browserEvent;
+ var originalEvent = mapBrowserEvent.originalEvent;
return (
- browserEvent.altKey &&
- !browserEvent.platformModifierKey &&
- browserEvent.shiftKey);
+ originalEvent.altKey &&
+ !(originalEvent.metaKey || originalEvent.ctrlKey) &&
+ originalEvent.shiftKey);
};
@@ -53370,7 +44214,7 @@ ol.events.condition.altShiftKeysOnly = function(mapBrowserEvent) {
* @function
* @api stable
*/
-ol.events.condition.always = goog.functions.TRUE;
+ol.events.condition.always = ol.functions.TRUE;
/**
@@ -53386,6 +44230,22 @@ ol.events.condition.click = function(mapBrowserEvent) {
/**
+ * Return `true` if the event has an "action"-producing mouse button.
+ *
+ * By definition, this includes left-click on windows/linux, and left-click
+ * without the ctrl key on Macs.
+ *
+ * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
+ * @return {boolean} The result.
+ */
+ol.events.condition.mouseActionButton = function(mapBrowserEvent) {
+ var originalEvent = mapBrowserEvent.originalEvent;
+ return originalEvent.button == 0 &&
+ !(goog.userAgent.WEBKIT && ol.has.MAC && originalEvent.ctrlKey);
+};
+
+
+/**
* Return always false.
*
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
@@ -53393,7 +44253,7 @@ ol.events.condition.click = function(mapBrowserEvent) {
* @function
* @api stable
*/
-ol.events.condition.never = goog.functions.FALSE;
+ol.events.condition.never = ol.functions.FALSE;
/**
@@ -53442,11 +44302,11 @@ ol.events.condition.doubleClick = function(mapBrowserEvent) {
* @api stable
*/
ol.events.condition.noModifierKeys = function(mapBrowserEvent) {
- var browserEvent = mapBrowserEvent.browserEvent;
+ var originalEvent = mapBrowserEvent.originalEvent;
return (
- !browserEvent.altKey &&
- !browserEvent.platformModifierKey &&
- !browserEvent.shiftKey);
+ !originalEvent.altKey &&
+ !(originalEvent.metaKey || originalEvent.ctrlKey) &&
+ !originalEvent.shiftKey);
};
@@ -53460,11 +44320,11 @@ ol.events.condition.noModifierKeys = function(mapBrowserEvent) {
* @api stable
*/
ol.events.condition.platformModifierKeyOnly = function(mapBrowserEvent) {
- var browserEvent = mapBrowserEvent.browserEvent;
+ var originalEvent = mapBrowserEvent.originalEvent;
return (
- !browserEvent.altKey &&
- browserEvent.platformModifierKey &&
- !browserEvent.shiftKey);
+ !originalEvent.altKey &&
+ (ol.has.MAC ? originalEvent.metaKey : originalEvent.ctrlKey) &&
+ !originalEvent.shiftKey);
};
@@ -53477,11 +44337,11 @@ ol.events.condition.platformModifierKeyOnly = function(mapBrowserEvent) {
* @api stable
*/
ol.events.condition.shiftKeyOnly = function(mapBrowserEvent) {
- var browserEvent = mapBrowserEvent.browserEvent;
+ var originalEvent = mapBrowserEvent.originalEvent;
return (
- !browserEvent.altKey &&
- !browserEvent.platformModifierKey &&
- browserEvent.shiftKey);
+ !originalEvent.altKey &&
+ !(originalEvent.metaKey || originalEvent.ctrlKey) &&
+ originalEvent.shiftKey);
};
@@ -53494,7 +44354,7 @@ ol.events.condition.shiftKeyOnly = function(mapBrowserEvent) {
* @api
*/
ol.events.condition.targetNotEditable = function(mapBrowserEvent) {
- var target = mapBrowserEvent.browserEvent.target;
+ var target = mapBrowserEvent.originalEvent.target;
goog.asserts.assertInstanceof(target, Element,
'target should be an Element');
var tagName = target.tagName;
@@ -53517,16 +44377,28 @@ ol.events.condition.mouseOnly = function(mapBrowserEvent) {
return mapBrowserEvent.pointerEvent.pointerType == 'mouse';
};
+
+/**
+ * Return `true` if the event originates from a primary pointer in
+ * contact with the surface or if the left mouse button is pressed.
+ * @see http://www.w3.org/TR/pointerevents/#button-states
+ *
+ * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
+ * @return {boolean} True if the event originates from a primary pointer.
+ * @api
+ */
+ol.events.condition.primaryAction = function(mapBrowserEvent) {
+ var pointerEvent = mapBrowserEvent.pointerEvent;
+ return pointerEvent.isPrimary && pointerEvent.button === 0;
+};
+
goog.provide('ol.interaction.Pointer');
-goog.require('goog.functions');
-goog.require('goog.object');
goog.require('ol');
goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.MapBrowserPointerEvent');
-goog.require('ol.Pixel');
goog.require('ol.interaction.Interaction');
-
+goog.require('ol.object');
/**
@@ -53606,7 +44478,7 @@ goog.inherits(ol.interaction.Pointer, ol.interaction.Interaction);
/**
- * @param {Array.<ol.pointer.PointerEvent>} pointerEvents
+ * @param {Array.<ol.pointer.PointerEvent>} pointerEvents List of events.
* @return {ol.Pixel} Centroid pixel.
*/
ol.interaction.Pointer.centroid = function(pointerEvents) {
@@ -53627,8 +44499,7 @@ ol.interaction.Pointer.centroid = function(pointerEvents) {
* or pointerup event.
* @private
*/
-ol.interaction.Pointer.prototype.isPointerDraggingEvent_ =
- function(mapBrowserEvent) {
+ol.interaction.Pointer.prototype.isPointerDraggingEvent_ = function(mapBrowserEvent) {
var type = mapBrowserEvent.type;
return (
type === ol.MapBrowserEvent.EventType.POINTERDOWN ||
@@ -53641,8 +44512,7 @@ ol.interaction.Pointer.prototype.isPointerDraggingEvent_ =
* @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
* @private
*/
-ol.interaction.Pointer.prototype.updateTrackedPointers_ =
- function(mapBrowserEvent) {
+ol.interaction.Pointer.prototype.updateTrackedPointers_ = function(mapBrowserEvent) {
if (this.isPointerDraggingEvent_(mapBrowserEvent)) {
var event = mapBrowserEvent.pointerEvent;
@@ -53655,7 +44525,7 @@ ol.interaction.Pointer.prototype.updateTrackedPointers_ =
// update only when there was a pointerdown event for this pointer
this.trackedPointers_[event.pointerId] = event;
}
- this.targetPointers = goog.object.getValues(this.trackedPointers_);
+ this.targetPointers = ol.object.getValues(this.trackedPointers_);
}
};
@@ -53672,7 +44542,7 @@ ol.interaction.Pointer.handleDragEvent = ol.nullFunction;
* @return {boolean} Capture dragging.
* @this {ol.interaction.Pointer}
*/
-ol.interaction.Pointer.handleUpEvent = goog.functions.FALSE;
+ol.interaction.Pointer.handleUpEvent = ol.functions.FALSE;
/**
@@ -53680,7 +44550,7 @@ ol.interaction.Pointer.handleUpEvent = goog.functions.FALSE;
* @return {boolean} Capture dragging.
* @this {ol.interaction.Pointer}
*/
-ol.interaction.Pointer.handleDownEvent = goog.functions.FALSE;
+ol.interaction.Pointer.handleDownEvent = ol.functions.FALSE;
/**
@@ -53737,21 +44607,22 @@ ol.interaction.Pointer.handleEvent = function(mapBrowserEvent) {
* @return {boolean} Should the event be stopped?
* @protected
*/
-ol.interaction.Pointer.prototype.shouldStopEvent = goog.functions.identity;
+ol.interaction.Pointer.prototype.shouldStopEvent = function(handled) {
+ return handled;
+};
goog.provide('ol.interaction.DragPan');
goog.require('goog.asserts');
goog.require('ol.Kinetic');
-goog.require('ol.Pixel');
-goog.require('ol.PreRenderFunction');
+
goog.require('ol.ViewHint');
goog.require('ol.coordinate');
+goog.require('ol.functions');
goog.require('ol.events.condition');
goog.require('ol.interaction.Pointer');
-
/**
* @classdesc
* Allows the user to pan the map by dragging the map.
@@ -53907,19 +44778,18 @@ ol.interaction.DragPan.handleDownEvent_ = function(mapBrowserEvent) {
/**
* @inheritDoc
*/
-ol.interaction.DragPan.prototype.shouldStopEvent = goog.functions.FALSE;
+ol.interaction.DragPan.prototype.shouldStopEvent = ol.functions.FALSE;
goog.provide('ol.interaction.DragRotate');
goog.require('ol');
goog.require('ol.ViewHint');
-goog.require('ol.events.ConditionType');
+goog.require('ol.functions');
goog.require('ol.events.condition');
goog.require('ol.interaction.Interaction');
goog.require('ol.interaction.Pointer');
-
/**
* @classdesc
* Allows the user to rotate the map by clicking and dragging on the map,
@@ -54024,8 +44894,8 @@ ol.interaction.DragRotate.handleDownEvent_ = function(mapBrowserEvent) {
return false;
}
- var browserEvent = mapBrowserEvent.browserEvent;
- if (browserEvent.isMouseActionButton() && this.condition_(mapBrowserEvent)) {
+ if (ol.events.condition.mouseActionButton(mapBrowserEvent) &&
+ this.condition_(mapBrowserEvent)) {
var map = mapBrowserEvent.map;
map.getView().setHint(ol.ViewHint.INTERACTING, 1);
map.render();
@@ -54040,21 +44910,20 @@ ol.interaction.DragRotate.handleDownEvent_ = function(mapBrowserEvent) {
/**
* @inheritDoc
*/
-ol.interaction.DragRotate.prototype.shouldStopEvent = goog.functions.FALSE;
+ol.interaction.DragRotate.prototype.shouldStopEvent = ol.functions.FALSE;
// FIXME add rotation
goog.provide('ol.render.Box');
-goog.require('goog.Disposable');
goog.require('goog.asserts');
+goog.require('ol.Disposable');
goog.require('ol.geom.Polygon');
-
/**
* @constructor
- * @extends {goog.Disposable}
+ * @extends {ol.Disposable}
* @param {string} className CSS class name.
*/
ol.render.Box = function(className) {
@@ -54092,7 +44961,7 @@ ol.render.Box = function(className) {
this.endPixel_ = null;
};
-goog.inherits(ol.render.Box, goog.Disposable);
+goog.inherits(ol.render.Box, ol.Disposable);
/**
@@ -54100,7 +44969,6 @@ goog.inherits(ol.render.Box, goog.Disposable);
*/
ol.render.Box.prototype.disposeInternal = function() {
this.setMap(null);
- goog.base(this, 'disposeInternal');
};
@@ -54188,9 +45056,8 @@ ol.render.Box.prototype.getGeometry = function() {
goog.provide('ol.DragBoxEvent');
goog.provide('ol.interaction.DragBox');
-goog.require('goog.events.Event');
+goog.require('ol.events.Event');
goog.require('ol');
-goog.require('ol.events.ConditionType');
goog.require('ol.events.condition');
goog.require('ol.interaction.Pointer');
goog.require('ol.render.Box');
@@ -54215,6 +45082,14 @@ ol.DragBoxEventType = {
* @api stable
*/
BOXSTART: 'boxstart',
+
+ /**
+ * Triggered on drag when box is active.
+ * @event ol.DragBoxEvent#boxdrag
+ * @api
+ */
+ BOXDRAG: 'boxdrag',
+
/**
* Triggered upon drag box end.
* @event ol.DragBoxEvent#boxend
@@ -54224,7 +45099,6 @@ ol.DragBoxEventType = {
};
-
/**
* @classdesc
* Events emitted by {@link ol.interaction.DragBox} instances are instances of
@@ -54232,11 +45106,12 @@ ol.DragBoxEventType = {
*
* @param {string} type The event type.
* @param {ol.Coordinate} coordinate The event coordinate.
- * @extends {goog.events.Event}
+ * @param {ol.MapBrowserEvent} mapBrowserEvent Originating event.
+ * @extends {ol.events.Event}
* @constructor
* @implements {oli.DragBoxEvent}
*/
-ol.DragBoxEvent = function(type, coordinate) {
+ol.DragBoxEvent = function(type, coordinate, mapBrowserEvent) {
goog.base(this, type);
/**
@@ -54247,9 +45122,15 @@ ol.DragBoxEvent = function(type, coordinate) {
*/
this.coordinate = coordinate;
-};
-goog.inherits(ol.DragBoxEvent, goog.events.Event);
+ /**
+ * @const
+ * @type {ol.MapBrowserEvent}
+ * @api
+ */
+ this.mapBrowserEvent = mapBrowserEvent;
+};
+goog.inherits(ol.DragBoxEvent, ol.events.Event);
/**
@@ -54298,11 +45179,35 @@ ol.interaction.DragBox = function(opt_options) {
this.condition_ = options.condition ?
options.condition : ol.events.condition.always;
+ /**
+ * @private
+ * @type {ol.interaction.DragBoxEndConditionType}
+ */
+ this.boxEndCondition_ = options.boxEndCondition ?
+ options.boxEndCondition : ol.interaction.DragBox.defaultBoxEndCondition;
};
goog.inherits(ol.interaction.DragBox, ol.interaction.Pointer);
/**
+ * The default condition for determining whether the boxend event
+ * should fire.
+ * @param {ol.MapBrowserEvent} mapBrowserEvent The originating MapBrowserEvent
+ * leading to the box end.
+ * @param {ol.Pixel} startPixel The starting pixel of the box.
+ * @param {ol.Pixel} endPixel The end pixel of the box.
+ * @return {boolean} Whether or not the boxend condition should be fired.
+ */
+ol.interaction.DragBox.defaultBoxEndCondition = function(mapBrowserEvent,
+ startPixel, endPixel) {
+ var width = endPixel[0] - startPixel[0];
+ var height = endPixel[1] - startPixel[1];
+ return width * width + height * height >=
+ ol.DRAG_BOX_HYSTERESIS_PIXELS_SQUARED;
+};
+
+
+/**
* @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
* @this {ol.interaction.DragBox}
* @private
@@ -54313,6 +45218,9 @@ ol.interaction.DragBox.handleDragEvent_ = function(mapBrowserEvent) {
}
this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
+
+ this.dispatchEvent(new ol.DragBoxEvent(ol.DragBoxEventType.BOXDRAG,
+ mapBrowserEvent.coordinate, mapBrowserEvent));
};
@@ -54348,14 +45256,11 @@ ol.interaction.DragBox.handleUpEvent_ = function(mapBrowserEvent) {
this.box_.setMap(null);
- var deltaX = mapBrowserEvent.pixel[0] - this.startPixel_[0];
- var deltaY = mapBrowserEvent.pixel[1] - this.startPixel_[1];
-
- if (deltaX * deltaX + deltaY * deltaY >=
- ol.DRAG_BOX_HYSTERESIS_PIXELS_SQUARED) {
+ if (this.boxEndCondition_(mapBrowserEvent,
+ this.startPixel_, mapBrowserEvent.pixel)) {
this.onBoxEnd(mapBrowserEvent);
this.dispatchEvent(new ol.DragBoxEvent(ol.DragBoxEventType.BOXEND,
- mapBrowserEvent.coordinate));
+ mapBrowserEvent.coordinate, mapBrowserEvent));
}
return false;
};
@@ -54372,13 +45277,13 @@ ol.interaction.DragBox.handleDownEvent_ = function(mapBrowserEvent) {
return false;
}
- var browserEvent = mapBrowserEvent.browserEvent;
- if (browserEvent.isMouseActionButton() && this.condition_(mapBrowserEvent)) {
+ if (ol.events.condition.mouseActionButton(mapBrowserEvent) &&
+ this.condition_(mapBrowserEvent)) {
this.startPixel_ = mapBrowserEvent.pixel;
this.box_.setMap(mapBrowserEvent.map);
this.box_.setPixels(this.startPixel_, this.startPixel_);
this.dispatchEvent(new ol.DragBoxEvent(ol.DragBoxEventType.BOXSTART,
- mapBrowserEvent.coordinate));
+ mapBrowserEvent.coordinate, mapBrowserEvent));
return true;
} else {
return false;
@@ -54395,7 +45300,6 @@ goog.require('ol.extent');
goog.require('ol.interaction.DragBox');
-
/**
* @classdesc
* Allows the user to zoom the map by clicking and dragging on the map,
@@ -54422,6 +45326,12 @@ ol.interaction.DragZoom = function(opt_options) {
*/
this.duration_ = options.duration !== undefined ? options.duration : 200;
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.out_ = options.out !== undefined ? options.out : false;
+
goog.base(this, {
condition: condition,
className: options.className || 'ol-dragzoom'
@@ -54445,6 +45355,17 @@ ol.interaction.DragZoom.prototype.onBoxEnd = function() {
var extent = this.getGeometry().getExtent();
+ if (this.out_) {
+ var mapExtent = view.calculateExtent(size);
+ var boxPixelExtent = ol.extent.createOrUpdateFromCoordinates([
+ map.getPixelFromCoordinate(ol.extent.getBottomLeft(extent)),
+ map.getPixelFromCoordinate(ol.extent.getTopRight(extent))]);
+ var factor = view.getResolutionForExtent(boxPixelExtent, size);
+
+ ol.extent.scaleFromCenter(mapExtent, 1 / factor);
+ extent = mapExtent;
+ }
+
var resolution = view.constrainResolution(
view.getResolutionForExtent(extent, size));
@@ -54472,17 +45393,14 @@ ol.interaction.DragZoom.prototype.onBoxEnd = function() {
goog.provide('ol.interaction.KeyboardPan');
goog.require('goog.asserts');
-goog.require('goog.events.KeyCodes');
-goog.require('goog.events.KeyHandler.EventType');
-goog.require('goog.functions');
goog.require('ol');
goog.require('ol.coordinate');
-goog.require('ol.events.ConditionType');
+goog.require('ol.events.EventType');
+goog.require('ol.events.KeyCode');
goog.require('ol.events.condition');
goog.require('ol.interaction.Interaction');
-
/**
* @classdesc
* Allows the user to pan the map using keyboard arrows.
@@ -54510,12 +45428,20 @@ ol.interaction.KeyboardPan = function(opt_options) {
/**
* @private
+ * @param {ol.MapBrowserEvent} mapBrowserEvent Browser event.
+ * @return {boolean} Combined condition result.
+ */
+ this.defaultCondition_ = function(mapBrowserEvent) {
+ return ol.events.condition.noModifierKeys(mapBrowserEvent) &&
+ ol.events.condition.targetNotEditable(mapBrowserEvent);
+ }
+
+ /**
+ * @private
* @type {ol.events.ConditionType}
*/
this.condition_ = options.condition !== undefined ?
- options.condition :
- goog.functions.and(ol.events.condition.noModifierKeys,
- ol.events.condition.targetNotEditable);
+ options.condition : this.defaultCondition_
/**
* @private
@@ -54533,7 +45459,6 @@ ol.interaction.KeyboardPan = function(opt_options) {
};
goog.inherits(ol.interaction.KeyboardPan, ol.interaction.Interaction);
-
/**
* Handles the {@link ol.MapBrowserEvent map browser event} if it was a
* `KeyEvent`, and decides the direction to pan to (if an arrow key was
@@ -54545,25 +45470,24 @@ goog.inherits(ol.interaction.KeyboardPan, ol.interaction.Interaction);
*/
ol.interaction.KeyboardPan.handleEvent = function(mapBrowserEvent) {
var stopEvent = false;
- if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
- var keyEvent = /** @type {goog.events.KeyEvent} */
- (mapBrowserEvent.browserEvent);
+ if (mapBrowserEvent.type == ol.events.EventType.KEYDOWN) {
+ var keyEvent = mapBrowserEvent.originalEvent;
var keyCode = keyEvent.keyCode;
if (this.condition_(mapBrowserEvent) &&
- (keyCode == goog.events.KeyCodes.DOWN ||
- keyCode == goog.events.KeyCodes.LEFT ||
- keyCode == goog.events.KeyCodes.RIGHT ||
- keyCode == goog.events.KeyCodes.UP)) {
+ (keyCode == ol.events.KeyCode.DOWN ||
+ keyCode == ol.events.KeyCode.LEFT ||
+ keyCode == ol.events.KeyCode.RIGHT ||
+ keyCode == ol.events.KeyCode.UP)) {
var map = mapBrowserEvent.map;
var view = map.getView();
goog.asserts.assert(view, 'map must have view');
var mapUnitsDelta = view.getResolution() * this.pixelDelta_;
var deltaX = 0, deltaY = 0;
- if (keyCode == goog.events.KeyCodes.DOWN) {
+ if (keyCode == ol.events.KeyCode.DOWN) {
deltaY = -mapUnitsDelta;
- } else if (keyCode == goog.events.KeyCodes.LEFT) {
+ } else if (keyCode == ol.events.KeyCode.LEFT) {
deltaX = -mapUnitsDelta;
- } else if (keyCode == goog.events.KeyCodes.RIGHT) {
+ } else if (keyCode == ol.events.KeyCode.RIGHT) {
deltaX = mapUnitsDelta;
} else {
deltaY = mapUnitsDelta;
@@ -54581,13 +45505,11 @@ ol.interaction.KeyboardPan.handleEvent = function(mapBrowserEvent) {
goog.provide('ol.interaction.KeyboardZoom');
goog.require('goog.asserts');
-goog.require('goog.events.KeyHandler.EventType');
-goog.require('ol.events.ConditionType');
+goog.require('ol.events.EventType');
goog.require('ol.events.condition');
goog.require('ol.interaction.Interaction');
-
/**
* @classdesc
* Allows the user to zoom the map using keyboard + and -.
@@ -54647,9 +45569,9 @@ goog.inherits(ol.interaction.KeyboardZoom, ol.interaction.Interaction);
*/
ol.interaction.KeyboardZoom.handleEvent = function(mapBrowserEvent) {
var stopEvent = false;
- if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
- var keyEvent = /** @type {goog.events.KeyEvent} */
- (mapBrowserEvent.browserEvent);
+ if (mapBrowserEvent.type == ol.events.EventType.KEYDOWN ||
+ mapBrowserEvent.type == ol.events.EventType.KEYPRESS) {
+ var keyEvent = mapBrowserEvent.originalEvent;
var charCode = keyEvent.charCode;
if (this.condition_(mapBrowserEvent) &&
(charCode == '+'.charCodeAt(0) || charCode == '-'.charCodeAt(0))) {
@@ -54670,15 +45592,12 @@ ol.interaction.KeyboardZoom.handleEvent = function(mapBrowserEvent) {
goog.provide('ol.interaction.MouseWheelZoom');
goog.require('goog.asserts');
-goog.require('goog.events.MouseWheelEvent');
-goog.require('goog.events.MouseWheelHandler.EventType');
goog.require('ol');
-goog.require('ol.Coordinate');
+goog.require('ol.events.EventType');
goog.require('ol.interaction.Interaction');
goog.require('ol.math');
-
/**
* @classdesc
* Allows the user to zoom the map by scrolling the mouse wheel.
@@ -54746,18 +45665,36 @@ goog.inherits(ol.interaction.MouseWheelZoom, ol.interaction.Interaction);
*/
ol.interaction.MouseWheelZoom.handleEvent = function(mapBrowserEvent) {
var stopEvent = false;
- if (mapBrowserEvent.type ==
- goog.events.MouseWheelHandler.EventType.MOUSEWHEEL) {
+ if (mapBrowserEvent.type == ol.events.EventType.WHEEL ||
+ mapBrowserEvent.type == ol.events.EventType.MOUSEWHEEL) {
var map = mapBrowserEvent.map;
- var mouseWheelEvent = mapBrowserEvent.browserEvent;
- goog.asserts.assertInstanceof(mouseWheelEvent, goog.events.MouseWheelEvent,
- 'mouseWheelEvent should be of type MouseWheelEvent');
+ var wheelEvent = /** @type {WheelEvent} */ (mapBrowserEvent.originalEvent);
if (this.useAnchor_) {
this.lastAnchor_ = mapBrowserEvent.coordinate;
}
- this.delta_ += mouseWheelEvent.deltaY;
+ // Delta normalisation inspired by
+ // https://github.com/mapbox/mapbox-gl-js/blob/001c7b9/js/ui/handler/scroll_zoom.js
+ //TODO There's more good stuff in there for inspiration to improve this interaction.
+ var delta;
+ if (mapBrowserEvent.type == ol.events.EventType.WHEEL) {
+ delta = wheelEvent.deltaY;
+ if (ol.has.FIREFOX &&
+ wheelEvent.deltaMode === ol.global.WheelEvent.DOM_DELTA_PIXEL) {
+ delta /= ol.has.DEVICE_PIXEL_RATIO;
+ }
+ if (wheelEvent.deltaMode === ol.global.WheelEvent.DOM_DELTA_LINE) {
+ delta *= 40;
+ }
+ } else if (mapBrowserEvent.type == ol.events.EventType.MOUSEWHEEL) {
+ delta = -wheelEvent.wheelDeltaY;
+ if (ol.has.SAFARI) {
+ delta /= 3;
+ }
+ }
+
+ this.delta_ += delta;
if (this.startTime_ === undefined) {
this.startTime_ = Date.now();
@@ -54766,9 +45703,9 @@ ol.interaction.MouseWheelZoom.handleEvent = function(mapBrowserEvent) {
var duration = ol.MOUSEWHEELZOOM_TIMEOUT_DURATION;
var timeLeft = Math.max(duration - (Date.now() - this.startTime_), 0);
- goog.global.clearTimeout(this.timeoutId_);
- this.timeoutId_ = goog.global.setTimeout(
- goog.bind(this.doZoom_, this, map), timeLeft);
+ ol.global.clearTimeout(this.timeoutId_);
+ this.timeoutId_ = ol.global.setTimeout(
+ this.doZoom_.bind(this, map), timeLeft);
mapBrowserEvent.preventDefault();
stopEvent = true;
@@ -54815,16 +45752,13 @@ ol.interaction.MouseWheelZoom.prototype.setMouseAnchor = function(useAnchor) {
goog.provide('ol.interaction.PinchRotate');
goog.require('goog.asserts');
-goog.require('goog.functions');
-goog.require('goog.style');
goog.require('ol');
-goog.require('ol.Coordinate');
+goog.require('ol.functions');
goog.require('ol.ViewHint');
goog.require('ol.interaction.Interaction');
goog.require('ol.interaction.Pointer');
-
/**
* @classdesc
* Allows the user to rotate the map by twisting with two fingers
@@ -54919,11 +45853,10 @@ ol.interaction.PinchRotate.handleDragEvent_ = function(mapBrowserEvent) {
// rotate anchor point.
// FIXME: should be the intersection point between the lines:
// touch0,touch1 and previousTouch0,previousTouch1
- var viewportPosition = goog.style.getClientPosition(map.getViewport());
- var centroid =
- ol.interaction.Pointer.centroid(this.targetPointers);
- centroid[0] -= viewportPosition.x;
- centroid[1] -= viewportPosition.y;
+ var viewportPosition = map.getViewport().getBoundingClientRect();
+ var centroid = ol.interaction.Pointer.centroid(this.targetPointers);
+ centroid[0] -= viewportPosition.left;
+ centroid[1] -= viewportPosition.top;
this.anchor_ = map.getCoordinateFromPixel(centroid);
// rotate
@@ -54987,21 +45920,18 @@ ol.interaction.PinchRotate.handleDownEvent_ = function(mapBrowserEvent) {
/**
* @inheritDoc
*/
-ol.interaction.PinchRotate.prototype.shouldStopEvent = goog.functions.FALSE;
+ol.interaction.PinchRotate.prototype.shouldStopEvent = ol.functions.FALSE;
goog.provide('ol.interaction.PinchZoom');
goog.require('goog.asserts');
-goog.require('goog.functions');
-goog.require('goog.style');
goog.require('ol');
-goog.require('ol.Coordinate');
+goog.require('ol.functions');
goog.require('ol.ViewHint');
goog.require('ol.interaction.Interaction');
goog.require('ol.interaction.Pointer');
-
/**
* @classdesc
* Allows the user to zoom the map by pinching with two fingers
@@ -55081,11 +46011,10 @@ ol.interaction.PinchZoom.handleDragEvent_ = function(mapBrowserEvent) {
var resolution = view.getResolution();
// scale anchor point.
- var viewportPosition = goog.style.getClientPosition(map.getViewport());
- var centroid =
- ol.interaction.Pointer.centroid(this.targetPointers);
- centroid[0] -= viewportPosition.x;
- centroid[1] -= viewportPosition.y;
+ var viewportPosition = map.getViewport().getBoundingClientRect();
+ var centroid = ol.interaction.Pointer.centroid(this.targetPointers);
+ centroid[0] -= viewportPosition.left;
+ centroid[1] -= viewportPosition.top;
this.anchor_ = map.getCoordinateFromPixel(centroid);
// scale, bypass the resolution constraint
@@ -55147,7 +46076,7 @@ ol.interaction.PinchZoom.handleDownEvent_ = function(mapBrowserEvent) {
/**
* @inheritDoc
*/
-ol.interaction.PinchZoom.prototype.shouldStopEvent = goog.functions.FALSE;
+ol.interaction.PinchZoom.prototype.shouldStopEvent = ol.functions.FALSE;
goog.provide('ol.interaction');
@@ -55263,16 +46192,16 @@ ol.interaction.defaults = function(opt_options) {
goog.provide('ol.layer.Group');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('ol.Collection');
goog.require('ol.CollectionEvent');
goog.require('ol.CollectionEventType');
goog.require('ol.Object');
goog.require('ol.ObjectEventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
goog.require('ol.layer.Base');
+goog.require('ol.object');
goog.require('ol.source.State');
@@ -55284,7 +46213,6 @@ ol.layer.GroupProperty = {
};
-
/**
* @classdesc
* A {@link ol.Collection} of layers that are handled together.
@@ -55300,7 +46228,7 @@ ol.layer.Group = function(opt_options) {
var options = opt_options || {};
var baseOptions = /** @type {olx.layer.GroupOptions} */
- (goog.object.clone(options));
+ (ol.object.assign({}, options));
delete baseOptions.layers;
var layers = options.layers;
@@ -55309,22 +46237,22 @@ ol.layer.Group = function(opt_options) {
/**
* @private
- * @type {Array.<goog.events.Key>}
+ * @type {Array.<ol.events.Key>}
*/
this.layersListenerKeys_ = [];
/**
* @private
- * @type {Object.<string, Array.<goog.events.Key>>}
+ * @type {Object.<string, Array.<ol.events.Key>>}
*/
this.listenerKeys_ = {};
- goog.events.listen(this,
+ ol.events.listen(this,
ol.Object.getChangeEventType(ol.layer.GroupProperty.LAYERS),
- this.handleLayersChanged_, false, this);
+ this.handleLayersChanged_, this);
if (layers) {
- if (goog.isArray(layers)) {
+ if (Array.isArray(layers)) {
layers = new ol.Collection(layers.slice());
} else {
goog.asserts.assertInstanceof(layers, ol.Collection,
@@ -55352,34 +46280,34 @@ ol.layer.Group.prototype.handleLayerChange_ = function() {
/**
- * @param {goog.events.Event} event Event.
+ * @param {ol.events.Event} event Event.
* @private
*/
ol.layer.Group.prototype.handleLayersChanged_ = function(event) {
- this.layersListenerKeys_.forEach(goog.events.unlistenByKey);
+ this.layersListenerKeys_.forEach(ol.events.unlistenByKey);
this.layersListenerKeys_.length = 0;
var layers = this.getLayers();
this.layersListenerKeys_.push(
- goog.events.listen(layers, ol.CollectionEventType.ADD,
- this.handleLayersAdd_, false, this),
- goog.events.listen(layers, ol.CollectionEventType.REMOVE,
- this.handleLayersRemove_, false, this));
+ ol.events.listen(layers, ol.CollectionEventType.ADD,
+ this.handleLayersAdd_, this),
+ ol.events.listen(layers, ol.CollectionEventType.REMOVE,
+ this.handleLayersRemove_, this));
- goog.object.forEach(this.listenerKeys_, function(keys) {
- keys.forEach(goog.events.unlistenByKey);
- });
- goog.object.clear(this.listenerKeys_);
+ for (var id in this.listenerKeys_) {
+ this.listenerKeys_[id].forEach(ol.events.unlistenByKey);
+ }
+ ol.object.clear(this.listenerKeys_);
var layersArray = layers.getArray();
var i, ii, layer;
for (i = 0, ii = layersArray.length; i < ii; i++) {
layer = layersArray[i];
this.listenerKeys_[goog.getUid(layer).toString()] = [
- goog.events.listen(layer, ol.ObjectEventType.PROPERTYCHANGE,
- this.handleLayerChange_, false, this),
- goog.events.listen(layer, goog.events.EventType.CHANGE,
- this.handleLayerChange_, false, this)
+ ol.events.listen(layer, ol.ObjectEventType.PROPERTYCHANGE,
+ this.handleLayerChange_, this),
+ ol.events.listen(layer, ol.events.EventType.CHANGE,
+ this.handleLayerChange_, this)
];
}
@@ -55397,10 +46325,10 @@ ol.layer.Group.prototype.handleLayersAdd_ = function(collectionEvent) {
goog.asserts.assert(!(key in this.listenerKeys_),
'listeners already registered');
this.listenerKeys_[key] = [
- goog.events.listen(layer, ol.ObjectEventType.PROPERTYCHANGE,
- this.handleLayerChange_, false, this),
- goog.events.listen(layer, goog.events.EventType.CHANGE,
- this.handleLayerChange_, false, this)
+ ol.events.listen(layer, ol.ObjectEventType.PROPERTYCHANGE,
+ this.handleLayerChange_, this),
+ ol.events.listen(layer, ol.events.EventType.CHANGE,
+ this.handleLayerChange_, this)
];
this.changed();
};
@@ -55414,7 +46342,7 @@ ol.layer.Group.prototype.handleLayersRemove_ = function(collectionEvent) {
var layer = /** @type {ol.layer.Base} */ (collectionEvent.element);
var key = goog.getUid(layer).toString();
goog.asserts.assert(key in this.listenerKeys_, 'no listeners to unregister');
- this.listenerKeys_[key].forEach(goog.events.unlistenByKey);
+ this.listenerKeys_[key].forEach(ol.events.unlistenByKey);
delete this.listenerKeys_[key];
this.changed();
};
@@ -55511,7 +46439,6 @@ goog.require('ol.proj.Projection');
goog.require('ol.proj.Units');
-
/**
* @classdesc
* Projection object for web/spherical Mercator (EPSG:3857).
@@ -55660,12 +46587,24 @@ ol.proj.EPSG3857.toEPSG4326 = function(input, opt_output, opt_dimension) {
return output;
};
+goog.provide('ol.sphere.WGS84');
+
+goog.require('ol.Sphere');
+
+
+/**
+ * A sphere with radius equal to the semi-major axis of the WGS84 ellipsoid.
+ * @const
+ * @type {ol.Sphere}
+ */
+ol.sphere.WGS84 = new ol.Sphere(6378137);
+
goog.provide('ol.proj.EPSG4326');
goog.require('ol.proj');
goog.require('ol.proj.Projection');
goog.require('ol.proj.Units');
-
+goog.require('ol.sphere.WGS84');
/**
@@ -55689,6 +46628,7 @@ ol.proj.EPSG4326_ = function(code, opt_axisOrientation) {
extent: ol.proj.EPSG4326.EXTENT,
axisOrientation: opt_axisOrientation,
global: true,
+ metersPerUnit: ol.proj.EPSG4326.METERS_PER_UNIT,
worldExtent: ol.proj.EPSG4326.EXTENT
});
};
@@ -55713,6 +46653,13 @@ ol.proj.EPSG4326.EXTENT = [-180, -90, 180, 90];
/**
+ * @const
+ * @type {number}
+ */
+ol.proj.EPSG4326.METERS_PER_UNIT = Math.PI * ol.sphere.WGS84.radius / 180;
+
+
+/**
* Projections equal to EPSG:4326.
*
* @const
@@ -55759,7 +46706,6 @@ goog.provide('ol.layer.Image');
goog.require('ol.layer.Layer');
-
/**
* @classdesc
* Server-rendered images that are available for arbitrary extents and
@@ -55791,9 +46737,9 @@ ol.layer.Image.prototype.getSource;
goog.provide('ol.layer.Tile');
-goog.require('goog.object');
goog.require('ol');
goog.require('ol.layer.Layer');
+goog.require('ol.object');
/**
@@ -55805,7 +46751,6 @@ ol.layer.TileProperty = {
};
-
/**
* @classdesc
* For layer sources that provide pre-rendered, tiled images in grids that are
@@ -55823,7 +46768,7 @@ ol.layer.TileProperty = {
ol.layer.Tile = function(opt_options) {
var options = opt_options ? opt_options : {};
- var baseOptions = goog.object.clone(options);
+ var baseOptions = ol.object.assign({}, options);
delete baseOptions.preload;
delete baseOptions.useInterimTilesOnError;
@@ -55885,8 +46830,7 @@ ol.layer.Tile.prototype.getUseInterimTilesOnError = function() {
* @observable
* @api
*/
-ol.layer.Tile.prototype.setUseInterimTilesOnError =
- function(useInterimTilesOnError) {
+ol.layer.Tile.prototype.setUseInterimTilesOnError = function(useInterimTilesOnError) {
this.set(
ol.layer.TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
};
@@ -55895,31 +46839,6 @@ goog.provide('ol.render.canvas');
/**
- * @typedef {{fillStyle: string}}
- */
-ol.render.canvas.FillState;
-
-
-/**
- * @typedef {{lineCap: string,
- * lineDash: Array.<number>,
- * lineJoin: string,
- * lineWidth: number,
- * miterLimit: number,
- * strokeStyle: string}}
- */
-ol.render.canvas.StrokeState;
-
-
-/**
- * @typedef {{font: string,
- * textAlign: string,
- * textBaseline: string}}
- */
-ol.render.canvas.TextState;
-
-
-/**
* @const
* @type {string}
*/
@@ -55988,28 +46907,24 @@ ol.render.canvas.defaultTextBaseline = 'middle';
*/
ol.render.canvas.defaultLineWidth = 1;
-goog.provide('ol.structs.IHasChecksum');
-
-
-
-/**
- * @interface
- */
-ol.structs.IHasChecksum = function() {
-};
-
/**
- * @return {string} The checksum.
+ * @param {CanvasRenderingContext2D} context Context.
+ * @param {number} rotation Rotation.
+ * @param {number} offsetX X offset.
+ * @param {number} offsetY Y offset.
*/
-ol.structs.IHasChecksum.prototype.getChecksum = function() {
+ol.render.canvas.rotateAtOffset = function(context, rotation, offsetX, offsetY) {
+ if (rotation !== 0) {
+ context.translate(offsetX, offsetY);
+ context.rotate(rotation);
+ context.translate(-offsetX, -offsetY);
+ }
};
goog.provide('ol.style.Fill');
goog.require('ol.color');
-goog.require('ol.structs.IHasChecksum');
-
/**
@@ -56018,7 +46933,6 @@ goog.require('ol.structs.IHasChecksum');
*
* @constructor
* @param {olx.style.FillOptions=} opt_options Options.
- * @implements {ol.structs.IHasChecksum}
* @api
*/
ol.style.Fill = function(opt_options) {
@@ -56027,7 +46941,7 @@ ol.style.Fill = function(opt_options) {
/**
* @private
- * @type {ol.Color|string}
+ * @type {ol.Color|ol.ColorLike}
*/
this.color_ = options.color !== undefined ? options.color : null;
@@ -56041,7 +46955,7 @@ ol.style.Fill = function(opt_options) {
/**
* Get the fill color.
- * @return {ol.Color|string} Color.
+ * @return {ol.Color|ol.ColorLike} Color.
* @api
*/
ol.style.Fill.prototype.getColor = function() {
@@ -56052,7 +46966,7 @@ ol.style.Fill.prototype.getColor = function() {
/**
* Set the color.
*
- * @param {ol.Color|string} color Color.
+ * @param {ol.Color|ol.ColorLike} color Color.
* @api
*/
ol.style.Fill.prototype.setColor = function(color) {
@@ -56062,12 +46976,19 @@ ol.style.Fill.prototype.setColor = function(color) {
/**
- * @inheritDoc
+ * @return {string} The checksum.
*/
ol.style.Fill.prototype.getChecksum = function() {
if (this.checksum_ === undefined) {
- this.checksum_ = 'f' + (this.color_ ?
- ol.color.asString(this.color_) : '-');
+ if (
+ this.color_ instanceof CanvasPattern ||
+ this.color_ instanceof CanvasGradient
+ ) {
+ this.checksum_ = goog.getUid(this.color_).toString();
+ } else {
+ this.checksum_ = 'f' + (this.color_ ?
+ ol.color.asString(this.color_) : '-');
+ }
}
return this.checksum_;
@@ -56121,7 +47042,8 @@ goog.crypt.stringToByteArray = function(str) {
/**
* Turns an array of numbers into the string given by the concatenation of the
* characters to which the numbers correspond.
- * @param {Array<number>} bytes Array of numbers representing characters.
+ * @param {!Uint8Array|!Array<number>} bytes Array of numbers representing
+ * characters.
* @return {string} Stringification of the array.
*/
goog.crypt.byteArrayToString = function(bytes) {
@@ -56153,10 +47075,14 @@ goog.crypt.byteArrayToString = function(bytes) {
* @return {string} Hex string.
*/
goog.crypt.byteArrayToHex = function(array) {
- return goog.array.map(array, function(numByte) {
- var hexByte = numByte.toString(16);
- return hexByte.length > 1 ? hexByte : '0' + hexByte;
- }).join('');
+ return goog.array
+ .map(
+ array,
+ function(numByte) {
+ var hexByte = numByte.toString(16);
+ return hexByte.length > 1 ? hexByte : '0' + hexByte;
+ })
+ .join('');
};
@@ -56167,8 +47093,8 @@ goog.crypt.byteArrayToHex = function(array) {
* @return {!Array<number>} Array of {0,255} integers for the given string.
*/
goog.crypt.hexToByteArray = function(hexString) {
- goog.asserts.assert(hexString.length % 2 == 0,
- 'Key string length must be multiple of 2');
+ goog.asserts.assert(
+ hexString.length % 2 == 0, 'Key string length must be multiple of 2');
var arr = [];
for (var i = 0; i < hexString.length; i += 2) {
arr.push(parseInt(hexString.substring(i, i + 2), 16));
@@ -56192,6 +47118,15 @@ goog.crypt.stringToUtf8ByteArray = function(str) {
} else if (c < 2048) {
out[p++] = (c >> 6) | 192;
out[p++] = (c & 63) | 128;
+ } else if (
+ ((c & 0xFC00) == 0xD800) && (i + 1) < str.length &&
+ ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {
+ // Surrogate Pair
+ c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);
+ out[p++] = (c >> 18) | 240;
+ out[p++] = ((c >> 12) & 63) | 128;
+ out[p++] = ((c >> 6) & 63) | 128;
+ out[p++] = (c & 63) | 128;
} else {
out[p++] = (c >> 12) | 224;
out[p++] = ((c >> 6) & 63) | 128;
@@ -56217,11 +47152,20 @@ goog.crypt.utf8ByteArrayToString = function(bytes) {
} else if (c1 > 191 && c1 < 224) {
var c2 = bytes[pos++];
out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
+ } else if (c1 > 239 && c1 < 365) {
+ // Surrogate Pair
+ var c2 = bytes[pos++];
+ var c3 = bytes[pos++];
+ var c4 = bytes[pos++];
+ var u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) -
+ 0x10000;
+ out[c++] = String.fromCharCode(0xD800 + (u >> 10));
+ out[c++] = String.fromCharCode(0xDC00 + (u & 1023));
} else {
var c2 = bytes[pos++];
var c3 = bytes[pos++];
- out[c++] = String.fromCharCode(
- (c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
+ out[c++] =
+ String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
}
}
return out.join('');
@@ -56230,14 +47174,13 @@ goog.crypt.utf8ByteArrayToString = function(bytes) {
/**
* XOR two byte arrays.
- * @param {!ArrayBufferView|!Array<number>} bytes1 Byte array 1.
- * @param {!ArrayBufferView|!Array<number>} bytes2 Byte array 2.
+ * @param {!Uint8Array|!Int8Array|!Array<number>} bytes1 Byte array 1.
+ * @param {!Uint8Array|!Int8Array|!Array<number>} bytes2 Byte array 2.
* @return {!Array<number>} Resulting XOR of the two byte arrays.
*/
goog.crypt.xorByteArray = function(bytes1, bytes2) {
goog.asserts.assert(
- bytes1.length == bytes2.length,
- 'XOR array lengths must match');
+ bytes1.length == bytes2.length, 'XOR array lengths must match');
var result = [];
for (var i = 0; i < bytes1.length; i++) {
@@ -56475,16 +47418,14 @@ goog.crypt.Md5.prototype.compress_ = function(buf, opt_offset) {
if (goog.isString(buf)) {
for (var i = 0; i < 16; ++i) {
X[i] = (buf.charCodeAt(opt_offset++)) |
- (buf.charCodeAt(opt_offset++) << 8) |
- (buf.charCodeAt(opt_offset++) << 16) |
- (buf.charCodeAt(opt_offset++) << 24);
+ (buf.charCodeAt(opt_offset++) << 8) |
+ (buf.charCodeAt(opt_offset++) << 16) |
+ (buf.charCodeAt(opt_offset++) << 24);
}
} else {
for (var i = 0; i < 16; ++i) {
- X[i] = (buf[opt_offset++]) |
- (buf[opt_offset++] << 8) |
- (buf[opt_offset++] << 16) |
- (buf[opt_offset++] << 24);
+ X[i] = (buf[opt_offset++]) | (buf[opt_offset++] << 8) |
+ (buf[opt_offset++] << 16) | (buf[opt_offset++] << 24);
}
}
@@ -56725,9 +47666,9 @@ goog.crypt.Md5.prototype.update = function(bytes, opt_length) {
goog.crypt.Md5.prototype.digest = function() {
// This must accommodate at least 1 padding byte (0x80), 8 bytes of
// total bitlength, and must end at a 64-byte boundary.
- var pad = new Array((this.blockLength_ < 56 ?
- this.blockSize :
- this.blockSize * 2) - this.blockLength_);
+ var pad = new Array(
+ (this.blockLength_ < 56 ? this.blockSize : this.blockSize * 2) -
+ this.blockLength_);
// Add padding: 0x80 0x00*
pad[0] = 0x80;
@@ -56738,7 +47679,7 @@ goog.crypt.Md5.prototype.digest = function() {
var totalBits = this.totalLength_ * 8;
for (var i = pad.length - 8; i < pad.length; ++i) {
pad[i] = totalBits & 0xff;
- totalBits /= 0x100; // Don't use bit-shifting here!
+ totalBits /= 0x100; // Don't use bit-shifting here!
}
this.update(pad);
@@ -56757,8 +47698,6 @@ goog.provide('ol.style.Stroke');
goog.require('goog.crypt');
goog.require('goog.crypt.Md5');
goog.require('ol.color');
-goog.require('ol.structs.IHasChecksum');
-
/**
@@ -56770,7 +47709,6 @@ goog.require('ol.structs.IHasChecksum');
*
* @constructor
* @param {olx.style.StrokeOptions=} opt_options Options.
- * @implements {ol.structs.IHasChecksum}
* @api
*/
ol.style.Stroke = function(opt_options) {
@@ -56908,6 +47846,12 @@ ol.style.Stroke.prototype.setLineCap = function(lineCap) {
/**
* Set the line dash.
*
+ * Please note that Internet Explorer 10 and lower [do not support][mdn] the
+ * `setLineDash` method on the `CanvasRenderingContext2D` and therefore this
+ * property will have no visual effect in these browsers.
+ *
+ * [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility
+ *
* @param {Array.<number>} lineDash Line dash.
* @api
*/
@@ -56954,7 +47898,7 @@ ol.style.Stroke.prototype.setWidth = function(width) {
/**
- * @inheritDoc
+ * @return {string} The checksum.
*/
ol.style.Stroke.prototype.getChecksum = function() {
if (this.checksum_ === undefined) {
@@ -56985,16 +47929,16 @@ goog.provide('ol.style.Circle');
goog.require('goog.asserts');
goog.require('ol');
goog.require('ol.color');
+goog.require('ol.colorlike');
+goog.require('ol.dom');
goog.require('ol.has');
goog.require('ol.render.canvas');
-goog.require('ol.structs.IHasChecksum');
goog.require('ol.style.Fill');
goog.require('ol.style.Image');
goog.require('ol.style.ImageState');
goog.require('ol.style.Stroke');
-
/**
* @classdesc
* Set circle style for vector features.
@@ -57002,7 +47946,6 @@ goog.require('ol.style.Stroke');
* @constructor
* @param {olx.style.CircleOptions=} opt_options Options.
* @extends {ol.style.Image}
- * @implements {ol.structs.IHasChecksum}
* @api
*/
ol.style.Circle = function(opt_options) {
@@ -57211,15 +48154,8 @@ ol.style.Circle.prototype.unlistenImageChange = ol.nullFunction;
/**
- * @typedef {{strokeStyle: (string|undefined), strokeWidth: number,
- * size: number, lineDash: Array.<number>}}
- */
-ol.style.Circle.RenderOptions;
-
-
-/**
* @private
- * @param {ol.style.AtlasManager|undefined} atlasManager
+ * @param {ol.style.AtlasManager|undefined} atlasManager An atlas manager.
*/
ol.style.Circle.prototype.render_ = function(atlasManager) {
var imageSize;
@@ -57242,7 +48178,7 @@ ol.style.Circle.prototype.render_ = function(atlasManager) {
var size = 2 * (this.radius_ + strokeWidth) + 1;
- /** @type {ol.style.Circle.RenderOptions} */
+ /** @type {ol.style.CircleRenderOptions} */
var renderOptions = {
strokeStyle: strokeStyle,
strokeWidth: strokeWidth,
@@ -57252,18 +48188,14 @@ ol.style.Circle.prototype.render_ = function(atlasManager) {
if (atlasManager === undefined) {
// no atlas manager is used, create a new canvas
- this.canvas_ = /** @type {HTMLCanvasElement} */
- (document.createElement('CANVAS'));
- this.canvas_.height = size;
- this.canvas_.width = size;
+ var context = ol.dom.createCanvasContext2D(size, size);
+ this.canvas_ = context.canvas;
// canvas.width and height are rounded to the closest integer
size = this.canvas_.width;
imageSize = size;
// draw the circle on the canvas
- var context = /** @type {CanvasRenderingContext2D} */
- (this.canvas_.getContext('2d'));
this.draw_(renderOptions, context, 0, 0);
this.createHitDetectionCanvas_(renderOptions);
@@ -57276,12 +48208,12 @@ ol.style.Circle.prototype.render_ = function(atlasManager) {
if (hasCustomHitDetectionImage) {
// render the hit-detection image into a separate atlas image
renderHitDetectionCallback =
- goog.bind(this.drawHitDetectionCanvas_, this, renderOptions);
+ this.drawHitDetectionCanvas_.bind(this, renderOptions);
}
var id = this.getChecksum();
var info = atlasManager.add(
- id, size, size, goog.bind(this.draw_, this, renderOptions),
+ id, size, size, this.draw_.bind(this, renderOptions),
renderHitDetectionCallback);
goog.asserts.assert(info, 'circle radius is too large');
@@ -57307,8 +48239,8 @@ ol.style.Circle.prototype.render_ = function(atlasManager) {
/**
* @private
- * @param {ol.style.Circle.RenderOptions} renderOptions
- * @param {CanvasRenderingContext2D} context
+ * @param {ol.style.CircleRenderOptions} renderOptions Render options.
+ * @param {CanvasRenderingContext2D} context The rendering context.
* @param {number} x The origin for the symbol (x).
* @param {number} y The origin for the symbol (y).
*/
@@ -57325,7 +48257,7 @@ ol.style.Circle.prototype.draw_ = function(renderOptions, context, x, y) {
this.radius_, 0, 2 * Math.PI, true);
if (this.fill_) {
- context.fillStyle = ol.color.asString(this.fill_.getColor());
+ context.fillStyle = ol.colorlike.asColorLike(this.fill_.getColor());
context.fill();
}
if (this.stroke_) {
@@ -57342,7 +48274,7 @@ ol.style.Circle.prototype.draw_ = function(renderOptions, context, x, y) {
/**
* @private
- * @param {ol.style.Circle.RenderOptions} renderOptions
+ * @param {ol.style.CircleRenderOptions} renderOptions Render options.
*/
ol.style.Circle.prototype.createHitDetectionCanvas_ = function(renderOptions) {
this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];
@@ -57353,28 +48285,21 @@ ol.style.Circle.prototype.createHitDetectionCanvas_ = function(renderOptions) {
// if no fill style is set, create an extra hit-detection image with a
// default fill style
- this.hitDetectionCanvas_ = /** @type {HTMLCanvasElement} */
- (document.createElement('CANVAS'));
- var canvas = this.hitDetectionCanvas_;
+ var context = ol.dom.createCanvasContext2D(renderOptions.size, renderOptions.size);
+ this.hitDetectionCanvas_ = context.canvas;
- canvas.height = renderOptions.size;
- canvas.width = renderOptions.size;
-
- var context = /** @type {CanvasRenderingContext2D} */
- (canvas.getContext('2d'));
this.drawHitDetectionCanvas_(renderOptions, context, 0, 0);
};
/**
* @private
- * @param {ol.style.Circle.RenderOptions} renderOptions
- * @param {CanvasRenderingContext2D} context
+ * @param {ol.style.CircleRenderOptions} renderOptions Render options.
+ * @param {CanvasRenderingContext2D} context The context.
* @param {number} x The origin for the symbol (x).
* @param {number} y The origin for the symbol (y).
*/
-ol.style.Circle.prototype.drawHitDetectionCanvas_ =
- function(renderOptions, context, x, y) {
+ol.style.Circle.prototype.drawHitDetectionCanvas_ = function(renderOptions, context, x, y) {
// reset transform
context.setTransform(1, 0, 0, 1, 0, 0);
@@ -57401,7 +48326,7 @@ ol.style.Circle.prototype.drawHitDetectionCanvas_ =
/**
- * @inheritDoc
+ * @return {string} The checksum.
*/
ol.style.Circle.prototype.getChecksum = function() {
var strokeChecksum = this.stroke_ ?
@@ -57423,9 +48348,7 @@ ol.style.Circle.prototype.getChecksum = function() {
return this.checksums_[0];
};
-goog.provide('ol.style.GeometryFunction');
goog.provide('ol.style.Style');
-goog.provide('ol.style.StyleFunction');
goog.provide('ol.style.defaultGeometryFunction');
goog.require('goog.asserts');
@@ -57437,7 +48360,6 @@ goog.require('ol.style.Image');
goog.require('ol.style.Stroke');
-
/**
* @classdesc
* Container for vector feature rendering styles. Any changes made to the style
@@ -57445,6 +48367,7 @@ goog.require('ol.style.Stroke');
* feature or layer that uses the style is re-rendered.
*
* @constructor
+ * @struct
* @param {olx.style.StyleOptions=} opt_options Style options.
* @api
*/
@@ -57585,7 +48508,7 @@ ol.style.Style.prototype.getZIndex = function() {
ol.style.Style.prototype.setGeometry = function(geometry) {
if (goog.isFunction(geometry)) {
this.geometryFunction_ = geometry;
- } else if (goog.isString(geometry)) {
+ } else if (typeof geometry === 'string') {
this.geometryFunction_ = function(feature) {
var result = feature.get(geometry);
if (result) {
@@ -57619,18 +48542,6 @@ ol.style.Style.prototype.setZIndex = function(zIndex) {
/**
- * A function that takes an {@link ol.Feature} and a `{number}` representing
- * the view's resolution. The function should return an array of
- * {@link ol.style.Style}. This way e.g. a vector layer can be styled.
- *
- * @typedef {function((ol.Feature|ol.render.Feature), number):
- * (ol.style.Style|Array.<ol.style.Style>)}
- * @api
- */
-ol.style.StyleFunction;
-
-
-/**
* Convert the provided object into a style function. Functions passed through
* unchanged. Arrays of ol.style.Style or single style objects wrapped in a
* new style function.
@@ -57648,7 +48559,7 @@ ol.style.createStyleFunction = function(obj) {
* @type {Array.<ol.style.Style>}
*/
var styles;
- if (goog.isArray(obj)) {
+ if (Array.isArray(obj)) {
styles = obj;
} else {
goog.asserts.assertInstanceof(obj, ol.style.Style,
@@ -57777,17 +48688,6 @@ ol.style.createDefaultEditingStyles = function() {
/**
- * A function that takes an {@link ol.Feature} as argument and returns an
- * {@link ol.geom.Geometry} that will be rendered and styled for the feature.
- *
- * @typedef {function((ol.Feature|ol.render.Feature)):
- * (ol.geom.Geometry|ol.render.Feature|undefined)}
- * @api
- */
-ol.style.GeometryFunction;
-
-
-/**
* Function that is called with a feature and returns its default geometry.
* @param {ol.Feature|ol.render.Feature} feature Feature to get the geometry
* for.
@@ -57801,9 +48701,9 @@ ol.style.defaultGeometryFunction = function(feature) {
goog.provide('ol.layer.Vector');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('ol');
goog.require('ol.layer.Layer');
+goog.require('ol.object');
goog.require('ol.style.Style');
@@ -57815,7 +48715,6 @@ ol.layer.VectorProperty = {
};
-
/**
* @classdesc
* Vector data that is rendered client-side.
@@ -57839,7 +48738,7 @@ ol.layer.Vector = function(opt_options) {
goog.isFunction(options.renderOrder),
'renderOrder must be a comparator function');
- var baseOptions = goog.object.clone(options);
+ var baseOptions = ol.object.assign({}, options);
delete baseOptions.style;
delete baseOptions.renderBuffer;
@@ -57988,8 +48887,9 @@ ol.layer.Vector.prototype.setStyle = function(style) {
goog.provide('ol.layer.VectorTile');
-goog.require('goog.object');
+goog.require('goog.asserts');
goog.require('ol.layer.Vector');
+goog.require('ol.object');
/**
@@ -58001,6 +48901,25 @@ ol.layer.VectorTileProperty = {
};
+/**
+ * @enum {string}
+ * Render mode for vector tiles:
+ * * `'image'`: Vector tiles are rendered as images. Great performance, but
+ * point symbols and texts are always rotated with the view and pixels are
+ * scaled during zoom animations.
+ * * `'hybrid'`: Polygon and line elements are rendered as images, so pixels
+ * are scaled during zoom animations. Point symbols and texts are accurately
+ * rendered as vectors and can stay upright on rotated views.
+ * * `'vector'`: Vector tiles are rendered as vectors. Most accurate rendering
+ * even during animations, but slower performance than the other options.
+ * @api
+ */
+ol.layer.VectorTileRenderType = {
+ IMAGE: 'image',
+ HYBRID: 'hybrid',
+ VECTOR: 'vector'
+};
+
/**
* @classdesc
@@ -58017,7 +48936,7 @@ ol.layer.VectorTileProperty = {
ol.layer.VectorTile = function(opt_options) {
var options = opt_options ? opt_options : {};
- var baseOptions = goog.object.clone(options);
+ var baseOptions = ol.object.assign({}, options);
delete baseOptions.preload;
delete baseOptions.useInterimTilesOnError;
@@ -58027,6 +48946,18 @@ ol.layer.VectorTile = function(opt_options) {
this.setUseInterimTilesOnError(options.useInterimTilesOnError ?
options.useInterimTilesOnError : true);
+ goog.asserts.assert(options.renderMode == undefined ||
+ options.renderMode == ol.layer.VectorTileRenderType.IMAGE ||
+ options.renderMode == ol.layer.VectorTileRenderType.HYBRID ||
+ options.renderMode == ol.layer.VectorTileRenderType.VECTOR,
+ 'renderMode needs to be \'image\', \'hybrid\' or \'vector\'');
+
+ /**
+ * @private
+ * @type {ol.layer.VectorTileRenderType|string}
+ */
+ this.renderMode_ = options.renderMode || ol.layer.VectorTileRenderType.HYBRID;
+
};
goog.inherits(ol.layer.VectorTile, ol.layer.Vector);
@@ -58043,12 +48974,11 @@ ol.layer.VectorTile.prototype.getPreload = function() {
/**
- * Return the associated {@link ol.source.VectorTile source} of the layer.
- * @function
- * @return {ol.source.VectorTile} Source.
- * @api
+ * @return {ol.layer.VectorTileRenderType|string} The render mode.
*/
-ol.layer.VectorTile.prototype.getSource;
+ol.layer.VectorTile.prototype.getRenderMode = function() {
+ return this.renderMode_;
+};
/**
@@ -58080,8 +49010,7 @@ ol.layer.VectorTile.prototype.setPreload = function(preload) {
* @observable
* @api
*/
-ol.layer.VectorTile.prototype.setUseInterimTilesOnError =
- function(useInterimTilesOnError) {
+ol.layer.VectorTile.prototype.setUseInterimTilesOnError = function(useInterimTilesOnError) {
this.set(
ol.layer.TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
};
@@ -58092,12 +49021,13 @@ ol.layer.VectorTile.prototype.setUseInterimTilesOnError =
goog.provide('ol.render.canvas.Immediate');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.vec.Mat4');
goog.require('ol.array');
goog.require('ol.color');
+goog.require('ol.colorlike');
goog.require('ol.extent');
+goog.require('ol.geom.GeometryType');
goog.require('ol.geom.flat.transform');
goog.require('ol.has');
goog.require('ol.render.VectorContext');
@@ -58105,7 +49035,6 @@ goog.require('ol.render.canvas');
goog.require('ol.vec.Mat4');
-
/**
* @classdesc
* A concrete subclass of {@link ol.render.VectorContext} that implements
@@ -58124,15 +49053,8 @@ goog.require('ol.vec.Mat4');
* @param {number} viewRotation View rotation.
* @struct
*/
-ol.render.canvas.Immediate =
- function(context, pixelRatio, extent, transform, viewRotation) {
-
- /**
- * @private
- * @type {!Object.<string,
- * Array.<function(ol.render.canvas.Immediate)>>}
- */
- this.callbacksByZIndex_ = {};
+ol.render.canvas.Immediate = function(context, pixelRatio, extent, transform, viewRotation) {
+ goog.base(this);
/**
* @private
@@ -58166,31 +49088,31 @@ ol.render.canvas.Immediate =
/**
* @private
- * @type {?ol.render.canvas.FillState}
+ * @type {?ol.CanvasFillState}
*/
this.contextFillState_ = null;
/**
* @private
- * @type {?ol.render.canvas.StrokeState}
+ * @type {?ol.CanvasStrokeState}
*/
this.contextStrokeState_ = null;
/**
* @private
- * @type {?ol.render.canvas.TextState}
+ * @type {?ol.CanvasTextState}
*/
this.contextTextState_ = null;
/**
* @private
- * @type {?ol.render.canvas.FillState}
+ * @type {?ol.CanvasFillState}
*/
this.fillState_ = null;
/**
* @private
- * @type {?ol.render.canvas.StrokeState}
+ * @type {?ol.CanvasStrokeState}
*/
this.strokeState_ = null;
@@ -58298,19 +49220,19 @@ ol.render.canvas.Immediate =
/**
* @private
- * @type {?ol.render.canvas.FillState}
+ * @type {?ol.CanvasFillState}
*/
this.textFillState_ = null;
/**
* @private
- * @type {?ol.render.canvas.StrokeState}
+ * @type {?ol.CanvasStrokeState}
*/
this.textStrokeState_ = null;
/**
* @private
- * @type {?ol.render.canvas.TextState}
+ * @type {?ol.CanvasTextState}
*/
this.textState_ = null;
@@ -58327,6 +49249,7 @@ ol.render.canvas.Immediate =
this.tmpLocalTransform_ = goog.vec.Mat4.createNumber();
};
+goog.inherits(ol.render.canvas.Immediate, ol.render.VectorContext);
/**
@@ -58336,8 +49259,7 @@ ol.render.canvas.Immediate =
* @param {number} stride Stride.
* @private
*/
-ol.render.canvas.Immediate.prototype.drawImages_ =
- function(flatCoordinates, offset, end, stride) {
+ol.render.canvas.Immediate.prototype.drawImages_ = function(flatCoordinates, offset, end, stride) {
if (!this.image_) {
return;
}
@@ -58362,8 +49284,8 @@ ol.render.canvas.Immediate.prototype.drawImages_ =
var x = pixelCoordinates[i] - this.imageAnchorX_;
var y = pixelCoordinates[i + 1] - this.imageAnchorY_;
if (this.imageSnapToPixel_) {
- x = (x + 0.5) | 0;
- y = (y + 0.5) | 0;
+ x = Math.round(x);
+ y = Math.round(y);
}
if (rotation !== 0 || this.imageScale_ != 1) {
var centerX = x + this.imageAnchorX_;
@@ -58399,8 +49321,7 @@ ol.render.canvas.Immediate.prototype.drawImages_ =
* @param {number} stride Stride.
* @private
*/
-ol.render.canvas.Immediate.prototype.drawText_ =
- function(flatCoordinates, offset, end, stride) {
+ol.render.canvas.Immediate.prototype.drawText_ = function(flatCoordinates, offset, end, stride) {
if (!this.textState_ || this.text_ === '') {
return;
}
@@ -58454,19 +49375,21 @@ ol.render.canvas.Immediate.prototype.drawText_ =
* @private
* @return {number} end End.
*/
-ol.render.canvas.Immediate.prototype.moveToLineTo_ =
- function(flatCoordinates, offset, end, stride, close) {
+ol.render.canvas.Immediate.prototype.moveToLineTo_ = function(flatCoordinates, offset, end, stride, close) {
var context = this.context_;
var pixelCoordinates = ol.geom.flat.transform.transform2D(
flatCoordinates, offset, end, stride, this.transform_,
this.pixelCoordinates_);
context.moveTo(pixelCoordinates[0], pixelCoordinates[1]);
- var i;
- for (i = 2; i < pixelCoordinates.length; i += 2) {
+ var length = pixelCoordinates.length;
+ if (close) {
+ length -= 2;
+ }
+ for (var i = 2; i < length; i += 2) {
context.lineTo(pixelCoordinates[i], pixelCoordinates[i + 1]);
}
if (close) {
- context.lineTo(pixelCoordinates[0], pixelCoordinates[1]);
+ context.closePath();
}
return end;
};
@@ -58480,49 +49403,25 @@ ol.render.canvas.Immediate.prototype.moveToLineTo_ =
* @private
* @return {number} End.
*/
-ol.render.canvas.Immediate.prototype.drawRings_ =
- function(flatCoordinates, offset, ends, stride) {
- var context = this.context_;
+ol.render.canvas.Immediate.prototype.drawRings_ = function(flatCoordinates, offset, ends, stride) {
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
offset = this.moveToLineTo_(
flatCoordinates, offset, ends[i], stride, true);
- context.closePath(); // FIXME is this needed here?
}
return offset;
};
/**
- * Register a function to be called for rendering at a given zIndex. The
- * function will be called asynchronously. The callback will receive a
- * reference to {@link ol.render.canvas.Immediate} context for drawing.
- *
- * @param {number} zIndex Z index.
- * @param {function(ol.render.canvas.Immediate)} callback Callback.
- * @api
- */
-ol.render.canvas.Immediate.prototype.drawAsync = function(zIndex, callback) {
- var zIndexKey = zIndex.toString();
- var callbacks = this.callbacksByZIndex_[zIndexKey];
- if (callbacks !== undefined) {
- callbacks.push(callback);
- } else {
- this.callbacksByZIndex_[zIndexKey] = [callback];
- }
-};
-
-
-/**
* Render a circle geometry into the canvas. Rendering is immediate and uses
* the current fill and stroke styles.
*
- * @param {ol.geom.Circle} circleGeometry Circle geometry.
+ * @param {ol.geom.Circle} geometry Circle geometry.
* @api
*/
-ol.render.canvas.Immediate.prototype.drawCircleGeometry =
- function(circleGeometry) {
- if (!ol.extent.intersects(this.extent_, circleGeometry.getExtent())) {
+ol.render.canvas.Immediate.prototype.drawCircle = function(geometry) {
+ if (!ol.extent.intersects(this.extent_, geometry.getExtent())) {
return;
}
if (this.fillState_ || this.strokeState_) {
@@ -58533,7 +49432,7 @@ ol.render.canvas.Immediate.prototype.drawCircleGeometry =
this.setContextStrokeState_(this.strokeState_);
}
var pixelCoordinates = ol.geom.transformSimpleGeometry2D(
- circleGeometry, this.transform_, this.pixelCoordinates_);
+ geometry, this.transform_, this.pixelCoordinates_);
var dx = pixelCoordinates[2] - pixelCoordinates[0];
var dy = pixelCoordinates[3] - pixelCoordinates[1];
var radius = Math.sqrt(dx * dx + dy * dy);
@@ -58549,17 +49448,70 @@ ol.render.canvas.Immediate.prototype.drawCircleGeometry =
}
}
if (this.text_ !== '') {
- this.drawText_(circleGeometry.getCenter(), 0, 2, 2);
+ this.drawText_(geometry.getCenter(), 0, 2, 2);
+ }
+};
+
+
+/**
+ * Set the rendering style. Note that since this is an immediate rendering API,
+ * any `zIndex` on the provided style will be ignored.
+ *
+ * @param {ol.style.Style} style The rendering style.
+ * @api
+ */
+ol.render.canvas.Immediate.prototype.setStyle = function(style) {
+ this.setFillStrokeStyle(style.getFill(), style.getStroke());
+ this.setImageStyle(style.getImage());
+ this.setTextStyle(style.getText());
+};
+
+
+/**
+ * Render a geometry into the canvas. Call
+ * {@link ol.render.canvas.Immediate#setStyle} first to set the rendering style.
+ *
+ * @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render.
+ * @api
+ */
+ol.render.canvas.Immediate.prototype.drawGeometry = function(geometry) {
+ var type = geometry.getType();
+ switch (type) {
+ case ol.geom.GeometryType.POINT:
+ this.drawPoint(/** @type {ol.geom.Point} */ (geometry));
+ break;
+ case ol.geom.GeometryType.LINE_STRING:
+ this.drawLineString(/** @type {ol.geom.LineString} */ (geometry));
+ break;
+ case ol.geom.GeometryType.POLYGON:
+ this.drawPolygon(/** @type {ol.geom.Polygon} */ (geometry));
+ break;
+ case ol.geom.GeometryType.MULTI_POINT:
+ this.drawMultiPoint(/** @type {ol.geom.MultiPoint} */ (geometry));
+ break;
+ case ol.geom.GeometryType.MULTI_LINE_STRING:
+ this.drawMultiLineString(/** @type {ol.geom.MultiLineString} */ (geometry));
+ break;
+ case ol.geom.GeometryType.MULTI_POLYGON:
+ this.drawMultiPolygon(/** @type {ol.geom.MultiPolygon} */ (geometry));
+ break;
+ case ol.geom.GeometryType.GEOMETRY_COLLECTION:
+ this.drawGeometryCollection(/** @type {ol.geom.GeometryCollection} */ (geometry));
+ break;
+ case ol.geom.GeometryType.CIRCLE:
+ this.drawCircle(/** @type {ol.geom.Circle} */ (geometry));
+ break;
+ default:
+ goog.asserts.fail('Unsupported geometry type: ' + type);
}
};
/**
- * Render a feature into the canvas. In order to respect the zIndex of the
- * style this method draws asynchronously and thus *after* calls to
- * drawXxxxGeometry have been finished, effectively drawing the feature
- * *on top* of everything else. You probably should be using an
- * {@link ol.layer.Vector} instead of calling this method directly.
+ * Render a feature into the canvas. Note that any `zIndex` on the provided
+ * style will be ignored - features are rendered immediately in the order that
+ * this method is called. If you need `zIndex` support, you should be using an
+ * {@link ol.layer.Vector} instead.
*
* @param {ol.Feature} feature Feature.
* @param {ol.style.Style} style Style.
@@ -58571,20 +49523,9 @@ ol.render.canvas.Immediate.prototype.drawFeature = function(feature, style) {
!ol.extent.intersects(this.extent_, geometry.getExtent())) {
return;
}
- var zIndex = style.getZIndex();
- if (zIndex === undefined) {
- zIndex = 0;
- }
- this.drawAsync(zIndex, function(render) {
- render.setFillStrokeStyle(style.getFill(), style.getStroke());
- render.setImageStyle(style.getImage());
- render.setTextStyle(style.getText());
- var renderGeometry =
- ol.render.canvas.Immediate.GEOMETRY_RENDERERS_[geometry.getType()];
- goog.asserts.assert(renderGeometry !== undefined,
- 'renderGeometry should be defined');
- renderGeometry.call(render, geometry, null);
- });
+ this.setStyle(style);
+ goog.asserts.assert(geometry, 'geometry must be truthy');
+ this.drawGeometry(geometry);
};
@@ -58592,21 +49533,13 @@ ol.render.canvas.Immediate.prototype.drawFeature = function(feature, style) {
* Render a GeometryCollection to the canvas. Rendering is immediate and
* uses the current styles appropriate for each geometry in the collection.
*
- * @param {ol.geom.GeometryCollection} geometryCollectionGeometry Geometry
- * collection.
- * @param {ol.Feature} feature Feature.
+ * @param {ol.geom.GeometryCollection} geometry Geometry collection.
*/
-ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry =
- function(geometryCollectionGeometry, feature) {
- var geometries = geometryCollectionGeometry.getGeometriesArray();
+ol.render.canvas.Immediate.prototype.drawGeometryCollection = function(geometry) {
+ var geometries = geometry.getGeometriesArray();
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
- var geometry = geometries[i];
- var geometryRenderer =
- ol.render.canvas.Immediate.GEOMETRY_RENDERERS_[geometry.getType()];
- goog.asserts.assert(geometryRenderer !== undefined,
- 'geometryRenderer should be defined');
- geometryRenderer.call(this, geometry, feature);
+ this.drawGeometry(geometries[i]);
}
};
@@ -58615,13 +49548,11 @@ ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry =
* Render a Point geometry into the canvas. Rendering is immediate and uses
* the current style.
*
- * @param {ol.geom.Point|ol.render.Feature} pointGeometry Point geometry.
- * @api
+ * @param {ol.geom.Point|ol.render.Feature} geometry Point geometry.
*/
-ol.render.canvas.Immediate.prototype.drawPointGeometry =
- function(pointGeometry) {
- var flatCoordinates = pointGeometry.getFlatCoordinates();
- var stride = pointGeometry.getStride();
+ol.render.canvas.Immediate.prototype.drawPoint = function(geometry) {
+ var flatCoordinates = geometry.getFlatCoordinates();
+ var stride = geometry.getStride();
if (this.image_) {
this.drawImages_(flatCoordinates, 0, flatCoordinates.length, stride);
}
@@ -58635,14 +49566,11 @@ ol.render.canvas.Immediate.prototype.drawPointGeometry =
* Render a MultiPoint geometry into the canvas. Rendering is immediate and
* uses the current style.
*
- * @param {ol.geom.MultiPoint|ol.render.Feature} multiPointGeometry MultiPoint
- * geometry.
- * @api
+ * @param {ol.geom.MultiPoint|ol.render.Feature} geometry MultiPoint geometry.
*/
-ol.render.canvas.Immediate.prototype.drawMultiPointGeometry =
- function(multiPointGeometry) {
- var flatCoordinates = multiPointGeometry.getFlatCoordinates();
- var stride = multiPointGeometry.getStride();
+ol.render.canvas.Immediate.prototype.drawMultiPoint = function(geometry) {
+ var flatCoordinates = geometry.getFlatCoordinates();
+ var stride = geometry.getStride();
if (this.image_) {
this.drawImages_(flatCoordinates, 0, flatCoordinates.length, stride);
}
@@ -58656,26 +49584,23 @@ ol.render.canvas.Immediate.prototype.drawMultiPointGeometry =
* Render a LineString into the canvas. Rendering is immediate and uses
* the current style.
*
- * @param {ol.geom.LineString|ol.render.Feature} lineStringGeometry Line
- * string geometry.
- * @api
+ * @param {ol.geom.LineString|ol.render.Feature} geometry LineString geometry.
*/
-ol.render.canvas.Immediate.prototype.drawLineStringGeometry =
- function(lineStringGeometry) {
- if (!ol.extent.intersects(this.extent_, lineStringGeometry.getExtent())) {
+ol.render.canvas.Immediate.prototype.drawLineString = function(geometry) {
+ if (!ol.extent.intersects(this.extent_, geometry.getExtent())) {
return;
}
if (this.strokeState_) {
this.setContextStrokeState_(this.strokeState_);
var context = this.context_;
- var flatCoordinates = lineStringGeometry.getFlatCoordinates();
+ var flatCoordinates = geometry.getFlatCoordinates();
context.beginPath();
this.moveToLineTo_(flatCoordinates, 0, flatCoordinates.length,
- lineStringGeometry.getStride(), false);
+ geometry.getStride(), false);
context.stroke();
}
if (this.text_ !== '') {
- var flatMidpoint = lineStringGeometry.getFlatMidpoint();
+ var flatMidpoint = geometry.getFlatMidpoint();
this.drawText_(flatMidpoint, 0, 2, 2);
}
};
@@ -58685,23 +49610,21 @@ ol.render.canvas.Immediate.prototype.drawLineStringGeometry =
* Render a MultiLineString geometry into the canvas. Rendering is immediate
* and uses the current style.
*
- * @param {ol.geom.MultiLineString|ol.render.Feature} multiLineStringGeometry
- * MultiLineString geometry.
- * @api
+ * @param {ol.geom.MultiLineString|ol.render.Feature} geometry MultiLineString
+ * geometry.
*/
-ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry =
- function(multiLineStringGeometry) {
- var geometryExtent = multiLineStringGeometry.getExtent();
+ol.render.canvas.Immediate.prototype.drawMultiLineString = function(geometry) {
+ var geometryExtent = geometry.getExtent();
if (!ol.extent.intersects(this.extent_, geometryExtent)) {
return;
}
if (this.strokeState_) {
this.setContextStrokeState_(this.strokeState_);
var context = this.context_;
- var flatCoordinates = multiLineStringGeometry.getFlatCoordinates();
+ var flatCoordinates = geometry.getFlatCoordinates();
var offset = 0;
- var ends = multiLineStringGeometry.getEnds();
- var stride = multiLineStringGeometry.getStride();
+ var ends = geometry.getEnds();
+ var stride = geometry.getStride();
context.beginPath();
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
@@ -58711,7 +49634,7 @@ ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry =
context.stroke();
}
if (this.text_ !== '') {
- var flatMidpoints = multiLineStringGeometry.getFlatMidpoints();
+ var flatMidpoints = geometry.getFlatMidpoints();
this.drawText_(flatMidpoints, 0, flatMidpoints.length, 2);
}
};
@@ -58721,13 +49644,10 @@ ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry =
* Render a Polygon geometry into the canvas. Rendering is immediate and uses
* the current style.
*
- * @param {ol.geom.Polygon|ol.render.Feature} polygonGeometry Polygon
- * geometry.
- * @api
+ * @param {ol.geom.Polygon|ol.render.Feature} geometry Polygon geometry.
*/
-ol.render.canvas.Immediate.prototype.drawPolygonGeometry =
- function(polygonGeometry) {
- if (!ol.extent.intersects(this.extent_, polygonGeometry.getExtent())) {
+ol.render.canvas.Immediate.prototype.drawPolygon = function(geometry) {
+ if (!ol.extent.intersects(this.extent_, geometry.getExtent())) {
return;
}
if (this.strokeState_ || this.fillState_) {
@@ -58739,8 +49659,8 @@ ol.render.canvas.Immediate.prototype.drawPolygonGeometry =
}
var context = this.context_;
context.beginPath();
- this.drawRings_(polygonGeometry.getOrientedFlatCoordinates(),
- 0, polygonGeometry.getEnds(), polygonGeometry.getStride());
+ this.drawRings_(geometry.getOrientedFlatCoordinates(),
+ 0, geometry.getEnds(), geometry.getStride());
if (this.fillState_) {
context.fill();
}
@@ -58749,7 +49669,7 @@ ol.render.canvas.Immediate.prototype.drawPolygonGeometry =
}
}
if (this.text_ !== '') {
- var flatInteriorPoint = polygonGeometry.getFlatInteriorPoint();
+ var flatInteriorPoint = geometry.getFlatInteriorPoint();
this.drawText_(flatInteriorPoint, 0, 2, 2);
}
};
@@ -58758,12 +49678,10 @@ ol.render.canvas.Immediate.prototype.drawPolygonGeometry =
/**
* Render MultiPolygon geometry into the canvas. Rendering is immediate and
* uses the current style.
- * @param {ol.geom.MultiPolygon} multiPolygonGeometry MultiPolygon geometry.
- * @api
+ * @param {ol.geom.MultiPolygon} geometry MultiPolygon geometry.
*/
-ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry =
- function(multiPolygonGeometry) {
- if (!ol.extent.intersects(this.extent_, multiPolygonGeometry.getExtent())) {
+ol.render.canvas.Immediate.prototype.drawMultiPolygon = function(geometry) {
+ if (!ol.extent.intersects(this.extent_, geometry.getExtent())) {
return;
}
if (this.strokeState_ || this.fillState_) {
@@ -58774,10 +49692,10 @@ ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry =
this.setContextStrokeState_(this.strokeState_);
}
var context = this.context_;
- var flatCoordinates = multiPolygonGeometry.getOrientedFlatCoordinates();
+ var flatCoordinates = geometry.getOrientedFlatCoordinates();
var offset = 0;
- var endss = multiPolygonGeometry.getEndss();
- var stride = multiPolygonGeometry.getStride();
+ var endss = geometry.getEndss();
+ var stride = geometry.getStride();
var i, ii;
for (i = 0, ii = endss.length; i < ii; ++i) {
var ends = endss[i];
@@ -58792,41 +49710,17 @@ ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry =
}
}
if (this.text_ !== '') {
- var flatInteriorPoints = multiPolygonGeometry.getFlatInteriorPoints();
+ var flatInteriorPoints = geometry.getFlatInteriorPoints();
this.drawText_(flatInteriorPoints, 0, flatInteriorPoints.length, 2);
}
};
/**
- * @inheritDoc
- */
-ol.render.canvas.Immediate.prototype.drawText = goog.abstractMethod;
-
-
-/**
- * FIXME: empty description for jsdoc
- */
-ol.render.canvas.Immediate.prototype.flush = function() {
- /** @type {Array.<number>} */
- var zs = Object.keys(this.callbacksByZIndex_).map(Number);
- zs.sort(ol.array.numberSafeCompareFunction);
- var i, ii, callbacks, j, jj;
- for (i = 0, ii = zs.length; i < ii; ++i) {
- callbacks = this.callbacksByZIndex_[zs[i].toString()];
- for (j = 0, jj = callbacks.length; j < jj; ++j) {
- callbacks[j](this);
- }
- }
-};
-
-
-/**
- * @param {ol.render.canvas.FillState} fillState Fill state.
+ * @param {ol.CanvasFillState} fillState Fill state.
* @private
*/
-ol.render.canvas.Immediate.prototype.setContextFillState_ =
- function(fillState) {
+ol.render.canvas.Immediate.prototype.setContextFillState_ = function(fillState) {
var context = this.context_;
var contextFillState = this.contextFillState_;
if (!contextFillState) {
@@ -58843,11 +49737,10 @@ ol.render.canvas.Immediate.prototype.setContextFillState_ =
/**
- * @param {ol.render.canvas.StrokeState} strokeState Stroke state.
+ * @param {ol.CanvasStrokeState} strokeState Stroke state.
* @private
*/
-ol.render.canvas.Immediate.prototype.setContextStrokeState_ =
- function(strokeState) {
+ol.render.canvas.Immediate.prototype.setContextStrokeState_ = function(strokeState) {
var context = this.context_;
var contextStrokeState = this.contextStrokeState_;
if (!contextStrokeState) {
@@ -58872,7 +49765,7 @@ ol.render.canvas.Immediate.prototype.setContextStrokeState_ =
contextStrokeState.lineCap = context.lineCap = strokeState.lineCap;
}
if (ol.has.CANVAS_LINE_DASH) {
- if (!goog.array.equals(
+ if (!ol.array.equals(
contextStrokeState.lineDash, strokeState.lineDash)) {
context.setLineDash(contextStrokeState.lineDash = strokeState.lineDash);
}
@@ -58896,11 +49789,10 @@ ol.render.canvas.Immediate.prototype.setContextStrokeState_ =
/**
- * @param {ol.render.canvas.TextState} textState Text state.
+ * @param {ol.CanvasTextState} textState Text state.
* @private
*/
-ol.render.canvas.Immediate.prototype.setContextTextState_ =
- function(textState) {
+ol.render.canvas.Immediate.prototype.setContextTextState_ = function(textState) {
var context = this.context_;
var contextTextState = this.contextTextState_;
if (!contextTextState) {
@@ -58933,16 +49825,14 @@ ol.render.canvas.Immediate.prototype.setContextTextState_ =
*
* @param {ol.style.Fill} fillStyle Fill style.
* @param {ol.style.Stroke} strokeStyle Stroke style.
- * @api
*/
-ol.render.canvas.Immediate.prototype.setFillStrokeStyle =
- function(fillStyle, strokeStyle) {
+ol.render.canvas.Immediate.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
if (!fillStyle) {
this.fillState_ = null;
} else {
var fillStyleColor = fillStyle.getColor();
this.fillState_ = {
- fillStyle: ol.color.asString(fillStyleColor ?
+ fillStyle: ol.colorlike.asColorLike(fillStyleColor ?
fillStyleColor : ol.render.canvas.defaultFillStyle)
};
}
@@ -58978,7 +49868,6 @@ ol.render.canvas.Immediate.prototype.setFillStrokeStyle =
* the image style.
*
* @param {ol.style.Image} imageStyle Image style.
- * @api
*/
ol.render.canvas.Immediate.prototype.setImageStyle = function(imageStyle) {
if (!imageStyle) {
@@ -59014,7 +49903,6 @@ ol.render.canvas.Immediate.prototype.setImageStyle = function(imageStyle) {
* remove the text style.
*
* @param {ol.style.Text} textStyle Text style.
- * @api
*/
ol.render.canvas.Immediate.prototype.setTextStyle = function(textStyle) {
if (!textStyle) {
@@ -59026,7 +49914,7 @@ ol.render.canvas.Immediate.prototype.setTextStyle = function(textStyle) {
} else {
var textFillStyleColor = textFillStyle.getColor();
this.textFillState_ = {
- fillStyle: ol.color.asString(textFillStyleColor ?
+ fillStyle: ol.colorlike.asColorLike(textFillStyleColor ?
textFillStyleColor : ol.render.canvas.defaultFillStyle)
};
}
@@ -59082,43 +49970,20 @@ ol.render.canvas.Immediate.prototype.setTextStyle = function(textStyle) {
}
};
-
-/**
- * @const
- * @private
- * @type {Object.<ol.geom.GeometryType,
- * function(this: ol.render.canvas.Immediate,
- * (ol.geom.Geometry|ol.render.Feature), Object)>}
- */
-ol.render.canvas.Immediate.GEOMETRY_RENDERERS_ = {
- 'Point': ol.render.canvas.Immediate.prototype.drawPointGeometry,
- 'LineString': ol.render.canvas.Immediate.prototype.drawLineStringGeometry,
- 'Polygon': ol.render.canvas.Immediate.prototype.drawPolygonGeometry,
- 'MultiPoint': ol.render.canvas.Immediate.prototype.drawMultiPointGeometry,
- 'MultiLineString':
- ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry,
- 'MultiPolygon': ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry,
- 'GeometryCollection':
- ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry,
- 'Circle': ol.render.canvas.Immediate.prototype.drawCircleGeometry
-};
-
goog.provide('ol.renderer.canvas.Layer');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.vec.Mat4');
-goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.layer.Layer');
goog.require('ol.render.Event');
goog.require('ol.render.EventType');
+goog.require('ol.render.canvas');
goog.require('ol.render.canvas.Immediate');
goog.require('ol.renderer.Layer');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.Layer}
@@ -59140,11 +50005,10 @@ goog.inherits(ol.renderer.canvas.Layer, ol.renderer.Layer);
/**
* @param {olx.FrameState} frameState Frame state.
- * @param {ol.layer.LayerState} layerState Layer state.
+ * @param {ol.LayerState} layerState Layer state.
* @param {CanvasRenderingContext2D} context Context.
*/
-ol.renderer.canvas.Layer.prototype.composeFrame =
- function(frameState, layerState, context) {
+ol.renderer.canvas.Layer.prototype.composeFrame = function(frameState, layerState, context) {
this.dispatchPreComposeEvent(context, frameState);
@@ -59158,6 +50022,9 @@ ol.renderer.canvas.Layer.prototype.composeFrame =
goog.asserts.assert(extent !== undefined,
'layerState extent is defined');
var pixelRatio = frameState.pixelRatio;
+ var width = frameState.size[0] * pixelRatio;
+ var height = frameState.size[1] * pixelRatio;
+ var rotation = frameState.viewState.rotation;
var topLeft = ol.extent.getTopLeft(extent);
var topRight = ol.extent.getTopRight(extent);
var bottomRight = ol.extent.getBottomRight(extent);
@@ -59173,12 +50040,14 @@ ol.renderer.canvas.Layer.prototype.composeFrame =
bottomLeft, bottomLeft);
context.save();
+ ol.render.canvas.rotateAtOffset(context, -rotation, width / 2, height / 2);
context.beginPath();
context.moveTo(topLeft[0] * pixelRatio, topLeft[1] * pixelRatio);
context.lineTo(topRight[0] * pixelRatio, topRight[1] * pixelRatio);
context.lineTo(bottomRight[0] * pixelRatio, bottomRight[1] * pixelRatio);
context.lineTo(bottomLeft[0] * pixelRatio, bottomLeft[1] * pixelRatio);
context.clip();
+ ol.render.canvas.rotateAtOffset(context, rotation, width / 2, height / 2);
}
var imageTransform = this.getImageTransform();
@@ -59190,24 +50059,12 @@ ol.renderer.canvas.Layer.prototype.composeFrame =
// for performance reasons, context.setTransform is only used
// when the view is rotated. see http://jsperf.com/canvas-transform
- if (frameState.viewState.rotation === 0) {
- var dx = goog.vec.Mat4.getElement(imageTransform, 0, 3);
- var dy = goog.vec.Mat4.getElement(imageTransform, 1, 3);
- var dw = image.width * goog.vec.Mat4.getElement(imageTransform, 0, 0);
- var dh = image.height * goog.vec.Mat4.getElement(imageTransform, 1, 1);
- context.drawImage(image, 0, 0, +image.width, +image.height,
- Math.round(dx), Math.round(dy), Math.round(dw), Math.round(dh));
- } else {
- context.setTransform(
- goog.vec.Mat4.getElement(imageTransform, 0, 0),
- goog.vec.Mat4.getElement(imageTransform, 1, 0),
- goog.vec.Mat4.getElement(imageTransform, 0, 1),
- goog.vec.Mat4.getElement(imageTransform, 1, 1),
- goog.vec.Mat4.getElement(imageTransform, 0, 3),
- goog.vec.Mat4.getElement(imageTransform, 1, 3));
- context.drawImage(image, 0, 0);
- context.setTransform(1, 0, 0, 1, 0, 0);
- }
+ var dx = goog.vec.Mat4.getElement(imageTransform, 0, 3);
+ var dy = goog.vec.Mat4.getElement(imageTransform, 1, 3);
+ var dw = image.width * goog.vec.Mat4.getElement(imageTransform, 0, 0);
+ var dh = image.height * goog.vec.Mat4.getElement(imageTransform, 1, 1);
+ context.drawImage(image, 0, 0, +image.width, +image.height,
+ Math.round(dx), Math.round(dy), Math.round(dw), Math.round(dh));
context.globalAlpha = alpha;
if (clipped) {
@@ -59227,10 +50084,13 @@ ol.renderer.canvas.Layer.prototype.composeFrame =
* @param {goog.vec.Mat4.Number=} opt_transform Transform.
* @private
*/
-ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ =
- function(type, context, frameState, opt_transform) {
+ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ = function(type, context, frameState, opt_transform) {
var layer = this.getLayer();
if (layer.hasListener(type)) {
+ var width = frameState.size[0] * frameState.pixelRatio;
+ var height = frameState.size[1] * frameState.pixelRatio;
+ var rotation = frameState.viewState.rotation;
+ ol.render.canvas.rotateAtOffset(context, -rotation, width / 2, height / 2);
var transform = opt_transform !== undefined ?
opt_transform : this.getTransform(frameState, 0);
var render = new ol.render.canvas.Immediate(
@@ -59239,7 +50099,7 @@ ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ =
var composeEvent = new ol.render.Event(type, layer, render, frameState,
context, null);
layer.dispatchEvent(composeEvent);
- render.flush();
+ ol.render.canvas.rotateAtOffset(context, rotation, width / 2, height / 2);
}
};
@@ -59250,8 +50110,7 @@ ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ =
* @param {goog.vec.Mat4.Number=} opt_transform Transform.
* @protected
*/
-ol.renderer.canvas.Layer.prototype.dispatchPostComposeEvent =
- function(context, frameState, opt_transform) {
+ol.renderer.canvas.Layer.prototype.dispatchPostComposeEvent = function(context, frameState, opt_transform) {
this.dispatchComposeEvent_(ol.render.EventType.POSTCOMPOSE, context,
frameState, opt_transform);
};
@@ -59263,8 +50122,7 @@ ol.renderer.canvas.Layer.prototype.dispatchPostComposeEvent =
* @param {goog.vec.Mat4.Number=} opt_transform Transform.
* @protected
*/
-ol.renderer.canvas.Layer.prototype.dispatchPreComposeEvent =
- function(context, frameState, opt_transform) {
+ol.renderer.canvas.Layer.prototype.dispatchPreComposeEvent = function(context, frameState, opt_transform) {
this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, context,
frameState, opt_transform);
};
@@ -59276,8 +50134,7 @@ ol.renderer.canvas.Layer.prototype.dispatchPreComposeEvent =
* @param {goog.vec.Mat4.Number=} opt_transform Transform.
* @protected
*/
-ol.renderer.canvas.Layer.prototype.dispatchRenderEvent =
- function(context, frameState, opt_transform) {
+ol.renderer.canvas.Layer.prototype.dispatchRenderEvent = function(context, frameState, opt_transform) {
this.dispatchComposeEvent_(ol.render.EventType.RENDER, context,
frameState, opt_transform);
};
@@ -59301,8 +50158,7 @@ ol.renderer.canvas.Layer.prototype.getImageTransform = goog.abstractMethod;
* @protected
* @return {!goog.vec.Mat4.Number} Transform.
*/
-ol.renderer.canvas.Layer.prototype.getTransform =
- function(frameState, offsetX) {
+ol.renderer.canvas.Layer.prototype.getTransform = function(frameState, offsetX) {
var viewState = frameState.viewState;
var pixelRatio = frameState.pixelRatio;
return ol.vec.Mat4.makeTransform2D(this.transform_,
@@ -59318,7 +50174,7 @@ ol.renderer.canvas.Layer.prototype.getTransform =
/**
* @param {olx.FrameState} frameState Frame state.
- * @param {ol.layer.LayerState} layerState Layer state.
+ * @param {ol.LayerState} layerState Layer state.
* @return {boolean} whether composeFrame should be called.
*/
ol.renderer.canvas.Layer.prototype.prepareFrame = goog.abstractMethod;
@@ -59328,59 +50184,15 @@ ol.renderer.canvas.Layer.prototype.prepareFrame = goog.abstractMethod;
* @param {ol.Pixel} pixelOnMap Pixel.
* @param {goog.vec.Mat4.Number} imageTransformInv The transformation matrix
* to convert from a map pixel to a canvas pixel.
- * @return {ol.Pixel}
+ * @return {ol.Pixel} The pixel.
* @protected
*/
-ol.renderer.canvas.Layer.prototype.getPixelOnCanvas =
- function(pixelOnMap, imageTransformInv) {
+ol.renderer.canvas.Layer.prototype.getPixelOnCanvas = function(pixelOnMap, imageTransformInv) {
var pixelOnCanvas = [0, 0];
ol.vec.Mat4.multVec2(imageTransformInv, pixelOnMap, pixelOnCanvas);
return pixelOnCanvas;
};
-
-/**
- * @param {ol.Size} size Size.
- * @return {boolean} True when the canvas with the current size does not exceed
- * the maximum dimensions.
- */
-ol.renderer.canvas.Layer.testCanvasSize = (function() {
-
- /**
- * @type {CanvasRenderingContext2D}
- */
- var context = null;
-
- /**
- * @type {ImageData}
- */
- var imageData = null;
-
- return function(size) {
- if (!context) {
- context = ol.dom.createCanvasContext2D(1, 1);
- imageData = context.createImageData(1, 1);
- var data = imageData.data;
- data[0] = 42;
- data[1] = 84;
- data[2] = 126;
- data[3] = 255;
- }
- var canvas = context.canvas;
- var good = size[0] <= canvas.width && size[1] <= canvas.height;
- if (!good) {
- canvas.width = size[0];
- canvas.height = size[1];
- var x = size[0] - 1;
- var y = size[1] - 1;
- context.putImageData(imageData, x, y);
- var result = context.getImageData(x, y, 1, 1);
- good = goog.array.equals(imageData.data, result.data);
- }
- return good;
- };
-})();
-
goog.provide('ol.render.IReplayGroup');
goog.require('ol.render.VectorContext');
@@ -59409,7 +50221,6 @@ ol.render.REPLAY_ORDER = [
];
-
/**
* @interface
*/
@@ -59417,6 +50228,11 @@ ol.render.IReplayGroup = function() {
};
+/* eslint-disable valid-jsdoc */
+// TODO: enable valid-jsdoc for @interface methods when this issue is resolved
+// https://github.com/eslint/eslint/issues/4887
+
+
/**
* @param {number|undefined} zIndex Z index.
* @param {ol.render.ReplayType} replayType Replay type.
@@ -59442,19 +50258,19 @@ goog.provide('ol.render.canvas.Replay');
goog.provide('ol.render.canvas.ReplayGroup');
goog.provide('ol.render.canvas.TextReplay');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('goog.vec.Mat4');
goog.require('ol');
goog.require('ol.array');
goog.require('ol.color');
+goog.require('ol.colorlike');
goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.extent.Relationship');
goog.require('ol.geom.flat.simplify');
goog.require('ol.geom.flat.transform');
goog.require('ol.has');
+goog.require('ol.object');
goog.require('ol.render.IReplayGroup');
goog.require('ol.render.VectorContext');
goog.require('ol.render.canvas');
@@ -59481,7 +50297,6 @@ ol.render.canvas.Instruction = {
};
-
/**
* @constructor
* @extends {ol.render.VectorContext}
@@ -59573,6 +50388,12 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution) {
* @type {!goog.vec.Mat4.Number}
*/
this.tmpLocalTransform_ = goog.vec.Mat4.createNumber();
+
+ /**
+ * @private
+ * @type {!goog.vec.Mat4.Number}
+ */
+ this.tmpLocalTransformInv_ = goog.vec.Mat4.createNumber();
};
goog.inherits(ol.render.canvas.Replay, ol.render.VectorContext);
@@ -59586,8 +50407,7 @@ goog.inherits(ol.render.canvas.Replay, ol.render.VectorContext);
* @protected
* @return {number} My end.
*/
-ol.render.canvas.Replay.prototype.appendFlatCoordinates =
- function(flatCoordinates, offset, end, stride, close) {
+ol.render.canvas.Replay.prototype.appendFlatCoordinates = function(flatCoordinates, offset, end, stride, close) {
var myEnd = this.coordinates.length;
var extent = this.getBufferedMaxExtent();
@@ -59680,12 +50500,13 @@ ol.render.canvas.Replay.prototype.replay_ = function(
goog.asserts.assert(pixelCoordinates === this.pixelCoordinates_,
'pixelCoordinates should be the same as this.pixelCoordinates_');
}
- var skipFeatures = !goog.object.isEmpty(skippedFeaturesHash);
+ var skipFeatures = !ol.object.isEmpty(skippedFeaturesHash);
var i = 0; // instruction index
var ii = instructions.length; // end of instructions
var d = 0; // data index
var dd; // end of per-instruction data
var localTransform = this.tmpLocalTransform_;
+ var localTransformInv = this.tmpLocalTransformInv_;
var prevX, prevY, roundX, roundY;
while (i < ii) {
var instruction = instructions[i];
@@ -59699,8 +50520,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
!feature.getGeometry()) {
i = /** @type {number} */ (instruction[2]);
} else if (opt_hitExtent !== undefined && !ol.extent.intersects(
- /** @type {Array<number>} */ (opt_hitExtent),
- feature.getGeometry().getExtent())) {
+ opt_hitExtent, feature.getGeometry().getExtent())) {
i = /** @type {number} */ (instruction[2]);
} else {
++i;
@@ -59756,8 +50576,8 @@ ol.render.canvas.Replay.prototype.replay_ = function(
x = pixelCoordinates[d] - anchorX;
y = pixelCoordinates[d + 1] - anchorY;
if (snapToPixel) {
- x = (x + 0.5) | 0;
- y = (y + 0.5) | 0;
+ x = Math.round(x);
+ y = Math.round(y);
}
if (scale != 1 || rotation !== 0) {
var centerX = x + anchorX;
@@ -59765,7 +50585,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
ol.vec.Mat4.makeTransform2D(
localTransform, centerX, centerY, scale, scale,
rotation, -centerX, -centerY);
- context.setTransform(
+ context.transform(
goog.vec.Mat4.getElement(localTransform, 0, 0),
goog.vec.Mat4.getElement(localTransform, 1, 0),
goog.vec.Mat4.getElement(localTransform, 0, 1),
@@ -59778,14 +50598,24 @@ ol.render.canvas.Replay.prototype.replay_ = function(
context.globalAlpha = alpha * opacity;
}
- context.drawImage(image, originX, originY, width, height,
- x, y, width * pixelRatio, height * pixelRatio);
+ var w = (width + originX > image.width) ? image.width - originX : width;
+ var h = (height + originY > image.height) ? image.height - originY : height;
+
+ context.drawImage(image, originX, originY, w, h,
+ x, y, w * pixelRatio, h * pixelRatio);
if (opacity != 1) {
context.globalAlpha = alpha;
}
if (scale != 1 || rotation !== 0) {
- context.setTransform(1, 0, 0, 1, 0, 0);
+ goog.vec.Mat4.invert(localTransform, localTransformInv);
+ context.transform(
+ goog.vec.Mat4.getElement(localTransformInv, 0, 0),
+ goog.vec.Mat4.getElement(localTransformInv, 1, 0),
+ goog.vec.Mat4.getElement(localTransformInv, 0, 1),
+ goog.vec.Mat4.getElement(localTransformInv, 1, 1),
+ goog.vec.Mat4.getElement(localTransformInv, 0, 3),
+ goog.vec.Mat4.getElement(localTransformInv, 1, 3));
}
}
++i;
@@ -59797,7 +50627,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
goog.asserts.assert(goog.isNumber(instruction[2]),
'3rd instruction should be a number');
dd = /** @type {number} */ (instruction[2]);
- goog.asserts.assert(goog.isString(instruction[3]),
+ goog.asserts.assert(typeof instruction[3] === 'string',
'4th instruction should be a string');
text = /** @type {string} */ (instruction[3]);
goog.asserts.assert(goog.isNumber(instruction[4]),
@@ -59812,10 +50642,10 @@ ol.render.canvas.Replay.prototype.replay_ = function(
goog.asserts.assert(goog.isNumber(instruction[7]),
'8th instruction should be a number');
scale = /** @type {number} */ (instruction[7]) * pixelRatio;
- goog.asserts.assert(goog.isBoolean(instruction[8]),
+ goog.asserts.assert(typeof instruction[8] === 'boolean',
'9th instruction should be a boolean');
fill = /** @type {boolean} */ (instruction[8]);
- goog.asserts.assert(goog.isBoolean(instruction[9]),
+ goog.asserts.assert(typeof instruction[9] === 'boolean',
'10th instruction should be a boolean');
stroke = /** @type {boolean} */ (instruction[9]);
for (; d < dd; d += 2) {
@@ -59824,7 +50654,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
if (scale != 1 || rotation !== 0) {
ol.vec.Mat4.makeTransform2D(
localTransform, x, y, scale, scale, rotation, -x, -y);
- context.setTransform(
+ context.transform(
goog.vec.Mat4.getElement(localTransform, 0, 0),
goog.vec.Mat4.getElement(localTransform, 1, 0),
goog.vec.Mat4.getElement(localTransform, 0, 1),
@@ -59861,7 +50691,14 @@ ol.render.canvas.Replay.prototype.replay_ = function(
}
if (scale != 1 || rotation !== 0) {
- context.setTransform(1, 0, 0, 1, 0, 0);
+ goog.vec.Mat4.invert(localTransform, localTransformInv);
+ context.transform(
+ goog.vec.Mat4.getElement(localTransformInv, 0, 0),
+ goog.vec.Mat4.getElement(localTransformInv, 1, 0),
+ goog.vec.Mat4.getElement(localTransformInv, 0, 1),
+ goog.vec.Mat4.getElement(localTransformInv, 1, 1),
+ goog.vec.Mat4.getElement(localTransformInv, 0, 3),
+ goog.vec.Mat4.getElement(localTransformInv, 1, 3));
}
}
++i;
@@ -59911,19 +50748,21 @@ ol.render.canvas.Replay.prototype.replay_ = function(
++i;
break;
case ol.render.canvas.Instruction.SET_FILL_STYLE:
- goog.asserts.assert(goog.isString(instruction[1]),
- '2nd instruction should be a string');
- context.fillStyle = /** @type {string} */ (instruction[1]);
+ goog.asserts.assert(
+ ol.colorlike.isColorLike(instruction[1]),
+ '2nd instruction should be a string, ' +
+ 'CanvasPattern, or CanvasGradient');
+ context.fillStyle = /** @type {ol.ColorLike} */ (instruction[1]);
++i;
break;
case ol.render.canvas.Instruction.SET_STROKE_STYLE:
- goog.asserts.assert(goog.isString(instruction[1]),
+ goog.asserts.assert(typeof instruction[1] === 'string',
'2nd instruction should be a string');
goog.asserts.assert(goog.isNumber(instruction[2]),
'3rd instruction should be a number');
- goog.asserts.assert(goog.isString(instruction[3]),
+ goog.asserts.assert(typeof instruction[3] === 'string',
'4rd instruction should be a string');
- goog.asserts.assert(goog.isString(instruction[4]),
+ goog.asserts.assert(typeof instruction[4] === 'string',
'5th instruction should be a string');
goog.asserts.assert(goog.isNumber(instruction[5]),
'6th instruction should be a number');
@@ -59945,11 +50784,11 @@ ol.render.canvas.Replay.prototype.replay_ = function(
++i;
break;
case ol.render.canvas.Instruction.SET_TEXT_STYLE:
- goog.asserts.assert(goog.isString(instruction[1]),
+ goog.asserts.assert(typeof instruction[1] === 'string',
'2nd instruction should be a string');
- goog.asserts.assert(goog.isString(instruction[2]),
+ goog.asserts.assert(typeof instruction[2] === 'string',
'3rd instruction should be a string');
- goog.asserts.assert(goog.isString(instruction[3]),
+ goog.asserts.assert(typeof instruction[3] === 'string',
'4th instruction should be a string');
context.font = /** @type {string} */ (instruction[1]);
context.textAlign = /** @type {string} */ (instruction[2]);
@@ -60014,8 +50853,7 @@ ol.render.canvas.Replay.prototype.replayHitDetection = function(
/**
* @private
*/
-ol.render.canvas.Replay.prototype.reverseHitDetectionInstructions_ =
- function() {
+ol.render.canvas.Replay.prototype.reverseHitDetectionInstructions_ = function() {
var hitDetectionInstructions = this.hitDetectionInstructions;
// step 1 - reverse array
hitDetectionInstructions.reverse();
@@ -60080,7 +50918,6 @@ ol.render.canvas.Replay.prototype.getBufferedMaxExtent = function() {
};
-
/**
* @constructor
* @extends {ol.render.canvas.Replay}
@@ -60183,8 +51020,7 @@ goog.inherits(ol.render.canvas.ImageReplay, ol.render.canvas.Replay);
* @private
* @return {number} My end.
*/
-ol.render.canvas.ImageReplay.prototype.drawCoordinates_ =
- function(flatCoordinates, offset, end, stride) {
+ol.render.canvas.ImageReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) {
return this.appendFlatCoordinates(
flatCoordinates, offset, end, stride, false);
};
@@ -60193,8 +51029,7 @@ ol.render.canvas.ImageReplay.prototype.drawCoordinates_ =
/**
* @inheritDoc
*/
-ol.render.canvas.ImageReplay.prototype.drawPointGeometry =
- function(pointGeometry, feature) {
+ol.render.canvas.ImageReplay.prototype.drawPoint = function(pointGeometry, feature) {
if (!this.image_) {
return;
}
@@ -60246,8 +51081,7 @@ ol.render.canvas.ImageReplay.prototype.drawPointGeometry =
/**
* @inheritDoc
*/
-ol.render.canvas.ImageReplay.prototype.drawMultiPointGeometry =
- function(multiPointGeometry, feature) {
+ol.render.canvas.ImageReplay.prototype.drawMultiPoint = function(multiPointGeometry, feature) {
if (!this.image_) {
return;
}
@@ -60350,7 +51184,6 @@ ol.render.canvas.ImageReplay.prototype.setImageStyle = function(imageStyle) {
};
-
/**
* @constructor
* @extends {ol.render.canvas.Replay}
@@ -60408,8 +51241,7 @@ goog.inherits(ol.render.canvas.LineStringReplay, ol.render.canvas.Replay);
* @private
* @return {number} end.
*/
-ol.render.canvas.LineStringReplay.prototype.drawFlatCoordinates_ =
- function(flatCoordinates, offset, end, stride) {
+ol.render.canvas.LineStringReplay.prototype.drawFlatCoordinates_ = function(flatCoordinates, offset, end, stride) {
var myBegin = this.coordinates.length;
var myEnd = this.appendFlatCoordinates(
flatCoordinates, offset, end, stride, false);
@@ -60456,7 +51288,7 @@ ol.render.canvas.LineStringReplay.prototype.setStrokeStyle_ = function() {
goog.asserts.assert(miterLimit !== undefined, 'miterLimit should be defined');
if (state.currentStrokeStyle != strokeStyle ||
state.currentLineCap != lineCap ||
- !goog.array.equals(state.currentLineDash, lineDash) ||
+ !ol.array.equals(state.currentLineDash, lineDash) ||
state.currentLineJoin != lineJoin ||
state.currentLineWidth != lineWidth ||
state.currentMiterLimit != miterLimit) {
@@ -60482,8 +51314,7 @@ ol.render.canvas.LineStringReplay.prototype.setStrokeStyle_ = function() {
/**
* @inheritDoc
*/
-ol.render.canvas.LineStringReplay.prototype.drawLineStringGeometry =
- function(lineStringGeometry, feature) {
+ol.render.canvas.LineStringReplay.prototype.drawLineString = function(lineStringGeometry, feature) {
var state = this.state_;
goog.asserts.assert(state, 'state should not be null');
var strokeStyle = state.strokeStyle;
@@ -60510,8 +51341,7 @@ ol.render.canvas.LineStringReplay.prototype.drawLineStringGeometry =
/**
* @inheritDoc
*/
-ol.render.canvas.LineStringReplay.prototype.drawMultiLineStringGeometry =
- function(multiLineStringGeometry, feature) {
+ol.render.canvas.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {
var state = this.state_;
goog.asserts.assert(state, 'state should not be null');
var strokeStyle = state.strokeStyle;
@@ -60557,8 +51387,7 @@ ol.render.canvas.LineStringReplay.prototype.finish = function() {
/**
* @inheritDoc
*/
-ol.render.canvas.LineStringReplay.prototype.setFillStrokeStyle =
- function(fillStyle, strokeStyle) {
+ol.render.canvas.LineStringReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
goog.asserts.assert(this.state_, 'this.state_ should not be null');
goog.asserts.assert(!fillStyle, 'fillStyle should be null');
goog.asserts.assert(strokeStyle, 'strokeStyle should not be null');
@@ -60589,7 +51418,6 @@ ol.render.canvas.LineStringReplay.prototype.setFillStrokeStyle =
};
-
/**
* @constructor
* @extends {ol.render.canvas.Replay}
@@ -60605,14 +51433,14 @@ ol.render.canvas.PolygonReplay = function(tolerance, maxExtent, resolution) {
/**
* @private
- * @type {{currentFillStyle: (string|undefined),
+ * @type {{currentFillStyle: (ol.ColorLike|undefined),
* currentStrokeStyle: (string|undefined),
* currentLineCap: (string|undefined),
* currentLineDash: Array.<number>,
* currentLineJoin: (string|undefined),
* currentLineWidth: (number|undefined),
* currentMiterLimit: (number|undefined),
- * fillStyle: (string|undefined),
+ * fillStyle: (ol.ColorLike|undefined),
* strokeStyle: (string|undefined),
* lineCap: (string|undefined),
* lineDash: Array.<number>,
@@ -60649,8 +51477,7 @@ goog.inherits(ol.render.canvas.PolygonReplay, ol.render.canvas.Replay);
* @private
* @return {number} End.
*/
-ol.render.canvas.PolygonReplay.prototype.drawFlatCoordinatess_ =
- function(flatCoordinates, offset, ends, stride) {
+ol.render.canvas.PolygonReplay.prototype.drawFlatCoordinatess_ = function(flatCoordinates, offset, ends, stride) {
var state = this.state_;
var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
this.instructions.push(beginPathInstruction);
@@ -60690,8 +51517,7 @@ ol.render.canvas.PolygonReplay.prototype.drawFlatCoordinatess_ =
/**
* @inheritDoc
*/
-ol.render.canvas.PolygonReplay.prototype.drawCircleGeometry =
- function(circleGeometry, feature) {
+ol.render.canvas.PolygonReplay.prototype.drawCircle = function(circleGeometry, feature) {
var state = this.state_;
goog.asserts.assert(state, 'state should not be null');
var fillStyle = state.fillStyle;
@@ -60743,8 +51569,7 @@ ol.render.canvas.PolygonReplay.prototype.drawCircleGeometry =
/**
* @inheritDoc
*/
-ol.render.canvas.PolygonReplay.prototype.drawPolygonGeometry =
- function(polygonGeometry, feature) {
+ol.render.canvas.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
var state = this.state_;
goog.asserts.assert(state, 'state should not be null');
var fillStyle = state.fillStyle;
@@ -60779,8 +51604,7 @@ ol.render.canvas.PolygonReplay.prototype.drawPolygonGeometry =
/**
* @inheritDoc
*/
-ol.render.canvas.PolygonReplay.prototype.drawMultiPolygonGeometry =
- function(multiPolygonGeometry, feature) {
+ol.render.canvas.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {
var state = this.state_;
goog.asserts.assert(state, 'state should not be null');
var fillStyle = state.fillStyle;
@@ -60857,15 +51681,14 @@ ol.render.canvas.PolygonReplay.prototype.getBufferedMaxExtent = function() {
/**
* @inheritDoc
*/
-ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyle =
- function(fillStyle, strokeStyle) {
+ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
goog.asserts.assert(this.state_, 'this.state_ should not be null');
goog.asserts.assert(fillStyle || strokeStyle,
'fillStyle or strokeStyle should not be null');
var state = this.state_;
if (fillStyle) {
var fillStyleColor = fillStyle.getColor();
- state.fillStyle = ol.color.asString(fillStyleColor ?
+ state.fillStyle = ol.colorlike.asColorLike(fillStyleColor ?
fillStyleColor : ol.render.canvas.defaultFillStyle);
} else {
state.fillStyle = undefined;
@@ -60950,7 +51773,6 @@ ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function() {
};
-
/**
* @constructor
* @extends {ol.render.canvas.Replay}
@@ -60966,19 +51788,19 @@ ol.render.canvas.TextReplay = function(tolerance, maxExtent, resolution) {
/**
* @private
- * @type {?ol.render.canvas.FillState}
+ * @type {?ol.CanvasFillState}
*/
this.replayFillState_ = null;
/**
* @private
- * @type {?ol.render.canvas.StrokeState}
+ * @type {?ol.CanvasStrokeState}
*/
this.replayStrokeState_ = null;
/**
* @private
- * @type {?ol.render.canvas.TextState}
+ * @type {?ol.CanvasTextState}
*/
this.replayTextState_ = null;
@@ -61014,19 +51836,19 @@ ol.render.canvas.TextReplay = function(tolerance, maxExtent, resolution) {
/**
* @private
- * @type {?ol.render.canvas.FillState}
+ * @type {?ol.CanvasFillState}
*/
this.textFillState_ = null;
/**
* @private
- * @type {?ol.render.canvas.StrokeState}
+ * @type {?ol.CanvasStrokeState}
*/
this.textStrokeState_ = null;
/**
* @private
- * @type {?ol.render.canvas.TextState}
+ * @type {?ol.CanvasTextState}
*/
this.textState_ = null;
@@ -61037,8 +51859,7 @@ goog.inherits(ol.render.canvas.TextReplay, ol.render.canvas.Replay);
/**
* @inheritDoc
*/
-ol.render.canvas.TextReplay.prototype.drawText =
- function(flatCoordinates, offset, end, stride, geometry, feature) {
+ol.render.canvas.TextReplay.prototype.drawText = function(flatCoordinates, offset, end, stride, geometry, feature) {
if (this.text_ === '' || !this.textState_ ||
(!this.textFillState_ && !this.textStrokeState_)) {
return;
@@ -61067,11 +51888,10 @@ ol.render.canvas.TextReplay.prototype.drawText =
/**
- * @param {ol.render.canvas.FillState} fillState Fill state.
+ * @param {ol.CanvasFillState} fillState Fill state.
* @private
*/
-ol.render.canvas.TextReplay.prototype.setReplayFillState_ =
- function(fillState) {
+ol.render.canvas.TextReplay.prototype.setReplayFillState_ = function(fillState) {
var replayFillState = this.replayFillState_;
if (replayFillState &&
replayFillState.fillStyle == fillState.fillStyle) {
@@ -61092,11 +51912,10 @@ ol.render.canvas.TextReplay.prototype.setReplayFillState_ =
/**
- * @param {ol.render.canvas.StrokeState} strokeState Stroke state.
+ * @param {ol.CanvasStrokeState} strokeState Stroke state.
* @private
*/
-ol.render.canvas.TextReplay.prototype.setReplayStrokeState_ =
- function(strokeState) {
+ol.render.canvas.TextReplay.prototype.setReplayStrokeState_ = function(strokeState) {
var replayStrokeState = this.replayStrokeState_;
if (replayStrokeState &&
replayStrokeState.lineCap == strokeState.lineCap &&
@@ -61135,11 +51954,10 @@ ol.render.canvas.TextReplay.prototype.setReplayStrokeState_ =
/**
- * @param {ol.render.canvas.TextState} textState Text state.
+ * @param {ol.CanvasTextState} textState Text state.
* @private
*/
-ol.render.canvas.TextReplay.prototype.setReplayTextState_ =
- function(textState) {
+ol.render.canvas.TextReplay.prototype.setReplayTextState_ = function(textState) {
var replayTextState = this.replayTextState_;
if (replayTextState &&
replayTextState.font == textState.font &&
@@ -61177,7 +51995,7 @@ ol.render.canvas.TextReplay.prototype.setTextStyle = function(textStyle) {
this.textFillState_ = null;
} else {
var textFillStyleColor = textFillStyle.getColor();
- var fillStyle = ol.color.asString(textFillStyleColor ?
+ var fillStyle = ol.colorlike.asColorLike(textFillStyleColor ?
textFillStyleColor : ol.render.canvas.defaultFillStyle);
if (!this.textFillState_) {
this.textFillState_ = {
@@ -61264,7 +52082,6 @@ ol.render.canvas.TextReplay.prototype.setTextStyle = function(textStyle) {
};
-
/**
* @constructor
* @implements {ol.render.IReplayGroup}
@@ -61392,8 +52209,7 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
/**
* @inheritDoc
*/
-ol.render.canvas.ReplayGroup.prototype.getReplay =
- function(zIndex, replayType) {
+ol.render.canvas.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
var zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
var replays = this.replaysByZIndex_[zIndexKey];
if (replays === undefined) {
@@ -61418,7 +52234,7 @@ ol.render.canvas.ReplayGroup.prototype.getReplay =
* @inheritDoc
*/
ol.render.canvas.ReplayGroup.prototype.isEmpty = function() {
- return goog.object.isEmpty(this.replaysByZIndex_);
+ return ol.object.isEmpty(this.replaysByZIndex_);
};
@@ -61429,9 +52245,11 @@ ol.render.canvas.ReplayGroup.prototype.isEmpty = function() {
* @param {number} viewRotation View rotation.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
+ * @param {Array.<ol.render.ReplayType>=} opt_replayTypes Ordered replay types
+ * to replay. Default is {@link ol.render.REPLAY_ORDER}
*/
-ol.render.canvas.ReplayGroup.prototype.replay = function(
- context, pixelRatio, transform, viewRotation, skippedFeaturesHash) {
+ol.render.canvas.ReplayGroup.prototype.replay = function(context, pixelRatio,
+ transform, viewRotation, skippedFeaturesHash, opt_replayTypes) {
/** @type {Array.<number>} */
var zs = Object.keys(this.replaysByZIndex_).map(Number);
@@ -61456,11 +52274,12 @@ ol.render.canvas.ReplayGroup.prototype.replay = function(
context.closePath();
context.clip();
+ var replayTypes = opt_replayTypes ? opt_replayTypes : ol.render.REPLAY_ORDER;
var i, ii, j, jj, replays, replay;
for (i = 0, ii = zs.length; i < ii; ++i) {
replays = this.replaysByZIndex_[zs[i].toString()];
- for (j = 0, jj = ol.render.REPLAY_ORDER.length; j < jj; ++j) {
- replay = replays[ol.render.REPLAY_ORDER[j]];
+ for (j = 0, jj = replayTypes.length; j < jj; ++j) {
+ replay = replays[replayTypes[j]];
if (replay !== undefined) {
replay.replay(context, pixelRatio, transform, viewRotation,
skippedFeaturesHash);
@@ -61491,7 +52310,9 @@ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function(
featureCallback, opt_hitExtent) {
/** @type {Array.<number>} */
var zs = Object.keys(this.replaysByZIndex_).map(Number);
- zs.sort(function(a, b) { return b - a; });
+ zs.sort(function(a, b) {
+ return b - a;
+ });
var i, ii, j, replays, replay, result;
for (i = 0, ii = zs.length; i < ii; ++i) {
@@ -61533,7 +52354,6 @@ goog.require('ol.extent');
goog.require('ol.geom.GeometryType');
-
/**
* Lightweight, read-only, {@link ol.Feature} and {@link ol.geom.Geometry} like
* structure, optimized for rendering and styling. Geometry access through the
@@ -61627,13 +52447,19 @@ ol.render.Feature.prototype.getExtent = function() {
/**
* @return {Array.<number>} Flat coordinates.
*/
-ol.render.Feature.prototype.getFlatCoordinates =
- ol.render.Feature.prototype.getOrientedFlatCoordinates = function() {
+ol.render.Feature.prototype.getOrientedFlatCoordinates = function() {
return this.flatCoordinates_;
};
/**
+ * @return {Array.<number>} Flat coordinates.
+ */
+ol.render.Feature.prototype.getFlatCoordinates =
+ ol.render.Feature.prototype.getOrientedFlatCoordinates;
+
+
+/**
* Get the feature for working with its geometry.
* @return {ol.render.Feature} Feature.
* @api
@@ -61731,15 +52557,14 @@ ol.renderer.vector.getTolerance = function(resolution, pixelRatio) {
* @param {ol.Feature} feature Feature.
* @private
*/
-ol.renderer.vector.renderCircleGeometry_ =
- function(replayGroup, geometry, style, feature) {
+ol.renderer.vector.renderCircleGeometry_ = function(replayGroup, geometry, style, feature) {
var fillStyle = style.getFill();
var strokeStyle = style.getStroke();
if (fillStyle || strokeStyle) {
var polygonReplay = replayGroup.getReplay(
style.getZIndex(), ol.render.ReplayType.POLYGON);
polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
- polygonReplay.drawCircleGeometry(geometry, feature);
+ polygonReplay.drawCircle(geometry, feature);
}
var textStyle = style.getText();
if (textStyle) {
@@ -61756,7 +52581,7 @@ ol.renderer.vector.renderCircleGeometry_ =
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @param {ol.style.Style} style Style.
* @param {number} squaredTolerance Squared tolerance.
- * @param {function(this: T, goog.events.Event)} listener Listener function.
+ * @param {function(this: T, ol.events.Event)} listener Listener function.
* @param {T} thisArg Value to use as `this` when executing `listener`.
* @return {boolean} `true` if style is loading.
* @template T
@@ -61817,8 +52642,7 @@ ol.renderer.vector.renderFeature_ = function(
* @param {ol.Feature} feature Feature.
* @private
*/
-ol.renderer.vector.renderGeometryCollectionGeometry_ =
- function(replayGroup, geometry, style, feature) {
+ol.renderer.vector.renderGeometryCollectionGeometry_ = function(replayGroup, geometry, style, feature) {
var geometries = geometry.getGeometriesArray();
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
@@ -61838,14 +52662,13 @@ ol.renderer.vector.renderGeometryCollectionGeometry_ =
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @private
*/
-ol.renderer.vector.renderLineStringGeometry_ =
- function(replayGroup, geometry, style, feature) {
+ol.renderer.vector.renderLineStringGeometry_ = function(replayGroup, geometry, style, feature) {
var strokeStyle = style.getStroke();
if (strokeStyle) {
var lineStringReplay = replayGroup.getReplay(
style.getZIndex(), ol.render.ReplayType.LINE_STRING);
lineStringReplay.setFillStrokeStyle(null, strokeStyle);
- lineStringReplay.drawLineStringGeometry(geometry, feature);
+ lineStringReplay.drawLineString(geometry, feature);
}
var textStyle = style.getText();
if (textStyle) {
@@ -61864,14 +52687,13 @@ ol.renderer.vector.renderLineStringGeometry_ =
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @private
*/
-ol.renderer.vector.renderMultiLineStringGeometry_ =
- function(replayGroup, geometry, style, feature) {
+ol.renderer.vector.renderMultiLineStringGeometry_ = function(replayGroup, geometry, style, feature) {
var strokeStyle = style.getStroke();
if (strokeStyle) {
var lineStringReplay = replayGroup.getReplay(
style.getZIndex(), ol.render.ReplayType.LINE_STRING);
lineStringReplay.setFillStrokeStyle(null, strokeStyle);
- lineStringReplay.drawMultiLineStringGeometry(geometry, feature);
+ lineStringReplay.drawMultiLineString(geometry, feature);
}
var textStyle = style.getText();
if (textStyle) {
@@ -61892,15 +52714,14 @@ ol.renderer.vector.renderMultiLineStringGeometry_ =
* @param {ol.Feature} feature Feature.
* @private
*/
-ol.renderer.vector.renderMultiPolygonGeometry_ =
- function(replayGroup, geometry, style, feature) {
+ol.renderer.vector.renderMultiPolygonGeometry_ = function(replayGroup, geometry, style, feature) {
var fillStyle = style.getFill();
var strokeStyle = style.getStroke();
if (strokeStyle || fillStyle) {
var polygonReplay = replayGroup.getReplay(
style.getZIndex(), ol.render.ReplayType.POLYGON);
polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
- polygonReplay.drawMultiPolygonGeometry(geometry, feature);
+ polygonReplay.drawMultiPolygon(geometry, feature);
}
var textStyle = style.getText();
if (textStyle) {
@@ -61921,8 +52742,7 @@ ol.renderer.vector.renderMultiPolygonGeometry_ =
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @private
*/
-ol.renderer.vector.renderPointGeometry_ =
- function(replayGroup, geometry, style, feature) {
+ol.renderer.vector.renderPointGeometry_ = function(replayGroup, geometry, style, feature) {
var imageStyle = style.getImage();
if (imageStyle) {
if (imageStyle.getImageState() != ol.style.ImageState.LOADED) {
@@ -61931,7 +52751,7 @@ ol.renderer.vector.renderPointGeometry_ =
var imageReplay = replayGroup.getReplay(
style.getZIndex(), ol.render.ReplayType.IMAGE);
imageReplay.setImageStyle(imageStyle);
- imageReplay.drawPointGeometry(geometry, feature);
+ imageReplay.drawPoint(geometry, feature);
}
var textStyle = style.getText();
if (textStyle) {
@@ -61951,8 +52771,7 @@ ol.renderer.vector.renderPointGeometry_ =
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @private
*/
-ol.renderer.vector.renderMultiPointGeometry_ =
- function(replayGroup, geometry, style, feature) {
+ol.renderer.vector.renderMultiPointGeometry_ = function(replayGroup, geometry, style, feature) {
var imageStyle = style.getImage();
if (imageStyle) {
if (imageStyle.getImageState() != ol.style.ImageState.LOADED) {
@@ -61961,7 +52780,7 @@ ol.renderer.vector.renderMultiPointGeometry_ =
var imageReplay = replayGroup.getReplay(
style.getZIndex(), ol.render.ReplayType.IMAGE);
imageReplay.setImageStyle(imageStyle);
- imageReplay.drawMultiPointGeometry(geometry, feature);
+ imageReplay.drawMultiPoint(geometry, feature);
}
var textStyle = style.getText();
if (textStyle) {
@@ -61982,15 +52801,14 @@ ol.renderer.vector.renderMultiPointGeometry_ =
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @private
*/
-ol.renderer.vector.renderPolygonGeometry_ =
- function(replayGroup, geometry, style, feature) {
+ol.renderer.vector.renderPolygonGeometry_ = function(replayGroup, geometry, style, feature) {
var fillStyle = style.getFill();
var strokeStyle = style.getStroke();
if (fillStyle || strokeStyle) {
var polygonReplay = replayGroup.getReplay(
style.getZIndex(), ol.render.ReplayType.POLYGON);
polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
- polygonReplay.drawPolygonGeometry(geometry, feature);
+ polygonReplay.drawPolygon(geometry, feature);
}
var textStyle = style.getText();
if (textStyle) {
@@ -62028,7 +52846,6 @@ goog.require('ol.ImageBase');
goog.require('ol.ImageState');
-
/**
* @constructor
* @extends {ol.ImageBase}
@@ -62104,7 +52921,7 @@ ol.ImageCanvas.prototype.load = function() {
goog.asserts.assert(this.loader_, 'this.loader_ must be set');
this.state = ol.ImageState.LOADING;
this.changed();
- this.loader_(goog.bind(this.handleLoad_, this));
+ this.loader_(this.handleLoad_.bind(this));
}
};
@@ -62116,22 +52933,8 @@ ol.ImageCanvas.prototype.getImage = function(opt_context) {
return this.canvas_;
};
-
-/**
- * A function that is called to trigger asynchronous canvas drawing. It is
- * called with a "done" callback that should be called when drawing is done.
- * If any error occurs during drawing, the "done" callback should be called with
- * that error.
- *
- * @typedef {function(function(Error))}
- */
-ol.ImageCanvasLoader;
-
goog.provide('ol.reproj');
-goog.require('goog.labs.userAgent.browser');
-goog.require('goog.labs.userAgent.platform');
-goog.require('goog.math');
goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.math');
@@ -62148,8 +52951,18 @@ goog.require('ol.proj');
* @type {boolean}
* @private
*/
-ol.reproj.browserAntialiasesClip_ = !goog.labs.userAgent.browser.isChrome() ||
- goog.labs.userAgent.platform.isIos();
+ol.reproj.browserAntialiasesClip_ = (function(winNav, winChrome) {
+ // Adapted from http://stackoverflow.com/questions/4565112/javascript-how-to-find-out-if-the-user-browser-is-chrome
+ var isOpera = winNav.userAgent.indexOf('OPR') > -1;
+ var isIEedge = winNav.userAgent.indexOf('Edge') > -1;
+ return !(
+ !winNav.userAgent.match('CriOS') && // Not Chrome on iOS
+ winChrome !== null && winChrome !== undefined && // Has chrome in window
+ winNav.vendor === 'Google Inc.' && // Vendor is Google.
+ isOpera == false && // Not Opera
+ isIEedge == false // Not Edge
+ );
+})(goog.global.navigator, goog.global.chrome)
/**
@@ -62190,7 +53003,7 @@ ol.reproj.calculateSourceResolution = function(sourceProj, targetProj,
sourceProj.getPointResolution(sourceResolution, sourceCenter) /
sourceResolution;
- if (goog.math.isFiniteNumber(compensationFactor) && compensationFactor > 0) {
+ if (isFinite(compensationFactor) && compensationFactor > 0) {
sourceResolution /= compensationFactor;
}
@@ -62230,12 +53043,13 @@ ol.reproj.enlargeClipPoint_ = function(centroidX, centroidY, x, y) {
* @param {Array.<{extent: ol.Extent,
* image: (HTMLCanvasElement|Image|HTMLVideoElement)}>} sources
* Array of sources.
+ * @param {number} gutter Gutter of the sources.
* @param {boolean=} opt_renderEdges Render reprojection edges.
* @return {HTMLCanvasElement} Canvas with reprojected data.
*/
ol.reproj.render = function(width, height, pixelRatio,
sourceResolution, sourceExtent, targetResolution, targetExtent,
- triangulation, sources, opt_renderEdges) {
+ triangulation, sources, gutter, opt_renderEdges) {
var context = ol.dom.createCanvasContext2D(Math.round(pixelRatio * width),
Math.round(pixelRatio * height));
@@ -62257,17 +53071,20 @@ ol.reproj.render = function(width, height, pixelRatio,
Math.round(pixelRatio * canvasWidthInUnits / sourceResolution),
Math.round(pixelRatio * canvasHeightInUnits / sourceResolution));
- stitchContext.scale(pixelRatio / sourceResolution,
- pixelRatio / sourceResolution);
- stitchContext.translate(-sourceDataExtent[0], sourceDataExtent[3]);
+ var stitchScale = pixelRatio / sourceResolution;
sources.forEach(function(src, i, arr) {
- var xPos = src.extent[0];
- var yPos = -src.extent[3];
+ var xPos = src.extent[0] - sourceDataExtent[0];
+ var yPos = -(src.extent[3] - sourceDataExtent[3]);
var srcWidth = ol.extent.getWidth(src.extent);
var srcHeight = ol.extent.getHeight(src.extent);
- stitchContext.drawImage(src.image, xPos, yPos, srcWidth, srcHeight);
+ stitchContext.drawImage(
+ src.image,
+ gutter, gutter,
+ src.image.width - 2 * gutter, src.image.height - 2 * gutter,
+ xPos * stitchScale, yPos * stitchScale,
+ srcWidth * stitchScale, srcHeight * stitchScale);
});
var targetTopLeft = ol.extent.getTopLeft(targetExtent);
@@ -62389,22 +53206,12 @@ ol.reproj.render = function(width, height, pixelRatio,
goog.provide('ol.reproj.Triangulation');
goog.require('goog.asserts');
-goog.require('goog.math');
goog.require('ol.extent');
+goog.require('ol.math');
goog.require('ol.proj');
/**
- * Single triangle; consists of 3 source points and 3 target points.
- *
- * @typedef {{source: Array.<ol.Coordinate>,
- * target: Array.<ol.Coordinate>}}
- */
-ol.reproj.Triangle;
-
-
-
-/**
* @classdesc
* Class containing triangulation of the given target extent.
* Used for determining source data and the reprojection itself.
@@ -62436,8 +53243,8 @@ ol.reproj.Triangulation = function(sourceProj, targetProj, targetExtent,
var transformInv = ol.proj.getTransform(this.targetProj_, this.sourceProj_);
/**
- * @param {ol.Coordinate} c
- * @return {ol.Coordinate}
+ * @param {ol.Coordinate} c A coordinate.
+ * @return {ol.Coordinate} Transformed coordinate.
* @private
*/
this.transformInv_ = function(c) {
@@ -62461,7 +53268,7 @@ ol.reproj.Triangulation = function(sourceProj, targetProj, targetExtent,
this.errorThresholdSquared_ = errorThreshold * errorThreshold;
/**
- * @type {Array.<ol.reproj.Triangle>}
+ * @type {Array.<ol.ReprojTriangle>}
* @private
*/
this.triangles_ = [];
@@ -62561,12 +53368,12 @@ ol.reproj.Triangulation = function(sourceProj, targetProj, targetExtent,
/**
* Adds triangle to the triangulation.
- * @param {ol.Coordinate} a
- * @param {ol.Coordinate} b
- * @param {ol.Coordinate} c
- * @param {ol.Coordinate} aSrc
- * @param {ol.Coordinate} bSrc
- * @param {ol.Coordinate} cSrc
+ * @param {ol.Coordinate} a The target a coordinate.
+ * @param {ol.Coordinate} b The target b coordinate.
+ * @param {ol.Coordinate} c The target c coordinate.
+ * @param {ol.Coordinate} aSrc The source a coordinate.
+ * @param {ol.Coordinate} bSrc The source b coordinate.
+ * @param {ol.Coordinate} cSrc The source c coordinate.
* @private
*/
ol.reproj.Triangulation.prototype.addTriangle_ = function(a, b, c,
@@ -62583,14 +53390,14 @@ ol.reproj.Triangulation.prototype.addTriangle_ = function(a, b, c,
* (and reprojects the vertices) if valid.
* Performs quad subdivision if needed to increase precision.
*
- * @param {ol.Coordinate} a
- * @param {ol.Coordinate} b
- * @param {ol.Coordinate} c
- * @param {ol.Coordinate} d
- * @param {ol.Coordinate} aSrc
- * @param {ol.Coordinate} bSrc
- * @param {ol.Coordinate} cSrc
- * @param {ol.Coordinate} dSrc
+ * @param {ol.Coordinate} a The target a coordinate.
+ * @param {ol.Coordinate} b The target b coordinate.
+ * @param {ol.Coordinate} c The target c coordinate.
+ * @param {ol.Coordinate} d The target d coordinate.
+ * @param {ol.Coordinate} aSrc The source a coordinate.
+ * @param {ol.Coordinate} bSrc The source b coordinate.
+ * @param {ol.Coordinate} cSrc The source c coordinate.
+ * @param {ol.Coordinate} dSrc The source d coordinate.
* @param {number} maxSubdivision Maximal allowed subdivision of the quad.
* @private
*/
@@ -62651,10 +53458,10 @@ ol.reproj.Triangulation.prototype.addQuad_ = function(a, b, c, d,
if (wrapsX) {
goog.asserts.assert(this.sourceWorldWidth_);
var centerSrcEstimX =
- (goog.math.modulo(aSrc[0], this.sourceWorldWidth_) +
- goog.math.modulo(cSrc[0], this.sourceWorldWidth_)) / 2;
+ (ol.math.modulo(aSrc[0], this.sourceWorldWidth_) +
+ ol.math.modulo(cSrc[0], this.sourceWorldWidth_)) / 2;
dx = centerSrcEstimX -
- goog.math.modulo(centerSrc[0], this.sourceWorldWidth_);
+ ol.math.modulo(centerSrc[0], this.sourceWorldWidth_);
} else {
dx = (aSrc[0] + cSrc[0]) / 2 - centerSrc[0];
}
@@ -62722,18 +53529,17 @@ ol.reproj.Triangulation.prototype.calculateSourceExtent = function() {
/**
- * @return {Array.<ol.reproj.Triangle>} Array of the calculated triangles.
+ * @return {Array.<ol.ReprojTriangle>} Array of the calculated triangles.
*/
ol.reproj.Triangulation.prototype.getTriangles = function() {
return this.triangles_;
};
goog.provide('ol.reproj.Image');
-goog.provide('ol.reproj.ImageFunctionType');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.ImageBase');
goog.require('ol.ImageState');
goog.require('ol.extent');
@@ -62743,13 +53549,6 @@ goog.require('ol.reproj.Triangulation');
/**
- * @typedef {function(ol.Extent, number, number) : ol.ImageBase}
- */
-ol.reproj.ImageFunctionType;
-
-
-
-/**
* @classdesc
* Class encapsulating single reprojected image.
* See {@link ol.source.Image}.
@@ -62761,7 +53560,7 @@ ol.reproj.ImageFunctionType;
* @param {ol.Extent} targetExtent Target extent.
* @param {number} targetResolution Target resolution.
* @param {number} pixelRatio Pixel ratio.
- * @param {ol.reproj.ImageFunctionType} getImageFunction
+ * @param {ol.ReprojImageFunctionType} getImageFunction
* Function returning source images (extent, resolution, pixelRatio).
*/
ol.reproj.Image = function(sourceProj, targetProj,
@@ -62833,7 +53632,7 @@ ol.reproj.Image = function(sourceProj, targetProj,
/**
* @private
- * @type {goog.events.Key}
+ * @type {?ol.events.Key}
*/
this.sourceListenerKey_ = null;
@@ -62894,7 +53693,7 @@ ol.reproj.Image.prototype.reproject_ = function() {
this.targetResolution_, this.targetExtent_, this.triangulation_, [{
extent: this.sourceImage_.getExtent(),
image: this.sourceImage_.getImage()
- }]);
+ }], 0);
}
this.state = sourceState;
this.changed();
@@ -62914,15 +53713,15 @@ ol.reproj.Image.prototype.load = function() {
sourceState == ol.ImageState.ERROR) {
this.reproject_();
} else {
- this.sourceListenerKey_ = this.sourceImage_.listen(
- goog.events.EventType.CHANGE, function(e) {
+ this.sourceListenerKey_ = ol.events.listen(this.sourceImage_,
+ ol.events.EventType.CHANGE, function(e) {
var sourceState = this.sourceImage_.getState();
if (sourceState == ol.ImageState.LOADED ||
sourceState == ol.ImageState.ERROR) {
this.unlistenSource_();
this.reproject_();
}
- }, false, this);
+ }, this);
this.sourceImage_.load();
}
}
@@ -62935,17 +53734,15 @@ ol.reproj.Image.prototype.load = function() {
ol.reproj.Image.prototype.unlistenSource_ = function() {
goog.asserts.assert(this.sourceListenerKey_,
'this.sourceListenerKey_ should not be null');
- goog.events.unlistenByKey(this.sourceListenerKey_);
+ ol.events.unlistenByKey(this.sourceListenerKey_);
this.sourceListenerKey_ = null;
};
goog.provide('ol.source.Image');
goog.provide('ol.source.ImageEvent');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.events.Event');
-goog.require('ol.Attribution');
+goog.require('ol.events.Event');
goog.require('ol.ImageState');
goog.require('ol.array');
goog.require('ol.extent');
@@ -62955,18 +53752,6 @@ goog.require('ol.source.Source');
/**
- * @typedef {{attributions: (Array.<ol.Attribution>|undefined),
- * extent: (null|ol.Extent|undefined),
- * logo: (string|olx.LogoOptions|undefined),
- * projection: ol.proj.ProjectionLike,
- * resolutions: (Array.<number>|undefined),
- * state: (ol.source.State|undefined)}}
- */
-ol.source.ImageOptions;
-
-
-
-/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
* instantiated in apps.
@@ -62974,7 +53759,7 @@ ol.source.ImageOptions;
*
* @constructor
* @extends {ol.source.Source}
- * @param {ol.source.ImageOptions} options Single image source options.
+ * @param {ol.SourceImageOptions} options Single image source options.
* @api
*/
ol.source.Image = function(options) {
@@ -62994,7 +53779,7 @@ ol.source.Image = function(options) {
this.resolutions_ = options.resolutions !== undefined ?
options.resolutions : null;
goog.asserts.assert(!this.resolutions_ ||
- goog.array.isSorted(this.resolutions_,
+ ol.array.isSorted(this.resolutions_,
function(a, b) {
return b - a;
}, true), 'resolutions must be null or sorted in descending order');
@@ -63030,8 +53815,7 @@ ol.source.Image.prototype.getResolutions = function() {
* @param {number} resolution Resolution.
* @return {number} Resolution.
*/
-ol.source.Image.prototype.findNearestResolution =
- function(resolution) {
+ol.source.Image.prototype.findNearestResolution = function(resolution) {
if (this.resolutions_) {
var idx = ol.array.linearFindNearest(this.resolutions_, resolution, 0);
resolution = this.resolutions_[idx];
@@ -63047,8 +53831,7 @@ ol.source.Image.prototype.findNearestResolution =
* @param {ol.proj.Projection} projection Projection.
* @return {ol.ImageBase} Single image.
*/
-ol.source.Image.prototype.getImage =
- function(extent, resolution, pixelRatio, projection) {
+ol.source.Image.prototype.getImage = function(extent, resolution, pixelRatio, projection) {
var sourceProjection = this.getProjection();
if (!ol.ENABLE_RASTER_REPROJECTION ||
!sourceProjection ||
@@ -63074,10 +53857,10 @@ ol.source.Image.prototype.getImage =
this.reprojectedImage_ = new ol.reproj.Image(
sourceProjection, projection, extent, resolution, pixelRatio,
- goog.bind(function(extent, resolution, pixelRatio) {
+ function(extent, resolution, pixelRatio) {
return this.getImageInternal(extent, resolution,
pixelRatio, sourceProjection);
- }, this));
+ }.bind(this));
this.reprojectedRevision_ = this.getRevision();
return this.reprojectedImage_;
@@ -63098,7 +53881,7 @@ ol.source.Image.prototype.getImageInternal = goog.abstractMethod;
/**
* Handle image change events.
- * @param {goog.events.Event} event Event.
+ * @param {ol.events.Event} event Event.
* @protected
*/
ol.source.Image.prototype.handleImageChange = function(event) {
@@ -63119,6 +53902,8 @@ ol.source.Image.prototype.handleImageChange = function(event) {
new ol.source.ImageEvent(ol.source.ImageEventType.IMAGELOADERROR,
image));
break;
+ default:
+ // pass
}
};
@@ -63134,14 +53919,13 @@ ol.source.Image.defaultImageLoadFunction = function(image, src) {
};
-
/**
* @classdesc
* Events emitted by {@link ol.source.Image} instances are instances of this
* type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.source.ImageEvent}
* @param {string} type Type.
* @param {ol.Image} image The image.
@@ -63158,7 +53942,7 @@ ol.source.ImageEvent = function(type, image) {
this.image = image;
};
-goog.inherits(ol.source.ImageEvent, goog.events.Event);
+goog.inherits(ol.source.ImageEvent, ol.events.Event);
/**
@@ -63191,20 +53975,18 @@ ol.source.ImageEventType = {
goog.provide('ol.source.ImageCanvas');
-goog.require('ol.CanvasFunctionType');
goog.require('ol.ImageCanvas');
goog.require('ol.extent');
goog.require('ol.source.Image');
-
/**
* @classdesc
* Base class for image sources where a canvas element is the image.
*
* @constructor
* @extends {ol.source.Image}
- * @param {olx.source.ImageCanvasOptions} options
+ * @param {olx.source.ImageCanvasOptions} options Constructor options.
* @api
*/
ol.source.ImageCanvas = function(options) {
@@ -63214,8 +53996,7 @@ ol.source.ImageCanvas = function(options) {
logo: options.logo,
projection: options.projection,
resolutions: options.resolutions,
- state: options.state !== undefined ?
- /** @type {ol.source.State} */ (options.state) : undefined
+ state: options.state
});
/**
@@ -63250,8 +54031,7 @@ goog.inherits(ol.source.ImageCanvas, ol.source.Image);
/**
* @inheritDoc
*/
-ol.source.ImageCanvas.prototype.getImageInternal =
- function(extent, resolution, pixelRatio, projection) {
+ol.source.ImageCanvas.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
resolution = this.findNearestResolution(resolution);
var canvas = this.canvas_;
@@ -63282,18 +54062,16 @@ ol.source.ImageCanvas.prototype.getImageInternal =
};
goog.provide('ol.Feature');
-goog.provide('ol.FeatureStyleFunction');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol');
goog.require('ol.Object');
goog.require('ol.geom.Geometry');
goog.require('ol.style.Style');
-
/**
* @classdesc
* A vector object for geographic features with a geometry and other
@@ -63371,24 +54149,24 @@ ol.Feature = function(opt_geometryOrProperties) {
/**
* @private
- * @type {goog.events.Key}
+ * @type {?ol.events.Key}
*/
this.geometryChangeKey_ = null;
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(this.geometryName_),
- this.handleGeometryChanged_, false, this);
+ this.handleGeometryChanged_, this);
if (opt_geometryOrProperties !== undefined) {
if (opt_geometryOrProperties instanceof ol.geom.Geometry ||
!opt_geometryOrProperties) {
- var geometry = /** @type {ol.geom.Geometry} */ (opt_geometryOrProperties);
+ var geometry = opt_geometryOrProperties;
this.setGeometry(geometry);
} else {
goog.asserts.assert(goog.isObject(opt_geometryOrProperties),
'opt_geometryOrProperties should be an Object');
- var properties = /** @type {Object.<string, *>} */
- (opt_geometryOrProperties);
+ /** @type {Object.<string, *>} */
+ var properties = opt_geometryOrProperties;
this.setProperties(properties);
}
}
@@ -63493,13 +54271,13 @@ ol.Feature.prototype.handleGeometryChange_ = function() {
*/
ol.Feature.prototype.handleGeometryChanged_ = function() {
if (this.geometryChangeKey_) {
- goog.events.unlistenByKey(this.geometryChangeKey_);
+ ol.events.unlistenByKey(this.geometryChangeKey_);
this.geometryChangeKey_ = null;
}
var geometry = this.getGeometry();
if (geometry) {
- this.geometryChangeKey_ = goog.events.listen(geometry,
- goog.events.EventType.CHANGE, this.handleGeometryChange_, false, this);
+ this.geometryChangeKey_ = ol.events.listen(geometry,
+ ol.events.EventType.CHANGE, this.handleGeometryChange_, this);
}
this.changed();
};
@@ -63557,30 +54335,18 @@ ol.Feature.prototype.setId = function(id) {
* @api stable
*/
ol.Feature.prototype.setGeometryName = function(name) {
- goog.events.unlisten(
+ ol.events.unlisten(
this, ol.Object.getChangeEventType(this.geometryName_),
- this.handleGeometryChanged_, false, this);
+ this.handleGeometryChanged_, this);
this.geometryName_ = name;
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(this.geometryName_),
- this.handleGeometryChanged_, false, this);
+ this.handleGeometryChanged_, this);
this.handleGeometryChanged_();
};
/**
- * A function that returns an array of {@link ol.style.Style styles} given a
- * resolution. The `this` keyword inside the function references the
- * {@link ol.Feature} to be styled.
- *
- * @typedef {function(this: ol.Feature, number):
- * (ol.style.Style|Array.<ol.style.Style>)}
- * @api stable
- */
-ol.FeatureStyleFunction;
-
-
-/**
* Convert the provided object into a feature style function. Functions passed
* through unchanged. Arrays of ol.style.Style or single style objects wrapped
* in a new feature style function.
@@ -63598,7 +54364,7 @@ ol.Feature.createStyleFunction = function(obj) {
* @type {Array.<ol.style.Style>}
*/
var styles;
- if (goog.isArray(obj)) {
+ if (Array.isArray(obj)) {
styles = obj;
} else {
goog.asserts.assertInstanceof(obj, ol.style.Style,
@@ -63612,5847 +54378,15 @@ ol.Feature.createStyleFunction = function(obj) {
return styleFunction;
};
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Common events for the network classes.
- */
-
-
-goog.provide('goog.net.EventType');
-
-
-/**
- * Event names for network events
- * @enum {string}
- */
-goog.net.EventType = {
- COMPLETE: 'complete',
- SUCCESS: 'success',
- ERROR: 'error',
- ABORT: 'abort',
- READY: 'ready',
- READY_STATE_CHANGE: 'readystatechange',
- TIMEOUT: 'timeout',
- INCREMENTAL_DATA: 'incrementaldata',
- PROGRESS: 'progress'
-};
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-goog.provide('goog.Thenable');
-
-
-
-/**
- * Provides a more strict interface for Thenables in terms of
- * http://promisesaplus.com for interop with {@see goog.Promise}.
- *
- * @interface
- * @extends {IThenable<TYPE>}
- * @template TYPE
- */
-goog.Thenable = function() {};
-
-
-/**
- * Adds callbacks that will operate on the result of the Thenable, returning a
- * new child Promise.
- *
- * If the Thenable is fulfilled, the {@code onFulfilled} callback will be
- * invoked with the fulfillment value as argument, and the child Promise will
- * be fulfilled with the return value of the callback. If the callback throws
- * an exception, the child Promise will be rejected with the thrown value
- * instead.
- *
- * If the Thenable is rejected, the {@code onRejected} callback will be invoked
- * with the rejection reason as argument, and the child Promise will be rejected
- * with the return value of the callback or thrown value.
- *
- * @param {?(function(this:THIS, TYPE): VALUE)=} opt_onFulfilled A
- * function that will be invoked with the fulfillment value if the Promise
- * is fullfilled.
- * @param {?(function(this:THIS, *): *)=} opt_onRejected A function that will
- * be invoked with the rejection reason if the Promise is rejected.
- * @param {THIS=} opt_context An optional context object that will be the
- * execution context for the callbacks. By default, functions are executed
- * with the default this.
- *
- * @return {RESULT} A new Promise that will receive the result
- * of the fulfillment or rejection callback.
- * @template VALUE
- * @template THIS
- *
- * When a Promise (or thenable) is returned from the fulfilled callback,
- * the result is the payload of that promise, not the promise itself.
- *
- * @template RESULT := type('goog.Promise',
- * cond(isUnknown(VALUE), unknown(),
- * mapunion(VALUE, (V) =>
- * cond(isTemplatized(V) && sub(rawTypeOf(V), 'IThenable'),
- * templateTypeOf(V, 0),
- * cond(sub(V, 'Thenable'),
- * unknown(),
- * V)))))
- * =:
- *
- */
-goog.Thenable.prototype.then = function(opt_onFulfilled, opt_onRejected,
- opt_context) {};
-
-
-/**
- * An expando property to indicate that an object implements
- * {@code goog.Thenable}.
- *
- * {@see addImplementation}.
- *
- * @const
- */
-goog.Thenable.IMPLEMENTED_BY_PROP = '$goog_Thenable';
-
-
-/**
- * Marks a given class (constructor) as an implementation of Thenable, so
- * that we can query that fact at runtime. The class must have already
- * implemented the interface.
- * Exports a 'then' method on the constructor prototype, so that the objects
- * also implement the extern {@see goog.Thenable} interface for interop with
- * other Promise implementations.
- * @param {function(new:goog.Thenable,...?)} ctor The class constructor. The
- * corresponding class must have already implemented the interface.
- */
-goog.Thenable.addImplementation = function(ctor) {
- goog.exportProperty(ctor.prototype, 'then', ctor.prototype.then);
- if (COMPILED) {
- ctor.prototype[goog.Thenable.IMPLEMENTED_BY_PROP] = true;
- } else {
- // Avoids dictionary access in uncompiled mode.
- ctor.prototype.$goog_Thenable = true;
- }
-};
-
-
-/**
- * @param {*} object
- * @return {boolean} Whether a given instance implements {@code goog.Thenable}.
- * The class/superclass of the instance must call {@code addImplementation}.
- */
-goog.Thenable.isImplementedBy = function(object) {
- if (!object) {
- return false;
- }
- try {
- if (COMPILED) {
- return !!object[goog.Thenable.IMPLEMENTED_BY_PROP];
- }
- return !!object.$goog_Thenable;
- } catch (e) {
- // Property access seems to be forbidden.
- return false;
- }
-};
-
-// Copyright 2015 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Simple freelist.
- *
- * An anterative to goog.structs.SimplePool, it imposes the requirement that the
- * objects in the list contain a "next" property that can be used to maintain
- * the pool.
- */
-
-goog.provide('goog.async.FreeList');
-
-
-/**
- * @template ITEM
- */
-goog.async.FreeList = goog.defineClass(null, {
- /**
- * @param {function():ITEM} create
- * @param {function(ITEM):void} reset
- * @param {number} limit
- */
- constructor: function(create, reset, limit) {
- /** @const {number} */
- this.limit_ = limit;
- /** @const {function()} */
- this.create_ = create;
- /** @const {function(ITEM):void} */
- this.reset_ = reset;
-
- /** @type {number} */
- this.occupants_ = 0;
- /** @type {ITEM} */
- this.head_ = null;
- },
-
- /**
- * @return {ITEM}
- */
- get: function() {
- var item;
- if (this.occupants_ > 0) {
- this.occupants_--;
- item = this.head_;
- this.head_ = item.next;
- item.next = null;
- } else {
- item = this.create_();
- }
- return item;
- },
-
- /**
- * @param {ITEM} item An item available for possible future reuse.
- */
- put: function(item) {
- this.reset_(item);
- if (this.occupants_ < this.limit_) {
- this.occupants_++;
- item.next = this.head_;
- this.head_ = item;
- }
- },
-
- /**
- * Visible for testing.
- * @package
- * @return {number}
- */
- occupants: function() {
- return this.occupants_;
- }
-});
-
-
-
-
-// Copyright 2015 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-goog.provide('goog.async.WorkItem');
-goog.provide('goog.async.WorkQueue');
-
-goog.require('goog.asserts');
-goog.require('goog.async.FreeList');
-
-
-// TODO(johnlenz): generalize the WorkQueue if this is used by more
-// than goog.async.run.
-
-
-
-/**
- * A low GC workqueue. The key elements of this design:
- * - avoids the need for goog.bind or equivalent by carrying scope
- * - avoids the need for array reallocation by using a linked list
- * - minimizes work entry objects allocation by recycling objects
- * @constructor
- * @final
- * @struct
- */
-goog.async.WorkQueue = function() {
- this.workHead_ = null;
- this.workTail_ = null;
-};
-
-
-/** @define {number} The maximum number of entries to keep for recycling. */
-goog.define('goog.async.WorkQueue.DEFAULT_MAX_UNUSED', 100);
-
-
-/** @const @private {goog.async.FreeList<goog.async.WorkItem>} */
-goog.async.WorkQueue.freelist_ = new goog.async.FreeList(
- function() {return new goog.async.WorkItem(); },
- function(item) {item.reset()},
- goog.async.WorkQueue.DEFAULT_MAX_UNUSED);
-
-
-/**
- * @param {function()} fn
- * @param {Object|null|undefined} scope
- */
-goog.async.WorkQueue.prototype.add = function(fn, scope) {
- var item = this.getUnusedItem_();
- item.set(fn, scope);
-
- if (this.workTail_) {
- this.workTail_.next = item;
- this.workTail_ = item;
- } else {
- goog.asserts.assert(!this.workHead_);
- this.workHead_ = item;
- this.workTail_ = item;
- }
-};
-
-
-/**
- * @return {goog.async.WorkItem}
- */
-goog.async.WorkQueue.prototype.remove = function() {
- var item = null;
-
- if (this.workHead_) {
- item = this.workHead_;
- this.workHead_ = this.workHead_.next;
- if (!this.workHead_) {
- this.workTail_ = null;
- }
- item.next = null;
- }
- return item;
-};
-
-
-/**
- * @param {goog.async.WorkItem} item
- */
-goog.async.WorkQueue.prototype.returnUnused = function(item) {
- goog.async.WorkQueue.freelist_.put(item);
-};
-
-
-/**
- * @return {goog.async.WorkItem}
- * @private
- */
-goog.async.WorkQueue.prototype.getUnusedItem_ = function() {
- return goog.async.WorkQueue.freelist_.get();
-};
-
-
-
-/**
- * @constructor
- * @final
- * @struct
- */
-goog.async.WorkItem = function() {
- /** @type {?function()} */
- this.fn = null;
- /** @type {Object|null|undefined} */
- this.scope = null;
- /** @type {?goog.async.WorkItem} */
- this.next = null;
-};
-
-
-/**
- * @param {function()} fn
- * @param {Object|null|undefined} scope
- */
-goog.async.WorkItem.prototype.set = function(fn, scope) {
- this.fn = fn;
- this.scope = scope;
- this.next = null;
-};
-
-
-/** Reset the work item so they don't prevent GC before reuse */
-goog.async.WorkItem.prototype.reset = function() {
- this.fn = null;
- this.scope = null;
- this.next = null;
-};
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Simple notifiers for the Closure testing framework.
- *
- * @author johnlenz@google.com (John Lenz)
- */
-
-goog.provide('goog.testing.watchers');
-
-
-/** @private {!Array<function()>} */
-goog.testing.watchers.resetWatchers_ = [];
-
-
-/**
- * Fires clock reset watching functions.
- */
-goog.testing.watchers.signalClockReset = function() {
- var watchers = goog.testing.watchers.resetWatchers_;
- for (var i = 0; i < watchers.length; i++) {
- goog.testing.watchers.resetWatchers_[i]();
- }
-};
-
-
-/**
- * Enqueues a function to be called when the clock used for setTimeout is reset.
- * @param {function()} fn
- */
-goog.testing.watchers.watchClockReset = function(fn) {
- goog.testing.watchers.resetWatchers_.push(fn);
-};
-
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-goog.provide('goog.async.run');
-
-goog.require('goog.async.WorkQueue');
-goog.require('goog.async.nextTick');
-goog.require('goog.async.throwException');
-goog.require('goog.testing.watchers');
-
-
-/**
- * Fires the provided callback just before the current callstack unwinds, or as
- * soon as possible after the current JS execution context.
- * @param {function(this:THIS)} callback
- * @param {THIS=} opt_context Object to use as the "this value" when calling
- * the provided function.
- * @template THIS
- */
-goog.async.run = function(callback, opt_context) {
- if (!goog.async.run.schedule_) {
- goog.async.run.initializeRunner_();
- }
- if (!goog.async.run.workQueueScheduled_) {
- // Nothing is currently scheduled, schedule it now.
- goog.async.run.schedule_();
- goog.async.run.workQueueScheduled_ = true;
- }
-
- goog.async.run.workQueue_.add(callback, opt_context);
-};
-
-
-/**
- * Initializes the function to use to process the work queue.
- * @private
- */
-goog.async.run.initializeRunner_ = function() {
- // If native Promises are available in the browser, just schedule the callback
- // on a fulfilled promise, which is specified to be async, but as fast as
- // possible.
- if (goog.global.Promise && goog.global.Promise.resolve) {
- var promise = goog.global.Promise.resolve(undefined);
- goog.async.run.schedule_ = function() {
- promise.then(goog.async.run.processWorkQueue);
- };
- } else {
- goog.async.run.schedule_ = function() {
- goog.async.nextTick(goog.async.run.processWorkQueue);
- };
- }
-};
-
-
-/**
- * Forces goog.async.run to use nextTick instead of Promise.
- *
- * This should only be done in unit tests. It's useful because MockClock
- * replaces nextTick, but not the browser Promise implementation, so it allows
- * Promise-based code to be tested with MockClock.
- *
- * However, we also want to run promises if the MockClock is no longer in
- * control so we schedule a backup "setTimeout" to the unmocked timeout if
- * provided.
- *
- * @param {function(function())=} opt_realSetTimeout
- */
-goog.async.run.forceNextTick = function(opt_realSetTimeout) {
- goog.async.run.schedule_ = function() {
- goog.async.nextTick(goog.async.run.processWorkQueue);
- if (opt_realSetTimeout) {
- opt_realSetTimeout(goog.async.run.processWorkQueue);
- }
- };
-};
-
-
-/**
- * The function used to schedule work asynchronousely.
- * @private {function()}
- */
-goog.async.run.schedule_;
-
-
-/** @private {boolean} */
-goog.async.run.workQueueScheduled_ = false;
-
-
-/** @private {!goog.async.WorkQueue} */
-goog.async.run.workQueue_ = new goog.async.WorkQueue();
-
-
-if (goog.DEBUG) {
- /**
- * Reset the work queue.
- * @private
- */
- goog.async.run.resetQueue_ = function() {
- goog.async.run.workQueueScheduled_ = false;
- goog.async.run.workQueue_ = new goog.async.WorkQueue();
- };
-
- // If there is a clock implemenation in use for testing
- // and it is reset, reset the queue.
- goog.testing.watchers.watchClockReset(goog.async.run.resetQueue_);
-}
-
-
-/**
- * Run any pending goog.async.run work items. This function is not intended
- * for general use, but for use by entry point handlers to run items ahead of
- * goog.async.nextTick.
- */
-goog.async.run.processWorkQueue = function() {
- // NOTE: additional work queue items may be added while processing.
- var item = null;
- while (item = goog.async.run.workQueue_.remove()) {
- try {
- item.fn.call(item.scope);
- } catch (e) {
- goog.async.throwException(e);
- }
- goog.async.run.workQueue_.returnUnused(item);
- }
-
- // There are no more work items, allow processing to be scheduled again.
- goog.async.run.workQueueScheduled_ = false;
-};
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-goog.provide('goog.promise.Resolver');
-
-
-
-/**
- * Resolver interface for promises. The resolver is a convenience interface that
- * bundles the promise and its associated resolve and reject functions together,
- * for cases where the resolver needs to be persisted internally.
- *
- * @interface
- * @template TYPE
- */
-goog.promise.Resolver = function() {};
-
-
-/**
- * The promise that created this resolver.
- * @type {!goog.Promise<TYPE>}
- */
-goog.promise.Resolver.prototype.promise;
-
-
-/**
- * Resolves this resolver with the specified value.
- * @type {function((TYPE|goog.Promise<TYPE>|Thenable)=)}
- */
-goog.promise.Resolver.prototype.resolve;
-
-
-/**
- * Rejects this resolver with the specified reason.
- * @type {function(*=): void}
- */
-goog.promise.Resolver.prototype.reject;
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-goog.provide('goog.Promise');
-
-goog.require('goog.Thenable');
-goog.require('goog.asserts');
-goog.require('goog.async.FreeList');
-goog.require('goog.async.run');
-goog.require('goog.async.throwException');
-goog.require('goog.debug.Error');
-goog.require('goog.promise.Resolver');
-
-
-
-/**
- * Promises provide a result that may be resolved asynchronously. A Promise may
- * be resolved by being fulfilled with a fulfillment value, rejected with a
- * rejection reason, or blocked by another Promise. A Promise is said to be
- * settled if it is either fulfilled or rejected. Once settled, the Promise
- * result is immutable.
- *
- * Promises may represent results of any type, including undefined. Rejection
- * reasons are typically Errors, but may also be of any type. Closure Promises
- * allow for optional type annotations that enforce that fulfillment values are
- * of the appropriate types at compile time.
- *
- * The result of a Promise is accessible by calling {@code then} and registering
- * {@code onFulfilled} and {@code onRejected} callbacks. Once the Promise
- * is settled, the relevant callbacks are invoked with the fulfillment value or
- * rejection reason as argument. Callbacks are always invoked in the order they
- * were registered, even when additional {@code then} calls are made from inside
- * another callback. A callback is always run asynchronously sometime after the
- * scope containing the registering {@code then} invocation has returned.
- *
- * If a Promise is resolved with another Promise, the first Promise will block
- * until the second is settled, and then assumes the same result as the second
- * Promise. This allows Promises to depend on the results of other Promises,
- * linking together multiple asynchronous operations.
- *
- * This implementation is compatible with the Promises/A+ specification and
- * passes that specification's conformance test suite. A Closure Promise may be
- * resolved with a Promise instance (or sufficiently compatible Promise-like
- * object) created by other Promise implementations. From the specification,
- * Promise-like objects are known as "Thenables".
- *
- * @see http://promisesaplus.com/
- *
- * @param {function(
- * this:RESOLVER_CONTEXT,
- * function((TYPE|IThenable<TYPE>|Thenable)=),
- * function(*=)): void} resolver
- * Initialization function that is invoked immediately with {@code resolve}
- * and {@code reject} functions as arguments. The Promise is resolved or
- * rejected with the first argument passed to either function.
- * @param {RESOLVER_CONTEXT=} opt_context An optional context for executing the
- * resolver function. If unspecified, the resolver function will be executed
- * in the default scope.
- * @constructor
- * @struct
- * @final
- * @implements {goog.Thenable<TYPE>}
- * @template TYPE,RESOLVER_CONTEXT
- */
-goog.Promise = function(resolver, opt_context) {
- /**
- * The internal state of this Promise. Either PENDING, FULFILLED, REJECTED, or
- * BLOCKED.
- * @private {goog.Promise.State_}
- */
- this.state_ = goog.Promise.State_.PENDING;
-
- /**
- * The settled result of the Promise. Immutable once set with either a
- * fulfillment value or rejection reason.
- * @private {*}
- */
- this.result_ = undefined;
-
- /**
- * For Promises created by calling {@code then()}, the originating parent.
- * @private {goog.Promise}
- */
- this.parent_ = null;
-
- /**
- * The linked list of {@code onFulfilled} and {@code onRejected} callbacks
- * added to this Promise by calls to {@code then()}.
- * @private {?goog.Promise.CallbackEntry_}
- */
- this.callbackEntries_ = null;
-
- /**
- * The tail of the linked list of {@code onFulfilled} and {@code onRejected}
- * callbacks added to this Promise by calls to {@code then()}.
- * @private {?goog.Promise.CallbackEntry_}
- */
- this.callbackEntriesTail_ = null;
-
- /**
- * Whether the Promise is in the queue of Promises to execute.
- * @private {boolean}
- */
- this.executing_ = false;
-
- if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
- /**
- * A timeout ID used when the {@code UNHANDLED_REJECTION_DELAY} is greater
- * than 0 milliseconds. The ID is set when the Promise is rejected, and
- * cleared only if an {@code onRejected} callback is invoked for the
- * Promise (or one of its descendants) before the delay is exceeded.
- *
- * If the rejection is not handled before the timeout completes, the
- * rejection reason is passed to the unhandled rejection handler.
- * @private {number}
- */
- this.unhandledRejectionId_ = 0;
- } else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
- /**
- * When the {@code UNHANDLED_REJECTION_DELAY} is set to 0 milliseconds, a
- * boolean that is set if the Promise is rejected, and reset to false if an
- * {@code onRejected} callback is invoked for the Promise (or one of its
- * descendants). If the rejection is not handled before the next timestep,
- * the rejection reason is passed to the unhandled rejection handler.
- * @private {boolean}
- */
- this.hadUnhandledRejection_ = false;
- }
-
- if (goog.Promise.LONG_STACK_TRACES) {
- /**
- * A list of stack trace frames pointing to the locations where this Promise
- * was created or had callbacks added to it. Saved to add additional context
- * to stack traces when an exception is thrown.
- * @private {!Array<string>}
- */
- this.stack_ = [];
- this.addStackTrace_(new Error('created'));
-
- /**
- * Index of the most recently executed stack frame entry.
- * @private {number}
- */
- this.currentStep_ = 0;
- }
-
- // As an optimization, we can skip this if resolver is goog.nullFunction.
- // This value is passed internally when creating a promise which will be
- // resolved through a more optimized path.
- if (resolver != goog.nullFunction) {
- try {
- var self = this;
- resolver.call(
- opt_context,
- function(value) {
- self.resolve_(goog.Promise.State_.FULFILLED, value);
- },
- function(reason) {
- if (goog.DEBUG &&
- !(reason instanceof goog.Promise.CancellationError)) {
- try {
- // Promise was rejected. Step up one call frame to see why.
- if (reason instanceof Error) {
- throw reason;
- } else {
- throw new Error('Promise rejected.');
- }
- } catch (e) {
- // Only thrown so browser dev tools can catch rejections of
- // promises when the option to break on caught exceptions is
- // activated.
- }
- }
- self.resolve_(goog.Promise.State_.REJECTED, reason);
- });
- } catch (e) {
- this.resolve_(goog.Promise.State_.REJECTED, e);
- }
- }
-};
-
-
-/**
- * @define {boolean} Whether traces of {@code then} calls should be included in
- * exceptions thrown
- */
-goog.define('goog.Promise.LONG_STACK_TRACES', false);
-
-
-/**
- * @define {number} The delay in milliseconds before a rejected Promise's reason
- * is passed to the rejection handler. By default, the rejection handler
- * rethrows the rejection reason so that it appears in the developer console or
- * {@code window.onerror} handler.
- *
- * Rejections are rethrown as quickly as possible by default. A negative value
- * disables rejection handling entirely.
- */
-goog.define('goog.Promise.UNHANDLED_REJECTION_DELAY', 0);
-
-
-/**
- * The possible internal states for a Promise. These states are not directly
- * observable to external callers.
- * @enum {number}
- * @private
- */
-goog.Promise.State_ = {
- /** The Promise is waiting for resolution. */
- PENDING: 0,
-
- /** The Promise is blocked waiting for the result of another Thenable. */
- BLOCKED: 1,
-
- /** The Promise has been resolved with a fulfillment value. */
- FULFILLED: 2,
-
- /** The Promise has been resolved with a rejection reason. */
- REJECTED: 3
-};
-
-
-
-/**
- * Entries in the callback chain. Each call to {@code then},
- * {@code thenCatch}, or {@code thenAlways} creates an entry containing the
- * functions that may be invoked once the Promise is settled.
- *
- * @private @final @struct @constructor
- */
-goog.Promise.CallbackEntry_ = function() {
- /** @type {?goog.Promise} */
- this.child = null;
- /** @type {Function} */
- this.onFulfilled = null;
- /** @type {Function} */
- this.onRejected = null;
- /** @type {?} */
- this.context = null;
- /** @type {?goog.Promise.CallbackEntry_} */
- this.next = null;
-
- /**
- * A boolean value to indicate this is a "thenAlways" callback entry.
- * Unlike a normal "then/thenVoid" a "thenAlways doesn't participate
- * in "cancel" considerations but is simply an observer and requires
- * special handling.
- * @type {boolean}
- */
- this.always = false;
-};
-
-
-/** clear the object prior to reuse */
-goog.Promise.CallbackEntry_.prototype.reset = function() {
- this.child = null;
- this.onFulfilled = null;
- this.onRejected = null;
- this.context = null;
- this.always = false;
-};
-
-
-/**
- * @define {number} The number of currently unused objects to keep around for
- * reuse.
- */
-goog.define('goog.Promise.DEFAULT_MAX_UNUSED', 100);
-
-
-/** @const @private {goog.async.FreeList<!goog.Promise.CallbackEntry_>} */
-goog.Promise.freelist_ = new goog.async.FreeList(
- function() {
- return new goog.Promise.CallbackEntry_();
- },
- function(item) {
- item.reset();
- },
- goog.Promise.DEFAULT_MAX_UNUSED);
-
-
-/**
- * @param {Function} onFulfilled
- * @param {Function} onRejected
- * @param {?} context
- * @return {!goog.Promise.CallbackEntry_}
- * @private
- */
-goog.Promise.getCallbackEntry_ = function(onFulfilled, onRejected, context) {
- var entry = goog.Promise.freelist_.get();
- entry.onFulfilled = onFulfilled;
- entry.onRejected = onRejected;
- entry.context = context;
- return entry;
-};
-
-
-/**
- * @param {!goog.Promise.CallbackEntry_} entry
- * @private
- */
-goog.Promise.returnEntry_ = function(entry) {
- goog.Promise.freelist_.put(entry);
-};
-
-
-// NOTE: this is the same template expression as is used for
-// goog.IThenable.prototype.then
-
-
-/**
- * @param {VALUE=} opt_value
- * @return {RESULT} A new Promise that is immediately resolved
- * with the given value. If the input value is already a goog.Promise, it
- * will be returned immediately without creating a new instance.
- * @template VALUE
- * @template RESULT := type('goog.Promise',
- * cond(isUnknown(VALUE), unknown(),
- * mapunion(VALUE, (V) =>
- * cond(isTemplatized(V) && sub(rawTypeOf(V), 'IThenable'),
- * templateTypeOf(V, 0),
- * cond(sub(V, 'Thenable'),
- * unknown(),
- * V)))))
- * =:
- */
-goog.Promise.resolve = function(opt_value) {
- if (opt_value instanceof goog.Promise) {
- // Avoid creating a new object if we already have a promise object
- // of the correct type.
- return opt_value;
- }
-
- // Passing goog.nullFunction will cause the constructor to take an optimized
- // path that skips calling the resolver function.
- var promise = new goog.Promise(goog.nullFunction);
- promise.resolve_(goog.Promise.State_.FULFILLED, opt_value);
- return promise;
-};
-
-
-/**
- * @param {*=} opt_reason
- * @return {!goog.Promise} A new Promise that is immediately rejected with the
- * given reason.
- */
-goog.Promise.reject = function(opt_reason) {
- return new goog.Promise(function(resolve, reject) {
- reject(opt_reason);
- });
-};
-
-
-/**
- * This is identical to
- * {@code goog.Promise.resolve(value).then(onFulfilled, onRejected)}, but it
- * avoids creating an unnecessary wrapper Promise when {@code value} is already
- * thenable.
- *
- * @param {?(goog.Thenable<TYPE>|Thenable|TYPE)} value
- * @param {function(TYPE): ?} onFulfilled
- * @param {function(*): *} onRejected
- * @template TYPE
- * @private
- */
-goog.Promise.resolveThen_ = function(value, onFulfilled, onRejected) {
- var isThenable = goog.Promise.maybeThen_(
- value, onFulfilled, onRejected, null);
- if (!isThenable) {
- goog.async.run(goog.partial(onFulfilled, value));
- }
-};
-
-
-/**
- * @param {!Array<?(goog.Promise<TYPE>|goog.Thenable<TYPE>|Thenable|*)>}
- * promises
- * @return {!goog.Promise<TYPE>} A Promise that receives the result of the
- * first Promise (or Promise-like) input to settle immediately after it
- * settles.
- * @template TYPE
- */
-goog.Promise.race = function(promises) {
- return new goog.Promise(function(resolve, reject) {
- if (!promises.length) {
- resolve(undefined);
- }
- for (var i = 0, promise; i < promises.length; i++) {
- promise = promises[i];
- goog.Promise.resolveThen_(promise, resolve, reject);
- }
- });
-};
-
-
-/**
- * @param {!Array<?(goog.Promise<TYPE>|goog.Thenable<TYPE>|Thenable|*)>}
- * promises
- * @return {!goog.Promise<!Array<TYPE>>} A Promise that receives a list of
- * every fulfilled value once every input Promise (or Promise-like) is
- * successfully fulfilled, or is rejected with the first rejection reason
- * immediately after it is rejected.
- * @template TYPE
- */
-goog.Promise.all = function(promises) {
- return new goog.Promise(function(resolve, reject) {
- var toFulfill = promises.length;
- var values = [];
-
- if (!toFulfill) {
- resolve(values);
- return;
- }
-
- var onFulfill = function(index, value) {
- toFulfill--;
- values[index] = value;
- if (toFulfill == 0) {
- resolve(values);
- }
- };
-
- var onReject = function(reason) {
- reject(reason);
- };
-
- for (var i = 0, promise; i < promises.length; i++) {
- promise = promises[i];
- goog.Promise.resolveThen_(
- promise, goog.partial(onFulfill, i), onReject);
- }
- });
-};
-
-
-/**
- * @param {!Array<?(goog.Promise<TYPE>|goog.Thenable<TYPE>|Thenable|*)>}
- * promises
- * @return {!goog.Promise<!Array<{
- * fulfilled: boolean,
- * value: (TYPE|undefined),
- * reason: (*|undefined)}>>} A Promise that resolves with a list of
- * result objects once all input Promises (or Promise-like) have
- * settled. Each result object contains a 'fulfilled' boolean indicating
- * whether an input Promise was fulfilled or rejected. For fulfilled
- * Promises, the resulting value is stored in the 'value' field. For
- * rejected Promises, the rejection reason is stored in the 'reason'
- * field.
- * @template TYPE
- */
-goog.Promise.allSettled = function(promises) {
- return new goog.Promise(function(resolve, reject) {
- var toSettle = promises.length;
- var results = [];
-
- if (!toSettle) {
- resolve(results);
- return;
- }
-
- var onSettled = function(index, fulfilled, result) {
- toSettle--;
- results[index] = fulfilled ?
- {fulfilled: true, value: result} :
- {fulfilled: false, reason: result};
- if (toSettle == 0) {
- resolve(results);
- }
- };
-
- for (var i = 0, promise; i < promises.length; i++) {
- promise = promises[i];
- goog.Promise.resolveThen_(promise,
- goog.partial(onSettled, i, true /* fulfilled */),
- goog.partial(onSettled, i, false /* fulfilled */));
- }
- });
-};
-
-
-/**
- * @param {!Array<?(goog.Promise<TYPE>|goog.Thenable<TYPE>|Thenable|*)>}
- * promises
- * @return {!goog.Promise<TYPE>} A Promise that receives the value of the first
- * input to be fulfilled, or is rejected with a list of every rejection
- * reason if all inputs are rejected.
- * @template TYPE
- */
-goog.Promise.firstFulfilled = function(promises) {
- return new goog.Promise(function(resolve, reject) {
- var toReject = promises.length;
- var reasons = [];
-
- if (!toReject) {
- resolve(undefined);
- return;
- }
-
- var onFulfill = function(value) {
- resolve(value);
- };
-
- var onReject = function(index, reason) {
- toReject--;
- reasons[index] = reason;
- if (toReject == 0) {
- reject(reasons);
- }
- };
-
- for (var i = 0, promise; i < promises.length; i++) {
- promise = promises[i];
- goog.Promise.resolveThen_(
- promise, onFulfill, goog.partial(onReject, i));
- }
- });
-};
-
-
-/**
- * @return {!goog.promise.Resolver<TYPE>} Resolver wrapping the promise and its
- * resolve / reject functions. Resolving or rejecting the resolver
- * resolves or rejects the promise.
- * @template TYPE
- */
-goog.Promise.withResolver = function() {
- var resolve, reject;
- var promise = new goog.Promise(function(rs, rj) {
- resolve = rs;
- reject = rj;
- });
- return new goog.Promise.Resolver_(promise, resolve, reject);
-};
-
-
-/**
- * Adds callbacks that will operate on the result of the Promise, returning a
- * new child Promise.
- *
- * If the Promise is fulfilled, the {@code onFulfilled} callback will be invoked
- * with the fulfillment value as argument, and the child Promise will be
- * fulfilled with the return value of the callback. If the callback throws an
- * exception, the child Promise will be rejected with the thrown value instead.
- *
- * If the Promise is rejected, the {@code onRejected} callback will be invoked
- * with the rejection reason as argument, and the child Promise will be resolved
- * with the return value or rejected with the thrown value of the callback.
- *
- * @override
- */
-goog.Promise.prototype.then = function(
- opt_onFulfilled, opt_onRejected, opt_context) {
-
- if (opt_onFulfilled != null) {
- goog.asserts.assertFunction(opt_onFulfilled,
- 'opt_onFulfilled should be a function.');
- }
- if (opt_onRejected != null) {
- goog.asserts.assertFunction(opt_onRejected,
- 'opt_onRejected should be a function. Did you pass opt_context ' +
- 'as the second argument instead of the third?');
- }
-
- if (goog.Promise.LONG_STACK_TRACES) {
- this.addStackTrace_(new Error('then'));
- }
-
- return this.addChildPromise_(
- goog.isFunction(opt_onFulfilled) ? opt_onFulfilled : null,
- goog.isFunction(opt_onRejected) ? opt_onRejected : null,
- opt_context);
-};
-goog.Thenable.addImplementation(goog.Promise);
-
-
-/**
- * Adds callbacks that will operate on the result of the Promise without
- * returning a child Promise (unlike "then").
- *
- * If the Promise is fulfilled, the {@code onFulfilled} callback will be invoked
- * with the fulfillment value as argument.
- *
- * If the Promise is rejected, the {@code onRejected} callback will be invoked
- * with the rejection reason as argument.
- *
- * @param {?(function(this:THIS, TYPE):?)=} opt_onFulfilled A
- * function that will be invoked with the fulfillment value if the Promise
- * is fulfilled.
- * @param {?(function(this:THIS, *): *)=} opt_onRejected A function that will
- * be invoked with the rejection reason if the Promise is rejected.
- * @param {THIS=} opt_context An optional context object that will be the
- * execution context for the callbacks. By default, functions are executed
- * with the default this.
- * @package
- * @template THIS
- */
-goog.Promise.prototype.thenVoid = function(
- opt_onFulfilled, opt_onRejected, opt_context) {
-
- if (opt_onFulfilled != null) {
- goog.asserts.assertFunction(opt_onFulfilled,
- 'opt_onFulfilled should be a function.');
- }
- if (opt_onRejected != null) {
- goog.asserts.assertFunction(opt_onRejected,
- 'opt_onRejected should be a function. Did you pass opt_context ' +
- 'as the second argument instead of the third?');
- }
-
- if (goog.Promise.LONG_STACK_TRACES) {
- this.addStackTrace_(new Error('then'));
- }
-
- // Note: no default rejection handler is provided here as we need to
- // distinguish unhandled rejections.
- this.addCallbackEntry_(goog.Promise.getCallbackEntry_(
- opt_onFulfilled || goog.nullFunction,
- opt_onRejected || null,
- opt_context));
-};
-
-
-/**
- * Adds a callback that will be invoked when the Promise is settled (fulfilled
- * or rejected). The callback receives no argument, and no new child Promise is
- * created. This is useful for ensuring that cleanup takes place after certain
- * asynchronous operations. Callbacks added with {@code thenAlways} will be
- * executed in the same order with other calls to {@code then},
- * {@code thenAlways}, or {@code thenCatch}.
- *
- * Since it does not produce a new child Promise, cancellation propagation is
- * not prevented by adding callbacks with {@code thenAlways}. A Promise that has
- * a cleanup handler added with {@code thenAlways} will be canceled if all of
- * its children created by {@code then} (or {@code thenCatch}) are canceled.
- * Additionally, since any rejections are not passed to the callback, it does
- * not stop the unhandled rejection handler from running.
- *
- * @param {function(this:THIS): void} onSettled A function that will be invoked
- * when the Promise is settled (fulfilled or rejected).
- * @param {THIS=} opt_context An optional context object that will be the
- * execution context for the callbacks. By default, functions are executed
- * in the global scope.
- * @return {!goog.Promise<TYPE>} This Promise, for chaining additional calls.
- * @template THIS
- */
-goog.Promise.prototype.thenAlways = function(onSettled, opt_context) {
- if (goog.Promise.LONG_STACK_TRACES) {
- this.addStackTrace_(new Error('thenAlways'));
- }
-
- var entry = goog.Promise.getCallbackEntry_(onSettled, onSettled, opt_context);
- entry.always = true;
- this.addCallbackEntry_(entry);
- return this;
-};
-
-
-/**
- * Adds a callback that will be invoked only if the Promise is rejected. This
- * is equivalent to {@code then(null, onRejected)}.
- *
- * @param {!function(this:THIS, *): *} onRejected A function that will be
- * invoked with the rejection reason if the Promise is rejected.
- * @param {THIS=} opt_context An optional context object that will be the
- * execution context for the callbacks. By default, functions are executed
- * in the global scope.
- * @return {!goog.Promise} A new Promise that will receive the result of the
- * callback.
- * @template THIS
- */
-goog.Promise.prototype.thenCatch = function(onRejected, opt_context) {
- if (goog.Promise.LONG_STACK_TRACES) {
- this.addStackTrace_(new Error('thenCatch'));
- }
- return this.addChildPromise_(null, onRejected, opt_context);
-};
-
-
-/**
- * Cancels the Promise if it is still pending by rejecting it with a cancel
- * Error. No action is performed if the Promise is already resolved.
- *
- * All child Promises of the canceled Promise will be rejected with the same
- * cancel error, as with normal Promise rejection. If the Promise to be canceled
- * is the only child of a pending Promise, the parent Promise will also be
- * canceled. Cancellation may propagate upward through multiple generations.
- *
- * @param {string=} opt_message An optional debugging message for describing the
- * cancellation reason.
- */
-goog.Promise.prototype.cancel = function(opt_message) {
- if (this.state_ == goog.Promise.State_.PENDING) {
- goog.async.run(function() {
- var err = new goog.Promise.CancellationError(opt_message);
- this.cancelInternal_(err);
- }, this);
- }
-};
-
-
-/**
- * Cancels this Promise with the given error.
- *
- * @param {!Error} err The cancellation error.
- * @private
- */
-goog.Promise.prototype.cancelInternal_ = function(err) {
- if (this.state_ == goog.Promise.State_.PENDING) {
- if (this.parent_) {
- // Cancel the Promise and remove it from the parent's child list.
- this.parent_.cancelChild_(this, err);
- this.parent_ = null;
- } else {
- this.resolve_(goog.Promise.State_.REJECTED, err);
- }
- }
-};
-
-
-/**
- * Cancels a child Promise from the list of callback entries. If the Promise has
- * not already been resolved, reject it with a cancel error. If there are no
- * other children in the list of callback entries, propagate the cancellation
- * by canceling this Promise as well.
- *
- * @param {!goog.Promise} childPromise The Promise to cancel.
- * @param {!Error} err The cancel error to use for rejecting the Promise.
- * @private
- */
-goog.Promise.prototype.cancelChild_ = function(childPromise, err) {
- if (!this.callbackEntries_) {
- return;
- }
- var childCount = 0;
- var childEntry = null;
- var beforeChildEntry = null;
-
- // Find the callback entry for the childPromise, and count whether there are
- // additional child Promises.
- for (var entry = this.callbackEntries_; entry; entry = entry.next) {
- if (!entry.always) {
- childCount++;
- if (entry.child == childPromise) {
- childEntry = entry;
- }
- if (childEntry && childCount > 1) {
- break;
- }
- }
- if (!childEntry) {
- beforeChildEntry = entry;
- }
- }
-
- // Can a child entry be missing?
-
- // If the child Promise was the only child, cancel this Promise as well.
- // Otherwise, reject only the child Promise with the cancel error.
- if (childEntry) {
- if (this.state_ == goog.Promise.State_.PENDING && childCount == 1) {
- this.cancelInternal_(err);
- } else {
- if (beforeChildEntry) {
- this.removeEntryAfter_(beforeChildEntry);
- } else {
- this.popEntry_();
- }
-
- this.executeCallback_(
- childEntry, goog.Promise.State_.REJECTED, err);
- }
- }
-};
-
-
-/**
- * Adds a callback entry to the current Promise, and schedules callback
- * execution if the Promise has already been settled.
- *
- * @param {goog.Promise.CallbackEntry_} callbackEntry Record containing
- * {@code onFulfilled} and {@code onRejected} callbacks to execute after
- * the Promise is settled.
- * @private
- */
-goog.Promise.prototype.addCallbackEntry_ = function(callbackEntry) {
- if (!this.hasEntry_() &&
- (this.state_ == goog.Promise.State_.FULFILLED ||
- this.state_ == goog.Promise.State_.REJECTED)) {
- this.scheduleCallbacks_();
- }
- this.queueEntry_(callbackEntry);
-};
-
-
-/**
- * Creates a child Promise and adds it to the callback entry list. The result of
- * the child Promise is determined by the state of the parent Promise and the
- * result of the {@code onFulfilled} or {@code onRejected} callbacks as
- * specified in the Promise resolution procedure.
- *
- * @see http://promisesaplus.com/#the__method
- *
- * @param {?function(this:THIS, TYPE):
- * (RESULT|goog.Promise<RESULT>|Thenable)} onFulfilled A callback that
- * will be invoked if the Promise is fullfilled, or null.
- * @param {?function(this:THIS, *): *} onRejected A callback that will be
- * invoked if the Promise is rejected, or null.
- * @param {THIS=} opt_context An optional execution context for the callbacks.
- * in the default calling context.
- * @return {!goog.Promise} The child Promise.
- * @template RESULT,THIS
- * @private
- */
-goog.Promise.prototype.addChildPromise_ = function(
- onFulfilled, onRejected, opt_context) {
-
- /** @type {goog.Promise.CallbackEntry_} */
- var callbackEntry = goog.Promise.getCallbackEntry_(null, null, null);
-
- callbackEntry.child = new goog.Promise(function(resolve, reject) {
- // Invoke onFulfilled, or resolve with the parent's value if absent.
- callbackEntry.onFulfilled = onFulfilled ? function(value) {
- try {
- var result = onFulfilled.call(opt_context, value);
- resolve(result);
- } catch (err) {
- reject(err);
- }
- } : resolve;
-
- // Invoke onRejected, or reject with the parent's reason if absent.
- callbackEntry.onRejected = onRejected ? function(reason) {
- try {
- var result = onRejected.call(opt_context, reason);
- if (!goog.isDef(result) &&
- reason instanceof goog.Promise.CancellationError) {
- // Propagate cancellation to children if no other result is returned.
- reject(reason);
- } else {
- resolve(result);
- }
- } catch (err) {
- reject(err);
- }
- } : reject;
- });
-
- callbackEntry.child.parent_ = this;
- this.addCallbackEntry_(callbackEntry);
- return callbackEntry.child;
-};
-
-
-/**
- * Unblocks the Promise and fulfills it with the given value.
- *
- * @param {TYPE} value
- * @private
- */
-goog.Promise.prototype.unblockAndFulfill_ = function(value) {
- goog.asserts.assert(this.state_ == goog.Promise.State_.BLOCKED);
- this.state_ = goog.Promise.State_.PENDING;
- this.resolve_(goog.Promise.State_.FULFILLED, value);
-};
-
-
-/**
- * Unblocks the Promise and rejects it with the given rejection reason.
- *
- * @param {*} reason
- * @private
- */
-goog.Promise.prototype.unblockAndReject_ = function(reason) {
- goog.asserts.assert(this.state_ == goog.Promise.State_.BLOCKED);
- this.state_ = goog.Promise.State_.PENDING;
- this.resolve_(goog.Promise.State_.REJECTED, reason);
-};
-
-
-/**
- * Attempts to resolve a Promise with a given resolution state and value. This
- * is a no-op if the given Promise has already been resolved.
- *
- * If the given result is a Thenable (such as another Promise), the Promise will
- * be settled with the same state and result as the Thenable once it is itself
- * settled.
- *
- * If the given result is not a Thenable, the Promise will be settled (fulfilled
- * or rejected) with that result based on the given state.
- *
- * @see http://promisesaplus.com/#the_promise_resolution_procedure
- *
- * @param {goog.Promise.State_} state
- * @param {*} x The result to apply to the Promise.
- * @private
- */
-goog.Promise.prototype.resolve_ = function(state, x) {
- if (this.state_ != goog.Promise.State_.PENDING) {
- return;
- }
-
- if (this == x) {
- state = goog.Promise.State_.REJECTED;
- x = new TypeError('Promise cannot resolve to itself');
- }
-
- this.state_ = goog.Promise.State_.BLOCKED;
- var isThenable = goog.Promise.maybeThen_(
- x, this.unblockAndFulfill_, this.unblockAndReject_, this);
- if (isThenable) {
- return;
- }
-
- this.result_ = x;
- this.state_ = state;
- // Since we can no longer be canceled, remove link to parent, so that the
- // child promise does not keep the parent promise alive.
- this.parent_ = null;
- this.scheduleCallbacks_();
-
- if (state == goog.Promise.State_.REJECTED &&
- !(x instanceof goog.Promise.CancellationError)) {
- goog.Promise.addUnhandledRejection_(this, x);
- }
-};
-
-
-/**
- * Invokes the "then" method of an input value if that value is a Thenable. This
- * is a no-op if the value is not thenable.
- *
- * @param {*} value A potentially thenable value.
- * @param {!Function} onFulfilled
- * @param {!Function} onRejected
- * @param {*} context
- * @return {boolean} Whether the input value was thenable.
- * @private
- */
-goog.Promise.maybeThen_ = function(value, onFulfilled, onRejected, context) {
- if (value instanceof goog.Promise) {
- value.thenVoid(onFulfilled, onRejected, context);
- return true;
- } else if (goog.Thenable.isImplementedBy(value)) {
- value = /** @type {!goog.Thenable} */ (value);
- value.then(onFulfilled, onRejected, context);
- return true;
- } else if (goog.isObject(value)) {
- try {
- var then = value['then'];
- if (goog.isFunction(then)) {
- goog.Promise.tryThen_(
- value, then, onFulfilled, onRejected, context);
- return true;
- }
- } catch (e) {
- onRejected.call(context, e);
- return true;
- }
- }
-
- return false;
-};
-
-
-/**
- * Attempts to call the {@code then} method on an object in the hopes that it is
- * a Promise-compatible instance. This allows interoperation between different
- * Promise implementations, however a non-compliant object may cause a Promise
- * to hang indefinitely. If the {@code then} method throws an exception, the
- * dependent Promise will be rejected with the thrown value.
- *
- * @see http://promisesaplus.com/#point-70
- *
- * @param {Thenable} thenable An object with a {@code then} method that may be
- * compatible with the Promise/A+ specification.
- * @param {!Function} then The {@code then} method of the Thenable object.
- * @param {!Function} onFulfilled
- * @param {!Function} onRejected
- * @param {*} context
- * @private
- */
-goog.Promise.tryThen_ = function(
- thenable, then, onFulfilled, onRejected, context) {
-
- var called = false;
- var resolve = function(value) {
- if (!called) {
- called = true;
- onFulfilled.call(context, value);
- }
- };
-
- var reject = function(reason) {
- if (!called) {
- called = true;
- onRejected.call(context, reason);
- }
- };
-
- try {
- then.call(thenable, resolve, reject);
- } catch (e) {
- reject(e);
- }
-};
-
-
-/**
- * Executes the pending callbacks of a settled Promise after a timeout.
- *
- * Section 2.2.4 of the Promises/A+ specification requires that Promise
- * callbacks must only be invoked from a call stack that only contains Promise
- * implementation code, which we accomplish by invoking callback execution after
- * a timeout. If {@code startExecution_} is called multiple times for the same
- * Promise, the callback chain will be evaluated only once. Additional callbacks
- * may be added during the evaluation phase, and will be executed in the same
- * event loop.
- *
- * All Promises added to the waiting list during the same browser event loop
- * will be executed in one batch to avoid using a separate timeout per Promise.
- *
- * @private
- */
-goog.Promise.prototype.scheduleCallbacks_ = function() {
- if (!this.executing_) {
- this.executing_ = true;
- goog.async.run(this.executeCallbacks_, this);
- }
-};
-
-
-/**
- * @return {boolean} Whether there are any pending callbacks queued.
- * @private
- */
-goog.Promise.prototype.hasEntry_ = function() {
- return !!this.callbackEntries_;
-};
-
-
-/**
- * @param {goog.Promise.CallbackEntry_} entry
- * @private
- */
-goog.Promise.prototype.queueEntry_ = function(entry) {
- goog.asserts.assert(entry.onFulfilled != null);
-
- if (this.callbackEntriesTail_) {
- this.callbackEntriesTail_.next = entry;
- this.callbackEntriesTail_ = entry;
- } else {
- // It the work queue was empty set the head too.
- this.callbackEntries_ = entry;
- this.callbackEntriesTail_ = entry;
- }
-};
-
-
-/**
- * @return {goog.Promise.CallbackEntry_} entry
- * @private
- */
-goog.Promise.prototype.popEntry_ = function() {
- var entry = null;
- if (this.callbackEntries_) {
- entry = this.callbackEntries_;
- this.callbackEntries_ = entry.next;
- entry.next = null;
- }
- // It the work queue is empty clear the tail too.
- if (!this.callbackEntries_) {
- this.callbackEntriesTail_ = null;
- }
-
- if (entry != null) {
- goog.asserts.assert(entry.onFulfilled != null);
- }
- return entry;
-};
-
-
-/**
- * @param {goog.Promise.CallbackEntry_} previous
- * @private
- */
-goog.Promise.prototype.removeEntryAfter_ = function(previous) {
- goog.asserts.assert(this.callbackEntries_);
- goog.asserts.assert(previous != null);
- // If the last entry is being removed, update the tail
- if (previous.next == this.callbackEntriesTail_) {
- this.callbackEntriesTail_ = previous;
- }
-
- previous.next = previous.next.next;
-};
-
-
-/**
- * Executes all pending callbacks for this Promise.
- *
- * @private
- */
-goog.Promise.prototype.executeCallbacks_ = function() {
- var entry = null;
- while (entry = this.popEntry_()) {
- if (goog.Promise.LONG_STACK_TRACES) {
- this.currentStep_++;
- }
- this.executeCallback_(entry, this.state_, this.result_);
- }
- this.executing_ = false;
-};
-
-
-/**
- * Executes a pending callback for this Promise. Invokes an {@code onFulfilled}
- * or {@code onRejected} callback based on the settled state of the Promise.
- *
- * @param {!goog.Promise.CallbackEntry_} callbackEntry An entry containing the
- * onFulfilled and/or onRejected callbacks for this step.
- * @param {goog.Promise.State_} state The resolution status of the Promise,
- * either FULFILLED or REJECTED.
- * @param {*} result The settled result of the Promise.
- * @private
- */
-goog.Promise.prototype.executeCallback_ = function(
- callbackEntry, state, result) {
- // Cancel an unhandled rejection if the then/thenVoid call had an onRejected.
- if (state == goog.Promise.State_.REJECTED &&
- callbackEntry.onRejected && !callbackEntry.always) {
- this.removeUnhandledRejection_();
- }
-
- if (callbackEntry.child) {
- // When the parent is settled, the child no longer needs to hold on to it,
- // as the parent can no longer be canceled.
- callbackEntry.child.parent_ = null;
- goog.Promise.invokeCallback_(callbackEntry, state, result);
- } else {
- // Callbacks created with thenAlways or thenVoid do not have the rejection
- // handling code normally set up in the child Promise.
- try {
- callbackEntry.always ?
- callbackEntry.onFulfilled.call(callbackEntry.context) :
- goog.Promise.invokeCallback_(callbackEntry, state, result);
- } catch (err) {
- goog.Promise.handleRejection_.call(null, err);
- }
- }
- goog.Promise.returnEntry_(callbackEntry);
-};
-
-
-/**
- * Executes the onFulfilled or onRejected callback for a callbackEntry.
- *
- * @param {!goog.Promise.CallbackEntry_} callbackEntry
- * @param {goog.Promise.State_} state
- * @param {*} result
- * @private
- */
-goog.Promise.invokeCallback_ = function(callbackEntry, state, result) {
- if (state == goog.Promise.State_.FULFILLED) {
- callbackEntry.onFulfilled.call(callbackEntry.context, result);
- } else if (callbackEntry.onRejected) {
- callbackEntry.onRejected.call(callbackEntry.context, result);
- }
-};
-
-
-/**
- * Records a stack trace entry for functions that call {@code then} or the
- * Promise constructor. May be disabled by unsetting {@code LONG_STACK_TRACES}.
- *
- * @param {!Error} err An Error object created by the calling function for
- * providing a stack trace.
- * @private
- */
-goog.Promise.prototype.addStackTrace_ = function(err) {
- if (goog.Promise.LONG_STACK_TRACES && goog.isString(err.stack)) {
- // Extract the third line of the stack trace, which is the entry for the
- // user function that called into Promise code.
- var trace = err.stack.split('\n', 4)[3];
- var message = err.message;
-
- // Pad the message to align the traces.
- message += Array(11 - message.length).join(' ');
- this.stack_.push(message + trace);
- }
-};
-
-
-/**
- * Adds extra stack trace information to an exception for the list of
- * asynchronous {@code then} calls that have been run for this Promise. Stack
- * trace information is recorded in {@see #addStackTrace_}, and appended to
- * rethrown errors when {@code LONG_STACK_TRACES} is enabled.
- *
- * @param {*} err An unhandled exception captured during callback execution.
- * @private
- */
-goog.Promise.prototype.appendLongStack_ = function(err) {
- if (goog.Promise.LONG_STACK_TRACES &&
- err && goog.isString(err.stack) && this.stack_.length) {
- var longTrace = ['Promise trace:'];
-
- for (var promise = this; promise; promise = promise.parent_) {
- for (var i = this.currentStep_; i >= 0; i--) {
- longTrace.push(promise.stack_[i]);
- }
- longTrace.push('Value: ' +
- '[' + (promise.state_ == goog.Promise.State_.REJECTED ?
- 'REJECTED' : 'FULFILLED') + '] ' +
- '<' + String(promise.result_) + '>');
- }
- err.stack += '\n\n' + longTrace.join('\n');
- }
-};
-
-
-/**
- * Marks this rejected Promise as having being handled. Also marks any parent
- * Promises in the rejected state as handled. The rejection handler will no
- * longer be invoked for this Promise (if it has not been called already).
- *
- * @private
- */
-goog.Promise.prototype.removeUnhandledRejection_ = function() {
- if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
- for (var p = this; p && p.unhandledRejectionId_; p = p.parent_) {
- goog.global.clearTimeout(p.unhandledRejectionId_);
- p.unhandledRejectionId_ = 0;
- }
- } else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
- for (var p = this; p && p.hadUnhandledRejection_; p = p.parent_) {
- p.hadUnhandledRejection_ = false;
- }
- }
-};
-
-
-/**
- * Marks this rejected Promise as unhandled. If no {@code onRejected} callback
- * is called for this Promise before the {@code UNHANDLED_REJECTION_DELAY}
- * expires, the reason will be passed to the unhandled rejection handler. The
- * handler typically rethrows the rejection reason so that it becomes visible in
- * the developer console.
- *
- * @param {!goog.Promise} promise The rejected Promise.
- * @param {*} reason The Promise rejection reason.
- * @private
- */
-goog.Promise.addUnhandledRejection_ = function(promise, reason) {
- if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
- promise.unhandledRejectionId_ = goog.global.setTimeout(function() {
- promise.appendLongStack_(reason);
- goog.Promise.handleRejection_.call(null, reason);
- }, goog.Promise.UNHANDLED_REJECTION_DELAY);
-
- } else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
- promise.hadUnhandledRejection_ = true;
- goog.async.run(function() {
- if (promise.hadUnhandledRejection_) {
- promise.appendLongStack_(reason);
- goog.Promise.handleRejection_.call(null, reason);
- }
- });
- }
-};
-
-
-/**
- * A method that is invoked with the rejection reasons for Promises that are
- * rejected but have no {@code onRejected} callbacks registered yet.
- * @type {function(*)}
- * @private
- */
-goog.Promise.handleRejection_ = goog.async.throwException;
-
-
-/**
- * Sets a handler that will be called with reasons from unhandled rejected
- * Promises. If the rejected Promise (or one of its descendants) has an
- * {@code onRejected} callback registered, the rejection will be considered
- * handled, and the rejection handler will not be called.
- *
- * By default, unhandled rejections are rethrown so that the error may be
- * captured by the developer console or a {@code window.onerror} handler.
- *
- * @param {function(*)} handler A function that will be called with reasons from
- * rejected Promises. Defaults to {@code goog.async.throwException}.
- */
-goog.Promise.setUnhandledRejectionHandler = function(handler) {
- goog.Promise.handleRejection_ = handler;
-};
-
-
-
-/**
- * Error used as a rejection reason for canceled Promises.
- *
- * @param {string=} opt_message
- * @constructor
- * @extends {goog.debug.Error}
- * @final
- */
-goog.Promise.CancellationError = function(opt_message) {
- goog.Promise.CancellationError.base(this, 'constructor', opt_message);
-};
-goog.inherits(goog.Promise.CancellationError, goog.debug.Error);
-
-
-/** @override */
-goog.Promise.CancellationError.prototype.name = 'cancel';
-
-
-
-/**
- * Internal implementation of the resolver interface.
- *
- * @param {!goog.Promise<TYPE>} promise
- * @param {function((TYPE|goog.Promise<TYPE>|Thenable)=)} resolve
- * @param {function(*=): void} reject
- * @implements {goog.promise.Resolver<TYPE>}
- * @final @struct
- * @constructor
- * @private
- * @template TYPE
- */
-goog.Promise.Resolver_ = function(promise, resolve, reject) {
- /** @const */
- this.promise = promise;
-
- /** @const */
- this.resolve = resolve;
-
- /** @const */
- this.reject = reject;
-};
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview A timer class to which other classes and objects can
- * listen on. This is only an abstraction above setInterval.
- *
- * @see ../demos/timers.html
- */
-
-goog.provide('goog.Timer');
-
-goog.require('goog.Promise');
-goog.require('goog.events.EventTarget');
-
-
-
-/**
- * Class for handling timing events.
- *
- * @param {number=} opt_interval Number of ms between ticks (Default: 1ms).
- * @param {Object=} opt_timerObject An object that has setTimeout, setInterval,
- * clearTimeout and clearInterval (eg Window).
- * @constructor
- * @extends {goog.events.EventTarget}
- */
-goog.Timer = function(opt_interval, opt_timerObject) {
- goog.events.EventTarget.call(this);
-
- /**
- * Number of ms between ticks
- * @type {number}
- * @private
- */
- this.interval_ = opt_interval || 1;
-
- /**
- * An object that implements setTimeout, setInterval, clearTimeout and
- * clearInterval. We default to the window object. Changing this on
- * goog.Timer.prototype changes the object for all timer instances which can
- * be useful if your environment has some other implementation of timers than
- * the window object.
- * @type {Object}
- * @private
- */
- this.timerObject_ = opt_timerObject || goog.Timer.defaultTimerObject;
-
- /**
- * Cached tick_ bound to the object for later use in the timer.
- * @type {Function}
- * @private
- */
- this.boundTick_ = goog.bind(this.tick_, this);
-
- /**
- * Firefox browser often fires the timer event sooner
- * (sometimes MUCH sooner) than the requested timeout. So we
- * compare the time to when the event was last fired, and
- * reschedule if appropriate. See also goog.Timer.intervalScale
- * @type {number}
- * @private
- */
- this.last_ = goog.now();
-};
-goog.inherits(goog.Timer, goog.events.EventTarget);
-
-
-/**
- * Maximum timeout value.
- *
- * Timeout values too big to fit into a signed 32-bit integer may cause
- * overflow in FF, Safari, and Chrome, resulting in the timeout being
- * scheduled immediately. It makes more sense simply not to schedule these
- * timeouts, since 24.8 days is beyond a reasonable expectation for the
- * browser to stay open.
- *
- * @type {number}
- * @private
- */
-goog.Timer.MAX_TIMEOUT_ = 2147483647;
-
-
-/**
- * A timer ID that cannot be returned by any known implmentation of
- * Window.setTimeout. Passing this value to window.clearTimeout should
- * therefore be a no-op.
- *
- * @const {number}
- * @private
- */
-goog.Timer.INVALID_TIMEOUT_ID_ = -1;
-
-
-/**
- * Whether this timer is enabled
- * @type {boolean}
- */
-goog.Timer.prototype.enabled = false;
-
-
-/**
- * An object that implements setTimout, setInterval, clearTimeout and
- * clearInterval. We default to the global object. Changing
- * goog.Timer.defaultTimerObject changes the object for all timer instances
- * which can be useful if your environment has some other implementation of
- * timers you'd like to use.
- * @type {Object}
- */
-goog.Timer.defaultTimerObject = goog.global;
-
-
-/**
- * A variable that controls the timer error correction. If the
- * timer is called before the requested interval times
- * intervalScale, which often happens on mozilla, the timer is
- * rescheduled. See also this.last_
- * @type {number}
- */
-goog.Timer.intervalScale = 0.8;
-
-
-/**
- * Variable for storing the result of setInterval
- * @type {?number}
- * @private
- */
-goog.Timer.prototype.timer_ = null;
-
-
-/**
- * Gets the interval of the timer.
- * @return {number} interval Number of ms between ticks.
- */
-goog.Timer.prototype.getInterval = function() {
- return this.interval_;
-};
-
-
-/**
- * Sets the interval of the timer.
- * @param {number} interval Number of ms between ticks.
- */
-goog.Timer.prototype.setInterval = function(interval) {
- this.interval_ = interval;
- if (this.timer_ && this.enabled) {
- // Stop and then start the timer to reset the interval.
- this.stop();
- this.start();
- } else if (this.timer_) {
- this.stop();
- }
-};
-
-
-/**
- * Callback for the setTimeout used by the timer
- * @private
- */
-goog.Timer.prototype.tick_ = function() {
- if (this.enabled) {
- var elapsed = goog.now() - this.last_;
- if (elapsed > 0 &&
- elapsed < this.interval_ * goog.Timer.intervalScale) {
- this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
- this.interval_ - elapsed);
- return;
- }
-
- // Prevents setInterval from registering a duplicate timeout when called
- // in the timer event handler.
- if (this.timer_) {
- this.timerObject_.clearTimeout(this.timer_);
- this.timer_ = null;
- }
-
- this.dispatchTick();
- // The timer could be stopped in the timer event handler.
- if (this.enabled) {
- this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
- this.interval_);
- this.last_ = goog.now();
- }
- }
-};
-
-
-/**
- * Dispatches the TICK event. This is its own method so subclasses can override.
- */
-goog.Timer.prototype.dispatchTick = function() {
- this.dispatchEvent(goog.Timer.TICK);
-};
-
-
-/**
- * Starts the timer.
- */
-goog.Timer.prototype.start = function() {
- this.enabled = true;
-
- // If there is no interval already registered, start it now
- if (!this.timer_) {
- // IMPORTANT!
- // window.setInterval in FireFox has a bug - it fires based on
- // absolute time, rather than on relative time. What this means
- // is that if a computer is sleeping/hibernating for 24 hours
- // and the timer interval was configured to fire every 1000ms,
- // then after the PC wakes up the timer will fire, in rapid
- // succession, 3600*24 times.
- // This bug is described here and is already fixed, but it will
- // take time to propagate, so for now I am switching this over
- // to setTimeout logic.
- // https://bugzilla.mozilla.org/show_bug.cgi?id=376643
- //
- this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
- this.interval_);
- this.last_ = goog.now();
- }
-};
-
-
-/**
- * Stops the timer.
- */
-goog.Timer.prototype.stop = function() {
- this.enabled = false;
- if (this.timer_) {
- this.timerObject_.clearTimeout(this.timer_);
- this.timer_ = null;
- }
-};
-
-
-/** @override */
-goog.Timer.prototype.disposeInternal = function() {
- goog.Timer.superClass_.disposeInternal.call(this);
- this.stop();
- delete this.timerObject_;
-};
-
-
-/**
- * Constant for the timer's event type
- * @type {string}
- */
-goog.Timer.TICK = 'tick';
-
-
-/**
- * Calls the given function once, after the optional pause.
- *
- * The function is always called asynchronously, even if the delay is 0. This
- * is a common trick to schedule a function to run after a batch of browser
- * event processing.
- *
- * @param {function(this:SCOPE)|{handleEvent:function()}|null} listener Function
- * or object that has a handleEvent method.
- * @param {number=} opt_delay Milliseconds to wait; default is 0.
- * @param {SCOPE=} opt_handler Object in whose scope to call the listener.
- * @return {number} A handle to the timer ID.
- * @template SCOPE
- */
-goog.Timer.callOnce = function(listener, opt_delay, opt_handler) {
- if (goog.isFunction(listener)) {
- if (opt_handler) {
- listener = goog.bind(listener, opt_handler);
- }
- } else if (listener && typeof listener.handleEvent == 'function') {
- // using typeof to prevent strict js warning
- listener = goog.bind(listener.handleEvent, listener);
- } else {
- throw Error('Invalid listener argument');
- }
-
- if (opt_delay > goog.Timer.MAX_TIMEOUT_) {
- // Timeouts greater than MAX_INT return immediately due to integer
- // overflow in many browsers. Since MAX_INT is 24.8 days, just don't
- // schedule anything at all.
- return goog.Timer.INVALID_TIMEOUT_ID_;
- } else {
- return goog.Timer.defaultTimerObject.setTimeout(
- listener, opt_delay || 0);
- }
-};
-
-
-/**
- * Clears a timeout initiated by callOnce
- * @param {?number} timerId a timer ID.
- */
-goog.Timer.clear = function(timerId) {
- goog.Timer.defaultTimerObject.clearTimeout(timerId);
-};
-
-
-/**
- * @param {number} delay Milliseconds to wait.
- * @param {(RESULT|goog.Thenable<RESULT>|Thenable)=} opt_result The value
- * with which the promise will be resolved.
- * @return {!goog.Promise<RESULT>} A promise that will be resolved after
- * the specified delay, unless it is canceled first.
- * @template RESULT
- */
-goog.Timer.promise = function(delay, opt_result) {
- var timerKey = null;
- return new goog.Promise(function(resolve, reject) {
- timerKey = goog.Timer.callOnce(function() {
- resolve(opt_result);
- }, delay);
- if (timerKey == goog.Timer.INVALID_TIMEOUT_ID_) {
- reject(new Error('Failed to schedule timer.'));
- }
- }).thenCatch(function(error) {
- // Clear the timer. The most likely reason is "cancel" signal.
- goog.Timer.clear(timerKey);
- throw error;
- });
-};
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview JSON utility functions.
- * @author arv@google.com (Erik Arvidsson)
- */
-
-
-goog.provide('goog.json');
-goog.provide('goog.json.Replacer');
-goog.provide('goog.json.Reviver');
-goog.provide('goog.json.Serializer');
-
-
-/**
- * @define {boolean} If true, use the native JSON parsing API.
- * NOTE(ruilopes): EXPERIMENTAL, handle with care. Setting this to true might
- * break your code. The default {@code goog.json.parse} implementation is able
- * to handle invalid JSON, such as JSPB.
- */
-goog.define('goog.json.USE_NATIVE_JSON', false);
-
-
-/**
- * Tests if a string is an invalid JSON string. This only ensures that we are
- * not using any invalid characters
- * @param {string} s The string to test.
- * @return {boolean} True if the input is a valid JSON string.
- */
-goog.json.isValid = function(s) {
- // All empty whitespace is not valid.
- if (/^\s*$/.test(s)) {
- return false;
- }
-
- // This is taken from http://www.json.org/json2.js which is released to the
- // public domain.
- // Changes: We dissallow \u2028 Line separator and \u2029 Paragraph separator
- // inside strings. We also treat \u2028 and \u2029 as whitespace which they
- // are in the RFC but IE and Safari does not match \s to these so we need to
- // include them in the reg exps in all places where whitespace is allowed.
- // We allowed \x7f inside strings because some tools don't escape it,
- // e.g. http://www.json.org/java/org/json/JSONObject.java
-
- // Parsing happens in three stages. In the first stage, we run the text
- // against regular expressions that look for non-JSON patterns. We are
- // especially concerned with '()' and 'new' because they can cause invocation,
- // and '=' because it can cause mutation. But just to be safe, we want to
- // reject all unexpected forms.
-
- // We split the first stage into 4 regexp operations in order to work around
- // crippling inefficiencies in IE's and Safari's regexp engines. First we
- // replace all backslash pairs with '@' (a non-JSON character). Second, we
- // replace all simple value tokens with ']' characters. Third, we delete all
- // open brackets that follow a colon or comma or that begin the text. Finally,
- // we look to see that the remaining characters are only whitespace or ']' or
- // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
-
- // Don't make these static since they have the global flag.
- var backslashesRe = /\\["\\\/bfnrtu]/g;
- var simpleValuesRe =
- /"[^"\\\n\r\u2028\u2029\x00-\x08\x0a-\x1f]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
- var openBracketsRe = /(?:^|:|,)(?:[\s\u2028\u2029]*\[)+/g;
- var remainderRe = /^[\],:{}\s\u2028\u2029]*$/;
-
- return remainderRe.test(s.replace(backslashesRe, '@').
- replace(simpleValuesRe, ']').
- replace(openBracketsRe, ''));
-};
-
-
-/**
- * Parses a JSON string and returns the result. This throws an exception if
- * the string is an invalid JSON string.
- *
- * Note that this is very slow on large strings. If you trust the source of
- * the string then you should use unsafeParse instead.
- *
- * @param {*} s The JSON string to parse.
- * @throws Error if s is invalid JSON.
- * @return {Object} The object generated from the JSON string, or null.
- */
-goog.json.parse = goog.json.USE_NATIVE_JSON ?
- /** @type {function(*):Object} */ (goog.global['JSON']['parse']) :
- function(s) {
- var o = String(s);
- if (goog.json.isValid(o)) {
- /** @preserveTry */
- try {
- return /** @type {Object} */ (eval('(' + o + ')'));
- } catch (ex) {
- }
- }
- throw Error('Invalid JSON string: ' + o);
- };
-
-
-/**
- * Parses a JSON string and returns the result. This uses eval so it is open
- * to security issues and it should only be used if you trust the source.
- *
- * @param {string} s The JSON string to parse.
- * @return {Object} The object generated from the JSON string.
- */
-goog.json.unsafeParse = goog.json.USE_NATIVE_JSON ?
- /** @type {function(string):Object} */ (goog.global['JSON']['parse']) :
- function(s) {
- return /** @type {Object} */ (eval('(' + s + ')'));
- };
-
-
-/**
- * JSON replacer, as defined in Section 15.12.3 of the ES5 spec.
- * @see http://ecma-international.org/ecma-262/5.1/#sec-15.12.3
- *
- * TODO(nicksantos): Array should also be a valid replacer.
- *
- * @typedef {function(this:Object, string, *): *}
- */
-goog.json.Replacer;
-
-
-/**
- * JSON reviver, as defined in Section 15.12.2 of the ES5 spec.
- * @see http://ecma-international.org/ecma-262/5.1/#sec-15.12.3
- *
- * @typedef {function(this:Object, string, *): *}
- */
-goog.json.Reviver;
-
-
-/**
- * Serializes an object or a value to a JSON string.
- *
- * @param {*} object The object to serialize.
- * @param {?goog.json.Replacer=} opt_replacer A replacer function
- * called for each (key, value) pair that determines how the value
- * should be serialized. By defult, this just returns the value
- * and allows default serialization to kick in.
- * @throws Error if there are loops in the object graph.
- * @return {string} A JSON string representation of the input.
- */
-goog.json.serialize = goog.json.USE_NATIVE_JSON ?
- /** @type {function(*, ?goog.json.Replacer=):string} */
- (goog.global['JSON']['stringify']) :
- function(object, opt_replacer) {
- // NOTE(nicksantos): Currently, we never use JSON.stringify.
- //
- // The last time I evaluated this, JSON.stringify had subtle bugs and
- // behavior differences on all browsers, and the performance win was not
- // large enough to justify all the issues. This may change in the future
- // as browser implementations get better.
- //
- // assertSerialize in json_test contains if branches for the cases
- // that fail.
- return new goog.json.Serializer(opt_replacer).serialize(object);
- };
-
-
-
-/**
- * Class that is used to serialize JSON objects to a string.
- * @param {?goog.json.Replacer=} opt_replacer Replacer.
- * @constructor
- */
-goog.json.Serializer = function(opt_replacer) {
- /**
- * @type {goog.json.Replacer|null|undefined}
- * @private
- */
- this.replacer_ = opt_replacer;
-};
-
-
-/**
- * Serializes an object or a value to a JSON string.
- *
- * @param {*} object The object to serialize.
- * @throws Error if there are loops in the object graph.
- * @return {string} A JSON string representation of the input.
- */
-goog.json.Serializer.prototype.serialize = function(object) {
- var sb = [];
- this.serializeInternal(object, sb);
- return sb.join('');
-};
-
-
-/**
- * Serializes a generic value to a JSON string
- * @protected
- * @param {*} object The object to serialize.
- * @param {Array<string>} sb Array used as a string builder.
- * @throws Error if there are loops in the object graph.
- */
-goog.json.Serializer.prototype.serializeInternal = function(object, sb) {
- if (object == null) {
- // undefined == null so this branch covers undefined as well as null
- sb.push('null');
- return;
- }
-
- if (typeof object == 'object') {
- if (goog.isArray(object)) {
- this.serializeArray(object, sb);
- return;
- } else if (object instanceof String ||
- object instanceof Number ||
- object instanceof Boolean) {
- object = object.valueOf();
- // Fall through to switch below.
- } else {
- this.serializeObject_(/** @type {Object} */ (object), sb);
- return;
- }
- }
-
- switch (typeof object) {
- case 'string':
- this.serializeString_(object, sb);
- break;
- case 'number':
- this.serializeNumber_(object, sb);
- break;
- case 'boolean':
- sb.push(object);
- break;
- case 'function':
- sb.push('null');
- break;
- default:
- throw Error('Unknown type: ' + typeof object);
- }
-};
-
-
-/**
- * Character mappings used internally for goog.string.quote
- * @private
- * @type {!Object}
- */
-goog.json.Serializer.charToJsonCharCache_ = {
- '\"': '\\"',
- '\\': '\\\\',
- '/': '\\/',
- '\b': '\\b',
- '\f': '\\f',
- '\n': '\\n',
- '\r': '\\r',
- '\t': '\\t',
-
- '\x0B': '\\u000b' // '\v' is not supported in JScript
-};
-
-
-/**
- * Regular expression used to match characters that need to be replaced.
- * The S60 browser has a bug where unicode characters are not matched by
- * regular expressions. The condition below detects such behaviour and
- * adjusts the regular expression accordingly.
- * @private
- * @type {!RegExp}
- */
-goog.json.Serializer.charsToReplace_ = /\uffff/.test('\uffff') ?
- /[\\\"\x00-\x1f\x7f-\uffff]/g : /[\\\"\x00-\x1f\x7f-\xff]/g;
-
-
-/**
- * Serializes a string to a JSON string
- * @private
- * @param {string} s The string to serialize.
- * @param {Array<string>} sb Array used as a string builder.
- */
-goog.json.Serializer.prototype.serializeString_ = function(s, sb) {
- // The official JSON implementation does not work with international
- // characters.
- sb.push('"', s.replace(goog.json.Serializer.charsToReplace_, function(c) {
- // caching the result improves performance by a factor 2-3
- var rv = goog.json.Serializer.charToJsonCharCache_[c];
- if (!rv) {
- rv = '\\u' + (c.charCodeAt(0) | 0x10000).toString(16).substr(1);
- goog.json.Serializer.charToJsonCharCache_[c] = rv;
- }
- return rv;
- }), '"');
-};
-
-
-/**
- * Serializes a number to a JSON string
- * @private
- * @param {number} n The number to serialize.
- * @param {Array<string>} sb Array used as a string builder.
- */
-goog.json.Serializer.prototype.serializeNumber_ = function(n, sb) {
- sb.push(isFinite(n) && !isNaN(n) ? n : 'null');
-};
-
-
-/**
- * Serializes an array to a JSON string
- * @param {Array<string>} arr The array to serialize.
- * @param {Array<string>} sb Array used as a string builder.
- * @protected
- */
-goog.json.Serializer.prototype.serializeArray = function(arr, sb) {
- var l = arr.length;
- sb.push('[');
- var sep = '';
- for (var i = 0; i < l; i++) {
- sb.push(sep);
-
- var value = arr[i];
- this.serializeInternal(
- this.replacer_ ? this.replacer_.call(arr, String(i), value) : value,
- sb);
-
- sep = ',';
- }
- sb.push(']');
-};
-
-
-/**
- * Serializes an object to a JSON string
- * @private
- * @param {Object} obj The object to serialize.
- * @param {Array<string>} sb Array used as a string builder.
- */
-goog.json.Serializer.prototype.serializeObject_ = function(obj, sb) {
- sb.push('{');
- var sep = '';
- for (var key in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
- var value = obj[key];
- // Skip functions.
- if (typeof value != 'function') {
- sb.push(sep);
- this.serializeString_(key, sb);
- sb.push(':');
-
- this.serializeInternal(
- this.replacer_ ? this.replacer_.call(obj, key, value) : value,
- sb);
-
- sep = ',';
- }
- }
- }
- sb.push('}');
-};
-
-// Copyright 2007 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Error codes shared between goog.net.IframeIo and
- * goog.net.XhrIo.
- */
-
-goog.provide('goog.net.ErrorCode');
-
-
-/**
- * Error codes
- * @enum {number}
- */
-goog.net.ErrorCode = {
-
- /**
- * There is no error condition.
- */
- NO_ERROR: 0,
-
- /**
- * The most common error from iframeio, unfortunately, is that the browser
- * responded with an error page that is classed as a different domain. The
- * situations, are when a browser error page is shown -- 404, access denied,
- * DNS failure, connection reset etc.)
- *
- */
- ACCESS_DENIED: 1,
-
- /**
- * Currently the only case where file not found will be caused is when the
- * code is running on the local file system and a non-IE browser makes a
- * request to a file that doesn't exist.
- */
- FILE_NOT_FOUND: 2,
-
- /**
- * If Firefox shows a browser error page, such as a connection reset by
- * server or access denied, then it will fail silently without the error or
- * load handlers firing.
- */
- FF_SILENT_ERROR: 3,
-
- /**
- * Custom error provided by the client through the error check hook.
- */
- CUSTOM_ERROR: 4,
-
- /**
- * Exception was thrown while processing the request.
- */
- EXCEPTION: 5,
-
- /**
- * The Http response returned a non-successful http status code.
- */
- HTTP_ERROR: 6,
-
- /**
- * The request was aborted.
- */
- ABORT: 7,
-
- /**
- * The request timed out.
- */
- TIMEOUT: 8,
-
- /**
- * The resource is not available offline.
- */
- OFFLINE: 9
-};
-
-
-/**
- * Returns a friendly error message for an error code. These messages are for
- * debugging and are not localized.
- * @param {goog.net.ErrorCode} errorCode An error code.
- * @return {string} A message for debugging.
- */
-goog.net.ErrorCode.getDebugMessage = function(errorCode) {
- switch (errorCode) {
- case goog.net.ErrorCode.NO_ERROR:
- return 'No Error';
-
- case goog.net.ErrorCode.ACCESS_DENIED:
- return 'Access denied to content document';
-
- case goog.net.ErrorCode.FILE_NOT_FOUND:
- return 'File not found';
-
- case goog.net.ErrorCode.FF_SILENT_ERROR:
- return 'Firefox silently errored';
-
- case goog.net.ErrorCode.CUSTOM_ERROR:
- return 'Application custom error';
-
- case goog.net.ErrorCode.EXCEPTION:
- return 'An exception occurred';
-
- case goog.net.ErrorCode.HTTP_ERROR:
- return 'Http response at 400 or 500 level';
-
- case goog.net.ErrorCode.ABORT:
- return 'Request was aborted';
-
- case goog.net.ErrorCode.TIMEOUT:
- return 'Request timed out';
-
- case goog.net.ErrorCode.OFFLINE:
- return 'The resource is not available offline';
-
- default:
- return 'Unrecognized error code';
- }
-};
-
-// Copyright 2011 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Constants for HTTP status codes.
- */
-
-goog.provide('goog.net.HttpStatus');
-
-
-/**
- * HTTP Status Codes defined in RFC 2616 and RFC 6585.
- * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
- * @see http://tools.ietf.org/html/rfc6585
- * @enum {number}
- */
-goog.net.HttpStatus = {
- // Informational 1xx
- CONTINUE: 100,
- SWITCHING_PROTOCOLS: 101,
-
- // Successful 2xx
- OK: 200,
- CREATED: 201,
- ACCEPTED: 202,
- NON_AUTHORITATIVE_INFORMATION: 203,
- NO_CONTENT: 204,
- RESET_CONTENT: 205,
- PARTIAL_CONTENT: 206,
-
- // Redirection 3xx
- MULTIPLE_CHOICES: 300,
- MOVED_PERMANENTLY: 301,
- FOUND: 302,
- SEE_OTHER: 303,
- NOT_MODIFIED: 304,
- USE_PROXY: 305,
- TEMPORARY_REDIRECT: 307,
-
- // Client Error 4xx
- BAD_REQUEST: 400,
- UNAUTHORIZED: 401,
- PAYMENT_REQUIRED: 402,
- FORBIDDEN: 403,
- NOT_FOUND: 404,
- METHOD_NOT_ALLOWED: 405,
- NOT_ACCEPTABLE: 406,
- PROXY_AUTHENTICATION_REQUIRED: 407,
- REQUEST_TIMEOUT: 408,
- CONFLICT: 409,
- GONE: 410,
- LENGTH_REQUIRED: 411,
- PRECONDITION_FAILED: 412,
- REQUEST_ENTITY_TOO_LARGE: 413,
- REQUEST_URI_TOO_LONG: 414,
- UNSUPPORTED_MEDIA_TYPE: 415,
- REQUEST_RANGE_NOT_SATISFIABLE: 416,
- EXPECTATION_FAILED: 417,
- PRECONDITION_REQUIRED: 428,
- TOO_MANY_REQUESTS: 429,
- REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
-
- // Server Error 5xx
- INTERNAL_SERVER_ERROR: 500,
- NOT_IMPLEMENTED: 501,
- BAD_GATEWAY: 502,
- SERVICE_UNAVAILABLE: 503,
- GATEWAY_TIMEOUT: 504,
- HTTP_VERSION_NOT_SUPPORTED: 505,
- NETWORK_AUTHENTICATION_REQUIRED: 511,
-
- /*
- * IE returns this code for 204 due to its use of URLMon, which returns this
- * code for 'Operation Aborted'. The status text is 'Unknown', the response
- * headers are ''. Known to occur on IE 6 on XP through IE9 on Win7.
- */
- QUIRK_IE_NO_CONTENT: 1223
-};
-
-
-/**
- * Returns whether the given status should be considered successful.
- *
- * Successful codes are OK (200), CREATED (201), ACCEPTED (202),
- * NO CONTENT (204), PARTIAL CONTENT (206), NOT MODIFIED (304),
- * and IE's no content code (1223).
- *
- * @param {number} status The status code to test.
- * @return {boolean} Whether the status code should be considered successful.
- */
-goog.net.HttpStatus.isSuccess = function(status) {
- switch (status) {
- case goog.net.HttpStatus.OK:
- case goog.net.HttpStatus.CREATED:
- case goog.net.HttpStatus.ACCEPTED:
- case goog.net.HttpStatus.NO_CONTENT:
- case goog.net.HttpStatus.PARTIAL_CONTENT:
- case goog.net.HttpStatus.NOT_MODIFIED:
- case goog.net.HttpStatus.QUIRK_IE_NO_CONTENT:
- return true;
-
- default:
- return false;
- }
-};
-
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-goog.provide('goog.net.XhrLike');
-
-
-
-/**
- * Interface for the common parts of XMLHttpRequest.
- *
- * Mostly copied from externs/w3c_xml.js.
- *
- * @interface
- * @see http://www.w3.org/TR/XMLHttpRequest/
- */
-goog.net.XhrLike = function() {};
-
-
-/**
- * Typedef that refers to either native or custom-implemented XHR objects.
- * @typedef {!goog.net.XhrLike|!XMLHttpRequest}
- */
-goog.net.XhrLike.OrNative;
-
-
-/**
- * @type {function()|null|undefined}
- * @see http://www.w3.org/TR/XMLHttpRequest/#handler-xhr-onreadystatechange
- */
-goog.net.XhrLike.prototype.onreadystatechange;
-
-
-/**
- * @type {string}
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsetext-attribute
- */
-goog.net.XhrLike.prototype.responseText;
-
-
-/**
- * @type {Document}
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsexml-attribute
- */
-goog.net.XhrLike.prototype.responseXML;
-
-
-/**
- * @type {number}
- * @see http://www.w3.org/TR/XMLHttpRequest/#readystate
- */
-goog.net.XhrLike.prototype.readyState;
-
-
-/**
- * @type {number}
- * @see http://www.w3.org/TR/XMLHttpRequest/#status
- */
-goog.net.XhrLike.prototype.status;
-
-
-/**
- * @type {string}
- * @see http://www.w3.org/TR/XMLHttpRequest/#statustext
- */
-goog.net.XhrLike.prototype.statusText;
-
-
-/**
- * @param {string} method
- * @param {string} url
- * @param {?boolean=} opt_async
- * @param {?string=} opt_user
- * @param {?string=} opt_password
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-open()-method
- */
-goog.net.XhrLike.prototype.open = function(method, url, opt_async, opt_user,
- opt_password) {};
-
-
-/**
- * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=} opt_data
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-send()-method
- */
-goog.net.XhrLike.prototype.send = function(opt_data) {};
-
-
-/**
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-abort()-method
- */
-goog.net.XhrLike.prototype.abort = function() {};
-
-
-/**
- * @param {string} header
- * @param {string} value
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method
- */
-goog.net.XhrLike.prototype.setRequestHeader = function(header, value) {};
-
-
-/**
- * @param {string} header
- * @return {string}
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
- */
-goog.net.XhrLike.prototype.getResponseHeader = function(header) {};
-
-
-/**
- * @return {string}
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders()-method
- */
-goog.net.XhrLike.prototype.getAllResponseHeaders = function() {};
-
-// Copyright 2010 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Interface for a factory for creating XMLHttpRequest objects
- * and metadata about them.
- * @author dbk@google.com (David Barrett-Kahn)
- */
-
-goog.provide('goog.net.XmlHttpFactory');
-
-/** @suppress {extraRequire} Typedef. */
-goog.require('goog.net.XhrLike');
-
-
-
-/**
- * Abstract base class for an XmlHttpRequest factory.
- * @constructor
- */
-goog.net.XmlHttpFactory = function() {
-};
-
-
-/**
- * Cache of options - we only actually call internalGetOptions once.
- * @type {Object}
- * @private
- */
-goog.net.XmlHttpFactory.prototype.cachedOptions_ = null;
-
-
-/**
- * @return {!goog.net.XhrLike.OrNative} A new XhrLike instance.
- */
-goog.net.XmlHttpFactory.prototype.createInstance = goog.abstractMethod;
-
-
-/**
- * @return {Object} Options describing how xhr objects obtained from this
- * factory should be used.
- */
-goog.net.XmlHttpFactory.prototype.getOptions = function() {
- return this.cachedOptions_ ||
- (this.cachedOptions_ = this.internalGetOptions());
-};
-
-
-/**
- * Override this method in subclasses to preserve the caching offered by
- * getOptions().
- * @return {Object} Options describing how xhr objects obtained from this
- * factory should be used.
- * @protected
- */
-goog.net.XmlHttpFactory.prototype.internalGetOptions = goog.abstractMethod;
-
-// Copyright 2010 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Implementation of XmlHttpFactory which allows construction from
- * simple factory methods.
- * @author dbk@google.com (David Barrett-Kahn)
- */
-
-goog.provide('goog.net.WrapperXmlHttpFactory');
-
-/** @suppress {extraRequire} Typedef. */
-goog.require('goog.net.XhrLike');
-goog.require('goog.net.XmlHttpFactory');
-
-
-
-/**
- * An xhr factory subclass which can be constructed using two factory methods.
- * This exists partly to allow the preservation of goog.net.XmlHttp.setFactory()
- * with an unchanged signature.
- * @param {function():!goog.net.XhrLike.OrNative} xhrFactory
- * A function which returns a new XHR object.
- * @param {function():!Object} optionsFactory A function which returns the
- * options associated with xhr objects from this factory.
- * @extends {goog.net.XmlHttpFactory}
- * @constructor
- * @final
- */
-goog.net.WrapperXmlHttpFactory = function(xhrFactory, optionsFactory) {
- goog.net.XmlHttpFactory.call(this);
-
- /**
- * XHR factory method.
- * @type {function() : !goog.net.XhrLike.OrNative}
- * @private
- */
- this.xhrFactory_ = xhrFactory;
-
- /**
- * Options factory method.
- * @type {function() : !Object}
- * @private
- */
- this.optionsFactory_ = optionsFactory;
-};
-goog.inherits(goog.net.WrapperXmlHttpFactory, goog.net.XmlHttpFactory);
-
-
-/** @override */
-goog.net.WrapperXmlHttpFactory.prototype.createInstance = function() {
- return this.xhrFactory_();
-};
-
-
-/** @override */
-goog.net.WrapperXmlHttpFactory.prototype.getOptions = function() {
- return this.optionsFactory_();
-};
-
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Low level handling of XMLHttpRequest.
- * @author arv@google.com (Erik Arvidsson)
- * @author dbk@google.com (David Barrett-Kahn)
- */
-
-goog.provide('goog.net.DefaultXmlHttpFactory');
-goog.provide('goog.net.XmlHttp');
-goog.provide('goog.net.XmlHttp.OptionType');
-goog.provide('goog.net.XmlHttp.ReadyState');
-goog.provide('goog.net.XmlHttpDefines');
-
-goog.require('goog.asserts');
-goog.require('goog.net.WrapperXmlHttpFactory');
-goog.require('goog.net.XmlHttpFactory');
-
-
-/**
- * Static class for creating XMLHttpRequest objects.
- * @return {!goog.net.XhrLike.OrNative} A new XMLHttpRequest object.
- */
-goog.net.XmlHttp = function() {
- return goog.net.XmlHttp.factory_.createInstance();
-};
-
-
-/**
- * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to
- * true bypasses the ActiveX probing code.
- * NOTE(ruilopes): Due to the way JSCompiler works, this define *will not* strip
- * out the ActiveX probing code from binaries. To achieve this, use
- * {@code goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR} instead.
- * TODO(ruilopes): Collapse both defines.
- */
-goog.define('goog.net.XmlHttp.ASSUME_NATIVE_XHR', false);
-
-
-/** @const */
-goog.net.XmlHttpDefines = {};
-
-
-/**
- * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to
- * true eliminates the ActiveX probing code.
- */
-goog.define('goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR', false);
-
-
-/**
- * Gets the options to use with the XMLHttpRequest objects obtained using
- * the static methods.
- * @return {Object} The options.
- */
-goog.net.XmlHttp.getOptions = function() {
- return goog.net.XmlHttp.factory_.getOptions();
-};
-
-
-/**
- * Type of options that an XmlHttp object can have.
- * @enum {number}
- */
-goog.net.XmlHttp.OptionType = {
- /**
- * Whether a goog.nullFunction should be used to clear the onreadystatechange
- * handler instead of null.
- */
- USE_NULL_FUNCTION: 0,
-
- /**
- * NOTE(user): In IE if send() errors on a *local* request the readystate
- * is still changed to COMPLETE. We need to ignore it and allow the
- * try/catch around send() to pick up the error.
- */
- LOCAL_REQUEST_ERROR: 1
-};
-
-
-/**
- * Status constants for XMLHTTP, matches:
- * http://msdn.microsoft.com/library/default.asp?url=/library/
- * en-us/xmlsdk/html/0e6a34e4-f90c-489d-acff-cb44242fafc6.asp
- * @enum {number}
- */
-goog.net.XmlHttp.ReadyState = {
- /**
- * Constant for when xmlhttprequest.readyState is uninitialized
- */
- UNINITIALIZED: 0,
-
- /**
- * Constant for when xmlhttprequest.readyState is loading.
- */
- LOADING: 1,
-
- /**
- * Constant for when xmlhttprequest.readyState is loaded.
- */
- LOADED: 2,
-
- /**
- * Constant for when xmlhttprequest.readyState is in an interactive state.
- */
- INTERACTIVE: 3,
-
- /**
- * Constant for when xmlhttprequest.readyState is completed
- */
- COMPLETE: 4
-};
-
-
-/**
- * The global factory instance for creating XMLHttpRequest objects.
- * @type {goog.net.XmlHttpFactory}
- * @private
- */
-goog.net.XmlHttp.factory_;
-
-
-/**
- * Sets the factories for creating XMLHttpRequest objects and their options.
- * @param {Function} factory The factory for XMLHttpRequest objects.
- * @param {Function} optionsFactory The factory for options.
- * @deprecated Use setGlobalFactory instead.
- */
-goog.net.XmlHttp.setFactory = function(factory, optionsFactory) {
- goog.net.XmlHttp.setGlobalFactory(new goog.net.WrapperXmlHttpFactory(
- goog.asserts.assert(factory),
- goog.asserts.assert(optionsFactory)));
-};
-
-
-/**
- * Sets the global factory object.
- * @param {!goog.net.XmlHttpFactory} factory New global factory object.
- */
-goog.net.XmlHttp.setGlobalFactory = function(factory) {
- goog.net.XmlHttp.factory_ = factory;
-};
-
-
-
-/**
- * Default factory to use when creating xhr objects. You probably shouldn't be
- * instantiating this directly, but rather using it via goog.net.XmlHttp.
- * @extends {goog.net.XmlHttpFactory}
- * @constructor
- */
-goog.net.DefaultXmlHttpFactory = function() {
- goog.net.XmlHttpFactory.call(this);
-};
-goog.inherits(goog.net.DefaultXmlHttpFactory, goog.net.XmlHttpFactory);
-
-
-/** @override */
-goog.net.DefaultXmlHttpFactory.prototype.createInstance = function() {
- var progId = this.getProgId_();
- if (progId) {
- return new ActiveXObject(progId);
- } else {
- return new XMLHttpRequest();
- }
-};
-
-
-/** @override */
-goog.net.DefaultXmlHttpFactory.prototype.internalGetOptions = function() {
- var progId = this.getProgId_();
- var options = {};
- if (progId) {
- options[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] = true;
- options[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] = true;
- }
- return options;
-};
-
-
-/**
- * The ActiveX PROG ID string to use to create xhr's in IE. Lazily initialized.
- * @type {string|undefined}
- * @private
- */
-goog.net.DefaultXmlHttpFactory.prototype.ieProgId_;
-
-
-/**
- * Initialize the private state used by other functions.
- * @return {string} The ActiveX PROG ID string to use to create xhr's in IE.
- * @private
- */
-goog.net.DefaultXmlHttpFactory.prototype.getProgId_ = function() {
- if (goog.net.XmlHttp.ASSUME_NATIVE_XHR ||
- goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR) {
- return '';
- }
-
- // The following blog post describes what PROG IDs to use to create the
- // XMLHTTP object in Internet Explorer:
- // http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
- // However we do not (yet) fully trust that this will be OK for old versions
- // of IE on Win9x so we therefore keep the last 2.
- if (!this.ieProgId_ && typeof XMLHttpRequest == 'undefined' &&
- typeof ActiveXObject != 'undefined') {
- // Candidate Active X types.
- var ACTIVE_X_IDENTS = ['MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0',
- 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];
- for (var i = 0; i < ACTIVE_X_IDENTS.length; i++) {
- var candidate = ACTIVE_X_IDENTS[i];
- /** @preserveTry */
- try {
- new ActiveXObject(candidate);
- // NOTE(user): cannot assign progid and return candidate in one line
- // because JSCompiler complaings: BUG 658126
- this.ieProgId_ = candidate;
- return candidate;
- } catch (e) {
- // do nothing; try next choice
- }
- }
-
- // couldn't find any matches
- throw Error('Could not create ActiveXObject. ActiveX might be disabled,' +
- ' or MSXML might not be installed');
- }
-
- return /** @type {string} */ (this.ieProgId_);
-};
-
-
-//Set the global factory to an instance of the default factory.
-goog.net.XmlHttp.setGlobalFactory(new goog.net.DefaultXmlHttpFactory());
-
-// Copyright 2008 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Simple utilities for dealing with URI strings.
- *
- * This is intended to be a lightweight alternative to constructing goog.Uri
- * objects. Whereas goog.Uri adds several kilobytes to the binary regardless
- * of how much of its functionality you use, this is designed to be a set of
- * mostly-independent utilities so that the compiler includes only what is
- * necessary for the task. Estimated savings of porting is 5k pre-gzip and
- * 1.5k post-gzip. To ensure the savings remain, future developers should
- * avoid adding new functionality to existing functions, but instead create
- * new ones and factor out shared code.
- *
- * Many of these utilities have limited functionality, tailored to common
- * cases. The query parameter utilities assume that the parameter keys are
- * already encoded, since most keys are compile-time alphanumeric strings. The
- * query parameter mutation utilities also do not tolerate fragment identifiers.
- *
- * By design, these functions can be slower than goog.Uri equivalents.
- * Repeated calls to some of functions may be quadratic in behavior for IE,
- * although the effect is somewhat limited given the 2kb limit.
- *
- * One advantage of the limited functionality here is that this approach is
- * less sensitive to differences in URI encodings than goog.Uri, since these
- * functions operate on strings directly, rather than decoding them and
- * then re-encoding.
- *
- * Uses features of RFC 3986 for parsing/formatting URIs:
- * http://www.ietf.org/rfc/rfc3986.txt
- *
- * @author gboyer@google.com (Garrett Boyer) - The "lightened" design.
- */
-
-goog.provide('goog.uri.utils');
-goog.provide('goog.uri.utils.ComponentIndex');
-goog.provide('goog.uri.utils.QueryArray');
-goog.provide('goog.uri.utils.QueryValue');
-goog.provide('goog.uri.utils.StandardQueryParam');
-
-goog.require('goog.asserts');
-goog.require('goog.string');
-
-
-/**
- * Character codes inlined to avoid object allocations due to charCode.
- * @enum {number}
- * @private
- */
-goog.uri.utils.CharCode_ = {
- AMPERSAND: 38,
- EQUAL: 61,
- HASH: 35,
- QUESTION: 63
-};
-
-
-/**
- * Builds a URI string from already-encoded parts.
- *
- * No encoding is performed. Any component may be omitted as either null or
- * undefined.
- *
- * @param {?string=} opt_scheme The scheme such as 'http'.
- * @param {?string=} opt_userInfo The user name before the '@'.
- * @param {?string=} opt_domain The domain such as 'www.google.com', already
- * URI-encoded.
- * @param {(string|number|null)=} opt_port The port number.
- * @param {?string=} opt_path The path, already URI-encoded. If it is not
- * empty, it must begin with a slash.
- * @param {?string=} opt_queryData The URI-encoded query data.
- * @param {?string=} opt_fragment The URI-encoded fragment identifier.
- * @return {string} The fully combined URI.
- */
-goog.uri.utils.buildFromEncodedParts = function(opt_scheme, opt_userInfo,
- opt_domain, opt_port, opt_path, opt_queryData, opt_fragment) {
- var out = '';
-
- if (opt_scheme) {
- out += opt_scheme + ':';
- }
-
- if (opt_domain) {
- out += '//';
-
- if (opt_userInfo) {
- out += opt_userInfo + '@';
- }
-
- out += opt_domain;
-
- if (opt_port) {
- out += ':' + opt_port;
- }
- }
-
- if (opt_path) {
- out += opt_path;
- }
-
- if (opt_queryData) {
- out += '?' + opt_queryData;
- }
-
- if (opt_fragment) {
- out += '#' + opt_fragment;
- }
-
- return out;
-};
-
-
-/**
- * A regular expression for breaking a URI into its component parts.
- *
- * {@link http://www.ietf.org/rfc/rfc3986.txt} says in Appendix B
- * As the "first-match-wins" algorithm is identical to the "greedy"
- * disambiguation method used by POSIX regular expressions, it is natural and
- * commonplace to use a regular expression for parsing the potential five
- * components of a URI reference.
- *
- * The following line is the regular expression for breaking-down a
- * well-formed URI reference into its components.
- *
- * <pre>
- * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- * 12 3 4 5 6 7 8 9
- * </pre>
- *
- * The numbers in the second line above are only to assist readability; they
- * indicate the reference points for each subexpression (i.e., each paired
- * parenthesis). We refer to the value matched for subexpression <n> as $<n>.
- * For example, matching the above expression to
- * <pre>
- * http://www.ics.uci.edu/pub/ietf/uri/#Related
- * </pre>
- * results in the following subexpression matches:
- * <pre>
- * $1 = http:
- * $2 = http
- * $3 = //www.ics.uci.edu
- * $4 = www.ics.uci.edu
- * $5 = /pub/ietf/uri/
- * $6 = <undefined>
- * $7 = <undefined>
- * $8 = #Related
- * $9 = Related
- * </pre>
- * where <undefined> indicates that the component is not present, as is the
- * case for the query component in the above example. Therefore, we can
- * determine the value of the five components as
- * <pre>
- * scheme = $2
- * authority = $4
- * path = $5
- * query = $7
- * fragment = $9
- * </pre>
- *
- * The regular expression has been modified slightly to expose the
- * userInfo, domain, and port separately from the authority.
- * The modified version yields
- * <pre>
- * $1 = http scheme
- * $2 = <undefined> userInfo -\
- * $3 = www.ics.uci.edu domain | authority
- * $4 = <undefined> port -/
- * $5 = /pub/ietf/uri/ path
- * $6 = <undefined> query without ?
- * $7 = Related fragment without #
- * </pre>
- * @type {!RegExp}
- * @private
- */
-goog.uri.utils.splitRe_ = new RegExp(
- '^' +
- '(?:' +
- '([^:/?#.]+)' + // scheme - ignore special characters
- // used by other URL parts such as :,
- // ?, /, #, and .
- ':)?' +
- '(?://' +
- '(?:([^/?#]*)@)?' + // userInfo
- '([^/#?]*?)' + // domain
- '(?::([0-9]+))?' + // port
- '(?=[/#?]|$)' + // authority-terminating character
- ')?' +
- '([^?#]+)?' + // path
- '(?:\\?([^#]*))?' + // query
- '(?:#(.*))?' + // fragment
- '$');
-
-
-/**
- * The index of each URI component in the return value of goog.uri.utils.split.
- * @enum {number}
- */
-goog.uri.utils.ComponentIndex = {
- SCHEME: 1,
- USER_INFO: 2,
- DOMAIN: 3,
- PORT: 4,
- PATH: 5,
- QUERY_DATA: 6,
- FRAGMENT: 7
-};
-
-
-/**
- * Splits a URI into its component parts.
- *
- * Each component can be accessed via the component indices; for example:
- * <pre>
- * goog.uri.utils.split(someStr)[goog.uri.utils.CompontentIndex.QUERY_DATA];
- * </pre>
- *
- * @param {string} uri The URI string to examine.
- * @return {!Array<string|undefined>} Each component still URI-encoded.
- * Each component that is present will contain the encoded value, whereas
- * components that are not present will be undefined or empty, depending
- * on the browser's regular expression implementation. Never null, since
- * arbitrary strings may still look like path names.
- */
-goog.uri.utils.split = function(uri) {
- // See @return comment -- never null.
- return /** @type {!Array<string|undefined>} */ (
- uri.match(goog.uri.utils.splitRe_));
-};
-
-
-/**
- * @param {?string} uri A possibly null string.
- * @param {boolean=} opt_preserveReserved If true, percent-encoding of RFC-3986
- * reserved characters will not be removed.
- * @return {?string} The string URI-decoded, or null if uri is null.
- * @private
- */
-goog.uri.utils.decodeIfPossible_ = function(uri, opt_preserveReserved) {
- if (!uri) {
- return uri;
- }
-
- return opt_preserveReserved ? decodeURI(uri) : decodeURIComponent(uri);
-};
-
-
-/**
- * Gets a URI component by index.
- *
- * It is preferred to use the getPathEncoded() variety of functions ahead,
- * since they are more readable.
- *
- * @param {goog.uri.utils.ComponentIndex} componentIndex The component index.
- * @param {string} uri The URI to examine.
- * @return {?string} The still-encoded component, or null if the component
- * is not present.
- * @private
- */
-goog.uri.utils.getComponentByIndex_ = function(componentIndex, uri) {
- // Convert undefined, null, and empty string into null.
- return goog.uri.utils.split(uri)[componentIndex] || null;
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The protocol or scheme, or null if none. Does not
- * include trailing colons or slashes.
- */
-goog.uri.utils.getScheme = function(uri) {
- return goog.uri.utils.getComponentByIndex_(
- goog.uri.utils.ComponentIndex.SCHEME, uri);
-};
-
-
-/**
- * Gets the effective scheme for the URL. If the URL is relative then the
- * scheme is derived from the page's location.
- * @param {string} uri The URI to examine.
- * @return {string} The protocol or scheme, always lower case.
- */
-goog.uri.utils.getEffectiveScheme = function(uri) {
- var scheme = goog.uri.utils.getScheme(uri);
- if (!scheme && goog.global.self && goog.global.self.location) {
- var protocol = goog.global.self.location.protocol;
- scheme = protocol.substr(0, protocol.length - 1);
- }
- // NOTE: When called from a web worker in Firefox 3.5, location maybe null.
- // All other browsers with web workers support self.location from the worker.
- return scheme ? scheme.toLowerCase() : '';
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The user name still encoded, or null if none.
- */
-goog.uri.utils.getUserInfoEncoded = function(uri) {
- return goog.uri.utils.getComponentByIndex_(
- goog.uri.utils.ComponentIndex.USER_INFO, uri);
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The decoded user info, or null if none.
- */
-goog.uri.utils.getUserInfo = function(uri) {
- return goog.uri.utils.decodeIfPossible_(
- goog.uri.utils.getUserInfoEncoded(uri));
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The domain name still encoded, or null if none.
- */
-goog.uri.utils.getDomainEncoded = function(uri) {
- return goog.uri.utils.getComponentByIndex_(
- goog.uri.utils.ComponentIndex.DOMAIN, uri);
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The decoded domain, or null if none.
- */
-goog.uri.utils.getDomain = function(uri) {
- return goog.uri.utils.decodeIfPossible_(
- goog.uri.utils.getDomainEncoded(uri), true /* opt_preserveReserved */);
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?number} The port number, or null if none.
- */
-goog.uri.utils.getPort = function(uri) {
- // Coerce to a number. If the result of getComponentByIndex_ is null or
- // non-numeric, the number coersion yields NaN. This will then return
- // null for all non-numeric cases (though also zero, which isn't a relevant
- // port number).
- return Number(goog.uri.utils.getComponentByIndex_(
- goog.uri.utils.ComponentIndex.PORT, uri)) || null;
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The path still encoded, or null if none. Includes the
- * leading slash, if any.
- */
-goog.uri.utils.getPathEncoded = function(uri) {
- return goog.uri.utils.getComponentByIndex_(
- goog.uri.utils.ComponentIndex.PATH, uri);
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The decoded path, or null if none. Includes the leading
- * slash, if any.
- */
-goog.uri.utils.getPath = function(uri) {
- return goog.uri.utils.decodeIfPossible_(
- goog.uri.utils.getPathEncoded(uri), true /* opt_preserveReserved */);
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The query data still encoded, or null if none. Does not
- * include the question mark itself.
- */
-goog.uri.utils.getQueryData = function(uri) {
- return goog.uri.utils.getComponentByIndex_(
- goog.uri.utils.ComponentIndex.QUERY_DATA, uri);
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The fragment identifier, or null if none. Does not
- * include the hash mark itself.
- */
-goog.uri.utils.getFragmentEncoded = function(uri) {
- // The hash mark may not appear in any other part of the URL.
- var hashIndex = uri.indexOf('#');
- return hashIndex < 0 ? null : uri.substr(hashIndex + 1);
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @param {?string} fragment The encoded fragment identifier, or null if none.
- * Does not include the hash mark itself.
- * @return {string} The URI with the fragment set.
- */
-goog.uri.utils.setFragmentEncoded = function(uri, fragment) {
- return goog.uri.utils.removeFragment(uri) + (fragment ? '#' + fragment : '');
-};
-
-
-/**
- * @param {string} uri The URI to examine.
- * @return {?string} The decoded fragment identifier, or null if none. Does
- * not include the hash mark.
- */
-goog.uri.utils.getFragment = function(uri) {
- return goog.uri.utils.decodeIfPossible_(
- goog.uri.utils.getFragmentEncoded(uri));
-};
-
-
-/**
- * Extracts everything up to the port of the URI.
- * @param {string} uri The URI string.
- * @return {string} Everything up to and including the port.
- */
-goog.uri.utils.getHost = function(uri) {
- var pieces = goog.uri.utils.split(uri);
- return goog.uri.utils.buildFromEncodedParts(
- pieces[goog.uri.utils.ComponentIndex.SCHEME],
- pieces[goog.uri.utils.ComponentIndex.USER_INFO],
- pieces[goog.uri.utils.ComponentIndex.DOMAIN],
- pieces[goog.uri.utils.ComponentIndex.PORT]);
-};
-
-
-/**
- * Extracts the path of the URL and everything after.
- * @param {string} uri The URI string.
- * @return {string} The URI, starting at the path and including the query
- * parameters and fragment identifier.
- */
-goog.uri.utils.getPathAndAfter = function(uri) {
- var pieces = goog.uri.utils.split(uri);
- return goog.uri.utils.buildFromEncodedParts(null, null, null, null,
- pieces[goog.uri.utils.ComponentIndex.PATH],
- pieces[goog.uri.utils.ComponentIndex.QUERY_DATA],
- pieces[goog.uri.utils.ComponentIndex.FRAGMENT]);
-};
-
-
-/**
- * Gets the URI with the fragment identifier removed.
- * @param {string} uri The URI to examine.
- * @return {string} Everything preceding the hash mark.
- */
-goog.uri.utils.removeFragment = function(uri) {
- // The hash mark may not appear in any other part of the URL.
- var hashIndex = uri.indexOf('#');
- return hashIndex < 0 ? uri : uri.substr(0, hashIndex);
-};
-
-
-/**
- * Ensures that two URI's have the exact same domain, scheme, and port.
- *
- * Unlike the version in goog.Uri, this checks protocol, and therefore is
- * suitable for checking against the browser's same-origin policy.
- *
- * @param {string} uri1 The first URI.
- * @param {string} uri2 The second URI.
- * @return {boolean} Whether they have the same scheme, domain and port.
- */
-goog.uri.utils.haveSameDomain = function(uri1, uri2) {
- var pieces1 = goog.uri.utils.split(uri1);
- var pieces2 = goog.uri.utils.split(uri2);
- return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==
- pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&
- pieces1[goog.uri.utils.ComponentIndex.SCHEME] ==
- pieces2[goog.uri.utils.ComponentIndex.SCHEME] &&
- pieces1[goog.uri.utils.ComponentIndex.PORT] ==
- pieces2[goog.uri.utils.ComponentIndex.PORT];
-};
-
-
-/**
- * Asserts that there are no fragment or query identifiers, only in uncompiled
- * mode.
- * @param {string} uri The URI to examine.
- * @private
- */
-goog.uri.utils.assertNoFragmentsOrQueries_ = function(uri) {
- // NOTE: would use goog.asserts here, but jscompiler doesn't know that
- // indexOf has no side effects.
- if (goog.DEBUG && (uri.indexOf('#') >= 0 || uri.indexOf('?') >= 0)) {
- throw Error('goog.uri.utils: Fragment or query identifiers are not ' +
- 'supported: [' + uri + ']');
- }
-};
-
-
-/**
- * Supported query parameter values by the parameter serializing utilities.
- *
- * If a value is null or undefined, the key-value pair is skipped, as an easy
- * way to omit parameters conditionally. Non-array parameters are converted
- * to a string and URI encoded. Array values are expanded into multiple
- * &key=value pairs, with each element stringized and URI-encoded.
- *
- * @typedef {*}
- */
-goog.uri.utils.QueryValue;
-
-
-/**
- * An array representing a set of query parameters with alternating keys
- * and values.
- *
- * Keys are assumed to be URI encoded already and live at even indices. See
- * goog.uri.utils.QueryValue for details on how parameter values are encoded.
- *
- * Example:
- * <pre>
- * var data = [
- * // Simple param: ?name=BobBarker
- * 'name', 'BobBarker',
- * // Conditional param -- may be omitted entirely.
- * 'specialDietaryNeeds', hasDietaryNeeds() ? getDietaryNeeds() : null,
- * // Multi-valued param: &house=LosAngeles&house=NewYork&house=null
- * 'house', ['LosAngeles', 'NewYork', null]
- * ];
- * </pre>
- *
- * @typedef {!Array<string|goog.uri.utils.QueryValue>}
- */
-goog.uri.utils.QueryArray;
-
-
-/**
- * Parses encoded query parameters and calls callback function for every
- * parameter found in the string.
- *
- * Missing value of parameter (e.g. “…&key&…”) is treated as if the value was an
- * empty string. Keys may be empty strings (e.g. “…&=value&…”) which also means
- * that “…&=&…” and “…&&…” will result in an empty key and value.
- *
- * @param {string} encodedQuery Encoded query string excluding question mark at
- * the beginning.
- * @param {function(string, string)} callback Function called for every
- * parameter found in query string. The first argument (name) will not be
- * urldecoded (so the function is consistent with buildQueryData), but the
- * second will. If the parameter has no value (i.e. “=” was not present)
- * the second argument (value) will be an empty string.
- */
-goog.uri.utils.parseQueryData = function(encodedQuery, callback) {
- if (!encodedQuery) {
- return;
- }
- var pairs = encodedQuery.split('&');
- for (var i = 0; i < pairs.length; i++) {
- var indexOfEquals = pairs[i].indexOf('=');
- var name = null;
- var value = null;
- if (indexOfEquals >= 0) {
- name = pairs[i].substring(0, indexOfEquals);
- value = pairs[i].substring(indexOfEquals + 1);
- } else {
- name = pairs[i];
- }
- callback(name, value ? goog.string.urlDecode(value) : '');
- }
-};
-
-
-/**
- * Appends a URI and query data in a string buffer with special preconditions.
- *
- * Internal implementation utility, performing very few object allocations.
- *
- * @param {!Array<string|undefined>} buffer A string buffer. The first element
- * must be the base URI, and may have a fragment identifier. If the array
- * contains more than one element, the second element must be an ampersand,
- * and may be overwritten, depending on the base URI. Undefined elements
- * are treated as empty-string.
- * @return {string} The concatenated URI and query data.
- * @private
- */
-goog.uri.utils.appendQueryData_ = function(buffer) {
- if (buffer[1]) {
- // At least one query parameter was added. We need to check the
- // punctuation mark, which is currently an ampersand, and also make sure
- // there aren't any interfering fragment identifiers.
- var baseUri = /** @type {string} */ (buffer[0]);
- var hashIndex = baseUri.indexOf('#');
- if (hashIndex >= 0) {
- // Move the fragment off the base part of the URI into the end.
- buffer.push(baseUri.substr(hashIndex));
- buffer[0] = baseUri = baseUri.substr(0, hashIndex);
- }
- var questionIndex = baseUri.indexOf('?');
- if (questionIndex < 0) {
- // No question mark, so we need a question mark instead of an ampersand.
- buffer[1] = '?';
- } else if (questionIndex == baseUri.length - 1) {
- // Question mark is the very last character of the existing URI, so don't
- // append an additional delimiter.
- buffer[1] = undefined;
- }
- }
-
- return buffer.join('');
-};
-
-
-/**
- * Appends key=value pairs to an array, supporting multi-valued objects.
- * @param {string} key The key prefix.
- * @param {goog.uri.utils.QueryValue} value The value to serialize.
- * @param {!Array<string>} pairs The array to which the 'key=value' strings
- * should be appended.
- * @private
- */
-goog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) {
- if (goog.isArray(value)) {
- // Convince the compiler it's an array.
- goog.asserts.assertArray(value);
- for (var j = 0; j < value.length; j++) {
- // Convert to string explicitly, to short circuit the null and array
- // logic in this function -- this ensures that null and undefined get
- // written as literal 'null' and 'undefined', and arrays don't get
- // expanded out but instead encoded in the default way.
- goog.uri.utils.appendKeyValuePairs_(key, String(value[j]), pairs);
- }
- } else if (value != null) {
- // Skip a top-level null or undefined entirely.
- pairs.push('&', key,
- // Check for empty string. Zero gets encoded into the url as literal
- // strings. For empty string, skip the equal sign, to be consistent
- // with UriBuilder.java.
- value === '' ? '' : '=',
- goog.string.urlEncode(value));
- }
-};
-
-
-/**
- * Builds a buffer of query data from a sequence of alternating keys and values.
- *
- * @param {!Array<string|undefined>} buffer A string buffer to append to. The
- * first element appended will be an '&', and may be replaced by the caller.
- * @param {!goog.uri.utils.QueryArray|!Arguments} keysAndValues An array with
- * alternating keys and values -- see the typedef.
- * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.
- * @return {!Array<string|undefined>} The buffer argument.
- * @private
- */
-goog.uri.utils.buildQueryDataBuffer_ = function(
- buffer, keysAndValues, opt_startIndex) {
- goog.asserts.assert(Math.max(keysAndValues.length - (opt_startIndex || 0),
- 0) % 2 == 0, 'goog.uri.utils: Key/value lists must be even in length.');
-
- for (var i = opt_startIndex || 0; i < keysAndValues.length; i += 2) {
- goog.uri.utils.appendKeyValuePairs_(
- keysAndValues[i], keysAndValues[i + 1], buffer);
- }
-
- return buffer;
-};
-
-
-/**
- * Builds a query data string from a sequence of alternating keys and values.
- * Currently generates "&key&" for empty args.
- *
- * @param {goog.uri.utils.QueryArray} keysAndValues Alternating keys and
- * values. See the typedef.
- * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.
- * @return {string} The encoded query string, in the form 'a=1&b=2'.
- */
-goog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) {
- var buffer = goog.uri.utils.buildQueryDataBuffer_(
- [], keysAndValues, opt_startIndex);
- buffer[0] = ''; // Remove the leading ampersand.
- return buffer.join('');
-};
-
-
-/**
- * Builds a buffer of query data from a map.
- *
- * @param {!Array<string|undefined>} buffer A string buffer to append to. The
- * first element appended will be an '&', and may be replaced by the caller.
- * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys
- * are URI-encoded parameter keys, and the values conform to the contract
- * specified in the goog.uri.utils.QueryValue typedef.
- * @return {!Array<string|undefined>} The buffer argument.
- * @private
- */
-goog.uri.utils.buildQueryDataBufferFromMap_ = function(buffer, map) {
- for (var key in map) {
- goog.uri.utils.appendKeyValuePairs_(key, map[key], buffer);
- }
-
- return buffer;
-};
-
-
-/**
- * Builds a query data string from a map.
- * Currently generates "&key&" for empty args.
- *
- * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys
- * are URI-encoded parameter keys, and the values are arbitrary types
- * or arrays. Keys with a null value are dropped.
- * @return {string} The encoded query string, in the form 'a=1&b=2'.
- */
-goog.uri.utils.buildQueryDataFromMap = function(map) {
- var buffer = goog.uri.utils.buildQueryDataBufferFromMap_([], map);
- buffer[0] = '';
- return buffer.join('');
-};
-
-
-/**
- * Appends URI parameters to an existing URI.
- *
- * The variable arguments may contain alternating keys and values. Keys are
- * assumed to be already URI encoded. The values should not be URI-encoded,
- * and will instead be encoded by this function.
- * <pre>
- * appendParams('http://www.foo.com?existing=true',
- * 'key1', 'value1',
- * 'key2', 'value?willBeEncoded',
- * 'key3', ['valueA', 'valueB', 'valueC'],
- * 'key4', null);
- * result: 'http://www.foo.com?existing=true&' +
- * 'key1=value1&' +
- * 'key2=value%3FwillBeEncoded&' +
- * 'key3=valueA&key3=valueB&key3=valueC'
- * </pre>
- *
- * A single call to this function will not exhibit quadratic behavior in IE,
- * whereas multiple repeated calls may, although the effect is limited by
- * fact that URL's generally can't exceed 2kb.
- *
- * @param {string} uri The original URI, which may already have query data.
- * @param {...(goog.uri.utils.QueryArray|string|goog.uri.utils.QueryValue)} var_args
- * An array or argument list conforming to goog.uri.utils.QueryArray.
- * @return {string} The URI with all query parameters added.
- */
-goog.uri.utils.appendParams = function(uri, var_args) {
- return goog.uri.utils.appendQueryData_(
- arguments.length == 2 ?
- goog.uri.utils.buildQueryDataBuffer_([uri], arguments[1], 0) :
- goog.uri.utils.buildQueryDataBuffer_([uri], arguments, 1));
-};
-
-
-/**
- * Appends query parameters from a map.
- *
- * @param {string} uri The original URI, which may already have query data.
- * @param {!Object<goog.uri.utils.QueryValue>} map An object where keys are
- * URI-encoded parameter keys, and the values are arbitrary types or arrays.
- * Keys with a null value are dropped.
- * @return {string} The new parameters.
- */
-goog.uri.utils.appendParamsFromMap = function(uri, map) {
- return goog.uri.utils.appendQueryData_(
- goog.uri.utils.buildQueryDataBufferFromMap_([uri], map));
-};
-
-
-/**
- * Appends a single URI parameter.
- *
- * Repeated calls to this can exhibit quadratic behavior in IE6 due to the
- * way string append works, though it should be limited given the 2kb limit.
- *
- * @param {string} uri The original URI, which may already have query data.
- * @param {string} key The key, which must already be URI encoded.
- * @param {*=} opt_value The value, which will be stringized and encoded
- * (assumed not already to be encoded). If omitted, undefined, or null, the
- * key will be added as a valueless parameter.
- * @return {string} The URI with the query parameter added.
- */
-goog.uri.utils.appendParam = function(uri, key, opt_value) {
- var paramArr = [uri, '&', key];
- if (goog.isDefAndNotNull(opt_value)) {
- paramArr.push('=', goog.string.urlEncode(opt_value));
- }
- return goog.uri.utils.appendQueryData_(paramArr);
-};
-
-
-/**
- * Finds the next instance of a query parameter with the specified name.
- *
- * Does not instantiate any objects.
- *
- * @param {string} uri The URI to search. May contain a fragment identifier
- * if opt_hashIndex is specified.
- * @param {number} startIndex The index to begin searching for the key at. A
- * match may be found even if this is one character after the ampersand.
- * @param {string} keyEncoded The URI-encoded key.
- * @param {number} hashOrEndIndex Index to stop looking at. If a hash
- * mark is present, it should be its index, otherwise it should be the
- * length of the string.
- * @return {number} The position of the first character in the key's name,
- * immediately after either a question mark or a dot.
- * @private
- */
-goog.uri.utils.findParam_ = function(
- uri, startIndex, keyEncoded, hashOrEndIndex) {
- var index = startIndex;
- var keyLength = keyEncoded.length;
-
- // Search for the key itself and post-filter for surronuding punctuation,
- // rather than expensively building a regexp.
- while ((index = uri.indexOf(keyEncoded, index)) >= 0 &&
- index < hashOrEndIndex) {
- var precedingChar = uri.charCodeAt(index - 1);
- // Ensure that the preceding character is '&' or '?'.
- if (precedingChar == goog.uri.utils.CharCode_.AMPERSAND ||
- precedingChar == goog.uri.utils.CharCode_.QUESTION) {
- // Ensure the following character is '&', '=', '#', or NaN
- // (end of string).
- var followingChar = uri.charCodeAt(index + keyLength);
- if (!followingChar ||
- followingChar == goog.uri.utils.CharCode_.EQUAL ||
- followingChar == goog.uri.utils.CharCode_.AMPERSAND ||
- followingChar == goog.uri.utils.CharCode_.HASH) {
- return index;
- }
- }
- index += keyLength + 1;
- }
-
- return -1;
-};
-
-
-/**
- * Regular expression for finding a hash mark or end of string.
- * @type {RegExp}
- * @private
- */
-goog.uri.utils.hashOrEndRe_ = /#|$/;
-
-
-/**
- * Determines if the URI contains a specific key.
- *
- * Performs no object instantiations.
- *
- * @param {string} uri The URI to process. May contain a fragment
- * identifier.
- * @param {string} keyEncoded The URI-encoded key. Case-sensitive.
- * @return {boolean} Whether the key is present.
- */
-goog.uri.utils.hasParam = function(uri, keyEncoded) {
- return goog.uri.utils.findParam_(uri, 0, keyEncoded,
- uri.search(goog.uri.utils.hashOrEndRe_)) >= 0;
-};
-
-
-/**
- * Gets the first value of a query parameter.
- * @param {string} uri The URI to process. May contain a fragment.
- * @param {string} keyEncoded The URI-encoded key. Case-sensitive.
- * @return {?string} The first value of the parameter (URI-decoded), or null
- * if the parameter is not found.
- */
-goog.uri.utils.getParamValue = function(uri, keyEncoded) {
- var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
- var foundIndex = goog.uri.utils.findParam_(
- uri, 0, keyEncoded, hashOrEndIndex);
-
- if (foundIndex < 0) {
- return null;
- } else {
- var endPosition = uri.indexOf('&', foundIndex);
- if (endPosition < 0 || endPosition > hashOrEndIndex) {
- endPosition = hashOrEndIndex;
- }
- // Progress forth to the end of the "key=" or "key&" substring.
- foundIndex += keyEncoded.length + 1;
- // Use substr, because it (unlike substring) will return empty string
- // if foundIndex > endPosition.
- return goog.string.urlDecode(
- uri.substr(foundIndex, endPosition - foundIndex));
- }
-};
-
-
-/**
- * Gets all values of a query parameter.
- * @param {string} uri The URI to process. May contain a fragment.
- * @param {string} keyEncoded The URI-encoded key. Case-sensitive.
- * @return {!Array<string>} All URI-decoded values with the given key.
- * If the key is not found, this will have length 0, but never be null.
- */
-goog.uri.utils.getParamValues = function(uri, keyEncoded) {
- var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
- var position = 0;
- var foundIndex;
- var result = [];
-
- while ((foundIndex = goog.uri.utils.findParam_(
- uri, position, keyEncoded, hashOrEndIndex)) >= 0) {
- // Find where this parameter ends, either the '&' or the end of the
- // query parameters.
- position = uri.indexOf('&', foundIndex);
- if (position < 0 || position > hashOrEndIndex) {
- position = hashOrEndIndex;
- }
-
- // Progress forth to the end of the "key=" or "key&" substring.
- foundIndex += keyEncoded.length + 1;
- // Use substr, because it (unlike substring) will return empty string
- // if foundIndex > position.
- result.push(goog.string.urlDecode(uri.substr(
- foundIndex, position - foundIndex)));
- }
-
- return result;
-};
-
-
-/**
- * Regexp to find trailing question marks and ampersands.
- * @type {RegExp}
- * @private
- */
-goog.uri.utils.trailingQueryPunctuationRe_ = /[?&]($|#)/;
-
-
-/**
- * Removes all instances of a query parameter.
- * @param {string} uri The URI to process. Must not contain a fragment.
- * @param {string} keyEncoded The URI-encoded key.
- * @return {string} The URI with all instances of the parameter removed.
- */
-goog.uri.utils.removeParam = function(uri, keyEncoded) {
- var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
- var position = 0;
- var foundIndex;
- var buffer = [];
-
- // Look for a query parameter.
- while ((foundIndex = goog.uri.utils.findParam_(
- uri, position, keyEncoded, hashOrEndIndex)) >= 0) {
- // Get the portion of the query string up to, but not including, the ?
- // or & starting the parameter.
- buffer.push(uri.substring(position, foundIndex));
- // Progress to immediately after the '&'. If not found, go to the end.
- // Avoid including the hash mark.
- position = Math.min((uri.indexOf('&', foundIndex) + 1) || hashOrEndIndex,
- hashOrEndIndex);
- }
-
- // Append everything that is remaining.
- buffer.push(uri.substr(position));
-
- // Join the buffer, and remove trailing punctuation that remains.
- return buffer.join('').replace(
- goog.uri.utils.trailingQueryPunctuationRe_, '$1');
-};
-
-
-/**
- * Replaces all existing definitions of a parameter with a single definition.
- *
- * Repeated calls to this can exhibit quadratic behavior due to the need to
- * find existing instances and reconstruct the string, though it should be
- * limited given the 2kb limit. Consider using appendParams to append multiple
- * parameters in bulk.
- *
- * @param {string} uri The original URI, which may already have query data.
- * @param {string} keyEncoded The key, which must already be URI encoded.
- * @param {*} value The value, which will be stringized and encoded (assumed
- * not already to be encoded).
- * @return {string} The URI with the query parameter added.
- */
-goog.uri.utils.setParam = function(uri, keyEncoded, value) {
- return goog.uri.utils.appendParam(
- goog.uri.utils.removeParam(uri, keyEncoded), keyEncoded, value);
-};
-
-
-/**
- * Generates a URI path using a given URI and a path with checks to
- * prevent consecutive "//". The baseUri passed in must not contain
- * query or fragment identifiers. The path to append may not contain query or
- * fragment identifiers.
- *
- * @param {string} baseUri URI to use as the base.
- * @param {string} path Path to append.
- * @return {string} Updated URI.
- */
-goog.uri.utils.appendPath = function(baseUri, path) {
- goog.uri.utils.assertNoFragmentsOrQueries_(baseUri);
-
- // Remove any trailing '/'
- if (goog.string.endsWith(baseUri, '/')) {
- baseUri = baseUri.substr(0, baseUri.length - 1);
- }
- // Remove any leading '/'
- if (goog.string.startsWith(path, '/')) {
- path = path.substr(1);
- }
- return goog.string.buildString(baseUri, '/', path);
-};
-
-
-/**
- * Replaces the path.
- * @param {string} uri URI to use as the base.
- * @param {string} path New path.
- * @return {string} Updated URI.
- */
-goog.uri.utils.setPath = function(uri, path) {
- // Add any missing '/'.
- if (!goog.string.startsWith(path, '/')) {
- path = '/' + path;
- }
- var parts = goog.uri.utils.split(uri);
- return goog.uri.utils.buildFromEncodedParts(
- parts[goog.uri.utils.ComponentIndex.SCHEME],
- parts[goog.uri.utils.ComponentIndex.USER_INFO],
- parts[goog.uri.utils.ComponentIndex.DOMAIN],
- parts[goog.uri.utils.ComponentIndex.PORT],
- path,
- parts[goog.uri.utils.ComponentIndex.QUERY_DATA],
- parts[goog.uri.utils.ComponentIndex.FRAGMENT]);
-};
-
-
-/**
- * Standard supported query parameters.
- * @enum {string}
- */
-goog.uri.utils.StandardQueryParam = {
-
- /** Unused parameter for unique-ifying. */
- RANDOM: 'zx'
-};
-
-
-/**
- * Sets the zx parameter of a URI to a random value.
- * @param {string} uri Any URI.
- * @return {string} That URI with the "zx" parameter added or replaced to
- * contain a random string.
- */
-goog.uri.utils.makeUnique = function(uri) {
- return goog.uri.utils.setParam(uri,
- goog.uri.utils.StandardQueryParam.RANDOM, goog.string.getRandomString());
-};
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Wrapper class for handling XmlHttpRequests.
- *
- * One off requests can be sent through goog.net.XhrIo.send() or an
- * instance can be created to send multiple requests. Each request uses its
- * own XmlHttpRequest object and handles clearing of the event callback to
- * ensure no leaks.
- *
- * XhrIo is event based, it dispatches events on success, failure, finishing,
- * ready-state change, or progress.
- *
- * The ready-state or timeout event fires first, followed by
- * a generic completed event. Then the abort, error, or success event
- * is fired as appropriate. Progress events are fired as they are
- * received. Lastly, the ready event will fire to indicate that the
- * object may be used to make another request.
- *
- * The error event may also be called before completed and
- * ready-state-change if the XmlHttpRequest.open() or .send() methods throw.
- *
- * This class does not support multiple requests, queuing, or prioritization.
- *
- * When progress events are supported by the browser, and progress is
- * enabled via .setProgressEventsEnabled(true), the
- * goog.net.EventType.PROGRESS event will be the re-dispatched browser
- * progress event.
- *
- * Tested = IE6, FF1.5, Safari, Opera 8.5
- *
- * TODO(user): Error cases aren't playing nicely in Safari.
- *
- */
-
-
-goog.provide('goog.net.XhrIo');
-goog.provide('goog.net.XhrIo.ResponseType');
-
-goog.require('goog.Timer');
-goog.require('goog.array');
-goog.require('goog.asserts');
-goog.require('goog.debug.entryPointRegistry');
-goog.require('goog.events.EventTarget');
-goog.require('goog.json');
-goog.require('goog.log');
-goog.require('goog.net.ErrorCode');
-goog.require('goog.net.EventType');
-goog.require('goog.net.HttpStatus');
-goog.require('goog.net.XmlHttp');
-goog.require('goog.object');
-goog.require('goog.string');
-goog.require('goog.structs');
-goog.require('goog.structs.Map');
-goog.require('goog.uri.utils');
-goog.require('goog.userAgent');
-
-goog.forwardDeclare('goog.Uri');
-
-
-
-/**
- * Basic class for handling XMLHttpRequests.
- * @param {goog.net.XmlHttpFactory=} opt_xmlHttpFactory Factory to use when
- * creating XMLHttpRequest objects.
- * @constructor
- * @extends {goog.events.EventTarget}
- */
-goog.net.XhrIo = function(opt_xmlHttpFactory) {
- goog.net.XhrIo.base(this, 'constructor');
-
- /**
- * Map of default headers to add to every request, use:
- * XhrIo.headers.set(name, value)
- * @type {!goog.structs.Map}
- */
- this.headers = new goog.structs.Map();
-
- /**
- * Optional XmlHttpFactory
- * @private {goog.net.XmlHttpFactory}
- */
- this.xmlHttpFactory_ = opt_xmlHttpFactory || null;
-
- /**
- * Whether XMLHttpRequest is active. A request is active from the time send()
- * is called until onReadyStateChange() is complete, or error() or abort()
- * is called.
- * @private {boolean}
- */
- this.active_ = false;
-
- /**
- * The XMLHttpRequest object that is being used for the transfer.
- * @private {?goog.net.XhrLike.OrNative}
- */
- this.xhr_ = null;
-
- /**
- * The options to use with the current XMLHttpRequest object.
- * @private {Object}
- */
- this.xhrOptions_ = null;
-
- /**
- * Last URL that was requested.
- * @private {string|goog.Uri}
- */
- this.lastUri_ = '';
-
- /**
- * Method for the last request.
- * @private {string}
- */
- this.lastMethod_ = '';
-
- /**
- * Last error code.
- * @private {!goog.net.ErrorCode}
- */
- this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
-
- /**
- * Last error message.
- * @private {Error|string}
- */
- this.lastError_ = '';
-
- /**
- * Used to ensure that we don't dispatch an multiple ERROR events. This can
- * happen in IE when it does a synchronous load and one error is handled in
- * the ready statte change and one is handled due to send() throwing an
- * exception.
- * @private {boolean}
- */
- this.errorDispatched_ = false;
-
- /**
- * Used to make sure we don't fire the complete event from inside a send call.
- * @private {boolean}
- */
- this.inSend_ = false;
-
- /**
- * Used in determining if a call to {@link #onReadyStateChange_} is from
- * within a call to this.xhr_.open.
- * @private {boolean}
- */
- this.inOpen_ = false;
-
- /**
- * Used in determining if a call to {@link #onReadyStateChange_} is from
- * within a call to this.xhr_.abort.
- * @private {boolean}
- */
- this.inAbort_ = false;
-
- /**
- * Number of milliseconds after which an incomplete request will be aborted
- * and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no timeout
- * is set.
- * @private {number}
- */
- this.timeoutInterval_ = 0;
-
- /**
- * Timer to track request timeout.
- * @private {?number}
- */
- this.timeoutId_ = null;
-
- /**
- * The requested type for the response. The empty string means use the default
- * XHR behavior.
- * @private {goog.net.XhrIo.ResponseType}
- */
- this.responseType_ = goog.net.XhrIo.ResponseType.DEFAULT;
-
- /**
- * Whether a "credentialed" request is to be sent (one that is aware of
- * cookies and authentication). This is applicable only for cross-domain
- * requests and more recent browsers that support this part of the HTTP Access
- * Control standard.
- *
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-withcredentials-attribute
- *
- * @private {boolean}
- */
- this.withCredentials_ = false;
-
- /**
- * Whether progress events are enabled for this request. This is
- * disabled by default because setting a progress event handler
- * causes pre-flight OPTIONS requests to be sent for CORS requests,
- * even in cases where a pre-flight request would not otherwise be
- * sent.
- *
- * @see http://xhr.spec.whatwg.org/#security-considerations
- *
- * Note that this can cause problems for Firefox 22 and below, as an
- * older "LSProgressEvent" will be dispatched by the browser. That
- * progress event is no longer supported, and can lead to failures,
- * including throwing exceptions.
- *
- * @see http://bugzilla.mozilla.org/show_bug.cgi?id=845631
- * @see b/23469793
- *
- * @private {boolean}
- */
- this.progressEventsEnabled_ = false;
-
- /**
- * True if we can use XMLHttpRequest's timeout directly.
- * @private {boolean}
- */
- this.useXhr2Timeout_ = false;
-};
-goog.inherits(goog.net.XhrIo, goog.events.EventTarget);
-
-
-/**
- * Response types that may be requested for XMLHttpRequests.
- * @enum {string}
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsetype-attribute
- */
-goog.net.XhrIo.ResponseType = {
- DEFAULT: '',
- TEXT: 'text',
- DOCUMENT: 'document',
- // Not supported as of Chrome 10.0.612.1 dev
- BLOB: 'blob',
- ARRAY_BUFFER: 'arraybuffer'
-};
-
-
-/**
- * A reference to the XhrIo logger
- * @private {goog.debug.Logger}
- * @const
- */
-goog.net.XhrIo.prototype.logger_ =
- goog.log.getLogger('goog.net.XhrIo');
-
-
-/**
- * The Content-Type HTTP header name
- * @type {string}
- */
-goog.net.XhrIo.CONTENT_TYPE_HEADER = 'Content-Type';
-
-
-/**
- * The pattern matching the 'http' and 'https' URI schemes
- * @type {!RegExp}
- */
-goog.net.XhrIo.HTTP_SCHEME_PATTERN = /^https?$/i;
-
-
-/**
- * The methods that typically come along with form data. We set different
- * headers depending on whether the HTTP action is one of these.
- */
-goog.net.XhrIo.METHODS_WITH_FORM_DATA = ['POST', 'PUT'];
-
-
-/**
- * The Content-Type HTTP header value for a url-encoded form
- * @type {string}
- */
-goog.net.XhrIo.FORM_CONTENT_TYPE =
- 'application/x-www-form-urlencoded;charset=utf-8';
-
-
-/**
- * The XMLHttpRequest Level two timeout delay ms property name.
- *
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute
- *
- * @private {string}
- * @const
- */
-goog.net.XhrIo.XHR2_TIMEOUT_ = 'timeout';
-
-
-/**
- * The XMLHttpRequest Level two ontimeout handler property name.
- *
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute
- *
- * @private {string}
- * @const
- */
-goog.net.XhrIo.XHR2_ON_TIMEOUT_ = 'ontimeout';
-
-
-/**
- * All non-disposed instances of goog.net.XhrIo created
- * by {@link goog.net.XhrIo.send} are in this Array.
- * @see goog.net.XhrIo.cleanup
- * @private {!Array<!goog.net.XhrIo>}
- */
-goog.net.XhrIo.sendInstances_ = [];
-
-
-/**
- * Static send that creates a short lived instance of XhrIo to send the
- * request.
- * @see goog.net.XhrIo.cleanup
- * @param {string|goog.Uri} url Uri to make request to.
- * @param {?function(this:goog.net.XhrIo, ?)=} opt_callback Callback function
- * for when request is complete.
- * @param {string=} opt_method Send method, default: GET.
- * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}
- * opt_content Body data.
- * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
- * request.
- * @param {number=} opt_timeoutInterval Number of milliseconds after which an
- * incomplete request will be aborted; 0 means no timeout is set.
- * @param {boolean=} opt_withCredentials Whether to send credentials with the
- * request. Default to false. See {@link goog.net.XhrIo#setWithCredentials}.
- * @return {!goog.net.XhrIo} The sent XhrIo.
- */
-goog.net.XhrIo.send = function(url, opt_callback, opt_method, opt_content,
- opt_headers, opt_timeoutInterval,
- opt_withCredentials) {
- var x = new goog.net.XhrIo();
- goog.net.XhrIo.sendInstances_.push(x);
- if (opt_callback) {
- x.listen(goog.net.EventType.COMPLETE, opt_callback);
- }
- x.listenOnce(goog.net.EventType.READY, x.cleanupSend_);
- if (opt_timeoutInterval) {
- x.setTimeoutInterval(opt_timeoutInterval);
- }
- if (opt_withCredentials) {
- x.setWithCredentials(opt_withCredentials);
- }
- x.send(url, opt_method, opt_content, opt_headers);
- return x;
-};
-
-
-/**
- * Disposes all non-disposed instances of goog.net.XhrIo created by
- * {@link goog.net.XhrIo.send}.
- * {@link goog.net.XhrIo.send} cleans up the goog.net.XhrIo instance
- * it creates when the request completes or fails. However, if
- * the request never completes, then the goog.net.XhrIo is not disposed.
- * This can occur if the window is unloaded before the request completes.
- * We could have {@link goog.net.XhrIo.send} return the goog.net.XhrIo
- * it creates and make the client of {@link goog.net.XhrIo.send} be
- * responsible for disposing it in this case. However, this makes things
- * significantly more complicated for the client, and the whole point
- * of {@link goog.net.XhrIo.send} is that it's simple and easy to use.
- * Clients of {@link goog.net.XhrIo.send} should call
- * {@link goog.net.XhrIo.cleanup} when doing final
- * cleanup on window unload.
- */
-goog.net.XhrIo.cleanup = function() {
- var instances = goog.net.XhrIo.sendInstances_;
- while (instances.length) {
- instances.pop().dispose();
- }
-};
-
-
-/**
- * Installs exception protection for all entry point introduced by
- * goog.net.XhrIo instances which are not protected by
- * {@link goog.debug.ErrorHandler#protectWindowSetTimeout},
- * {@link goog.debug.ErrorHandler#protectWindowSetInterval}, or
- * {@link goog.events.protectBrowserEventEntryPoint}.
- *
- * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
- * protect the entry point(s).
- */
-goog.net.XhrIo.protectEntryPoints = function(errorHandler) {
- goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ =
- errorHandler.protectEntryPoint(
- goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);
-};
-
-
-/**
- * Disposes of the specified goog.net.XhrIo created by
- * {@link goog.net.XhrIo.send} and removes it from
- * {@link goog.net.XhrIo.pendingStaticSendInstances_}.
- * @private
- */
-goog.net.XhrIo.prototype.cleanupSend_ = function() {
- this.dispose();
- goog.array.remove(goog.net.XhrIo.sendInstances_, this);
-};
-
-
-/**
- * Returns the number of milliseconds after which an incomplete request will be
- * aborted, or 0 if no timeout is set.
- * @return {number} Timeout interval in milliseconds.
- */
-goog.net.XhrIo.prototype.getTimeoutInterval = function() {
- return this.timeoutInterval_;
-};
-
-
-/**
- * Sets the number of milliseconds after which an incomplete request will be
- * aborted and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no
- * timeout is set.
- * @param {number} ms Timeout interval in milliseconds; 0 means none.
- */
-goog.net.XhrIo.prototype.setTimeoutInterval = function(ms) {
- this.timeoutInterval_ = Math.max(0, ms);
-};
-
-
-/**
- * Sets the desired type for the response. At time of writing, this is only
- * supported in very recent versions of WebKit (10.0.612.1 dev and later).
- *
- * If this is used, the response may only be accessed via {@link #getResponse}.
- *
- * @param {goog.net.XhrIo.ResponseType} type The desired type for the response.
- */
-goog.net.XhrIo.prototype.setResponseType = function(type) {
- this.responseType_ = type;
-};
-
-
-/**
- * Gets the desired type for the response.
- * @return {goog.net.XhrIo.ResponseType} The desired type for the response.
- */
-goog.net.XhrIo.prototype.getResponseType = function() {
- return this.responseType_;
-};
-
-
-/**
- * Sets whether a "credentialed" request that is aware of cookie and
- * authentication information should be made. This option is only supported by
- * browsers that support HTTP Access Control. As of this writing, this option
- * is not supported in IE.
- *
- * @param {boolean} withCredentials Whether this should be a "credentialed"
- * request.
- */
-goog.net.XhrIo.prototype.setWithCredentials = function(withCredentials) {
- this.withCredentials_ = withCredentials;
-};
-
-
-/**
- * Gets whether a "credentialed" request is to be sent.
- * @return {boolean} The desired type for the response.
- */
-goog.net.XhrIo.prototype.getWithCredentials = function() {
- return this.withCredentials_;
-};
-
-
-/**
- * Sets whether progress events are enabled for this request. Note
- * that progress events require pre-flight OPTIONS request handling
- * for CORS requests, and may cause trouble with older browsers. See
- * progressEventsEnabled_ for details.
- * @param {boolean} enabled Whether progress events should be enabled.
- */
-goog.net.XhrIo.prototype.setProgressEventsEnabled = function(enabled) {
- this.progressEventsEnabled_ = enabled;
-};
-
-
-/**
- * Gets whether progress events are enabled.
- * @return {boolean} Whether progress events are enabled for this request.
- */
-goog.net.XhrIo.prototype.getProgressEventsEnabled = function() {
- return this.progressEventsEnabled_;
-};
-
-
-/**
- * Instance send that actually uses XMLHttpRequest to make a server call.
- * @param {string|goog.Uri} url Uri to make request to.
- * @param {string=} opt_method Send method, default: GET.
- * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}
- * opt_content Body data.
- * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
- * request.
- */
-goog.net.XhrIo.prototype.send = function(url, opt_method, opt_content,
- opt_headers) {
- if (this.xhr_) {
- throw Error('[goog.net.XhrIo] Object is active with another request=' +
- this.lastUri_ + '; newUri=' + url);
- }
-
- var method = opt_method ? opt_method.toUpperCase() : 'GET';
-
- this.lastUri_ = url;
- this.lastError_ = '';
- this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
- this.lastMethod_ = method;
- this.errorDispatched_ = false;
- this.active_ = true;
-
- // Use the factory to create the XHR object and options
- this.xhr_ = this.createXhr();
- this.xhrOptions_ = this.xmlHttpFactory_ ?
- this.xmlHttpFactory_.getOptions() : goog.net.XmlHttp.getOptions();
-
- // Set up the onreadystatechange callback
- this.xhr_.onreadystatechange = goog.bind(this.onReadyStateChange_, this);
-
- // Set up upload/download progress events, if progress events are supported.
- if (this.getProgressEventsEnabled() && 'onprogress' in this.xhr_) {
- this.xhr_.onprogress = goog.bind(this.onProgressHandler_, this);
- if (this.xhr_.upload) {
- this.xhr_.upload.onprogress = goog.bind(this.onProgressHandler_, this);
- }
- }
-
- /**
- * Try to open the XMLHttpRequest (always async), if an error occurs here it
- * is generally permission denied
- * @preserveTry
- */
- try {
- goog.log.fine(this.logger_, this.formatMsg_('Opening Xhr'));
- this.inOpen_ = true;
- this.xhr_.open(method, String(url), true); // Always async!
- this.inOpen_ = false;
- } catch (err) {
- goog.log.fine(this.logger_,
- this.formatMsg_('Error opening Xhr: ' + err.message));
- this.error_(goog.net.ErrorCode.EXCEPTION, err);
- return;
- }
-
- // We can't use null since this won't allow requests with form data to have a
- // content length specified which will cause some proxies to return a 411
- // error.
- var content = opt_content || '';
-
- var headers = this.headers.clone();
-
- // Add headers specific to this request
- if (opt_headers) {
- goog.structs.forEach(opt_headers, function(value, key) {
- headers.set(key, value);
- });
- }
-
- // Find whether a content type header is set, ignoring case.
- // HTTP header names are case-insensitive. See:
- // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
- var contentTypeKey = goog.array.find(headers.getKeys(),
- goog.net.XhrIo.isContentTypeHeader_);
-
- var contentIsFormData = (goog.global['FormData'] &&
- (content instanceof goog.global['FormData']));
- if (goog.array.contains(goog.net.XhrIo.METHODS_WITH_FORM_DATA, method) &&
- !contentTypeKey && !contentIsFormData) {
- // For requests typically with form data, default to the url-encoded form
- // content type unless this is a FormData request. For FormData,
- // the browser will automatically add a multipart/form-data content type
- // with an appropriate multipart boundary.
- headers.set(goog.net.XhrIo.CONTENT_TYPE_HEADER,
- goog.net.XhrIo.FORM_CONTENT_TYPE);
- }
-
- // Add the headers to the Xhr object
- headers.forEach(function(value, key) {
- this.xhr_.setRequestHeader(key, value);
- }, this);
-
- if (this.responseType_) {
- this.xhr_.responseType = this.responseType_;
- }
-
- if (goog.object.containsKey(this.xhr_, 'withCredentials')) {
- this.xhr_.withCredentials = this.withCredentials_;
- }
-
- /**
- * Try to send the request, or other wise report an error (404 not found).
- * @preserveTry
- */
- try {
- this.cleanUpTimeoutTimer_(); // Paranoid, should never be running.
- if (this.timeoutInterval_ > 0) {
- this.useXhr2Timeout_ = goog.net.XhrIo.shouldUseXhr2Timeout_(this.xhr_);
- goog.log.fine(this.logger_, this.formatMsg_('Will abort after ' +
- this.timeoutInterval_ + 'ms if incomplete, xhr2 ' +
- this.useXhr2Timeout_));
- if (this.useXhr2Timeout_) {
- this.xhr_[goog.net.XhrIo.XHR2_TIMEOUT_] = this.timeoutInterval_;
- this.xhr_[goog.net.XhrIo.XHR2_ON_TIMEOUT_] =
- goog.bind(this.timeout_, this);
- } else {
- this.timeoutId_ = goog.Timer.callOnce(this.timeout_,
- this.timeoutInterval_, this);
- }
- }
- goog.log.fine(this.logger_, this.formatMsg_('Sending request'));
- this.inSend_ = true;
- this.xhr_.send(content);
- this.inSend_ = false;
-
- } catch (err) {
- goog.log.fine(this.logger_, this.formatMsg_('Send error: ' + err.message));
- this.error_(goog.net.ErrorCode.EXCEPTION, err);
- }
-};
-
-
-/**
- * Determines if the argument is an XMLHttpRequest that supports the level 2
- * timeout value and event.
- *
- * Currently, FF 21.0 OS X has the fields but won't actually call the timeout
- * handler. Perhaps the confusion in the bug referenced below hasn't
- * entirely been resolved.
- *
- * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute
- * @see https://bugzilla.mozilla.org/show_bug.cgi?id=525816
- *
- * @param {!goog.net.XhrLike.OrNative} xhr The request.
- * @return {boolean} True if the request supports level 2 timeout.
- * @private
- */
-goog.net.XhrIo.shouldUseXhr2Timeout_ = function(xhr) {
- return goog.userAgent.IE &&
- goog.userAgent.isVersionOrHigher(9) &&
- goog.isNumber(xhr[goog.net.XhrIo.XHR2_TIMEOUT_]) &&
- goog.isDef(xhr[goog.net.XhrIo.XHR2_ON_TIMEOUT_]);
-};
-
-
-/**
- * @param {string} header An HTTP header key.
- * @return {boolean} Whether the key is a content type header (ignoring
- * case.
- * @private
- */
-goog.net.XhrIo.isContentTypeHeader_ = function(header) {
- return goog.string.caseInsensitiveEquals(
- goog.net.XhrIo.CONTENT_TYPE_HEADER, header);
-};
-
-
-/**
- * Creates a new XHR object.
- * @return {!goog.net.XhrLike.OrNative} The newly created XHR object.
- * @protected
- */
-goog.net.XhrIo.prototype.createXhr = function() {
- return this.xmlHttpFactory_ ?
- this.xmlHttpFactory_.createInstance() : goog.net.XmlHttp();
-};
-
-
-/**
- * The request didn't complete after {@link goog.net.XhrIo#timeoutInterval_}
- * milliseconds; raises a {@link goog.net.EventType.TIMEOUT} event and aborts
- * the request.
- * @private
- */
-goog.net.XhrIo.prototype.timeout_ = function() {
- if (typeof goog == 'undefined') {
- // If goog is undefined then the callback has occurred as the application
- // is unloading and will error. Thus we let it silently fail.
- } else if (this.xhr_) {
- this.lastError_ = 'Timed out after ' + this.timeoutInterval_ +
- 'ms, aborting';
- this.lastErrorCode_ = goog.net.ErrorCode.TIMEOUT;
- goog.log.fine(this.logger_, this.formatMsg_(this.lastError_));
- this.dispatchEvent(goog.net.EventType.TIMEOUT);
- this.abort(goog.net.ErrorCode.TIMEOUT);
- }
-};
-
-
-/**
- * Something errorred, so inactivate, fire error callback and clean up
- * @param {goog.net.ErrorCode} errorCode The error code.
- * @param {Error} err The error object.
- * @private
- */
-goog.net.XhrIo.prototype.error_ = function(errorCode, err) {
- this.active_ = false;
- if (this.xhr_) {
- this.inAbort_ = true;
- this.xhr_.abort(); // Ensures XHR isn't hung (FF)
- this.inAbort_ = false;
- }
- this.lastError_ = err;
- this.lastErrorCode_ = errorCode;
- this.dispatchErrors_();
- this.cleanUpXhr_();
-};
-
-
-/**
- * Dispatches COMPLETE and ERROR in case of an error. This ensures that we do
- * not dispatch multiple error events.
- * @private
- */
-goog.net.XhrIo.prototype.dispatchErrors_ = function() {
- if (!this.errorDispatched_) {
- this.errorDispatched_ = true;
- this.dispatchEvent(goog.net.EventType.COMPLETE);
- this.dispatchEvent(goog.net.EventType.ERROR);
- }
-};
-
-
-/**
- * Abort the current XMLHttpRequest
- * @param {goog.net.ErrorCode=} opt_failureCode Optional error code to use -
- * defaults to ABORT.
- */
-goog.net.XhrIo.prototype.abort = function(opt_failureCode) {
- if (this.xhr_ && this.active_) {
- goog.log.fine(this.logger_, this.formatMsg_('Aborting'));
- this.active_ = false;
- this.inAbort_ = true;
- this.xhr_.abort();
- this.inAbort_ = false;
- this.lastErrorCode_ = opt_failureCode || goog.net.ErrorCode.ABORT;
- this.dispatchEvent(goog.net.EventType.COMPLETE);
- this.dispatchEvent(goog.net.EventType.ABORT);
- this.cleanUpXhr_();
- }
-};
-
-
-/**
- * Nullifies all callbacks to reduce risks of leaks.
- * @override
- * @protected
- */
-goog.net.XhrIo.prototype.disposeInternal = function() {
- if (this.xhr_) {
- // We explicitly do not call xhr_.abort() unless active_ is still true.
- // This is to avoid unnecessarily aborting a successful request when
- // dispose() is called in a callback triggered by a complete response, but
- // in which browser cleanup has not yet finished.
- // (See http://b/issue?id=1684217.)
- if (this.active_) {
- this.active_ = false;
- this.inAbort_ = true;
- this.xhr_.abort();
- this.inAbort_ = false;
- }
- this.cleanUpXhr_(true);
- }
-
- goog.net.XhrIo.base(this, 'disposeInternal');
-};
-
-
-/**
- * Internal handler for the XHR object's readystatechange event. This method
- * checks the status and the readystate and fires the correct callbacks.
- * If the request has ended, the handlers are cleaned up and the XHR object is
- * nullified.
- * @private
- */
-goog.net.XhrIo.prototype.onReadyStateChange_ = function() {
- if (this.isDisposed()) {
- // This method is the target of an untracked goog.Timer.callOnce().
- return;
- }
- if (!this.inOpen_ && !this.inSend_ && !this.inAbort_) {
- // Were not being called from within a call to this.xhr_.send
- // this.xhr_.abort, or this.xhr_.open, so this is an entry point
- this.onReadyStateChangeEntryPoint_();
- } else {
- this.onReadyStateChangeHelper_();
- }
-};
-
-
-/**
- * Used to protect the onreadystatechange handler entry point. Necessary
- * as {#onReadyStateChange_} maybe called from within send or abort, this
- * method is only called when {#onReadyStateChange_} is called as an
- * entry point.
- * {@see #protectEntryPoints}
- * @private
- */
-goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ = function() {
- this.onReadyStateChangeHelper_();
-};
-
-
-/**
- * Helper for {@link #onReadyStateChange_}. This is used so that
- * entry point calls to {@link #onReadyStateChange_} can be routed through
- * {@link #onReadyStateChangeEntryPoint_}.
- * @private
- */
-goog.net.XhrIo.prototype.onReadyStateChangeHelper_ = function() {
- if (!this.active_) {
- // can get called inside abort call
- return;
- }
-
- if (typeof goog == 'undefined') {
- // NOTE(user): If goog is undefined then the callback has occurred as the
- // application is unloading and will error. Thus we let it silently fail.
-
- } else if (
- this.xhrOptions_[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] &&
- this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE &&
- this.getStatus() == 2) {
- // NOTE(user): In IE if send() errors on a *local* request the readystate
- // is still changed to COMPLETE. We need to ignore it and allow the
- // try/catch around send() to pick up the error.
- goog.log.fine(this.logger_, this.formatMsg_(
- 'Local request error detected and ignored'));
-
- } else {
-
- // In IE when the response has been cached we sometimes get the callback
- // from inside the send call and this usually breaks code that assumes that
- // XhrIo is asynchronous. If that is the case we delay the callback
- // using a timer.
- if (this.inSend_ &&
- this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE) {
- goog.Timer.callOnce(this.onReadyStateChange_, 0, this);
- return;
- }
-
- this.dispatchEvent(goog.net.EventType.READY_STATE_CHANGE);
-
- // readyState indicates the transfer has finished
- if (this.isComplete()) {
- goog.log.fine(this.logger_, this.formatMsg_('Request complete'));
-
- this.active_ = false;
-
- try {
- // Call the specific callbacks for success or failure. Only call the
- // success if the status is 200 (HTTP_OK) or 304 (HTTP_CACHED)
- if (this.isSuccess()) {
- this.dispatchEvent(goog.net.EventType.COMPLETE);
- this.dispatchEvent(goog.net.EventType.SUCCESS);
- } else {
- this.lastErrorCode_ = goog.net.ErrorCode.HTTP_ERROR;
- this.lastError_ =
- this.getStatusText() + ' [' + this.getStatus() + ']';
- this.dispatchErrors_();
- }
- } finally {
- this.cleanUpXhr_();
- }
- }
- }
-};
-
-
-/**
- * Internal handler for the XHR object's onprogress event.
- * @param {!ProgressEvent} e XHR progress event.
- * @private
- */
-goog.net.XhrIo.prototype.onProgressHandler_ = function(e) {
- goog.asserts.assert(e.type === goog.net.EventType.PROGRESS,
- 'goog.net.EventType.PROGRESS is of the same type as raw XHR progress.');
- // Redispatch the progress event.
- this.dispatchEvent(e);
-};
-
-
-/**
- * Remove the listener to protect against leaks, and nullify the XMLHttpRequest
- * object.
- * @param {boolean=} opt_fromDispose If this is from the dispose (don't want to
- * fire any events).
- * @private
- */
-goog.net.XhrIo.prototype.cleanUpXhr_ = function(opt_fromDispose) {
- if (this.xhr_) {
- // Cancel any pending timeout event handler.
- this.cleanUpTimeoutTimer_();
-
- // Save reference so we can mark it as closed after the READY event. The
- // READY event may trigger another request, thus we must nullify this.xhr_
- var xhr = this.xhr_;
- var clearedOnReadyStateChange =
- this.xhrOptions_[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] ?
- goog.nullFunction : null;
- this.xhr_ = null;
- this.xhrOptions_ = null;
-
- if (!opt_fromDispose) {
- this.dispatchEvent(goog.net.EventType.READY);
- }
-
- try {
- // NOTE(user): Not nullifying in FireFox can still leak if the callbacks
- // are defined in the same scope as the instance of XhrIo. But, IE doesn't
- // allow you to set the onreadystatechange to NULL so nullFunction is
- // used.
- xhr.onreadystatechange = clearedOnReadyStateChange;
- } catch (e) {
- // This seems to occur with a Gears HTTP request. Delayed the setting of
- // this onreadystatechange until after READY is sent out and catching the
- // error to see if we can track down the problem.
- goog.log.error(this.logger_,
- 'Problem encountered resetting onreadystatechange: ' + e.message);
- }
- }
-};
-
-
-/**
- * Make sure the timeout timer isn't running.
- * @private
- */
-goog.net.XhrIo.prototype.cleanUpTimeoutTimer_ = function() {
- if (this.xhr_ && this.useXhr2Timeout_) {
- this.xhr_[goog.net.XhrIo.XHR2_ON_TIMEOUT_] = null;
- }
- if (goog.isNumber(this.timeoutId_)) {
- goog.Timer.clear(this.timeoutId_);
- this.timeoutId_ = null;
- }
-};
-
-
-/**
- * @return {boolean} Whether there is an active request.
- */
-goog.net.XhrIo.prototype.isActive = function() {
- return !!this.xhr_;
-};
-
-
-/**
- * @return {boolean} Whether the request has completed.
- */
-goog.net.XhrIo.prototype.isComplete = function() {
- return this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE;
-};
-
-
-/**
- * @return {boolean} Whether the request completed with a success.
- */
-goog.net.XhrIo.prototype.isSuccess = function() {
- var status = this.getStatus();
- // A zero status code is considered successful for local files.
- return goog.net.HttpStatus.isSuccess(status) ||
- status === 0 && !this.isLastUriEffectiveSchemeHttp_();
-};
-
-
-/**
- * @return {boolean} whether the effective scheme of the last URI that was
- * fetched was 'http' or 'https'.
- * @private
- */
-goog.net.XhrIo.prototype.isLastUriEffectiveSchemeHttp_ = function() {
- var scheme = goog.uri.utils.getEffectiveScheme(String(this.lastUri_));
- return goog.net.XhrIo.HTTP_SCHEME_PATTERN.test(scheme);
-};
-
-
-/**
- * Get the readystate from the Xhr object
- * Will only return correct result when called from the context of a callback
- * @return {goog.net.XmlHttp.ReadyState} goog.net.XmlHttp.ReadyState.*.
- */
-goog.net.XhrIo.prototype.getReadyState = function() {
- return this.xhr_ ?
- /** @type {goog.net.XmlHttp.ReadyState} */ (this.xhr_.readyState) :
- goog.net.XmlHttp.ReadyState.UNINITIALIZED;
-};
-
-
-/**
- * Get the status from the Xhr object
- * Will only return correct result when called from the context of a callback
- * @return {number} Http status.
- */
-goog.net.XhrIo.prototype.getStatus = function() {
- /**
- * IE doesn't like you checking status until the readystate is greater than 2
- * (i.e. it is receiving or complete). The try/catch is used for when the
- * page is unloading and an ERROR_NOT_AVAILABLE may occur when accessing xhr_.
- * @preserveTry
- */
- try {
- return this.getReadyState() > goog.net.XmlHttp.ReadyState.LOADED ?
- this.xhr_.status : -1;
- } catch (e) {
- return -1;
- }
-};
-
-
-/**
- * Get the status text from the Xhr object
- * Will only return correct result when called from the context of a callback
- * @return {string} Status text.
- */
-goog.net.XhrIo.prototype.getStatusText = function() {
- /**
- * IE doesn't like you checking status until the readystate is greater than 2
- * (i.e. it is recieving or complete). The try/catch is used for when the
- * page is unloading and an ERROR_NOT_AVAILABLE may occur when accessing xhr_.
- * @preserveTry
- */
- try {
- return this.getReadyState() > goog.net.XmlHttp.ReadyState.LOADED ?
- this.xhr_.statusText : '';
- } catch (e) {
- goog.log.fine(this.logger_, 'Can not get status: ' + e.message);
- return '';
- }
-};
-
-
-/**
- * Get the last Uri that was requested
- * @return {string} Last Uri.
- */
-goog.net.XhrIo.prototype.getLastUri = function() {
- return String(this.lastUri_);
-};
-
-
-/**
- * Get the response text from the Xhr object
- * Will only return correct result when called from the context of a callback.
- * @return {string} Result from the server, or '' if no result available.
- */
-goog.net.XhrIo.prototype.getResponseText = function() {
- /** @preserveTry */
- try {
- return this.xhr_ ? this.xhr_.responseText : '';
- } catch (e) {
- // http://www.w3.org/TR/XMLHttpRequest/#the-responsetext-attribute
- // states that responseText should return '' (and responseXML null)
- // when the state is not LOADING or DONE. Instead, IE can
- // throw unexpected exceptions, for example when a request is aborted
- // or no data is available yet.
- goog.log.fine(this.logger_, 'Can not get responseText: ' + e.message);
- return '';
- }
-};
-
-
-/**
- * Get the response body from the Xhr object. This property is only available
- * in IE since version 7 according to MSDN:
- * http://msdn.microsoft.com/en-us/library/ie/ms534368(v=vs.85).aspx
- * Will only return correct result when called from the context of a callback.
- *
- * One option is to construct a VBArray from the returned object and convert
- * it to a JavaScript array using the toArray method:
- * {@code (new window['VBArray'](xhrIo.getResponseBody())).toArray()}
- * This will result in an array of numbers in the range of [0..255]
- *
- * Another option is to use the VBScript CStr method to convert it into a
- * string as outlined in http://stackoverflow.com/questions/1919972
- *
- * @return {Object} Binary result from the server or null if not available.
- */
-goog.net.XhrIo.prototype.getResponseBody = function() {
- /** @preserveTry */
- try {
- if (this.xhr_ && 'responseBody' in this.xhr_) {
- return this.xhr_['responseBody'];
- }
- } catch (e) {
- // IE can throw unexpected exceptions, for example when a request is aborted
- // or no data is yet available.
- goog.log.fine(this.logger_, 'Can not get responseBody: ' + e.message);
- }
- return null;
-};
-
-
-/**
- * Get the response XML from the Xhr object
- * Will only return correct result when called from the context of a callback.
- * @return {Document} The DOM Document representing the XML file, or null
- * if no result available.
- */
-goog.net.XhrIo.prototype.getResponseXml = function() {
- /** @preserveTry */
- try {
- return this.xhr_ ? this.xhr_.responseXML : null;
- } catch (e) {
- goog.log.fine(this.logger_, 'Can not get responseXML: ' + e.message);
- return null;
- }
-};
-
-
-/**
- * Get the response and evaluates it as JSON from the Xhr object
- * Will only return correct result when called from the context of a callback
- * @param {string=} opt_xssiPrefix Optional XSSI prefix string to use for
- * stripping of the response before parsing. This needs to be set only if
- * your backend server prepends the same prefix string to the JSON response.
- * @return {Object|undefined} JavaScript object.
- */
-goog.net.XhrIo.prototype.getResponseJson = function(opt_xssiPrefix) {
- if (!this.xhr_) {
- return undefined;
- }
-
- var responseText = this.xhr_.responseText;
- if (opt_xssiPrefix && responseText.indexOf(opt_xssiPrefix) == 0) {
- responseText = responseText.substring(opt_xssiPrefix.length);
- }
-
- return goog.json.parse(responseText);
-};
-
-
-/**
- * Get the response as the type specificed by {@link #setResponseType}. At time
- * of writing, this is only directly supported in very recent versions of WebKit
- * (10.0.612.1 dev and later). If the field is not supported directly, we will
- * try to emulate it.
- *
- * Emulating the response means following the rules laid out at
- * http://www.w3.org/TR/XMLHttpRequest/#the-response-attribute
- *
- * On browsers with no support for this (Chrome < 10, Firefox < 4, etc), only
- * response types of DEFAULT or TEXT may be used, and the response returned will
- * be the text response.
- *
- * On browsers with Mozilla's draft support for array buffers (Firefox 4, 5),
- * only response types of DEFAULT, TEXT, and ARRAY_BUFFER may be used, and the
- * response returned will be either the text response or the Mozilla
- * implementation of the array buffer response.
- *
- * On browsers will full support, any valid response type supported by the
- * browser may be used, and the response provided by the browser will be
- * returned.
- *
- * @return {*} The response.
- */
-goog.net.XhrIo.prototype.getResponse = function() {
- /** @preserveTry */
- try {
- if (!this.xhr_) {
- return null;
- }
- if ('response' in this.xhr_) {
- return this.xhr_.response;
- }
- switch (this.responseType_) {
- case goog.net.XhrIo.ResponseType.DEFAULT:
- case goog.net.XhrIo.ResponseType.TEXT:
- return this.xhr_.responseText;
- // DOCUMENT and BLOB don't need to be handled here because they are
- // introduced in the same spec that adds the .response field, and would
- // have been caught above.
- // ARRAY_BUFFER needs an implementation for Firefox 4, where it was
- // implemented using a draft spec rather than the final spec.
- case goog.net.XhrIo.ResponseType.ARRAY_BUFFER:
- if ('mozResponseArrayBuffer' in this.xhr_) {
- return this.xhr_.mozResponseArrayBuffer;
- }
- }
- // Fell through to a response type that is not supported on this browser.
- goog.log.error(this.logger_,
- 'Response type ' + this.responseType_ + ' is not ' +
- 'supported on this browser');
- return null;
- } catch (e) {
- goog.log.fine(this.logger_, 'Can not get response: ' + e.message);
- return null;
- }
-};
-
-
-/**
- * Get the value of the response-header with the given name from the Xhr object
- * Will only return correct result when called from the context of a callback
- * and the request has completed
- * @param {string} key The name of the response-header to retrieve.
- * @return {string|undefined} The value of the response-header named key.
- */
-goog.net.XhrIo.prototype.getResponseHeader = function(key) {
- return this.xhr_ && this.isComplete() ?
- this.xhr_.getResponseHeader(key) : undefined;
-};
-
-
-/**
- * Gets the text of all the headers in the response.
- * Will only return correct result when called from the context of a callback
- * and the request has completed.
- * @return {string} The value of the response headers or empty string.
- */
-goog.net.XhrIo.prototype.getAllResponseHeaders = function() {
- return this.xhr_ && this.isComplete() ?
- this.xhr_.getAllResponseHeaders() : '';
-};
-
-
-/**
- * Returns all response headers as a key-value map.
- * Multiple values for the same header key can be combined into one,
- * separated by a comma and a space.
- * Note that the native getResponseHeader method for retrieving a single header
- * does a case insensitive match on the header name. This method does not
- * include any case normalization logic, it will just return a key-value
- * representation of the headers.
- * See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
- * @return {!Object<string, string>} An object with the header keys as keys
- * and header values as values.
- */
-goog.net.XhrIo.prototype.getResponseHeaders = function() {
- var headersObject = {};
- var headersArray = this.getAllResponseHeaders().split('\r\n');
- for (var i = 0; i < headersArray.length; i++) {
- if (goog.string.isEmptyOrWhitespace(headersArray[i])) {
- continue;
- }
- var keyValue = goog.string.splitLimit(headersArray[i], ': ', 2);
- if (headersObject[keyValue[0]]) {
- headersObject[keyValue[0]] += ', ' + keyValue[1];
- } else {
- headersObject[keyValue[0]] = keyValue[1];
- }
- }
- return headersObject;
-};
-
-
-/**
- * Get the last error message
- * @return {goog.net.ErrorCode} Last error code.
- */
-goog.net.XhrIo.prototype.getLastErrorCode = function() {
- return this.lastErrorCode_;
-};
-
-
-/**
- * Get the last error message
- * @return {string} Last error message.
- */
-goog.net.XhrIo.prototype.getLastError = function() {
- return goog.isString(this.lastError_) ? this.lastError_ :
- String(this.lastError_);
-};
-
-
-/**
- * Adds the last method, status and URI to the message. This is used to add
- * this information to the logging calls.
- * @param {string} msg The message text that we want to add the extra text to.
- * @return {string} The message with the extra text appended.
- * @private
- */
-goog.net.XhrIo.prototype.formatMsg_ = function(msg) {
- return msg + ' [' + this.lastMethod_ + ' ' + this.lastUri_ + ' ' +
- this.getStatus() + ']';
-};
-
-
-// Register the xhr handler as an entry point, so that
-// it can be monitored for exception handling, etc.
-goog.debug.entryPointRegistry.register(
- /**
- * @param {function(!Function): !Function} transformer The transforming
- * function.
- */
- function(transformer) {
- goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ =
- transformer(goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);
- });
-
-goog.provide('ol.TileLoadFunctionType');
-goog.provide('ol.TileVectorLoadFunctionType');
-
-
-/**
- * A function that takes an {@link ol.Tile} for the tile and a
- * `{string}` for the url as arguments.
- *
- * @typedef {function(ol.Tile, string)}
- * @api
- */
-ol.TileLoadFunctionType;
-
-
-/**
- * A function that is called with a tile url for the features to load and
- * a callback that takes the loaded features as argument.
- *
- * @typedef {function(string, function(Array.<ol.Feature>))}
- * @api
- */
-ol.TileVectorLoadFunctionType;
-
goog.provide('ol.VectorTile');
goog.require('ol.Tile');
-goog.require('ol.TileCoord');
-goog.require('ol.TileLoadFunctionType');
goog.require('ol.TileState');
+goog.require('ol.dom');
goog.require('ol.proj.Projection');
/**
- * @typedef {{
- * dirty: boolean,
- * renderedRenderOrder: (null|function(ol.Feature, ol.Feature):number),
- * renderedRevision: number,
- * replayGroup: ol.render.IReplayGroup}}
- */
-ol.TileReplayState;
-
-
-
-/**
* @constructor
* @extends {ol.Tile}
* @param {ol.TileCoord} tileCoord Tile coordinate.
@@ -69460,15 +54394,19 @@ ol.TileReplayState;
* @param {string} src Data source url.
* @param {ol.format.Feature} format Feature format.
* @param {ol.TileLoadFunctionType} tileLoadFunction Tile load function.
- * @param {ol.proj.Projection} projection Feature projection.
*/
-ol.VectorTile =
- function(tileCoord, state, src, format, tileLoadFunction, projection) {
+ol.VectorTile = function(tileCoord, state, src, format, tileLoadFunction) {
goog.base(this, tileCoord, state);
/**
* @private
+ * @type {CanvasRenderingContext2D}
+ */
+ this.context_ = ol.dom.createCanvasContext2D();
+
+ /**
+ * @private
* @type {ol.format.Feature}
*/
this.format_ = format;
@@ -69486,10 +54424,11 @@ ol.VectorTile =
this.loader_;
/**
+ * Data projection
* @private
* @type {ol.proj.Projection}
*/
- this.projection_ = projection;
+ this.projection_;
/**
* @private
@@ -69499,7 +54438,9 @@ ol.VectorTile =
dirty: false,
renderedRenderOrder: null,
renderedRevision: -1,
- replayGroup: null
+ renderedTileRevision: -1,
+ replayGroup: null,
+ skippedFeatures: []
};
/**
@@ -69519,10 +54460,19 @@ goog.inherits(ol.VectorTile, ol.Tile);
/**
+ * @return {CanvasRenderingContext2D} The rendering context.
+ */
+ol.VectorTile.prototype.getContext = function() {
+ return this.context_;
+};
+
+
+/**
* @inheritDoc
*/
-ol.VectorTile.prototype.disposeInternal = function() {
- goog.base(this, 'disposeInternal');
+ol.VectorTile.prototype.getImage = function() {
+ return this.replayState_.renderedTileRevision == -1 ?
+ null : this.context_.canvas;
};
@@ -69545,7 +54495,7 @@ ol.VectorTile.prototype.getFeatures = function() {
/**
- * @return {ol.TileReplayState}
+ * @return {ol.TileReplayState} The replay state.
*/
ol.VectorTile.prototype.getReplayState = function() {
return this.replayState_;
@@ -69575,13 +54525,14 @@ ol.VectorTile.prototype.load = function() {
if (this.state == ol.TileState.IDLE) {
this.setState(ol.TileState.LOADING);
this.tileLoadFunction_(this, this.url_);
- this.loader_(null, NaN, this.projection_);
+ this.loader_(null, NaN, null);
}
};
/**
* @param {Array.<ol.Feature>} features Features.
+ * @api
*/
ol.VectorTile.prototype.setFeatures = function(features) {
this.features_ = features;
@@ -69590,7 +54541,9 @@ ol.VectorTile.prototype.setFeatures = function(features) {
/**
+ * Set the projection of the features that were added with {@link #setFeatures}.
* @param {ol.proj.Projection} projection Feature projection.
+ * @api
*/
ol.VectorTile.prototype.setProjection = function(projection) {
this.projection_ = projection;
@@ -69628,296 +54581,11 @@ ol.format.FormatType = {
XML: 'xml'
};
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview
- * XML utilities.
- *
- */
-
-goog.provide('goog.dom.xml');
-
-goog.require('goog.dom');
-goog.require('goog.dom.NodeType');
-goog.require('goog.userAgent');
-
-
-/**
- * Max XML size for MSXML2. Used to prevent potential DoS attacks.
- * @type {number}
- */
-goog.dom.xml.MAX_XML_SIZE_KB = 2 * 1024; // In kB
-
-
-/**
- * Max XML size for MSXML2. Used to prevent potential DoS attacks.
- * @type {number}
- */
-goog.dom.xml.MAX_ELEMENT_DEPTH = 256; // Same default as MSXML6.
-
-
-/**
- * Check for ActiveXObject support by the browser.
- * @return {boolean} true if browser has ActiveXObject support.
- * @private
- */
-goog.dom.xml.hasActiveXObjectSupport_ = function() {
- if (!goog.userAgent.IE) {
- // Avoid raising useless exception in case code is not compiled
- // and browser is not MSIE.
- return false;
- }
- try {
- // Due to lot of changes in IE 9, 10 & 11 behaviour and ActiveX being
- // totally disableable using MSIE's security level, trying to create the
- // ActiveXOjbect is a lot more reliable than testing for the existance of
- // window.ActiveXObject
- new ActiveXObject('MSXML2.DOMDocument');
- return true;
- } catch (e) {
- return false;
- }
-};
-
-
-/**
- * True if browser has ActiveXObject support.
- * Possible override if this test become wrong in coming IE versions.
- * @type {boolean}
- */
-goog.dom.xml.ACTIVEX_SUPPORT =
- goog.userAgent.IE && goog.dom.xml.hasActiveXObjectSupport_();
-
-
-/**
- * Creates an XML document appropriate for the current JS runtime
- * @param {string=} opt_rootTagName The root tag name.
- * @param {string=} opt_namespaceUri Namespace URI of the document element.
- * @param {boolean=} opt_preferActiveX Whether to default to ActiveXObject to
- * create Document in IE. Use this if you need xpath support in IE (e.g.,
- * selectSingleNode or selectNodes), but be aware that the ActiveXObject does
- * not support various DOM-specific Document methods and attributes.
- * @return {Document} The new document.
- * @throws {Error} if browser does not support creating new documents or
- * namespace is provided without a root tag name.
- */
-goog.dom.xml.createDocument = function(opt_rootTagName, opt_namespaceUri,
- opt_preferActiveX) {
- if (opt_namespaceUri && !opt_rootTagName) {
- throw Error("Can't create document with namespace and no root tag");
- }
- // If document.implementation.createDocument is available and they haven't
- // explicitly opted to use ActiveXObject when possible.
- if (document.implementation && document.implementation.createDocument &&
- !(goog.dom.xml.ACTIVEX_SUPPORT && opt_preferActiveX)) {
- return document.implementation.createDocument(opt_namespaceUri || '',
- opt_rootTagName || '', null);
- } else if (goog.dom.xml.ACTIVEX_SUPPORT) {
- var doc = goog.dom.xml.createMsXmlDocument_();
- if (doc) {
- if (opt_rootTagName) {
- doc.appendChild(doc.createNode(goog.dom.NodeType.ELEMENT,
- opt_rootTagName,
- opt_namespaceUri || ''));
- }
- return doc;
- }
- }
- throw Error('Your browser does not support creating new documents');
-};
-
-
-/**
- * Creates an XML document from a string
- * @param {string} xml The text.
- * @param {boolean=} opt_preferActiveX Whether to default to ActiveXObject to
- * create Document in IE. Use this if you need xpath support in IE (e.g.,
- * selectSingleNode or selectNodes), but be aware that the ActiveXObject does
- * not support various DOM-specific Document methods and attributes.
- * @return {Document} XML document from the text.
- * @throws {Error} if browser does not support loading XML documents.
- */
-goog.dom.xml.loadXml = function(xml, opt_preferActiveX) {
- if (typeof DOMParser != 'undefined' &&
- !(goog.dom.xml.ACTIVEX_SUPPORT && opt_preferActiveX)) {
- return new DOMParser().parseFromString(xml, 'application/xml');
- } else if (goog.dom.xml.ACTIVEX_SUPPORT) {
- var doc = goog.dom.xml.createMsXmlDocument_();
- doc.loadXML(xml);
- return doc;
- }
- throw Error('Your browser does not support loading xml documents');
-};
-
-
-/**
- * Serializes an XML document or subtree to string.
- * @param {Document|Element} xml The document or the root node of the subtree.
- * @return {string} The serialized XML.
- * @throws {Error} if browser does not support XML serialization.
- */
-goog.dom.xml.serialize = function(xml) {
- // Compatible with IE/ActiveXObject.
- var text = xml.xml;
- if (text) {
- return text;
- }
- // Compatible with Firefox, Opera and WebKit.
- if (typeof XMLSerializer != 'undefined') {
- return new XMLSerializer().serializeToString(xml);
- }
- throw Error('Your browser does not support serializing XML documents');
-};
-
-
-/**
- * Selects a single node using an Xpath expression and a root node
- * @param {Node} node The root node.
- * @param {string} path Xpath selector.
- * @return {Node} The selected node, or null if no matching node.
- */
-goog.dom.xml.selectSingleNode = function(node, path) {
- if (typeof node.selectSingleNode != 'undefined') {
- var doc = goog.dom.getOwnerDocument(node);
- if (typeof doc.setProperty != 'undefined') {
- doc.setProperty('SelectionLanguage', 'XPath');
- }
- return node.selectSingleNode(path);
- } else if (document.implementation.hasFeature('XPath', '3.0')) {
- var doc = goog.dom.getOwnerDocument(node);
- var resolver = doc.createNSResolver(doc.documentElement);
- var result = doc.evaluate(path, node, resolver,
- XPathResult.FIRST_ORDERED_NODE_TYPE, null);
- return result.singleNodeValue;
- }
- // This browser does not support xpath for the given node. If IE, ensure XML
- // Document was created using ActiveXObject
- // TODO(joeltine): This should throw instead of return null.
- return null;
-};
-
-
-/**
- * Selects multiple nodes using an Xpath expression and a root node
- * @param {Node} node The root node.
- * @param {string} path Xpath selector.
- * @return {(NodeList|Array<Node>)} The selected nodes, or empty array if no
- * matching nodes.
- */
-goog.dom.xml.selectNodes = function(node, path) {
- if (typeof node.selectNodes != 'undefined') {
- var doc = goog.dom.getOwnerDocument(node);
- if (typeof doc.setProperty != 'undefined') {
- doc.setProperty('SelectionLanguage', 'XPath');
- }
- return node.selectNodes(path);
- } else if (document.implementation.hasFeature('XPath', '3.0')) {
- var doc = goog.dom.getOwnerDocument(node);
- var resolver = doc.createNSResolver(doc.documentElement);
- var nodes = doc.evaluate(path, node, resolver,
- XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
- var results = [];
- var count = nodes.snapshotLength;
- for (var i = 0; i < count; i++) {
- results.push(nodes.snapshotItem(i));
- }
- return results;
- } else {
- // This browser does not support xpath for the given node. If IE, ensure XML
- // Document was created using ActiveXObject.
- // TODO(joeltine): This should throw instead of return empty array.
- return [];
- }
-};
-
-
-/**
- * Sets multiple attributes on an element. Differs from goog.dom.setProperties
- * in that it exclusively uses the element's setAttributes method. Use this
- * when you need to ensure that the exact property is available as an attribute
- * and can be read later by the native getAttribute method.
- * @param {!Element} element XML or DOM element to set attributes on.
- * @param {!Object<string, string>} attributes Map of property:value pairs.
- */
-goog.dom.xml.setAttributes = function(element, attributes) {
- for (var key in attributes) {
- if (attributes.hasOwnProperty(key)) {
- element.setAttribute(key, attributes[key]);
- }
- }
-};
-
-
-/**
- * Creates an instance of the MSXML2.DOMDocument.
- * @return {Document} The new document.
- * @private
- */
-goog.dom.xml.createMsXmlDocument_ = function() {
- var doc = new ActiveXObject('MSXML2.DOMDocument');
- if (doc) {
- // Prevent potential vulnerabilities exposed by MSXML2, see
- // http://b/1707300 and http://wiki/Main/ISETeamXMLAttacks for details.
- doc.resolveExternals = false;
- doc.validateOnParse = false;
- // Add a try catch block because accessing these properties will throw an
- // error on unsupported MSXML versions. This affects Windows machines
- // running IE6 or IE7 that are on XP SP2 or earlier without MSXML updates.
- // See http://msdn.microsoft.com/en-us/library/ms766391(VS.85).aspx for
- // specific details on which MSXML versions support these properties.
- try {
- doc.setProperty('ProhibitDTD', true);
- doc.setProperty('MaxXMLSize', goog.dom.xml.MAX_XML_SIZE_KB);
- doc.setProperty('MaxElementDepth', goog.dom.xml.MAX_ELEMENT_DEPTH);
- } catch (e) {
- // No-op.
- }
- }
- return doc;
-};
-
goog.provide('ol.xml');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
-goog.require('goog.dom.xml');
-goog.require('goog.object');
-goog.require('goog.userAgent');
-
-
-/**
- * When using {@link ol.xml.makeChildAppender} or
- * {@link ol.xml.makeSimpleNodeFactory}, the top `objectStack` item needs to
- * have this structure.
- * @typedef {{node:Node}}
- */
-ol.xml.NodeStackItem;
-
-
-/**
- * @typedef {function(Node, Array.<*>)}
- */
-ol.xml.Parser;
-
-
-/**
- * @typedef {function(Node, *, Array.<*>)}
- */
-ol.xml.Serializer;
+goog.require('ol.array');
/**
@@ -69927,45 +54595,20 @@ ol.xml.Serializer;
* @const
* @type {Document}
*/
-ol.xml.DOCUMENT = goog.dom.xml.createDocument();
+ol.xml.DOCUMENT = document.implementation.createDocument('', '', null);
/**
* @param {string} namespaceURI Namespace URI.
* @param {string} qualifiedName Qualified name.
* @return {Node} Node.
- * @private
*/
-ol.xml.createElementNS_ = function(namespaceURI, qualifiedName) {
+ol.xml.createElementNS = function(namespaceURI, qualifiedName) {
return ol.xml.DOCUMENT.createElementNS(namespaceURI, qualifiedName);
};
/**
- * @param {string} namespaceURI Namespace URI.
- * @param {string} qualifiedName Qualified name.
- * @return {Node} Node.
- * @private
- */
-ol.xml.createElementNSActiveX_ = function(namespaceURI, qualifiedName) {
- if (!namespaceURI) {
- namespaceURI = '';
- }
- return ol.xml.DOCUMENT.createNode(1, qualifiedName, namespaceURI);
-};
-
-
-/**
- * @param {string} namespaceURI Namespace URI.
- * @param {string} qualifiedName Qualified name.
- * @return {Node} Node.
- */
-ol.xml.createElementNS =
- (document.implementation && document.implementation.createDocument) ?
- ol.xml.createElementNS_ : ol.xml.createElementNSActiveX_;
-
-
-/**
* Recursively grab all text content of child nodes into a single string.
* @param {Node} node Node.
* @param {boolean} normalizeWhitespace Normalize whitespace: remove all line
@@ -69983,9 +54626,9 @@ ol.xml.getAllTextContent = function(node, normalizeWhitespace) {
* @param {Node} node Node.
* @param {boolean} normalizeWhitespace Normalize whitespace: remove all line
* breaks.
- * @param {Array.<String|string>} accumulator Accumulator.
+ * @param {Array.<string>} accumulator Accumulator.
* @private
- * @return {Array.<String|string>} Accumulator.
+ * @return {Array.<string>} Accumulator.
*/
ol.xml.getAllTextContent_ = function(node, normalizeWhitespace, accumulator) {
if (node.nodeType == goog.dom.NodeType.CDATA_SECTION ||
@@ -70007,103 +54650,30 @@ ol.xml.getAllTextContent_ = function(node, normalizeWhitespace, accumulator) {
/**
- * @param {Node} node Node.
- * @private
- * @return {string} Local name.
- */
-ol.xml.getLocalName_ = function(node) {
- return node.localName;
-};
-
-
-/**
- * @param {Node} node Node.
- * @private
- * @return {string} Local name.
- */
-ol.xml.getLocalNameIE_ = function(node) {
- var localName = node.localName;
- if (localName !== undefined) {
- return localName;
- }
- var baseName = node.baseName;
- goog.asserts.assert(baseName,
- 'Failed to get localName/baseName of node %s', node);
- return baseName;
-};
-
-
-/**
- * @param {Node} node Node.
- * @return {string} Local name.
- */
-ol.xml.getLocalName = goog.userAgent.IE ?
- ol.xml.getLocalNameIE_ : ol.xml.getLocalName_;
-
-
-/**
* @param {?} value Value.
- * @private
* @return {boolean} Is document.
*/
-ol.xml.isDocument_ = function(value) {
+ol.xml.isDocument = function(value) {
return value instanceof Document;
};
/**
* @param {?} value Value.
- * @private
- * @return {boolean} Is document.
- */
-ol.xml.isDocumentIE_ = function(value) {
- return goog.isObject(value) && value.nodeType == goog.dom.NodeType.DOCUMENT;
-};
-
-
-/**
- * @param {?} value Value.
- * @return {boolean} Is document.
- */
-ol.xml.isDocument = goog.userAgent.IE ?
- ol.xml.isDocumentIE_ : ol.xml.isDocument_;
-
-
-/**
- * @param {?} value Value.
- * @private
* @return {boolean} Is node.
*/
-ol.xml.isNode_ = function(value) {
+ol.xml.isNode = function(value) {
return value instanceof Node;
};
/**
- * @param {?} value Value.
- * @private
- * @return {boolean} Is node.
- */
-ol.xml.isNodeIE_ = function(value) {
- return goog.isObject(value) && value.nodeType !== undefined;
-};
-
-
-/**
- * @param {?} value Value.
- * @return {boolean} Is node.
- */
-ol.xml.isNode = goog.userAgent.IE ? ol.xml.isNodeIE_ : ol.xml.isNode_;
-
-
-/**
* @param {Node} node Node.
* @param {?string} namespaceURI Namespace URI.
* @param {string} name Attribute name.
* @return {string} Value
- * @private
*/
-ol.xml.getAttributeNS_ = function(node, namespaceURI, name) {
+ol.xml.getAttributeNS = function(node, namespaceURI, name) {
return node.getAttributeNS(namespaceURI, name) || '';
};
@@ -70112,121 +54682,14 @@ ol.xml.getAttributeNS_ = function(node, namespaceURI, name) {
* @param {Node} node Node.
* @param {?string} namespaceURI Namespace URI.
* @param {string} name Attribute name.
- * @return {string} Value
- * @private
- */
-ol.xml.getAttributeNSActiveX_ = function(node, namespaceURI, name) {
- var attributeValue = '';
- var attributeNode = ol.xml.getAttributeNodeNS(node, namespaceURI, name);
- if (attributeNode !== undefined) {
- attributeValue = attributeNode.nodeValue;
- }
- return attributeValue;
-};
-
-
-/**
- * @param {Node} node Node.
- * @param {?string} namespaceURI Namespace URI.
- * @param {string} name Attribute name.
- * @return {string} Value
- */
-ol.xml.getAttributeNS =
- (document.implementation && document.implementation.createDocument) ?
- ol.xml.getAttributeNS_ : ol.xml.getAttributeNSActiveX_;
-
-
-/**
- * @param {Node} node Node.
- * @param {?string} namespaceURI Namespace URI.
- * @param {string} name Attribute name.
- * @return {?Node} Attribute node or null if none found.
- * @private
- */
-ol.xml.getAttributeNodeNS_ = function(node, namespaceURI, name) {
- return node.getAttributeNodeNS(namespaceURI, name);
-};
-
-
-/**
- * @param {Node} node Node.
- * @param {?string} namespaceURI Namespace URI.
- * @param {string} name Attribute name.
- * @return {?Node} Attribute node or null if none found.
- * @private
- */
-ol.xml.getAttributeNodeNSActiveX_ = function(node, namespaceURI, name) {
- var attributeNode = null;
- var attributes = node.attributes;
- var potentialNode, fullName;
- for (var i = 0, len = attributes.length; i < len; ++i) {
- potentialNode = attributes[i];
- if (potentialNode.namespaceURI == namespaceURI) {
- fullName = (potentialNode.prefix) ?
- (potentialNode.prefix + ':' + name) : name;
- if (fullName == potentialNode.nodeName) {
- attributeNode = potentialNode;
- break;
- }
- }
- }
- return attributeNode;
-};
-
-
-/**
- * @param {Node} node Node.
- * @param {?string} namespaceURI Namespace URI.
- * @param {string} name Attribute name.
- * @return {?Node} Attribute node or null if none found.
- */
-ol.xml.getAttributeNodeNS =
- (document.implementation && document.implementation.createDocument) ?
- ol.xml.getAttributeNodeNS_ : ol.xml.getAttributeNodeNSActiveX_;
-
-
-/**
- * @param {Node} node Node.
- * @param {?string} namespaceURI Namespace URI.
- * @param {string} name Attribute name.
* @param {string|number} value Value.
- * @private
*/
-ol.xml.setAttributeNS_ = function(node, namespaceURI, name, value) {
+ol.xml.setAttributeNS = function(node, namespaceURI, name, value) {
node.setAttributeNS(namespaceURI, name, value);
};
/**
- * @param {Node} node Node.
- * @param {?string} namespaceURI Namespace URI.
- * @param {string} name Attribute name.
- * @param {string|number} value Value.
- * @private
- */
-ol.xml.setAttributeNSActiveX_ = function(node, namespaceURI, name, value) {
- if (namespaceURI) {
- var attribute = node.ownerDocument.createNode(2, name, namespaceURI);
- attribute.nodeValue = value;
- node.setAttributeNode(attribute);
- } else {
- node.setAttribute(name, value);
- }
-};
-
-
-/**
- * @param {Node} node Node.
- * @param {?string} namespaceURI Namespace URI.
- * @param {string} name Attribute name.
- * @param {string|number} value Value.
- */
-ol.xml.setAttributeNS =
- (document.implementation && document.implementation.createDocument) ?
- ol.xml.setAttributeNS_ : ol.xml.setAttributeNSActiveX_;
-
-
-/**
* Parse an XML string to an XML Document.
* @param {string} xml XML.
* @return {Document} Document.
@@ -70243,7 +54706,7 @@ ol.xml.parse = function(xml) {
* @param {function(this: T, Node, Array.<*>): (Array.<*>|undefined)}
* valueReader Value reader.
* @param {T=} opt_this The object to use as `this` in `valueReader`.
- * @return {ol.xml.Parser} Parser.
+ * @return {ol.XmlParser} Parser.
* @template T
*/
ol.xml.makeArrayExtender = function(valueReader, opt_this) {
@@ -70255,13 +54718,13 @@ ol.xml.makeArrayExtender = function(valueReader, opt_this) {
function(node, objectStack) {
var value = valueReader.call(opt_this, node, objectStack);
if (value !== undefined) {
- goog.asserts.assert(goog.isArray(value),
+ goog.asserts.assert(Array.isArray(value),
'valueReader function is expected to return an array of values');
var array = /** @type {Array.<*>} */
(objectStack[objectStack.length - 1]);
- goog.asserts.assert(goog.isArray(array),
+ goog.asserts.assert(Array.isArray(array),
'objectStack is supposed to be an array of arrays');
- goog.array.extend(array, value);
+ ol.array.extend(array, value);
}
});
};
@@ -70272,7 +54735,7 @@ ol.xml.makeArrayExtender = function(valueReader, opt_this) {
* object stack.
* @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
* @param {T=} opt_this The object to use as `this` in `valueReader`.
- * @return {ol.xml.Parser} Parser.
+ * @return {ol.XmlParser} Parser.
* @template T
*/
ol.xml.makeArrayPusher = function(valueReader, opt_this) {
@@ -70286,7 +54749,7 @@ ol.xml.makeArrayPusher = function(valueReader, opt_this) {
node, objectStack);
if (value !== undefined) {
var array = objectStack[objectStack.length - 1];
- goog.asserts.assert(goog.isArray(array),
+ goog.asserts.assert(Array.isArray(array),
'objectStack is supposed to be an array of arrays');
array.push(value);
}
@@ -70299,7 +54762,7 @@ ol.xml.makeArrayPusher = function(valueReader, opt_this) {
* top of the stack.
* @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
* @param {T=} opt_this The object to use as `this` in `valueReader`.
- * @return {ol.xml.Parser} Parser.
+ * @return {ol.XmlParser} Parser.
* @template T
*/
ol.xml.makeReplacer = function(valueReader, opt_this) {
@@ -70324,11 +54787,10 @@ ol.xml.makeReplacer = function(valueReader, opt_this) {
* @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
* @param {string=} opt_property Property.
* @param {T=} opt_this The object to use as `this` in `valueReader`.
- * @return {ol.xml.Parser} Parser.
+ * @return {ol.XmlParser} Parser.
* @template T
*/
-ol.xml.makeObjectPropertyPusher =
- function(valueReader, opt_property, opt_this) {
+ol.xml.makeObjectPropertyPusher = function(valueReader, opt_property, opt_this) {
goog.asserts.assert(valueReader !== undefined,
'undefined valueReader, expected function(this: T, Node, Array.<*>)');
return (
@@ -70346,7 +54808,12 @@ ol.xml.makeObjectPropertyPusher =
opt_property : node.localName;
goog.asserts.assert(goog.isObject(object),
'entity from stack was not an object');
- var array = goog.object.setIfUndefined(object, property, []);
+ var array;
+ if (property in object) {
+ array = object[property];
+ } else {
+ array = object[property] = [];
+ }
array.push(value);
}
});
@@ -70358,11 +54825,10 @@ ol.xml.makeObjectPropertyPusher =
* @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
* @param {string=} opt_property Property.
* @param {T=} opt_this The object to use as `this` in `valueReader`.
- * @return {ol.xml.Parser} Parser.
+ * @return {ol.XmlParser} Parser.
* @template T
*/
-ol.xml.makeObjectPropertySetter =
- function(valueReader, opt_property, opt_this) {
+ol.xml.makeObjectPropertySetter = function(valueReader, opt_property, opt_this) {
goog.asserts.assert(valueReader !== undefined,
'undefined valueReader, expected function(this: T, Node, Array.<*>)');
return (
@@ -70389,11 +54855,11 @@ ol.xml.makeObjectPropertySetter =
/**
* Create a serializer that appends nodes written by its `nodeWriter` to its
* designated parent. The parent is the `node` of the
- * {@link ol.xml.NodeStackItem} at the top of the `objectStack`.
+ * {@link ol.XmlNodeStackItem} at the top of the `objectStack`.
* @param {function(this: T, Node, V, Array.<*>)}
* nodeWriter Node writer.
* @param {T=} opt_this The object to use as `this` in `nodeWriter`.
- * @return {ol.xml.Serializer} Serializer.
+ * @return {ol.XmlSerializer} Serializer.
* @template T, V
*/
ol.xml.makeChildAppender = function(nodeWriter, opt_this) {
@@ -70422,7 +54888,7 @@ ol.xml.makeChildAppender = function(nodeWriter, opt_this) {
* @param {function(this: T, Node, V, Array.<*>)}
* nodeWriter Node writer.
* @param {T=} opt_this The object to use as `this` in `nodeWriter`.
- * @return {ol.xml.Serializer} Serializer.
+ * @return {ol.XmlSerializer} Serializer.
* @template T, V
*/
ol.xml.makeArraySerializer = function(nodeWriter, opt_this) {
@@ -70539,7 +55005,7 @@ ol.xml.makeStructureNS = function(namespaceURIs, structure, opt_structureNS) {
/**
* Parse a node using the parsers and object stack.
- * @param {Object.<string, Object.<string, ol.xml.Parser>>} parsersNS
+ * @param {Object.<string, Object.<string, ol.XmlParser>>} parsersNS
* Parsers by namespace.
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
@@ -70562,7 +55028,7 @@ ol.xml.parseNode = function(parsersNS, node, objectStack, opt_this) {
/**
* Push an object on top of the stack, parse and return the popped object.
* @param {T} object Object.
- * @param {Object.<string, Object.<string, ol.xml.Parser>>} parsersNS
+ * @param {Object.<string, Object.<string, ol.XmlParser>>} parsersNS
* Parsers by namespace.
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
@@ -70580,7 +55046,7 @@ ol.xml.pushParseAndPop = function(
/**
* Walk through an array of `values` and call a serializer for each value.
- * @param {Object.<string, Object.<string, ol.xml.Serializer>>} serializersNS
+ * @param {Object.<string, Object.<string, ol.XmlSerializer>>} serializersNS
* Namespaced serializers.
* @param {function(this: T, *, Array.<*>, (string|undefined)): (Node|undefined)} nodeFactory
* Node factory. The `nodeFactory` creates the node whose namespace and name
@@ -70620,7 +55086,7 @@ ol.xml.serialize = function(
/**
* @param {O} object Object.
- * @param {Object.<string, Object.<string, ol.xml.Serializer>>} serializersNS
+ * @param {Object.<string, Object.<string, ol.XmlSerializer>>} serializersNS
* Namespaced serializers.
* @param {function(this: T, *, Array.<*>, (string|undefined)): (Node|undefined)} nodeFactory
* Node factory. The `nodeFactory` creates the node whose namespace and name
@@ -70649,57 +55115,18 @@ ol.xml.pushSerializeAndPop = function(object,
return objectStack.pop();
};
-goog.provide('ol.FeatureLoader');
-goog.provide('ol.FeatureUrlFunction');
goog.provide('ol.featureloader');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.net.EventType');
-goog.require('goog.net.XhrIo');
-goog.require('goog.net.XhrIo.ResponseType');
goog.require('ol.TileState');
goog.require('ol.VectorTile');
goog.require('ol.format.FormatType');
goog.require('ol.proj');
goog.require('ol.proj.Projection');
-goog.require('ol.proj.Units');
goog.require('ol.xml');
/**
- * {@link ol.source.Vector} sources use a function of this type to load
- * features.
- *
- * This function takes an {@link ol.Extent} representing the area to be loaded,
- * a `{number}` representing the resolution (map units per pixel) and an
- * {@link ol.proj.Projection} for the projection as arguments. `this` within
- * the function is bound to the {@link ol.source.Vector} it's called from.
- *
- * The function is responsible for loading the features and adding them to the
- * source.
- * @api
- * @typedef {function(this:ol.source.Vector, ol.Extent, number,
- * ol.proj.Projection)}
- */
-ol.FeatureLoader;
-
-
-/**
- * {@link ol.source.Vector} sources use a function of this type to get the url
- * to load features from.
- *
- * This function takes an {@link ol.Extent} representing the area to be loaded,
- * a `{number}` representing the resolution (map units per pixel) and an
- * {@link ol.proj.Projection} for the projection as arguments and returns a
- * `{string}` representing the URL.
- * @api
- * @typedef {function(ol.Extent, number, ol.proj.Projection) : string}
- */
-ol.FeatureUrlFunction;
-
-
-/**
* @param {string|ol.FeatureUrlFunction} url Feature URL service.
* @param {ol.format.Feature} format Feature format.
* @param {function(this:ol.VectorTile, Array.<ol.Feature>, ol.proj.Projection)|function(this:ol.source.Vector, Array.<ol.Feature>)} success
@@ -70719,68 +55146,47 @@ ol.featureloader.loadFeaturesXhr = function(url, format, success, failure) {
* @this {ol.source.Vector|ol.VectorTile}
*/
function(extent, resolution, projection) {
- var xhrIo = new goog.net.XhrIo();
- xhrIo.setResponseType(
- format.getType() == ol.format.FormatType.ARRAY_BUFFER ?
- goog.net.XhrIo.ResponseType.ARRAY_BUFFER :
- goog.net.XhrIo.ResponseType.TEXT);
- goog.events.listen(xhrIo, goog.net.EventType.COMPLETE,
- /**
- * @param {Event} event Event.
- * @private
- * @this {ol.source.Vector}
- */
- function(event) {
- var xhrIo = event.target;
- goog.asserts.assertInstanceof(xhrIo, goog.net.XhrIo,
- 'event.target/xhrIo is an instance of goog.net.XhrIo');
- if (xhrIo.isSuccess()) {
- var type = format.getType();
- /** @type {Document|Node|Object|string|undefined} */
- var source;
- if (type == ol.format.FormatType.JSON) {
- source = xhrIo.getResponseText();
- } else if (type == ol.format.FormatType.TEXT) {
- source = xhrIo.getResponseText();
- } else if (type == ol.format.FormatType.XML) {
- if (!goog.userAgent.IE) {
- source = xhrIo.getResponseXml();
- }
- if (!source) {
- source = ol.xml.parse(xhrIo.getResponseText());
- }
- } else if (type == ol.format.FormatType.ARRAY_BUFFER) {
- source = xhrIo.getResponse();
- } else {
- goog.asserts.fail('unexpected format type');
- }
- if (source) {
- if (ol.ENABLE_VECTOR_TILE && this instanceof ol.VectorTile) {
- var dataUnits = format.readProjection(source).getUnits();
- if (dataUnits === ol.proj.Units.TILE_PIXELS) {
- projection = new ol.proj.Projection({
- code: this.getProjection().getCode(),
- units: dataUnits
- });
- this.setProjection(projection);
- }
- }
- success.call(this, format.readFeatures(source,
- {featureProjection: projection}));
- } else {
- goog.asserts.fail('undefined or null source');
- }
- } else {
- failure.call(this);
- }
- goog.dispose(xhrIo);
- }, false, this);
- if (goog.isFunction(url)) {
- xhrIo.send(url(extent, resolution, projection));
- } else {
- xhrIo.send(url);
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET',
+ goog.isFunction(url) ? url(extent, resolution, projection) : url,
+ true);
+ if (format.getType() == ol.format.FormatType.ARRAY_BUFFER) {
+ xhr.responseType = 'arraybuffer';
}
-
+ /**
+ * @param {Event} event Event.
+ * @private
+ */
+ xhr.onload = function(event) {
+ if (xhr.status >= 200 && xhr.status < 300) {
+ var type = format.getType();
+ /** @type {Document|Node|Object|string|undefined} */
+ var source;
+ if (type == ol.format.FormatType.JSON ||
+ type == ol.format.FormatType.TEXT) {
+ source = xhr.responseText;
+ } else if (type == ol.format.FormatType.XML) {
+ source = xhr.responseXML;
+ if (!source) {
+ source = ol.xml.parse(xhr.responseText);
+ }
+ } else if (type == ol.format.FormatType.ARRAY_BUFFER) {
+ source = /** @type {ArrayBuffer} */ (xhr.response);
+ } else {
+ goog.asserts.fail('unexpected format type');
+ }
+ if (source) {
+ success.call(this, format.readFeatures(source,
+ {featureProjection: projection}),
+ format.readProjection(source));
+ } else {
+ goog.asserts.fail('undefined or null source');
+ }
+ } else {
+ failure.call(this);
+ }
+ }.bind(this);
+ xhr.send();
});
};
@@ -70798,9 +55204,11 @@ ol.featureloader.tile = function(url, format) {
return ol.featureloader.loadFeaturesXhr(url, format,
/**
* @param {Array.<ol.Feature>} features The loaded features.
+ * @param {ol.proj.Projection} dataProjection Data projection.
* @this {ol.VectorTile}
*/
- function(features) {
+ function(features, dataProjection) {
+ this.setProjection(dataProjection);
this.setFeatures(features);
},
/**
@@ -70825,25 +55233,16 @@ ol.featureloader.xhr = function(url, format) {
return ol.featureloader.loadFeaturesXhr(url, format,
/**
* @param {Array.<ol.Feature>} features The loaded features.
+ * @param {ol.proj.Projection} dataProjection Data projection.
* @this {ol.source.Vector}
*/
- function(features) {
+ function(features, dataProjection) {
this.addFeatures(features);
}, /* FIXME handle error */ ol.nullFunction);
};
-goog.provide('ol.LoadingStrategy');
goog.provide('ol.loadingstrategy');
-goog.require('ol.TileCoord');
-
-
-/**
- * @typedef {function(ol.Extent, number): Array.<ol.Extent>}
- * @api
- */
-ol.LoadingStrategy;
-
/**
* Strategy function for loading all features with a single request.
@@ -70918,11 +55317,10 @@ var define;
https://github.com/mourner/rbush
*/
-(function () { 'use strict';
+(function () {
+'use strict';
function rbush(maxEntries, format) {
-
- // jshint newcap: false, validthis: true
if (!(this instanceof rbush)) return new rbush(maxEntries, format);
// max entries in a node is 9 by default; min node fill is 40% for best performance
@@ -71147,12 +55545,11 @@ rbush.prototype = {
M = Math.ceil(N / Math.pow(M, height - 1));
}
- // TODO eliminate recursion?
-
node = {
children: [],
height: height,
- bbox: null
+ bbox: null,
+ leaf: false
};
// split the items into M mostly square tiles
@@ -71214,7 +55611,7 @@ rbush.prototype = {
}
}
- node = targetNode;
+ node = targetNode || node.children[0];
}
return node;
@@ -71258,7 +55655,9 @@ rbush.prototype = {
var newNode = {
children: node.children.splice(splitIndex, node.children.length - splitIndex),
- height: node.height
+ height: node.height,
+ bbox: null,
+ leaf: false
};
if (node.leaf) newNode.leaf = true;
@@ -71274,7 +55673,9 @@ rbush.prototype = {
// split root node
this.data = {
children: [node, newNode],
- height: node.height + 1
+ height: node.height + 1,
+ bbox: null,
+ leaf: false
};
calcBBox(this.data, this.toBBox);
},
@@ -71378,8 +55779,6 @@ rbush.prototype = {
// because the algorithms are very sensitive to sorting functions performance,
// so they should be dead simple and without inner calls
- // jshint evil: true
-
var compareArr = ['return a', ' - b', ';'];
this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
@@ -71523,7 +55922,7 @@ function swap(arr, i, j) {
// export as AMD/CommonJS module or global variable
-if (typeof define === 'function' && define.amd) define('rbush', function() { return rbush; });
+if (typeof define === 'function' && define.amd) define('rbush', function () { return rbush; });
else if (typeof module !== 'undefined') module.exports = rbush;
else if (typeof self !== 'undefined') self.rbush = rbush;
else window.rbush = rbush;
@@ -71536,10 +55935,9 @@ ol.ext.rbush = module.exports;
goog.provide('ol.structs.RBush');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('ol.ext.rbush');
goog.require('ol.extent');
-
+goog.require('ol.object');
/**
@@ -71732,8 +56130,7 @@ ol.structs.RBush.prototype.forEach = function(callback, opt_this) {
* @return {*} Callback return value.
* @template S
*/
-ol.structs.RBush.prototype.forEachInExtent =
- function(extent, callback, opt_this) {
+ol.structs.RBush.prototype.forEachInExtent = function(extent, callback, opt_this) {
if (goog.DEBUG) {
++this.readers_;
try {
@@ -71771,7 +56168,7 @@ ol.structs.RBush.prototype.forEach_ = function(values, callback, opt_this) {
* @return {boolean} Is empty.
*/
ol.structs.RBush.prototype.isEmpty = function() {
- return goog.object.isEmpty(this.items_);
+ return ol.object.isEmpty(this.items_);
};
@@ -71800,23 +56197,20 @@ goog.provide('ol.source.Vector');
goog.provide('ol.source.VectorEvent');
goog.provide('ol.source.VectorEventType');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('ol');
goog.require('ol.Collection');
goog.require('ol.CollectionEventType');
-goog.require('ol.Extent');
goog.require('ol.Feature');
-goog.require('ol.FeatureLoader');
-goog.require('ol.LoadingStrategy');
goog.require('ol.ObjectEventType');
+goog.require('ol.array');
+goog.require('ol.events');
+goog.require('ol.events.Event');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
goog.require('ol.featureloader');
goog.require('ol.loadingstrategy');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.source.Source');
goog.require('ol.source.State');
@@ -71858,7 +56252,6 @@ ol.source.VectorEventType = {
};
-
/**
* @classdesc
* Provides a source of features for vector layers. Vector features provided
@@ -71889,13 +56282,25 @@ ol.source.Vector = function(opt_options) {
*/
this.loader_ = ol.nullFunction;
+ /**
+ * @private
+ * @type {ol.format.Feature|undefined}
+ */
+ this.format_ = options.format;
+
+ /**
+ * @private
+ * @type {string|ol.FeatureUrlFunction|undefined}
+ */
+ this.url_ = options.url;
+
if (options.loader !== undefined) {
this.loader_ = options.loader;
- } else if (options.url !== undefined) {
- goog.asserts.assert(options.format !== undefined,
+ } else if (this.url_ !== undefined) {
+ goog.asserts.assert(this.format_ !== undefined,
'format must be set when url is set');
// create a XHR feature loader for "url" and "format"
- this.loader_ = ol.featureloader.xhr(options.url, options.format);
+ this.loader_ = ol.featureloader.xhr(this.url_, this.format_);
}
/**
@@ -71942,7 +56347,7 @@ ol.source.Vector = function(opt_options) {
/**
* @private
- * @type {Object.<string, Array.<goog.events.Key>>}
+ * @type {Object.<string, Array.<ol.events.Key>>}
*/
this.featureChangeKeys_ = {};
@@ -71956,7 +56361,7 @@ ol.source.Vector = function(opt_options) {
if (options.features instanceof ol.Collection) {
collection = options.features;
features = collection.getArray();
- } else if (goog.isArray(options.features)) {
+ } else if (Array.isArray(options.features)) {
features = options.features;
}
if (!useSpatialIndex && collection === undefined) {
@@ -72016,29 +56421,27 @@ ol.source.Vector.prototype.addFeatureInternal = function(feature) {
/**
- * @param {string} featureKey
- * @param {ol.Feature} feature
+ * @param {string} featureKey Unique identifier for the feature.
+ * @param {ol.Feature} feature The feature.
* @private
*/
ol.source.Vector.prototype.setupChangeEvents_ = function(featureKey, feature) {
goog.asserts.assert(!(featureKey in this.featureChangeKeys_),
'key (%s) not yet registered in featureChangeKey', featureKey);
this.featureChangeKeys_[featureKey] = [
- goog.events.listen(feature,
- goog.events.EventType.CHANGE,
- this.handleFeatureChange_, false, this),
- goog.events.listen(feature,
- ol.ObjectEventType.PROPERTYCHANGE,
- this.handleFeatureChange_, false, this)
+ ol.events.listen(feature, ol.events.EventType.CHANGE,
+ this.handleFeatureChange_, this),
+ ol.events.listen(feature, ol.ObjectEventType.PROPERTYCHANGE,
+ this.handleFeatureChange_, this)
];
};
/**
- * @param {string} featureKey
- * @param {ol.Feature} feature
- * @return {boolean} `true` if the feature is "valid", in the sense that it is
- * also a candidate for insertion into the Rtree, otherwise `false`.
+ * @param {string} featureKey Unique identifier for the feature.
+ * @param {ol.Feature} feature The feature.
+ * @return {boolean} The feature is "valid", in the sense that it is also a
+ * candidate for insertion into the Rtree.
* @private
*/
ol.source.Vector.prototype.addToIndex_ = function(featureKey, feature) {
@@ -72123,7 +56526,7 @@ ol.source.Vector.prototype.bindFeaturesCollection_ = function(collection) {
goog.asserts.assert(!this.featuresCollection_,
'bindFeaturesCollection can only be called once');
var modifyingCollection = false;
- goog.events.listen(this, ol.source.VectorEventType.ADDFEATURE,
+ ol.events.listen(this, ol.source.VectorEventType.ADDFEATURE,
function(evt) {
if (!modifyingCollection) {
modifyingCollection = true;
@@ -72131,7 +56534,7 @@ ol.source.Vector.prototype.bindFeaturesCollection_ = function(collection) {
modifyingCollection = false;
}
});
- goog.events.listen(this, ol.source.VectorEventType.REMOVEFEATURE,
+ ol.events.listen(this, ol.source.VectorEventType.REMOVEFEATURE,
function(evt) {
if (!modifyingCollection) {
modifyingCollection = true;
@@ -72139,7 +56542,7 @@ ol.source.Vector.prototype.bindFeaturesCollection_ = function(collection) {
modifyingCollection = false;
}
});
- goog.events.listen(collection, ol.CollectionEventType.ADD,
+ ol.events.listen(collection, ol.CollectionEventType.ADD,
function(evt) {
if (!modifyingCollection) {
var feature = evt.element;
@@ -72148,8 +56551,8 @@ ol.source.Vector.prototype.bindFeaturesCollection_ = function(collection) {
this.addFeature(feature);
modifyingCollection = false;
}
- }, false, this);
- goog.events.listen(collection, ol.CollectionEventType.REMOVE,
+ }, this);
+ ol.events.listen(collection, ol.CollectionEventType.REMOVE,
function(evt) {
if (!modifyingCollection) {
var feature = evt.element;
@@ -72158,7 +56561,7 @@ ol.source.Vector.prototype.bindFeaturesCollection_ = function(collection) {
this.removeFeature(feature);
modifyingCollection = false;
}
- }, false, this);
+ }, this);
this.featuresCollection_ = collection;
};
@@ -72172,7 +56575,7 @@ ol.source.Vector.prototype.clear = function(opt_fast) {
if (opt_fast) {
for (var featureId in this.featureChangeKeys_) {
var keys = this.featureChangeKeys_[featureId];
- keys.forEach(goog.events.unlistenByKey);
+ keys.forEach(ol.events.unlistenByKey);
}
if (!this.featuresCollection_) {
this.featureChangeKeys_ = {};
@@ -72180,20 +56583,21 @@ ol.source.Vector.prototype.clear = function(opt_fast) {
this.undefIdIndex_ = {};
}
} else {
- var rmFeatureInternal = this.removeFeatureInternal;
if (this.featuresRtree_) {
- this.featuresRtree_.forEach(rmFeatureInternal, this);
- goog.object.forEach(this.nullGeometryFeatures_, rmFeatureInternal, this);
+ this.featuresRtree_.forEach(this.removeFeatureInternal, this);
+ for (var id in this.nullGeometryFeatures_) {
+ this.removeFeatureInternal(this.nullGeometryFeatures_[id]);
+ }
}
}
if (this.featuresCollection_) {
this.featuresCollection_.clear();
}
- goog.asserts.assert(goog.object.isEmpty(this.featureChangeKeys_),
+ goog.asserts.assert(ol.object.isEmpty(this.featureChangeKeys_),
'featureChangeKeys is an empty object now');
- goog.asserts.assert(goog.object.isEmpty(this.idIndex_),
+ goog.asserts.assert(ol.object.isEmpty(this.idIndex_),
'idIndex is an empty object now');
- goog.asserts.assert(goog.object.isEmpty(this.undefIdIndex_),
+ goog.asserts.assert(ol.object.isEmpty(this.undefIdIndex_),
'undefIdIndex is an empty object now');
if (this.featuresRtree_) {
@@ -72242,8 +56646,7 @@ ol.source.Vector.prototype.forEachFeature = function(callback, opt_this) {
* @return {S|undefined} The return value from the last call to the callback.
* @template T,S
*/
-ol.source.Vector.prototype.forEachFeatureAtCoordinateDirect =
- function(coordinate, callback, opt_this) {
+ol.source.Vector.prototype.forEachFeatureAtCoordinateDirect = function(coordinate, callback, opt_this) {
var extent = [coordinate[0], coordinate[1], coordinate[0], coordinate[1]];
return this.forEachFeatureInExtent(extent, function(feature) {
var geometry = feature.getGeometry();
@@ -72278,8 +56681,7 @@ ol.source.Vector.prototype.forEachFeatureAtCoordinateDirect =
* @template T,S
* @api
*/
-ol.source.Vector.prototype.forEachFeatureInExtent =
- function(extent, callback, opt_this) {
+ol.source.Vector.prototype.forEachFeatureInExtent = function(extent, callback, opt_this) {
if (this.featuresRtree_) {
return this.featuresRtree_.forEachInExtent(extent, callback, opt_this);
} else if (this.featuresCollection_) {
@@ -72305,12 +56707,11 @@ ol.source.Vector.prototype.forEachFeatureInExtent =
* @template T,S
* @api
*/
-ol.source.Vector.prototype.forEachFeatureIntersectingExtent =
- function(extent, callback, opt_this) {
+ol.source.Vector.prototype.forEachFeatureIntersectingExtent = function(extent, callback, opt_this) {
return this.forEachFeatureInExtent(extent,
/**
* @param {ol.Feature} feature Feature.
- * @return {S|undefined}
+ * @return {S|undefined} The return value from the last call to the callback.
* @template S
*/
function(feature) {
@@ -72331,7 +56732,7 @@ ol.source.Vector.prototype.forEachFeatureIntersectingExtent =
* Get the features collection associated with this source. Will be `null`
* unless the source was configured with `useSpatialIndex` set to `false`, or
* with an {@link ol.Collection} as `features`.
- * @return {ol.Collection.<ol.Feature>}
+ * @return {ol.Collection.<ol.Feature>} The collection of features.
* @api
*/
ol.source.Vector.prototype.getFeaturesCollection = function() {
@@ -72350,9 +56751,9 @@ ol.source.Vector.prototype.getFeatures = function() {
features = this.featuresCollection_.getArray();
} else if (this.featuresRtree_) {
features = this.featuresRtree_.getAll();
- if (!goog.object.isEmpty(this.nullGeometryFeatures_)) {
- goog.array.extend(
- features, goog.object.getValues(this.nullGeometryFeatures_));
+ if (!ol.object.isEmpty(this.nullGeometryFeatures_)) {
+ ol.array.extend(
+ features, ol.object.getValues(this.nullGeometryFeatures_));
}
}
goog.asserts.assert(features !== undefined,
@@ -72400,11 +56801,13 @@ ol.source.Vector.prototype.getFeaturesInExtent = function(extent) {
* This method is not available when the source is configured with
* `useSpatialIndex` set to `false`.
* @param {ol.Coordinate} coordinate Coordinate.
+ * @param {function(ol.Feature):boolean=} opt_filter Feature filter function.
+ * The filter function will receive one argument, the {@link ol.Feature feature}
+ * and it should return a boolean value. By default, no filtering is made.
* @return {ol.Feature} Closest feature.
* @api stable
*/
-ol.source.Vector.prototype.getClosestFeatureToCoordinate =
- function(coordinate) {
+ol.source.Vector.prototype.getClosestFeatureToCoordinate = function(coordinate, opt_filter) {
// Find the closest feature using branch and bound. We start searching an
// infinite extent, and find the distance from the first feature found. This
// becomes the closest feature. We then compute a smaller extent which any
@@ -72421,28 +56824,31 @@ ol.source.Vector.prototype.getClosestFeatureToCoordinate =
goog.asserts.assert(this.featuresRtree_,
'getClosestFeatureToCoordinate does not work with useSpatialIndex set ' +
'to false');
+ var filter = opt_filter ? opt_filter : ol.functions.TRUE;
this.featuresRtree_.forEachInExtent(extent,
/**
* @param {ol.Feature} feature Feature.
*/
function(feature) {
- var geometry = feature.getGeometry();
- goog.asserts.assert(geometry,
- 'feature geometry is defined and not null');
- var previousMinSquaredDistance = minSquaredDistance;
- minSquaredDistance = geometry.closestPointXY(
- x, y, closestPoint, minSquaredDistance);
- if (minSquaredDistance < previousMinSquaredDistance) {
- closestFeature = feature;
- // This is sneaky. Reduce the extent that it is currently being
- // searched while the R-Tree traversal using this same extent object
- // is still in progress. This is safe because the new extent is
- // strictly contained by the old extent.
- var minDistance = Math.sqrt(minSquaredDistance);
- extent[0] = x - minDistance;
- extent[1] = y - minDistance;
- extent[2] = x + minDistance;
- extent[3] = y + minDistance;
+ if (filter(feature)) {
+ var geometry = feature.getGeometry();
+ goog.asserts.assert(geometry,
+ 'feature geometry is defined and not null');
+ var previousMinSquaredDistance = minSquaredDistance;
+ minSquaredDistance = geometry.closestPointXY(
+ x, y, closestPoint, minSquaredDistance);
+ if (minSquaredDistance < previousMinSquaredDistance) {
+ closestFeature = feature;
+ // This is sneaky. Reduce the extent that it is currently being
+ // searched while the R-Tree traversal using this same extent object
+ // is still in progress. This is safe because the new extent is
+ // strictly contained by the old extent.
+ var minDistance = Math.sqrt(minSquaredDistance);
+ extent[0] = x - minDistance;
+ extent[1] = y - minDistance;
+ extent[2] = x + minDistance;
+ extent[3] = y + minDistance;
+ }
}
});
return closestFeature;
@@ -72480,7 +56886,29 @@ ol.source.Vector.prototype.getFeatureById = function(id) {
/**
- * @param {goog.events.Event} event Event.
+ * Get the format associated with this source.
+ *
+ * @return {ol.format.Feature|undefined} The feature format.
+ * @api
+ */
+ol.source.Vector.prototype.getFormat = function() {
+ return this.format_;
+};
+
+
+/**
+ * Get the url associated with this source.
+ *
+ * @return {string|ol.FeatureUrlFunction|undefined} The url.
+ * @api
+ */
+ol.source.Vector.prototype.getUrl = function() {
+ return this.url_;
+};
+
+
+/**
+ * @param {ol.events.Event} event Event.
* @private
*/
ol.source.Vector.prototype.handleFeatureChange_ = function(event) {
@@ -72544,7 +56972,7 @@ ol.source.Vector.prototype.handleFeatureChange_ = function(event) {
*/
ol.source.Vector.prototype.isEmpty = function() {
return this.featuresRtree_.isEmpty() &&
- goog.object.isEmpty(this.nullGeometryFeatures_);
+ ol.object.isEmpty(this.nullGeometryFeatures_);
};
@@ -72606,7 +57034,7 @@ ol.source.Vector.prototype.removeFeatureInternal = function(feature) {
var featureKey = goog.getUid(feature).toString();
goog.asserts.assert(featureKey in this.featureChangeKeys_,
'featureKey exists in featureChangeKeys');
- this.featureChangeKeys_[featureKey].forEach(goog.events.unlistenByKey);
+ this.featureChangeKeys_[featureKey].forEach(ol.events.unlistenByKey);
delete this.featureChangeKeys_[featureKey];
var id = feature.getId();
if (id !== undefined) {
@@ -72639,14 +57067,13 @@ ol.source.Vector.prototype.removeFromIdIndex_ = function(feature) {
};
-
/**
* @classdesc
* Events emitted by {@link ol.source.Vector} instances are instances of this
* type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.source.VectorEvent}
* @param {string} type Type.
* @param {ol.Feature=} opt_feature Feature.
@@ -72663,13 +57090,13 @@ ol.source.VectorEvent = function(type, opt_feature) {
this.feature = opt_feature;
};
-goog.inherits(ol.source.VectorEvent, goog.events.Event);
+goog.inherits(ol.source.VectorEvent, ol.events.Event);
goog.provide('ol.source.ImageVector');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('goog.vec.Mat4');
goog.require('ol.dom');
goog.require('ol.extent');
@@ -72681,7 +57108,6 @@ goog.require('ol.style.Style');
goog.require('ol.vec.Mat4');
-
/**
* @classdesc
* An image source whose images are canvas elements into which vector features
@@ -72733,7 +57159,7 @@ ol.source.ImageVector = function(options) {
goog.base(this, {
attributions: options.attributions,
- canvasFunction: goog.bind(this.canvasFunctionInternal_, this),
+ canvasFunction: this.canvasFunctionInternal_.bind(this),
logo: options.logo,
projection: options.projection,
ratio: options.ratio,
@@ -72757,8 +57183,8 @@ ol.source.ImageVector = function(options) {
this.setStyle(options.style);
- goog.events.listen(this.source_, goog.events.EventType.CHANGE,
- this.handleSourceChange_, undefined, this);
+ ol.events.listen(this.source_, ol.events.EventType.CHANGE,
+ this.handleSourceChange_, this);
};
goog.inherits(ol.source.ImageVector, ol.source.ImageCanvas);
@@ -72773,8 +57199,7 @@ goog.inherits(ol.source.ImageVector, ol.source.ImageCanvas);
* @return {HTMLCanvasElement} Canvas element.
* @private
*/
-ol.source.ImageVector.prototype.canvasFunctionInternal_ =
- function(extent, resolution, pixelRatio, size, projection) {
+ol.source.ImageVector.prototype.canvasFunctionInternal_ = function(extent, resolution, pixelRatio, size, projection) {
var replayGroup = new ol.render.canvas.ReplayGroup(
ol.renderer.vector.getTolerance(resolution, pixelRatio), extent,
@@ -72884,8 +57309,7 @@ ol.source.ImageVector.prototype.getStyleFunction = function() {
* @return {!goog.vec.Mat4.Number} Transform.
* @private
*/
-ol.source.ImageVector.prototype.getTransform_ =
- function(center, resolution, pixelRatio, size) {
+ol.source.ImageVector.prototype.getTransform_ = function(center, resolution, pixelRatio, size) {
return ol.vec.Mat4.makeTransform2D(this.transform_,
size[0] / 2, size[1] / 2,
pixelRatio / resolution, -pixelRatio / resolution,
@@ -72896,11 +57320,10 @@ ol.source.ImageVector.prototype.getTransform_ =
/**
* Handle changes in image style state.
- * @param {goog.events.Event} event Image style change event.
+ * @param {ol.events.Event} event Image style change event.
* @private
*/
-ol.source.ImageVector.prototype.handleImageChange_ =
- function(event) {
+ol.source.ImageVector.prototype.handleImageChange_ = function(event) {
this.changed();
};
@@ -72923,8 +57346,7 @@ ol.source.ImageVector.prototype.handleSourceChange_ = function() {
* @return {boolean} `true` if an image is loading.
* @private
*/
-ol.source.ImageVector.prototype.renderFeature_ =
- function(feature, resolution, pixelRatio, replayGroup) {
+ol.source.ImageVector.prototype.renderFeature_ = function(feature, resolution, pixelRatio, replayGroup) {
var styles;
var styleFunction = feature.getStyleFunction();
if (styleFunction) {
@@ -72936,6 +57358,9 @@ ol.source.ImageVector.prototype.renderFeature_ =
return false;
}
var i, ii, loading = false;
+ if (!Array.isArray(styles)) {
+ styles = [styles];
+ }
for (i = 0, ii = styles.length; i < ii; ++i) {
loading = ol.renderer.vector.renderFeature(
replayGroup, feature, styles[i],
@@ -72967,8 +57392,8 @@ ol.source.ImageVector.prototype.setStyle = function(style) {
goog.provide('ol.renderer.canvas.ImageLayer');
goog.require('goog.asserts');
-goog.require('goog.functions');
goog.require('goog.vec.Mat4');
+goog.require('ol.functions');
goog.require('ol.ImageBase');
goog.require('ol.ViewHint');
goog.require('ol.dom');
@@ -72980,7 +57405,6 @@ goog.require('ol.source.ImageVector');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.canvas.Layer}
@@ -73021,8 +57445,7 @@ goog.inherits(ol.renderer.canvas.ImageLayer, ol.renderer.canvas.Layer);
/**
* @inheritDoc
*/
-ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg) {
+ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
var layer = this.getLayer();
var source = layer.getSource();
var resolution = frameState.viewState.resolution;
@@ -73043,8 +57466,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtCoordinate =
/**
* @inheritDoc
*/
-ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel =
- function(pixel, frameState, callback, thisArg) {
+ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
if (!this.getImage()) {
return undefined;
}
@@ -73056,7 +57478,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel =
ol.vec.Mat4.multVec2(
frameState.pixelToCoordinateMatrix, coordinate, coordinate);
var hasFeature = this.forEachFeatureAtCoordinate(
- coordinate, frameState, goog.functions.TRUE, this);
+ coordinate, frameState, ol.functions.TRUE, this);
if (hasFeature) {
return callback.call(thisArg, this.getLayer());
@@ -73110,14 +57532,12 @@ ol.renderer.canvas.ImageLayer.prototype.getImageTransform = function() {
/**
* @inheritDoc
*/
-ol.renderer.canvas.ImageLayer.prototype.prepareFrame =
- function(frameState, layerState) {
+ol.renderer.canvas.ImageLayer.prototype.prepareFrame = function(frameState, layerState) {
var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState;
var viewCenter = viewState.center;
var viewResolution = viewState.resolution;
- var viewRotation = viewState.rotation;
var image;
var imageLayer = this.getLayer();
@@ -73165,7 +57585,7 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame =
pixelRatio * frameState.size[0] / 2,
pixelRatio * frameState.size[1] / 2,
scale, scale,
- viewRotation,
+ 0,
imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution,
imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution);
this.imageTransformInv_ = null;
@@ -73173,62 +57593,59 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame =
this.updateLogos(frameState, imageSource);
}
- return true;
+ return !!this.image_;
};
// FIXME find correct globalCompositeOperation
-// FIXME optimize :-)
goog.provide('ol.renderer.canvas.TileLayer');
goog.require('goog.asserts');
goog.require('goog.vec.Mat4');
-goog.require('ol.Size');
goog.require('ol.TileRange');
goog.require('ol.TileState');
goog.require('ol.array');
goog.require('ol.dom');
goog.require('ol.extent');
-goog.require('ol.layer.Tile');
+goog.require('ol.render.EventType');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.size');
-goog.require('ol.tilecoord');
+goog.require('ol.source.Tile');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.canvas.Layer}
- * @param {ol.layer.Tile} tileLayer Tile layer.
+ * @param {ol.layer.Tile|ol.layer.VectorTile} tileLayer Tile layer.
*/
ol.renderer.canvas.TileLayer = function(tileLayer) {
goog.base(this, tileLayer);
/**
- * @private
- * @type {HTMLCanvasElement}
+ * @protected
+ * @type {CanvasRenderingContext2D}
*/
- this.canvas_ = null;
+ this.context = ol.dom.createCanvasContext2D();
/**
- * @private
- * @type {ol.Size}
+ * @protected
+ * @type {Array.<ol.Tile|undefined>}
*/
- this.canvasSize_ = null;
+ this.renderedTiles = null;
/**
- * @private
- * @type {boolean}
+ * @protected
+ * @type {ol.Extent}
*/
- this.canvasTooBig_ = false;
+ this.tmpExtent = ol.extent.createEmpty();
/**
* @private
- * @type {CanvasRenderingContext2D}
+ * @type {ol.TileCoord}
*/
- this.context_ = null;
+ this.tmpTileCoord_ = [0, 0, 0];
/**
* @private
@@ -73237,46 +57654,10 @@ ol.renderer.canvas.TileLayer = function(tileLayer) {
this.imageTransform_ = goog.vec.Mat4.createNumber();
/**
- * @private
- * @type {?goog.vec.Mat4.Number}
- */
- this.imageTransformInv_ = null;
-
- /**
- * @private
- * @type {number}
- */
- this.renderedCanvasZ_ = NaN;
-
- /**
- * @private
- * @type {number}
- */
- this.renderedTileWidth_ = NaN;
-
- /**
- * @private
+ * @protected
* @type {number}
*/
- this.renderedTileHeight_ = NaN;
-
- /**
- * @private
- * @type {ol.TileRange}
- */
- this.renderedCanvasTileRange_ = null;
-
- /**
- * @private
- * @type {Array.<ol.Tile|undefined>}
- */
- this.renderedTiles_ = null;
-
- /**
- * @private
- * @type {ol.Size}
- */
- this.tmpSize_ = [0, 0];
+ this.zDirection = 0;
};
goog.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.Layer);
@@ -73285,105 +57666,32 @@ goog.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.Layer);
/**
* @inheritDoc
*/
-ol.renderer.canvas.TileLayer.prototype.getImage = function() {
- return this.canvas_;
-};
-
-
-/**
- * @inheritDoc
- */
-ol.renderer.canvas.TileLayer.prototype.getImageTransform = function() {
- return this.imageTransform_;
+ol.renderer.canvas.TileLayer.prototype.composeFrame = function(
+ frameState, layerState, context) {
+ var transform = this.getTransform(frameState, 0);
+ this.dispatchPreComposeEvent(context, frameState, transform);
+ this.renderTileImages(context, frameState, layerState);
+ this.dispatchPostComposeEvent(context, frameState, transform);
};
/**
* @inheritDoc
*/
-ol.renderer.canvas.TileLayer.prototype.prepareFrame =
- function(frameState, layerState) {
-
- //
- // Warning! You're entering a dangerous zone!
- //
- // The canvas tile layer renderering is highly optimized, hence
- // the complexity of this function. For best performance we try
- // to minimize the number of pixels to update on the canvas. This
- // includes:
- //
- // - Only drawing pixels that will be visible.
- // - Not re-drawing pixels/tiles that are already correct.
- // - Minimizing calls to clearRect.
- // - Never shrink the canvas. Just make it bigger when necessary.
- // Re-sizing the canvas also clears it, which further means
- // re-creating it (expensive).
- //
- // The various steps performed by this functions:
- //
- // - Create a canvas element if none has been created yet.
- //
- // - Make the canvas bigger if it's too small. Note that we never shrink
- // the canvas, we just make it bigger when necessary, when rotating for
- // example. Note also that the canvas always contains a whole number
- // of tiles.
- //
- // - Invalidate the canvas tile range (renderedCanvasTileRange_ = null)
- // if (1) the canvas has been enlarged, or (2) the zoom level changes,
- // or (3) the canvas tile range doesn't contain the required tile
- // range. This canvas tile range invalidation thing is related to
- // an optimization where we attempt to redraw as few pixels as
- // possible on each prepareFrame call.
- //
- // - If the canvas tile range has been invalidated we reset
- // renderedCanvasTileRange_ and reset the renderedTiles_ array.
- // The renderedTiles_ array is the structure used to determine
- // the canvas pixels that need not be redrawn from one prepareFrame
- // call to another. It records while tile has been rendered at
- // which position in the canvas.
- //
- // - We then determine the tiles to draw on the canvas. Tiles for
- // the target resolution may not be loaded yet. In that case we
- // use low-resolution/interim tiles if loaded already. And, if
- // for a non-yet-loaded tile we haven't found a corresponding
- // low-resolution tile we indicate that the pixels for that
- // tile must be cleared on the canvas. Note: determining the
- // interim tiles is based on tile extents instead of tile
- // coords, this is to be able to handler irregular tile grids.
- //
- // - We're now ready to render. We start by calling clearRect
- // for the tiles that aren't loaded yet and are not fully covered
- // by a low-resolution tile (if they're loaded, we'll draw them;
- // if they're fully covered by a low-resolution tile then there's
- // no need to clear). We then render the tiles "back to front",
- // i.e. starting with the low-resolution tiles.
- //
- // - After rendering some bookkeeping is performed (updateUsedTiles,
- // etc.). manageTilePyramid is what enqueue tiles in the tile
- // queue for loading.
- //
- // - The last step involves updating the image transform matrix,
- // which will be used by the map renderer for the final
- // composition and positioning.
- //
+ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(
+ frameState, layerState) {
var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState;
var projection = viewState.projection;
var tileLayer = this.getLayer();
- goog.asserts.assertInstanceof(tileLayer, ol.layer.Tile,
- 'layer is an instance of ol.layer.Tile');
var tileSource = tileLayer.getSource();
+ goog.asserts.assertInstanceof(tileSource, ol.source.Tile,
+ 'source is an ol.source.Tile');
var tileGrid = tileSource.getTileGridForProjection(projection);
- var tileGutter = tileSource.getGutter();
- var z = tileGrid.getZForResolution(viewState.resolution);
- var tilePixelSize =
- tileSource.getTilePixelSize(z, frameState.pixelRatio, projection);
- var tilePixelRatio = tilePixelSize[0] /
- ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize_)[0];
+ var z = tileGrid.getZForResolution(viewState.resolution, this.zDirection);
var tileResolution = tileGrid.getResolution(z);
- var tilePixelResolution = tileResolution / tilePixelRatio;
var center = viewState.center;
var extent;
if (tileResolution == viewState.resolution) {
@@ -73405,87 +57713,11 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
extent, tileResolution);
- var canvasWidth = tilePixelSize[0] * tileRange.getWidth();
- var canvasHeight = tilePixelSize[1] * tileRange.getHeight();
-
- var canvas, context;
- if (!this.canvas_) {
- goog.asserts.assert(!this.canvasSize_,
- 'canvasSize is null (because canvas is null)');
- goog.asserts.assert(!this.context_,
- 'context is null (because canvas is null)');
- goog.asserts.assert(!this.renderedCanvasTileRange_,
- 'renderedCanvasTileRange is null (because canvas is null)');
- context = ol.dom.createCanvasContext2D(canvasWidth, canvasHeight);
- this.canvas_ = context.canvas;
- this.canvasSize_ = [canvasWidth, canvasHeight];
- this.context_ = context;
- this.canvasTooBig_ =
- !ol.renderer.canvas.Layer.testCanvasSize(this.canvasSize_);
- } else {
- goog.asserts.assert(this.canvasSize_,
- 'non-null canvasSize (because canvas is not null)');
- goog.asserts.assert(this.context_,
- 'non-null context (because canvas is not null)');
- canvas = this.canvas_;
- context = this.context_;
- if (this.canvasSize_[0] < canvasWidth ||
- this.canvasSize_[1] < canvasHeight ||
- this.renderedTileWidth_ !== tilePixelSize[0] ||
- this.renderedTileHeight_ !== tilePixelSize[1] ||
- (this.canvasTooBig_ && (this.canvasSize_[0] > canvasWidth ||
- this.canvasSize_[1] > canvasHeight))) {
- // Canvas is too small or tileSize has changed, resize it.
- // We never shrink the canvas, unless
- // we know that the current canvas size exceeds the maximum size
- canvas.width = canvasWidth;
- canvas.height = canvasHeight;
- this.canvasSize_ = [canvasWidth, canvasHeight];
- this.canvasTooBig_ =
- !ol.renderer.canvas.Layer.testCanvasSize(this.canvasSize_);
- this.renderedCanvasTileRange_ = null;
- } else {
- canvasWidth = this.canvasSize_[0];
- canvasHeight = this.canvasSize_[1];
- if (z != this.renderedCanvasZ_ ||
- !this.renderedCanvasTileRange_.containsTileRange(tileRange)) {
- this.renderedCanvasTileRange_ = null;
- }
- }
- }
-
- var canvasTileRange, canvasTileRangeWidth, minX, minY;
- if (!this.renderedCanvasTileRange_) {
- canvasTileRangeWidth = canvasWidth / tilePixelSize[0];
- var canvasTileRangeHeight = canvasHeight / tilePixelSize[1];
- minX = tileRange.minX -
- Math.floor((canvasTileRangeWidth - tileRange.getWidth()) / 2);
- minY = tileRange.minY -
- Math.floor((canvasTileRangeHeight - tileRange.getHeight()) / 2);
- this.renderedCanvasZ_ = z;
- this.renderedTileWidth_ = tilePixelSize[0];
- this.renderedTileHeight_ = tilePixelSize[1];
- this.renderedCanvasTileRange_ = new ol.TileRange(
- minX, minX + canvasTileRangeWidth - 1,
- minY, minY + canvasTileRangeHeight - 1);
- this.renderedTiles_ =
- new Array(canvasTileRangeWidth * canvasTileRangeHeight);
- canvasTileRange = this.renderedCanvasTileRange_;
- } else {
- canvasTileRange = this.renderedCanvasTileRange_;
- canvasTileRangeWidth = canvasTileRange.getWidth();
- }
-
- goog.asserts.assert(canvasTileRange.containsTileRange(tileRange),
- 'tileRange is contained in canvasTileRange');
-
/**
* @type {Object.<number, Object.<string, ol.Tile>>}
*/
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};
- /** @type {Array.<ol.Tile>} */
- var tilesToClear = [];
var findLoadedTiles = this.createLoadedTileFinder(
tileSource, projection, tilesToDrawByZ);
@@ -73514,15 +57746,12 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
}
goog.asserts.assert(tile);
if (drawableTile(tile)) {
- tilesToDrawByZ[z][ol.tilecoord.toString(tile.tileCoord)] = tile;
+ tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
continue;
}
fullyLoaded = tileGrid.forEachTileCoordParentTileRange(
tile.tileCoord, findLoadedTiles, null, tmpTileRange, tmpExtent);
if (!fullyLoaded) {
- // FIXME we do not need to clear the tile if it is fully covered by its
- // children
- tilesToClear.push(tile);
childTileRange = tileGrid.getTileCoordChildTileRange(
tile.tileCoord, tmpTileRange, tmpExtent);
if (childTileRange) {
@@ -73533,86 +57762,22 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
}
}
- var i, ii;
- for (i = 0, ii = tilesToClear.length; i < ii; ++i) {
- tile = tilesToClear[i];
- x = tilePixelSize[0] * (tile.tileCoord[1] - canvasTileRange.minX);
- y = tilePixelSize[1] * (canvasTileRange.maxY - tile.tileCoord[2]);
- context.clearRect(x, y, tilePixelSize[0], tilePixelSize[1]);
- }
-
/** @type {Array.<number>} */
var zs = Object.keys(tilesToDrawByZ).map(Number);
zs.sort(ol.array.numberSafeCompareFunction);
- var opaque = tileSource.getOpaque();
- var origin = ol.extent.getTopLeft(tileGrid.getTileCoordExtent(
- [z, canvasTileRange.minX, canvasTileRange.maxY],
- tmpExtent));
- var currentZ, index, scale, tileCoordKey, tileExtent, tileState, tilesToDraw;
- var ix, iy, interimTileRange, maxX, maxY;
- var height, width;
+ var renderables = [];
+ var i, ii, currentZ, tileCoordKey, tilesToDraw;
for (i = 0, ii = zs.length; i < ii; ++i) {
currentZ = zs[i];
- tilePixelSize =
- tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
tilesToDraw = tilesToDrawByZ[currentZ];
- if (currentZ == z) {
- for (tileCoordKey in tilesToDraw) {
- tile = tilesToDraw[tileCoordKey];
- index =
- (tile.tileCoord[2] - canvasTileRange.minY) * canvasTileRangeWidth +
- (tile.tileCoord[1] - canvasTileRange.minX);
- if (this.renderedTiles_[index] != tile) {
- x = tilePixelSize[0] * (tile.tileCoord[1] - canvasTileRange.minX);
- y = tilePixelSize[1] * (canvasTileRange.maxY - tile.tileCoord[2]);
- tileState = tile.getState();
- if (tileState == ol.TileState.EMPTY ||
- (tileState == ol.TileState.ERROR && !useInterimTilesOnError) ||
- !opaque) {
- context.clearRect(x, y, tilePixelSize[0], tilePixelSize[1]);
- }
- if (tileState == ol.TileState.LOADED) {
- context.drawImage(tile.getImage(),
- tileGutter, tileGutter, tilePixelSize[0], tilePixelSize[1],
- x, y, tilePixelSize[0], tilePixelSize[1]);
- }
- this.renderedTiles_[index] = tile;
- }
- }
- } else {
- scale = tileGrid.getResolution(currentZ) / tileResolution;
- for (tileCoordKey in tilesToDraw) {
- tile = tilesToDraw[tileCoordKey];
- tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
- x = (tileExtent[0] - origin[0]) / tilePixelResolution;
- y = (origin[1] - tileExtent[3]) / tilePixelResolution;
- width = scale * tilePixelSize[0];
- height = scale * tilePixelSize[1];
- tileState = tile.getState();
- if (tileState == ol.TileState.EMPTY || !opaque) {
- context.clearRect(x, y, width, height);
- }
- if (tileState == ol.TileState.LOADED) {
- context.drawImage(tile.getImage(),
- tileGutter, tileGutter, tilePixelSize[0], tilePixelSize[1],
- x, y, width, height);
- }
- interimTileRange =
- tileGrid.getTileRangeForExtentAndZ(tileExtent, z, tmpTileRange);
- minX = Math.max(interimTileRange.minX, canvasTileRange.minX);
- maxX = Math.min(interimTileRange.maxX, canvasTileRange.maxX);
- minY = Math.max(interimTileRange.minY, canvasTileRange.minY);
- maxY = Math.min(interimTileRange.maxY, canvasTileRange.maxY);
- for (ix = minX; ix <= maxX; ++ix) {
- for (iy = minY; iy <= maxY; ++iy) {
- index = (iy - canvasTileRange.minY) * canvasTileRangeWidth +
- (ix - canvasTileRange.minX);
- this.renderedTiles_[index] = undefined;
- }
- }
+ for (tileCoordKey in tilesToDraw) {
+ tile = tilesToDraw[tileCoordKey];
+ if (tile.getState() == ol.TileState.LOADED) {
+ renderables.push(tile);
}
}
}
+ this.renderedTiles = renderables;
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio,
@@ -73620,16 +57785,6 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
this.scheduleExpireCache(frameState, tileSource);
this.updateLogos(frameState, tileSource);
- ol.vec.Mat4.makeTransform2D(this.imageTransform_,
- pixelRatio * frameState.size[0] / 2,
- pixelRatio * frameState.size[1] / 2,
- pixelRatio * tilePixelResolution / viewState.resolution,
- pixelRatio * tilePixelResolution / viewState.resolution,
- viewState.rotation,
- (origin[0] - center[0]) / tilePixelResolution,
- (center[1] - origin[1]) / tilePixelResolution);
- this.imageTransformInv_ = null;
-
return true;
};
@@ -73637,22 +57792,16 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
/**
* @inheritDoc
*/
-ol.renderer.canvas.TileLayer.prototype.forEachLayerAtPixel =
- function(pixel, frameState, callback, thisArg) {
- if (!this.context_) {
- return undefined;
- }
-
- if (!this.imageTransformInv_) {
- this.imageTransformInv_ = goog.vec.Mat4.createNumber();
- goog.vec.Mat4.invert(this.imageTransform_, this.imageTransformInv_);
- }
+ol.renderer.canvas.TileLayer.prototype.forEachLayerAtPixel = function(
+ pixel, frameState, callback, thisArg) {
+ var canvas = this.context.canvas;
+ var size = frameState.size;
+ canvas.width = size[0];
+ canvas.height = size[1];
+ this.composeFrame(frameState, this.getLayer().getLayerState(), this.context);
- var pixelOnCanvas =
- this.getPixelOnCanvas(pixel, this.imageTransformInv_);
-
- var imageData = this.context_.getImageData(
- pixelOnCanvas[0], pixelOnCanvas[1], 1, 1).data;
+ var imageData = this.context.getImageData(
+ pixel[0], pixel[1], 1, 1).data;
if (imageData[3] > 0) {
return callback.call(thisArg, this.getLayer());
@@ -73661,22 +57810,156 @@ ol.renderer.canvas.TileLayer.prototype.forEachLayerAtPixel =
}
};
+
+/**
+ * @param {CanvasRenderingContext2D} context Context.
+ * @param {olx.FrameState} frameState Frame state.
+ * @param {ol.LayerState} layerState Layer state.
+ * @protected
+ */
+ol.renderer.canvas.TileLayer.prototype.renderTileImages = function(context, frameState, layerState) {
+ var pixelRatio = frameState.pixelRatio;
+ var viewState = frameState.viewState;
+ var center = viewState.center;
+ var projection = viewState.projection;
+ var resolution = viewState.resolution;
+ var rotation = viewState.rotation;
+ var size = frameState.size;
+ var offsetX = Math.round(pixelRatio * size[0] / 2);
+ var offsetY = Math.round(pixelRatio * size[1] / 2);
+ var pixelScale = pixelRatio / resolution;
+ var layer = this.getLayer();
+ var source = layer.getSource();
+ goog.asserts.assertInstanceof(source, ol.source.Tile,
+ 'source is an ol.source.Tile');
+ var tileGutter = source.getGutter(projection);
+ var tileGrid = source.getTileGridForProjection(projection);
+
+ var hasRenderListeners = layer.hasListener(ol.render.EventType.RENDER);
+ var renderContext = context;
+ var drawOffsetX, drawOffsetY, drawScale, drawSize;
+ if (rotation || hasRenderListeners) {
+ renderContext = this.context;
+ var renderCanvas = renderContext.canvas;
+ var drawZ = tileGrid.getZForResolution(resolution);
+ var drawTileSize = source.getTilePixelSize(drawZ, pixelRatio, projection);
+ var tileSize = ol.size.toSize(tileGrid.getTileSize(drawZ));
+ drawScale = drawTileSize[0] / tileSize[0];
+ var width = context.canvas.width * drawScale;
+ var height = context.canvas.height * drawScale;
+ // Make sure the canvas is big enough for all possible rotation angles
+ drawSize = Math.round(Math.sqrt(width * width + height * height));
+ if (renderCanvas.width != drawSize) {
+ renderCanvas.width = renderCanvas.height = drawSize;
+ } else {
+ renderContext.clearRect(0, 0, drawSize, drawSize);
+ }
+ drawOffsetX = (drawSize - width) / 2 / drawScale;
+ drawOffsetY = (drawSize - height) / 2 / drawScale;
+ pixelScale *= drawScale;
+ offsetX = Math.round(drawScale * (offsetX + drawOffsetX))
+ offsetY = Math.round(drawScale * (offsetY + drawOffsetY));
+ }
+ // for performance reasons, context.save / context.restore is not used
+ // to save and restore the transformation matrix and the opacity.
+ // see http://jsperf.com/context-save-restore-versus-variable
+ var alpha = renderContext.globalAlpha;
+ renderContext.globalAlpha = layerState.opacity;
+
+ var tilesToDraw = this.renderedTiles;
+
+ var pixelExtents;
+ var opaque = source.getOpaque(projection) && layerState.opacity == 1;
+ if (!opaque) {
+ tilesToDraw.reverse();
+ pixelExtents = [];
+ }
+ for (var i = 0, ii = tilesToDraw.length; i < ii; ++i) {
+ var tile = tilesToDraw[i];
+ var tileCoord = tile.getTileCoord();
+ var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
+ var currentZ = tileCoord[0];
+ // Calculate all insert points by tile widths from a common origin to avoid
+ // gaps caused by rounding
+ var origin = ol.extent.getBottomLeft(tileGrid.getTileCoordExtent(
+ tileGrid.getTileCoordForCoordAndZ(center, currentZ, this.tmpTileCoord_)));
+ var w = Math.round(ol.extent.getWidth(tileExtent) * pixelScale);
+ var h = Math.round(ol.extent.getHeight(tileExtent) * pixelScale);
+ var left = Math.round((tileExtent[0] - origin[0]) * pixelScale / w) * w +
+ offsetX + Math.round((origin[0] - center[0]) * pixelScale);
+ var top = Math.round((origin[1] - tileExtent[3]) * pixelScale / h) * h +
+ offsetY + Math.round((center[1] - origin[1]) * pixelScale);
+ if (!opaque) {
+ var pixelExtent = [left, top, left + w, top + h];
+ // Create a clip mask for regions in this low resolution tile that are
+ // already filled by a higher resolution tile
+ renderContext.save();
+ for (var j = 0, jj = pixelExtents.length; j < jj; ++j) {
+ var clipExtent = pixelExtents[j];
+ if (ol.extent.intersects(pixelExtent, clipExtent)) {
+ renderContext.beginPath();
+ // counter-clockwise (outer ring) for current tile
+ renderContext.moveTo(pixelExtent[0], pixelExtent[1]);
+ renderContext.lineTo(pixelExtent[0], pixelExtent[3]);
+ renderContext.lineTo(pixelExtent[2], pixelExtent[3]);
+ renderContext.lineTo(pixelExtent[2], pixelExtent[1]);
+ // clockwise (inner ring) for higher resolution tile
+ renderContext.moveTo(clipExtent[0], clipExtent[1]);
+ renderContext.lineTo(clipExtent[2], clipExtent[1]);
+ renderContext.lineTo(clipExtent[2], clipExtent[3]);
+ renderContext.lineTo(clipExtent[0], clipExtent[3]);
+ renderContext.closePath();
+ renderContext.clip();
+ }
+ }
+ pixelExtents.push(pixelExtent);
+ }
+ var tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection);
+ renderContext.drawImage(tile.getImage(), tileGutter, tileGutter,
+ tilePixelSize[0], tilePixelSize[1], left, top, w, h);
+ if (!opaque) {
+ renderContext.restore();
+ }
+ }
+
+ if (hasRenderListeners) {
+ var dX = drawOffsetX - offsetX / drawScale + offsetX;
+ var dY = drawOffsetY - offsetY / drawScale + offsetY;
+ var imageTransform = ol.vec.Mat4.makeTransform2D(this.imageTransform_,
+ drawSize / 2 - dX, drawSize / 2 - dY, pixelScale, -pixelScale,
+ -rotation, -center[0] + dX / pixelScale, -center[1] - dY / pixelScale);
+ this.dispatchRenderEvent(renderContext, frameState, imageTransform);
+ }
+ if (rotation || hasRenderListeners) {
+ context.drawImage(renderContext.canvas, -Math.round(drawOffsetX),
+ -Math.round(drawOffsetY), drawSize / drawScale, drawSize / drawScale);
+ }
+ renderContext.globalAlpha = alpha;
+};
+
+
+/**
+ * @function
+ * @return {ol.layer.Tile|ol.layer.VectorTile}
+ */
+ol.renderer.canvas.TileLayer.prototype.getLayer;
+
goog.provide('ol.renderer.canvas.VectorLayer');
goog.require('goog.asserts');
-goog.require('goog.events');
+goog.require('ol.events');
goog.require('ol.ViewHint');
goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.layer.Vector');
goog.require('ol.render.EventType');
+goog.require('ol.render.canvas');
goog.require('ol.render.canvas.ReplayGroup');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.renderer.vector');
goog.require('ol.source.Vector');
-
/**
* @constructor
* @extends {ol.renderer.canvas.Layer}
@@ -73735,8 +58018,7 @@ goog.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);
/**
* @inheritDoc
*/
-ol.renderer.canvas.VectorLayer.prototype.composeFrame =
- function(frameState, layerState, context) {
+ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, layerState, context) {
var extent = frameState.extent;
var pixelRatio = frameState.pixelRatio;
@@ -73771,6 +58053,10 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
var alpha = replayContext.globalAlpha;
replayContext.globalAlpha = layerState.opacity;
+ var width = frameState.size[0] * pixelRatio;
+ var height = frameState.size[1] * pixelRatio;
+ ol.render.canvas.rotateAtOffset(replayContext, -rotation,
+ width / 2, height / 2);
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
skippedFeatureUids);
if (vectorSource.getWrapX() && projection.canWrapX() &&
@@ -73800,6 +58086,8 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
// restore original transform for render and compose events
transform = this.getTransform(frameState, 0);
}
+ ol.render.canvas.rotateAtOffset(replayContext, rotation,
+ width / 2, height / 2);
if (replayContext != context) {
this.dispatchRenderEvent(replayContext, frameState, transform);
@@ -73816,19 +58104,17 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
/**
* @inheritDoc
*/
-ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg) {
+ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
if (!this.replayGroup_) {
return undefined;
} else {
var resolution = frameState.viewState.resolution;
var rotation = frameState.viewState.rotation;
var layer = this.getLayer();
- var layerState = frameState.layerStates[goog.getUid(layer)];
/** @type {Object.<string, boolean>} */
var features = {};
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
- rotation, layerState.managed ? frameState.skippedFeatureUids : {},
+ rotation, {},
/**
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result.
@@ -73847,11 +58133,10 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate =
/**
* Handle changes in image style state.
- * @param {goog.events.Event} event Image style change event.
+ * @param {ol.events.Event} event Image style change event.
* @private
*/
-ol.renderer.canvas.VectorLayer.prototype.handleStyleImageChange_ =
- function(event) {
+ol.renderer.canvas.VectorLayer.prototype.handleStyleImageChange_ = function(event) {
this.renderIfReadyAndVisible();
};
@@ -73859,8 +58144,7 @@ ol.renderer.canvas.VectorLayer.prototype.handleStyleImageChange_ =
/**
* @inheritDoc
*/
-ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
- function(frameState, layerState) {
+ol.renderer.canvas.VectorLayer.prototype.prepareFrame = function(frameState, layerState) {
var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector,
@@ -73919,8 +58203,6 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
return true;
}
- // FIXME dispose of old replayGroup in post render
- goog.dispose(this.replayGroup_);
this.replayGroup_ = null;
this.dirty_ = false;
@@ -73930,12 +58212,11 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
ol.renderer.vector.getTolerance(resolution, pixelRatio), extent,
resolution, vectorLayer.getRenderBuffer());
vectorSource.loadFeatures(extent, resolution, projection);
- var renderFeature =
- /**
- * @param {ol.Feature} feature Feature.
- * @this {ol.renderer.canvas.VectorLayer}
- */
- function(feature) {
+ /**
+ * @param {ol.Feature} feature Feature.
+ * @this {ol.renderer.canvas.VectorLayer}
+ */
+ var renderFeature = function(feature) {
var styles;
var styleFunction = feature.getStyleFunction();
if (styleFunction) {
@@ -73988,13 +58269,12 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
* @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
* @return {boolean} `true` if an image is loading.
*/
-ol.renderer.canvas.VectorLayer.prototype.renderFeature =
- function(feature, resolution, pixelRatio, styles, replayGroup) {
+ol.renderer.canvas.VectorLayer.prototype.renderFeature = function(feature, resolution, pixelRatio, styles, replayGroup) {
if (!styles) {
return false;
}
var loading = false;
- if (goog.isArray(styles)) {
+ if (Array.isArray(styles)) {
for (var i = 0, ii = styles.length; i < ii; ++i) {
loading = ol.renderer.vector.renderFeature(
replayGroup, feature, styles[i],
@@ -74011,39 +58291,13 @@ ol.renderer.canvas.VectorLayer.prototype.renderFeature =
};
goog.provide('ol.TileUrlFunction');
-goog.provide('ol.TileUrlFunctionType');
goog.require('goog.asserts');
-goog.require('goog.math');
-goog.require('ol.TileCoord');
+goog.require('ol.math');
goog.require('ol.tilecoord');
/**
- * {@link ol.source.Tile} sources use a function of this type to get the url
- * that provides a tile for a given tile coordinate.
- *
- * This function takes an {@link ol.TileCoord} for the tile coordinate, a
- * `{number}` representing the pixel ratio and an {@link ol.proj.Projection} for
- * the projection as arguments and returns a `{string}` representing the tile
- * URL, or undefined if no tile should be requested for the passed tile
- * coordinate.
- *
- * @typedef {function(ol.TileCoord, number,
- * ol.proj.Projection): (string|undefined)}
- * @api
- */
-ol.TileUrlFunctionType;
-
-
-/**
- * @typedef {function(ol.TileCoord, ol.proj.Projection, ol.TileCoord=):
- * ol.TileCoord}
- */
-ol.TileCoordTransformType;
-
-
-/**
* @param {string} template Template.
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
* @return {ol.TileUrlFunctionType} Tile URL function.
@@ -74121,7 +58375,7 @@ ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) {
return undefined;
} else {
var h = ol.tilecoord.hash(tileCoord);
- var index = goog.math.modulo(h, tileUrlFunctions.length);
+ var index = ol.math.modulo(h, tileUrlFunctions.length);
return tileUrlFunctions[index](tileCoord, pixelRatio, projection);
}
});
@@ -74134,8 +58388,7 @@ ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) {
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
-ol.TileUrlFunction.nullTileUrlFunction =
- function(tileCoord, pixelRatio, projection) {
+ol.TileUrlFunction.nullTileUrlFunction = function(tileCoord, pixelRatio, projection) {
return undefined;
};
@@ -74162,43 +58415,21 @@ ol.TileUrlFunction.expandUrl = function(url) {
goog.provide('ol.source.UrlTile');
-goog.require('goog.events');
-goog.require('ol.TileLoadFunctionType');
+goog.require('ol.events');
goog.require('ol.TileState');
goog.require('ol.TileUrlFunction');
-goog.require('ol.TileUrlFunctionType');
-goog.require('ol.proj');
goog.require('ol.source.Tile');
goog.require('ol.source.TileEvent');
/**
- * @typedef {{attributions: (Array.<ol.Attribution>|undefined),
- * extent: (ol.Extent|undefined),
- * logo: (string|olx.LogoOptions|undefined),
- * opaque: (boolean|undefined),
- * projection: ol.proj.ProjectionLike,
- * state: (ol.source.State|string|undefined),
- * tileGrid: (ol.tilegrid.TileGrid|undefined),
- * tileLoadFunction: ol.TileLoadFunctionType,
- * tilePixelRatio: (number|undefined),
- * tileUrlFunction: (ol.TileUrlFunctionType|undefined),
- * url: (string|undefined),
- * urls: (Array.<string>|undefined),
- * wrapX: (boolean|undefined)}}
- */
-ol.source.UrlTileOptions;
-
-
-
-/**
* @classdesc
* Base class for sources providing tiles divided into a tile grid over http.
*
* @constructor
* @fires ol.source.TileEvent
* @extends {ol.source.Tile}
- * @param {ol.source.UrlTileOptions} options Image tile options.
+ * @param {ol.SourceUrlTileOptions} options Image tile options.
*/
ol.source.UrlTile = function(options) {
@@ -74209,8 +58440,7 @@ ol.source.UrlTile = function(options) {
logo: options.logo,
opaque: options.opaque,
projection: options.projection,
- state: options.state ?
- /** @type {ol.source.State} */ (options.state) : undefined,
+ state: options.state,
tileGrid: options.tileGrid,
tilePixelRatio: options.tilePixelRatio,
wrapX: options.wrapX
@@ -74226,8 +58456,8 @@ ol.source.UrlTile = function(options) {
* @protected
* @type {ol.TileUrlFunctionType}
*/
- this.tileUrlFunction = options.tileUrlFunction ?
- options.tileUrlFunction :
+ this.tileUrlFunction = this.fixedTileUrlFunction ?
+ this.fixedTileUrlFunction.bind(this) :
ol.TileUrlFunction.nullTileUrlFunction;
/**
@@ -74237,11 +58467,7 @@ ol.source.UrlTile = function(options) {
this.urls = null;
if (options.urls) {
- if (options.tileUrlFunction) {
- this.urls = options.urls;
- } else {
- this.setUrls(options.urls);
- }
+ this.setUrls(options.urls);
} else if (options.url) {
this.setUrl(options.url);
}
@@ -74254,6 +58480,12 @@ goog.inherits(ol.source.UrlTile, ol.source.Tile);
/**
+ * @type {ol.TileUrlFunctionType|undefined}
+ * @protected
+ */
+ol.source.UrlTile.prototype.fixedTileUrlFunction;
+
+/**
* Return the tile load function of the source.
* @return {ol.TileLoadFunctionType} TileLoadFunction
* @api
@@ -74287,7 +58519,7 @@ ol.source.UrlTile.prototype.getUrls = function() {
/**
* Handle tile change events.
- * @param {goog.events.Event} event Event.
+ * @param {ol.events.Event} event Event.
* @protected
*/
ol.source.UrlTile.prototype.handleTileChange = function(event) {
@@ -74305,6 +58537,8 @@ ol.source.UrlTile.prototype.handleTileChange = function(event) {
this.dispatchEvent(
new ol.source.TileEvent(ol.source.TileEventType.TILELOADERROR, tile));
break;
+ default:
+ // pass
}
};
@@ -74324,15 +58558,16 @@ ol.source.UrlTile.prototype.setTileLoadFunction = function(tileLoadFunction) {
/**
* Set the tile URL function of the source.
* @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function.
+ * @param {string=} opt_key Optional new tile key for the source.
* @api
*/
-ol.source.UrlTile.prototype.setTileUrlFunction = function(tileUrlFunction) {
- // FIXME It should be possible to be more intelligent and avoid clearing the
- // FIXME cache. The tile URL function would need to be incorporated into the
- // FIXME cache key somehow.
- this.tileCache.clear();
+ol.source.UrlTile.prototype.setTileUrlFunction = function(tileUrlFunction, opt_key) {
this.tileUrlFunction = tileUrlFunction;
- this.changed();
+ if (typeof opt_key !== 'undefined') {
+ this.setKey(opt_key);
+ } else {
+ this.changed();
+ }
};
@@ -74342,9 +58577,10 @@ ol.source.UrlTile.prototype.setTileUrlFunction = function(tileUrlFunction) {
* @api stable
*/
ol.source.UrlTile.prototype.setUrl = function(url) {
- this.setTileUrlFunction(ol.TileUrlFunction.createFromTemplates(
- ol.TileUrlFunction.expandUrl(url), this.tileGrid));
- this.urls = [url];
+ var urls = this.urls = ol.TileUrlFunction.expandUrl(url);
+ this.setTileUrlFunction(this.fixedTileUrlFunction ?
+ this.fixedTileUrlFunction.bind(this) :
+ ol.TileUrlFunction.createFromTemplates(urls, this.tileGrid), url);
};
@@ -74354,9 +58590,11 @@ ol.source.UrlTile.prototype.setUrl = function(url) {
* @api stable
*/
ol.source.UrlTile.prototype.setUrls = function(urls) {
- this.setTileUrlFunction(ol.TileUrlFunction.createFromTemplates(
- urls, this.tileGrid));
this.urls = urls;
+ var key = urls.join('\n');
+ this.setTileUrlFunction(this.fixedTileUrlFunction ?
+ this.fixedTileUrlFunction.bind(this) :
+ ol.TileUrlFunction.createFromTemplates(urls, this.tileGrid), key);
};
@@ -74372,16 +58610,15 @@ ol.source.UrlTile.prototype.useTile = function(z, x, y) {
goog.provide('ol.source.VectorTile');
-goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
goog.require('ol.TileState');
goog.require('ol.VectorTile');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.featureloader');
+goog.require('ol.size');
goog.require('ol.source.UrlTile');
-
/**
* @classdesc
* Class for layer sources providing vector data divided into a tile grid, to be
@@ -74402,13 +58639,12 @@ ol.source.VectorTile = function(options) {
goog.base(this, {
attributions: options.attributions,
- cacheSize: ol.DEFAULT_TILE_CACHE_HIGH_WATER_MARK / 16,
+ cacheSize: options.cacheSize !== undefined ? options.cacheSize : 128,
extent: options.extent,
logo: options.logo,
- opaque: options.opaque,
+ opaque: false,
projection: options.projection,
- state: options.state ?
- /** @type {ol.source.State} */ (options.state) : undefined,
+ state: options.state,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction ?
options.tileLoadFunction : ol.source.VectorTile.defaultTileLoadFunction,
@@ -74428,7 +58664,7 @@ ol.source.VectorTile = function(options) {
/**
* @protected
* @type {function(new: ol.VectorTile, ol.TileCoord, ol.TileState, string,
- * ol.format.Feature, ol.TileLoadFunctionType, ol.proj.Projection)}
+ * ol.format.Feature, ol.TileLoadFunctionType)}
*/
this.tileClass = options.tileClass ? options.tileClass : ol.VectorTile;
@@ -74439,13 +58675,11 @@ goog.inherits(ol.source.VectorTile, ol.source.UrlTile);
/**
* @inheritDoc
*/
-ol.source.VectorTile.prototype.getTile =
- function(z, x, y, pixelRatio, projection) {
+ol.source.VectorTile.prototype.getTile = function(z, x, y, pixelRatio, projection) {
var tileCoordKey = this.getKeyZXY(z, x, y);
if (this.tileCache.containsKey(tileCoordKey)) {
return /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey));
} else {
- goog.asserts.assert(projection, 'argument projection is truthy');
var tileCoord = [z, x, y];
var urlTileCoord = this.getTileCoordForTileUrlFunction(
tileCoord, projection);
@@ -74455,9 +58689,9 @@ ol.source.VectorTile.prototype.getTile =
tileCoord,
tileUrl !== undefined ? ol.TileState.IDLE : ol.TileState.EMPTY,
tileUrl !== undefined ? tileUrl : '',
- this.format_, this.tileLoadFunction, projection);
- goog.events.listen(tile, goog.events.EventType.CHANGE,
- this.handleTileChange, false, this);
+ this.format_, this.tileLoadFunction);
+ ol.events.listen(tile, ol.events.EventType.CHANGE,
+ this.handleTileChange, this);
this.tileCache.set(tileCoordKey, tile);
return tile;
@@ -74466,6 +58700,15 @@ ol.source.VectorTile.prototype.getTile =
/**
+ * @inheritDoc
+ */
+ol.source.VectorTile.prototype.getTilePixelSize = function(z, pixelRatio, projection) {
+ var tileSize = ol.size.toSize(this.tileGrid.getTileSize(z));
+ return [tileSize[0] * pixelRatio, tileSize[1] * pixelRatio];
+};
+
+
+/**
* @param {ol.VectorTile} vectorTile Vector tile.
* @param {string} url URL.
*/
@@ -74476,32 +58719,48 @@ ol.source.VectorTile.defaultTileLoadFunction = function(vectorTile, url) {
goog.provide('ol.renderer.canvas.VectorTileLayer');
goog.require('goog.asserts');
-goog.require('goog.events');
+goog.require('ol.events');
goog.require('goog.vec.Mat4');
goog.require('ol.Feature');
-goog.require('ol.TileRange');
-goog.require('ol.TileState');
goog.require('ol.VectorTile');
-goog.require('ol.ViewHint');
goog.require('ol.array');
-goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.layer.VectorTile');
+goog.require('ol.proj');
goog.require('ol.proj.Units');
goog.require('ol.render.EventType');
+goog.require('ol.render.canvas');
goog.require('ol.render.canvas.ReplayGroup');
-goog.require('ol.renderer.canvas.Layer');
+goog.require('ol.renderer.canvas.TileLayer');
goog.require('ol.renderer.vector');
goog.require('ol.size');
goog.require('ol.source.VectorTile');
-goog.require('ol.tilecoord');
goog.require('ol.vec.Mat4');
+/**
+ * @const
+ * @type {!Object.<string, Array.<ol.render.ReplayType>>}
+ */
+ol.renderer.canvas.IMAGE_REPLAYS = {
+ 'image': ol.render.REPLAY_ORDER,
+ 'hybrid': [ol.render.ReplayType.POLYGON, ol.render.ReplayType.LINE_STRING]
+};
+
+
+/**
+ * @const
+ * @type {!Object.<string, Array.<ol.render.ReplayType>>}
+ */
+ol.renderer.canvas.VECTOR_REPLAYS = {
+ 'hybrid': [ol.render.ReplayType.IMAGE, ol.render.ReplayType.TEXT],
+ 'vector': ol.render.REPLAY_ORDER
+};
+
/**
* @constructor
- * @extends {ol.renderer.canvas.Layer}
+ * @extends {ol.renderer.canvas.TileLayer}
* @param {ol.layer.VectorTile} layer VectorTile layer.
*/
ol.renderer.canvas.VectorTileLayer = function(layer) {
@@ -74510,73 +58769,75 @@ ol.renderer.canvas.VectorTileLayer = function(layer) {
/**
* @private
- * @type {CanvasRenderingContext2D}
- */
- this.context_ = ol.dom.createCanvasContext2D();
-
- /**
- * @private
* @type {boolean}
*/
this.dirty_ = false;
/**
* @private
- * @type {Array.<ol.VectorTile>}
- */
- this.renderedTiles_ = [];
-
- /**
- * @private
- * @type {ol.Extent}
- */
- this.tmpExtent_ = ol.extent.createEmpty();
-
- /**
- * @private
- * @type {ol.Size}
- */
- this.tmpSize_ = [NaN, NaN];
-
- /**
- * @private
* @type {!goog.vec.Mat4.Number}
*/
this.tmpTransform_ = goog.vec.Mat4.createNumber();
+ // Use lower resolution for pure vector rendering. Closest resolution otherwise.
+ this.zDirection =
+ layer.getRenderMode() == ol.layer.VectorTileRenderType.VECTOR ? 1 : 0;
+
};
-goog.inherits(ol.renderer.canvas.VectorTileLayer, ol.renderer.canvas.Layer);
+goog.inherits(ol.renderer.canvas.VectorTileLayer, ol.renderer.canvas.TileLayer);
/**
* @inheritDoc
*/
-ol.renderer.canvas.VectorTileLayer.prototype.composeFrame =
- function(frameState, layerState, context) {
+ol.renderer.canvas.VectorTileLayer.prototype.composeFrame = function(
+ frameState, layerState, context) {
+ var transform = this.getTransform(frameState, 0);
+ this.dispatchPreComposeEvent(context, frameState, transform);
+ var renderMode = this.getLayer().getRenderMode();
+ if (renderMode !== ol.layer.VectorTileRenderType.VECTOR) {
+ this.renderTileImages(context, frameState, layerState);
+ }
+ if (renderMode !== ol.layer.VectorTileRenderType.IMAGE) {
+ this.renderTileReplays_(context, frameState, layerState);
+ }
+ this.dispatchPostComposeEvent(context, frameState, transform);
+};
+
+
+/**
+ * @param {CanvasRenderingContext2D} context Context.
+ * @param {olx.FrameState} frameState Frame state.
+ * @param {ol.LayerState} layerState Layer state.
+ * @private
+ */
+ol.renderer.canvas.VectorTileLayer.prototype.renderTileReplays_ = function(
+ context, frameState, layerState) {
+ var layer = this.getLayer();
+ var replays = ol.renderer.canvas.VECTOR_REPLAYS[layer.getRenderMode()];
var pixelRatio = frameState.pixelRatio;
var skippedFeatureUids = layerState.managed ?
frameState.skippedFeatureUids : {};
var viewState = frameState.viewState;
var center = viewState.center;
- var projection = viewState.projection;
var resolution = viewState.resolution;
var rotation = viewState.rotation;
- var layer = this.getLayer();
+ var size = frameState.size;
+ var pixelScale = pixelRatio / resolution;
var source = layer.getSource();
goog.asserts.assertInstanceof(source, ol.source.VectorTile,
'Source is an ol.source.VectorTile');
+ var tilePixelRatio = source.getTilePixelRatio(pixelRatio);
var transform = this.getTransform(frameState, 0);
- this.dispatchPreComposeEvent(context, frameState, transform);
-
var replayContext;
if (layer.hasListener(ol.render.EventType.RENDER)) {
// resize and clear
- this.context_.canvas.width = context.canvas.width;
- this.context_.canvas.height = context.canvas.height;
- replayContext = this.context_;
+ this.context.canvas.width = context.canvas.width;
+ this.context.canvas.height = context.canvas.height;
+ replayContext = this.context;
} else {
replayContext = context;
}
@@ -74586,55 +58847,58 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame =
var alpha = replayContext.globalAlpha;
replayContext.globalAlpha = layerState.opacity;
- var tilesToDraw = this.renderedTiles_;
+ var tilesToDraw = this.renderedTiles;
var tileGrid = source.getTileGrid();
- var currentZ, i, ii, origin, tile, tileSize;
- var tilePixelRatio, tilePixelResolution, tilePixelSize, tileResolution;
+ var currentZ, i, ii, offsetX, offsetY, origin, pixelSpace, replayState;
+ var tile, tileExtent, tilePixelResolution, tileResolution, tileTransform;
for (i = 0, ii = tilesToDraw.length; i < ii; ++i) {
tile = tilesToDraw[i];
+ replayState = tile.getReplayState();
+ tileExtent = tileGrid.getTileCoordExtent(
+ tile.getTileCoord(), this.tmpExtent);
currentZ = tile.getTileCoord()[0];
- tileSize = tileGrid.getTileSize(currentZ);
- tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection);
- tilePixelRatio = tilePixelSize[0] /
- ol.size.toSize(tileSize, this.tmpSize_)[0];
+ pixelSpace = tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS;
tileResolution = tileGrid.getResolution(currentZ);
tilePixelResolution = tileResolution / tilePixelRatio;
- if (tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) {
- origin = ol.extent.getTopLeft(tileGrid.getTileCoordExtent(
- tile.getTileCoord(), this.tmpExtent_));
- transform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
- pixelRatio * frameState.size[0] / 2,
- pixelRatio * frameState.size[1] / 2,
- pixelRatio * tilePixelResolution / resolution,
- pixelRatio * tilePixelResolution / resolution,
- viewState.rotation,
+ offsetX = Math.round(pixelRatio * size[0] / 2);
+ offsetY = Math.round(pixelRatio * size[1] / 2);
+
+ if (pixelSpace) {
+ origin = ol.extent.getTopLeft(tileExtent);
+ tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
+ offsetX, offsetY,
+ pixelScale * tilePixelResolution,
+ pixelScale * tilePixelResolution,
+ rotation,
(origin[0] - center[0]) / tilePixelResolution,
(center[1] - origin[1]) / tilePixelResolution);
+ } else {
+ tileTransform = transform;
}
- tile.getReplayState().replayGroup.replay(replayContext, pixelRatio,
- transform, rotation, skippedFeatureUids);
+ ol.render.canvas.rotateAtOffset(replayContext, -rotation, offsetX, offsetY);
+ replayState.replayGroup.replay(replayContext, pixelRatio,
+ tileTransform, rotation, skippedFeatureUids, replays);
+ ol.render.canvas.rotateAtOffset(replayContext, rotation, offsetX, offsetY);
}
- transform = this.getTransform(frameState, 0);
-
if (replayContext != context) {
this.dispatchRenderEvent(replayContext, frameState, transform);
context.drawImage(replayContext.canvas, 0, 0);
}
replayContext.globalAlpha = alpha;
-
- this.dispatchPostComposeEvent(context, frameState, transform);
};
/**
* @param {ol.VectorTile} tile Tile.
- * @param {ol.layer.VectorTile} layer Vector tile layer.
- * @param {number} pixelRatio Pixel ratio.
+ * @param {olx.FrameState} frameState Frame state.
*/
ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
- layer, pixelRatio) {
+ frameState) {
+ var layer = this.getLayer();
+ var pixelRatio = frameState.pixelRatio;
+ var projection = frameState.viewState.projection;
var revision = layer.getRevision();
var renderOrder = layer.getRenderOrder() || null;
@@ -74644,8 +58908,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
return;
}
- // FIXME dispose of old replayGroup in post render
- goog.dispose(replayState.replayGroup);
replayState.replayGroup = null;
replayState.dirty = false;
@@ -74654,17 +58916,22 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
'Source is an ol.source.VectorTile');
var tileGrid = source.getTileGrid();
var tileCoord = tile.getTileCoord();
- var pixelSpace = tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS;
- var extent;
+ var tileProjection = tile.getProjection();
+ var pixelSpace = tileProjection.getUnits() == ol.proj.Units.TILE_PIXELS;
+ var resolution = tileGrid.getResolution(tileCoord[0]);
+ var extent, reproject, tileResolution;
if (pixelSpace) {
- var tilePixelSize = source.getTilePixelSize(tileCoord[0], pixelRatio,
- tile.getProjection());
- extent = [0, 0, tilePixelSize[0], tilePixelSize[1]];
+ var tilePixelRatio = tileResolution = source.getTilePixelRatio(pixelRatio);
+ var tileSize = ol.size.toSize(tileGrid.getTileSize(tileCoord[0]));
+ extent = [0, 0, tileSize[0] * tilePixelRatio, tileSize[1] * tilePixelRatio];
} else {
+ tileResolution = resolution;
extent = tileGrid.getTileCoordExtent(tileCoord);
+ if (!ol.proj.equivalent(projection, tileProjection)) {
+ reproject = true;
+ tile.setProjection(projection);
+ }
}
- var resolution = tileGrid.getResolution(tileCoord[0]);
- var tileResolution = pixelSpace ? source.getTilePixelRatio() : resolution;
replayState.dirty = false;
var replayGroup = new ol.render.canvas.ReplayGroup(0, extent,
tileResolution, layer.getRenderBuffer());
@@ -74688,7 +58955,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
}
}
if (styles) {
- if (!goog.isArray(styles)) {
+ if (!Array.isArray(styles)) {
styles = [styles];
}
var dirty = this.renderFeature(feature, squaredTolerance, styles,
@@ -74702,29 +58969,36 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
if (renderOrder && renderOrder !== replayState.renderedRenderOrder) {
features.sort(renderOrder);
}
- features.forEach(renderFeature, this);
+ var feature;
+ for (var i = 0, ii = features.length; i < ii; ++i) {
+ feature = features[i];
+ if (reproject) {
+ feature.getGeometry().transform(tileProjection, projection);
+ }
+ renderFeature.call(this, feature);
+ }
replayGroup.finish();
replayState.renderedRevision = revision;
replayState.renderedRenderOrder = renderOrder;
replayState.replayGroup = replayGroup;
+ replayState.resolution = NaN;
};
/**
* @inheritDoc
*/
-ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg) {
+ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
+ var pixelRatio = frameState.pixelRatio;
var resolution = frameState.viewState.resolution;
var rotation = frameState.viewState.rotation;
var layer = this.getLayer();
- var layerState = frameState.layerStates[goog.getUid(layer)];
/** @type {Object.<string, boolean>} */
var features = {};
- var replayables = this.renderedTiles_;
+ var replayables = this.renderedTiles;
var source = layer.getSource();
goog.asserts.assertInstanceof(source, ol.source.VectorTile,
'Source is an ol.source.VectorTile');
@@ -74736,13 +59010,13 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate =
tile = replayables[i];
tileCoord = tile.getTileCoord();
tileExtent = source.getTileGrid().getTileCoordExtent(tileCoord,
- this.tmpExtent_);
+ this.tmpExtent);
if (!ol.extent.containsCoordinate(tileExtent, coordinate)) {
continue;
}
if (tile.getProjection().getUnits() === ol.proj.Units.TILE_PIXELS) {
origin = ol.extent.getTopLeft(tileExtent);
- tilePixelRatio = source.getTilePixelRatio();
+ tilePixelRatio = source.getTilePixelRatio(pixelRatio);
tileResolution = tileGrid.getResolution(tileCoord[0]) / tilePixelRatio;
tileSpaceCoordinate = [
(coordinate[0] - origin[0]) / tileResolution,
@@ -74754,8 +59028,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate =
}
replayGroup = tile.getReplayState().replayGroup;
found = found || replayGroup.forEachFeatureAtCoordinate(
- tileSpaceCoordinate, resolution, rotation,
- layerState.managed ? frameState.skippedFeatureUids : {},
+ tileSpaceCoordinate, resolution, rotation, {},
/**
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result.
@@ -74775,11 +59048,10 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate =
/**
* Handle changes in image style state.
- * @param {goog.events.Event} event Image style change event.
+ * @param {ol.events.Event} event Image style change event.
* @private
*/
-ol.renderer.canvas.VectorTileLayer.prototype.handleStyleImageChange_ =
- function(event) {
+ol.renderer.canvas.VectorTileLayer.prototype.handleStyleImageChange_ = function(event) {
this.renderIfReadyAndVisible();
};
@@ -74787,118 +59059,18 @@ ol.renderer.canvas.VectorTileLayer.prototype.handleStyleImageChange_ =
/**
* @inheritDoc
*/
-ol.renderer.canvas.VectorTileLayer.prototype.prepareFrame =
- function(frameState, layerState) {
- var layer = /** @type {ol.layer.Vector} */ (this.getLayer());
- goog.asserts.assertInstanceof(layer, ol.layer.VectorTile,
- 'layer is an instance of ol.layer.VectorTile');
- var source = layer.getSource();
- goog.asserts.assertInstanceof(source, ol.source.VectorTile,
- 'Source is an ol.source.VectorTile');
-
- this.updateAttributions(
- frameState.attributions, source.getAttributions());
- this.updateLogos(frameState, source);
-
- var animating = frameState.viewHints[ol.ViewHint.ANIMATING];
- var interacting = frameState.viewHints[ol.ViewHint.INTERACTING];
- var updateWhileAnimating = layer.getUpdateWhileAnimating();
- var updateWhileInteracting = layer.getUpdateWhileInteracting();
-
- if (!this.dirty_ && (!updateWhileAnimating && animating) ||
- (!updateWhileInteracting && interacting)) {
- return true;
- }
-
- var extent = frameState.extent;
- if (layerState.extent) {
- extent = ol.extent.getIntersection(extent, layerState.extent);
- }
- if (ol.extent.isEmpty(extent)) {
- // Return false to prevent the rendering of the layer.
- return false;
- }
-
- var viewState = frameState.viewState;
- var projection = viewState.projection;
- var resolution = viewState.resolution;
- var pixelRatio = frameState.pixelRatio;
-
- var tileGrid = source.getTileGrid();
- var resolutions = tileGrid.getResolutions();
- var z = resolutions.length - 1;
- while (z > 0 && resolutions[z] < resolution) {
- --z;
- }
- var tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
- this.updateUsedTiles(frameState.usedTiles, source, z, tileRange);
- this.manageTilePyramid(frameState, source, tileGrid, pixelRatio,
- projection, extent, z, layer.getPreload());
- this.scheduleExpireCache(frameState, source);
-
- /**
- * @type {Object.<number, Object.<string, ol.VectorTile>>}
- */
- var tilesToDrawByZ = {};
- tilesToDrawByZ[z] = {};
-
- var findLoadedTiles = this.createLoadedTileFinder(source, projection,
- tilesToDrawByZ);
-
- var useInterimTilesOnError = layer.getUseInterimTilesOnError();
-
- var tmpExtent = this.tmpExtent_;
- var tmpTileRange = new ol.TileRange(0, 0, 0, 0);
- var childTileRange, fullyLoaded, tile, tileState, x, y;
- for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
- for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
-
- tile = source.getTile(z, x, y, pixelRatio, projection);
- goog.asserts.assertInstanceof(tile, ol.VectorTile,
- 'Tile is an ol.VectorTile');
- tileState = tile.getState();
- if (tileState == ol.TileState.LOADED ||
- tileState == ol.TileState.EMPTY ||
- (tileState == ol.TileState.ERROR && !useInterimTilesOnError)) {
- tilesToDrawByZ[z][ol.tilecoord.toString(tile.tileCoord)] = tile;
- continue;
- }
-
- fullyLoaded = tileGrid.forEachTileCoordParentTileRange(
- tile.tileCoord, findLoadedTiles, null, tmpTileRange, tmpExtent);
- if (!fullyLoaded) {
- childTileRange = tileGrid.getTileCoordChildTileRange(
- tile.tileCoord, tmpTileRange, tmpExtent);
- if (childTileRange) {
- findLoadedTiles(z + 1, childTileRange);
- }
- }
-
- }
- }
-
- this.dirty_ = false;
-
- /** @type {Array.<number>} */
- var zs = Object.keys(tilesToDrawByZ).map(Number);
- zs.sort(ol.array.numberSafeCompareFunction);
- var replayables = [];
- var i, ii, currentZ, tileCoordKey, tilesToDraw;
- for (i = 0, ii = zs.length; i < ii; ++i) {
- currentZ = zs[i];
- tilesToDraw = tilesToDrawByZ[currentZ];
- for (tileCoordKey in tilesToDraw) {
- tile = tilesToDraw[tileCoordKey];
- if (tile.getState() == ol.TileState.LOADED) {
- replayables.push(tile);
- this.createReplayGroup(tile, layer, pixelRatio);
- }
+ol.renderer.canvas.VectorTileLayer.prototype.prepareFrame = function(frameState, layerState) {
+ var prepared = goog.base(this, 'prepareFrame', frameState, layerState);
+ if (prepared) {
+ var skippedFeatures = Object.keys(frameState.skippedFeatureUids_ || {});
+ for (var i = 0, ii = this.renderedTiles.length; i < ii; ++i) {
+ var tile = this.renderedTiles[i];
+ goog.asserts.assertInstanceof(tile, ol.VectorTile, 'got an ol.VectorTile');
+ this.createReplayGroup(tile, frameState);
+ this.renderTileImage_(tile, frameState, layerState, skippedFeatures);
}
}
-
- this.renderedTiles_ = replayables;
-
- return true;
+ return prepared;
};
@@ -74910,13 +59082,12 @@ ol.renderer.canvas.VectorTileLayer.prototype.prepareFrame =
* @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
* @return {boolean} `true` if an image is loading.
*/
-ol.renderer.canvas.VectorTileLayer.prototype.renderFeature =
- function(feature, squaredTolerance, styles, replayGroup) {
+ol.renderer.canvas.VectorTileLayer.prototype.renderFeature = function(feature, squaredTolerance, styles, replayGroup) {
if (!styles) {
return false;
}
var loading = false;
- if (goog.isArray(styles)) {
+ if (Array.isArray(styles)) {
for (var i = 0, ii = styles.length; i < ii; ++i) {
loading = ol.renderer.vector.renderFeature(
replayGroup, feature, styles[i], squaredTolerance,
@@ -74930,17 +59101,81 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderFeature =
return loading;
};
+
+/**
+ * @param {ol.VectorTile} tile Tile.
+ * @param {olx.FrameState} frameState Frame state.
+ * @param {ol.LayerState} layerState Layer state.
+ * @param {Array.<string>} skippedFeatures Skipped features.
+ * @private
+ */
+ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function(
+ tile, frameState, layerState, skippedFeatures) {
+ var layer = this.getLayer();
+ var replays = ol.renderer.canvas.IMAGE_REPLAYS[layer.getRenderMode()];
+ if (!replays) {
+ // do not create an image in 'vector' mode
+ return;
+ }
+ var pixelRatio = frameState.pixelRatio;
+ var replayState = tile.getReplayState();
+ var revision = layer.getRevision();
+ if (!ol.array.equals(replayState.skippedFeatures, skippedFeatures) ||
+ replayState.renderedTileRevision !== revision) {
+ replayState.skippedFeatures = skippedFeatures;
+ replayState.renderedTileRevision = revision;
+ var tileContext = tile.getContext();
+ var source = layer.getSource();
+ var tileGrid = source.getTileGrid();
+ var currentZ = tile.getTileCoord()[0];
+ var resolution = tileGrid.getResolution(currentZ);
+ var tileSize = ol.size.toSize(tileGrid.getTileSize(currentZ));
+ var tileResolution = tileGrid.getResolution(currentZ);
+ var resolutionRatio = tileResolution / resolution;
+ var width = tileSize[0] * pixelRatio * resolutionRatio;
+ var height = tileSize[1] * pixelRatio * resolutionRatio;
+ tileContext.canvas.width = width / resolutionRatio + 0.5;
+ tileContext.canvas.height = height / resolutionRatio + 0.5;
+ tileContext.scale(1 / resolutionRatio, 1 / resolutionRatio);
+ tileContext.translate(width / 2, height / 2);
+ var pixelSpace = tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS;
+ var pixelScale = pixelRatio / resolution;
+ var tilePixelRatio = source.getTilePixelRatio(pixelRatio);
+ var tilePixelResolution = tileResolution / tilePixelRatio;
+ var tileExtent = tileGrid.getTileCoordExtent(
+ tile.getTileCoord(), this.tmpExtent);
+ var tileTransform;
+ if (pixelSpace) {
+ tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
+ 0, 0,
+ pixelScale * tilePixelResolution, pixelScale * tilePixelResolution,
+ 0,
+ -tileSize[0] * tilePixelRatio / 2, -tileSize[1] * tilePixelRatio / 2);
+ } else {
+ var tileCenter = ol.extent.getCenter(tileExtent);
+ tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
+ 0, 0,
+ pixelScale, -pixelScale,
+ 0,
+ -tileCenter[0], -tileCenter[1]);
+ }
+
+ replayState.replayGroup.replay(tileContext, pixelRatio,
+ tileTransform, 0, frameState.skippedFeatureUids || {}, replays);
+ }
+}
+
// FIXME offset panning
goog.provide('ol.renderer.canvas.Map');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.style');
goog.require('goog.vec.Mat4');
goog.require('ol');
goog.require('ol.RendererType');
+goog.require('ol.array');
goog.require('ol.css');
goog.require('ol.dom');
goog.require('ol.layer.Image');
@@ -74950,6 +59185,7 @@ goog.require('ol.layer.Vector');
goog.require('ol.layer.VectorTile');
goog.require('ol.render.Event');
goog.require('ol.render.EventType');
+goog.require('ol.render.canvas');
goog.require('ol.render.canvas.Immediate');
goog.require('ol.renderer.Map');
goog.require('ol.renderer.canvas.ImageLayer');
@@ -74961,7 +59197,6 @@ goog.require('ol.source.State');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.Map}
@@ -75029,8 +59264,7 @@ ol.renderer.canvas.Map.prototype.createLayerRenderer = function(layer) {
* @param {olx.FrameState} frameState Frame state.
* @private
*/
-ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ =
- function(type, frameState) {
+ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ = function(type, frameState) {
var map = this.getMap();
var context = this.context_;
if (map.hasListener(type)) {
@@ -75046,8 +59280,6 @@ ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ =
var composeEvent = new ol.render.Event(type, map, vectorContext,
frameState, context, null);
map.dispatchEvent(composeEvent);
-
- vectorContext.flush();
}
};
@@ -75091,21 +59323,26 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
}
var context = this.context_;
- var width = frameState.size[0] * frameState.pixelRatio;
- var height = frameState.size[1] * frameState.pixelRatio;
+ var pixelRatio = frameState.pixelRatio;
+ var width = Math.round(frameState.size[0] * pixelRatio);
+ var height = Math.round(frameState.size[1] * pixelRatio);
if (this.canvas_.width != width || this.canvas_.height != height) {
this.canvas_.width = width;
this.canvas_.height = height;
} else {
- context.clearRect(0, 0, this.canvas_.width, this.canvas_.height);
+ context.clearRect(0, 0, width, height);
}
+ var rotation = frameState.viewState.rotation;
+
this.calculateMatrices2D(frameState);
this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, frameState);
var layerStatesArray = frameState.layerStatesArray;
- goog.array.stableSort(layerStatesArray, ol.renderer.Map.sortByZIndex);
+ ol.array.stableSort(layerStatesArray, ol.renderer.Map.sortByZIndex);
+
+ ol.render.canvas.rotateAtOffset(context, rotation, width / 2, height / 2);
var viewResolution = frameState.viewState.resolution;
var i, ii, layer, layerRenderer, layerState;
@@ -75124,6 +59361,8 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
}
}
+ ol.render.canvas.rotateAtOffset(context, -rotation, width / 2, height / 2);
+
this.dispatchComposeEvent_(
ol.render.EventType.POSTCOMPOSE, frameState);
@@ -75143,7 +59382,6 @@ goog.require('ol.layer.Layer');
goog.require('ol.renderer.Layer');
-
/**
* @constructor
* @extends {ol.renderer.Layer}
@@ -75172,7 +59410,7 @@ ol.renderer.dom.Layer.prototype.clearFrame = ol.nullFunction;
/**
* @param {olx.FrameState} frameState Frame state.
- * @param {ol.layer.LayerState} layerState Layer state.
+ * @param {ol.LayerState} layerState Layer state.
*/
ol.renderer.dom.Layer.prototype.composeFrame = ol.nullFunction;
@@ -75187,7 +59425,7 @@ ol.renderer.dom.Layer.prototype.getTarget = function() {
/**
* @param {olx.FrameState} frameState Frame state.
- * @param {ol.layer.LayerState} layerState Layer state.
+ * @param {ol.LayerState} layerState Layer state.
* @return {boolean} whether composeFrame should be called.
*/
ol.renderer.dom.Layer.prototype.prepareFrame = goog.abstractMethod;
@@ -75207,7 +59445,6 @@ goog.require('ol.renderer.dom.Layer');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.dom.Layer}
@@ -75239,8 +59476,7 @@ goog.inherits(ol.renderer.dom.ImageLayer, ol.renderer.dom.Layer);
/**
* @inheritDoc
*/
-ol.renderer.dom.ImageLayer.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg) {
+ol.renderer.dom.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
var layer = this.getLayer();
var source = layer.getSource();
var resolution = frameState.viewState.resolution;
@@ -75270,8 +59506,7 @@ ol.renderer.dom.ImageLayer.prototype.clearFrame = function() {
/**
* @inheritDoc
*/
-ol.renderer.dom.ImageLayer.prototype.prepareFrame =
- function(frameState, layerState) {
+ol.renderer.dom.ImageLayer.prototype.prepareFrame = function(frameState, layerState) {
var viewState = frameState.viewState;
var viewCenter = viewState.center;
@@ -75364,8 +59599,6 @@ goog.require('goog.dom');
goog.require('goog.style');
goog.require('goog.vec.Mat4');
goog.require('ol');
-goog.require('ol.Coordinate');
-goog.require('ol.TileCoord');
goog.require('ol.TileRange');
goog.require('ol.TileState');
goog.require('ol.ViewHint');
@@ -75375,12 +59608,10 @@ goog.require('ol.extent');
goog.require('ol.layer.Tile');
goog.require('ol.renderer.dom.Layer');
goog.require('ol.size');
-goog.require('ol.tilecoord');
goog.require('ol.tilegrid.TileGrid');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.dom.Layer}
@@ -75433,8 +59664,7 @@ ol.renderer.dom.TileLayer.prototype.clearFrame = function() {
/**
* @inheritDoc
*/
-ol.renderer.dom.TileLayer.prototype.prepareFrame =
- function(frameState, layerState) {
+ol.renderer.dom.TileLayer.prototype.prepareFrame = function(frameState, layerState) {
if (!layerState.visible) {
if (this.renderedVisible_) {
@@ -75453,7 +59683,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
'layer is an instance of ol.layer.Tile');
var tileSource = tileLayer.getSource();
var tileGrid = tileSource.getTileGridForProjection(projection);
- var tileGutter = tileSource.getGutter();
+ var tileGutter = tileSource.getGutter(projection);
var z = tileGrid.getZForResolution(viewState.resolution);
var tileResolution = tileGrid.getResolution(z);
var center = viewState.center;
@@ -75498,7 +59728,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
goog.asserts.assert(tile);
tileState = tile.getState();
if (tileState == ol.TileState.LOADED) {
- tilesToDrawByZ[z][ol.tilecoord.toString(tile.tileCoord)] = tile;
+ tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
continue;
} else if (tileState == ol.TileState.EMPTY ||
(tileState == ol.TileState.ERROR &&
@@ -75621,7 +59851,6 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
};
-
/**
* @constructor
* @private
@@ -75701,7 +59930,7 @@ ol.renderer.dom.TileLayerZ_.prototype.addTile = function(tile, tileGutter) {
var tileCoordY = tileCoord[2];
goog.asserts.assert(tileCoordZ == this.tileCoordOrigin_[0],
'tileCoordZ matches z of tileCoordOrigin');
- var tileCoordKey = ol.tilecoord.toString(tileCoord);
+ var tileCoordKey = tileCoord.toString();
if (tileCoordKey in this.tiles_) {
return;
}
@@ -75777,8 +60006,7 @@ ol.renderer.dom.TileLayerZ_.prototype.getResolution = function() {
* @param {ol.Extent} extent Extent.
* @param {ol.TileRange=} opt_tileRange Temporary ol.TileRange object.
*/
-ol.renderer.dom.TileLayerZ_.prototype.removeTilesOutsideExtent =
- function(extent, opt_tileRange) {
+ol.renderer.dom.TileLayerZ_.prototype.removeTilesOutsideExtent = function(extent, opt_tileRange) {
var tileRange = this.tileGrid_.getTileRangeForExtentAndZ(
extent, this.tileCoordOrigin_[0], opt_tileRange);
/** @type {Array.<ol.Tile>} */
@@ -75793,7 +60021,7 @@ ol.renderer.dom.TileLayerZ_.prototype.removeTilesOutsideExtent =
var i, ii;
for (i = 0, ii = tilesToRemove.length; i < ii; ++i) {
tile = tilesToRemove[i];
- tileCoordKey = ol.tilecoord.toString(tile.tileCoord);
+ tileCoordKey = tile.tileCoord.toString();
goog.dom.removeNode(tile.getImage(this));
delete this.tiles_[tileCoordKey];
}
@@ -75813,7 +60041,7 @@ ol.renderer.dom.TileLayerZ_.prototype.setTransform = function(transform) {
goog.provide('ol.renderer.dom.VectorLayer');
goog.require('goog.asserts');
-goog.require('goog.events');
+goog.require('ol.events');
goog.require('goog.vec.Mat4');
goog.require('ol.ViewHint');
goog.require('ol.dom');
@@ -75828,7 +60056,6 @@ goog.require('ol.renderer.vector');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.dom.Layer}
@@ -75906,8 +60133,18 @@ goog.inherits(ol.renderer.dom.VectorLayer, ol.renderer.dom.Layer);
/**
* @inheritDoc
*/
-ol.renderer.dom.VectorLayer.prototype.composeFrame =
- function(frameState, layerState) {
+ol.renderer.dom.VectorLayer.prototype.clearFrame = function() {
+ // Clear the canvas
+ var canvas = this.context_.canvas;
+ canvas.width = canvas.width;
+ this.renderedRevision_ = 0;
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.dom.VectorLayer.prototype.composeFrame = function(frameState, layerState) {
var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector,
@@ -75968,8 +60205,7 @@ ol.renderer.dom.VectorLayer.prototype.composeFrame =
* @param {goog.vec.Mat4.Number} transform Transform.
* @private
*/
-ol.renderer.dom.VectorLayer.prototype.dispatchEvent_ =
- function(type, frameState, transform) {
+ol.renderer.dom.VectorLayer.prototype.dispatchEvent_ = function(type, frameState, transform) {
var context = this.context_;
var layer = this.getLayer();
if (layer.hasListener(type)) {
@@ -75979,7 +60215,6 @@ ol.renderer.dom.VectorLayer.prototype.dispatchEvent_ =
var event = new ol.render.Event(type, layer, render, frameState,
context, null);
layer.dispatchEvent(event);
- render.flush();
}
};
@@ -75987,19 +60222,17 @@ ol.renderer.dom.VectorLayer.prototype.dispatchEvent_ =
/**
* @inheritDoc
*/
-ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg) {
+ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
if (!this.replayGroup_) {
return undefined;
} else {
var resolution = frameState.viewState.resolution;
var rotation = frameState.viewState.rotation;
var layer = this.getLayer();
- var layerState = frameState.layerStates[goog.getUid(layer)];
/** @type {Object.<string, boolean>} */
var features = {};
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
- rotation, layerState.managed ? frameState.skippedFeatureUids : {},
+ rotation, {},
/**
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result.
@@ -76018,11 +60251,10 @@ ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtCoordinate =
/**
* Handle changes in image style state.
- * @param {goog.events.Event} event Image style change event.
+ * @param {ol.events.Event} event Image style change event.
* @private
*/
-ol.renderer.dom.VectorLayer.prototype.handleStyleImageChange_ =
- function(event) {
+ol.renderer.dom.VectorLayer.prototype.handleStyleImageChange_ = function(event) {
this.renderIfReadyAndVisible();
};
@@ -76030,8 +60262,7 @@ ol.renderer.dom.VectorLayer.prototype.handleStyleImageChange_ =
/**
* @inheritDoc
*/
-ol.renderer.dom.VectorLayer.prototype.prepareFrame =
- function(frameState, layerState) {
+ol.renderer.dom.VectorLayer.prototype.prepareFrame = function(frameState, layerState) {
var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector,
@@ -76076,8 +60307,6 @@ ol.renderer.dom.VectorLayer.prototype.prepareFrame =
return true;
}
- // FIXME dispose of old replayGroup in post render
- goog.dispose(this.replayGroup_);
this.replayGroup_ = null;
this.dirty_ = false;
@@ -76087,12 +60316,11 @@ ol.renderer.dom.VectorLayer.prototype.prepareFrame =
ol.renderer.vector.getTolerance(resolution, pixelRatio), extent,
resolution, vectorLayer.getRenderBuffer());
vectorSource.loadFeatures(extent, resolution, projection);
- var renderFeature =
- /**
- * @param {ol.Feature} feature Feature.
- * @this {ol.renderer.dom.VectorLayer}
- */
- function(feature) {
+ /**
+ * @param {ol.Feature} feature Feature.
+ * @this {ol.renderer.dom.VectorLayer}
+ */
+ var renderFeature = function(feature) {
var styles;
var styleFunction = feature.getStyleFunction();
if (styleFunction) {
@@ -76145,13 +60373,12 @@ ol.renderer.dom.VectorLayer.prototype.prepareFrame =
* @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
* @return {boolean} `true` if an image is loading.
*/
-ol.renderer.dom.VectorLayer.prototype.renderFeature =
- function(feature, resolution, pixelRatio, styles, replayGroup) {
+ol.renderer.dom.VectorLayer.prototype.renderFeature = function(feature, resolution, pixelRatio, styles, replayGroup) {
if (!styles) {
return false;
}
var loading = false;
- if (goog.isArray(styles)) {
+ if (Array.isArray(styles)) {
for (var i = 0, ii = styles.length; i < ii; ++i) {
loading = ol.renderer.vector.renderFeature(
replayGroup, feature, styles[i],
@@ -76169,16 +60396,16 @@ ol.renderer.dom.VectorLayer.prototype.renderFeature =
goog.provide('ol.renderer.dom.Map');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.Event');
+goog.require('ol.events.EventType');
goog.require('goog.style');
goog.require('goog.vec.Mat4');
goog.require('ol');
goog.require('ol.RendererType');
+goog.require('ol.array');
goog.require('ol.css');
goog.require('ol.dom');
goog.require('ol.layer.Image');
@@ -76197,7 +60424,6 @@ goog.require('ol.source.State');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.Map}
@@ -76238,8 +60464,8 @@ ol.renderer.dom.Map = function(container, map) {
style.height = '100%';
// prevent the img context menu on mobile devices
- goog.events.listen(this.layersPane_, goog.events.EventType.TOUCHSTART,
- goog.events.Event.preventDefault);
+ ol.events.listen(this.layersPane_, ol.events.EventType.TOUCHSTART,
+ ol.events.Event.preventDefault);
goog.dom.insertChildAt(container, this.layersPane_, 0);
@@ -76286,8 +60512,7 @@ ol.renderer.dom.Map.prototype.createLayerRenderer = function(layer) {
* @param {olx.FrameState} frameState Frame state.
* @private
*/
-ol.renderer.dom.Map.prototype.dispatchComposeEvent_ =
- function(type, frameState) {
+ol.renderer.dom.Map.prototype.dispatchComposeEvent_ = function(type, frameState) {
var map = this.getMap();
if (map.hasListener(type)) {
var extent = frameState.extent;
@@ -76309,7 +60534,6 @@ ol.renderer.dom.Map.prototype.dispatchComposeEvent_ =
var composeEvent = new ol.render.Event(type, map, vectorContext,
frameState, context, null);
map.dispatchEvent(composeEvent);
- vectorContext.flush();
}
};
@@ -76347,7 +60571,7 @@ ol.renderer.dom.Map.prototype.renderFrame = function(frameState) {
this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, frameState);
var layerStatesArray = frameState.layerStatesArray;
- goog.array.stableSort(layerStatesArray, ol.renderer.Map.sortByZIndex);
+ ol.array.stableSort(layerStatesArray, ol.renderer.Map.sortByZIndex);
var viewResolution = frameState.viewState.resolution;
var i, ii, layer, layerRenderer, layerState;
@@ -78592,12 +62816,11 @@ goog.provide('ol.webgl.Shader');
goog.provide('ol.webgl.Vertex');
goog.provide('ol.webgl.shader');
-goog.require('goog.functions');
goog.require('goog.webgl');
+goog.require('ol.functions');
goog.require('ol.webgl');
-
/**
* @constructor
* @param {string} source Source.
@@ -78631,8 +62854,7 @@ ol.webgl.Shader.prototype.getSource = function() {
/**
* @return {boolean} Is animated?
*/
-ol.webgl.Shader.prototype.isAnimated = goog.functions.FALSE;
-
+ol.webgl.Shader.prototype.isAnimated = ol.functions.FALSE;
/**
@@ -78655,7 +62877,6 @@ ol.webgl.shader.Fragment.prototype.getType = function() {
};
-
/**
* @constructor
* @extends {ol.webgl.Shader}
@@ -78684,7 +62905,6 @@ goog.provide('ol.render.webgl.imagereplay.shader.DefaultVertex');
goog.require('ol.webgl.shader');
-
/**
* @constructor
* @extends {ol.webgl.shader.Fragment}
@@ -78720,7 +62940,6 @@ ol.render.webgl.imagereplay.shader.DefaultFragment.SOURCE = goog.DEBUG ?
ol.render.webgl.imagereplay.shader.DefaultFragment.OPTIMIZED_SOURCE;
-
/**
* @constructor
* @extends {ol.webgl.shader.Vertex}
@@ -78756,7 +62975,6 @@ ol.render.webgl.imagereplay.shader.DefaultVertex.SOURCE = goog.DEBUG ?
ol.render.webgl.imagereplay.shader.DefaultVertex.OPTIMIZED_SOURCE;
-
/**
* @constructor
* @param {WebGLRenderingContext} gl GL.
@@ -78842,7 +63060,6 @@ ol.webgl.BufferUsage = {
};
-
/**
* @constructor
* @param {Array.<number>=} opt_arr Array.
@@ -78885,29 +63102,21 @@ ol.webgl.Buffer.prototype.getUsage = function() {
goog.provide('ol.webgl.Context');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.log');
-goog.require('goog.object');
goog.require('ol');
+goog.require('ol.Disposable');
goog.require('ol.array');
+goog.require('ol.events');
+goog.require('ol.object');
goog.require('ol.webgl.Buffer');
goog.require('ol.webgl.WebGLContextEventType');
/**
- * @typedef {{buf: ol.webgl.Buffer,
- * buffer: WebGLBuffer}}
- */
-ol.webgl.BufferCacheEntry;
-
-
-
-/**
* @classdesc
* A WebGL context for accessing low-level WebGL capabilities.
*
* @constructor
- * @extends {goog.events.EventTarget}
+ * @extends {ol.Disposable}
* @param {HTMLCanvasElement} canvas Canvas.
* @param {WebGLRenderingContext} gl GL.
*/
@@ -78927,13 +63136,13 @@ ol.webgl.Context = function(canvas, gl) {
/**
* @private
- * @type {Object.<number, ol.webgl.BufferCacheEntry>}
+ * @type {Object.<string, ol.WebglBufferCacheEntry>}
*/
this.bufferCache_ = {};
/**
* @private
- * @type {Object.<number, WebGLShader>}
+ * @type {Object.<string, WebGLShader>}
*/
this.shaderCache_ = {};
@@ -78980,12 +63189,13 @@ ol.webgl.Context = function(canvas, gl) {
'Failed to get extension "OES_element_index_uint"');
}
- goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.LOST,
- this.handleWebGLContextLost, false, this);
- goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED,
- this.handleWebGLContextRestored, false, this);
+ ol.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.LOST,
+ this.handleWebGLContextLost, this);
+ ol.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED,
+ this.handleWebGLContextRestored, this);
};
+goog.inherits(ol.webgl.Context, ol.Disposable);
/**
@@ -78998,7 +63208,7 @@ ol.webgl.Context = function(canvas, gl) {
ol.webgl.Context.prototype.bindBuffer = function(target, buf) {
var gl = this.getGL();
var arr = buf.getArray();
- var bufferKey = goog.getUid(buf);
+ var bufferKey = String(goog.getUid(buf));
if (bufferKey in this.bufferCache_) {
var bufferCacheEntry = this.bufferCache_[bufferKey];
gl.bindBuffer(target, bufferCacheEntry.buffer);
@@ -79031,7 +63241,7 @@ ol.webgl.Context.prototype.bindBuffer = function(target, buf) {
*/
ol.webgl.Context.prototype.deleteBuffer = function(buf) {
var gl = this.getGL();
- var bufferKey = goog.getUid(buf);
+ var bufferKey = String(goog.getUid(buf));
goog.asserts.assert(bufferKey in this.bufferCache_,
'attempted to delete uncached buffer');
var bufferCacheEntry = this.bufferCache_[bufferKey];
@@ -79046,17 +63256,19 @@ ol.webgl.Context.prototype.deleteBuffer = function(buf) {
* @inheritDoc
*/
ol.webgl.Context.prototype.disposeInternal = function() {
+ ol.events.unlistenAll(this.canvas_);
var gl = this.getGL();
if (!gl.isContextLost()) {
- goog.object.forEach(this.bufferCache_, function(bufferCacheEntry) {
- gl.deleteBuffer(bufferCacheEntry.buffer);
- });
- goog.object.forEach(this.programCache_, function(program) {
- gl.deleteProgram(program);
- });
- goog.object.forEach(this.shaderCache_, function(shader) {
- gl.deleteShader(shader);
- });
+ var key;
+ for (key in this.bufferCache_) {
+ gl.deleteBuffer(this.bufferCache_[key].buffer);
+ }
+ for (key in this.programCache_) {
+ gl.deleteProgram(this.programCache_[key]);
+ }
+ for (key in this.shaderCache_) {
+ gl.deleteShader(this.shaderCache_[key]);
+ }
// delete objects for hit-detection
gl.deleteFramebuffer(this.hitDetectionFramebuffer_);
gl.deleteRenderbuffer(this.hitDetectionRenderbuffer_);
@@ -79102,7 +63314,7 @@ ol.webgl.Context.prototype.getHitDetectionFramebuffer = function() {
* @return {WebGLShader} Shader.
*/
ol.webgl.Context.prototype.getShader = function(shaderObject) {
- var shaderKey = goog.getUid(shaderObject);
+ var shaderKey = String(goog.getUid(shaderObject));
if (shaderKey in this.shaderCache_) {
return this.shaderCache_[shaderKey];
} else {
@@ -79110,16 +63322,10 @@ ol.webgl.Context.prototype.getShader = function(shaderObject) {
var shader = gl.createShader(shaderObject.getType());
gl.shaderSource(shader, shaderObject.getSource());
gl.compileShader(shader);
- if (goog.DEBUG) {
- if (!gl.getShaderParameter(shader, goog.webgl.COMPILE_STATUS) &&
- !gl.isContextLost()) {
- goog.log.error(this.logger_, gl.getShaderInfoLog(shader));
- }
- }
goog.asserts.assert(
gl.getShaderParameter(shader, goog.webgl.COMPILE_STATUS) ||
gl.isContextLost(),
- 'illegal state, shader not compiled or context lost');
+ gl.getShaderInfoLog(shader) || 'illegal state, shader not compiled or context lost');
this.shaderCache_[shaderKey] = shader;
return shader;
}
@@ -79146,16 +63352,10 @@ ol.webgl.Context.prototype.getProgram = function(
gl.attachShader(program, this.getShader(fragmentShaderObject));
gl.attachShader(program, this.getShader(vertexShaderObject));
gl.linkProgram(program);
- if (goog.DEBUG) {
- if (!gl.getProgramParameter(program, goog.webgl.LINK_STATUS) &&
- !gl.isContextLost()) {
- goog.log.error(this.logger_, gl.getProgramInfoLog(program));
- }
- }
goog.asserts.assert(
gl.getProgramParameter(program, goog.webgl.LINK_STATUS) ||
gl.isContextLost(),
- 'illegal state, shader not linked or context lost');
+ gl.getProgramInfoLog(program) || 'illegal state, shader not linked or context lost');
this.programCache_[programKey] = program;
return program;
}
@@ -79166,9 +63366,9 @@ ol.webgl.Context.prototype.getProgram = function(
* FIXME empy description for jsdoc
*/
ol.webgl.Context.prototype.handleWebGLContextLost = function() {
- goog.object.clear(this.bufferCache_);
- goog.object.clear(this.shaderCache_);
- goog.object.clear(this.programCache_);
+ ol.object.clear(this.bufferCache_);
+ ol.object.clear(this.shaderCache_);
+ ol.object.clear(this.programCache_);
this.currentProgram_ = null;
this.hitDetectionFramebuffer_ = null;
this.hitDetectionTexture_ = null;
@@ -79230,17 +63430,10 @@ ol.webgl.Context.prototype.useProgram = function(program) {
/**
- * @private
- * @type {goog.log.Logger}
- */
-ol.webgl.Context.prototype.logger_ = goog.log.getLogger('ol.webgl.Context');
-
-
-/**
* @param {WebGLRenderingContext} gl WebGL rendering context.
* @param {number=} opt_wrapS wrapS.
* @param {number=} opt_wrapT wrapT.
- * @return {WebGLTexture}
+ * @return {WebGLTexture} The texture.
* @private
*/
ol.webgl.Context.createTexture_ = function(gl, opt_wrapS, opt_wrapT) {
@@ -79268,7 +63461,7 @@ ol.webgl.Context.createTexture_ = function(gl, opt_wrapS, opt_wrapT) {
* @param {number} height Height.
* @param {number=} opt_wrapS wrapS.
* @param {number=} opt_wrapT wrapT.
- * @return {WebGLTexture}
+ * @return {WebGLTexture} The texture.
*/
ol.webgl.Context.createEmptyTexture = function(
gl, width, height, opt_wrapS, opt_wrapT) {
@@ -79286,7 +63479,7 @@ ol.webgl.Context.createEmptyTexture = function(
* @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image.
* @param {number=} opt_wrapS wrapS.
* @param {number=} opt_wrapT wrapT.
- * @return {WebGLTexture}
+ * @return {WebGLTexture} The texture.
*/
ol.webgl.Context.createTexture = function(gl, image, opt_wrapS, opt_wrapT) {
var texture = ol.webgl.Context.createTexture_(gl, opt_wrapS, opt_wrapT);
@@ -79300,10 +63493,9 @@ goog.provide('ol.render.webgl.ImageReplay');
goog.provide('ol.render.webgl.ReplayGroup');
goog.require('goog.asserts');
-goog.require('goog.functions');
-goog.require('goog.object');
goog.require('goog.vec.Mat4');
goog.require('ol.extent');
+goog.require('ol.object');
goog.require('ol.render.IReplayGroup');
goog.require('ol.render.VectorContext');
goog.require('ol.render.webgl.imagereplay.shader.Default');
@@ -79315,7 +63507,6 @@ goog.require('ol.webgl.Buffer');
goog.require('ol.webgl.Context');
-
/**
* @constructor
* @extends {ol.render.VectorContext}
@@ -79496,7 +63687,7 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) {
/**
* Start index per feature (the feature).
- * @type {Array.<ol.Feature>}
+ * @type {Array.<ol.Feature|ol.render.Feature>}
* @private
*/
this.startIndicesFeature_ = [];
@@ -79514,8 +63705,7 @@ goog.inherits(ol.render.webgl.ImageReplay, ol.render.VectorContext);
* @param {ol.webgl.Context} context WebGL context.
* @return {function()} Delete resources function.
*/
-ol.render.webgl.ImageReplay.prototype.getDeleteResourcesFunction =
- function(context) {
+ol.render.webgl.ImageReplay.prototype.getDeleteResourcesFunction = function(context) {
// We only delete our stuff here. The shaders and the program may
// be used by other ImageReplay instances (for other layers). And
// they will be deleted when disposing of the ol.webgl.Context
@@ -79546,12 +63736,6 @@ ol.render.webgl.ImageReplay.prototype.getDeleteResourcesFunction =
/**
- * @inheritDoc
- */
-ol.render.webgl.ImageReplay.prototype.drawAsync = goog.abstractMethod;
-
-
-/**
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {number} end End.
@@ -79559,8 +63743,7 @@ ol.render.webgl.ImageReplay.prototype.drawAsync = goog.abstractMethod;
* @return {number} My end.
* @private
*/
-ol.render.webgl.ImageReplay.prototype.drawCoordinates_ =
- function(flatCoordinates, offset, end, stride) {
+ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) {
goog.asserts.assert(this.anchorX_ !== undefined, 'anchorX is defined');
goog.asserts.assert(this.anchorY_ !== undefined, 'anchorY is defined');
goog.asserts.assert(this.height_ !== undefined, 'height is defined');
@@ -79671,8 +63854,7 @@ ol.render.webgl.ImageReplay.prototype.drawCoordinates_ =
/**
* @inheritDoc
*/
-ol.render.webgl.ImageReplay.prototype.drawMultiPointGeometry =
- function(multiPointGeometry, feature) {
+ol.render.webgl.ImageReplay.prototype.drawMultiPoint = function(multiPointGeometry, feature) {
this.startIndices_.push(this.indices_.length);
this.startIndicesFeature_.push(feature);
var flatCoordinates = multiPointGeometry.getFlatCoordinates();
@@ -79685,8 +63867,7 @@ ol.render.webgl.ImageReplay.prototype.drawMultiPointGeometry =
/**
* @inheritDoc
*/
-ol.render.webgl.ImageReplay.prototype.drawPointGeometry =
- function(pointGeometry, feature) {
+ol.render.webgl.ImageReplay.prototype.drawPoint = function(pointGeometry, feature) {
this.startIndices_.push(this.indices_.length);
this.startIndicesFeature_.push(feature);
var flatCoordinates = pointGeometry.getFlatCoordinates();
@@ -79765,8 +63946,7 @@ ol.render.webgl.ImageReplay.prototype.finish = function(context) {
* @param {Object.<string, WebGLTexture>} texturePerImage Texture cache.
* @param {WebGLRenderingContext} gl Gl.
*/
-ol.render.webgl.ImageReplay.prototype.createTextures_ =
- function(textures, images, texturePerImage, gl) {
+ol.render.webgl.ImageReplay.prototype.createTextures_ = function(textures, images, texturePerImage, gl) {
goog.asserts.assert(textures.length === 0,
'upon creation, textures is empty');
@@ -79798,7 +63978,7 @@ ol.render.webgl.ImageReplay.prototype.createTextures_ =
* @param {number} opacity Global opacity.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
- * @param {function(ol.Feature): T|undefined} featureCallback Feature callback.
+ * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
* this extent are checked.
@@ -79917,15 +64097,14 @@ ol.render.webgl.ImageReplay.prototype.replay = function(context,
* @param {Array.<WebGLTexture>} textures Textures.
* @param {Array.<number>} groupIndices Texture group indices.
*/
-ol.render.webgl.ImageReplay.prototype.drawReplay_ =
- function(gl, context, skippedFeaturesHash, textures, groupIndices) {
+ol.render.webgl.ImageReplay.prototype.drawReplay_ = function(gl, context, skippedFeaturesHash, textures, groupIndices) {
goog.asserts.assert(textures.length === groupIndices.length,
'number of textures and groupIndeces match');
var elementType = context.hasOESElementIndexUint ?
goog.webgl.UNSIGNED_INT : goog.webgl.UNSIGNED_SHORT;
var elementSize = context.hasOESElementIndexUint ? 4 : 2;
- if (!goog.object.isEmpty(skippedFeaturesHash)) {
+ if (!ol.object.isEmpty(skippedFeaturesHash)) {
this.drawReplaySkipping_(
gl, skippedFeaturesHash, textures, groupIndices,
elementType, elementSize);
@@ -79968,8 +64147,7 @@ ol.render.webgl.ImageReplay.prototype.drawReplay_ =
* @param {number} elementType Element type.
* @param {number} elementSize Element Size.
*/
-ol.render.webgl.ImageReplay.prototype.drawReplaySkipping_ =
- function(gl, skippedFeaturesHash, textures, groupIndices,
+ol.render.webgl.ImageReplay.prototype.drawReplaySkipping_ = function(gl, skippedFeaturesHash, textures, groupIndices,
elementType, elementSize) {
var featureIndex = 0;
@@ -80035,15 +64213,14 @@ ol.render.webgl.ImageReplay.prototype.drawElements_ = function(
* @param {ol.webgl.Context} context Context.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
- * @param {function(ol.Feature): T|undefined} featureCallback Feature callback.
+ * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
* this extent are checked.
* @return {T|undefined} Callback result.
* @template T
*/
-ol.render.webgl.ImageReplay.prototype.drawHitDetectionReplay_ =
- function(gl, context, skippedFeaturesHash, featureCallback, oneByOne,
+ol.render.webgl.ImageReplay.prototype.drawHitDetectionReplay_ = function(gl, context, skippedFeaturesHash, featureCallback, oneByOne,
opt_hitExtent) {
if (!oneByOne) {
// draw all hit-detection features in "once" (by texture group)
@@ -80063,12 +64240,11 @@ ol.render.webgl.ImageReplay.prototype.drawHitDetectionReplay_ =
* @param {ol.webgl.Context} context Context.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
- * @param {function(ol.Feature): T|undefined} featureCallback Feature callback.
+ * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
* @return {T|undefined} Callback result.
* @template T
*/
-ol.render.webgl.ImageReplay.prototype.drawHitDetectionReplayAll_ =
- function(gl, context, skippedFeaturesHash, featureCallback) {
+ol.render.webgl.ImageReplay.prototype.drawHitDetectionReplayAll_ = function(gl, context, skippedFeaturesHash, featureCallback) {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
this.drawReplay_(gl, context, skippedFeaturesHash,
this.hitDetectionTextures_, this.hitDetectionGroupIndices_);
@@ -80088,14 +64264,13 @@ ol.render.webgl.ImageReplay.prototype.drawHitDetectionReplayAll_ =
* @param {ol.webgl.Context} context Context.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
- * @param {function(ol.Feature): T|undefined} featureCallback Feature callback.
+ * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
* this extent are checked.
* @return {T|undefined} Callback result.
* @template T
*/
-ol.render.webgl.ImageReplay.prototype.drawHitDetectionReplayOneByOne_ =
- function(gl, context, skippedFeaturesHash, featureCallback,
+ol.render.webgl.ImageReplay.prototype.drawHitDetectionReplayOneByOne_ = function(gl, context, skippedFeaturesHash, featureCallback,
opt_hitExtent) {
goog.asserts.assert(this.hitDetectionTextures_.length ===
this.hitDetectionGroupIndices_.length,
@@ -80219,7 +64394,6 @@ ol.render.webgl.ImageReplay.prototype.setImageStyle = function(imageStyle) {
};
-
/**
* @constructor
* @implements {ol.render.IReplayGroup}
@@ -80263,15 +64437,21 @@ ol.render.webgl.ReplayGroup = function(
* @param {ol.webgl.Context} context WebGL context.
* @return {function()} Delete resources function.
*/
-ol.render.webgl.ReplayGroup.prototype.getDeleteResourcesFunction =
- function(context) {
+ol.render.webgl.ReplayGroup.prototype.getDeleteResourcesFunction = function(context) {
var functions = [];
var replayKey;
for (replayKey in this.replays_) {
functions.push(
this.replays_[replayKey].getDeleteResourcesFunction(context));
}
- return goog.functions.sequence.apply(null, functions);
+ return function() {
+ var length = functions.length;
+ var result;
+ for (var i = 0; i < length; i++) {
+ result = functions[i].apply(this, arguments);
+ }
+ return result;
+ };
};
@@ -80289,8 +64469,7 @@ ol.render.webgl.ReplayGroup.prototype.finish = function(context) {
/**
* @inheritDoc
*/
-ol.render.webgl.ReplayGroup.prototype.getReplay =
- function(zIndex, replayType) {
+ol.render.webgl.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
var replay = this.replays_[replayType];
if (replay === undefined) {
var constructor = ol.render.webgl.BATCH_CONSTRUCTORS_[replayType];
@@ -80308,7 +64487,7 @@ ol.render.webgl.ReplayGroup.prototype.getReplay =
* @inheritDoc
*/
ol.render.webgl.ReplayGroup.prototype.isEmpty = function() {
- return goog.object.isEmpty(this.replays_);
+ return ol.object.isEmpty(this.replays_);
};
@@ -80350,7 +64529,7 @@ ol.render.webgl.ReplayGroup.prototype.replay = function(context,
* @param {number} opacity Global opacity.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
- * @param {function(ol.Feature): T|undefined} featureCallback Feature callback.
+ * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
* this extent are checked.
@@ -80387,7 +64566,7 @@ ol.render.webgl.ReplayGroup.prototype.replayHitDetection_ = function(context,
* @param {number} opacity Global opacity.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
- * @param {function(ol.Feature): T|undefined} callback Feature callback.
+ * @param {function((ol.Feature|ol.render.Feature)): T|undefined} callback Feature callback.
* @return {T|undefined} Callback result.
* @template T
*/
@@ -80416,7 +64595,7 @@ ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
coordinate, resolution, rotation, ol.render.webgl.HIT_DETECTION_SIZE_,
pixelRatio, opacity, skippedFeaturesHash,
/**
- * @param {ol.Feature} feature Feature.
+ * @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result.
*/
function(feature) {
@@ -80457,7 +64636,7 @@ ol.render.webgl.ReplayGroup.prototype.hasFeatureAtCoordinate = function(
coordinate, resolution, rotation, ol.render.webgl.HIT_DETECTION_SIZE_,
pixelRatio, opacity, skippedFeaturesHash,
/**
- * @param {ol.Feature} feature Feature.
+ * @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {boolean} Is there a feature?
*/
function(feature) {
@@ -80490,14 +64669,14 @@ ol.render.webgl.BATCH_CONSTRUCTORS_ = {
ol.render.webgl.HIT_DETECTION_SIZE_ = [1, 1];
goog.provide('ol.render.webgl.Immediate');
-goog.require('ol.array');
+goog.require('goog.asserts');
goog.require('ol.extent');
+goog.require('ol.geom.GeometryType');
goog.require('ol.render.VectorContext');
goog.require('ol.render.webgl.ImageReplay');
goog.require('ol.render.webgl.ReplayGroup');
-
/**
* @constructor
* @extends {ol.render.VectorContext}
@@ -80510,8 +64689,7 @@ goog.require('ol.render.webgl.ReplayGroup');
* @param {number} pixelRatio Pixel ratio.
* @struct
*/
-ol.render.webgl.Immediate = function(context,
- center, resolution, rotation, size, extent, pixelRatio) {
+ol.render.webgl.Immediate = function(context, center, resolution, rotation, size, extent, pixelRatio) {
goog.base(this);
/**
@@ -80555,58 +64733,44 @@ ol.render.webgl.Immediate = function(context,
*/
this.imageStyle_ = null;
- /**
- * @private
- * @type {!Object.<string,
- * Array.<function(ol.render.webgl.Immediate)>>}
- */
- this.callbacksByZIndex_ = {};
};
goog.inherits(ol.render.webgl.Immediate, ol.render.VectorContext);
/**
- * FIXME: empty description for jsdoc
- */
-ol.render.webgl.Immediate.prototype.flush = function() {
- /** @type {Array.<number>} */
- var zs = Object.keys(this.callbacksByZIndex_).map(Number);
- zs.sort(ol.array.numberSafeCompareFunction);
- var i, ii, callbacks, j, jj;
- for (i = 0, ii = zs.length; i < ii; ++i) {
- callbacks = this.callbacksByZIndex_[zs[i].toString()];
- for (j = 0, jj = callbacks.length; j < jj; ++j) {
- callbacks[j](this);
- }
- }
-};
-
-
-/**
- * Register a function to be called for rendering at a given zIndex. The
- * function will be called asynchronously. The callback will receive a
- * reference to {@link ol.render.canvas.Immediate} context for drawing.
- * @param {number} zIndex Z index.
- * @param {function(ol.render.webgl.Immediate)} callback Callback.
+ * Set the rendering style. Note that since this is an immediate rendering API,
+ * any `zIndex` on the provided style will be ignored.
+ *
+ * @param {ol.style.Style} style The rendering style.
* @api
*/
-ol.render.webgl.Immediate.prototype.drawAsync = function(zIndex, callback) {
- var zIndexKey = zIndex.toString();
- var callbacks = this.callbacksByZIndex_[zIndexKey];
- if (callbacks !== undefined) {
- callbacks.push(callback);
- } else {
- this.callbacksByZIndex_[zIndexKey] = [callback];
- }
+ol.render.webgl.Immediate.prototype.setStyle = function(style) {
+ this.setImageStyle(style.getImage());
};
/**
- * @inheritDoc
+ * Render a geometry into the canvas. Call
+ * {@link ol.render.webgl.Immediate#setStyle} first to set the rendering style.
+ *
+ * @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render.
* @api
*/
-ol.render.webgl.Immediate.prototype.drawCircleGeometry =
- function(circleGeometry, data) {
+ol.render.webgl.Immediate.prototype.drawGeometry = function(geometry) {
+ var type = geometry.getType();
+ switch (type) {
+ case ol.geom.GeometryType.POINT:
+ this.drawPoint(/** @type {ol.geom.Point} */ (geometry), null);
+ break;
+ case ol.geom.GeometryType.MULTI_POINT:
+ this.drawMultiPoint(/** @type {ol.geom.MultiPoint} */ (geometry), null);
+ break;
+ case ol.geom.GeometryType.GEOMETRY_COLLECTION:
+ this.drawGeometryCollection(/** @type {ol.geom.GeometryCollection} */ (geometry), null);
+ break;
+ default:
+ goog.asserts.fail('Unsupported geometry type: ' + type);
+ }
};
@@ -80620,59 +64784,34 @@ ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) {
!ol.extent.intersects(this.extent_, geometry.getExtent())) {
return;
}
- var zIndex = style.getZIndex();
- if (zIndex === undefined) {
- zIndex = 0;
- }
- this.drawAsync(zIndex, function(render) {
- render.setFillStrokeStyle(style.getFill(), style.getStroke());
- render.setImageStyle(style.getImage());
- render.setTextStyle(style.getText());
- var type = geometry.getType();
- var renderGeometry = ol.render.webgl.Immediate.GEOMETRY_RENDERERS_[type];
- // Do not assert since all kinds of geometries are not handled yet.
- // In spite, render what we support.
- if (renderGeometry) {
- renderGeometry.call(render, geometry, null);
- }
- });
+ this.setStyle(style);
+ goog.asserts.assert(geometry, 'geometry must be truthy');
+ this.drawGeometry(geometry);
};
/**
* @inheritDoc
- * @api
*/
-ol.render.webgl.Immediate.prototype.drawGeometryCollectionGeometry =
- function(geometryCollectionGeometry, data) {
- var geometries = geometryCollectionGeometry.getGeometriesArray();
- var renderers = ol.render.webgl.Immediate.GEOMETRY_RENDERERS_;
+ol.render.webgl.Immediate.prototype.drawGeometryCollection = function(geometry, data) {
+ var geometries = geometry.getGeometriesArray();
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
- var geometry = geometries[i];
- var geometryRenderer = renderers[geometry.getType()];
- // Do not assert since all kinds of geometries are not handled yet.
- // In order to support hierarchies, delegate instead what we can to
- // valid renderers.
- if (geometryRenderer) {
- geometryRenderer.call(this, geometry, data);
- }
+ this.drawGeometry(geometries[i]);
}
};
/**
* @inheritDoc
- * @api
*/
-ol.render.webgl.Immediate.prototype.drawPointGeometry =
- function(pointGeometry, data) {
+ol.render.webgl.Immediate.prototype.drawPoint = function(geometry, data) {
var context = this.context_;
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
var replay = /** @type {ol.render.webgl.ImageReplay} */ (
replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
replay.setImageStyle(this.imageStyle_);
- replay.drawPointGeometry(pointGeometry, data);
+ replay.drawPoint(geometry, data);
replay.finish(context);
// default colors
var opacity = 1;
@@ -80688,34 +64827,14 @@ ol.render.webgl.Immediate.prototype.drawPointGeometry =
/**
* @inheritDoc
- * @api
- */
-ol.render.webgl.Immediate.prototype.drawLineStringGeometry =
- function(lineStringGeometry, data) {
-};
-
-
-/**
- * @inheritDoc
- * @api
- */
-ol.render.webgl.Immediate.prototype.drawMultiLineStringGeometry =
- function(multiLineStringGeometry, data) {
-};
-
-
-/**
- * @inheritDoc
- * @api
*/
-ol.render.webgl.Immediate.prototype.drawMultiPointGeometry =
- function(multiPointGeometry, data) {
+ol.render.webgl.Immediate.prototype.drawMultiPoint = function(geometry, data) {
var context = this.context_;
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
var replay = /** @type {ol.render.webgl.ImageReplay} */ (
replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
replay.setImageStyle(this.imageStyle_);
- replay.drawMultiPointGeometry(multiPointGeometry, data);
+ replay.drawMultiPoint(geometry, data);
replay.finish(context);
var opacity = 1;
var skippedFeatures = {};
@@ -80730,71 +64849,11 @@ ol.render.webgl.Immediate.prototype.drawMultiPointGeometry =
/**
* @inheritDoc
- * @api
- */
-ol.render.webgl.Immediate.prototype.drawMultiPolygonGeometry =
- function(multiPolygonGeometry, data) {
-};
-
-
-/**
- * @inheritDoc
- * @api
- */
-ol.render.webgl.Immediate.prototype.drawPolygonGeometry =
- function(polygonGeometry, data) {
-};
-
-
-/**
- * @inheritDoc
- * @api
- */
-ol.render.webgl.Immediate.prototype.drawText =
- function(flatCoordinates, offset, end, stride, geometry, data) {
-};
-
-
-/**
- * @inheritDoc
- * @api
- */
-ol.render.webgl.Immediate.prototype.setFillStrokeStyle =
- function(fillStyle, strokeStyle) {
-};
-
-
-/**
- * @inheritDoc
- * @api
*/
ol.render.webgl.Immediate.prototype.setImageStyle = function(imageStyle) {
this.imageStyle_ = imageStyle;
};
-
-/**
- * @inheritDoc
- * @api
- */
-ol.render.webgl.Immediate.prototype.setTextStyle = function(textStyle) {
-};
-
-
-/**
- * @const
- * @private
- * @type {Object.<ol.geom.GeometryType,
- * function(this: ol.render.webgl.Immediate,
- * (ol.geom.Geometry|ol.render.Feature), Object)>}
- */
-ol.render.webgl.Immediate.GEOMETRY_RENDERERS_ = {
- 'Point': ol.render.webgl.Immediate.prototype.drawPointGeometry,
- 'MultiPoint': ol.render.webgl.Immediate.prototype.drawMultiPointGeometry,
- 'GeometryCollection':
- ol.render.webgl.Immediate.prototype.drawGeometryCollectionGeometry
-};
-
// This file is automatically generated, do not edit
goog.provide('ol.renderer.webgl.map.shader.Default');
goog.provide('ol.renderer.webgl.map.shader.Default.Locations');
@@ -80804,7 +64863,6 @@ goog.provide('ol.renderer.webgl.map.shader.DefaultVertex');
goog.require('ol.webgl.shader');
-
/**
* @constructor
* @extends {ol.webgl.shader.Fragment}
@@ -80840,7 +64898,6 @@ ol.renderer.webgl.map.shader.DefaultFragment.SOURCE = goog.DEBUG ?
ol.renderer.webgl.map.shader.DefaultFragment.OPTIMIZED_SOURCE;
-
/**
* @constructor
* @extends {ol.webgl.shader.Vertex}
@@ -80876,7 +64933,6 @@ ol.renderer.webgl.map.shader.DefaultVertex.SOURCE = goog.DEBUG ?
ol.renderer.webgl.map.shader.DefaultVertex.OPTIMIZED_SOURCE;
-
/**
* @constructor
* @param {WebGLRenderingContext} gl GL.
@@ -80939,7 +64995,6 @@ goog.require('ol.webgl.Buffer');
goog.require('ol.webgl.Context');
-
/**
* @constructor
* @extends {ol.renderer.Layer}
@@ -81012,27 +65067,27 @@ goog.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer);
* @param {number} framebufferDimension Framebuffer dimension.
* @protected
*/
-ol.renderer.webgl.Layer.prototype.bindFramebuffer =
- function(frameState, framebufferDimension) {
+ol.renderer.webgl.Layer.prototype.bindFramebuffer = function(frameState, framebufferDimension) {
var gl = this.mapRenderer.getGL();
if (this.framebufferDimension === undefined ||
this.framebufferDimension != framebufferDimension) {
+ /**
+ * @param {WebGLRenderingContext} gl GL.
+ * @param {WebGLFramebuffer} framebuffer Framebuffer.
+ * @param {WebGLTexture} texture Texture.
+ */
+ var postRenderFunction = function(gl, framebuffer, texture) {
+ if (!gl.isContextLost()) {
+ gl.deleteFramebuffer(framebuffer);
+ gl.deleteTexture(texture);
+ }
+ }.bind(null, gl, this.framebuffer, this.texture);
frameState.postRenderFunctions.push(
- goog.partial(
- /**
- * @param {WebGLRenderingContext} gl GL.
- * @param {WebGLFramebuffer} framebuffer Framebuffer.
- * @param {WebGLTexture} texture Texture.
- */
- function(gl, framebuffer, texture) {
- if (!gl.isContextLost()) {
- gl.deleteFramebuffer(framebuffer);
- gl.deleteTexture(texture);
- }
- }, gl, this.framebuffer, this.texture));
+ /** @type {ol.PostRenderFunction} */ (postRenderFunction)
+ );
var texture = ol.webgl.Context.createEmptyTexture(
gl, framebufferDimension, framebufferDimension);
@@ -81055,11 +65110,10 @@ ol.renderer.webgl.Layer.prototype.bindFramebuffer =
/**
* @param {olx.FrameState} frameState Frame state.
- * @param {ol.layer.LayerState} layerState Layer state.
+ * @param {ol.LayerState} layerState Layer state.
* @param {ol.webgl.Context} context Context.
*/
-ol.renderer.webgl.Layer.prototype.composeFrame =
- function(frameState, layerState, context) {
+ol.renderer.webgl.Layer.prototype.composeFrame = function(frameState, layerState, context) {
this.dispatchComposeEvent_(
ol.render.EventType.PRECOMPOSE, context, frameState);
@@ -81113,8 +65167,7 @@ ol.renderer.webgl.Layer.prototype.composeFrame =
* @param {olx.FrameState} frameState Frame state.
* @private
*/
-ol.renderer.webgl.Layer.prototype.dispatchComposeEvent_ =
- function(type, context, frameState) {
+ol.renderer.webgl.Layer.prototype.dispatchComposeEvent_ = function(type, context, frameState) {
var layer = this.getLayer();
if (layer.hasListener(type)) {
var viewState = frameState.viewState;
@@ -81170,7 +65223,7 @@ ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = function() {
/**
* @param {olx.FrameState} frameState Frame state.
- * @param {ol.layer.LayerState} layerState Layer state.
+ * @param {ol.LayerState} layerState Layer state.
* @param {ol.webgl.Context} context Context.
* @return {boolean} whether composeFrame should be called.
*/
@@ -81179,15 +65232,13 @@ ol.renderer.webgl.Layer.prototype.prepareFrame = goog.abstractMethod;
goog.provide('ol.renderer.webgl.ImageLayer');
goog.require('goog.asserts');
-goog.require('goog.functions');
goog.require('goog.vec.Mat4');
goog.require('goog.webgl');
-goog.require('ol.Coordinate');
-goog.require('ol.Extent');
goog.require('ol.ImageBase');
goog.require('ol.ViewHint');
goog.require('ol.dom');
goog.require('ol.extent');
+goog.require('ol.functions');
goog.require('ol.layer.Image');
goog.require('ol.proj');
goog.require('ol.renderer.webgl.Layer');
@@ -81196,7 +65247,6 @@ goog.require('ol.vec.Mat4');
goog.require('ol.webgl.Context');
-
/**
* @constructor
* @extends {ol.renderer.webgl.Layer}
@@ -81252,8 +65302,7 @@ ol.renderer.webgl.ImageLayer.prototype.createTexture_ = function(image) {
/**
* @inheritDoc
*/
-ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg) {
+ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
var layer = this.getLayer();
var source = layer.getSource();
var resolution = frameState.viewState.resolution;
@@ -81275,8 +65324,7 @@ ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate =
/**
* @inheritDoc
*/
-ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
- function(frameState, layerState, context) {
+ol.renderer.webgl.ImageLayer.prototype.prepareFrame = function(frameState, layerState, context) {
var gl = this.mapRenderer.getGL();
@@ -81319,17 +65367,18 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
image = image_;
texture = this.createTexture_(image_);
if (this.texture) {
+ /**
+ * @param {WebGLRenderingContext} gl GL.
+ * @param {WebGLTexture} texture Texture.
+ */
+ var postRenderFunction = function(gl, texture) {
+ if (!gl.isContextLost()) {
+ gl.deleteTexture(texture);
+ }
+ }.bind(null, gl, this.texture);
frameState.postRenderFunctions.push(
- goog.partial(
- /**
- * @param {WebGLRenderingContext} gl GL.
- * @param {WebGLTexture} texture Texture.
- */
- function(gl, texture) {
- if (!gl.isContextLost()) {
- gl.deleteTexture(texture);
- }
- }, gl, this.texture));
+ /** @type {ol.PostRenderFunction} */ (postRenderFunction)
+ );
}
}
}
@@ -81372,8 +65421,7 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
* @param {ol.Extent} imageExtent Image extent.
* @private
*/
-ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ =
- function(canvasWidth, canvasHeight, pixelRatio,
+ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = function(canvasWidth, canvasHeight, pixelRatio,
viewCenter, viewResolution, viewRotation, imageExtent) {
var canvasExtentWidth = canvasWidth * viewResolution;
@@ -81401,10 +65449,9 @@ ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ =
/**
* @inheritDoc
*/
-ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate =
- function(coordinate, frameState) {
+ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
var hasFeature = this.forEachFeatureAtCoordinate(
- coordinate, frameState, goog.functions.TRUE, this);
+ coordinate, frameState, ol.functions.TRUE, this);
return hasFeature !== undefined;
};
@@ -81412,8 +65459,7 @@ ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate =
/**
* @inheritDoc
*/
-ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel =
- function(pixel, frameState, callback, thisArg) {
+ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
if (!this.image_ || !this.image_.getImage()) {
return undefined;
}
@@ -81425,7 +65471,7 @@ ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel =
ol.vec.Mat4.multVec2(
frameState.pixelToCoordinateMatrix, coordinate, coordinate);
var hasFeature = this.forEachFeatureAtCoordinate(
- coordinate, frameState, goog.functions.TRUE, this);
+ coordinate, frameState, ol.functions.TRUE, this);
if (hasFeature) {
return callback.call(thisArg, this.getLayer());
@@ -81472,13 +65518,12 @@ ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel =
/**
* The transformation matrix to get the pixel on the image for a
* pixel on the map.
- * @param {ol.Size} mapSize
- * @param {ol.Size} imageSize
- * @return {goog.vec.Mat4.Number}
+ * @param {ol.Size} mapSize The map size.
+ * @param {ol.Size} imageSize The image size.
+ * @return {goog.vec.Mat4.Number} The transformation matrix.
* @private
*/
-ol.renderer.webgl.ImageLayer.prototype.getHitTransformationMatrix_ =
- function(mapSize, imageSize) {
+ol.renderer.webgl.ImageLayer.prototype.getHitTransformationMatrix_ = function(mapSize, imageSize) {
// the first matrix takes a map pixel, flips the y-axis and scales to
// a range between -1 ... 1
var mapCoordMatrix = goog.vec.Mat4.createNumber();
@@ -81519,7 +65564,6 @@ goog.provide('ol.renderer.webgl.tilelayer.shader.Vertex');
goog.require('ol.webgl.shader');
-
/**
* @constructor
* @extends {ol.webgl.shader.Fragment}
@@ -81555,7 +65599,6 @@ ol.renderer.webgl.tilelayer.shader.Fragment.SOURCE = goog.DEBUG ?
ol.renderer.webgl.tilelayer.shader.Fragment.OPTIMIZED_SOURCE;
-
/**
* @constructor
* @extends {ol.webgl.shader.Vertex}
@@ -81591,7 +65634,6 @@ ol.renderer.webgl.tilelayer.shader.Vertex.SOURCE = goog.DEBUG ?
ol.renderer.webgl.tilelayer.shader.Vertex.OPTIMIZED_SOURCE;
-
/**
* @constructor
* @param {WebGLRenderingContext} gl GL.
@@ -81645,12 +65687,10 @@ goog.require('ol.renderer.webgl.tilelayer.shader.Fragment');
goog.require('ol.renderer.webgl.tilelayer.shader.Locations');
goog.require('ol.renderer.webgl.tilelayer.shader.Vertex');
goog.require('ol.size');
-goog.require('ol.tilecoord');
goog.require('ol.vec.Mat4');
goog.require('ol.webgl.Buffer');
-
/**
* @constructor
* @extends {ol.renderer.webgl.Layer}
@@ -81740,8 +65780,7 @@ ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() {
* lookup.
* @protected
*/
-ol.renderer.webgl.TileLayer.prototype.createLoadedTileFinder =
- function(source, projection, tiles) {
+ol.renderer.webgl.TileLayer.prototype.createLoadedTileFinder = function(source, projection, tiles) {
var mapRenderer = this.mapRenderer;
return (
@@ -81751,17 +65790,17 @@ ol.renderer.webgl.TileLayer.prototype.createLoadedTileFinder =
* @return {boolean} The tile range is fully loaded.
*/
function(zoom, tileRange) {
- return source.forEachLoadedTile(projection, zoom,
- tileRange, function(tile) {
- var loaded = mapRenderer.isTileTextureLoaded(tile);
- if (loaded) {
- if (!tiles[zoom]) {
- tiles[zoom] = {};
- }
- tiles[zoom][tile.tileCoord.toString()] = tile;
- }
- return loaded;
- });
+ function callback(tile) {
+ var loaded = mapRenderer.isTileTextureLoaded(tile);
+ if (loaded) {
+ if (!tiles[zoom]) {
+ tiles[zoom] = {};
+ }
+ tiles[zoom][tile.tileCoord.toString()] = tile;
+ }
+ return loaded;
+ }
+ return source.forEachLoadedTile(projection, zoom, tileRange, callback);
});
};
@@ -81778,8 +65817,7 @@ ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() {
/**
* @inheritDoc
*/
-ol.renderer.webgl.TileLayer.prototype.prepareFrame =
- function(frameState, layerState, context) {
+ol.renderer.webgl.TileLayer.prototype.prepareFrame = function(frameState, layerState, context) {
var mapRenderer = this.mapRenderer;
var gl = context.getGL();
@@ -81800,7 +65838,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
var pixelRatio = tilePixelSize[0] /
ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize_)[0];
var tilePixelResolution = tileResolution / pixelRatio;
- var tileGutter = tileSource.getGutter();
+ var tileGutter = tileSource.getGutter(projection);
var center = viewState.center;
var extent;
@@ -81898,7 +65936,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
tileState = tile.getState();
if (tileState == ol.TileState.LOADED) {
if (mapRenderer.isTileTextureLoaded(tile)) {
- tilesToDrawByZ[z][ol.tilecoord.toString(tile.tileCoord)] = tile;
+ tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
continue;
}
} else if (tileState == ol.TileState.EMPTY ||
@@ -82013,8 +66051,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
/**
* @inheritDoc
*/
-ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel =
- function(pixel, frameState, callback, thisArg) {
+ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
if (!this.framebuffer) {
return undefined;
}
@@ -82046,7 +66083,7 @@ ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel =
goog.provide('ol.renderer.webgl.VectorLayer');
goog.require('goog.asserts');
-goog.require('goog.events');
+goog.require('ol.events');
goog.require('ol.ViewHint');
goog.require('ol.extent');
goog.require('ol.layer.Vector');
@@ -82056,7 +66093,6 @@ goog.require('ol.renderer.webgl.Layer');
goog.require('ol.vec.Mat4');
-
/**
* @constructor
* @extends {ol.renderer.webgl.Layer}
@@ -82106,7 +66142,7 @@ ol.renderer.webgl.VectorLayer = function(mapRenderer, vectorLayer) {
/**
* The last layer state.
* @private
- * @type {?ol.layer.LayerState}
+ * @type {?ol.LayerState}
*/
this.layerState_ = null;
@@ -82117,8 +66153,7 @@ goog.inherits(ol.renderer.webgl.VectorLayer, ol.renderer.webgl.Layer);
/**
* @inheritDoc
*/
-ol.renderer.webgl.VectorLayer.prototype.composeFrame =
- function(frameState, layerState, context) {
+ol.renderer.webgl.VectorLayer.prototype.composeFrame = function(frameState, layerState, context) {
this.layerState_ = layerState;
var viewState = frameState.viewState;
var replayGroup = this.replayGroup_;
@@ -82149,8 +66184,7 @@ ol.renderer.webgl.VectorLayer.prototype.disposeInternal = function() {
/**
* @inheritDoc
*/
-ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg) {
+ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
if (!this.replayGroup_ || !this.layerState_) {
return undefined;
} else {
@@ -82163,9 +66197,9 @@ ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate =
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate,
context, viewState.center, viewState.resolution, viewState.rotation,
frameState.size, frameState.pixelRatio, layerState.opacity,
- layerState.managed ? frameState.skippedFeatureUids : {},
+ {},
/**
- * @param {ol.Feature} feature Feature.
+ * @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result.
*/
function(feature) {
@@ -82183,8 +66217,7 @@ ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate =
/**
* @inheritDoc
*/
-ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtCoordinate =
- function(coordinate, frameState) {
+ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
if (!this.replayGroup_ || !this.layerState_) {
return false;
} else {
@@ -82202,8 +66235,7 @@ ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtCoordinate =
/**
* @inheritDoc
*/
-ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel =
- function(pixel, frameState, callback, thisArg) {
+ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
var coordinate = pixel.slice();
ol.vec.Mat4.multVec2(
frameState.pixelToCoordinateMatrix, coordinate, coordinate);
@@ -82219,11 +66251,10 @@ ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel =
/**
* Handle changes in image style state.
- * @param {goog.events.Event} event Image style change event.
+ * @param {ol.events.Event} event Image style change event.
* @private
*/
-ol.renderer.webgl.VectorLayer.prototype.handleStyleImageChange_ =
- function(event) {
+ol.renderer.webgl.VectorLayer.prototype.handleStyleImageChange_ = function(event) {
this.renderIfReadyAndVisible();
};
@@ -82231,8 +66262,7 @@ ol.renderer.webgl.VectorLayer.prototype.handleStyleImageChange_ =
/**
* @inheritDoc
*/
-ol.renderer.webgl.VectorLayer.prototype.prepareFrame =
- function(frameState, layerState, context) {
+ol.renderer.webgl.VectorLayer.prototype.prepareFrame = function(frameState, layerState, context) {
var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector,
@@ -82288,12 +66318,11 @@ ol.renderer.webgl.VectorLayer.prototype.prepareFrame =
ol.renderer.vector.getTolerance(resolution, pixelRatio),
extent, vectorLayer.getRenderBuffer());
vectorSource.loadFeatures(extent, resolution, projection);
- var renderFeature =
- /**
- * @param {ol.Feature} feature Feature.
- * @this {ol.renderer.webgl.VectorLayer}
- */
- function(feature) {
+ /**
+ * @param {ol.Feature} feature Feature.
+ * @this {ol.renderer.webgl.VectorLayer}
+ */
+ var renderFeature = function(feature) {
var styles;
var styleFunction = feature.getStyleFunction();
if (styleFunction) {
@@ -82346,13 +66375,12 @@ ol.renderer.webgl.VectorLayer.prototype.prepareFrame =
* @param {ol.render.webgl.ReplayGroup} replayGroup Replay group.
* @return {boolean} `true` if an image is loading.
*/
-ol.renderer.webgl.VectorLayer.prototype.renderFeature =
- function(feature, resolution, pixelRatio, styles, replayGroup) {
+ol.renderer.webgl.VectorLayer.prototype.renderFeature = function(feature, resolution, pixelRatio, styles, replayGroup) {
if (!styles) {
return false;
}
var loading = false;
- if (goog.isArray(styles)) {
+ if (Array.isArray(styles)) {
for (var i = 0, ii = styles.length; i < ii; ++i) {
loading = ol.renderer.vector.renderFeature(
replayGroup, feature, styles[i],
@@ -82372,20 +66400,17 @@ ol.renderer.webgl.VectorLayer.prototype.renderFeature =
goog.provide('ol.renderer.webgl.Map');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.log');
-goog.require('goog.log.Logger');
-goog.require('goog.object');
goog.require('goog.style');
goog.require('goog.webgl');
goog.require('ol');
goog.require('ol.RendererType');
+goog.require('ol.array');
goog.require('ol.css');
goog.require('ol.dom');
+goog.require('ol.events');
+goog.require('ol.events.Event');
goog.require('ol.layer.Image');
goog.require('ol.layer.Layer');
goog.require('ol.layer.Tile');
@@ -82407,13 +66432,6 @@ goog.require('ol.webgl.WebGLContextEventType');
/**
- * @typedef {{magFilter: number, minFilter: number, texture: WebGLTexture}}
- */
-ol.renderer.webgl.TextureCacheEntry;
-
-
-
-/**
* @constructor
* @extends {ol.renderer.Map}
* @param {Element} container Container.
@@ -82477,14 +66495,14 @@ ol.renderer.webgl.Map = function(container, map) {
*/
this.context_ = new ol.webgl.Context(this.canvas_, this.gl_);
- goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.LOST,
- this.handleWebGLContextLost, false, this);
- goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED,
- this.handleWebGLContextRestored, false, this);
+ ol.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.LOST,
+ this.handleWebGLContextLost, this);
+ ol.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED,
+ this.handleWebGLContextRestored, this);
/**
* @private
- * @type {ol.structs.LRUCache.<ol.renderer.webgl.TextureCacheEntry|null>}
+ * @type {ol.structs.LRUCache.<ol.WebglTextureCacheEntry|null>}
*/
this.textureCache_ = new ol.structs.LRUCache();
@@ -82499,20 +66517,19 @@ ol.renderer.webgl.Map = function(container, map) {
* @type {ol.structs.PriorityQueue.<Array>}
*/
this.tileTextureQueue_ = new ol.structs.PriorityQueue(
- goog.bind(
- /**
- * @param {Array.<*>} element Element.
- * @return {number} Priority.
- * @this {ol.renderer.webgl.Map}
- */
- function(element) {
- var tileCenter = /** @type {ol.Coordinate} */ (element[1]);
- var tileResolution = /** @type {number} */ (element[2]);
- var deltaX = tileCenter[0] - this.focus_[0];
- var deltaY = tileCenter[1] - this.focus_[1];
- return 65536 * Math.log(tileResolution) +
- Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;
- }, this),
+ /**
+ * @param {Array.<*>} element Element.
+ * @return {number} Priority.
+ * @this {ol.renderer.webgl.Map}
+ */
+ (function(element) {
+ var tileCenter = /** @type {ol.Coordinate} */ (element[1]);
+ var tileResolution = /** @type {number} */ (element[2]);
+ var deltaX = tileCenter[0] - this.focus_[0];
+ var deltaY = tileCenter[1] - this.focus_[1];
+ return 65536 * Math.log(tileResolution) +
+ Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;
+ }).bind(this),
/**
* @param {Array.<*>} element Element.
* @return {string} Key.
@@ -82521,11 +66538,14 @@ ol.renderer.webgl.Map = function(container, map) {
return /** @type {ol.Tile} */ (element[0]).getKey();
});
- /**
- * @private
- * @type {ol.PostRenderFunction}
- */
- this.loadNextTileTexture_ = goog.bind(
+
+ /**
+ * @param {ol.Map} map Map.
+ * @param {?olx.FrameState} frameState Frame state.
+ * @return {boolean} false.
+ * @this {ol.renderer.webgl.Map}
+ */
+ this.loadNextTileTexture_ =
function(map, frameState) {
if (!this.tileTextureQueue_.isEmpty()) {
this.tileTextureQueue_.reprioritize();
@@ -82536,7 +66556,9 @@ ol.renderer.webgl.Map = function(container, map) {
this.bindTileTexture(
tile, tileSize, tileGutter, goog.webgl.LINEAR, goog.webgl.LINEAR);
}
- }, this);
+ return false;
+ }.bind(this);
+
/**
* @private
@@ -82557,8 +66579,7 @@ goog.inherits(ol.renderer.webgl.Map, ol.renderer.Map);
* @param {number} magFilter Mag filter.
* @param {number} minFilter Min filter.
*/
-ol.renderer.webgl.Map.prototype.bindTileTexture =
- function(tile, tileSize, tileGutter, magFilter, minFilter) {
+ol.renderer.webgl.Map.prototype.bindTileTexture = function(tile, tileSize, tileGutter, magFilter, minFilter) {
var gl = this.getGL();
var tileKey = tile.getKey();
if (this.textureCache_.containsKey(tileKey)) {
@@ -82640,8 +66661,7 @@ ol.renderer.webgl.Map.prototype.createLayerRenderer = function(layer) {
* @param {olx.FrameState} frameState Frame state.
* @private
*/
-ol.renderer.webgl.Map.prototype.dispatchComposeEvent_ =
- function(type, frameState) {
+ol.renderer.webgl.Map.prototype.dispatchComposeEvent_ = function(type, frameState) {
var map = this.getMap();
if (map.hasListener(type)) {
var context = this.context_;
@@ -82660,8 +66680,6 @@ ol.renderer.webgl.Map.prototype.dispatchComposeEvent_ =
var composeEvent = new ol.render.Event(type, map, vectorContext,
frameState, null, context);
map.dispatchEvent(composeEvent);
-
- vectorContext.flush();
}
};
@@ -82674,7 +66692,7 @@ ol.renderer.webgl.Map.prototype.disposeInternal = function() {
if (!gl.isContextLost()) {
this.textureCache_.forEach(
/**
- * @param {?ol.renderer.webgl.TextureCacheEntry} textureCacheEntry
+ * @param {?ol.WebglTextureCacheEntry} textureCacheEntry
* Texture cache entry.
*/
function(textureCacheEntry) {
@@ -82683,7 +66701,7 @@ ol.renderer.webgl.Map.prototype.disposeInternal = function() {
}
});
}
- goog.dispose(this.context_);
+ this.context_.dispose();
goog.base(this, 'disposeInternal');
};
@@ -82714,7 +66732,7 @@ ol.renderer.webgl.Map.prototype.expireCache_ = function(map, frameState) {
/**
- * @return {ol.webgl.Context}
+ * @return {ol.webgl.Context} The context.
*/
ol.renderer.webgl.Map.prototype.getContext = function() {
return this.context_;
@@ -82746,24 +66764,19 @@ ol.renderer.webgl.Map.prototype.getType = function() {
/**
- * @param {goog.events.Event} event Event.
+ * @param {ol.events.Event} event Event.
* @protected
*/
ol.renderer.webgl.Map.prototype.handleWebGLContextLost = function(event) {
event.preventDefault();
this.textureCache_.clear();
this.textureCacheFrameMarkerCount_ = 0;
- goog.object.forEach(this.getLayerRenderers(),
- /**
- * @param {ol.renderer.Layer} layerRenderer Layer renderer.
- * @param {string} key Key.
- * @param {Object.<string, ol.renderer.Layer>} object Object.
- */
- function(layerRenderer, key, object) {
- goog.asserts.assertInstanceof(layerRenderer, ol.renderer.webgl.Layer,
- 'renderer is an instance of ol.renderer.webgl.Layer');
- layerRenderer.handleWebGLContextLost();
- });
+
+ var renderers = this.getLayerRenderers();
+ for (var id in renderers) {
+ var renderer = /** @type {ol.renderer.webgl.Layer} */ (renderers[id]);
+ renderer.handleWebGLContextLost();
+ }
};
@@ -82802,14 +66815,6 @@ ol.renderer.webgl.Map.prototype.isTileTextureLoaded = function(tile) {
/**
- * @private
- * @type {goog.log.Logger}
- */
-ol.renderer.webgl.Map.prototype.logger_ =
- goog.log.getLogger('ol.renderer.webgl.Map');
-
-
-/**
* @inheritDoc
*/
ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
@@ -82836,10 +66841,10 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, frameState);
- /** @type {Array.<ol.layer.LayerState>} */
+ /** @type {Array.<ol.LayerState>} */
var layerStatesToDraw = [];
var layerStatesArray = frameState.layerStatesArray;
- goog.array.stableSort(layerStatesArray, ol.renderer.Map.sortByZIndex);
+ ol.array.stableSort(layerStatesArray, ol.renderer.Map.sortByZIndex);
var viewResolution = frameState.viewState.resolution;
var i, ii, layerRenderer, layerState;
@@ -82887,7 +66892,9 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
if (this.textureCache_.getCount() - this.textureCacheFrameMarkerCount_ >
ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK) {
- frameState.postRenderFunctions.push(goog.bind(this.expireCache_, this));
+ frameState.postRenderFunctions.push(
+ /** @type {ol.PostRenderFunction} */ (this.expireCache_.bind(this))
+ );
}
if (!this.tileTextureQueue_.isEmpty()) {
@@ -82906,8 +66913,7 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
/**
* @inheritDoc
*/
-ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate =
- function(coordinate, frameState, callback, thisArg,
+ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg,
layerFilter, thisArg2) {
var result;
@@ -82940,8 +66946,7 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate =
/**
* @inheritDoc
*/
-ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate =
- function(coordinate, frameState, layerFilter, thisArg) {
+ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, layerFilter, thisArg) {
var hasFeature = false;
if (this.getGL().isContextLost()) {
@@ -82973,8 +66978,7 @@ ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate =
/**
* @inheritDoc
*/
-ol.renderer.webgl.Map.prototype.forEachLayerAtPixel =
- function(pixel, frameState, callback, thisArg,
+ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg,
layerFilter, thisArg2) {
if (this.getGL().isContextLost()) {
return false;
@@ -83009,26 +67013,9 @@ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel =
goog.provide('ol.Map');
goog.provide('ol.MapProperty');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.async.AnimationDelay');
goog.require('goog.async.nextTick');
-goog.require('goog.debug.Console');
goog.require('goog.dom');
-goog.require('goog.dom.ViewportSizeMonitor');
-goog.require('goog.dom.classlist');
-goog.require('goog.events');
-goog.require('goog.events.BrowserEvent');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventType');
-goog.require('goog.events.KeyHandler');
-goog.require('goog.events.KeyHandler.EventType');
-goog.require('goog.events.MouseWheelHandler');
-goog.require('goog.events.MouseWheelHandler.EventType');
-goog.require('goog.functions');
-goog.require('goog.log');
-goog.require('goog.log.Level');
-goog.require('goog.object');
goog.require('goog.style');
goog.require('goog.vec.Mat4');
goog.require('ol.Collection');
@@ -83041,20 +67028,22 @@ goog.require('ol.MapEventType');
goog.require('ol.Object');
goog.require('ol.ObjectEvent');
goog.require('ol.ObjectEventType');
-goog.require('ol.Pixel');
-goog.require('ol.PostRenderFunction');
-goog.require('ol.PreRenderFunction');
goog.require('ol.RendererType');
-goog.require('ol.Size');
goog.require('ol.TileQueue');
goog.require('ol.View');
goog.require('ol.ViewHint');
+goog.require('ol.array');
goog.require('ol.control');
+goog.require('ol.events');
+goog.require('ol.events.Event');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
+goog.require('ol.functions');
goog.require('ol.has');
goog.require('ol.interaction');
goog.require('ol.layer.Base');
goog.require('ol.layer.Group');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.proj.common');
goog.require('ol.renderer.Map');
@@ -83063,7 +67052,6 @@ goog.require('ol.renderer.dom.Map');
goog.require('ol.renderer.webgl.Map');
goog.require('ol.size');
goog.require('ol.structs.PriorityQueue');
-goog.require('ol.tilecoord');
goog.require('ol.vec.Mat4');
@@ -83124,7 +67112,6 @@ ol.MapProperty = {
};
-
/**
* @classdesc
* The map is the core component of OpenLayers. For a map to render, a view,
@@ -83211,11 +67198,17 @@ ol.Map = function(options) {
/**
* @private
- * @type {goog.async.AnimationDelay}
+ * @type {number|undefined}
+ */
+ this.animationDelayKey_;
+
+ /**
+ * @private
*/
- this.animationDelay_ =
- new goog.async.AnimationDelay(this.renderFrame_, undefined, this);
- this.registerDisposable(this.animationDelay_);
+ this.animationDelay_ = function() {
+ this.animationDelayKey_ = undefined;
+ this.renderFrame_.call(this, Date.now());
+ }.bind(this);
/**
* @private
@@ -83250,13 +67243,13 @@ ol.Map = function(options) {
/**
* @private
- * @type {goog.events.Key}
+ * @type {?ol.events.Key}
*/
this.viewPropertyListenerKey_ = null;
/**
* @private
- * @type {Array.<goog.events.Key>}
+ * @type {Array.<ol.events.Key>}
*/
this.layerGroupPropertyListenerKeys_ = null;
@@ -83265,7 +67258,7 @@ ol.Map = function(options) {
* @type {Element}
*/
this.viewport_ = document.createElement('DIV');
- this.viewport_.className = 'ol-viewport';
+ this.viewport_.className = 'ol-viewport' + (ol.has.TOUCH ? ' ol-touch' : '');
this.viewport_.style.position = 'relative';
this.viewport_.style.overflow = 'hidden';
this.viewport_.style.width = '100%';
@@ -83273,13 +67266,10 @@ ol.Map = function(options) {
// prevent page zoom on IE >= 10 browsers
this.viewport_.style.msTouchAction = 'none';
this.viewport_.style.touchAction = 'none';
- if (ol.has.TOUCH) {
- goog.dom.classlist.add(this.viewport_, 'ol-touch');
- }
/**
* @private
- * @type {Element}
+ * @type {!Element}
*/
this.overlayContainer_ = document.createElement('DIV');
this.overlayContainer_.className = 'ol-overlaycontainer';
@@ -83287,26 +67277,35 @@ ol.Map = function(options) {
/**
* @private
- * @type {Element}
+ * @type {!Element}
*/
this.overlayContainerStopEvent_ = document.createElement('DIV');
this.overlayContainerStopEvent_.className = 'ol-overlaycontainer-stopevent';
- goog.events.listen(this.overlayContainerStopEvent_, [
- goog.events.EventType.CLICK,
- goog.events.EventType.DBLCLICK,
- goog.events.EventType.MOUSEDOWN,
- goog.events.EventType.TOUCHSTART,
- goog.events.EventType.MSPOINTERDOWN,
+ var overlayEvents = [
+ ol.events.EventType.CLICK,
+ ol.events.EventType.DBLCLICK,
+ ol.events.EventType.MOUSEDOWN,
+ ol.events.EventType.TOUCHSTART,
+ ol.events.EventType.MSPOINTERDOWN,
ol.MapBrowserEvent.EventType.POINTERDOWN,
- goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel'
- ], goog.events.Event.stopPropagation);
+ ol.events.EventType.MOUSEWHEEL,
+ ol.events.EventType.WHEEL
+ ];
+ for (var i = 0, ii = overlayEvents.length; i < ii; ++i) {
+ ol.events.listen(this.overlayContainerStopEvent_, overlayEvents[i],
+ ol.events.Event.stopPropagation);
+ }
this.viewport_.appendChild(this.overlayContainerStopEvent_);
- var mapBrowserEventHandler = new ol.MapBrowserEventHandler(this);
- goog.events.listen(mapBrowserEventHandler,
- goog.object.getValues(ol.MapBrowserEvent.EventType),
- this.handleMapBrowserEvent, false, this);
- this.registerDisposable(mapBrowserEventHandler);
+ /**
+ * @private
+ * @type {ol.MapBrowserEventHandler}
+ */
+ this.mapBrowserEventHandler_ = new ol.MapBrowserEventHandler(this);
+ for (var key in ol.MapBrowserEvent.EventType) {
+ ol.events.listen(this.mapBrowserEventHandler_, ol.MapBrowserEvent.EventType[key],
+ this.handleMapBrowserEvent, this);
+ }
/**
* @private
@@ -83316,18 +67315,14 @@ ol.Map = function(options) {
/**
* @private
- * @type {goog.events.KeyHandler}
+ * @type {Array.<ol.events.Key>}
*/
- this.keyHandler_ = new goog.events.KeyHandler();
- goog.events.listen(this.keyHandler_, goog.events.KeyHandler.EventType.KEY,
- this.handleBrowserEvent, false, this);
- this.registerDisposable(this.keyHandler_);
+ this.keyHandlerKeys_ = null;
- var mouseWheelHandler = new goog.events.MouseWheelHandler(this.viewport_);
- goog.events.listen(mouseWheelHandler,
- goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
- this.handleBrowserEvent, false, this);
- this.registerDisposable(mouseWheelHandler);
+ ol.events.listen(this.viewport_, ol.events.EventType.WHEEL,
+ this.handleBrowserEvent, this);
+ ol.events.listen(this.viewport_, ol.events.EventType.MOUSEWHEEL,
+ this.handleBrowserEvent, this);
/**
* @type {ol.Collection.<ol.control.Control>}
@@ -83358,22 +67353,13 @@ ol.Map = function(options) {
* @type {ol.renderer.Map}
* @private
*/
- this.renderer_ =
- new optionsInternal.rendererConstructor(this.viewport_, this);
- this.registerDisposable(this.renderer_);
-
- /**
- * @type {goog.dom.ViewportSizeMonitor}
- * @private
- */
- this.viewportSizeMonitor_ = new goog.dom.ViewportSizeMonitor();
- this.registerDisposable(this.viewportSizeMonitor_);
+ this.renderer_ = new optionsInternal.rendererConstructor(this.viewport_, this);
/**
- * @type {goog.events.Key}
+ * @type {function(Event)|undefined}
* @private
*/
- this.viewportResizeListenerKey_ = null;
+ this.handleResize_;
/**
* @private
@@ -83398,8 +67384,8 @@ ol.Map = function(options) {
* @type {ol.TileQueue}
*/
this.tileQueue_ = new ol.TileQueue(
- goog.bind(this.getTilePriority, this),
- goog.bind(this.handleTileChange_, this));
+ this.getTilePriority.bind(this),
+ this.handleTileChange_.bind(this));
/**
* Uids of features to skip at rendering time.
@@ -83408,15 +67394,15 @@ ol.Map = function(options) {
*/
this.skippedFeatureUids_ = {};
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.MapProperty.LAYERGROUP),
- this.handleLayerGroupChanged_, false, this);
- goog.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.VIEW),
- this.handleViewChanged_, false, this);
- goog.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.SIZE),
- this.handleSizeChanged_, false, this);
- goog.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.TARGET),
- this.handleTargetChanged_, false, this);
+ this.handleLayerGroupChanged_, this);
+ ol.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.VIEW),
+ this.handleViewChanged_, this);
+ ol.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.SIZE),
+ this.handleSizeChanged_, this);
+ ol.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.TARGET),
+ this.handleTargetChanged_, this);
// setProperties will trigger the rendering of the map if the map
// is "defined" already.
@@ -83431,21 +67417,21 @@ ol.Map = function(options) {
control.setMap(this);
}, this);
- goog.events.listen(this.controls_, ol.CollectionEventType.ADD,
+ ol.events.listen(this.controls_, ol.CollectionEventType.ADD,
/**
* @param {ol.CollectionEvent} event Collection event.
*/
function(event) {
event.element.setMap(this);
- }, false, this);
+ }, this);
- goog.events.listen(this.controls_, ol.CollectionEventType.REMOVE,
+ ol.events.listen(this.controls_, ol.CollectionEventType.REMOVE,
/**
* @param {ol.CollectionEvent} event Collection event.
*/
function(event) {
event.element.setMap(null);
- }, false, this);
+ }, this);
this.interactions_.forEach(
/**
@@ -83456,33 +67442,33 @@ ol.Map = function(options) {
interaction.setMap(this);
}, this);
- goog.events.listen(this.interactions_, ol.CollectionEventType.ADD,
+ ol.events.listen(this.interactions_, ol.CollectionEventType.ADD,
/**
* @param {ol.CollectionEvent} event Collection event.
*/
function(event) {
event.element.setMap(this);
- }, false, this);
+ }, this);
- goog.events.listen(this.interactions_, ol.CollectionEventType.REMOVE,
+ ol.events.listen(this.interactions_, ol.CollectionEventType.REMOVE,
/**
* @param {ol.CollectionEvent} event Collection event.
*/
function(event) {
event.element.setMap(null);
- }, false, this);
+ }, this);
this.overlays_.forEach(this.addOverlayInternal_, this);
- goog.events.listen(this.overlays_, ol.CollectionEventType.ADD,
+ ol.events.listen(this.overlays_, ol.CollectionEventType.ADD,
/**
* @param {ol.CollectionEvent} event Collection event.
*/
function(event) {
this.addOverlayInternal_(/** @type {ol.Overlay} */ (event.element));
- }, false, this);
+ }, this);
- goog.events.listen(this.overlays_, ol.CollectionEventType.REMOVE,
+ ol.events.listen(this.overlays_, ol.CollectionEventType.REMOVE,
/**
* @param {ol.CollectionEvent} event Collection event.
*/
@@ -83492,7 +67478,7 @@ ol.Map = function(options) {
delete this.overlayIdIndex_[id.toString()];
}
event.element.setMap(null);
- }, false, this);
+ }, this);
};
goog.inherits(ol.Map, ol.Object);
@@ -83580,7 +67566,7 @@ ol.Map.prototype.beforeRender = function(var_args) {
* @return {boolean} Whether the preRenderFunction has been found and removed.
*/
ol.Map.prototype.removePreRenderFunction = function(preRenderFunction) {
- return goog.array.remove(this.preRenderFunctions_, preRenderFunction);
+ return ol.array.remove(this.preRenderFunctions_, preRenderFunction);
};
@@ -83589,7 +67575,22 @@ ol.Map.prototype.removePreRenderFunction = function(preRenderFunction) {
* @inheritDoc
*/
ol.Map.prototype.disposeInternal = function() {
- goog.dom.removeNode(this.viewport_);
+ this.mapBrowserEventHandler_.dispose();
+ this.renderer_.dispose();
+ ol.events.unlisten(this.viewport_, ol.events.EventType.WHEEL,
+ this.handleBrowserEvent, this);
+ ol.events.unlisten(this.viewport_, ol.events.EventType.MOUSEWHEEL,
+ this.handleBrowserEvent, this);
+ if (this.handleResize_ !== undefined) {
+ ol.global.removeEventListener(ol.events.EventType.RESIZE,
+ this.handleResize_, false);
+ this.handleResize_ = undefined;
+ }
+ if (this.animationDelayKey_) {
+ ol.global.cancelAnimationFrame(this.animationDelayKey_);
+ this.animationDelayKey_ = undefined;
+ }
+ this.setTarget(null);
goog.base(this, 'disposeInternal');
};
@@ -83620,15 +67621,14 @@ ol.Map.prototype.disposeInternal = function() {
* @template S,T,U
* @api stable
*/
-ol.Map.prototype.forEachFeatureAtPixel =
- function(pixel, callback, opt_this, opt_layerFilter, opt_this2) {
+ol.Map.prototype.forEachFeatureAtPixel = function(pixel, callback, opt_this, opt_layerFilter, opt_this2) {
if (!this.frameState_) {
return;
}
var coordinate = this.getCoordinateFromPixel(pixel);
var thisArg = opt_this !== undefined ? opt_this : null;
var layerFilter = opt_layerFilter !== undefined ?
- opt_layerFilter : goog.functions.TRUE;
+ opt_layerFilter : ol.functions.TRUE;
var thisArg2 = opt_this2 !== undefined ? opt_this2 : null;
return this.renderer_.forEachFeatureAtCoordinate(
coordinate, this.frameState_, callback, thisArg,
@@ -83658,14 +67658,13 @@ ol.Map.prototype.forEachFeatureAtPixel =
* @template S,T,U
* @api stable
*/
-ol.Map.prototype.forEachLayerAtPixel =
- function(pixel, callback, opt_this, opt_layerFilter, opt_this2) {
+ol.Map.prototype.forEachLayerAtPixel = function(pixel, callback, opt_this, opt_layerFilter, opt_this2) {
if (!this.frameState_) {
return;
}
var thisArg = opt_this !== undefined ? opt_this : null;
var layerFilter = opt_layerFilter !== undefined ?
- opt_layerFilter : goog.functions.TRUE;
+ opt_layerFilter : ol.functions.TRUE;
var thisArg2 = opt_this2 !== undefined ? opt_this2 : null;
return this.renderer_.forEachLayerAtPixel(
pixel, this.frameState_, callback, thisArg,
@@ -83688,14 +67687,13 @@ ol.Map.prototype.forEachLayerAtPixel =
* @template U
* @api
*/
-ol.Map.prototype.hasFeatureAtPixel =
- function(pixel, opt_layerFilter, opt_this) {
+ol.Map.prototype.hasFeatureAtPixel = function(pixel, opt_layerFilter, opt_this) {
if (!this.frameState_) {
return false;
}
var coordinate = this.getCoordinateFromPixel(pixel);
var layerFilter = opt_layerFilter !== undefined ?
- opt_layerFilter : goog.functions.TRUE;
+ opt_layerFilter : ol.functions.TRUE;
var thisArg = opt_this !== undefined ? opt_this : null;
return this.renderer_.hasFeatureAtCoordinate(
coordinate, this.frameState_, layerFilter, thisArg);
@@ -83720,8 +67718,12 @@ ol.Map.prototype.getEventCoordinate = function(event) {
* @api stable
*/
ol.Map.prototype.getEventPixel = function(event) {
- var eventPosition = goog.style.getRelativePosition(event, this.viewport_);
- return [eventPosition.x, eventPosition.y];
+ var viewportPosition = this.viewport_.getBoundingClientRect();
+ var eventPosition = event.changedTouches ? event.changedTouches[0] : event;
+ return [
+ eventPosition.clientX - viewportPosition.left,
+ eventPosition.clientY - viewportPosition.top
+ ];
};
@@ -83907,7 +67909,7 @@ ol.Map.prototype.getViewport = function() {
* this container will let mousedown and touchstart events through to the map,
* so clicks and gestures on an overlay will trigger {@link ol.MapBrowserEvent}
* events.
- * @return {Element} The map's overlay container.
+ * @return {!Element} The map's overlay container.
*/
ol.Map.prototype.getOverlayContainer = function() {
return this.overlayContainer_;
@@ -83919,7 +67921,7 @@ ol.Map.prototype.getOverlayContainer = function() {
* event propagation. Elements added to this container won't let mousedown and
* touchstart events through to the map, so clicks and gestures on an overlay
* don't trigger any {@link ol.MapBrowserEvent}.
- * @return {Element} The map's overlay container that stops events.
+ * @return {!Element} The map's overlay container that stops events.
*/
ol.Map.prototype.getOverlayContainerStopEvent = function() {
return this.overlayContainerStopEvent_;
@@ -83933,15 +67935,14 @@ ol.Map.prototype.getOverlayContainerStopEvent = function() {
* @param {number} tileResolution Tile resolution.
* @return {number} Tile priority.
*/
-ol.Map.prototype.getTilePriority =
- function(tile, tileSourceKey, tileCenter, tileResolution) {
+ol.Map.prototype.getTilePriority = function(tile, tileSourceKey, tileCenter, tileResolution) {
// Filter out tiles at higher zoom levels than the current zoom level, or that
// are outside the visible extent.
var frameState = this.frameState_;
if (!frameState || !(tileSourceKey in frameState.wantedTiles)) {
return ol.structs.PriorityQueue.DROP;
}
- var coordKey = ol.tilecoord.toString(tile.tileCoord);
+ var coordKey = tile.tileCoord.toString();
if (!frameState.wantedTiles[tileSourceKey][coordKey]) {
return ol.structs.PriorityQueue.DROP;
}
@@ -83959,7 +67960,7 @@ ol.Map.prototype.getTilePriority =
/**
- * @param {goog.events.BrowserEvent} browserEvent Browser event.
+ * @param {Event} browserEvent Browser event.
* @param {string=} opt_type Type.
*/
ol.Map.prototype.handleBrowserEvent = function(browserEvent, opt_type) {
@@ -84020,7 +68021,6 @@ ol.Map.prototype.handlePostRender = function() {
if (!tileQueue.isEmpty()) {
var maxTotalLoading = 16;
var maxNewLoads = maxTotalLoading;
- var tileSourceCount = 0;
if (frameState) {
var hints = frameState.viewHints;
if (hints[ol.ViewHint.ANIMATING]) {
@@ -84031,10 +68031,7 @@ ol.Map.prototype.handlePostRender = function() {
maxTotalLoading = this.loadTilesWhileInteracting_ ? 8 : 0;
maxNewLoads = 2;
}
- tileSourceCount = goog.object.getCount(frameState.wantedTiles);
}
- maxTotalLoading *= tileSourceCount;
- maxNewLoads *= tileSourceCount;
if (tileQueue.getTilesLoading() < maxTotalLoading) {
tileQueue.reprioritize(); // FIXME only call if view has changed
tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);
@@ -84067,27 +68064,43 @@ ol.Map.prototype.handleTargetChanged_ = function() {
// If it's not now an Element we remove the viewport from the DOM.
// If it's an Element we append the viewport element to it.
- var targetElement = this.getTargetElement();
+ var targetElement;
+ if (this.getTarget()) {
+ targetElement = this.getTargetElement();
+ goog.asserts.assert(targetElement !== null,
+ 'expects a non-null value for targetElement');
+ }
- this.keyHandler_.detach();
+ if (this.keyHandlerKeys_) {
+ for (var i = 0, ii = this.keyHandlerKeys_.length; i < ii; ++i) {
+ ol.events.unlistenByKey(this.keyHandlerKeys_[i]);
+ }
+ this.keyHandlerKeys_ = null;
+ }
if (!targetElement) {
goog.dom.removeNode(this.viewport_);
- if (this.viewportResizeListenerKey_) {
- goog.events.unlistenByKey(this.viewportResizeListenerKey_);
- this.viewportResizeListenerKey_ = null;
+ if (this.handleResize_ !== undefined) {
+ ol.global.removeEventListener(ol.events.EventType.RESIZE,
+ this.handleResize_, false);
+ this.handleResize_ = undefined;
}
} else {
targetElement.appendChild(this.viewport_);
var keyboardEventTarget = !this.keyboardEventTarget_ ?
targetElement : this.keyboardEventTarget_;
- this.keyHandler_.attach(keyboardEventTarget);
+ this.keyHandlerKeys_ = [
+ ol.events.listen(keyboardEventTarget, ol.events.EventType.KEYDOWN,
+ this.handleBrowserEvent, this),
+ ol.events.listen(keyboardEventTarget, ol.events.EventType.KEYPRESS,
+ this.handleBrowserEvent, this)
+ ];
- if (!this.viewportResizeListenerKey_) {
- this.viewportResizeListenerKey_ = goog.events.listen(
- this.viewportSizeMonitor_, goog.events.EventType.RESIZE,
- this.updateSize, false, this);
+ if (!this.handleResize_) {
+ this.handleResize_ = this.updateSize.bind(this);
+ ol.global.addEventListener(ol.events.EventType.RESIZE,
+ this.handleResize_, false);
}
}
@@ -84118,25 +68131,25 @@ ol.Map.prototype.handleViewPropertyChanged_ = function() {
*/
ol.Map.prototype.handleViewChanged_ = function() {
if (this.viewPropertyListenerKey_) {
- goog.events.unlistenByKey(this.viewPropertyListenerKey_);
+ ol.events.unlistenByKey(this.viewPropertyListenerKey_);
this.viewPropertyListenerKey_ = null;
}
var view = this.getView();
if (view) {
- this.viewPropertyListenerKey_ = goog.events.listen(
+ this.viewPropertyListenerKey_ = ol.events.listen(
view, ol.ObjectEventType.PROPERTYCHANGE,
- this.handleViewPropertyChanged_, false, this);
+ this.handleViewPropertyChanged_, this);
}
this.render();
};
/**
- * @param {goog.events.Event} event Event.
+ * @param {ol.events.Event} event Event.
* @private
*/
ol.Map.prototype.handleLayerGroupMemberChanged_ = function(event) {
- goog.asserts.assertInstanceof(event, goog.events.Event,
+ goog.asserts.assertInstanceof(event, ol.events.Event,
'event should be an Event');
this.render();
};
@@ -84158,18 +68171,18 @@ ol.Map.prototype.handleLayerGroupPropertyChanged_ = function(event) {
*/
ol.Map.prototype.handleLayerGroupChanged_ = function() {
if (this.layerGroupPropertyListenerKeys_) {
- this.layerGroupPropertyListenerKeys_.forEach(goog.events.unlistenByKey);
+ this.layerGroupPropertyListenerKeys_.forEach(ol.events.unlistenByKey);
this.layerGroupPropertyListenerKeys_ = null;
}
var layerGroup = this.getLayerGroup();
if (layerGroup) {
this.layerGroupPropertyListenerKeys_ = [
- goog.events.listen(
+ ol.events.listen(
layerGroup, ol.ObjectEventType.PROPERTYCHANGE,
- this.handleLayerGroupPropertyChanged_, false, this),
- goog.events.listen(
- layerGroup, goog.events.EventType.CHANGE,
- this.handleLayerGroupMemberChanged_, false, this)
+ this.handleLayerGroupPropertyChanged_, this),
+ ol.events.listen(
+ layerGroup, ol.events.EventType.CHANGE,
+ this.handleLayerGroupMemberChanged_, this)
];
}
this.render();
@@ -84177,31 +68190,6 @@ ol.Map.prototype.handleLayerGroupChanged_ = function() {
/**
- * Returns `true` if the map is defined, `false` otherwise. The map is defined
- * if it is contained in `document`, visible, has non-zero height and width, and
- * has a defined view.
- * @return {boolean} Is defined.
- */
-ol.Map.prototype.isDef = function() {
- if (!goog.dom.contains(document, this.viewport_)) {
- return false;
- }
- if (!goog.style.isElementShown(this.viewport_)) {
- return false;
- }
- var size = this.getSize();
- if (!size || size[0] <= 0 || size[1] <= 0) {
- return false;
- }
- var view = this.getView();
- if (!view || !view.isDef()) {
- return false;
- }
- return true;
-};
-
-
-/**
* @return {boolean} Is rendered.
*/
ol.Map.prototype.isRendered = function() {
@@ -84214,7 +68202,10 @@ ol.Map.prototype.isRendered = function() {
* @api stable
*/
ol.Map.prototype.renderSync = function() {
- this.animationDelay_.fire();
+ if (this.animationDelayKey_) {
+ ol.global.cancelAnimationFrame(this.animationDelayKey_);
+ }
+ this.animationDelay_();
};
@@ -84223,8 +68214,9 @@ ol.Map.prototype.renderSync = function() {
* @api stable
*/
ol.Map.prototype.render = function() {
- if (!this.animationDelay_.isActive()) {
- this.animationDelay_.start();
+ if (this.animationDelayKey_ === undefined) {
+ this.animationDelayKey_ = ol.global.requestAnimationFrame(
+ this.animationDelay_);
}
};
@@ -84295,11 +68287,11 @@ ol.Map.prototype.renderFrame_ = function(time) {
var size = this.getSize();
var view = this.getView();
+ var extent = ol.extent.createEmpty();
/** @type {?olx.FrameState} */
var frameState = null;
- if (size !== undefined && ol.size.hasArea(size) &&
- view && view.isDef()) {
- var viewHints = view.getHints();
+ if (size !== undefined && ol.size.hasArea(size) && view && view.isDef()) {
+ var viewHints = view.getHints(this.frameState_ ? this.frameState_.viewHints : undefined);
var layerStatesArray = this.getLayerGroup().getLayerStatesArray();
var layerStates = {};
for (i = 0, ii = layerStatesArray.length; i < ii; ++i) {
@@ -84310,12 +68302,12 @@ ol.Map.prototype.renderFrame_ = function(time) {
animate: false,
attributions: {},
coordinateToPixelMatrix: this.coordinateToPixelMatrix_,
- extent: null,
+ extent: extent,
focus: !this.focus_ ? viewState.center : this.focus_,
index: this.frameIndex_++,
layerStates: layerStates,
layerStatesArray: layerStatesArray,
- logos: goog.object.clone(this.logos_),
+ logos: ol.object.assign({}, this.logos_),
pixelRatio: this.pixelRatio_,
pixelToCoordinateMatrix: this.pixelToCoordinateMatrix_,
postRenderFunctions: [],
@@ -84342,7 +68334,7 @@ ol.Map.prototype.renderFrame_ = function(time) {
preRenderFunctions.length = n;
frameState.extent = ol.extent.getForViewAndSize(viewState.center,
- viewState.resolution, viewState.rotation, frameState.size);
+ viewState.resolution, viewState.rotation, frameState.size, extent);
}
this.frameState_ = frameState;
@@ -84459,19 +68451,6 @@ ol.Map.prototype.unskipFeature = function(feature) {
/**
- * @typedef {{controls: ol.Collection.<ol.control.Control>,
- * interactions: ol.Collection.<ol.interaction.Interaction>,
- * keyboardEventTarget: (Element|Document),
- * logos: Object.<string, string>,
- * overlays: ol.Collection.<ol.Overlay>,
- * rendererConstructor:
- * function(new: ol.renderer.Map, Element, ol.Map),
- * values: Object.<string, *>}}
- */
-ol.MapOptionsInternal;
-
-
-/**
* @param {olx.MapOptions} options Map options.
* @return {ol.MapOptionsInternal} Internal map options.
*/
@@ -84484,7 +68463,7 @@ ol.Map.createOptionsInternal = function(options) {
if (options.keyboardEventTarget !== undefined) {
// cannot use goog.dom.getElement because its argument cannot be
// of type Document
- keyboardEventTarget = goog.isString(options.keyboardEventTarget) ?
+ keyboardEventTarget = typeof options.keyboardEventTarget === 'string' ?
document.getElementById(options.keyboardEventTarget) :
options.keyboardEventTarget;
}
@@ -84496,12 +68475,14 @@ ol.Map.createOptionsInternal = function(options) {
var logos = {};
if (options.logo === undefined ||
- (goog.isBoolean(options.logo) && options.logo)) {
+ (typeof options.logo === 'boolean' && options.logo)) {
logos[ol.OL3_LOGO_URL] = ol.OL3_URL;
} else {
var logo = options.logo;
- if (goog.isString(logo)) {
+ if (typeof logo === 'string') {
logos[logo] = '';
+ } else if (logo instanceof HTMLElement) {
+ logos[goog.getUid(logo).toString()] = logo;
} else if (goog.isObject(logo)) {
goog.asserts.assertString(logo.href, 'logo.href should be a string');
goog.asserts.assertString(logo.src, 'logo.src should be a string');
@@ -84528,9 +68509,9 @@ ol.Map.createOptionsInternal = function(options) {
*/
var rendererTypes;
if (options.renderer !== undefined) {
- if (goog.isArray(options.renderer)) {
+ if (Array.isArray(options.renderer)) {
rendererTypes = options.renderer;
- } else if (goog.isString(options.renderer)) {
+ } else if (typeof options.renderer === 'string') {
rendererTypes = [options.renderer];
} else {
goog.asserts.fail('Incorrect format for renderer option');
@@ -84563,7 +68544,7 @@ ol.Map.createOptionsInternal = function(options) {
var controls;
if (options.controls !== undefined) {
- if (goog.isArray(options.controls)) {
+ if (Array.isArray(options.controls)) {
controls = new ol.Collection(options.controls.slice());
} else {
goog.asserts.assertInstanceof(options.controls, ol.Collection,
@@ -84576,7 +68557,7 @@ ol.Map.createOptionsInternal = function(options) {
var interactions;
if (options.interactions !== undefined) {
- if (goog.isArray(options.interactions)) {
+ if (Array.isArray(options.interactions)) {
interactions = new ol.Collection(options.interactions.slice());
} else {
goog.asserts.assertInstanceof(options.interactions, ol.Collection,
@@ -84589,7 +68570,7 @@ ol.Map.createOptionsInternal = function(options) {
var overlays;
if (options.overlays !== undefined) {
- if (goog.isArray(options.overlays)) {
+ if (Array.isArray(options.overlays)) {
overlays = new ol.Collection(options.overlays.slice());
} else {
goog.asserts.assertInstanceof(options.overlays, ol.Collection,
@@ -84615,24 +68596,14 @@ ol.Map.createOptionsInternal = function(options) {
ol.proj.common.add();
-
-if (goog.DEBUG) {
- (function() {
- goog.debug.Console.autoInstall();
- var logger = goog.log.getLogger('ol');
- logger.setLevel(goog.log.Level.FINEST);
- })();
-}
-
goog.provide('ol.Overlay');
goog.provide('ol.OverlayPositioning');
goog.provide('ol.OverlayProperty');
goog.require('goog.asserts');
goog.require('goog.dom');
-goog.require('goog.events');
+goog.require('ol.events');
goog.require('goog.style');
-goog.require('ol.Coordinate');
goog.require('ol.Map');
goog.require('ol.MapEventType');
goog.require('ol.Object');
@@ -84673,7 +68644,6 @@ ol.OverlayPositioning = {
};
-
/**
* @classdesc
* An element to be displayed over the map and attached to a single map
@@ -84764,29 +68734,29 @@ ol.Overlay = function(options) {
/**
* @private
- * @type {goog.events.Key}
+ * @type {?ol.events.Key}
*/
this.mapPostrenderListenerKey_ = null;
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.OverlayProperty.ELEMENT),
- this.handleElementChanged, false, this);
+ this.handleElementChanged, this);
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.OverlayProperty.MAP),
- this.handleMapChanged, false, this);
+ this.handleMapChanged, this);
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.OverlayProperty.OFFSET),
- this.handleOffsetChanged, false, this);
+ this.handleOffsetChanged, this);
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.OverlayProperty.POSITION),
- this.handlePositionChanged, false, this);
+ this.handlePositionChanged, this);
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.OverlayProperty.POSITIONING),
- this.handlePositioningChanged, false, this);
+ this.handlePositioningChanged, this);
if (options.element !== undefined) {
this.setElement(options.element);
@@ -84896,19 +68866,18 @@ ol.Overlay.prototype.handleElementChanged = function() {
ol.Overlay.prototype.handleMapChanged = function() {
if (this.mapPostrenderListenerKey_) {
goog.dom.removeNode(this.element_);
- goog.events.unlistenByKey(this.mapPostrenderListenerKey_);
+ ol.events.unlistenByKey(this.mapPostrenderListenerKey_);
this.mapPostrenderListenerKey_ = null;
}
var map = this.getMap();
if (map) {
- this.mapPostrenderListenerKey_ = goog.events.listen(map,
- ol.MapEventType.POSTRENDER, this.render, false, this);
+ this.mapPostrenderListenerKey_ = ol.events.listen(map,
+ ol.MapEventType.POSTRENDER, this.render, this);
this.updatePixelPosition();
var container = this.stopEvent_ ?
map.getOverlayContainerStopEvent() : map.getOverlayContainer();
if (this.insertFirst_) {
- goog.dom.insertChildAt(/** @type {!Element} */ (
- container), this.element_, 0);
+ goog.dom.insertChildAt(container, this.element_, 0);
} else {
container.appendChild(this.element_);
}
@@ -85063,7 +69032,7 @@ ol.Overlay.prototype.panIntoView_ = function() {
* Get the extent of an element relative to the document
* @param {Element|undefined} element The element.
* @param {ol.Size|undefined} size The size of the element.
- * @return {ol.Extent}
+ * @return {ol.Extent} The extent.
* @private
*/
ol.Overlay.prototype.getRect_ = function(element, size) {
@@ -85094,7 +69063,7 @@ ol.Overlay.prototype.setPositioning = function(positioning) {
/**
* Modify the visibility of the element.
- * @param {boolean} visible
+ * @param {boolean} visible Element visibility.
* @protected
*/
ol.Overlay.prototype.setVisible = function(visible) {
@@ -85124,8 +69093,8 @@ ol.Overlay.prototype.updatePixelPosition = function() {
/**
- * @param {ol.Pixel} pixel
- * @param {ol.Size|undefined} mapSize
+ * @param {ol.Pixel} pixel The pixel location.
+ * @param {ol.Size|undefined} mapSize The map size.
* @protected
*/
ol.Overlay.prototype.updateRenderedPosition = function(pixel, mapSize) {
@@ -85133,7 +69102,7 @@ ol.Overlay.prototype.updateRenderedPosition = function(pixel, mapSize) {
goog.asserts.assert(mapSize !== undefined, 'mapSize should be defined');
var style = this.element_.style;
var offset = this.getOffset();
- goog.asserts.assert(goog.isArray(offset), 'offset should be an array');
+ goog.asserts.assert(Array.isArray(offset), 'offset should be an array');
var positioning = this.getPositioning();
goog.asserts.assert(positioning !== undefined,
@@ -85197,11 +69166,8 @@ goog.provide('ol.control.OverviewMap');
goog.require('goog.asserts');
goog.require('goog.dom');
-goog.require('goog.dom.classlist');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.math.Size');
-goog.require('goog.style');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol');
goog.require('ol.Collection');
goog.require('ol.Map');
@@ -85218,7 +69184,6 @@ goog.require('ol.css');
goog.require('ol.extent');
-
/**
* Create a new control with a map acting as an overview map for an other
* defined map.
@@ -85248,27 +69213,27 @@ ol.control.OverviewMap = function(opt_options) {
this.collapsed_ = false;
}
- var className = options.className ? options.className : 'ol-overviewmap';
+ var className = options.className !== undefined ? options.className : 'ol-overviewmap';
- var tipLabel = options.tipLabel ? options.tipLabel : 'Overview map';
+ var tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Overview map';
- var collapseLabel = options.collapseLabel ? options.collapseLabel : '\u00AB';
+ var collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00AB';
/**
* @private
* @type {Node}
*/
- this.collapseLabel_ = goog.isString(collapseLabel) ?
+ this.collapseLabel_ = typeof collapseLabel === 'string' ?
goog.dom.createDom('SPAN', {}, collapseLabel) :
collapseLabel;
- var label = options.label ? options.label : '\u00BB';
+ var label = options.label !== undefined ? options.label : '\u00BB';
/**
* @private
* @type {Node}
*/
- this.label_ = goog.isString(label) ?
+ this.label_ = typeof label === 'string' ?
goog.dom.createDom('SPAN', {}, label) :
label;
@@ -85279,10 +69244,11 @@ ol.control.OverviewMap = function(opt_options) {
'title': tipLabel
}, activeLabel);
- goog.events.listen(button, goog.events.EventType.CLICK,
- this.handleClick_, false, this);
+ ol.events.listen(button, ol.events.EventType.CLICK,
+ this.handleClick_, this);
- var ovmapDiv = goog.dom.createDom('DIV', 'ol-overviewmap-map');
+ var ovmapDiv = document.createElement('DIV');
+ ovmapDiv.className = 'ol-overviewmap-map';
/**
* @type {ol.Map}
@@ -85306,7 +69272,9 @@ ol.control.OverviewMap = function(opt_options) {
}, this);
}
- var box = goog.dom.createDom('DIV', 'ol-overviewmap-box');
+ var box = document.createElement('DIV');
+ box.className = 'ol-overviewmap-box';
+ box.style.boxSizing = 'border-box';
/**
* @type {ol.Overlay}
@@ -85355,9 +69323,9 @@ ol.control.OverviewMap.prototype.setMap = function(map) {
goog.base(this, 'setMap', map);
if (map) {
- this.listenerKeys.push(goog.events.listen(
+ this.listenerKeys.push(ol.events.listen(
map, ol.ObjectEventType.PROPERTYCHANGE,
- this.handleMapPropertyChange_, false, this));
+ this.handleMapPropertyChange_, this));
// TODO: to really support map switching, this would need to be reworked
if (this.ovmap_.getLayers().getLength() === 0) {
@@ -85399,9 +69367,9 @@ ol.control.OverviewMap.prototype.handleMapPropertyChange_ = function(event) {
* @private
*/
ol.control.OverviewMap.prototype.bindView_ = function(view) {
- goog.events.listen(view,
+ ol.events.listen(view,
ol.Object.getChangeEventType(ol.ViewProperty.ROTATION),
- this.handleRotationChanged_, false, this);
+ this.handleRotationChanged_, this);
};
@@ -85411,9 +69379,9 @@ ol.control.OverviewMap.prototype.bindView_ = function(view) {
* @private
*/
ol.control.OverviewMap.prototype.unbindView_ = function(view) {
- goog.events.unlisten(view,
+ ol.events.unlisten(view,
ol.Object.getChangeEventType(ol.ViewProperty.ROTATION),
- this.handleRotationChanged_, false, this);
+ this.handleRotationChanged_, this);
};
@@ -85477,17 +69445,17 @@ ol.control.OverviewMap.prototype.validateExtent_ = function() {
ovmap.getPixelFromCoordinate(ol.extent.getTopLeft(extent));
var bottomRightPixel =
ovmap.getPixelFromCoordinate(ol.extent.getBottomRight(extent));
- var boxSize = new goog.math.Size(
- Math.abs(topLeftPixel[0] - bottomRightPixel[0]),
- Math.abs(topLeftPixel[1] - bottomRightPixel[1]));
+
+ var boxWidth = Math.abs(topLeftPixel[0] - bottomRightPixel[0]);
+ var boxHeight = Math.abs(topLeftPixel[1] - bottomRightPixel[1]);
var ovmapWidth = ovmapSize[0];
var ovmapHeight = ovmapSize[1];
- if (boxSize.width < ovmapWidth * ol.OVERVIEWMAP_MIN_RATIO ||
- boxSize.height < ovmapHeight * ol.OVERVIEWMAP_MIN_RATIO ||
- boxSize.width > ovmapWidth * ol.OVERVIEWMAP_MAX_RATIO ||
- boxSize.height > ovmapHeight * ol.OVERVIEWMAP_MAX_RATIO) {
+ if (boxWidth < ovmapWidth * ol.OVERVIEWMAP_MIN_RATIO ||
+ boxHeight < ovmapHeight * ol.OVERVIEWMAP_MIN_RATIO ||
+ boxWidth > ovmapWidth * ol.OVERVIEWMAP_MAX_RATIO ||
+ boxHeight > ovmapHeight * ol.OVERVIEWMAP_MAX_RATIO) {
this.resetExtent_();
} else if (!ol.extent.containsExtent(ovextent, extent)) {
this.recenter_();
@@ -85591,10 +69559,8 @@ ol.control.OverviewMap.prototype.updateBox_ = function() {
// set box size calculated from map extent size and overview map resolution
if (box) {
- var boxWidth = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution);
- var boxHeight = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution);
- goog.style.setBorderBoxSize(box, new goog.math.Size(
- boxWidth, boxHeight));
+ box.style.width = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution) + 'px';
+ box.style.height = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution) + 'px';
}
};
@@ -85628,7 +69594,7 @@ ol.control.OverviewMap.prototype.calculateCoordinateRotate_ = function(
/**
- * @param {goog.events.BrowserEvent} event The event to handle
+ * @param {Event} event The event to handle
* @private
*/
ol.control.OverviewMap.prototype.handleClick_ = function(event) {
@@ -85641,7 +69607,7 @@ ol.control.OverviewMap.prototype.handleClick_ = function(event) {
* @private
*/
ol.control.OverviewMap.prototype.handleToggle_ = function() {
- goog.dom.classlist.toggle(this.element, 'ol-collapsed');
+ this.element.classList.toggle('ol-collapsed');
if (this.collapsed_) {
goog.dom.replaceNode(this.collapseLabel_, this.label_);
} else {
@@ -85655,11 +69621,11 @@ ol.control.OverviewMap.prototype.handleToggle_ = function() {
if (!this.collapsed_ && !ovmap.isRendered()) {
ovmap.updateSize();
this.resetExtent_();
- goog.events.listenOnce(ovmap, ol.MapEventType.POSTRENDER,
+ ol.events.listenOnce(ovmap, ol.MapEventType.POSTRENDER,
function(event) {
this.updateBox_();
},
- false, this);
+ this);
}
};
@@ -85684,7 +69650,7 @@ ol.control.OverviewMap.prototype.setCollapsible = function(collapsible) {
return;
}
this.collapsible_ = collapsible;
- goog.dom.classlist.toggle(this.element, 'ol-uncollapsible');
+ this.element.classList.toggle('ol-uncollapsible');
if (!collapsible && this.collapsed_) {
this.handleToggle_();
}
@@ -85730,19 +69696,14 @@ goog.provide('ol.control.ScaleLineProperty');
goog.provide('ol.control.ScaleLineUnits');
goog.require('goog.asserts');
-goog.require('goog.dom');
-goog.require('goog.events');
+goog.require('ol.events');
goog.require('goog.style');
goog.require('ol');
goog.require('ol.Object');
-goog.require('ol.TransformFunction');
goog.require('ol.control.Control');
goog.require('ol.css');
-goog.require('ol.math');
-goog.require('ol.proj');
goog.require('ol.proj.METERS_PER_UNIT');
goog.require('ol.proj.Units');
-goog.require('ol.sphere.NORMAL');
/**
@@ -85768,7 +69729,6 @@ ol.control.ScaleLineUnits = {
};
-
/**
* @classdesc
* A control displaying rough x-axis distances, calculated for the center of the
@@ -85787,21 +69747,22 @@ ol.control.ScaleLine = function(opt_options) {
var options = opt_options ? opt_options : {};
- var className = options.className ? options.className : 'ol-scale-line';
+ var className = options.className !== undefined ? options.className : 'ol-scale-line';
/**
* @private
* @type {Element}
*/
- this.innerElement_ = goog.dom.createDom('DIV',
- className + '-inner');
+ this.innerElement_ = document.createElement('DIV');
+ this.innerElement_.className = className + '-inner';
/**
* @private
* @type {Element}
*/
- this.element_ = goog.dom.createDom('DIV',
- className + ' ' + ol.css.CLASS_UNSELECTABLE, this.innerElement_);
+ this.element_ = document.createElement('DIV');
+ this.element_.className = className + ' ' + ol.css.CLASS_UNSELECTABLE;
+ this.element_.appendChild(this.innerElement_);
/**
* @private
@@ -85833,12 +69794,6 @@ ol.control.ScaleLine = function(opt_options) {
*/
this.renderedHTML_ = '';
- /**
- * @private
- * @type {?ol.TransformFunction}
- */
- this.toEPSG4326_ = null;
-
var render = options.render ? options.render : ol.control.ScaleLine.render;
goog.base(this, {
@@ -85847,9 +69802,9 @@ ol.control.ScaleLine = function(opt_options) {
target: options.target
});
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.control.ScaleLineProperty.UNITS),
- this.handleUnitsChanged_, false, this);
+ this.handleUnitsChanged_, this);
this.setUnits(/** @type {ol.control.ScaleLineUnits} */ (options.units) ||
ol.control.ScaleLineUnits.METRIC);
@@ -85930,61 +69885,21 @@ ol.control.ScaleLine.prototype.updateElement_ = function() {
var center = viewState.center;
var projection = viewState.projection;
+ var metersPerUnit = projection.getMetersPerUnit();
var pointResolution =
- projection.getPointResolution(viewState.resolution, center);
- var projectionUnits = projection.getUnits();
-
- var cosLatitude;
- var units = this.getUnits();
- if (projectionUnits == ol.proj.Units.DEGREES &&
- (units == ol.control.ScaleLineUnits.METRIC ||
- units == ol.control.ScaleLineUnits.IMPERIAL ||
- units == ol.control.ScaleLineUnits.US ||
- units == ol.control.ScaleLineUnits.NAUTICAL)) {
-
- // Convert pointResolution from degrees to meters
- this.toEPSG4326_ = null;
- cosLatitude = Math.cos(ol.math.toRadians(center[1]));
- pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180;
- projectionUnits = ol.proj.Units.METERS;
-
- } else if (projectionUnits != ol.proj.Units.DEGREES &&
- units == ol.control.ScaleLineUnits.DEGREES) {
-
- // Convert pointResolution from other units to degrees
- if (!this.toEPSG4326_) {
- this.toEPSG4326_ = ol.proj.getTransformFromProjections(
- projection, ol.proj.get('EPSG:4326'));
- }
- cosLatitude = Math.cos(ol.math.toRadians(this.toEPSG4326_(center)[1]));
- var radius = ol.sphere.NORMAL.radius;
- goog.asserts.assert(ol.proj.METERS_PER_UNIT[projectionUnits],
- 'Meters per unit should be defined for the projection unit');
- radius /= ol.proj.METERS_PER_UNIT[projectionUnits];
- pointResolution *= 180 / (Math.PI * cosLatitude * radius);
- projectionUnits = ol.proj.Units.DEGREES;
-
- } else {
- this.toEPSG4326_ = null;
- }
-
- goog.asserts.assert(
- ((units == ol.control.ScaleLineUnits.METRIC ||
- units == ol.control.ScaleLineUnits.IMPERIAL ||
- units == ol.control.ScaleLineUnits.US ||
- units == ol.control.ScaleLineUnits.NAUTICAL) &&
- projectionUnits == ol.proj.Units.METERS) ||
- (units == ol.control.ScaleLineUnits.DEGREES &&
- projectionUnits == ol.proj.Units.DEGREES),
- 'Scale line units and projection units should match');
+ projection.getPointResolution(viewState.resolution, center) *
+ metersPerUnit;
var nominalCount = this.minWidth_ * pointResolution;
var suffix = '';
+ var units = this.getUnits();
if (units == ol.control.ScaleLineUnits.DEGREES) {
- if (nominalCount < 1 / 60) {
+ var metersPerDegree = ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES];
+ pointResolution /= metersPerDegree;
+ if (nominalCount < metersPerDegree / 60) {
suffix = '\u2033'; // seconds
pointResolution *= 3600;
- } else if (nominalCount < 1) {
+ } else if (nominalCount < metersPerDegree) {
suffix = '\u2032'; // minutes
pointResolution *= 60;
} else {
@@ -86033,7 +69948,7 @@ ol.control.ScaleLine.prototype.updateElement_ = function() {
Math.log(this.minWidth_ * pointResolution) / Math.log(10));
var count, width;
while (true) {
- count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] *
+ count = ol.control.ScaleLine.LEADING_DIGITS[((i % 3) + 3) % 3] *
Math.pow(10, Math.floor(i / 3));
width = Math.round(count / pointResolution);
if (isNaN(width)) {
@@ -86064,1481 +69979,17 @@ ol.control.ScaleLine.prototype.updateElement_ = function() {
};
-// Copyright 2005 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Class to create objects which want to handle multiple events
- * and have their listeners easily cleaned up via a dispose method.
- *
- * Example:
- * <pre>
- * function Something() {
- * Something.base(this);
- *
- * ... set up object ...
- *
- * // Add event listeners
- * this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar);
- * this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand);
- * this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse);
- * this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover);
- * this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover);
- * }
- * goog.inherits(Something, goog.events.EventHandler);
- *
- * Something.prototype.disposeInternal = function() {
- * Something.base(this, 'disposeInternal');
- * goog.dom.removeNode(this.container);
- * };
- *
- *
- * // Then elsewhere:
- *
- * var activeSomething = null;
- * function openSomething() {
- * activeSomething = new Something();
- * }
- *
- * function closeSomething() {
- * if (activeSomething) {
- * activeSomething.dispose(); // Remove event listeners
- * activeSomething = null;
- * }
- * }
- * </pre>
- *
- */
-
-goog.provide('goog.events.EventHandler');
-
-goog.require('goog.Disposable');
-goog.require('goog.events');
-goog.require('goog.object');
-
-goog.forwardDeclare('goog.events.EventWrapper');
-
-
-
-/**
- * Super class for objects that want to easily manage a number of event
- * listeners. It allows a short cut to listen and also provides a quick way
- * to remove all events listeners belonging to this object.
- * @param {SCOPE=} opt_scope Object in whose scope to call the listeners.
- * @constructor
- * @extends {goog.Disposable}
- * @template SCOPE
- */
-goog.events.EventHandler = function(opt_scope) {
- goog.Disposable.call(this);
- // TODO(mknichel): Rename this to this.scope_ and fix the classes in google3
- // that access this private variable. :(
- this.handler_ = opt_scope;
-
- /**
- * Keys for events that are being listened to.
- * @type {!Object<!goog.events.Key>}
- * @private
- */
- this.keys_ = {};
-};
-goog.inherits(goog.events.EventHandler, goog.Disposable);
-
-
-/**
- * Utility array used to unify the cases of listening for an array of types
- * and listening for a single event, without using recursion or allocating
- * an array each time.
- * @type {!Array<string>}
- * @const
- * @private
- */
-goog.events.EventHandler.typeArray_ = [];
-
-
-/**
- * Listen to an event on a Listenable. If the function is omitted then the
- * EventHandler's handleEvent method will be used.
- * @param {goog.events.ListenableType} src Event source.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type to listen for or array of event types.
- * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
- * opt_fn Optional callback function to be used as the listener or an object
- * with handleEvent function.
- * @param {boolean=} opt_capture Optional whether to use capture phase.
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- * @template EVENTOBJ
- */
-goog.events.EventHandler.prototype.listen = function(
- src, type, opt_fn, opt_capture) {
- return this.listen_(src, type, opt_fn, opt_capture);
-};
-
-
-/**
- * Listen to an event on a Listenable. If the function is omitted then the
- * EventHandler's handleEvent method will be used.
- * @param {goog.events.ListenableType} src Event source.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type to listen for or array of event types.
- * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
- * null|undefined} fn Optional callback function to be used as the
- * listener or an object with handleEvent function.
- * @param {boolean|undefined} capture Optional whether to use capture phase.
- * @param {T} scope Object in whose scope to call the listener.
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- * @template T,EVENTOBJ
- */
-goog.events.EventHandler.prototype.listenWithScope = function(
- src, type, fn, capture, scope) {
- // TODO(mknichel): Deprecate this function.
- return this.listen_(src, type, fn, capture, scope);
-};
-
-
-/**
- * Listen to an event on a Listenable. If the function is omitted then the
- * EventHandler's handleEvent method will be used.
- * @param {goog.events.ListenableType} src Event source.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type to listen for or array of event types.
- * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
- * Optional callback function to be used as the listener or an object with
- * handleEvent function.
- * @param {boolean=} opt_capture Optional whether to use capture phase.
- * @param {Object=} opt_scope Object in whose scope to call the listener.
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- * @template EVENTOBJ
- * @private
- */
-goog.events.EventHandler.prototype.listen_ = function(src, type, opt_fn,
- opt_capture,
- opt_scope) {
- if (!goog.isArray(type)) {
- if (type) {
- goog.events.EventHandler.typeArray_[0] = type.toString();
- }
- type = goog.events.EventHandler.typeArray_;
- }
- for (var i = 0; i < type.length; i++) {
- var listenerObj = goog.events.listen(
- src, type[i], opt_fn || this.handleEvent,
- opt_capture || false,
- opt_scope || this.handler_ || this);
-
- if (!listenerObj) {
- // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
- // (goog.events.CaptureSimulationMode) in IE8-, it will return null
- // value.
- return this;
- }
-
- var key = listenerObj.key;
- this.keys_[key] = listenerObj;
- }
-
- return this;
-};
-
-
-/**
- * Listen to an event on a Listenable. If the function is omitted, then the
- * EventHandler's handleEvent method will be used. After the event has fired the
- * event listener is removed from the target. If an array of event types is
- * provided, each event type will be listened to once.
- * @param {goog.events.ListenableType} src Event source.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type to listen for or array of event types.
- * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
- * Optional callback function to be used as the listener or an object with
- * handleEvent function.
- * @param {boolean=} opt_capture Optional whether to use capture phase.
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- * @template EVENTOBJ
- */
-goog.events.EventHandler.prototype.listenOnce = function(
- src, type, opt_fn, opt_capture) {
- return this.listenOnce_(src, type, opt_fn, opt_capture);
-};
-
-
-/**
- * Listen to an event on a Listenable. If the function is omitted, then the
- * EventHandler's handleEvent method will be used. After the event has fired the
- * event listener is removed from the target. If an array of event types is
- * provided, each event type will be listened to once.
- * @param {goog.events.ListenableType} src Event source.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type to listen for or array of event types.
- * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
- * null|undefined} fn Optional callback function to be used as the
- * listener or an object with handleEvent function.
- * @param {boolean|undefined} capture Optional whether to use capture phase.
- * @param {T} scope Object in whose scope to call the listener.
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- * @template T,EVENTOBJ
- */
-goog.events.EventHandler.prototype.listenOnceWithScope = function(
- src, type, fn, capture, scope) {
- // TODO(mknichel): Deprecate this function.
- return this.listenOnce_(src, type, fn, capture, scope);
-};
-
-
-/**
- * Listen to an event on a Listenable. If the function is omitted, then the
- * EventHandler's handleEvent method will be used. After the event has fired
- * the event listener is removed from the target. If an array of event types is
- * provided, each event type will be listened to once.
- * @param {goog.events.ListenableType} src Event source.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type to listen for or array of event types.
- * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
- * Optional callback function to be used as the listener or an object with
- * handleEvent function.
- * @param {boolean=} opt_capture Optional whether to use capture phase.
- * @param {Object=} opt_scope Object in whose scope to call the listener.
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- * @template EVENTOBJ
- * @private
- */
-goog.events.EventHandler.prototype.listenOnce_ = function(
- src, type, opt_fn, opt_capture, opt_scope) {
- if (goog.isArray(type)) {
- for (var i = 0; i < type.length; i++) {
- this.listenOnce_(src, type[i], opt_fn, opt_capture, opt_scope);
- }
- } else {
- var listenerObj = goog.events.listenOnce(
- src, type, opt_fn || this.handleEvent, opt_capture,
- opt_scope || this.handler_ || this);
- if (!listenerObj) {
- // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
- // (goog.events.CaptureSimulationMode) in IE8-, it will return null
- // value.
- return this;
- }
-
- var key = listenerObj.key;
- this.keys_[key] = listenerObj;
- }
-
- return this;
-};
-
-
-/**
- * Adds an event listener with a specific event wrapper on a DOM Node or an
- * object that has implemented {@link goog.events.EventTarget}. A listener can
- * only be added once to an object.
- *
- * @param {EventTarget|goog.events.EventTarget} src The node to listen to
- * events on.
- * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
- * @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener
- * Callback method, or an object with a handleEvent function.
- * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
- * false).
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- */
-goog.events.EventHandler.prototype.listenWithWrapper = function(
- src, wrapper, listener, opt_capt) {
- // TODO(mknichel): Remove the opt_scope from this function and then
- // templatize it.
- return this.listenWithWrapper_(src, wrapper, listener, opt_capt);
-};
-
-
-/**
- * Adds an event listener with a specific event wrapper on a DOM Node or an
- * object that has implemented {@link goog.events.EventTarget}. A listener can
- * only be added once to an object.
- *
- * @param {EventTarget|goog.events.EventTarget} src The node to listen to
- * events on.
- * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
- * @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null}
- * listener Optional callback function to be used as the
- * listener or an object with handleEvent function.
- * @param {boolean|undefined} capture Optional whether to use capture phase.
- * @param {T} scope Object in whose scope to call the listener.
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- * @template T
- */
-goog.events.EventHandler.prototype.listenWithWrapperAndScope = function(
- src, wrapper, listener, capture, scope) {
- // TODO(mknichel): Deprecate this function.
- return this.listenWithWrapper_(src, wrapper, listener, capture, scope);
-};
-
-
-/**
- * Adds an event listener with a specific event wrapper on a DOM Node or an
- * object that has implemented {@link goog.events.EventTarget}. A listener can
- * only be added once to an object.
- *
- * @param {EventTarget|goog.events.EventTarget} src The node to listen to
- * events on.
- * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
- * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
- * method, or an object with a handleEvent function.
- * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
- * false).
- * @param {Object=} opt_scope Element in whose scope to call the listener.
- * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
- * chaining of calls.
- * @private
- */
-goog.events.EventHandler.prototype.listenWithWrapper_ = function(
- src, wrapper, listener, opt_capt, opt_scope) {
- wrapper.listen(src, listener, opt_capt, opt_scope || this.handler_ || this,
- this);
- return this;
-};
-
-
-/**
- * @return {number} Number of listeners registered by this handler.
- */
-goog.events.EventHandler.prototype.getListenerCount = function() {
- var count = 0;
- for (var key in this.keys_) {
- if (Object.prototype.hasOwnProperty.call(this.keys_, key)) {
- count++;
- }
- }
- return count;
-};
-
-
-/**
- * Unlistens on an event.
- * @param {goog.events.ListenableType} src Event source.
- * @param {string|Array<string>|
- * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
- * type Event type or array of event types to unlisten to.
- * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
- * Optional callback function to be used as the listener or an object with
- * handleEvent function.
- * @param {boolean=} opt_capture Optional whether to use capture phase.
- * @param {Object=} opt_scope Object in whose scope to call the listener.
- * @return {!goog.events.EventHandler} This object, allowing for chaining of
- * calls.
- * @template EVENTOBJ
- */
-goog.events.EventHandler.prototype.unlisten = function(src, type, opt_fn,
- opt_capture,
- opt_scope) {
- if (goog.isArray(type)) {
- for (var i = 0; i < type.length; i++) {
- this.unlisten(src, type[i], opt_fn, opt_capture, opt_scope);
- }
- } else {
- var listener = goog.events.getListener(src, type,
- opt_fn || this.handleEvent,
- opt_capture, opt_scope || this.handler_ || this);
-
- if (listener) {
- goog.events.unlistenByKey(listener);
- delete this.keys_[listener.key];
- }
- }
-
- return this;
-};
-
-
-/**
- * Removes an event listener which was added with listenWithWrapper().
- *
- * @param {EventTarget|goog.events.EventTarget} src The target to stop
- * listening to events on.
- * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
- * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
- * listener function to remove.
- * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
- * whether the listener is fired during the capture or bubble phase of the
- * event.
- * @param {Object=} opt_scope Element in whose scope to call the listener.
- * @return {!goog.events.EventHandler} This object, allowing for chaining of
- * calls.
- */
-goog.events.EventHandler.prototype.unlistenWithWrapper = function(src, wrapper,
- listener, opt_capt, opt_scope) {
- wrapper.unlisten(src, listener, opt_capt,
- opt_scope || this.handler_ || this, this);
- return this;
-};
-
-
-/**
- * Unlistens to all events.
- */
-goog.events.EventHandler.prototype.removeAll = function() {
- goog.object.forEach(this.keys_, function(listenerObj, key) {
- if (this.keys_.hasOwnProperty(key)) {
- goog.events.unlistenByKey(listenerObj);
- }
- }, this);
-
- this.keys_ = {};
-};
-
-
-/**
- * Disposes of this EventHandler and removes all listeners that it registered.
- * @override
- * @protected
- */
-goog.events.EventHandler.prototype.disposeInternal = function() {
- goog.events.EventHandler.superClass_.disposeInternal.call(this);
- this.removeAll();
-};
-
-
-/**
- * Default event handler
- * @param {goog.events.Event} e Event object.
- */
-goog.events.EventHandler.prototype.handleEvent = function(e) {
- throw Error('EventHandler.handleEvent not implemented');
-};
-
-// Copyright 2012 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Bidi utility functions.
- *
- */
-
-goog.provide('goog.style.bidi');
-
-goog.require('goog.dom');
-goog.require('goog.style');
-goog.require('goog.userAgent');
-
-
-/**
- * Returns the normalized scrollLeft position for a scrolled element.
- * @param {Element} element The scrolled element.
- * @return {number} The number of pixels the element is scrolled. 0 indicates
- * that the element is not scrolled at all (which, in general, is the
- * left-most position in ltr and the right-most position in rtl).
- */
-goog.style.bidi.getScrollLeft = function(element) {
- var isRtl = goog.style.isRightToLeft(element);
- if (isRtl && goog.userAgent.GECKO) {
- // ScrollLeft starts at 0 and then goes negative as the element is scrolled
- // towards the left.
- return -element.scrollLeft;
- } else if (isRtl &&
- !(goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8'))) {
- // ScrollLeft starts at the maximum positive value and decreases towards
- // 0 as the element is scrolled towards the left. However, for overflow
- // visible, there is no scrollLeft and the value always stays correctly at 0
- var overflowX = goog.style.getComputedOverflowX(element);
- if (overflowX == 'visible') {
- return element.scrollLeft;
- } else {
- return element.scrollWidth - element.clientWidth - element.scrollLeft;
- }
- }
- // ScrollLeft behavior is identical in rtl and ltr, it starts at 0 and
- // increases as the element is scrolled away from the start.
- return element.scrollLeft;
-};
-
-
-/**
- * Returns the "offsetStart" of an element, analagous to offsetLeft but
- * normalized for right-to-left environments and various browser
- * inconsistencies. This value returned can always be passed to setScrollOffset
- * to scroll to an element's left edge in a left-to-right offsetParent or
- * right edge in a right-to-left offsetParent.
- *
- * For example, here offsetStart is 10px in an LTR environment and 5px in RTL:
- *
- * <pre>
- * | xxxxxxxxxx |
- * ^^^^^^^^^^ ^^^^ ^^^^^
- * 10px elem 5px
- * </pre>
- *
- * If an element is positioned before the start of its offsetParent, the
- * startOffset may be negative. This can be used with setScrollOffset to
- * reliably scroll to an element:
- *
- * <pre>
- * var scrollOffset = goog.style.bidi.getOffsetStart(element);
- * goog.style.bidi.setScrollOffset(element.offsetParent, scrollOffset);
- * </pre>
- *
- * @see setScrollOffset
- *
- * @param {Element} element The element for which we need to determine the
- * offsetStart position.
- * @return {number} The offsetStart for that element.
- */
-goog.style.bidi.getOffsetStart = function(element) {
- element = /** @type {!HTMLElement} */ (element);
- var offsetLeftForReal = element.offsetLeft;
-
- // The element might not have an offsetParent.
- // For example, the node might not be attached to the DOM tree,
- // and position:fixed children do not have an offset parent.
- // Just try to do the best we can with what we have.
- var bestParent = element.offsetParent;
-
- if (!bestParent && goog.style.getComputedPosition(element) == 'fixed') {
- bestParent = goog.dom.getOwnerDocument(element).documentElement;
- }
-
- // Just give up in this case.
- if (!bestParent) {
- return offsetLeftForReal;
- }
-
- if (goog.userAgent.GECKO) {
- // When calculating an element's offsetLeft, Firefox erroneously subtracts
- // the border width from the actual distance. So we need to add it back.
- var borderWidths = goog.style.getBorderBox(bestParent);
- offsetLeftForReal += borderWidths.left;
- } else if (goog.userAgent.isDocumentModeOrHigher(8) &&
- !goog.userAgent.isDocumentModeOrHigher(9)) {
- // When calculating an element's offsetLeft, IE8/9-Standards Mode
- // erroneously adds the border width to the actual distance. So we need to
- // subtract it.
- var borderWidths = goog.style.getBorderBox(bestParent);
- offsetLeftForReal -= borderWidths.left;
- }
-
- if (goog.style.isRightToLeft(bestParent)) {
- // Right edge of the element relative to the left edge of its parent.
- var elementRightOffset = offsetLeftForReal + element.offsetWidth;
-
- // Distance from the parent's right edge to the element's right edge.
- return bestParent.clientWidth - elementRightOffset;
- }
-
- return offsetLeftForReal;
-};
-
-
-/**
- * Sets the element's scrollLeft attribute so it is correctly scrolled by
- * offsetStart pixels. This takes into account whether the element is RTL and
- * the nuances of different browsers. To scroll to the "beginning" of an
- * element use getOffsetStart to obtain the element's offsetStart value and then
- * pass the value to setScrollOffset.
- * @see getOffsetStart
- * @param {Element} element The element to set scrollLeft on.
- * @param {number} offsetStart The number of pixels to scroll the element.
- * If this value is < 0, 0 is used.
- */
-goog.style.bidi.setScrollOffset = function(element, offsetStart) {
- offsetStart = Math.max(offsetStart, 0);
- // In LTR and in "mirrored" browser RTL (such as IE), we set scrollLeft to
- // the number of pixels to scroll.
- // Otherwise, in RTL, we need to account for different browser behavior.
- if (!goog.style.isRightToLeft(element)) {
- element.scrollLeft = offsetStart;
- } else if (goog.userAgent.GECKO) {
- // Negative scroll-left positions in RTL.
- element.scrollLeft = -offsetStart;
- } else if (!(goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8'))) {
- // Take the current scrollLeft value and move to the right by the
- // offsetStart to get to the left edge of the element, and then by
- // the clientWidth of the element to get to the right edge.
- element.scrollLeft =
- element.scrollWidth - offsetStart - element.clientWidth;
- } else {
- element.scrollLeft = offsetStart;
- }
-};
-
-
-/**
- * Sets the element's left style attribute in LTR or right style attribute in
- * RTL. Also clears the left attribute in RTL and the right attribute in LTR.
- * @param {Element} elem The element to position.
- * @param {number} left The left position in LTR; will be set as right in RTL.
- * @param {?number} top The top position. If null only the left/right is set.
- * @param {boolean} isRtl Whether we are in RTL mode.
- */
-goog.style.bidi.setPosition = function(elem, left, top, isRtl) {
- if (!goog.isNull(top)) {
- elem.style.top = top + 'px';
- }
- if (isRtl) {
- elem.style.right = left + 'px';
- elem.style.left = '';
- } else {
- elem.style.left = left + 'px';
- elem.style.right = '';
- }
-};
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Drag Utilities.
- *
- * Provides extensible functionality for drag & drop behaviour.
- *
- * @see ../demos/drag.html
- * @see ../demos/dragger.html
- */
-
-
-goog.provide('goog.fx.DragEvent');
-goog.provide('goog.fx.Dragger');
-goog.provide('goog.fx.Dragger.EventType');
-
-goog.require('goog.dom');
-goog.require('goog.dom.TagName');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventHandler');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
-goog.require('goog.math.Coordinate');
-goog.require('goog.math.Rect');
-goog.require('goog.style');
-goog.require('goog.style.bidi');
-goog.require('goog.userAgent');
-
-
-
-/**
- * A class that allows mouse or touch-based dragging (moving) of an element
- *
- * @param {Element} target The element that will be dragged.
- * @param {Element=} opt_handle An optional handle to control the drag, if null
- * the target is used.
- * @param {goog.math.Rect=} opt_limits Object containing left, top, width,
- * and height.
- *
- * @extends {goog.events.EventTarget}
- * @constructor
- * @struct
- */
-goog.fx.Dragger = function(target, opt_handle, opt_limits) {
- goog.fx.Dragger.base(this, 'constructor');
-
- /**
- * Reference to drag target element.
- * @type {?Element}
- */
- this.target = target;
-
- /**
- * Reference to the handler that initiates the drag.
- * @type {?Element}
- */
- this.handle = opt_handle || target;
-
- /**
- * Object representing the limits of the drag region.
- * @type {goog.math.Rect}
- */
- this.limits = opt_limits || new goog.math.Rect(NaN, NaN, NaN, NaN);
-
- /**
- * Reference to a document object to use for the events.
- * @private {Document}
- */
- this.document_ = goog.dom.getOwnerDocument(target);
-
- /** @private {!goog.events.EventHandler} */
- this.eventHandler_ = new goog.events.EventHandler(this);
- this.registerDisposable(this.eventHandler_);
-
- /**
- * Whether the element is rendered right-to-left. We initialize this lazily.
- * @private {boolean|undefined}}
- */
- this.rightToLeft_;
-
- /**
- * Current x position of mouse or touch relative to viewport.
- * @type {number}
- */
- this.clientX = 0;
-
- /**
- * Current y position of mouse or touch relative to viewport.
- * @type {number}
- */
- this.clientY = 0;
-
- /**
- * Current x position of mouse or touch relative to screen. Deprecated because
- * it doesn't take into affect zoom level or pixel density.
- * @type {number}
- * @deprecated Consider switching to clientX instead.
- */
- this.screenX = 0;
-
- /**
- * Current y position of mouse or touch relative to screen. Deprecated because
- * it doesn't take into affect zoom level or pixel density.
- * @type {number}
- * @deprecated Consider switching to clientY instead.
- */
- this.screenY = 0;
-
- /**
- * The x position where the first mousedown or touchstart occurred.
- * @type {number}
- */
- this.startX = 0;
-
- /**
- * The y position where the first mousedown or touchstart occurred.
- * @type {number}
- */
- this.startY = 0;
-
- /**
- * Current x position of drag relative to target's parent.
- * @type {number}
- */
- this.deltaX = 0;
-
- /**
- * Current y position of drag relative to target's parent.
- * @type {number}
- */
- this.deltaY = 0;
-
- /**
- * The current page scroll value.
- * @type {?goog.math.Coordinate}
- */
- this.pageScroll;
-
- /**
- * Whether dragging is currently enabled.
- * @private {boolean}
- */
- this.enabled_ = true;
-
- /**
- * Whether object is currently being dragged.
- * @private {boolean}
- */
- this.dragging_ = false;
-
- /**
- * Whether mousedown should be default prevented.
- * @private {boolean}
- **/
- this.preventMouseDown_ = true;
-
- /**
- * The amount of distance, in pixels, after which a mousedown or touchstart is
- * considered a drag.
- * @private {number}
- */
- this.hysteresisDistanceSquared_ = 0;
-
- /**
- * The SCROLL event target used to make drag element follow scrolling.
- * @private {?EventTarget}
- */
- this.scrollTarget_;
-
- /**
- * Whether IE drag events cancelling is on.
- * @private {boolean}
- */
- this.ieDragStartCancellingOn_ = false;
-
- /**
- * Whether the dragger implements the changes described in http://b/6324964,
- * making it truly RTL. This is a temporary flag to allow clients to
- * transition to the new behavior at their convenience. At some point it will
- * be the default.
- * @private {boolean}
- */
- this.useRightPositioningForRtl_ = false;
-
- // Add listener. Do not use the event handler here since the event handler is
- // used for listeners added and removed during the drag operation.
- goog.events.listen(this.handle,
- [goog.events.EventType.TOUCHSTART, goog.events.EventType.MOUSEDOWN],
- this.startDrag, false, this);
-};
-goog.inherits(goog.fx.Dragger, goog.events.EventTarget);
-// Dragger is meant to be extended, but defines most properties on its
-// prototype, thus making it unsuitable for sealing.
-goog.tagUnsealableClass(goog.fx.Dragger);
-
-
-/**
- * Whether setCapture is supported by the browser.
- * @type {boolean}
- * @private
- */
-goog.fx.Dragger.HAS_SET_CAPTURE_ =
- // IE and Gecko after 1.9.3 has setCapture
- // WebKit does not yet: https://bugs.webkit.org/show_bug.cgi?id=27330
- goog.userAgent.IE ||
- goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.3');
-
-
-/**
- * Creates copy of node being dragged. This is a utility function to be used
- * wherever it is inappropriate for the original source to follow the mouse
- * cursor itself.
- *
- * @param {Element} sourceEl Element to copy.
- * @return {!Element} The clone of {@code sourceEl}.
- */
-goog.fx.Dragger.cloneNode = function(sourceEl) {
- var clonedEl = /** @type {Element} */ (sourceEl.cloneNode(true)),
- origTexts = sourceEl.getElementsByTagName(goog.dom.TagName.TEXTAREA),
- dragTexts = clonedEl.getElementsByTagName(goog.dom.TagName.TEXTAREA);
- // Cloning does not copy the current value of textarea elements, so correct
- // this manually.
- for (var i = 0; i < origTexts.length; i++) {
- dragTexts[i].value = origTexts[i].value;
- }
- switch (sourceEl.tagName) {
- case goog.dom.TagName.TR:
- return goog.dom.createDom(goog.dom.TagName.TABLE, null,
- goog.dom.createDom(goog.dom.TagName.TBODY,
- null, clonedEl));
- case goog.dom.TagName.TD:
- case goog.dom.TagName.TH:
- return goog.dom.createDom(
- goog.dom.TagName.TABLE, null, goog.dom.createDom(
- goog.dom.TagName.TBODY, null, goog.dom.createDom(
- goog.dom.TagName.TR, null, clonedEl)));
- case goog.dom.TagName.TEXTAREA:
- clonedEl.value = sourceEl.value;
- default:
- return clonedEl;
- }
-};
-
-
-/**
- * Constants for event names.
- * @enum {string}
- */
-goog.fx.Dragger.EventType = {
- // The drag action was canceled before the START event. Possible reasons:
- // disabled dragger, dragging with the right mouse button or releasing the
- // button before reaching the hysteresis distance.
- EARLY_CANCEL: 'earlycancel',
- START: 'start',
- BEFOREDRAG: 'beforedrag',
- DRAG: 'drag',
- END: 'end'
-};
-
-
-/**
- * Turns on/off true RTL behavior. This should be called immediately after
- * construction. This is a temporary flag to allow clients to transition
- * to the new component at their convenience. At some point true will be the
- * default.
- * @param {boolean} useRightPositioningForRtl True if "right" should be used for
- * positioning, false if "left" should be used for positioning.
- */
-goog.fx.Dragger.prototype.enableRightPositioningForRtl =
- function(useRightPositioningForRtl) {
- this.useRightPositioningForRtl_ = useRightPositioningForRtl;
-};
-
-
-/**
- * Returns the event handler, intended for subclass use.
- * @return {!goog.events.EventHandler<T>} The event handler.
- * @this {T}
- * @template T
- */
-goog.fx.Dragger.prototype.getHandler = function() {
- // TODO(user): templated "this" values currently result in "this" being
- // "unknown" in the body of the function.
- var self = /** @type {goog.fx.Dragger} */ (this);
- return self.eventHandler_;
-};
-
-
-/**
- * Sets (or reset) the Drag limits after a Dragger is created.
- * @param {goog.math.Rect?} limits Object containing left, top, width,
- * height for new Dragger limits. If target is right-to-left and
- * enableRightPositioningForRtl(true) is called, then rect is interpreted as
- * right, top, width, and height.
- */
-goog.fx.Dragger.prototype.setLimits = function(limits) {
- this.limits = limits || new goog.math.Rect(NaN, NaN, NaN, NaN);
-};
-
-
-/**
- * Sets the distance the user has to drag the element before a drag operation is
- * started.
- * @param {number} distance The number of pixels after which a mousedown and
- * move is considered a drag.
- */
-goog.fx.Dragger.prototype.setHysteresis = function(distance) {
- this.hysteresisDistanceSquared_ = Math.pow(distance, 2);
-};
-
-
-/**
- * Gets the distance the user has to drag the element before a drag operation is
- * started.
- * @return {number} distance The number of pixels after which a mousedown and
- * move is considered a drag.
- */
-goog.fx.Dragger.prototype.getHysteresis = function() {
- return Math.sqrt(this.hysteresisDistanceSquared_);
-};
-
-
-/**
- * Sets the SCROLL event target to make drag element follow scrolling.
- *
- * @param {EventTarget} scrollTarget The event target that dispatches SCROLL
- * events.
- */
-goog.fx.Dragger.prototype.setScrollTarget = function(scrollTarget) {
- this.scrollTarget_ = scrollTarget;
-};
-
-
-/**
- * Enables cancelling of built-in IE drag events.
- * @param {boolean} cancelIeDragStart Whether to enable cancelling of IE
- * dragstart event.
- */
-goog.fx.Dragger.prototype.setCancelIeDragStart = function(cancelIeDragStart) {
- this.ieDragStartCancellingOn_ = cancelIeDragStart;
-};
-
-
-/**
- * @return {boolean} Whether the dragger is enabled.
- */
-goog.fx.Dragger.prototype.getEnabled = function() {
- return this.enabled_;
-};
-
-
-/**
- * Set whether dragger is enabled
- * @param {boolean} enabled Whether dragger is enabled.
- */
-goog.fx.Dragger.prototype.setEnabled = function(enabled) {
- this.enabled_ = enabled;
-};
-
-
-/**
- * Set whether mousedown should be default prevented.
- * @param {boolean} preventMouseDown Whether mousedown should be default
- * prevented.
- */
-goog.fx.Dragger.prototype.setPreventMouseDown = function(preventMouseDown) {
- this.preventMouseDown_ = preventMouseDown;
-};
-
-
-/** @override */
-goog.fx.Dragger.prototype.disposeInternal = function() {
- goog.fx.Dragger.superClass_.disposeInternal.call(this);
- goog.events.unlisten(this.handle,
- [goog.events.EventType.TOUCHSTART, goog.events.EventType.MOUSEDOWN],
- this.startDrag, false, this);
- this.cleanUpAfterDragging_();
-
- this.target = null;
- this.handle = null;
-};
-
-
-/**
- * Whether the DOM element being manipulated is rendered right-to-left.
- * @return {boolean} True if the DOM element is rendered right-to-left, false
- * otherwise.
- * @private
- */
-goog.fx.Dragger.prototype.isRightToLeft_ = function() {
- if (!goog.isDef(this.rightToLeft_)) {
- this.rightToLeft_ = goog.style.isRightToLeft(this.target);
- }
- return this.rightToLeft_;
-};
-
-
-/**
- * Event handler that is used to start the drag
- * @param {goog.events.BrowserEvent} e Event object.
- */
-goog.fx.Dragger.prototype.startDrag = function(e) {
- var isMouseDown = e.type == goog.events.EventType.MOUSEDOWN;
-
- // Dragger.startDrag() can be called by AbstractDragDrop with a mousemove
- // event and IE does not report pressed mouse buttons on mousemove. Also,
- // it does not make sense to check for the button if the user is already
- // dragging.
-
- if (this.enabled_ && !this.dragging_ &&
- (!isMouseDown || e.isMouseActionButton())) {
- if (this.hysteresisDistanceSquared_ == 0) {
- if (this.fireDragStart_(e)) {
- this.dragging_ = true;
- if (this.preventMouseDown_) {
- e.preventDefault();
- }
- } else {
- // If the start drag is cancelled, don't setup for a drag.
- return;
- }
- } else if (this.preventMouseDown_) {
- // Need to preventDefault for hysteresis to prevent page getting selected.
- e.preventDefault();
- }
- this.setupDragHandlers();
-
- this.clientX = this.startX = e.clientX;
- this.clientY = this.startY = e.clientY;
- this.screenX = e.screenX;
- this.screenY = e.screenY;
- this.computeInitialPosition();
- this.pageScroll = goog.dom.getDomHelper(this.document_).getDocumentScroll();
- } else {
- this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
- }
-};
-
-
-/**
- * Sets up event handlers when dragging starts.
- * @protected
- */
-goog.fx.Dragger.prototype.setupDragHandlers = function() {
- var doc = this.document_;
- var docEl = doc.documentElement;
- // Use bubbling when we have setCapture since we got reports that IE has
- // problems with the capturing events in combination with setCapture.
- var useCapture = !goog.fx.Dragger.HAS_SET_CAPTURE_;
-
- this.eventHandler_.listen(doc,
- [goog.events.EventType.TOUCHMOVE, goog.events.EventType.MOUSEMOVE],
- this.handleMove_, useCapture);
- this.eventHandler_.listen(doc,
- [goog.events.EventType.TOUCHEND, goog.events.EventType.MOUSEUP],
- this.endDrag, useCapture);
-
- if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
- docEl.setCapture(false);
- this.eventHandler_.listen(docEl,
- goog.events.EventType.LOSECAPTURE,
- this.endDrag);
- } else {
- // Make sure we stop the dragging if the window loses focus.
- // Don't use capture in this listener because we only want to end the drag
- // if the actual window loses focus. Since blur events do not bubble we use
- // a bubbling listener on the window.
- this.eventHandler_.listen(goog.dom.getWindow(doc),
- goog.events.EventType.BLUR,
- this.endDrag);
- }
-
- if (goog.userAgent.IE && this.ieDragStartCancellingOn_) {
- // Cancel IE's 'ondragstart' event.
- this.eventHandler_.listen(doc, goog.events.EventType.DRAGSTART,
- goog.events.Event.preventDefault);
- }
-
- if (this.scrollTarget_) {
- this.eventHandler_.listen(this.scrollTarget_, goog.events.EventType.SCROLL,
- this.onScroll_, useCapture);
- }
-};
-
-
-/**
- * Fires a goog.fx.Dragger.EventType.START event.
- * @param {goog.events.BrowserEvent} e Browser event that triggered the drag.
- * @return {boolean} False iff preventDefault was called on the DragEvent.
- * @private
- */
-goog.fx.Dragger.prototype.fireDragStart_ = function(e) {
- return this.dispatchEvent(new goog.fx.DragEvent(
- goog.fx.Dragger.EventType.START, this, e.clientX, e.clientY, e));
-};
-
-
-/**
- * Unregisters the event handlers that are only active during dragging, and
- * releases mouse capture.
- * @private
- */
-goog.fx.Dragger.prototype.cleanUpAfterDragging_ = function() {
- this.eventHandler_.removeAll();
- if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
- this.document_.releaseCapture();
- }
-};
-
-
-/**
- * Event handler that is used to end the drag.
- * @param {goog.events.BrowserEvent} e Event object.
- * @param {boolean=} opt_dragCanceled Whether the drag has been canceled.
- */
-goog.fx.Dragger.prototype.endDrag = function(e, opt_dragCanceled) {
- this.cleanUpAfterDragging_();
-
- if (this.dragging_) {
- this.dragging_ = false;
-
- var x = this.limitX(this.deltaX);
- var y = this.limitY(this.deltaY);
- var dragCanceled = opt_dragCanceled ||
- e.type == goog.events.EventType.TOUCHCANCEL;
- this.dispatchEvent(new goog.fx.DragEvent(
- goog.fx.Dragger.EventType.END, this, e.clientX, e.clientY, e, x, y,
- dragCanceled));
- } else {
- this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
- }
-};
-
-
-/**
- * Event handler that is used to end the drag by cancelling it.
- * @param {goog.events.BrowserEvent} e Event object.
- */
-goog.fx.Dragger.prototype.endDragCancel = function(e) {
- this.endDrag(e, true);
-};
-
-
-/**
- * Event handler that is used on mouse / touch move to update the drag
- * @param {goog.events.BrowserEvent} e Event object.
- * @private
- */
-goog.fx.Dragger.prototype.handleMove_ = function(e) {
- if (this.enabled_) {
- // dx in right-to-left cases is relative to the right.
- var sign = this.useRightPositioningForRtl_ &&
- this.isRightToLeft_() ? -1 : 1;
- var dx = sign * (e.clientX - this.clientX);
- var dy = e.clientY - this.clientY;
- this.clientX = e.clientX;
- this.clientY = e.clientY;
- this.screenX = e.screenX;
- this.screenY = e.screenY;
-
- if (!this.dragging_) {
- var diffX = this.startX - this.clientX;
- var diffY = this.startY - this.clientY;
- var distance = diffX * diffX + diffY * diffY;
- if (distance > this.hysteresisDistanceSquared_) {
- if (this.fireDragStart_(e)) {
- this.dragging_ = true;
- } else {
- // DragListGroup disposes of the dragger if BEFOREDRAGSTART is
- // canceled.
- if (!this.isDisposed()) {
- this.endDrag(e);
- }
- return;
- }
- }
- }
-
- var pos = this.calculatePosition_(dx, dy);
- var x = pos.x;
- var y = pos.y;
-
- if (this.dragging_) {
-
- var rv = this.dispatchEvent(new goog.fx.DragEvent(
- goog.fx.Dragger.EventType.BEFOREDRAG, this, e.clientX, e.clientY,
- e, x, y));
-
- // Only do the defaultAction and dispatch drag event if predrag didn't
- // prevent default
- if (rv) {
- this.doDrag(e, x, y, false);
- e.preventDefault();
- }
- }
- }
-};
-
-
-/**
- * Calculates the drag position.
- *
- * @param {number} dx The horizontal movement delta.
- * @param {number} dy The vertical movement delta.
- * @return {!goog.math.Coordinate} The newly calculated drag element position.
- * @private
- */
-goog.fx.Dragger.prototype.calculatePosition_ = function(dx, dy) {
- // Update the position for any change in body scrolling
- var pageScroll = goog.dom.getDomHelper(this.document_).getDocumentScroll();
- dx += pageScroll.x - this.pageScroll.x;
- dy += pageScroll.y - this.pageScroll.y;
- this.pageScroll = pageScroll;
-
- this.deltaX += dx;
- this.deltaY += dy;
-
- var x = this.limitX(this.deltaX);
- var y = this.limitY(this.deltaY);
- return new goog.math.Coordinate(x, y);
-};
-
-
-/**
- * Event handler for scroll target scrolling.
- * @param {goog.events.BrowserEvent} e The event.
- * @private
- */
-goog.fx.Dragger.prototype.onScroll_ = function(e) {
- var pos = this.calculatePosition_(0, 0);
- e.clientX = this.clientX;
- e.clientY = this.clientY;
- this.doDrag(e, pos.x, pos.y, true);
-};
-
-
-/**
- * @param {goog.events.BrowserEvent} e The closure object
- * representing the browser event that caused a drag event.
- * @param {number} x The new horizontal position for the drag element.
- * @param {number} y The new vertical position for the drag element.
- * @param {boolean} dragFromScroll Whether dragging was caused by scrolling
- * the associated scroll target.
- * @protected
- */
-goog.fx.Dragger.prototype.doDrag = function(e, x, y, dragFromScroll) {
- this.defaultAction(x, y);
- this.dispatchEvent(new goog.fx.DragEvent(
- goog.fx.Dragger.EventType.DRAG, this, e.clientX, e.clientY, e, x, y));
-};
-
-
-/**
- * Returns the 'real' x after limits are applied (allows for some
- * limits to be undefined).
- * @param {number} x X-coordinate to limit.
- * @return {number} The 'real' X-coordinate after limits are applied.
- */
-goog.fx.Dragger.prototype.limitX = function(x) {
- var rect = this.limits;
- var left = !isNaN(rect.left) ? rect.left : null;
- var width = !isNaN(rect.width) ? rect.width : 0;
- var maxX = left != null ? left + width : Infinity;
- var minX = left != null ? left : -Infinity;
- return Math.min(maxX, Math.max(minX, x));
-};
-
-
-/**
- * Returns the 'real' y after limits are applied (allows for some
- * limits to be undefined).
- * @param {number} y Y-coordinate to limit.
- * @return {number} The 'real' Y-coordinate after limits are applied.
- */
-goog.fx.Dragger.prototype.limitY = function(y) {
- var rect = this.limits;
- var top = !isNaN(rect.top) ? rect.top : null;
- var height = !isNaN(rect.height) ? rect.height : 0;
- var maxY = top != null ? top + height : Infinity;
- var minY = top != null ? top : -Infinity;
- return Math.min(maxY, Math.max(minY, y));
-};
-
-
-/**
- * Overridable function for computing the initial position of the target
- * before dragging begins.
- * @protected
- */
-goog.fx.Dragger.prototype.computeInitialPosition = function() {
- this.deltaX = this.useRightPositioningForRtl_ ?
- goog.style.bidi.getOffsetStart(this.target) :
- /** @type {!HTMLElement} */ (this.target).offsetLeft;
- this.deltaY = /** @type {!HTMLElement} */ (this.target).offsetTop;
-};
-
-
-/**
- * Overridable function for handling the default action of the drag behaviour.
- * Normally this is simply moving the element to x,y though in some cases it
- * might be used to resize the layer. This is basically a shortcut to
- * implementing a default ondrag event handler.
- * @param {number} x X-coordinate for target element. In right-to-left, x this
- * is the number of pixels the target should be moved to from the right.
- * @param {number} y Y-coordinate for target element.
- */
-goog.fx.Dragger.prototype.defaultAction = function(x, y) {
- if (this.useRightPositioningForRtl_ && this.isRightToLeft_()) {
- this.target.style.right = x + 'px';
- } else {
- this.target.style.left = x + 'px';
- }
- this.target.style.top = y + 'px';
-};
-
-
-/**
- * @return {boolean} Whether the dragger is currently in the midst of a drag.
- */
-goog.fx.Dragger.prototype.isDragging = function() {
- return this.dragging_;
-};
-
-
-
-/**
- * Object representing a drag event
- * @param {string} type Event type.
- * @param {goog.fx.Dragger} dragobj Drag object initiating event.
- * @param {number} clientX X-coordinate relative to the viewport.
- * @param {number} clientY Y-coordinate relative to the viewport.
- * @param {goog.events.BrowserEvent} browserEvent The closure object
- * representing the browser event that caused this drag event.
- * @param {number=} opt_actX Optional actual x for drag if it has been limited.
- * @param {number=} opt_actY Optional actual y for drag if it has been limited.
- * @param {boolean=} opt_dragCanceled Whether the drag has been canceled.
- * @constructor
- * @struct
- * @extends {goog.events.Event}
- */
-goog.fx.DragEvent = function(type, dragobj, clientX, clientY, browserEvent,
- opt_actX, opt_actY, opt_dragCanceled) {
- goog.events.Event.call(this, type);
-
- /**
- * X-coordinate relative to the viewport
- * @type {number}
- */
- this.clientX = clientX;
-
- /**
- * Y-coordinate relative to the viewport
- * @type {number}
- */
- this.clientY = clientY;
-
- /**
- * The closure object representing the browser event that caused this drag
- * event.
- * @type {goog.events.BrowserEvent}
- */
- this.browserEvent = browserEvent;
-
- /**
- * The real x-position of the drag if it has been limited
- * @type {number}
- */
- this.left = goog.isDef(opt_actX) ? opt_actX : dragobj.deltaX;
-
- /**
- * The real y-position of the drag if it has been limited
- * @type {number}
- */
- this.top = goog.isDef(opt_actY) ? opt_actY : dragobj.deltaY;
-
- /**
- * Reference to the drag object for this event
- * @type {goog.fx.Dragger}
- */
- this.dragger = dragobj;
-
- /**
- * Whether drag was canceled with this event. Used to differentiate between
- * a legitimate drag END that can result in an action and a drag END which is
- * a result of a drag cancelation. For now it can happen 1) with drag END
- * event on FireFox when user drags the mouse out of the window, 2) with
- * drag END event on IE7 which is generated on MOUSEMOVE event when user
- * moves the mouse into the document after the mouse button has been
- * released, 3) when TOUCHCANCEL is raised instead of TOUCHEND (on touch
- * events).
- * @type {boolean}
- */
- this.dragCanceled = !!opt_dragCanceled;
-};
-goog.inherits(goog.fx.DragEvent, goog.events.Event);
-
// FIXME should possibly show tooltip when dragging?
goog.provide('ol.control.ZoomSlider');
goog.require('goog.asserts');
goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventType');
-goog.require('goog.fx.DragEvent');
-goog.require('goog.fx.Dragger');
-goog.require('goog.fx.Dragger.EventType');
-goog.require('goog.math.Rect');
goog.require('goog.style');
-goog.require('ol.Size');
+goog.require('ol.events');
+goog.require('ol.events.Event');
+goog.require('ol.events.EventType');
+goog.require('ol.pointer.PointerEventHandler');
goog.require('ol.ViewHint');
goog.require('ol.animation');
goog.require('ol.control.Control');
@@ -87547,7 +69998,6 @@ goog.require('ol.easing');
goog.require('ol.math');
-
/**
* @classdesc
* A slider type of control for zooming.
@@ -87583,6 +70033,42 @@ ol.control.ZoomSlider = function(opt_options) {
this.direction_ = ol.control.ZoomSlider.direction.VERTICAL;
/**
+ * @type {boolean}
+ * @private
+ */
+ this.dragging_;
+
+ /**
+ * @type {!Array.<ol.events.Key>}
+ * @private
+ */
+ this.dragListenerKeys_ = [];
+
+ /**
+ * @type {number}
+ * @private
+ */
+ this.heightLimit_ = 0;
+
+ /**
+ * @type {number}
+ * @private
+ */
+ this.widthLimit_ = 0;
+
+ /**
+ * @type {number|undefined}
+ * @private
+ */
+ this.previousX_;
+
+ /**
+ * @type {number|undefined}
+ * @private
+ */
+ this.previousY_;
+
+ /**
* The calculated thumb size (border box plus margins). Set when initSlider_
* is called.
* @type {ol.Size}
@@ -87598,12 +70084,12 @@ ol.control.ZoomSlider = function(opt_options) {
this.sliderInitialized_ = false;
/**
- * @private
* @type {number}
+ * @private
*/
this.duration_ = options.duration !== undefined ? options.duration : 200;
- var className = options.className ? options.className : 'ol-zoomslider';
+ var className = options.className !== undefined ? options.className : 'ol-zoomslider';
var thumbElement = goog.dom.createDom('BUTTON', {
'type': 'button',
'class': className + '-thumb ' + ol.css.CLASS_UNSELECTABLE
@@ -87613,23 +70099,22 @@ ol.control.ZoomSlider = function(opt_options) {
thumbElement);
/**
- * @type {goog.fx.Dragger}
+ * @type {ol.pointer.PointerEventHandler}
* @private
*/
- this.dragger_ = new goog.fx.Dragger(thumbElement);
- this.registerDisposable(this.dragger_);
+ this.dragger_ = new ol.pointer.PointerEventHandler(containerElement);
- goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.START,
- this.handleDraggerStart_, false, this);
- goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.DRAG,
- this.handleDraggerDrag_, false, this);
- goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.END,
- this.handleDraggerEnd_, false, this);
+ ol.events.listen(this.dragger_, ol.pointer.EventType.POINTERDOWN,
+ this.handleDraggerStart_, this);
+ ol.events.listen(this.dragger_, ol.pointer.EventType.POINTERMOVE,
+ this.handleDraggerDrag_, this);
+ ol.events.listen(this.dragger_, ol.pointer.EventType.POINTERUP,
+ this.handleDraggerEnd_, this);
- goog.events.listen(containerElement, goog.events.EventType.CLICK,
- this.handleContainerClick_, false, this);
- goog.events.listen(thumbElement, goog.events.EventType.CLICK,
- goog.events.Event.stopPropagation);
+ ol.events.listen(containerElement, ol.events.EventType.CLICK,
+ this.handleContainerClick_, this);
+ ol.events.listen(thumbElement, ol.events.EventType.CLICK,
+ ol.events.Event.stopPropagation);
var render = options.render ? options.render : ol.control.ZoomSlider.render;
@@ -87642,6 +70127,15 @@ goog.inherits(ol.control.ZoomSlider, ol.control.Control);
/**
+ * @inheritDoc
+ */
+ol.control.ZoomSlider.prototype.disposeInternal = function() {
+ this.dragger_.dispose();
+ goog.base(this, 'disposeInternal');
+};
+
+
+/**
* The enum for available directions.
*
* @enum {number}
@@ -87674,7 +70168,7 @@ ol.control.ZoomSlider.prototype.initSlider_ = function() {
var container = this.element;
var containerSize = goog.style.getSize(container);
- var thumb = goog.dom.getFirstElementChild(container);
+ var thumb = container.firstElementChild;
var thumbMargins = goog.style.getMarginBox(thumb);
var thumbBorderBoxSize = goog.style.getBorderBoxSize(thumb);
var thumbWidth = thumbBorderBoxSize.width +
@@ -87683,18 +70177,13 @@ ol.control.ZoomSlider.prototype.initSlider_ = function() {
thumbMargins.top + thumbMargins.bottom;
this.thumbSize_ = [thumbWidth, thumbHeight];
- var width = containerSize.width - thumbWidth;
- var height = containerSize.height - thumbHeight;
-
- var limits;
if (containerSize.width > containerSize.height) {
this.direction_ = ol.control.ZoomSlider.direction.HORIZONTAL;
- limits = new goog.math.Rect(0, 0, width, 0);
+ this.widthLimit_ = containerSize.width - thumbWidth;
} else {
this.direction_ = ol.control.ZoomSlider.direction.VERTICAL;
- limits = new goog.math.Rect(0, 0, 0, height);
+ this.heightLimit_ = containerSize.height - thumbHeight;
}
- this.dragger_.setLimits(limits);
this.sliderInitialized_ = true;
};
@@ -87723,10 +70212,10 @@ ol.control.ZoomSlider.render = function(mapEvent) {
/**
- * @param {goog.events.BrowserEvent} browserEvent The browser event to handle.
+ * @param {Event} event The browser event to handle.
* @private
*/
-ol.control.ZoomSlider.prototype.handleContainerClick_ = function(browserEvent) {
+ol.control.ZoomSlider.prototype.handleContainerClick_ = function(event) {
var map = this.getMap();
var view = map.getView();
var currentResolution = view.getResolution();
@@ -87738,8 +70227,8 @@ ol.control.ZoomSlider.prototype.handleContainerClick_ = function(browserEvent) {
easing: ol.easing.easeOut
}));
var relativePosition = this.getRelativePosition_(
- browserEvent.offsetX - this.thumbSize_[0] / 2,
- browserEvent.offsetY - this.thumbSize_[1] / 2);
+ event.offsetX - this.thumbSize_[0] / 2,
+ event.offsetY - this.thumbSize_[1] / 2);
var resolution = this.getResolutionForPosition_(relativePosition);
view.setResolution(view.constrainResolution(resolution));
};
@@ -87747,45 +70236,79 @@ ol.control.ZoomSlider.prototype.handleContainerClick_ = function(browserEvent) {
/**
* Handle dragger start events.
- * @param {goog.fx.DragEvent} event The drag event.
+ * @param {ol.pointer.PointerEvent} event The drag event.
* @private
*/
ol.control.ZoomSlider.prototype.handleDraggerStart_ = function(event) {
- this.getMap().getView().setHint(ol.ViewHint.INTERACTING, 1);
+ if (!this.dragging_ &&
+ event.originalEvent.target === this.element.firstElementChild) {
+ this.getMap().getView().setHint(ol.ViewHint.INTERACTING, 1);
+ this.previousX_ = event.clientX;
+ this.previousY_ = event.clientY;
+ this.dragging_ = true;
+
+ if (this.dragListenerKeys_.length === 0) {
+ var drag = this.handleDraggerDrag_;
+ var end = this.handleDraggerEnd_;
+ this.dragListenerKeys_.push(
+ ol.events.listen(document, ol.events.EventType.MOUSEMOVE, drag, this),
+ ol.events.listen(document, ol.events.EventType.TOUCHMOVE, drag, this),
+ ol.events.listen(document, ol.pointer.EventType.POINTERMOVE, drag, this),
+ ol.events.listen(document, ol.events.EventType.MOUSEUP, end, this),
+ ol.events.listen(document, ol.events.EventType.TOUCHEND, end, this),
+ ol.events.listen(document, ol.pointer.EventType.POINTERUP, end, this)
+ );
+ }
+ }
};
/**
* Handle dragger drag events.
*
- * @param {goog.fx.DragEvent} event The drag event.
+ * @param {ol.pointer.PointerEvent|Event} event The drag event.
* @private
*/
ol.control.ZoomSlider.prototype.handleDraggerDrag_ = function(event) {
- var relativePosition = this.getRelativePosition_(event.left, event.top);
- this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
- this.getMap().getView().setResolution(this.currentResolution_);
+ if (this.dragging_) {
+ var element = this.element.firstElementChild;
+ var deltaX = event.clientX - this.previousX_ + parseInt(element.style.left, 10);
+ var deltaY = event.clientY - this.previousY_ + parseInt(element.style.top, 10);
+ var relativePosition = this.getRelativePosition_(deltaX, deltaY);
+ this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
+ this.getMap().getView().setResolution(this.currentResolution_);
+ this.setThumbPosition_(this.currentResolution_);
+ this.previousX_ = event.clientX;
+ this.previousY_ = event.clientY;
+ }
};
/**
* Handle dragger end events.
- * @param {goog.fx.DragEvent} event The drag event.
+ * @param {ol.pointer.PointerEvent|Event} event The drag event.
* @private
*/
ol.control.ZoomSlider.prototype.handleDraggerEnd_ = function(event) {
- var map = this.getMap();
- var view = map.getView();
- view.setHint(ol.ViewHint.INTERACTING, -1);
- goog.asserts.assert(this.currentResolution_,
- 'this.currentResolution_ should be defined');
- map.beforeRender(ol.animation.zoom({
- resolution: this.currentResolution_,
- duration: this.duration_,
- easing: ol.easing.easeOut
- }));
- var resolution = view.constrainResolution(this.currentResolution_);
- view.setResolution(resolution);
+ if (this.dragging_) {
+ var map = this.getMap();
+ var view = map.getView();
+ view.setHint(ol.ViewHint.INTERACTING, -1);
+ goog.asserts.assert(this.currentResolution_,
+ 'this.currentResolution_ should be defined');
+ map.beforeRender(ol.animation.zoom({
+ resolution: this.currentResolution_,
+ duration: this.duration_,
+ easing: ol.easing.easeOut
+ }));
+ var resolution = view.constrainResolution(this.currentResolution_);
+ view.setResolution(resolution);
+ this.dragging_ = false;
+ this.previousX_ = undefined;
+ this.previousY_ = undefined;
+ this.dragListenerKeys_.forEach(ol.events.unlistenByKey);
+ this.dragListenerKeys_.length = 0;
+ }
};
@@ -87797,15 +70320,12 @@ ol.control.ZoomSlider.prototype.handleDraggerEnd_ = function(event) {
*/
ol.control.ZoomSlider.prototype.setThumbPosition_ = function(res) {
var position = this.getPositionForResolution_(res);
- var dragger = this.dragger_;
- var thumb = goog.dom.getFirstElementChild(this.element);
+ var thumb = this.element.firstElementChild;
if (this.direction_ == ol.control.ZoomSlider.direction.HORIZONTAL) {
- var left = dragger.limits.left + dragger.limits.width * position;
- goog.style.setPosition(thumb, left);
+ thumb.style.left = this.widthLimit_ * position + 'px';
} else {
- var top = dragger.limits.top + dragger.limits.height * position;
- goog.style.setPosition(thumb, dragger.limits.left, top);
+ thumb.style.top = this.heightLimit_ * position + 'px';
}
};
@@ -87821,12 +70341,11 @@ ol.control.ZoomSlider.prototype.setThumbPosition_ = function(res) {
* @private
*/
ol.control.ZoomSlider.prototype.getRelativePosition_ = function(x, y) {
- var draggerLimits = this.dragger_.limits;
var amount;
if (this.direction_ === ol.control.ZoomSlider.direction.HORIZONTAL) {
- amount = (x - draggerLimits.left) / draggerLimits.width;
+ amount = x / this.widthLimit_;
} else {
- amount = (y - draggerLimits.top) / draggerLimits.height;
+ amount = y / this.heightLimit_;
}
return ol.math.clamp(amount, 0, 1);
};
@@ -87864,13 +70383,12 @@ goog.provide('ol.control.ZoomToExtent');
goog.require('goog.asserts');
goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.control.Control');
goog.require('ol.css');
-
/**
* @classdesc
* A button control which, when pressed, changes the map view to a specific
@@ -87890,19 +70408,19 @@ ol.control.ZoomToExtent = function(opt_options) {
*/
this.extent_ = options.extent ? options.extent : null;
- var className = options.className ? options.className :
+ var className = options.className !== undefined ? options.className :
'ol-zoom-extent';
- var label = options.label ? options.label : 'E';
- var tipLabel = options.tipLabel ?
+ var label = options.label !== undefined ? options.label : 'E';
+ var tipLabel = options.tipLabel !== undefined ?
options.tipLabel : 'Fit to extent';
var button = goog.dom.createDom('BUTTON', {
'type': 'button',
'title': tipLabel
}, label);
- goog.events.listen(button, goog.events.EventType.CLICK,
- this.handleClick_, false, this);
+ ol.events.listen(button, ol.events.EventType.CLICK,
+ this.handleClick_, this);
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
ol.css.CLASS_CONTROL;
@@ -87917,7 +70435,7 @@ goog.inherits(ol.control.ZoomToExtent, ol.control.Control);
/**
- * @param {goog.events.BrowserEvent} event The event to handle
+ * @param {Event} event The event to handle
* @private
*/
ol.control.ZoomToExtent.prototype.handleClick_ = function(event) {
@@ -87932,8 +70450,7 @@ ol.control.ZoomToExtent.prototype.handleClick_ = function(event) {
ol.control.ZoomToExtent.prototype.handleZoomToExtent_ = function() {
var map = this.getMap();
var view = map.getView();
- var extent = !this.extent_ ?
- view.getProjection().getExtent() : this.extent_;
+ var extent = !this.extent_ ? view.getProjection().getExtent() : this.extent_;
var size = map.getSize();
goog.asserts.assert(size, 'size should be defined');
view.fit(extent, size);
@@ -87942,7 +70459,7 @@ ol.control.ZoomToExtent.prototype.handleZoomToExtent_ = function() {
goog.provide('ol.DeviceOrientation');
goog.provide('ol.DeviceOrientationProperty');
-goog.require('goog.events');
+goog.require('ol.events');
goog.require('ol');
goog.require('ol.Object');
goog.require('ol.has');
@@ -87961,7 +70478,6 @@ ol.DeviceOrientationProperty = {
};
-
/**
* @classdesc
* The ol.DeviceOrientation class provides access to information from
@@ -88007,11 +70523,11 @@ ol.DeviceOrientationProperty = {
* equivalent properties in ol.DeviceOrientation are in radians for consistency
* with all other uses of angles throughout OpenLayers.
*
- * @see http://www.w3.org/TR/orientation-event/
- *
* To get notified of device orientation changes, register a listener for the
* generic `change` event on your `ol.DeviceOrientation` instance.
*
+ * @see {@link http://www.w3.org/TR/orientation-event/}
+ *
* @constructor
* @extends {ol.Object}
* @param {olx.DeviceOrientationOptions=} opt_options Options.
@@ -88025,13 +70541,13 @@ ol.DeviceOrientation = function(opt_options) {
/**
* @private
- * @type {goog.events.Key}
+ * @type {?ol.events.Key}
*/
this.listenerKey_ = null;
- goog.events.listen(this,
+ ol.events.listen(this,
ol.Object.getChangeEventType(ol.DeviceOrientationProperty.TRACKING),
- this.handleTrackingChanged_, false, this);
+ this.handleTrackingChanged_, this);
this.setTracking(options.tracking !== undefined ? options.tracking : false);
@@ -88050,16 +70566,15 @@ ol.DeviceOrientation.prototype.disposeInternal = function() {
/**
* @private
- * @param {goog.events.BrowserEvent} browserEvent Event.
+ * @param {Event} originalEvent Event.
*/
-ol.DeviceOrientation.prototype.orientationChange_ = function(browserEvent) {
- var event = /** @type {DeviceOrientationEvent} */
- (browserEvent.getBrowserEvent());
+ol.DeviceOrientation.prototype.orientationChange_ = function(originalEvent) {
+ var event = /** @type {DeviceOrientationEvent} */ (originalEvent);
if (event.alpha !== null) {
var alpha = ol.math.toRadians(event.alpha);
this.set(ol.DeviceOrientationProperty.ALPHA, alpha);
// event.absolute is undefined in iOS.
- if (goog.isBoolean(event.absolute) && event.absolute) {
+ if (typeof event.absolute === 'boolean' && event.absolute) {
this.set(ol.DeviceOrientationProperty.HEADING, alpha);
} else if (goog.isNumber(event.webkitCompassHeading) &&
event.webkitCompassAccuracy != -1) {
@@ -88150,10 +70665,10 @@ ol.DeviceOrientation.prototype.handleTrackingChanged_ = function() {
if (ol.has.DEVICE_ORIENTATION) {
var tracking = this.getTracking();
if (tracking && !this.listenerKey_) {
- this.listenerKey_ = goog.events.listen(goog.global, 'deviceorientation',
- this.orientationChange_, false, this);
- } else if (!tracking && this.listenerKey_) {
- goog.events.unlistenByKey(this.listenerKey_);
+ this.listenerKey_ = ol.events.listen(ol.global, 'deviceorientation',
+ this.orientationChange_, this);
+ } else if (!tracking && this.listenerKey_ !== null) {
+ ol.events.unlistenByKey(this.listenerKey_);
this.listenerKey_ = null;
}
}
@@ -88177,7 +70692,6 @@ goog.require('ol.geom.Geometry');
goog.require('ol.proj');
-
/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
@@ -88245,6 +70759,9 @@ ol.format.Feature.prototype.adaptOptions = function(options) {
options.dataProjection : this.defaultDataProjection,
rightHanded: options.rightHanded
};
+ if (options.decimals) {
+ updatedOptions.decimals = options.decimals;
+ }
}
return updatedOptions;
};
@@ -88339,34 +70856,56 @@ ol.format.Feature.transformWithOptions = function(
ol.proj.get(opt_options.featureProjection) : null;
var dataProjection = opt_options ?
ol.proj.get(opt_options.dataProjection) : null;
+ /**
+ * @type {ol.geom.Geometry|ol.Extent}
+ */
+ var transformed;
if (featureProjection && dataProjection &&
!ol.proj.equivalent(featureProjection, dataProjection)) {
if (geometry instanceof ol.geom.Geometry) {
- return (write ? geometry.clone() : geometry).transform(
+ transformed = (write ? geometry.clone() : geometry).transform(
write ? featureProjection : dataProjection,
write ? dataProjection : featureProjection);
} else {
// FIXME this is necessary because ol.format.GML treats extents
// as geometries
- return ol.proj.transformExtent(
+ transformed = ol.proj.transformExtent(
write ? geometry.slice() : geometry,
write ? featureProjection : dataProjection,
write ? dataProjection : featureProjection);
}
} else {
- return geometry;
+ transformed = geometry;
}
+ if (write && opt_options && opt_options.decimals) {
+ var power = Math.pow(10, opt_options.decimals);
+ // if decimals option on write, round each coordinate appropriately
+ /**
+ * @param {Array.<number>} coordinates Coordinates.
+ * @return {Array.<number>} Transformed coordinates.
+ */
+ var transform = function(coordinates) {
+ for (var i = 0, ii = coordinates.length; i < ii; ++i) {
+ coordinates[i] = Math.round(coordinates[i] * power) / power;
+ }
+ return coordinates;
+ };
+ if (Array.isArray(transformed)) {
+ transform(transformed);
+ } else {
+ transformed.applyTransform(transform);
+ }
+ }
+ return transformed;
};
goog.provide('ol.format.JSONFeature');
goog.require('goog.asserts');
-goog.require('goog.json');
goog.require('ol.format.Feature');
goog.require('ol.format.FormatType');
-
/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
@@ -88390,9 +70929,9 @@ goog.inherits(ol.format.JSONFeature, ol.format.Feature);
ol.format.JSONFeature.prototype.getObject_ = function(source) {
if (goog.isObject(source)) {
return source;
- } else if (goog.isString(source)) {
- var object = goog.json.parse(source);
- return object ? object : null;
+ } else if (typeof source === 'string') {
+ var object = JSON.parse(source);
+ return object ? /** @type {Object} */ (object) : null;
} else {
goog.asserts.fail();
return null;
@@ -88482,7 +71021,7 @@ ol.format.JSONFeature.prototype.readProjectionFromObject = goog.abstractMethod;
* @inheritDoc
*/
ol.format.JSONFeature.prototype.writeFeature = function(feature, opt_options) {
- return goog.json.serialize(this.writeFeatureObject(feature, opt_options));
+ return JSON.stringify(this.writeFeatureObject(feature, opt_options));
};
@@ -88497,9 +71036,8 @@ ol.format.JSONFeature.prototype.writeFeatureObject = goog.abstractMethod;
/**
* @inheritDoc
*/
-ol.format.JSONFeature.prototype.writeFeatures = function(
- features, opt_options) {
- return goog.json.serialize(this.writeFeaturesObject(features, opt_options));
+ol.format.JSONFeature.prototype.writeFeatures = function(features, opt_options) {
+ return JSON.stringify(this.writeFeaturesObject(features, opt_options));
};
@@ -88514,9 +71052,8 @@ ol.format.JSONFeature.prototype.writeFeaturesObject = goog.abstractMethod;
/**
* @inheritDoc
*/
-ol.format.JSONFeature.prototype.writeGeometry = function(
- geometry, opt_options) {
- return goog.json.serialize(this.writeGeometryObject(geometry, opt_options));
+ol.format.JSONFeature.prototype.writeGeometry = function(geometry, opt_options) {
+ return JSON.stringify(this.writeGeometryObject(geometry, opt_options));
};
@@ -88529,9 +71066,9 @@ ol.format.JSONFeature.prototype.writeGeometryObject = goog.abstractMethod;
goog.provide('ol.geom.flat.interpolate');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.math');
+goog.require('ol.array');
+goog.require('ol.math');
/**
@@ -88543,8 +71080,8 @@ goog.require('goog.math');
* @param {Array.<number>=} opt_dest Destination.
* @return {Array.<number>} Destination.
*/
-ol.geom.flat.interpolate.lineString =
- function(flatCoordinates, offset, end, stride, fraction, opt_dest) {
+ol.geom.flat.interpolate.lineString = function(flatCoordinates, offset, end, stride, fraction, opt_dest) {
+ // FIXME does not work when vertices are repeated
// FIXME interpolate extra dimensions
goog.asserts.assert(0 <= fraction && fraction <= 1,
'fraction should be in between 0 and 1');
@@ -88576,14 +71113,14 @@ ol.geom.flat.interpolate.lineString =
y1 = y2;
}
var target = fraction * length;
- var index = goog.array.binarySearch(cumulativeLengths, target);
+ var index = ol.array.binarySearch(cumulativeLengths, target);
if (index < 0) {
var t = (target - cumulativeLengths[-index - 2]) /
(cumulativeLengths[-index - 1] - cumulativeLengths[-index - 2]);
var o = offset + (-index - 2) * stride;
- pointX = goog.math.lerp(
+ pointX = ol.math.lerp(
flatCoordinates[o], flatCoordinates[o + stride], t);
- pointY = goog.math.lerp(
+ pointY = ol.math.lerp(
flatCoordinates[o + 1], flatCoordinates[o + stride + 1], t);
} else {
pointX = flatCoordinates[offset + index * stride];
@@ -88609,8 +71146,7 @@ ol.geom.flat.interpolate.lineString =
* @param {boolean} extrapolate Extrapolate.
* @return {ol.Coordinate} Coordinate.
*/
-ol.geom.flat.lineStringCoordinateAtM =
- function(flatCoordinates, offset, end, stride, m, extrapolate) {
+ol.geom.flat.lineStringCoordinateAtM = function(flatCoordinates, offset, end, stride, m, extrapolate) {
if (end == offset) {
return null;
}
@@ -88657,7 +71193,7 @@ ol.geom.flat.lineStringCoordinateAtM =
coordinate = [];
var i;
for (i = 0; i < stride - 1; ++i) {
- coordinate.push(goog.math.lerp(flatCoordinates[(lo - 1) * stride + i],
+ coordinate.push(ol.math.lerp(flatCoordinates[(lo - 1) * stride + i],
flatCoordinates[lo * stride + i], t));
}
coordinate.push(m);
@@ -88731,8 +71267,7 @@ goog.provide('ol.geom.flat.length');
* @param {number} stride Stride.
* @return {number} Length.
*/
-ol.geom.flat.length.lineString =
- function(flatCoordinates, offset, end, stride) {
+ol.geom.flat.length.lineString = function(flatCoordinates, offset, end, stride) {
var x1 = flatCoordinates[offset];
var y1 = flatCoordinates[offset + 1];
var length = 0;
@@ -88755,8 +71290,7 @@ ol.geom.flat.length.lineString =
* @param {number} stride Stride.
* @return {number} Perimeter.
*/
-ol.geom.flat.length.linearRing =
- function(flatCoordinates, offset, end, stride) {
+ol.geom.flat.length.linearRing = function(flatCoordinates, offset, end, stride) {
var perimeter =
ol.geom.flat.length.lineString(flatCoordinates, offset, end, stride);
var dx = flatCoordinates[end - stride] - flatCoordinates[offset];
@@ -88767,9 +71301,9 @@ ol.geom.flat.length.linearRing =
goog.provide('ol.geom.LineString');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('ol');
+goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.geom.GeometryLayout');
goog.require('ol.geom.GeometryType');
@@ -88784,7 +71318,6 @@ goog.require('ol.geom.flat.segments');
goog.require('ol.geom.flat.simplify');
-
/**
* @classdesc
* Linestring geometry.
@@ -88840,7 +71373,7 @@ ol.geom.LineString.prototype.appendCoordinate = function(coordinate) {
if (!this.flatCoordinates) {
this.flatCoordinates = coordinate.slice();
} else {
- goog.array.extend(this.flatCoordinates, coordinate);
+ ol.array.extend(this.flatCoordinates, coordinate);
}
this.changed();
};
@@ -88861,8 +71394,7 @@ ol.geom.LineString.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.LineString.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.LineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance <
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
@@ -88934,6 +71466,23 @@ ol.geom.LineString.prototype.getCoordinates = function() {
/**
+ * Return the coordinate at the provided fraction along the linestring.
+ * The `fraction` is a number between 0 and 1, where 0 is the start of the
+ * linestring and 1 is the end.
+ * @param {number} fraction Fraction.
+ * @param {ol.Coordinate=} opt_dest Optional coordinate whose values will
+ * be modified. If not provided, a new coordinate will be returned.
+ * @return {ol.Coordinate} Coordinate of the interpolated point.
+ * @api
+ */
+ol.geom.LineString.prototype.getCoordinateAt = function(fraction, opt_dest) {
+ return ol.geom.flat.interpolate.lineString(
+ this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
+ fraction, opt_dest);
+};
+
+
+/**
* Return the length of the linestring on projected plane.
* @return {number} Length (on projected plane).
* @api stable
@@ -88949,9 +71498,7 @@ ol.geom.LineString.prototype.getLength = function() {
*/
ol.geom.LineString.prototype.getFlatMidpoint = function() {
if (this.flatMidpointRevision_ != this.getRevision()) {
- this.flatMidpoint_ = ol.geom.flat.interpolate.lineString(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
- 0.5, this.flatMidpoint_);
+ this.flatMidpoint_ = this.getCoordinateAt(0.5, this.flatMidpoint_);
this.flatMidpointRevision_ = this.getRevision();
}
return this.flatMidpoint_;
@@ -88961,8 +71508,7 @@ ol.geom.LineString.prototype.getFlatMidpoint = function() {
/**
* @inheritDoc
*/
-ol.geom.LineString.prototype.getSimplifiedGeometryInternal =
- function(squaredTolerance) {
+ol.geom.LineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
var simplifiedFlatCoordinates = [];
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
@@ -89000,8 +71546,7 @@ ol.geom.LineString.prototype.intersectsExtent = function(extent) {
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
* @api stable
*/
-ol.geom.LineString.prototype.setCoordinates =
- function(coordinates, opt_layout) {
+ol.geom.LineString.prototype.setCoordinates = function(coordinates, opt_layout) {
if (!coordinates) {
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
} else {
@@ -89020,17 +71565,16 @@ ol.geom.LineString.prototype.setCoordinates =
* @param {ol.geom.GeometryLayout} layout Layout.
* @param {Array.<number>} flatCoordinates Flat coordinates.
*/
-ol.geom.LineString.prototype.setFlatCoordinates =
- function(layout, flatCoordinates) {
+ol.geom.LineString.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
this.setFlatCoordinatesInternal(layout, flatCoordinates);
this.changed();
};
goog.provide('ol.geom.MultiLineString');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('ol');
+goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.geom.GeometryLayout');
goog.require('ol.geom.GeometryType');
@@ -89044,7 +71588,6 @@ goog.require('ol.geom.flat.intersectsextent');
goog.require('ol.geom.flat.simplify');
-
/**
* @classdesc
* Multi-linestring geometry.
@@ -89094,7 +71637,7 @@ ol.geom.MultiLineString.prototype.appendLineString = function(lineString) {
if (!this.flatCoordinates) {
this.flatCoordinates = lineString.getFlatCoordinates().slice();
} else {
- goog.array.extend(
+ ol.array.extend(
this.flatCoordinates, lineString.getFlatCoordinates().slice());
}
this.ends_.push(this.flatCoordinates.length);
@@ -89118,8 +71661,7 @@ ol.geom.MultiLineString.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.MultiLineString.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.MultiLineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance <
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
@@ -89157,8 +71699,7 @@ ol.geom.MultiLineString.prototype.closestPointXY =
* @return {ol.Coordinate} Coordinate.
* @api stable
*/
-ol.geom.MultiLineString.prototype.getCoordinateAtM =
- function(m, opt_extrapolate, opt_interpolate) {
+ol.geom.MultiLineString.prototype.getCoordinateAtM = function(m, opt_extrapolate, opt_interpolate) {
if ((this.layout != ol.geom.GeometryLayout.XYM &&
this.layout != ol.geom.GeometryLayout.XYZM) ||
this.flatCoordinates.length === 0) {
@@ -89247,7 +71788,7 @@ ol.geom.MultiLineString.prototype.getFlatMidpoints = function() {
var end = ends[i];
var midpoint = ol.geom.flat.interpolate.lineString(
flatCoordinates, offset, end, stride, 0.5);
- goog.array.extend(midpoints, midpoint);
+ ol.array.extend(midpoints, midpoint);
offset = end;
}
return midpoints;
@@ -89257,8 +71798,7 @@ ol.geom.MultiLineString.prototype.getFlatMidpoints = function() {
/**
* @inheritDoc
*/
-ol.geom.MultiLineString.prototype.getSimplifiedGeometryInternal =
- function(squaredTolerance) {
+ol.geom.MultiLineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
var simplifiedFlatCoordinates = [];
var simplifiedEnds = [];
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeuckers(
@@ -89296,8 +71836,7 @@ ol.geom.MultiLineString.prototype.intersectsExtent = function(extent) {
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
* @api stable
*/
-ol.geom.MultiLineString.prototype.setCoordinates =
- function(coordinates, opt_layout) {
+ol.geom.MultiLineString.prototype.setCoordinates = function(coordinates, opt_layout) {
if (!coordinates) {
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
} else {
@@ -89318,8 +71857,7 @@ ol.geom.MultiLineString.prototype.setCoordinates =
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {Array.<number>} ends Ends.
*/
-ol.geom.MultiLineString.prototype.setFlatCoordinates =
- function(layout, flatCoordinates, ends) {
+ol.geom.MultiLineString.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) {
if (!flatCoordinates) {
goog.asserts.assert(ends && ends.length === 0,
'ends must be truthy and ends.length should be 0');
@@ -89353,7 +71891,7 @@ ol.geom.MultiLineString.prototype.setLineStrings = function(lineStrings) {
goog.asserts.assert(lineString.getLayout() == layout,
'layout of lineString should match layout');
}
- goog.array.extend(flatCoordinates, lineString.getFlatCoordinates());
+ ol.array.extend(flatCoordinates, lineString.getFlatCoordinates());
ends.push(flatCoordinates.length);
}
this.setFlatCoordinates(layout, flatCoordinates, ends);
@@ -89361,8 +71899,8 @@ ol.geom.MultiLineString.prototype.setLineStrings = function(lineStrings) {
goog.provide('ol.geom.MultiPoint');
-goog.require('goog.array');
goog.require('goog.asserts');
+goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.geom.GeometryLayout');
goog.require('ol.geom.GeometryType');
@@ -89373,7 +71911,6 @@ goog.require('ol.geom.flat.inflate');
goog.require('ol.math');
-
/**
* @classdesc
* Multi-point geometry.
@@ -89402,7 +71939,7 @@ ol.geom.MultiPoint.prototype.appendPoint = function(point) {
if (!this.flatCoordinates) {
this.flatCoordinates = point.getFlatCoordinates().slice();
} else {
- goog.array.extend(this.flatCoordinates, point.getFlatCoordinates());
+ ol.array.extend(this.flatCoordinates, point.getFlatCoordinates());
}
this.changed();
};
@@ -89423,8 +71960,7 @@ ol.geom.MultiPoint.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.MultiPoint.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.MultiPoint.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance <
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
@@ -89534,8 +72070,7 @@ ol.geom.MultiPoint.prototype.intersectsExtent = function(extent) {
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
* @api stable
*/
-ol.geom.MultiPoint.prototype.setCoordinates =
- function(coordinates, opt_layout) {
+ol.geom.MultiPoint.prototype.setCoordinates = function(coordinates, opt_layout) {
if (!coordinates) {
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
} else {
@@ -89554,8 +72089,7 @@ ol.geom.MultiPoint.prototype.setCoordinates =
* @param {ol.geom.GeometryLayout} layout Layout.
* @param {Array.<number>} flatCoordinates Flat coordinates.
*/
-ol.geom.MultiPoint.prototype.setFlatCoordinates =
- function(layout, flatCoordinates) {
+ol.geom.MultiPoint.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
this.setFlatCoordinatesInternal(layout, flatCoordinates);
this.changed();
};
@@ -89572,8 +72106,7 @@ goog.require('ol.extent');
* @param {number} stride Stride.
* @return {Array.<number>} Flat centers.
*/
-ol.geom.flat.center.linearRingss =
- function(flatCoordinates, offset, endss, stride) {
+ol.geom.flat.center.linearRingss = function(flatCoordinates, offset, endss, stride) {
var flatCenters = [];
var i, ii;
var extent = ol.extent.createEmpty();
@@ -89589,10 +72122,9 @@ ol.geom.flat.center.linearRingss =
goog.provide('ol.geom.MultiPolygon');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('ol');
+goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.geom.GeometryLayout');
goog.require('ol.geom.GeometryType');
@@ -89611,7 +72143,6 @@ goog.require('ol.geom.flat.orient');
goog.require('ol.geom.flat.simplify');
-
/**
* @classdesc
* Multi-polygon geometry.
@@ -89690,7 +72221,7 @@ ol.geom.MultiPolygon.prototype.appendPolygon = function(polygon) {
this.endss_.push();
} else {
var offset = this.flatCoordinates.length;
- goog.array.extend(this.flatCoordinates, polygon.getFlatCoordinates());
+ ol.array.extend(this.flatCoordinates, polygon.getFlatCoordinates());
ends = polygon.getEnds().slice();
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
@@ -89709,8 +72240,13 @@ ol.geom.MultiPolygon.prototype.appendPolygon = function(polygon) {
*/
ol.geom.MultiPolygon.prototype.clone = function() {
var multiPolygon = new ol.geom.MultiPolygon(null);
- var newEndss = /** @type {Array.<Array.<number>>} */
- (goog.object.unsafeClone(this.endss_));
+
+ var len = this.endss_.length;
+ var newEndss = new Array(len);
+ for (var i = 0; i < len; ++i) {
+ newEndss[i] = this.endss_[i].slice();
+ }
+
multiPolygon.setFlatCoordinates(
this.layout, this.flatCoordinates.slice(), newEndss);
return multiPolygon;
@@ -89720,8 +72256,7 @@ ol.geom.MultiPolygon.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.MultiPolygon.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.MultiPolygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance <
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
@@ -89846,8 +72381,7 @@ ol.geom.MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
/**
* @inheritDoc
*/
-ol.geom.MultiPolygon.prototype.getSimplifiedGeometryInternal =
- function(squaredTolerance) {
+ol.geom.MultiPolygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
var simplifiedFlatCoordinates = [];
var simplifiedEndss = [];
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizess(
@@ -89950,8 +72484,7 @@ ol.geom.MultiPolygon.prototype.intersectsExtent = function(extent) {
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
* @api stable
*/
-ol.geom.MultiPolygon.prototype.setCoordinates =
- function(coordinates, opt_layout) {
+ol.geom.MultiPolygon.prototype.setCoordinates = function(coordinates, opt_layout) {
if (!coordinates) {
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.endss_);
} else {
@@ -89978,8 +72511,7 @@ ol.geom.MultiPolygon.prototype.setCoordinates =
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {Array.<Array.<number>>} endss Endss.
*/
-ol.geom.MultiPolygon.prototype.setFlatCoordinates =
- function(layout, flatCoordinates, endss) {
+ol.geom.MultiPolygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, endss) {
goog.asserts.assert(endss, 'endss must be truthy');
if (!flatCoordinates || flatCoordinates.length === 0) {
goog.asserts.assert(endss.length === 0, 'the length of endss should be 0');
@@ -90018,7 +72550,7 @@ ol.geom.MultiPolygon.prototype.setPolygons = function(polygons) {
for (j = 0, jj = ends.length; j < jj; ++j) {
ends[j] += offset;
}
- goog.array.extend(flatCoordinates, polygon.getFlatCoordinates());
+ ol.array.extend(flatCoordinates, polygon.getFlatCoordinates());
endss.push(ends);
}
this.setFlatCoordinates(layout, flatCoordinates, endss);
@@ -90026,10 +72558,9 @@ ol.geom.MultiPolygon.prototype.setPolygons = function(polygons) {
goog.provide('ol.format.EsriJSON');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('ol.Feature');
+goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.format.Feature');
goog.require('ol.format.JSONFeature');
@@ -90043,10 +72574,10 @@ goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
goog.require('ol.geom.flat.orient');
+goog.require('ol.object');
goog.require('ol.proj');
-
/**
* @classdesc
* Feature format for reading and writing data in the EsriJSON format.
@@ -90097,7 +72628,7 @@ ol.format.EsriJSON.readGeometry_ = function(object, opt_options) {
} else if (object.rings) {
var layout = ol.format.EsriJSON.getGeometryLayout_(object);
var rings = ol.format.EsriJSON.convertRings_(object.rings, layout);
- object = /** @type {EsriJSONGeometry} */(goog.object.clone(object));
+ object = /** @type {EsriJSONGeometry} */(ol.object.assign({}, object));
if (rings.length === 1) {
type = ol.geom.GeometryType.POLYGON;
object.rings = rings[0];
@@ -90131,7 +72662,7 @@ ol.format.EsriJSON.convertRings_ = function(rings, layout) {
var holes = [];
var i, ii;
for (i = 0, ii = rings.length; i < ii; ++i) {
- var flatRing = goog.array.flatten(rings[i]);
+ var flatRing = ol.array.flatten(rings[i]);
// is this ring an outer ring? is it clockwise?
var clockwise = ol.geom.flat.orient.linearRingIsClockwise(flatRing, 0,
flatRing.length, layout.length);
@@ -90197,7 +72728,7 @@ ol.format.EsriJSON.readPointGeometry_ = function(object) {
* @return {ol.geom.Geometry} LineString.
*/
ol.format.EsriJSON.readLineStringGeometry_ = function(object) {
- goog.asserts.assert(goog.isArray(object.paths),
+ goog.asserts.assert(Array.isArray(object.paths),
'object.paths should be an array');
goog.asserts.assert(object.paths.length === 1,
'object.paths array length should be 1');
@@ -90212,7 +72743,7 @@ ol.format.EsriJSON.readLineStringGeometry_ = function(object) {
* @return {ol.geom.Geometry} MultiLineString.
*/
ol.format.EsriJSON.readMultiLineStringGeometry_ = function(object) {
- goog.asserts.assert(goog.isArray(object.paths),
+ goog.asserts.assert(Array.isArray(object.paths),
'object.paths should be an array');
goog.asserts.assert(object.paths.length > 1,
'object.paths array length should be more than 1');
@@ -90379,8 +72910,7 @@ ol.format.EsriJSON.writePolygonGeometry_ = function(geometry, opt_options) {
* @private
* @return {EsriJSONPolyline} EsriJSON geometry.
*/
-ol.format.EsriJSON.writeMultiLineStringGeometry_ =
- function(geometry, opt_options) {
+ol.format.EsriJSON.writeMultiLineStringGeometry_ = function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString,
'geometry should be an ol.geom.MultiLineString');
var hasZM = ol.format.EsriJSON.getHasZM_(geometry);
@@ -90679,7 +73209,7 @@ ol.format.EsriJSON.prototype.writeFeatureObject = function(
}
var properties = feature.getProperties();
delete properties[feature.getGeometryName()];
- if (!goog.object.isEmpty(properties)) {
+ if (!ol.object.isEmpty(properties)) {
object['attributes'] = properties;
} else {
object['attributes'] = {};
@@ -90714,8 +73244,7 @@ ol.format.EsriJSON.prototype.writeFeatures;
* @return {Object} EsriJSON Object.
* @api
*/
-ol.format.EsriJSON.prototype.writeFeaturesObject =
- function(features, opt_options) {
+ol.format.EsriJSON.prototype.writeFeaturesObject = function(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
var objects = [];
var i, ii;
@@ -90729,13 +73258,12 @@ ol.format.EsriJSON.prototype.writeFeaturesObject =
goog.provide('ol.geom.GeometryCollection');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryType');
-
+goog.require('ol.object');
/**
@@ -90786,9 +73314,9 @@ ol.geom.GeometryCollection.prototype.unlistenGeometriesChange_ = function() {
return;
}
for (i = 0, ii = this.geometries_.length; i < ii; ++i) {
- goog.events.unlisten(
- this.geometries_[i], goog.events.EventType.CHANGE,
- this.changed, false, this);
+ ol.events.unlisten(
+ this.geometries_[i], ol.events.EventType.CHANGE,
+ this.changed, this);
}
};
@@ -90802,9 +73330,9 @@ ol.geom.GeometryCollection.prototype.listenGeometriesChange_ = function() {
return;
}
for (i = 0, ii = this.geometries_.length; i < ii; ++i) {
- goog.events.listen(
- this.geometries_[i], goog.events.EventType.CHANGE,
- this.changed, false, this);
+ ol.events.listen(
+ this.geometries_[i], ol.events.EventType.CHANGE,
+ this.changed, this);
}
};
@@ -90824,8 +73352,7 @@ ol.geom.GeometryCollection.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.GeometryCollection.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.GeometryCollection.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance <
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
@@ -90889,10 +73416,9 @@ ol.geom.GeometryCollection.prototype.getGeometriesArray = function() {
/**
* @inheritDoc
*/
-ol.geom.GeometryCollection.prototype.getSimplifiedGeometry =
- function(squaredTolerance) {
+ol.geom.GeometryCollection.prototype.getSimplifiedGeometry = function(squaredTolerance) {
if (this.simplifiedGeometryRevision != this.getRevision()) {
- goog.object.clear(this.simplifiedGeometryCache);
+ ol.object.clear(this.simplifiedGeometryCache);
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
this.simplifiedGeometryRevision = this.getRevision();
}
@@ -90964,6 +73490,19 @@ ol.geom.GeometryCollection.prototype.isEmpty = function() {
/**
+ * @inheritDoc
+ * @api
+ */
+ol.geom.GeometryCollection.prototype.rotate = function(angle, anchor) {
+ var geometries = this.geometries_;
+ for (var i = 0, ii = geometries.length; i < ii; ++i) {
+ geometries[i].rotate(angle, anchor);
+ }
+ this.changed();
+};
+
+
+/**
* Set the geometries that make up this geometry collection.
* @param {Array.<ol.geom.Geometry>} geometries Geometries.
* @api stable
@@ -91029,7 +73568,6 @@ ol.geom.GeometryCollection.prototype.disposeInternal = function() {
goog.provide('ol.format.GeoJSON');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('ol.Feature');
goog.require('ol.format.Feature');
goog.require('ol.format.JSONFeature');
@@ -91040,10 +73578,10 @@ goog.require('ol.geom.MultiPoint');
goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
+goog.require('ol.object');
goog.require('ol.proj');
-
/**
* @classdesc
* Feature format for reading and writing data in the GeoJSON format.
@@ -91237,7 +73775,9 @@ ol.format.GeoJSON.writeGeometryCollectionGeometry_ = function(
goog.asserts.assertInstanceof(geometry, ol.geom.GeometryCollection,
'geometry should be an ol.geom.GeometryCollection');
var geometries = geometry.getGeometriesArray().map(function(geometry) {
- return ol.format.GeoJSON.writeGeometry_(geometry, opt_options);
+ var options = ol.object.assign({}, opt_options);
+ delete options.featureProjection;
+ return ol.format.GeoJSON.writeGeometry_(geometry, options);
});
return /** @type {GeoJSONGeometryCollection} */ ({
type: 'GeometryCollection',
@@ -91268,8 +73808,7 @@ ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry, opt_options) {
* @private
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
-ol.format.GeoJSON.writeMultiLineStringGeometry_ =
- function(geometry, opt_options) {
+ol.format.GeoJSON.writeMultiLineStringGeometry_ = function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString,
'geometry should be an ol.geom.MultiLineString');
return /** @type {GeoJSONGeometry} */ ({
@@ -91545,32 +74084,32 @@ ol.format.GeoJSON.prototype.writeFeature;
*
* @param {ol.Feature} feature Feature.
* @param {olx.format.WriteOptions=} opt_options Write options.
- * @return {Object} Object.
+ * @return {GeoJSONFeature} Object.
* @api stable
*/
-ol.format.GeoJSON.prototype.writeFeatureObject = function(
- feature, opt_options) {
+ol.format.GeoJSON.prototype.writeFeatureObject = function(feature, opt_options) {
opt_options = this.adaptOptions(opt_options);
- var object = {
+
+ var object = /** @type {GeoJSONFeature} */ ({
'type': 'Feature'
- };
+ });
var id = feature.getId();
if (id !== undefined) {
- object['id'] = id;
+ object.id = id;
}
var geometry = feature.getGeometry();
if (geometry) {
- object['geometry'] =
+ object.geometry =
ol.format.GeoJSON.writeGeometry_(geometry, opt_options);
} else {
- object['geometry'] = null;
+ object.geometry = null;
}
var properties = feature.getProperties();
delete properties[feature.getGeometryName()];
- if (!goog.object.isEmpty(properties)) {
- object['properties'] = properties;
+ if (!ol.object.isEmpty(properties)) {
+ object.properties = properties;
} else {
- object['properties'] = null;
+ object.properties = null;
}
return object;
};
@@ -91593,11 +74132,10 @@ ol.format.GeoJSON.prototype.writeFeatures;
*
* @param {Array.<ol.Feature>} features Features.
* @param {olx.format.WriteOptions=} opt_options Write options.
- * @return {Object} GeoJSON Object.
+ * @return {GeoJSONFeatureCollection} GeoJSON Object.
* @api stable
*/
-ol.format.GeoJSON.prototype.writeFeaturesObject =
- function(features, opt_options) {
+ol.format.GeoJSON.prototype.writeFeaturesObject = function(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
var objects = [];
var i, ii;
@@ -91639,17 +74177,15 @@ ol.format.GeoJSON.prototype.writeGeometryObject = function(geometry,
goog.provide('ol.format.XMLFeature');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
-goog.require('goog.dom.xml');
+goog.require('ol.array');
goog.require('ol.format.Feature');
goog.require('ol.format.FormatType');
goog.require('ol.proj');
goog.require('ol.xml');
-
/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
@@ -91660,6 +74196,13 @@ goog.require('ol.xml');
* @extends {ol.format.Feature}
*/
ol.format.XMLFeature = function() {
+
+ /**
+ * @type {XMLSerializer}
+ * @private
+ */
+ this.xmlSerializer_ = new XMLSerializer();
+
goog.base(this);
};
goog.inherits(ol.format.XMLFeature, ol.format.Feature);
@@ -91682,7 +74225,7 @@ ol.format.XMLFeature.prototype.readFeature = function(source, opt_options) {
/** @type {Document} */ (source), opt_options);
} else if (ol.xml.isNode(source)) {
return this.readFeatureFromNode(/** @type {Node} */ (source), opt_options);
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
return this.readFeatureFromDocument(doc, opt_options);
} else {
@@ -91725,7 +74268,7 @@ ol.format.XMLFeature.prototype.readFeatures = function(source, opt_options) {
/** @type {Document} */ (source), opt_options);
} else if (ol.xml.isNode(source)) {
return this.readFeaturesFromNode(/** @type {Node} */ (source), opt_options);
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
return this.readFeaturesFromDocument(doc, opt_options);
} else {
@@ -91748,7 +74291,7 @@ ol.format.XMLFeature.prototype.readFeaturesFromDocument = function(
var n;
for (n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
- goog.array.extend(features, this.readFeaturesFromNode(n, opt_options));
+ ol.array.extend(features, this.readFeaturesFromNode(n, opt_options));
}
}
return features;
@@ -91773,7 +74316,7 @@ ol.format.XMLFeature.prototype.readGeometry = function(source, opt_options) {
/** @type {Document} */ (source), opt_options);
} else if (ol.xml.isNode(source)) {
return this.readGeometryFromNode(/** @type {Node} */ (source), opt_options);
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
return this.readGeometryFromDocument(doc, opt_options);
} else {
@@ -91809,7 +74352,7 @@ ol.format.XMLFeature.prototype.readProjection = function(source) {
return this.readProjectionFromDocument(/** @type {Document} */ (source));
} else if (ol.xml.isNode(source)) {
return this.readProjectionFromNode(/** @type {Node} */ (source));
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
return this.readProjectionFromDocument(doc);
} else {
@@ -91846,7 +74389,7 @@ ol.format.XMLFeature.prototype.writeFeature = function(feature, opt_options) {
var node = this.writeFeatureNode(feature, opt_options);
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
- return goog.dom.xml.serialize(/** @type {Element} */(node));
+ return this.xmlSerializer_.serializeToString(node);
};
@@ -91866,7 +74409,7 @@ ol.format.XMLFeature.prototype.writeFeatures = function(features, opt_options) {
var node = this.writeFeaturesNode(features, opt_options);
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
- return goog.dom.xml.serialize(/** @type {Element} */(node));
+ return this.xmlSerializer_.serializeToString(node);
};
@@ -91885,7 +74428,7 @@ ol.format.XMLFeature.prototype.writeGeometry = function(geometry, opt_options) {
var node = this.writeGeometryNode(geometry, opt_options);
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
- return goog.dom.xml.serialize(/** @type {Element} */(node));
+ return this.xmlSerializer_.serializeToString(node);
};
@@ -91901,11 +74444,9 @@ ol.format.XMLFeature.prototype.writeGeometryNode = goog.abstractMethod;
// envelopes/extents, only geometries!
goog.provide('ol.format.GMLBase');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
-goog.require('goog.object');
-goog.require('goog.string');
+goog.require('ol.array');
goog.require('ol.Feature');
goog.require('ol.format.Feature');
goog.require('ol.format.XMLFeature');
@@ -91918,11 +74459,11 @@ goog.require('ol.geom.MultiPoint');
goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.xml');
-
/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
@@ -91989,15 +74530,30 @@ ol.format.GMLBase.GMLNS = 'http://www.opengis.net/gml';
/**
+ * A regular expression that matches if a string only contains whitespace
+ * characters. It will e.g. match `''`, `' '`, `'\n'` etc. The non-breaking
+ * space (0xa0) is explicitly included as IE doesn't include it in its
+ * definition of `\s`.
+ *
+ * Information from `goog.string.isEmptyOrWhitespace`: https://github.com/google/closure-library/blob/e877b1e/closure/goog/string/string.js#L156-L160
+ *
+ * @const
+ * @type {RegExp}
+ * @private
+ */
+ol.format.GMLBase.ONLY_WHITESPACE_RE_ = /^[\s\xa0]*$/;
+
+
+/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
- * @return {Array.<ol.Feature>} Features.
+ * @return {Array.<ol.Feature> | undefined} Features.
*/
ol.format.GMLBase.prototype.readFeaturesInternal = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
- var localName = ol.xml.getLocalName(node);
- var features;
+ var localName = node.localName;
+ var features = null;
if (localName == 'FeatureCollection') {
if (node.namespaceURI === 'http://www.opengis.net/wfs') {
features = ol.xml.pushParseAndPop([],
@@ -92021,29 +74577,37 @@ ol.format.GMLBase.prototype.readFeaturesInternal = function(node, objectStack) {
if (child.nodeType === 1) {
var ft = child.nodeName.split(':').pop();
if (featureType.indexOf(ft) === -1) {
- var key;
- if (!goog.object.contains(featureNS, child.namespaceURI)) {
- key = prefix + goog.object.getCount(featureNS);
- featureNS[key] = child.namespaceURI;
- } else {
- key = goog.object.findKey(featureNS, function(value) {
- return value === child.namespaceURI;
- });
+ var key = '';
+ var count = 0;
+ var uri = child.namespaceURI;
+ for (var candidate in featureNS) {
+ if (featureNS[candidate] === uri) {
+ key = candidate;
+ break;
+ }
+ ++count;
+ }
+ if (!key) {
+ key = prefix + count;
+ featureNS[key] = uri;
}
featureType.push(key + ':' + ft);
}
}
}
- context['featureType'] = featureType;
- context['featureNS'] = featureNS;
+ if (localName != 'featureMember') {
+ // recheck featureType for each featureMember
+ context['featureType'] = featureType;
+ context['featureNS'] = featureNS;
+ }
}
- if (goog.isString(featureNS)) {
+ if (typeof featureNS === 'string') {
var ns = featureNS;
featureNS = {};
featureNS[defaultPrefix] = ns;
}
var parsersNS = {};
- var featureTypes = goog.isArray(featureType) ? featureType : [featureType];
+ var featureTypes = Array.isArray(featureType) ? featureType : [featureType];
for (var p in featureNS) {
var parsers = {};
for (i = 0, ii = featureTypes.length; i < ii; ++i) {
@@ -92058,9 +74622,13 @@ ol.format.GMLBase.prototype.readFeaturesInternal = function(node, objectStack) {
}
parsersNS[featureNS[p]] = parsers;
}
- features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack);
+ if (localName == 'featureMember') {
+ features = ol.xml.pushParseAndPop(undefined, parsersNS, node, objectStack);
+ } else {
+ features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack);
+ }
}
- if (!features) {
+ if (features === null) {
features = [];
}
return features;
@@ -92076,7 +74644,8 @@ ol.format.GMLBase.prototype.readGeometryElement = function(node, objectStack) {
var context = objectStack[0];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
context['srsName'] = node.firstElementChild.getAttribute('srsName');
- var geometry = ol.xml.pushParseAndPop(/** @type {ol.geom.Geometry} */(null),
+ /** @type {ol.geom.Geometry} */
+ var geometry = ol.xml.pushParseAndPop(null,
this.GEOMETRY_PARSERS_, node, objectStack, this);
if (geometry) {
return /** @type {ol.geom.Geometry} */ (
@@ -92098,7 +74667,7 @@ ol.format.GMLBase.prototype.readFeatureElement = function(node, objectStack) {
ol.xml.getAttributeNS(node, ol.format.GMLBase.GMLNS, 'id');
var values = {}, geometryName;
for (n = node.firstElementChild; n; n = n.nextElementSibling) {
- var localName = ol.xml.getLocalName(n);
+ var localName = n.localName;
// Assume attribute elements have one child node and that the child
// is a text or CDATA node (to be treated as text).
// Otherwise assume it is a geometry node.
@@ -92106,7 +74675,7 @@ ol.format.GMLBase.prototype.readFeatureElement = function(node, objectStack) {
(n.childNodes.length === 1 &&
(n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) {
var value = ol.xml.getAllTextContent(n, false);
- if (goog.string.isEmpty(value)) {
+ if (ol.format.GMLBase.ONLY_WHITESPACE_RE_.test(value)) {
value = undefined;
}
values[localName] = value;
@@ -92160,8 +74729,8 @@ ol.format.GMLBase.prototype.readMultiPoint = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'MultiPoint',
'localName should be MultiPoint');
- var coordinates = ol.xml.pushParseAndPop(
- /** @type {Array.<Array.<number>>} */ ([]),
+ /** @type {Array.<Array.<number>>} */
+ var coordinates = ol.xml.pushParseAndPop([],
this.MULTIPOINT_PARSERS_, node, objectStack, this);
if (coordinates) {
return new ol.geom.MultiPoint(coordinates);
@@ -92181,8 +74750,8 @@ ol.format.GMLBase.prototype.readMultiLineString = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'MultiLineString',
'localName should be MultiLineString');
- var lineStrings = ol.xml.pushParseAndPop(
- /** @type {Array.<ol.geom.LineString>} */ ([]),
+ /** @type {Array.<ol.geom.LineString>} */
+ var lineStrings = ol.xml.pushParseAndPop([],
this.MULTILINESTRING_PARSERS_, node, objectStack, this);
if (lineStrings) {
var multiLineString = new ol.geom.MultiLineString(null);
@@ -92204,8 +74773,8 @@ ol.format.GMLBase.prototype.readMultiPolygon = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'MultiPolygon',
'localName should be MultiPolygon');
- var polygons = ol.xml.pushParseAndPop(
- /** @type {Array.<ol.geom.Polygon>} */ ([]),
+ /** @type {Array.<ol.geom.Polygon>} */
+ var polygons = ol.xml.pushParseAndPop([],
this.MULTIPOLYGON_PARSERS_, node, objectStack, this);
if (polygons) {
var multiPolygon = new ol.geom.MultiPolygon(null);
@@ -92238,8 +74807,7 @@ ol.format.GMLBase.prototype.pointMemberParser_ = function(node, objectStack) {
* @param {Array.<*>} objectStack Object stack.
* @private
*/
-ol.format.GMLBase.prototype.lineStringMemberParser_ =
- function(node, objectStack) {
+ol.format.GMLBase.prototype.lineStringMemberParser_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'lineStringMember' ||
@@ -92255,8 +74823,7 @@ ol.format.GMLBase.prototype.lineStringMemberParser_ =
* @param {Array.<*>} objectStack Object stack.
* @private
*/
-ol.format.GMLBase.prototype.polygonMemberParser_ =
- function(node, objectStack) {
+ol.format.GMLBase.prototype.polygonMemberParser_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'polygonMember' ||
@@ -92300,7 +74867,7 @@ ol.format.GMLBase.prototype.readFlatLinearRing_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'LinearRing',
'localName should be LinearRing');
- var ring = ol.xml.pushParseAndPop(/** @type {Array.<number>} */(null),
+ var ring = ol.xml.pushParseAndPop(null,
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
objectStack, this);
if (ring) {
@@ -92343,8 +74910,8 @@ ol.format.GMLBase.prototype.readPolygon = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'Polygon',
'localName should be Polygon');
- var flatLinearRings = ol.xml.pushParseAndPop(
- /** @type {Array.<Array.<number>>} */ ([null]),
+ /** @type {Array.<Array.<number>>} */
+ var flatLinearRings = ol.xml.pushParseAndPop([null],
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
if (flatLinearRings && flatLinearRings[0]) {
var polygon = new ol.geom.Polygon(null);
@@ -92352,7 +74919,7 @@ ol.format.GMLBase.prototype.readPolygon = function(node, objectStack) {
var ends = [flatCoordinates.length];
var i, ii;
for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
- goog.array.extend(flatCoordinates, flatLinearRings[i]);
+ ol.array.extend(flatCoordinates, flatLinearRings[i]);
ends.push(flatCoordinates.length);
}
polygon.setFlatCoordinates(
@@ -92370,119 +74937,116 @@ ol.format.GMLBase.prototype.readPolygon = function(node, objectStack) {
* @private
* @return {Array.<number>} Flat coordinates.
*/
-ol.format.GMLBase.prototype.readFlatCoordinatesFromNode_ =
- function(node, objectStack) {
+ol.format.GMLBase.prototype.readFlatCoordinatesFromNode_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
- return /** @type {Array.<number>} */ (ol.xml.pushParseAndPop(
- null,
+ return ol.xml.pushParseAndPop(null,
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
- objectStack, this));
+ objectStack, this);
};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GMLBase.prototype.MULTIPOINT_PARSERS_ = Object({
+ol.format.GMLBase.prototype.MULTIPOINT_PARSERS_ = {
'http://www.opengis.net/gml' : {
'pointMember': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.pointMemberParser_),
'pointMembers': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.pointMemberParser_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GMLBase.prototype.MULTILINESTRING_PARSERS_ = Object({
+ol.format.GMLBase.prototype.MULTILINESTRING_PARSERS_ = {
'http://www.opengis.net/gml' : {
'lineStringMember': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.lineStringMemberParser_),
'lineStringMembers': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.lineStringMemberParser_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GMLBase.prototype.MULTIPOLYGON_PARSERS_ = Object({
+ol.format.GMLBase.prototype.MULTIPOLYGON_PARSERS_ = {
'http://www.opengis.net/gml' : {
'polygonMember': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.polygonMemberParser_),
'polygonMembers': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.polygonMemberParser_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GMLBase.prototype.POINTMEMBER_PARSERS_ = Object({
+ol.format.GMLBase.prototype.POINTMEMBER_PARSERS_ = {
'http://www.opengis.net/gml' : {
'Point': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.readFlatCoordinatesFromNode_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GMLBase.prototype.LINESTRINGMEMBER_PARSERS_ = Object({
+ol.format.GMLBase.prototype.LINESTRINGMEMBER_PARSERS_ = {
'http://www.opengis.net/gml' : {
'LineString': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.readLineString)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GMLBase.prototype.POLYGONMEMBER_PARSERS_ = Object({
+ol.format.GMLBase.prototype.POLYGONMEMBER_PARSERS_ = {
'http://www.opengis.net/gml' : {
'Polygon': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.readPolygon)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @protected
*/
-ol.format.GMLBase.prototype.RING_PARSERS = Object({
+ol.format.GMLBase.prototype.RING_PARSERS = {
'http://www.opengis.net/gml' : {
'LinearRing': ol.xml.makeReplacer(
ol.format.GMLBase.prototype.readFlatLinearRing_)
}
-});
+};
/**
* @inheritDoc
*/
-ol.format.GMLBase.prototype.readGeometryFromNode =
- function(node, opt_options) {
+ol.format.GMLBase.prototype.readGeometryFromNode = function(node, opt_options) {
var geometry = this.readGeometryElement(node,
[this.getReadOptions(node, opt_options ? opt_options : {})]);
return geometry ? geometry : null;
@@ -92504,16 +75068,16 @@ ol.format.GMLBase.prototype.readFeatures;
/**
* @inheritDoc
*/
-ol.format.GMLBase.prototype.readFeaturesFromNode =
- function(node, opt_options) {
+ol.format.GMLBase.prototype.readFeaturesFromNode = function(node, opt_options) {
var options = {
featureType: this.featureType,
featureNS: this.featureNS
};
if (opt_options) {
- goog.object.extend(options, this.getReadOptions(node, opt_options));
+ ol.object.assign(options, this.getReadOptions(node, opt_options));
}
- return this.readFeaturesInternal(node, [options]);
+ var features = this.readFeaturesInternal(node, [options]);
+ return features || [];
};
@@ -92521,16 +75085,16 @@ ol.format.GMLBase.prototype.readFeaturesFromNode =
* @inheritDoc
*/
ol.format.GMLBase.prototype.readProjectionFromNode = function(node) {
- return ol.proj.get(this.srsName_ ? this.srsName_ :
+ return ol.proj.get(this.srsName ? this.srsName :
node.firstElementChild.getAttribute('srsName'));
};
goog.provide('ol.format.XSD');
goog.require('goog.asserts');
-goog.require('goog.string');
goog.require('ol');
goog.require('ol.xml');
+goog.require('ol.string');
/**
@@ -92669,11 +75233,11 @@ ol.format.XSD.writeBooleanTextNode = function(node, bool) {
ol.format.XSD.writeDateTimeTextNode = function(node, dateTime) {
var date = new Date(dateTime * 1000);
var string = date.getUTCFullYear() + '-' +
- goog.string.padNumber(date.getUTCMonth() + 1, 2) + '-' +
- goog.string.padNumber(date.getUTCDate(), 2) + 'T' +
- goog.string.padNumber(date.getUTCHours(), 2) + ':' +
- goog.string.padNumber(date.getUTCMinutes(), 2) + ':' +
- goog.string.padNumber(date.getUTCSeconds(), 2) + 'Z';
+ ol.string.padNumber(date.getUTCMonth() + 1, 2) + '-' +
+ ol.string.padNumber(date.getUTCDate(), 2) + 'T' +
+ ol.string.padNumber(date.getUTCHours(), 2) + ':' +
+ ol.string.padNumber(date.getUTCMinutes(), 2) + ':' +
+ ol.string.padNumber(date.getUTCSeconds(), 2) + 'Z';
node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
};
@@ -92692,8 +75256,7 @@ ol.format.XSD.writeDecimalTextNode = function(node, decimal) {
* @param {Node} node Node to append a TextNode with the decimal to.
* @param {number} nonNegativeInteger Non negative integer.
*/
-ol.format.XSD.writeNonNegativeIntegerTextNode =
- function(node, nonNegativeInteger) {
+ol.format.XSD.writeNonNegativeIntegerTextNode = function(node, nonNegativeInteger) {
goog.asserts.assert(nonNegativeInteger >= 0, 'value should be more than 0');
goog.asserts.assert(nonNegativeInteger == (nonNegativeInteger | 0),
'value should be an integer value');
@@ -92721,7 +75284,6 @@ goog.require('ol.proj');
goog.require('ol.xml');
-
/**
* @classdesc
* Feature format for reading and writing data in the GML format,
@@ -92818,8 +75380,8 @@ ol.format.GML2.prototype.readBox_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'Box', 'localName should be Box');
- var flatCoordinates = ol.xml.pushParseAndPop(
- /** @type {Array.<number>} */ ([null]),
+ /** @type {Array.<number>} */
+ var flatCoordinates = ol.xml.pushParseAndPop([null],
this.BOX_PARSERS_, node, objectStack, this);
return ol.extent.createOrUpdate(flatCoordinates[1][0],
flatCoordinates[1][1], flatCoordinates[1][3],
@@ -92832,19 +75394,18 @@ ol.format.GML2.prototype.readBox_ = function(node, objectStack) {
* @param {Array.<*>} objectStack Object stack.
* @private
*/
-ol.format.GML2.prototype.innerBoundaryIsParser_ =
- function(node, objectStack) {
+ol.format.GML2.prototype.innerBoundaryIsParser_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'innerBoundaryIs',
'localName should be innerBoundaryIs');
- var flatLinearRing = ol.xml.pushParseAndPop(
- /** @type {Array.<number>|undefined} */ (undefined),
+ /** @type {Array.<number>|undefined} */
+ var flatLinearRing = ol.xml.pushParseAndPop(undefined,
this.RING_PARSERS, node, objectStack, this);
if (flatLinearRing) {
var flatLinearRings = /** @type {Array.<Array.<number>>} */
(objectStack[objectStack.length - 1]);
- goog.asserts.assert(goog.isArray(flatLinearRings),
+ goog.asserts.assert(Array.isArray(flatLinearRings),
'flatLinearRings should be an array');
goog.asserts.assert(flatLinearRings.length > 0,
'flatLinearRings should have an array length larger than 0');
@@ -92858,19 +75419,18 @@ ol.format.GML2.prototype.innerBoundaryIsParser_ =
* @param {Array.<*>} objectStack Object stack.
* @private
*/
-ol.format.GML2.prototype.outerBoundaryIsParser_ =
- function(node, objectStack) {
+ol.format.GML2.prototype.outerBoundaryIsParser_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'outerBoundaryIs',
'localName should be outerBoundaryIs');
- var flatLinearRing = ol.xml.pushParseAndPop(
- /** @type {Array.<number>|undefined} */ (undefined),
+ /** @type {Array.<number>|undefined} */
+ var flatLinearRing = ol.xml.pushParseAndPop(undefined,
this.RING_PARSERS, node, objectStack, this);
if (flatLinearRing) {
var flatLinearRings = /** @type {Array.<Array.<number>>} */
(objectStack[objectStack.length - 1]);
- goog.asserts.assert(goog.isArray(flatLinearRings),
+ goog.asserts.assert(Array.isArray(flatLinearRings),
'flatLinearRings should be an array');
goog.asserts.assert(flatLinearRings.length > 0,
'flatLinearRings should have an array length larger than 0');
@@ -92881,49 +75441,49 @@ ol.format.GML2.prototype.outerBoundaryIsParser_ =
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = Object({
+ol.format.GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
'http://www.opengis.net/gml' : {
'coordinates': ol.xml.makeReplacer(
ol.format.GML2.prototype.readFlatCoordinates_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML2.prototype.FLAT_LINEAR_RINGS_PARSERS_ = Object({
+ol.format.GML2.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
'http://www.opengis.net/gml' : {
'innerBoundaryIs': ol.format.GML2.prototype.innerBoundaryIsParser_,
'outerBoundaryIs': ol.format.GML2.prototype.outerBoundaryIsParser_
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML2.prototype.BOX_PARSERS_ = Object({
+ol.format.GML2.prototype.BOX_PARSERS_ = {
'http://www.opengis.net/gml' : {
'coordinates': ol.xml.makeArrayPusher(
ol.format.GML2.prototype.readFlatCoordinates_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML2.prototype.GEOMETRY_PARSERS_ = Object({
+ol.format.GML2.prototype.GEOMETRY_PARSERS_ = {
'http://www.opengis.net/gml' : {
'Point': ol.xml.makeReplacer(ol.format.GMLBase.prototype.readPoint),
'MultiPoint': ol.xml.makeReplacer(
@@ -92939,16 +75499,15 @@ ol.format.GML2.prototype.GEOMETRY_PARSERS_ = Object({
ol.format.GMLBase.prototype.readMultiPolygon),
'Box': ol.xml.makeReplacer(ol.format.GML2.prototype.readBox_)
}
-});
+};
goog.provide('ol.format.GML');
goog.provide('ol.format.GML3');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
-goog.require('goog.object');
goog.require('ol');
+goog.require('ol.array');
goog.require('ol.Feature');
goog.require('ol.extent');
goog.require('ol.format.Feature');
@@ -92962,11 +75521,11 @@ goog.require('ol.geom.MultiLineString');
goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.xml');
-
/**
* @classdesc
* Feature format for reading and writing data in the GML format
@@ -93042,8 +75601,8 @@ ol.format.GML3.prototype.readMultiCurve_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'MultiCurve',
'localName should be MultiCurve');
- var lineStrings = ol.xml.pushParseAndPop(
- /** @type {Array.<ol.geom.LineString>} */ ([]),
+ /** @type {Array.<ol.geom.LineString>} */
+ var lineStrings = ol.xml.pushParseAndPop([],
this.MULTICURVE_PARSERS_, node, objectStack, this);
if (lineStrings) {
var multiLineString = new ol.geom.MultiLineString(null);
@@ -93066,8 +75625,8 @@ ol.format.GML3.prototype.readMultiSurface_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'MultiSurface',
'localName should be MultiSurface');
- var polygons = ol.xml.pushParseAndPop(
- /** @type {Array.<ol.geom.Polygon>} */ ([]),
+ /** @type {Array.<ol.geom.Polygon>} */
+ var polygons = ol.xml.pushParseAndPop([],
this.MULTISURFACE_PARSERS_, node, objectStack, this);
if (polygons) {
var multiPolygon = new ol.geom.MultiPolygon(null);
@@ -93121,8 +75680,7 @@ ol.format.GML3.prototype.readPatch_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'patches',
'localName should be patches');
- return ol.xml.pushParseAndPop(
- /** @type {Array.<Array.<number>>} */ ([null]),
+ return ol.xml.pushParseAndPop([null],
this.PATCHES_PARSERS_, node, objectStack, this);
};
@@ -93138,8 +75696,7 @@ ol.format.GML3.prototype.readSegment_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'segments',
'localName should be segments');
- return ol.xml.pushParseAndPop(
- /** @type {Array.<number>} */ ([null]),
+ return ol.xml.pushParseAndPop([null],
this.SEGMENTS_PARSERS_, node, objectStack, this);
};
@@ -93155,8 +75712,7 @@ ol.format.GML3.prototype.readPolygonPatch_ = function(node, objectStack) {
'npde.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'PolygonPatch',
'localName should be PolygonPatch');
- return ol.xml.pushParseAndPop(
- /** @type {Array.<Array.<number>>} */ ([null]),
+ return ol.xml.pushParseAndPop([null],
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
};
@@ -93167,14 +75723,12 @@ ol.format.GML3.prototype.readPolygonPatch_ = function(node, objectStack) {
* @private
* @return {Array.<number>|undefined} flat coordinates.
*/
-ol.format.GML3.prototype.readLineStringSegment_ =
- function(node, objectStack) {
+ol.format.GML3.prototype.readLineStringSegment_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'LineStringSegment',
'localName should be LineStringSegment');
- return ol.xml.pushParseAndPop(
- /** @type {Array.<number>} */ ([null]),
+ return ol.xml.pushParseAndPop([null],
this.GEOMETRY_FLAT_COORDINATES_PARSERS_,
node, objectStack, this);
};
@@ -93190,13 +75744,13 @@ ol.format.GML3.prototype.interiorParser_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'interior',
'localName should be interior');
- var flatLinearRing = ol.xml.pushParseAndPop(
- /** @type {Array.<number>|undefined} */ (undefined),
+ /** @type {Array.<number>|undefined} */
+ var flatLinearRing = ol.xml.pushParseAndPop(undefined,
this.RING_PARSERS, node, objectStack, this);
if (flatLinearRing) {
var flatLinearRings = /** @type {Array.<Array.<number>>} */
(objectStack[objectStack.length - 1]);
- goog.asserts.assert(goog.isArray(flatLinearRings),
+ goog.asserts.assert(Array.isArray(flatLinearRings),
'flatLinearRings should be an array');
goog.asserts.assert(flatLinearRings.length > 0,
'flatLinearRings should have an array length of 1 or more');
@@ -93215,13 +75769,13 @@ ol.format.GML3.prototype.exteriorParser_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'exterior',
'localName should be exterior');
- var flatLinearRing = ol.xml.pushParseAndPop(
- /** @type {Array.<number>|undefined} */ (undefined),
+ /** @type {Array.<number>|undefined} */
+ var flatLinearRing = ol.xml.pushParseAndPop(undefined,
this.RING_PARSERS, node, objectStack, this);
if (flatLinearRing) {
var flatLinearRings = /** @type {Array.<Array.<number>>} */
(objectStack[objectStack.length - 1]);
- goog.asserts.assert(goog.isArray(flatLinearRings),
+ goog.asserts.assert(Array.isArray(flatLinearRings),
'flatLinearRings should be an array');
goog.asserts.assert(flatLinearRings.length > 0,
'flatLinearRings should have an array length of 1 or more');
@@ -93241,8 +75795,8 @@ ol.format.GML3.prototype.readSurface_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'Surface',
'localName should be Surface');
- var flatLinearRings = ol.xml.pushParseAndPop(
- /** @type {Array.<Array.<number>>} */ ([null]),
+ /** @type {Array.<Array.<number>>} */
+ var flatLinearRings = ol.xml.pushParseAndPop([null],
this.SURFACE_PARSERS_, node, objectStack, this);
if (flatLinearRings && flatLinearRings[0]) {
var polygon = new ol.geom.Polygon(null);
@@ -93250,7 +75804,7 @@ ol.format.GML3.prototype.readSurface_ = function(node, objectStack) {
var ends = [flatCoordinates.length];
var i, ii;
for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
- goog.array.extend(flatCoordinates, flatLinearRings[i]);
+ ol.array.extend(flatCoordinates, flatLinearRings[i]);
ends.push(flatCoordinates.length);
}
polygon.setFlatCoordinates(
@@ -93272,8 +75826,8 @@ ol.format.GML3.prototype.readCurve_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'Curve', 'localName should be Curve');
- var flatCoordinates = ol.xml.pushParseAndPop(
- /** @type {Array.<number>} */ ([null]),
+ /** @type {Array.<number>} */
+ var flatCoordinates = ol.xml.pushParseAndPop([null],
this.CURVE_PARSERS_, node, objectStack, this);
if (flatCoordinates) {
var lineString = new ol.geom.LineString(null);
@@ -93296,8 +75850,8 @@ ol.format.GML3.prototype.readEnvelope_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'Envelope',
'localName should be Envelope');
- var flatCoordinates = ol.xml.pushParseAndPop(
- /** @type {Array.<number>} */ ([null]),
+ /** @type {Array.<number>} */
+ var flatCoordinates = ol.xml.pushParseAndPop([null],
this.ENVELOPE_PARSERS_, node, objectStack, this);
return ol.extent.createOrUpdate(flatCoordinates[1][0],
flatCoordinates[1][1], flatCoordinates[2][0],
@@ -93399,36 +75953,36 @@ ol.format.GML3.prototype.readFlatPosList_ = function(node, objectStack) {
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = Object({
+ol.format.GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
'http://www.opengis.net/gml' : {
'pos': ol.xml.makeReplacer(ol.format.GML3.prototype.readFlatPos_),
'posList': ol.xml.makeReplacer(ol.format.GML3.prototype.readFlatPosList_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.FLAT_LINEAR_RINGS_PARSERS_ = Object({
+ol.format.GML3.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
'http://www.opengis.net/gml' : {
'interior': ol.format.GML3.prototype.interiorParser_,
'exterior': ol.format.GML3.prototype.exteriorParser_
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.GEOMETRY_PARSERS_ = Object({
+ol.format.GML3.prototype.GEOMETRY_PARSERS_ = {
'http://www.opengis.net/gml' : {
'Point': ol.xml.makeReplacer(ol.format.GMLBase.prototype.readPoint),
'MultiPoint': ol.xml.makeReplacer(
@@ -93450,129 +76004,129 @@ ol.format.GML3.prototype.GEOMETRY_PARSERS_ = Object({
ol.format.GML3.prototype.readMultiCurve_),
'Envelope': ol.xml.makeReplacer(ol.format.GML3.prototype.readEnvelope_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.MULTICURVE_PARSERS_ = Object({
+ol.format.GML3.prototype.MULTICURVE_PARSERS_ = {
'http://www.opengis.net/gml' : {
'curveMember': ol.xml.makeArrayPusher(
ol.format.GML3.prototype.curveMemberParser_),
'curveMembers': ol.xml.makeArrayPusher(
ol.format.GML3.prototype.curveMemberParser_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.MULTISURFACE_PARSERS_ = Object({
+ol.format.GML3.prototype.MULTISURFACE_PARSERS_ = {
'http://www.opengis.net/gml' : {
'surfaceMember': ol.xml.makeArrayPusher(
ol.format.GML3.prototype.surfaceMemberParser_),
'surfaceMembers': ol.xml.makeArrayPusher(
ol.format.GML3.prototype.surfaceMemberParser_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.CURVEMEMBER_PARSERS_ = Object({
+ol.format.GML3.prototype.CURVEMEMBER_PARSERS_ = {
'http://www.opengis.net/gml' : {
'LineString': ol.xml.makeArrayPusher(
ol.format.GMLBase.prototype.readLineString),
'Curve': ol.xml.makeArrayPusher(ol.format.GML3.prototype.readCurve_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.SURFACEMEMBER_PARSERS_ = Object({
+ol.format.GML3.prototype.SURFACEMEMBER_PARSERS_ = {
'http://www.opengis.net/gml' : {
'Polygon': ol.xml.makeArrayPusher(ol.format.GMLBase.prototype.readPolygon),
'Surface': ol.xml.makeArrayPusher(ol.format.GML3.prototype.readSurface_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.SURFACE_PARSERS_ = Object({
+ol.format.GML3.prototype.SURFACE_PARSERS_ = {
'http://www.opengis.net/gml' : {
'patches': ol.xml.makeReplacer(ol.format.GML3.prototype.readPatch_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.CURVE_PARSERS_ = Object({
+ol.format.GML3.prototype.CURVE_PARSERS_ = {
'http://www.opengis.net/gml' : {
'segments': ol.xml.makeReplacer(ol.format.GML3.prototype.readSegment_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.ENVELOPE_PARSERS_ = Object({
+ol.format.GML3.prototype.ENVELOPE_PARSERS_ = {
'http://www.opengis.net/gml' : {
'lowerCorner': ol.xml.makeArrayPusher(
ol.format.GML3.prototype.readFlatPosList_),
'upperCorner': ol.xml.makeArrayPusher(
ol.format.GML3.prototype.readFlatPosList_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.PATCHES_PARSERS_ = Object({
+ol.format.GML3.prototype.PATCHES_PARSERS_ = {
'http://www.opengis.net/gml' : {
'PolygonPatch': ol.xml.makeReplacer(
ol.format.GML3.prototype.readPolygonPatch_)
}
-});
+};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
-ol.format.GML3.prototype.SEGMENTS_PARSERS_ = Object({
+ol.format.GML3.prototype.SEGMENTS_PARSERS_ = {
'http://www.opengis.net/gml' : {
'LineStringSegment': ol.xml.makeReplacer(
ol.format.GML3.prototype.readLineStringSegment_)
}
-});
+};
/**
@@ -93604,7 +76158,7 @@ ol.format.GML3.prototype.writePos_ = function(node, value, objectStack) {
/**
* @param {Array.<number>} point Point geometry.
* @param {string=} opt_srsName Optional srsName
- * @return {string}
+ * @return {string} The coords string.
* @private
*/
ol.format.GML3.prototype.getCoords_ = function(point, opt_srsName) {
@@ -93661,7 +76215,7 @@ ol.format.GML3.prototype.writePoint_ = function(node, geometry, objectStack) {
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GML3.ENVELOPE_SERIALIZERS_ = {
@@ -93687,7 +76241,7 @@ ol.format.GML3.prototype.writeEnvelope = function(node, extent, objectStack) {
}
var keys = ['lowerCorner', 'upperCorner'];
var values = [extent[0] + ' ' + extent[1], extent[2] + ' ' + extent[3]];
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */
+ ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
({node: node}), ol.format.GML3.ENVELOPE_SERIALIZERS_,
ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
values,
@@ -93701,8 +76255,7 @@ ol.format.GML3.prototype.writeEnvelope = function(node, extent, objectStack) {
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeLinearRing_ =
- function(node, geometry, objectStack) {
+ol.format.GML3.prototype.writeLinearRing_ = function(node, geometry, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var srsName = context['srsName'];
@@ -93722,8 +76275,7 @@ ol.format.GML3.prototype.writeLinearRing_ =
* @return {Node} Node.
* @private
*/
-ol.format.GML3.prototype.RING_NODE_FACTORY_ =
- function(value, objectStack, opt_nodeName) {
+ol.format.GML3.prototype.RING_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
var context = objectStack[objectStack.length - 1];
var parentNode = context.node;
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
@@ -93742,8 +76294,7 @@ ol.format.GML3.prototype.RING_NODE_FACTORY_ =
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeSurfaceOrPolygon_ =
- function(node, geometry, objectStack) {
+ol.format.GML3.prototype.writeSurfaceOrPolygon_ = function(node, geometry, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var srsName = context['srsName'];
@@ -93772,8 +76323,7 @@ ol.format.GML3.prototype.writeSurfaceOrPolygon_ =
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeCurveOrLineString_ =
- function(node, geometry, objectStack) {
+ol.format.GML3.prototype.writeCurveOrLineString_ = function(node, geometry, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var srsName = context['srsName'];
@@ -93800,8 +76350,7 @@ ol.format.GML3.prototype.writeCurveOrLineString_ =
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeMultiSurfaceOrPolygon_ =
- function(node, geometry, objectStack) {
+ol.format.GML3.prototype.writeMultiSurfaceOrPolygon_ = function(node, geometry, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var srsName = context['srsName'];
@@ -93845,8 +76394,7 @@ ol.format.GML3.prototype.writeMultiPoint_ = function(node, geometry,
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeMultiCurveOrLineString_ =
- function(node, geometry, objectStack) {
+ol.format.GML3.prototype.writeMultiCurveOrLineString_ = function(node, geometry, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var srsName = context['srsName'];
@@ -93881,8 +76429,7 @@ ol.format.GML3.prototype.writeRing_ = function(node, ring, objectStack) {
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeSurfaceOrPolygonMember_ =
- function(node, polygon, objectStack) {
+ol.format.GML3.prototype.writeSurfaceOrPolygonMember_ = function(node, polygon, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var child = this.GEOMETRY_NODE_FACTORY_(
@@ -93900,8 +76447,7 @@ ol.format.GML3.prototype.writeSurfaceOrPolygonMember_ =
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writePointMember_ =
- function(node, point, objectStack) {
+ol.format.GML3.prototype.writePointMember_ = function(node, point, objectStack) {
var child = ol.xml.createElementNS(node.namespaceURI, 'Point');
node.appendChild(child);
this.writePoint_(child, point, objectStack);
@@ -93914,8 +76460,7 @@ ol.format.GML3.prototype.writePointMember_ =
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeLineStringOrCurveMember_ =
- function(node, line, objectStack) {
+ol.format.GML3.prototype.writeLineStringOrCurveMember_ = function(node, line, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var child = this.GEOMETRY_NODE_FACTORY_(line, objectStack);
@@ -93932,8 +76477,7 @@ ol.format.GML3.prototype.writeLineStringOrCurveMember_ =
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeSurfacePatches_ =
- function(node, polygon, objectStack) {
+ol.format.GML3.prototype.writeSurfacePatches_ = function(node, polygon, objectStack) {
var child = ol.xml.createElementNS(node.namespaceURI, 'PolygonPatch');
node.appendChild(child);
this.writeSurfaceOrPolygon_(child, polygon, objectStack);
@@ -93946,8 +76490,7 @@ ol.format.GML3.prototype.writeSurfacePatches_ =
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeCurveSegments_ =
- function(node, line, objectStack) {
+ol.format.GML3.prototype.writeCurveSegments_ = function(node, line, objectStack) {
var child = ol.xml.createElementNS(node.namespaceURI,
'LineStringSegment');
node.appendChild(child);
@@ -93960,14 +76503,13 @@ ol.format.GML3.prototype.writeCurveSegments_ =
* @param {ol.geom.Geometry|ol.Extent} geometry Geometry.
* @param {Array.<*>} objectStack Node stack.
*/
-ol.format.GML3.prototype.writeGeometryElement =
- function(node, geometry, objectStack) {
+ol.format.GML3.prototype.writeGeometryElement = function(node, geometry, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
- var item = goog.object.clone(context);
+ var item = ol.object.assign({}, context);
item.node = node;
var value;
- if (goog.isArray(geometry)) {
+ if (Array.isArray(geometry)) {
if (context.dataProjection) {
value = ol.proj.transformExtent(
geometry, context.featureProjection, context.dataProjection);
@@ -93980,7 +76522,7 @@ ol.format.GML3.prototype.writeGeometryElement =
value =
ol.format.Feature.transformWithOptions(geometry, true, context);
}
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */
+ ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
(item), ol.format.GML3.GEOMETRY_SERIALIZERS_,
this.GEOMETRY_NODE_FACTORY_, [value],
objectStack, undefined, this);
@@ -93992,8 +76534,7 @@ ol.format.GML3.prototype.writeGeometryElement =
* @param {ol.Feature} feature Feature.
* @param {Array.<*>} objectStack Node stack.
*/
-ol.format.GML3.prototype.writeFeatureElement =
- function(node, feature, objectStack) {
+ol.format.GML3.prototype.writeFeatureElement = function(node, feature, objectStack) {
var fid = feature.getId();
if (fid) {
node.setAttribute('fid', fid);
@@ -94026,9 +76567,9 @@ ol.format.GML3.prototype.writeFeatureElement =
}
}
}
- var item = goog.object.clone(context);
+ var item = ol.object.assign({}, context);
item.node = node;
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */
+ ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
(item), context.serializers,
ol.xml.makeSimpleNodeFactory(undefined, featureNS),
values,
@@ -94042,8 +76583,7 @@ ol.format.GML3.prototype.writeFeatureElement =
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.GML3.prototype.writeFeatureMembers_ =
- function(node, features, objectStack) {
+ol.format.GML3.prototype.writeFeatureMembers_ = function(node, features, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var featureType = context['featureType'];
@@ -94052,9 +76592,9 @@ ol.format.GML3.prototype.writeFeatureMembers_ =
serializers[featureNS] = {};
serializers[featureNS][featureType] = ol.xml.makeChildAppender(
this.writeFeatureElement, this);
- var item = goog.object.clone(context);
+ var item = ol.object.assign({}, context);
item.node = node;
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */
+ ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
(item),
serializers,
ol.xml.makeSimpleNodeFactory(featureType, featureNS), features,
@@ -94063,7 +76603,7 @@ ol.format.GML3.prototype.writeFeatureMembers_ =
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GML3.SURFACEORPOLYGONMEMBER_SERIALIZERS_ = {
@@ -94077,7 +76617,7 @@ ol.format.GML3.SURFACEORPOLYGONMEMBER_SERIALIZERS_ = {
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GML3.POINTMEMBER_SERIALIZERS_ = {
@@ -94089,7 +76629,7 @@ ol.format.GML3.POINTMEMBER_SERIALIZERS_ = {
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GML3.LINESTRINGORCURVEMEMBER_SERIALIZERS_ = {
@@ -94103,7 +76643,7 @@ ol.format.GML3.LINESTRINGORCURVEMEMBER_SERIALIZERS_ = {
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GML3.RING_SERIALIZERS_ = {
@@ -94115,7 +76655,7 @@ ol.format.GML3.RING_SERIALIZERS_ = {
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GML3.GEOMETRY_SERIALIZERS_ = {
@@ -94168,8 +76708,7 @@ ol.format.GML3.MULTIGEOMETRY_TO_MEMBER_NODENAME_ = {
* @return {Node|undefined} Node.
* @private
*/
-ol.format.GML3.prototype.MULTIGEOMETRY_MEMBER_NODE_FACTORY_ =
- function(value, objectStack, opt_nodeName) {
+ol.format.GML3.prototype.MULTIGEOMETRY_MEMBER_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
var parentNode = objectStack[objectStack.length - 1].node;
goog.asserts.assert(ol.xml.isNode(parentNode),
'parentNode should be a node');
@@ -94186,8 +76725,7 @@ ol.format.GML3.prototype.MULTIGEOMETRY_MEMBER_NODE_FACTORY_ =
* @return {Node|undefined} Node.
* @private
*/
-ol.format.GML3.prototype.GEOMETRY_NODE_FACTORY_ =
- function(value, objectStack, opt_nodeName) {
+ol.format.GML3.prototype.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
var multiSurface = context['multiSurface'];
@@ -94198,7 +76736,7 @@ ol.format.GML3.prototype.GEOMETRY_NODE_FACTORY_ =
goog.asserts.assert(ol.xml.isNode(parentNode),
'parentNode should be a node');
var nodeName;
- if (!goog.isArray(value)) {
+ if (!Array.isArray(value)) {
goog.asserts.assertInstanceof(value, ol.geom.Geometry,
'value should be an ol.geom.Geometry');
nodeName = value.getType();
@@ -94234,7 +76772,7 @@ ol.format.GML3.prototype.writeGeometryNode = function(geometry, opt_options) {
curve: this.curve_, surface: this.surface_,
multiSurface: this.multiSurface_, multiCurve: this.multiCurve_};
if (opt_options) {
- goog.object.extend(context, opt_options);
+ ol.object.assign(context, opt_options);
}
this.writeGeometryElement(geom, geometry, [context]);
return geom;
@@ -94277,14 +76815,13 @@ ol.format.GML3.prototype.writeFeaturesNode = function(features, opt_options) {
featureType: this.featureType
};
if (opt_options) {
- goog.object.extend(context, opt_options);
+ ol.object.assign(context, opt_options);
}
this.writeFeatureMembers_(node, features, [context]);
return node;
};
-
/**
* @classdesc
* Feature format for reading and writing data in the GML format
@@ -94340,7 +76877,6 @@ goog.require('ol.proj');
goog.require('ol.xml');
-
/**
* @classdesc
* Feature format for reading and writing data in the GPX format.
@@ -94605,7 +77141,7 @@ ol.format.GPX.FEATURE_READER_ = {
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.GPX.GPX_PARSERS_ = ol.xml.makeStructureNS(
@@ -94618,7 +77154,7 @@ ol.format.GPX.GPX_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.GPX.LINK_PARSERS_ = ol.xml.makeStructureNS(
@@ -94632,7 +77168,7 @@ ol.format.GPX.LINK_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.GPX.RTE_PARSERS_ = ol.xml.makeStructureNS(
@@ -94652,7 +77188,7 @@ ol.format.GPX.RTE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.GPX.RTEPT_PARSERS_ = ol.xml.makeStructureNS(
@@ -94664,7 +77200,7 @@ ol.format.GPX.RTEPT_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.GPX.TRK_PARSERS_ = ol.xml.makeStructureNS(
@@ -94684,7 +77220,7 @@ ol.format.GPX.TRK_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.GPX.TRKSEG_PARSERS_ = ol.xml.makeStructureNS(
@@ -94695,7 +77231,7 @@ ol.format.GPX.TRKSEG_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.GPX.TRKPT_PARSERS_ = ol.xml.makeStructureNS(
@@ -94707,7 +77243,7 @@ ol.format.GPX.TRKPT_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.GPX.WPT_PARSERS_ = ol.xml.makeStructureNS(
@@ -94738,7 +77274,7 @@ ol.format.GPX.WPT_PARSERS_ = ol.xml.makeStructureNS(
/**
- * @param {Array.<ol.Feature>} features
+ * @param {Array.<ol.Feature>} features List of features.
* @private
*/
ol.format.GPX.prototype.handleReadExtensions_ = function(features) {
@@ -94812,8 +77348,8 @@ ol.format.GPX.prototype.readFeaturesFromNode = function(node, opt_options) {
return [];
}
if (node.localName == 'gpx') {
- var features = ol.xml.pushParseAndPop(
- /** @type {Array.<ol.Feature>} */ ([]), ol.format.GPX.GPX_PARSERS_,
+ /** @type {Array.<ol.Feature>} */
+ var features = ol.xml.pushParseAndPop([], ol.format.GPX.GPX_PARSERS_,
node, [this.getReadOptions(node, opt_options)]);
if (features) {
this.handleReadExtensions_(features);
@@ -94852,7 +77388,7 @@ ol.format.GPX.writeLink_ = function(node, value, objectStack) {
properties['linkText'],
properties['linkType']
];
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ ({node: node}),
+ ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */ ({node: node}),
ol.format.GPX.LINK_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
link, objectStack, ol.format.GPX.LINK_SEQUENCE_);
};
@@ -94876,12 +77412,12 @@ ol.format.GPX.writeWptType_ = function(node, coordinate, objectStack) {
ol.xml.setAttributeNS(node, null, 'lat', coordinate[1]);
ol.xml.setAttributeNS(node, null, 'lon', coordinate[0]);
var geometryLayout = context['geometryLayout'];
- /* jshint -W086 */
switch (geometryLayout) {
case ol.geom.GeometryLayout.XYZM:
if (coordinate[3] !== 0) {
properties['time'] = coordinate[3];
}
+ // fall through
case ol.geom.GeometryLayout.XYZ:
if (coordinate[2] !== 0) {
properties['ele'] = coordinate[2];
@@ -94891,11 +77427,13 @@ ol.format.GPX.writeWptType_ = function(node, coordinate, objectStack) {
if (coordinate[2] !== 0) {
properties['time'] = coordinate[2];
}
+ break;
+ default:
+ // pass
}
- /* jshint +W086 */
var orderedKeys = ol.format.GPX.WPT_TYPE_SEQUENCE_[namespaceURI];
var values = ol.xml.makeSequence(properties, orderedKeys);
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */
+ ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
({node: node, 'properties': properties}),
ol.format.GPX.WPT_TYPE_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
values, objectStack, orderedKeys);
@@ -94924,7 +77462,7 @@ ol.format.GPX.writeRte_ = function(node, feature, objectStack) {
var parentNode = objectStack[objectStack.length - 1].node;
var orderedKeys = ol.format.GPX.RTE_SEQUENCE_[parentNode.namespaceURI];
var values = ol.xml.makeSequence(properties, orderedKeys);
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (context),
+ ol.xml.pushSerializeAndPop(context,
ol.format.GPX.RTE_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
values, objectStack, orderedKeys);
};
@@ -94939,6 +77477,7 @@ ol.format.GPX.writeRte_ = function(node, feature, objectStack) {
ol.format.GPX.writeTrk_ = function(node, feature, objectStack) {
var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]);
var properties = feature.getProperties();
+ /** @type {ol.XmlNodeStackItem} */
var context = {node: node, 'properties': properties};
var geometry = feature.getGeometry();
if (geometry) {
@@ -94951,7 +77490,7 @@ ol.format.GPX.writeTrk_ = function(node, feature, objectStack) {
var parentNode = objectStack[objectStack.length - 1].node;
var orderedKeys = ol.format.GPX.TRK_SEQUENCE_[parentNode.namespaceURI];
var values = ol.xml.makeSequence(properties, orderedKeys);
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (context),
+ ol.xml.pushSerializeAndPop(context,
ol.format.GPX.TRK_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
values, objectStack, orderedKeys);
};
@@ -94964,9 +77503,10 @@ ol.format.GPX.writeTrk_ = function(node, feature, objectStack) {
* @private
*/
ol.format.GPX.writeTrkSeg_ = function(node, lineString, objectStack) {
+ /** @type {ol.XmlNodeStackItem} */
var context = {node: node, 'geometryLayout': lineString.getLayout(),
'properties': {}};
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (context),
+ ol.xml.pushSerializeAndPop(context,
ol.format.GPX.TRKSEG_SERIALIZERS_, ol.format.GPX.TRKSEG_NODE_FACTORY_,
lineString.getCoordinates(), objectStack);
};
@@ -95004,7 +77544,7 @@ ol.format.GPX.LINK_SEQUENCE_ = ['text', 'type'];
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GPX.LINK_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -95027,7 +77567,7 @@ ol.format.GPX.RTE_SEQUENCE_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GPX.RTE_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -95058,7 +77598,7 @@ ol.format.GPX.TRK_SEQUENCE_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GPX.TRK_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -95086,7 +77626,7 @@ ol.format.GPX.TRKSEG_NODE_FACTORY_ = ol.xml.makeSimpleNodeFactory('trkpt');
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GPX.TRKSEG_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -95109,7 +77649,7 @@ ol.format.GPX.WPT_TYPE_SEQUENCE_ = ol.xml.makeStructureNS(
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GPX.WPT_TYPE_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -95177,7 +77717,7 @@ ol.format.GPX.GPX_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.GPX.GPX_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -95190,6 +77730,8 @@ ol.format.GPX.GPX_SERIALIZERS_ = ol.xml.makeStructureNS(
/**
* Encode an array of features in the GPX format.
+ * LineString geometries are output as routes (`<rte>`), and MultiLineString
+ * as tracks (`<trk>`).
*
* @function
* @param {Array.<ol.Feature>} features Features.
@@ -95202,6 +77744,8 @@ ol.format.GPX.prototype.writeFeatures;
/**
* Encode an array of features in the GPX format as an XML node.
+ * LineString geometries are output as routes (`<rte>`), and MultiLineString
+ * as tracks (`<trk>`).
*
* @param {Array.<ol.Feature>} features Features.
* @param {olx.format.WriteOptions=} opt_options Options.
@@ -95213,167 +77757,12 @@ ol.format.GPX.prototype.writeFeaturesNode = function(features, opt_options) {
//FIXME Serialize metadata
var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
- ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */
+ ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
({node: gpx}), ol.format.GPX.GPX_SERIALIZERS_,
ol.format.GPX.GPX_NODE_FACTORY_, features, [opt_options]);
return gpx;
};
-// Copyright 2013 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Utilities for string newlines.
- * @author nnaze@google.com (Nathan Naze)
- */
-
-
-/**
- * Namespace for string utilities
- */
-goog.provide('goog.string.newlines');
-goog.provide('goog.string.newlines.Line');
-
-goog.require('goog.array');
-
-
-/**
- * Splits a string into lines, properly handling universal newlines.
- * @param {string} str String to split.
- * @param {boolean=} opt_keepNewlines Whether to keep the newlines in the
- * resulting strings. Defaults to false.
- * @return {!Array<string>} String split into lines.
- */
-goog.string.newlines.splitLines = function(str, opt_keepNewlines) {
- var lines = goog.string.newlines.getLines(str);
- return goog.array.map(lines, function(line) {
- return opt_keepNewlines ? line.getFullLine() : line.getContent();
- });
-};
-
-
-
-/**
- * Line metadata class that records the start/end indicies of lines
- * in a string. Can be used to implement common newline use cases such as
- * splitLines() or determining line/column of an index in a string.
- * Also implements methods to get line contents.
- *
- * Indexes are expressed as string indicies into string.substring(), inclusive
- * at the start, exclusive at the end.
- *
- * Create an array of these with goog.string.newlines.getLines().
- * @param {string} string The original string.
- * @param {number} startLineIndex The index of the start of the line.
- * @param {number} endContentIndex The index of the end of the line, excluding
- * newlines.
- * @param {number} endLineIndex The index of the end of the line, index
- * newlines.
- * @constructor
- * @struct
- * @final
- */
-goog.string.newlines.Line = function(string, startLineIndex,
- endContentIndex, endLineIndex) {
- /**
- * The original string.
- * @type {string}
- */
- this.string = string;
-
- /**
- * Index of the start of the line.
- * @type {number}
- */
- this.startLineIndex = startLineIndex;
-
- /**
- * Index of the end of the line, excluding any newline characters.
- * Index is the first character after the line, suitable for
- * String.substring().
- * @type {number}
- */
- this.endContentIndex = endContentIndex;
-
- /**
- * Index of the end of the line, excluding any newline characters.
- * Index is the first character after the line, suitable for
- * String.substring().
- * @type {number}
- */
-
- this.endLineIndex = endLineIndex;
-};
-
-
-/**
- * @return {string} The content of the line, excluding any newline characters.
- */
-goog.string.newlines.Line.prototype.getContent = function() {
- return this.string.substring(this.startLineIndex, this.endContentIndex);
-};
-
-
-/**
- * @return {string} The full line, including any newline characters.
- */
-goog.string.newlines.Line.prototype.getFullLine = function() {
- return this.string.substring(this.startLineIndex, this.endLineIndex);
-};
-
-
-/**
- * @return {string} The newline characters, if any ('\n', \r', '\r\n', '', etc).
- */
-goog.string.newlines.Line.prototype.getNewline = function() {
- return this.string.substring(this.endContentIndex, this.endLineIndex);
-};
-
-
-/**
- * Splits a string into an array of line metadata.
- * @param {string} str String to split.
- * @return {!Array<!goog.string.newlines.Line>} Array of line metadata.
- */
-goog.string.newlines.getLines = function(str) {
- // We use the constructor because literals are evaluated only once in
- // < ES 3.1.
- // See http://www.mail-archive.com/es-discuss@mozilla.org/msg01796.html
- var re = RegExp('\r\n|\r|\n', 'g');
- var sliceIndex = 0;
- var result;
- var lines = [];
-
- while (result = re.exec(str)) {
- var line = new goog.string.newlines.Line(
- str, sliceIndex, result.index, result.index + result[0].length);
- lines.push(line);
-
- // remember where to start the slice from
- sliceIndex = re.lastIndex;
- }
-
- // If the string does not end with a newline, add the last line.
- if (sliceIndex < str.length) {
- var line = new goog.string.newlines.Line(
- str, sliceIndex, str.length, str.length);
- lines.push(line);
- }
-
- return lines;
-};
-
goog.provide('ol.format.TextFeature');
goog.require('goog.asserts');
@@ -95381,7 +77770,6 @@ goog.require('ol.format.Feature');
goog.require('ol.format.FormatType');
-
/**
* @classdesc
* Abstract base class; normally only used for creating subclasses and not
@@ -95403,7 +77791,7 @@ goog.inherits(ol.format.TextFeature, ol.format.Feature);
* @return {string} Text.
*/
ol.format.TextFeature.prototype.getText_ = function(source) {
- if (goog.isString(source)) {
+ if (typeof source === 'string') {
return source;
} else {
goog.asserts.fail();
@@ -95548,7 +77936,6 @@ goog.provide('ol.format.IGC');
goog.provide('ol.format.IGCZ');
goog.require('goog.asserts');
-goog.require('goog.string.newlines');
goog.require('ol.Feature');
goog.require('ol.format.Feature');
goog.require('ol.format.TextFeature');
@@ -95569,7 +77956,6 @@ ol.format.IGCZ = {
};
-
/**
* @classdesc
* Feature format for `*.igc` flight recording files.
@@ -95635,6 +78021,16 @@ ol.format.IGC.HFDTE_RECORD_RE_ = /^HFDTE(\d{2})(\d{2})(\d{2})/;
/**
+ * A regular expression matching the newline characters `\r\n`, `\r` and `\n`.
+ *
+ * @const
+ * @type {RegExp}
+ * @private
+ */
+ol.format.IGC.NEWLINE_RE_ = /\r\n|\r|\n/;
+
+
+/**
* @inheritDoc
*/
ol.format.IGC.prototype.getExtensions = function() {
@@ -95659,7 +78055,7 @@ ol.format.IGC.prototype.readFeature;
*/
ol.format.IGC.prototype.readFeatureFromText = function(text, opt_options) {
var altitudeMode = this.altitudeMode_;
- var lines = goog.string.newlines.splitLines(text);
+ var lines = text.split(ol.format.IGC.NEWLINE_RE_);
/** @type {Object.<string, string>} */
var properties = {};
var flatCoordinates = [];
@@ -95710,7 +78106,6 @@ ol.format.IGC.prototype.readFeatureFromText = function(text, opt_options) {
m = ol.format.IGC.H_RECORD_RE_.exec(line);
if (m) {
properties[m[1]] = m[2].trim();
- m = ol.format.IGC.HFDTE_RECORD_RE_.exec(line);
}
}
}
@@ -95780,6 +78175,3175 @@ ol.format.IGC.prototype.readProjection;
// limitations under the License.
/**
+ * @fileoverview Generics method for collection-like classes and objects.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ *
+ * This file contains functions to work with collections. It supports using
+ * Map, Set, Array and Object and other classes that implement collection-like
+ * methods.
+ */
+
+
+goog.provide('goog.structs');
+
+goog.require('goog.array');
+goog.require('goog.object');
+
+
+// We treat an object as a dictionary if it has getKeys or it is an object that
+// isn't arrayLike.
+
+
+/**
+ * Returns the number of values in the collection-like object.
+ * @param {Object} col The collection-like object.
+ * @return {number} The number of values in the collection-like object.
+ */
+goog.structs.getCount = function(col) {
+ if (col.getCount && typeof col.getCount == 'function') {
+ return col.getCount();
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return col.length;
+ }
+ return goog.object.getCount(col);
+};
+
+
+/**
+ * Returns the values of the collection-like object.
+ * @param {Object} col The collection-like object.
+ * @return {!Array<?>} The values in the collection-like object.
+ */
+goog.structs.getValues = function(col) {
+ if (col.getValues && typeof col.getValues == 'function') {
+ return col.getValues();
+ }
+ if (goog.isString(col)) {
+ return col.split('');
+ }
+ if (goog.isArrayLike(col)) {
+ var rv = [];
+ var l = col.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(col[i]);
+ }
+ return rv;
+ }
+ return goog.object.getValues(col);
+};
+
+
+/**
+ * Returns the keys of the collection. Some collections have no notion of
+ * keys/indexes and this function will return undefined in those cases.
+ * @param {Object} col The collection-like object.
+ * @return {!Array|undefined} The keys in the collection.
+ */
+goog.structs.getKeys = function(col) {
+ if (col.getKeys && typeof col.getKeys == 'function') {
+ return col.getKeys();
+ }
+ // if we have getValues but no getKeys we know this is a key-less collection
+ if (col.getValues && typeof col.getValues == 'function') {
+ return undefined;
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ var rv = [];
+ var l = col.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(i);
+ }
+ return rv;
+ }
+
+ return goog.object.getKeys(col);
+};
+
+
+/**
+ * Whether the collection contains the given value. This is O(n) and uses
+ * equals (==) to test the existence.
+ * @param {Object} col The collection-like object.
+ * @param {*} val The value to check for.
+ * @return {boolean} True if the map contains the value.
+ */
+goog.structs.contains = function(col, val) {
+ if (col.contains && typeof col.contains == 'function') {
+ return col.contains(val);
+ }
+ if (col.containsValue && typeof col.containsValue == 'function') {
+ return col.containsValue(val);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.contains(/** @type {!Array<?>} */ (col), val);
+ }
+ return goog.object.containsValue(col, val);
+};
+
+
+/**
+ * Whether the collection is empty.
+ * @param {Object} col The collection-like object.
+ * @return {boolean} True if empty.
+ */
+goog.structs.isEmpty = function(col) {
+ if (col.isEmpty && typeof col.isEmpty == 'function') {
+ return col.isEmpty();
+ }
+
+ // We do not use goog.string.isEmptyOrWhitespace because here we treat the
+ // string as
+ // collection and as such even whitespace matters
+
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.isEmpty(/** @type {!Array<?>} */ (col));
+ }
+ return goog.object.isEmpty(col);
+};
+
+
+/**
+ * Removes all the elements from the collection.
+ * @param {Object} col The collection-like object.
+ */
+goog.structs.clear = function(col) {
+ // NOTE(arv): This should not contain strings because strings are immutable
+ if (col.clear && typeof col.clear == 'function') {
+ col.clear();
+ } else if (goog.isArrayLike(col)) {
+ goog.array.clear(/** @type {IArrayLike<?>} */ (col));
+ } else {
+ goog.object.clear(col);
+ }
+};
+
+
+/**
+ * Calls a function for each value in a collection. The function takes
+ * three arguments; the value, the key and the collection.
+ *
+ * NOTE: This will be deprecated soon! Please use a more specific method if
+ * possible, e.g. goog.array.forEach, goog.object.forEach, etc.
+ *
+ * @param {S} col The collection-like object.
+ * @param {function(this:T,?,?,S):?} f The function to call for every value.
+ * This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and the return value is irrelevant.
+ * @param {T=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @template T,S
+ */
+goog.structs.forEach = function(col, f, opt_obj) {
+ if (col.forEach && typeof col.forEach == 'function') {
+ col.forEach(f, opt_obj);
+ } else if (goog.isArrayLike(col) || goog.isString(col)) {
+ goog.array.forEach(/** @type {!Array<?>} */ (col), f, opt_obj);
+ } else {
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col);
+ }
+ }
+};
+
+
+/**
+ * Calls a function for every value in the collection. When a call returns true,
+ * adds the value to a new collection (Array is returned by default).
+ *
+ * @param {S} col The collection-like object.
+ * @param {function(this:T,?,?,S):boolean} f The function to call for every
+ * value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and should return a Boolean. If the
+ * return value is true the value is added to the result collection. If it
+ * is false the value is not included.
+ * @param {T=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {!Object|!Array<?>} A new collection where the passed values are
+ * present. If col is a key-less collection an array is returned. If col
+ * has keys and values a plain old JS object is returned.
+ * @template T,S
+ */
+goog.structs.filter = function(col, f, opt_obj) {
+ if (typeof col.filter == 'function') {
+ return col.filter(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.filter(/** @type {!Array<?>} */ (col), f, opt_obj);
+ }
+
+ var rv;
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ if (keys) {
+ rv = {};
+ for (var i = 0; i < l; i++) {
+ if (f.call(/** @type {?} */ (opt_obj), values[i], keys[i], col)) {
+ rv[keys[i]] = values[i];
+ }
+ }
+ } else {
+ // We should not use goog.array.filter here since we want to make sure that
+ // the index is undefined as well as make sure that col is passed to the
+ // function.
+ rv = [];
+ for (var i = 0; i < l; i++) {
+ if (f.call(opt_obj, values[i], undefined, col)) {
+ rv.push(values[i]);
+ }
+ }
+ }
+ return rv;
+};
+
+
+/**
+ * Calls a function for every value in the collection and adds the result into a
+ * new collection (defaults to creating a new Array).
+ *
+ * @param {S} col The collection-like object.
+ * @param {function(this:T,?,?,S):V} f The function to call for every value.
+ * This function takes 3 arguments (the value, the key or undefined if the
+ * collection has no notion of keys, and the collection) and should return
+ * something. The result will be used as the value in the new collection.
+ * @param {T=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {!Object<V>|!Array<V>} A new collection with the new values. If
+ * col is a key-less collection an array is returned. If col has keys and
+ * values a plain old JS object is returned.
+ * @template T,S,V
+ */
+goog.structs.map = function(col, f, opt_obj) {
+ if (typeof col.map == 'function') {
+ return col.map(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.map(/** @type {!Array<?>} */ (col), f, opt_obj);
+ }
+
+ var rv;
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ if (keys) {
+ rv = {};
+ for (var i = 0; i < l; i++) {
+ rv[keys[i]] = f.call(/** @type {?} */ (opt_obj), values[i], keys[i], col);
+ }
+ } else {
+ // We should not use goog.array.map here since we want to make sure that
+ // the index is undefined as well as make sure that col is passed to the
+ // function.
+ rv = [];
+ for (var i = 0; i < l; i++) {
+ rv[i] = f.call(/** @type {?} */ (opt_obj), values[i], undefined, col);
+ }
+ }
+ return rv;
+};
+
+
+/**
+ * Calls f for each value in a collection. If any call returns true this returns
+ * true (without checking the rest). If all returns false this returns false.
+ *
+ * @param {S} col The collection-like object.
+ * @param {function(this:T,?,?,S):boolean} f The function to call for every
+ * value. This function takes 3 arguments (the value, the key or undefined
+ * if the collection has no notion of keys, and the collection) and should
+ * return a boolean.
+ * @param {T=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {boolean} True if any value passes the test.
+ * @template T,S
+ */
+goog.structs.some = function(col, f, opt_obj) {
+ if (typeof col.some == 'function') {
+ return col.some(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.some(/** @type {!Array<?>} */ (col), f, opt_obj);
+ }
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ if (f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Calls f for each value in a collection. If all calls return true this return
+ * true this returns true. If any returns false this returns false at this point
+ * and does not continue to check the remaining values.
+ *
+ * @param {S} col The collection-like object.
+ * @param {function(this:T,?,?,S):boolean} f The function to call for every
+ * value. This function takes 3 arguments (the value, the key or
+ * undefined if the collection has no notion of keys, and the collection)
+ * and should return a boolean.
+ * @param {T=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {boolean} True if all key-value pairs pass the test.
+ * @template T,S
+ */
+goog.structs.every = function(col, f, opt_obj) {
+ if (typeof col.every == 'function') {
+ return col.every(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.every(/** @type {!Array<?>} */ (col), f, opt_obj);
+ }
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ if (!f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Python style iteration utilities.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.iter');
+goog.provide('goog.iter.Iterable');
+goog.provide('goog.iter.Iterator');
+goog.provide('goog.iter.StopIteration');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.functions');
+goog.require('goog.math');
+
+
+/**
+ * @typedef {goog.iter.Iterator|{length:number}|{__iterator__}}
+ */
+goog.iter.Iterable;
+
+
+/**
+ * Singleton Error object that is used to terminate iterations.
+ * @const {!Error}
+ */
+goog.iter.StopIteration = ('StopIteration' in goog.global) ?
+ // For script engines that support legacy iterators.
+ goog.global['StopIteration'] :
+ {message: 'StopIteration', stack: ''};
+
+
+
+/**
+ * Class/interface for iterators. An iterator needs to implement a {@code next}
+ * method and it needs to throw a {@code goog.iter.StopIteration} when the
+ * iteration passes beyond the end. Iterators have no {@code hasNext} method.
+ * It is recommended to always use the helper functions to iterate over the
+ * iterator or in case you are only targeting JavaScript 1.7 for in loops.
+ * @constructor
+ * @template VALUE
+ */
+goog.iter.Iterator = function() {};
+
+
+/**
+ * Returns the next value of the iteration. This will throw the object
+ * {@see goog.iter#StopIteration} when the iteration passes the end.
+ * @return {VALUE} Any object or value.
+ */
+goog.iter.Iterator.prototype.next = function() {
+ throw goog.iter.StopIteration;
+};
+
+
+/**
+ * Returns the {@code Iterator} object itself. This is used to implement
+ * the iterator protocol in JavaScript 1.7
+ * @param {boolean=} opt_keys Whether to return the keys or values. Default is
+ * to only return the values. This is being used by the for-in loop (true)
+ * and the for-each-in loop (false). Even though the param gives a hint
+ * about what the iterator will return there is no guarantee that it will
+ * return the keys when true is passed.
+ * @return {!goog.iter.Iterator<VALUE>} The object itself.
+ */
+goog.iter.Iterator.prototype.__iterator__ = function(opt_keys) {
+ return this;
+};
+
+
+/**
+ * Returns an iterator that knows how to iterate over the values in the object.
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable If the
+ * object is an iterator it will be returned as is. If the object has an
+ * {@code __iterator__} method that will be called to get the value
+ * iterator. If the object is an array-like object we create an iterator
+ * for that.
+ * @return {!goog.iter.Iterator<VALUE>} An iterator that knows how to iterate
+ * over the values in {@code iterable}.
+ * @template VALUE
+ */
+goog.iter.toIterator = function(iterable) {
+ if (iterable instanceof goog.iter.Iterator) {
+ return iterable;
+ }
+ if (typeof iterable.__iterator__ == 'function') {
+ return iterable.__iterator__(false);
+ }
+ if (goog.isArrayLike(iterable)) {
+ var i = 0;
+ var newIter = new goog.iter.Iterator;
+ newIter.next = function() {
+ while (true) {
+ if (i >= iterable.length) {
+ throw goog.iter.StopIteration;
+ }
+ // Don't include deleted elements.
+ if (!(i in iterable)) {
+ i++;
+ continue;
+ }
+ return iterable[i++];
+ }
+ };
+ return newIter;
+ }
+
+
+ // TODO(arv): Should we fall back on goog.structs.getValues()?
+ throw Error('Not implemented');
+};
+
+
+/**
+ * Calls a function for each element in the iterator with the element of the
+ * iterator passed as argument.
+ *
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * to iterate over. If the iterable is an object {@code toIterator} will be
+ * called on it.
+ * @param {function(this:THIS,VALUE,?,!goog.iter.Iterator<VALUE>)} f
+ * The function to call for every element. This function takes 3 arguments
+ * (the element, undefined, and the iterator) and the return value is
+ * irrelevant. The reason for passing undefined as the second argument is
+ * so that the same function can be used in {@see goog.array#forEach} as
+ * well as others. The third parameter is of type "number" for
+ * arraylike objects, undefined, otherwise.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * {@code f}.
+ * @template THIS, VALUE
+ */
+goog.iter.forEach = function(iterable, f, opt_obj) {
+ if (goog.isArrayLike(iterable)) {
+ /** @preserveTry */
+ try {
+ // NOTES: this passes the index number to the second parameter
+ // of the callback contrary to the documentation above.
+ goog.array.forEach(
+ /** @type {IArrayLike<?>} */ (iterable), f, opt_obj);
+ } catch (ex) {
+ if (ex !== goog.iter.StopIteration) {
+ throw ex;
+ }
+ }
+ } else {
+ iterable = goog.iter.toIterator(iterable);
+ /** @preserveTry */
+ try {
+ while (true) {
+ f.call(opt_obj, iterable.next(), undefined, iterable);
+ }
+ } catch (ex) {
+ if (ex !== goog.iter.StopIteration) {
+ throw ex;
+ }
+ }
+ }
+};
+
+
+/**
+ * Calls a function for every element in the iterator, and if the function
+ * returns true adds the element to a new iterator.
+ *
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * to iterate over.
+ * @param {
+ * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
+ * The function to call for every element. This function takes 3 arguments
+ * (the element, undefined, and the iterator) and should return a boolean.
+ * If the return value is true the element will be included in the returned
+ * iterator. If it is false the element is not included.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * {@code f}.
+ * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements
+ * that passed the test are present.
+ * @template THIS, VALUE
+ */
+goog.iter.filter = function(iterable, f, opt_obj) {
+ var iterator = goog.iter.toIterator(iterable);
+ var newIter = new goog.iter.Iterator;
+ newIter.next = function() {
+ while (true) {
+ var val = iterator.next();
+ if (f.call(opt_obj, val, undefined, iterator)) {
+ return val;
+ }
+ }
+ };
+ return newIter;
+};
+
+
+/**
+ * Calls a function for every element in the iterator, and if the function
+ * returns false adds the element to a new iterator.
+ *
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * to iterate over.
+ * @param {
+ * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
+ * The function to call for every element. This function takes 3 arguments
+ * (the element, undefined, and the iterator) and should return a boolean.
+ * If the return value is false the element will be included in the returned
+ * iterator. If it is true the element is not included.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * {@code f}.
+ * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements
+ * that did not pass the test are present.
+ * @template THIS, VALUE
+ */
+goog.iter.filterFalse = function(iterable, f, opt_obj) {
+ return goog.iter.filter(iterable, goog.functions.not(f), opt_obj);
+};
+
+
+/**
+ * Creates a new iterator that returns the values in a range. This function
+ * can take 1, 2 or 3 arguments:
+ * <pre>
+ * range(5) same as range(0, 5, 1)
+ * range(2, 5) same as range(2, 5, 1)
+ * </pre>
+ *
+ * @param {number} startOrStop The stop value if only one argument is provided.
+ * The start value if 2 or more arguments are provided. If only one
+ * argument is used the start value is 0.
+ * @param {number=} opt_stop The stop value. If left out then the first
+ * argument is used as the stop value.
+ * @param {number=} opt_step The number to increment with between each call to
+ * next. This can be negative.
+ * @return {!goog.iter.Iterator<number>} A new iterator that returns the values
+ * in the range.
+ */
+goog.iter.range = function(startOrStop, opt_stop, opt_step) {
+ var start = 0;
+ var stop = startOrStop;
+ var step = opt_step || 1;
+ if (arguments.length > 1) {
+ start = startOrStop;
+ stop = opt_stop;
+ }
+ if (step == 0) {
+ throw Error('Range step argument must not be zero');
+ }
+
+ var newIter = new goog.iter.Iterator;
+ newIter.next = function() {
+ if (step > 0 && start >= stop || step < 0 && start <= stop) {
+ throw goog.iter.StopIteration;
+ }
+ var rv = start;
+ start += step;
+ return rv;
+ };
+ return newIter;
+};
+
+
+/**
+ * Joins the values in a iterator with a delimiter.
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * to get the values from.
+ * @param {string} deliminator The text to put between the values.
+ * @return {string} The joined value string.
+ * @template VALUE
+ */
+goog.iter.join = function(iterable, deliminator) {
+ return goog.iter.toArray(iterable).join(deliminator);
+};
+
+
+/**
+ * For every element in the iterator call a function and return a new iterator
+ * with that value.
+ *
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterator to iterate over.
+ * @param {
+ * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):RESULT} f
+ * The function to call for every element. This function takes 3 arguments
+ * (the element, undefined, and the iterator) and should return a new value.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * {@code f}.
+ * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the
+ * results of applying the function to each element in the original
+ * iterator.
+ * @template THIS, VALUE, RESULT
+ */
+goog.iter.map = function(iterable, f, opt_obj) {
+ var iterator = goog.iter.toIterator(iterable);
+ var newIter = new goog.iter.Iterator;
+ newIter.next = function() {
+ var val = iterator.next();
+ return f.call(opt_obj, val, undefined, iterator);
+ };
+ return newIter;
+};
+
+
+/**
+ * Passes every element of an iterator into a function and accumulates the
+ * result.
+ *
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * to iterate over.
+ * @param {function(this:THIS,VALUE,VALUE):VALUE} f The function to call for
+ * every element. This function takes 2 arguments (the function's previous
+ * result or the initial value, and the value of the current element).
+ * function(previousValue, currentElement) : newValue.
+ * @param {VALUE} val The initial value to pass into the function on the first
+ * call.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * f.
+ * @return {VALUE} Result of evaluating f repeatedly across the values of
+ * the iterator.
+ * @template THIS, VALUE
+ */
+goog.iter.reduce = function(iterable, f, val, opt_obj) {
+ var rval = val;
+ goog.iter.forEach(
+ iterable, function(val) { rval = f.call(opt_obj, rval, val); });
+ return rval;
+};
+
+
+/**
+ * Goes through the values in the iterator. Calls f for each of these, and if
+ * any of them returns true, this returns true (without checking the rest). If
+ * all return false this will return false.
+ *
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * object.
+ * @param {
+ * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
+ * The function to call for every value. This function takes 3 arguments
+ * (the value, undefined, and the iterator) and should return a boolean.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * {@code f}.
+ * @return {boolean} true if any value passes the test.
+ * @template THIS, VALUE
+ */
+goog.iter.some = function(iterable, f, opt_obj) {
+ iterable = goog.iter.toIterator(iterable);
+ /** @preserveTry */
+ try {
+ while (true) {
+ if (f.call(opt_obj, iterable.next(), undefined, iterable)) {
+ return true;
+ }
+ }
+ } catch (ex) {
+ if (ex !== goog.iter.StopIteration) {
+ throw ex;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Goes through the values in the iterator. Calls f for each of these and if any
+ * of them returns false this returns false (without checking the rest). If all
+ * return true this will return true.
+ *
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * object.
+ * @param {
+ * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
+ * The function to call for every value. This function takes 3 arguments
+ * (the value, undefined, and the iterator) and should return a boolean.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * {@code f}.
+ * @return {boolean} true if every value passes the test.
+ * @template THIS, VALUE
+ */
+goog.iter.every = function(iterable, f, opt_obj) {
+ iterable = goog.iter.toIterator(iterable);
+ /** @preserveTry */
+ try {
+ while (true) {
+ if (!f.call(opt_obj, iterable.next(), undefined, iterable)) {
+ return false;
+ }
+ }
+ } catch (ex) {
+ if (ex !== goog.iter.StopIteration) {
+ throw ex;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Takes zero or more iterables and returns one iterator that will iterate over
+ * them in the order chained.
+ * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
+ * number of iterable objects.
+ * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will
+ * iterate over all the given iterables' contents.
+ * @template VALUE
+ */
+goog.iter.chain = function(var_args) {
+ return goog.iter.chainFromIterable(arguments);
+};
+
+
+/**
+ * Takes a single iterable containing zero or more iterables and returns one
+ * iterator that will iterate over each one in the order given.
+ * @see https://goo.gl/5NRp5d
+ * @param {goog.iter.Iterable} iterable The iterable of iterables to chain.
+ * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will
+ * iterate over all the contents of the iterables contained within
+ * {@code iterable}.
+ * @template VALUE
+ */
+goog.iter.chainFromIterable = function(iterable) {
+ var iterator = goog.iter.toIterator(iterable);
+ var iter = new goog.iter.Iterator();
+ var current = null;
+
+ iter.next = function() {
+ while (true) {
+ if (current == null) {
+ var it = iterator.next();
+ current = goog.iter.toIterator(it);
+ }
+ try {
+ return current.next();
+ } catch (ex) {
+ if (ex !== goog.iter.StopIteration) {
+ throw ex;
+ }
+ current = null;
+ }
+ }
+ };
+
+ return iter;
+};
+
+
+/**
+ * Builds a new iterator that iterates over the original, but skips elements as
+ * long as a supplied function returns true.
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * object.
+ * @param {
+ * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
+ * The function to call for every value. This function takes 3 arguments
+ * (the value, undefined, and the iterator) and should return a boolean.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * {@code f}.
+ * @return {!goog.iter.Iterator<VALUE>} A new iterator that drops elements from
+ * the original iterator as long as {@code f} is true.
+ * @template THIS, VALUE
+ */
+goog.iter.dropWhile = function(iterable, f, opt_obj) {
+ var iterator = goog.iter.toIterator(iterable);
+ var newIter = new goog.iter.Iterator;
+ var dropping = true;
+ newIter.next = function() {
+ while (true) {
+ var val = iterator.next();
+ if (dropping && f.call(opt_obj, val, undefined, iterator)) {
+ continue;
+ } else {
+ dropping = false;
+ }
+ return val;
+ }
+ };
+ return newIter;
+};
+
+
+/**
+ * Builds a new iterator that iterates over the original, but only as long as a
+ * supplied function returns true.
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * object.
+ * @param {
+ * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
+ * The function to call for every value. This function takes 3 arguments
+ * (the value, undefined, and the iterator) and should return a boolean.
+ * @param {THIS=} opt_obj This is used as the 'this' object in f when called.
+ * @return {!goog.iter.Iterator<VALUE>} A new iterator that keeps elements in
+ * the original iterator as long as the function is true.
+ * @template THIS, VALUE
+ */
+goog.iter.takeWhile = function(iterable, f, opt_obj) {
+ var iterator = goog.iter.toIterator(iterable);
+ var iter = new goog.iter.Iterator();
+ iter.next = function() {
+ var val = iterator.next();
+ if (f.call(opt_obj, val, undefined, iterator)) {
+ return val;
+ }
+ throw goog.iter.StopIteration;
+ };
+ return iter;
+};
+
+
+/**
+ * Converts the iterator to an array
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
+ * to convert to an array.
+ * @return {!Array<VALUE>} An array of the elements the iterator iterates over.
+ * @template VALUE
+ */
+goog.iter.toArray = function(iterable) {
+ // Fast path for array-like.
+ if (goog.isArrayLike(iterable)) {
+ return goog.array.toArray(/** @type {!IArrayLike<?>} */ (iterable));
+ }
+ iterable = goog.iter.toIterator(iterable);
+ var array = [];
+ goog.iter.forEach(iterable, function(val) { array.push(val); });
+ return array;
+};
+
+
+/**
+ * Iterates over two iterables and returns true if they contain the same
+ * sequence of elements and have the same length.
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable1 The first
+ * iterable object.
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable2 The second
+ * iterable object.
+ * @param {function(VALUE,VALUE):boolean=} opt_equalsFn Optional comparison
+ * function.
+ * Should take two arguments to compare, and return true if the arguments
+ * are equal. Defaults to {@link goog.array.defaultCompareEquality} which
+ * compares the elements using the built-in '===' operator.
+ * @return {boolean} true if the iterables contain the same sequence of elements
+ * and have the same length.
+ * @template VALUE
+ */
+goog.iter.equals = function(iterable1, iterable2, opt_equalsFn) {
+ var fillValue = {};
+ var pairs = goog.iter.zipLongest(fillValue, iterable1, iterable2);
+ var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
+ return goog.iter.every(
+ pairs, function(pair) { return equalsFn(pair[0], pair[1]); });
+};
+
+
+/**
+ * Advances the iterator to the next position, returning the given default value
+ * instead of throwing an exception if the iterator has no more entries.
+ * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterable
+ * object.
+ * @param {VALUE} defaultValue The value to return if the iterator is empty.
+ * @return {VALUE} The next item in the iteration, or defaultValue if the
+ * iterator was empty.
+ * @template VALUE
+ */
+goog.iter.nextOrValue = function(iterable, defaultValue) {
+ try {
+ return goog.iter.toIterator(iterable).next();
+ } catch (e) {
+ if (e != goog.iter.StopIteration) {
+ throw e;
+ }
+ return defaultValue;
+ }
+};
+
+
+/**
+ * Cartesian product of zero or more sets. Gives an iterator that gives every
+ * combination of one element chosen from each set. For example,
+ * ([1, 2], [3, 4]) gives ([1, 3], [1, 4], [2, 3], [2, 4]).
+ * @see http://docs.python.org/library/itertools.html#itertools.product
+ * @param {...!IArrayLike<VALUE>} var_args Zero or more sets, as
+ * arrays.
+ * @return {!goog.iter.Iterator<!Array<VALUE>>} An iterator that gives each
+ * n-tuple (as an array).
+ * @template VALUE
+ */
+goog.iter.product = function(var_args) {
+ var someArrayEmpty =
+ goog.array.some(arguments, function(arr) { return !arr.length; });
+
+ // An empty set in a cartesian product gives an empty set.
+ if (someArrayEmpty || !arguments.length) {
+ return new goog.iter.Iterator();
+ }
+
+ var iter = new goog.iter.Iterator();
+ var arrays = arguments;
+
+ // The first indices are [0, 0, ...]
+ var indicies = goog.array.repeat(0, arrays.length);
+
+ iter.next = function() {
+
+ if (indicies) {
+ var retVal = goog.array.map(indicies, function(valueIndex, arrayIndex) {
+ return arrays[arrayIndex][valueIndex];
+ });
+
+ // Generate the next-largest indices for the next call.
+ // Increase the rightmost index. If it goes over, increase the next
+ // rightmost (like carry-over addition).
+ for (var i = indicies.length - 1; i >= 0; i--) {
+ // Assertion prevents compiler warning below.
+ goog.asserts.assert(indicies);
+ if (indicies[i] < arrays[i].length - 1) {
+ indicies[i]++;
+ break;
+ }
+
+ // We're at the last indices (the last element of every array), so
+ // the iteration is over on the next call.
+ if (i == 0) {
+ indicies = null;
+ break;
+ }
+ // Reset the index in this column and loop back to increment the
+ // next one.
+ indicies[i] = 0;
+ }
+ return retVal;
+ }
+
+ throw goog.iter.StopIteration;
+ };
+
+ return iter;
+};
+
+
+/**
+ * Create an iterator to cycle over the iterable's elements indefinitely.
+ * For example, ([1, 2, 3]) would return : 1, 2, 3, 1, 2, 3, ...
+ * @see: http://docs.python.org/library/itertools.html#itertools.cycle.
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable object.
+ * @return {!goog.iter.Iterator<VALUE>} An iterator that iterates indefinitely
+ * over the values in {@code iterable}.
+ * @template VALUE
+ */
+goog.iter.cycle = function(iterable) {
+ var baseIterator = goog.iter.toIterator(iterable);
+
+ // We maintain a cache to store the iterable elements as we iterate
+ // over them. The cache is used to return elements once we have
+ // iterated over the iterable once.
+ var cache = [];
+ var cacheIndex = 0;
+
+ var iter = new goog.iter.Iterator();
+
+ // This flag is set after the iterable is iterated over once
+ var useCache = false;
+
+ iter.next = function() {
+ var returnElement = null;
+
+ // Pull elements off the original iterator if not using cache
+ if (!useCache) {
+ try {
+ // Return the element from the iterable
+ returnElement = baseIterator.next();
+ cache.push(returnElement);
+ return returnElement;
+ } catch (e) {
+ // If an exception other than StopIteration is thrown
+ // or if there are no elements to iterate over (the iterable was empty)
+ // throw an exception
+ if (e != goog.iter.StopIteration || goog.array.isEmpty(cache)) {
+ throw e;
+ }
+ // set useCache to true after we know that a 'StopIteration' exception
+ // was thrown and the cache is not empty (to handle the 'empty iterable'
+ // use case)
+ useCache = true;
+ }
+ }
+
+ returnElement = cache[cacheIndex];
+ cacheIndex = (cacheIndex + 1) % cache.length;
+
+ return returnElement;
+ };
+
+ return iter;
+};
+
+
+/**
+ * Creates an iterator that counts indefinitely from a starting value.
+ * @see http://docs.python.org/2/library/itertools.html#itertools.count
+ * @param {number=} opt_start The starting value. Default is 0.
+ * @param {number=} opt_step The number to increment with between each call to
+ * next. Negative and floating point numbers are allowed. Default is 1.
+ * @return {!goog.iter.Iterator<number>} A new iterator that returns the values
+ * in the series.
+ */
+goog.iter.count = function(opt_start, opt_step) {
+ var counter = opt_start || 0;
+ var step = goog.isDef(opt_step) ? opt_step : 1;
+ var iter = new goog.iter.Iterator();
+
+ iter.next = function() {
+ var returnValue = counter;
+ counter += step;
+ return returnValue;
+ };
+
+ return iter;
+};
+
+
+/**
+ * Creates an iterator that returns the same object or value repeatedly.
+ * @param {VALUE} value Any object or value to repeat.
+ * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the
+ * repeated value.
+ * @template VALUE
+ */
+goog.iter.repeat = function(value) {
+ var iter = new goog.iter.Iterator();
+
+ iter.next = goog.functions.constant(value);
+
+ return iter;
+};
+
+
+/**
+ * Creates an iterator that returns running totals from the numbers in
+ * {@code iterable}. For example, the array {@code [1, 2, 3, 4, 5]} yields
+ * {@code 1 -> 3 -> 6 -> 10 -> 15}.
+ * @see http://docs.python.org/3.2/library/itertools.html#itertools.accumulate
+ * @param {!goog.iter.Iterable<number>} iterable The iterable of numbers to
+ * accumulate.
+ * @return {!goog.iter.Iterator<number>} A new iterator that returns the
+ * numbers in the series.
+ */
+goog.iter.accumulate = function(iterable) {
+ var iterator = goog.iter.toIterator(iterable);
+ var total = 0;
+ var iter = new goog.iter.Iterator();
+
+ iter.next = function() {
+ total += iterator.next();
+ return total;
+ };
+
+ return iter;
+};
+
+
+/**
+ * Creates an iterator that returns arrays containing the ith elements from the
+ * provided iterables. The returned arrays will be the same size as the number
+ * of iterables given in {@code var_args}. Once the shortest iterable is
+ * exhausted, subsequent calls to {@code next()} will throw
+ * {@code goog.iter.StopIteration}.
+ * @see http://docs.python.org/2/library/itertools.html#itertools.izip
+ * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
+ * number of iterable objects.
+ * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns
+ * arrays of elements from the provided iterables.
+ * @template VALUE
+ */
+goog.iter.zip = function(var_args) {
+ var args = arguments;
+ var iter = new goog.iter.Iterator();
+
+ if (args.length > 0) {
+ var iterators = goog.array.map(args, goog.iter.toIterator);
+ iter.next = function() {
+ var arr = goog.array.map(iterators, function(it) { return it.next(); });
+ return arr;
+ };
+ }
+
+ return iter;
+};
+
+
+/**
+ * Creates an iterator that returns arrays containing the ith elements from the
+ * provided iterables. The returned arrays will be the same size as the number
+ * of iterables given in {@code var_args}. Shorter iterables will be extended
+ * with {@code fillValue}. Once the longest iterable is exhausted, subsequent
+ * calls to {@code next()} will throw {@code goog.iter.StopIteration}.
+ * @see http://docs.python.org/2/library/itertools.html#itertools.izip_longest
+ * @param {VALUE} fillValue The object or value used to fill shorter iterables.
+ * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
+ * number of iterable objects.
+ * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns
+ * arrays of elements from the provided iterables.
+ * @template VALUE
+ */
+goog.iter.zipLongest = function(fillValue, var_args) {
+ var args = goog.array.slice(arguments, 1);
+ var iter = new goog.iter.Iterator();
+
+ if (args.length > 0) {
+ var iterators = goog.array.map(args, goog.iter.toIterator);
+
+ iter.next = function() {
+ var iteratorsHaveValues = false; // false when all iterators are empty.
+ var arr = goog.array.map(iterators, function(it) {
+ var returnValue;
+ try {
+ returnValue = it.next();
+ // Iterator had a value, so we've not exhausted the iterators.
+ // Set flag accordingly.
+ iteratorsHaveValues = true;
+ } catch (ex) {
+ if (ex !== goog.iter.StopIteration) {
+ throw ex;
+ }
+ returnValue = fillValue;
+ }
+ return returnValue;
+ });
+
+ if (!iteratorsHaveValues) {
+ throw goog.iter.StopIteration;
+ }
+ return arr;
+ };
+ }
+
+ return iter;
+};
+
+
+/**
+ * Creates an iterator that filters {@code iterable} based on a series of
+ * {@code selectors}. On each call to {@code next()}, one item is taken from
+ * both the {@code iterable} and {@code selectors} iterators. If the item from
+ * {@code selectors} evaluates to true, the item from {@code iterable} is given.
+ * Otherwise, it is skipped. Once either {@code iterable} or {@code selectors}
+ * is exhausted, subsequent calls to {@code next()} will throw
+ * {@code goog.iter.StopIteration}.
+ * @see http://docs.python.org/2/library/itertools.html#itertools.compress
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to filter.
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} selectors An
+ * iterable of items to be evaluated in a boolean context to determine if
+ * the corresponding element in {@code iterable} should be included in the
+ * result.
+ * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the
+ * filtered values.
+ * @template VALUE
+ */
+goog.iter.compress = function(iterable, selectors) {
+ var selectorIterator = goog.iter.toIterator(selectors);
+
+ return goog.iter.filter(
+ iterable, function() { return !!selectorIterator.next(); });
+};
+
+
+
+/**
+ * Implements the {@code goog.iter.groupBy} iterator.
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to group.
+ * @param {function(VALUE): KEY=} opt_keyFunc Optional function for
+ * determining the key value for each group in the {@code iterable}. Default
+ * is the identity function.
+ * @constructor
+ * @extends {goog.iter.Iterator<!Array<?>>}
+ * @template KEY, VALUE
+ * @private
+ */
+goog.iter.GroupByIterator_ = function(iterable, opt_keyFunc) {
+
+ /**
+ * The iterable to group, coerced to an iterator.
+ * @type {!goog.iter.Iterator}
+ */
+ this.iterator = goog.iter.toIterator(iterable);
+
+ /**
+ * A function for determining the key value for each element in the iterable.
+ * If no function is provided, the identity function is used and returns the
+ * element unchanged.
+ * @type {function(VALUE): KEY}
+ */
+ this.keyFunc = opt_keyFunc || goog.functions.identity;
+
+ /**
+ * The target key for determining the start of a group.
+ * @type {KEY}
+ */
+ this.targetKey;
+
+ /**
+ * The current key visited during iteration.
+ * @type {KEY}
+ */
+ this.currentKey;
+
+ /**
+ * The current value being added to the group.
+ * @type {VALUE}
+ */
+ this.currentValue;
+};
+goog.inherits(goog.iter.GroupByIterator_, goog.iter.Iterator);
+
+
+/** @override */
+goog.iter.GroupByIterator_.prototype.next = function() {
+ while (this.currentKey == this.targetKey) {
+ this.currentValue = this.iterator.next(); // Exits on StopIteration
+ this.currentKey = this.keyFunc(this.currentValue);
+ }
+ this.targetKey = this.currentKey;
+ return [this.currentKey, this.groupItems_(this.targetKey)];
+};
+
+
+/**
+ * Performs the grouping of objects using the given key.
+ * @param {KEY} targetKey The target key object for the group.
+ * @return {!Array<VALUE>} An array of grouped objects.
+ * @private
+ */
+goog.iter.GroupByIterator_.prototype.groupItems_ = function(targetKey) {
+ var arr = [];
+ while (this.currentKey == targetKey) {
+ arr.push(this.currentValue);
+ try {
+ this.currentValue = this.iterator.next();
+ } catch (ex) {
+ if (ex !== goog.iter.StopIteration) {
+ throw ex;
+ }
+ break;
+ }
+ this.currentKey = this.keyFunc(this.currentValue);
+ }
+ return arr;
+};
+
+
+/**
+ * Creates an iterator that returns arrays containing elements from the
+ * {@code iterable} grouped by a key value. For iterables with repeated
+ * elements (i.e. sorted according to a particular key function), this function
+ * has a {@code uniq}-like effect. For example, grouping the array:
+ * {@code [A, B, B, C, C, A]} produces
+ * {@code [A, [A]], [B, [B, B]], [C, [C, C]], [A, [A]]}.
+ * @see http://docs.python.org/2/library/itertools.html#itertools.groupby
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to group.
+ * @param {function(VALUE): KEY=} opt_keyFunc Optional function for
+ * determining the key value for each group in the {@code iterable}. Default
+ * is the identity function.
+ * @return {!goog.iter.Iterator<!Array<?>>} A new iterator that returns
+ * arrays of consecutive key and groups.
+ * @template KEY, VALUE
+ */
+goog.iter.groupBy = function(iterable, opt_keyFunc) {
+ return new goog.iter.GroupByIterator_(iterable, opt_keyFunc);
+};
+
+
+/**
+ * Gives an iterator that gives the result of calling the given function
+ * <code>f</code> with the arguments taken from the next element from
+ * <code>iterable</code> (the elements are expected to also be iterables).
+ *
+ * Similar to {@see goog.iter#map} but allows the function to accept multiple
+ * arguments from the iterable.
+ *
+ * @param {!goog.iter.Iterable<!goog.iter.Iterable>} iterable The iterable of
+ * iterables to iterate over.
+ * @param {function(this:THIS,...*):RESULT} f The function to call for every
+ * element. This function takes N+2 arguments, where N represents the
+ * number of items from the next element of the iterable. The two
+ * additional arguments passed to the function are undefined and the
+ * iterator itself. The function should return a new value.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within
+ * {@code f}.
+ * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the
+ * results of applying the function to each element in the original
+ * iterator.
+ * @template THIS, RESULT
+ */
+goog.iter.starMap = function(iterable, f, opt_obj) {
+ var iterator = goog.iter.toIterator(iterable);
+ var iter = new goog.iter.Iterator();
+
+ iter.next = function() {
+ var args = goog.iter.toArray(iterator.next());
+ return f.apply(opt_obj, goog.array.concat(args, undefined, iterator));
+ };
+
+ return iter;
+};
+
+
+/**
+ * Returns an array of iterators each of which can iterate over the values in
+ * {@code iterable} without advancing the others.
+ * @see http://docs.python.org/2/library/itertools.html#itertools.tee
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to tee.
+ * @param {number=} opt_num The number of iterators to create. Default is 2.
+ * @return {!Array<goog.iter.Iterator<VALUE>>} An array of iterators.
+ * @template VALUE
+ */
+goog.iter.tee = function(iterable, opt_num) {
+ var iterator = goog.iter.toIterator(iterable);
+ var num = goog.isNumber(opt_num) ? opt_num : 2;
+ var buffers =
+ goog.array.map(goog.array.range(num), function() { return []; });
+
+ var addNextIteratorValueToBuffers = function() {
+ var val = iterator.next();
+ goog.array.forEach(buffers, function(buffer) { buffer.push(val); });
+ };
+
+ var createIterator = function(buffer) {
+ // Each tee'd iterator has an associated buffer (initially empty). When a
+ // tee'd iterator's buffer is empty, it calls
+ // addNextIteratorValueToBuffers(), adding the next value to all tee'd
+ // iterators' buffers, and then returns that value. This allows each
+ // iterator to be advanced independently.
+ var iter = new goog.iter.Iterator();
+
+ iter.next = function() {
+ if (goog.array.isEmpty(buffer)) {
+ addNextIteratorValueToBuffers();
+ }
+ goog.asserts.assert(!goog.array.isEmpty(buffer));
+ return buffer.shift();
+ };
+
+ return iter;
+ };
+
+ return goog.array.map(buffers, createIterator);
+};
+
+
+/**
+ * Creates an iterator that returns arrays containing a count and an element
+ * obtained from the given {@code iterable}.
+ * @see http://docs.python.org/2/library/functions.html#enumerate
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to enumerate.
+ * @param {number=} opt_start Optional starting value. Default is 0.
+ * @return {!goog.iter.Iterator<!Array<?>>} A new iterator containing
+ * count/item pairs.
+ * @template VALUE
+ */
+goog.iter.enumerate = function(iterable, opt_start) {
+ return goog.iter.zip(goog.iter.count(opt_start), iterable);
+};
+
+
+/**
+ * Creates an iterator that returns the first {@code limitSize} elements from an
+ * iterable. If this number is greater than the number of elements in the
+ * iterable, all the elements are returned.
+ * @see http://goo.gl/V0sihp Inspired by the limit iterator in Guava.
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to limit.
+ * @param {number} limitSize The maximum number of elements to return.
+ * @return {!goog.iter.Iterator<VALUE>} A new iterator containing
+ * {@code limitSize} elements.
+ * @template VALUE
+ */
+goog.iter.limit = function(iterable, limitSize) {
+ goog.asserts.assert(goog.math.isInt(limitSize) && limitSize >= 0);
+
+ var iterator = goog.iter.toIterator(iterable);
+
+ var iter = new goog.iter.Iterator();
+ var remaining = limitSize;
+
+ iter.next = function() {
+ if (remaining-- > 0) {
+ return iterator.next();
+ }
+ throw goog.iter.StopIteration;
+ };
+
+ return iter;
+};
+
+
+/**
+ * Creates an iterator that is advanced {@code count} steps ahead. Consumed
+ * values are silently discarded. If {@code count} is greater than the number
+ * of elements in {@code iterable}, an empty iterator is returned. Subsequent
+ * calls to {@code next()} will throw {@code goog.iter.StopIteration}.
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to consume.
+ * @param {number} count The number of elements to consume from the iterator.
+ * @return {!goog.iter.Iterator<VALUE>} An iterator advanced zero or more steps
+ * ahead.
+ * @template VALUE
+ */
+goog.iter.consume = function(iterable, count) {
+ goog.asserts.assert(goog.math.isInt(count) && count >= 0);
+
+ var iterator = goog.iter.toIterator(iterable);
+
+ while (count-- > 0) {
+ goog.iter.nextOrValue(iterator, null);
+ }
+
+ return iterator;
+};
+
+
+/**
+ * Creates an iterator that returns a range of elements from an iterable.
+ * Similar to {@see goog.array#slice} but does not support negative indexes.
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to slice.
+ * @param {number} start The index of the first element to return.
+ * @param {number=} opt_end The index after the last element to return. If
+ * defined, must be greater than or equal to {@code start}.
+ * @return {!goog.iter.Iterator<VALUE>} A new iterator containing a slice of
+ * the original.
+ * @template VALUE
+ */
+goog.iter.slice = function(iterable, start, opt_end) {
+ goog.asserts.assert(goog.math.isInt(start) && start >= 0);
+
+ var iterator = goog.iter.consume(iterable, start);
+
+ if (goog.isNumber(opt_end)) {
+ goog.asserts.assert(goog.math.isInt(opt_end) && opt_end >= start);
+ iterator = goog.iter.limit(iterator, opt_end - start /* limitSize */);
+ }
+
+ return iterator;
+};
+
+
+/**
+ * Checks an array for duplicate elements.
+ * @param {?IArrayLike<VALUE>} arr The array to check for
+ * duplicates.
+ * @return {boolean} True, if the array contains duplicates, false otherwise.
+ * @private
+ * @template VALUE
+ */
+// TODO(user): Consider moving this into goog.array as a public function.
+goog.iter.hasDuplicates_ = function(arr) {
+ var deduped = [];
+ goog.array.removeDuplicates(arr, deduped);
+ return arr.length != deduped.length;
+};
+
+
+/**
+ * Creates an iterator that returns permutations of elements in
+ * {@code iterable}.
+ *
+ * Permutations are obtained by taking the Cartesian product of
+ * {@code opt_length} iterables and filtering out those with repeated
+ * elements. For example, the permutations of {@code [1,2,3]} are
+ * {@code [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]}.
+ * @see http://docs.python.org/2/library/itertools.html#itertools.permutations
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable from which to generate permutations.
+ * @param {number=} opt_length Length of each permutation. If omitted, defaults
+ * to the length of {@code iterable}.
+ * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing the
+ * permutations of {@code iterable}.
+ * @template VALUE
+ */
+goog.iter.permutations = function(iterable, opt_length) {
+ var elements = goog.iter.toArray(iterable);
+ var length = goog.isNumber(opt_length) ? opt_length : elements.length;
+
+ var sets = goog.array.repeat(elements, length);
+ var product = goog.iter.product.apply(undefined, sets);
+
+ return goog.iter.filter(
+ product, function(arr) { return !goog.iter.hasDuplicates_(arr); });
+};
+
+
+/**
+ * Creates an iterator that returns combinations of elements from
+ * {@code iterable}.
+ *
+ * Combinations are obtained by taking the {@see goog.iter#permutations} of
+ * {@code iterable} and filtering those whose elements appear in the order they
+ * are encountered in {@code iterable}. For example, the 3-length combinations
+ * of {@code [0,1,2,3]} are {@code [[0,1,2], [0,1,3], [0,2,3], [1,2,3]]}.
+ * @see http://docs.python.org/2/library/itertools.html#itertools.combinations
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable from which to generate combinations.
+ * @param {number} length The length of each combination.
+ * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing
+ * combinations from the {@code iterable}.
+ * @template VALUE
+ */
+goog.iter.combinations = function(iterable, length) {
+ var elements = goog.iter.toArray(iterable);
+ var indexes = goog.iter.range(elements.length);
+ var indexIterator = goog.iter.permutations(indexes, length);
+ // sortedIndexIterator will now give arrays of with the given length that
+ // indicate what indexes into "elements" should be returned on each iteration.
+ var sortedIndexIterator = goog.iter.filter(
+ indexIterator, function(arr) { return goog.array.isSorted(arr); });
+
+ var iter = new goog.iter.Iterator();
+
+ function getIndexFromElements(index) { return elements[index]; }
+
+ iter.next = function() {
+ return goog.array.map(sortedIndexIterator.next(), getIndexFromElements);
+ };
+
+ return iter;
+};
+
+
+/**
+ * Creates an iterator that returns combinations of elements from
+ * {@code iterable}, with repeated elements possible.
+ *
+ * Combinations are obtained by taking the Cartesian product of {@code length}
+ * iterables and filtering those whose elements appear in the order they are
+ * encountered in {@code iterable}. For example, the 2-length combinations of
+ * {@code [1,2,3]} are {@code [[1,1], [1,2], [1,3], [2,2], [2,3], [3,3]]}.
+ * @see https://goo.gl/C0yXe4
+ * @see https://goo.gl/djOCsk
+ * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
+ * iterable to combine.
+ * @param {number} length The length of each combination.
+ * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing
+ * combinations from the {@code iterable}.
+ * @template VALUE
+ */
+goog.iter.combinationsWithReplacement = function(iterable, length) {
+ var elements = goog.iter.toArray(iterable);
+ var indexes = goog.array.range(elements.length);
+ var sets = goog.array.repeat(indexes, length);
+ var indexIterator = goog.iter.product.apply(undefined, sets);
+ // sortedIndexIterator will now give arrays of with the given length that
+ // indicate what indexes into "elements" should be returned on each iteration.
+ var sortedIndexIterator = goog.iter.filter(
+ indexIterator, function(arr) { return goog.array.isSorted(arr); });
+
+ var iter = new goog.iter.Iterator();
+
+ function getIndexFromElements(index) { return elements[index]; }
+
+ iter.next = function() {
+ return goog.array.map(
+ /** @type {!Array<number>} */
+ (sortedIndexIterator.next()), getIndexFromElements);
+ };
+
+ return iter;
+};
+
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Datastructure: Hash Map.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ *
+ * This file contains an implementation of a Map structure. It implements a lot
+ * of the methods used in goog.structs so those functions work on hashes. This
+ * is best suited for complex key types. For simple keys such as numbers and
+ * strings consider using the lighter-weight utilities in goog.object.
+ */
+
+
+goog.provide('goog.structs.Map');
+
+goog.require('goog.iter.Iterator');
+goog.require('goog.iter.StopIteration');
+goog.require('goog.object');
+
+
+
+/**
+ * Class for Hash Map datastructure.
+ * @param {*=} opt_map Map or Object to initialize the map with.
+ * @param {...*} var_args If 2 or more arguments are present then they
+ * will be used as key-value pairs.
+ * @constructor
+ * @template K, V
+ */
+goog.structs.Map = function(opt_map, var_args) {
+
+ /**
+ * Underlying JS object used to implement the map.
+ * @private {!Object}
+ */
+ this.map_ = {};
+
+ /**
+ * An array of keys. This is necessary for two reasons:
+ * 1. Iterating the keys using for (var key in this.map_) allocates an
+ * object for every key in IE which is really bad for IE6 GC perf.
+ * 2. Without a side data structure, we would need to escape all the keys
+ * as that would be the only way we could tell during iteration if the
+ * key was an internal key or a property of the object.
+ *
+ * This array can contain deleted keys so it's necessary to check the map
+ * as well to see if the key is still in the map (this doesn't require a
+ * memory allocation in IE).
+ * @private {!Array<string>}
+ */
+ this.keys_ = [];
+
+ /**
+ * The number of key value pairs in the map.
+ * @private {number}
+ */
+ this.count_ = 0;
+
+ /**
+ * Version used to detect changes while iterating.
+ * @private {number}
+ */
+ this.version_ = 0;
+
+ var argLength = arguments.length;
+
+ if (argLength > 1) {
+ if (argLength % 2) {
+ throw Error('Uneven number of arguments');
+ }
+ for (var i = 0; i < argLength; i += 2) {
+ this.set(arguments[i], arguments[i + 1]);
+ }
+ } else if (opt_map) {
+ this.addAll(/** @type {Object} */ (opt_map));
+ }
+};
+
+
+/**
+ * @return {number} The number of key-value pairs in the map.
+ */
+goog.structs.Map.prototype.getCount = function() {
+ return this.count_;
+};
+
+
+/**
+ * Returns the values of the map.
+ * @return {!Array<V>} The values in the map.
+ */
+goog.structs.Map.prototype.getValues = function() {
+ this.cleanupKeysArray_();
+
+ var rv = [];
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ rv.push(this.map_[key]);
+ }
+ return rv;
+};
+
+
+/**
+ * Returns the keys of the map.
+ * @return {!Array<string>} Array of string values.
+ */
+goog.structs.Map.prototype.getKeys = function() {
+ this.cleanupKeysArray_();
+ return /** @type {!Array<string>} */ (this.keys_.concat());
+};
+
+
+/**
+ * Whether the map contains the given key.
+ * @param {*} key The key to check for.
+ * @return {boolean} Whether the map contains the key.
+ */
+goog.structs.Map.prototype.containsKey = function(key) {
+ return goog.structs.Map.hasKey_(this.map_, key);
+};
+
+
+/**
+ * Whether the map contains the given value. This is O(n).
+ * @param {V} val The value to check for.
+ * @return {boolean} Whether the map contains the value.
+ */
+goog.structs.Map.prototype.containsValue = function(val) {
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ if (goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Whether this map is equal to the argument map.
+ * @param {goog.structs.Map} otherMap The map against which to test equality.
+ * @param {function(V, V): boolean=} opt_equalityFn Optional equality function
+ * to test equality of values. If not specified, this will test whether
+ * the values contained in each map are identical objects.
+ * @return {boolean} Whether the maps are equal.
+ */
+goog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) {
+ if (this === otherMap) {
+ return true;
+ }
+
+ if (this.count_ != otherMap.getCount()) {
+ return false;
+ }
+
+ var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals;
+
+ this.cleanupKeysArray_();
+ for (var key, i = 0; key = this.keys_[i]; i++) {
+ if (!equalityFn(this.get(key), otherMap.get(key))) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+
+/**
+ * Default equality test for values.
+ * @param {*} a The first value.
+ * @param {*} b The second value.
+ * @return {boolean} Whether a and b reference the same object.
+ */
+goog.structs.Map.defaultEquals = function(a, b) {
+ return a === b;
+};
+
+
+/**
+ * @return {boolean} Whether the map is empty.
+ */
+goog.structs.Map.prototype.isEmpty = function() {
+ return this.count_ == 0;
+};
+
+
+/**
+ * Removes all key-value pairs from the map.
+ */
+goog.structs.Map.prototype.clear = function() {
+ this.map_ = {};
+ this.keys_.length = 0;
+ this.count_ = 0;
+ this.version_ = 0;
+};
+
+
+/**
+ * Removes a key-value pair based on the key. This is O(logN) amortized due to
+ * updating the keys array whenever the count becomes half the size of the keys
+ * in the keys array.
+ * @param {*} key The key to remove.
+ * @return {boolean} Whether object was removed.
+ */
+goog.structs.Map.prototype.remove = function(key) {
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ delete this.map_[key];
+ this.count_--;
+ this.version_++;
+
+ // clean up the keys array if the threshhold is hit
+ if (this.keys_.length > 2 * this.count_) {
+ this.cleanupKeysArray_();
+ }
+
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Cleans up the temp keys array by removing entries that are no longer in the
+ * map.
+ * @private
+ */
+goog.structs.Map.prototype.cleanupKeysArray_ = function() {
+ if (this.count_ != this.keys_.length) {
+ // First remove keys that are no longer in the map.
+ var srcIndex = 0;
+ var destIndex = 0;
+ while (srcIndex < this.keys_.length) {
+ var key = this.keys_[srcIndex];
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ this.keys_[destIndex++] = key;
+ }
+ srcIndex++;
+ }
+ this.keys_.length = destIndex;
+ }
+
+ if (this.count_ != this.keys_.length) {
+ // If the count still isn't correct, that means we have duplicates. This can
+ // happen when the same key is added and removed multiple times. Now we have
+ // to allocate one extra Object to remove the duplicates. This could have
+ // been done in the first pass, but in the common case, we can avoid
+ // allocating an extra object by only doing this when necessary.
+ var seen = {};
+ var srcIndex = 0;
+ var destIndex = 0;
+ while (srcIndex < this.keys_.length) {
+ var key = this.keys_[srcIndex];
+ if (!(goog.structs.Map.hasKey_(seen, key))) {
+ this.keys_[destIndex++] = key;
+ seen[key] = 1;
+ }
+ srcIndex++;
+ }
+ this.keys_.length = destIndex;
+ }
+};
+
+
+/**
+ * Returns the value for the given key. If the key is not found and the default
+ * value is not given this will return {@code undefined}.
+ * @param {*} key The key to get the value for.
+ * @param {DEFAULT=} opt_val The value to return if no item is found for the
+ * given key, defaults to undefined.
+ * @return {V|DEFAULT} The value for the given key.
+ * @template DEFAULT
+ */
+goog.structs.Map.prototype.get = function(key, opt_val) {
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ return this.map_[key];
+ }
+ return opt_val;
+};
+
+
+/**
+ * Adds a key-value pair to the map.
+ * @param {*} key The key.
+ * @param {V} value The value to add.
+ * @return {*} Some subclasses return a value.
+ */
+goog.structs.Map.prototype.set = function(key, value) {
+ if (!(goog.structs.Map.hasKey_(this.map_, key))) {
+ this.count_++;
+ // TODO(johnlenz): This class lies, it claims to return an array of string
+ // keys, but instead returns the original object used.
+ this.keys_.push(/** @type {?} */ (key));
+ // Only change the version if we add a new key.
+ this.version_++;
+ }
+ this.map_[key] = value;
+};
+
+
+/**
+ * Adds multiple key-value pairs from another goog.structs.Map or Object.
+ * @param {Object} map Object containing the data to add.
+ */
+goog.structs.Map.prototype.addAll = function(map) {
+ var keys, values;
+ if (map instanceof goog.structs.Map) {
+ keys = map.getKeys();
+ values = map.getValues();
+ } else {
+ keys = goog.object.getKeys(map);
+ values = goog.object.getValues(map);
+ }
+ // we could use goog.array.forEach here but I don't want to introduce that
+ // dependency just for this.
+ for (var i = 0; i < keys.length; i++) {
+ this.set(keys[i], values[i]);
+ }
+};
+
+
+/**
+ * Calls the given function on each entry in the map.
+ * @param {function(this:T, V, K, goog.structs.Map<K,V>)} f
+ * @param {T=} opt_obj The value of "this" inside f.
+ * @template T
+ */
+goog.structs.Map.prototype.forEach = function(f, opt_obj) {
+ var keys = this.getKeys();
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ var value = this.get(key);
+ f.call(opt_obj, value, key, this);
+ }
+};
+
+
+/**
+ * Clones a map and returns a new map.
+ * @return {!goog.structs.Map} A new map with the same key-value pairs.
+ */
+goog.structs.Map.prototype.clone = function() {
+ return new goog.structs.Map(this);
+};
+
+
+/**
+ * Returns a new map in which all the keys and values are interchanged
+ * (keys become values and values become keys). If multiple keys map to the
+ * same value, the chosen transposed value is implementation-dependent.
+ *
+ * It acts very similarly to {goog.object.transpose(Object)}.
+ *
+ * @return {!goog.structs.Map} The transposed map.
+ */
+goog.structs.Map.prototype.transpose = function() {
+ var transposed = new goog.structs.Map();
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ var value = this.map_[key];
+ transposed.set(value, key);
+ }
+
+ return transposed;
+};
+
+
+/**
+ * @return {!Object} Object representation of the map.
+ */
+goog.structs.Map.prototype.toObject = function() {
+ this.cleanupKeysArray_();
+ var obj = {};
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ obj[key] = this.map_[key];
+ }
+ return obj;
+};
+
+
+/**
+ * Returns an iterator that iterates over the keys in the map. Removal of keys
+ * while iterating might have undesired side effects.
+ * @return {!goog.iter.Iterator} An iterator over the keys in the map.
+ */
+goog.structs.Map.prototype.getKeyIterator = function() {
+ return this.__iterator__(true);
+};
+
+
+/**
+ * Returns an iterator that iterates over the values in the map. Removal of
+ * keys while iterating might have undesired side effects.
+ * @return {!goog.iter.Iterator} An iterator over the values in the map.
+ */
+goog.structs.Map.prototype.getValueIterator = function() {
+ return this.__iterator__(false);
+};
+
+
+/**
+ * Returns an iterator that iterates over the values or the keys in the map.
+ * This throws an exception if the map was mutated since the iterator was
+ * created.
+ * @param {boolean=} opt_keys True to iterate over the keys. False to iterate
+ * over the values. The default value is false.
+ * @return {!goog.iter.Iterator} An iterator over the values or keys in the map.
+ */
+goog.structs.Map.prototype.__iterator__ = function(opt_keys) {
+ // Clean up keys to minimize the risk of iterating over dead keys.
+ this.cleanupKeysArray_();
+
+ var i = 0;
+ var version = this.version_;
+ var selfObj = this;
+
+ var newIter = new goog.iter.Iterator;
+ newIter.next = function() {
+ if (version != selfObj.version_) {
+ throw Error('The map has changed since the iterator was created');
+ }
+ if (i >= selfObj.keys_.length) {
+ throw goog.iter.StopIteration;
+ }
+ var key = selfObj.keys_[i++];
+ return opt_keys ? key : selfObj.map_[key];
+ };
+ return newIter;
+};
+
+
+/**
+ * Safe way to test for hasOwnProperty. It even allows testing for
+ * 'hasOwnProperty'.
+ * @param {Object} obj The object to test for presence of the given key.
+ * @param {*} key The key to check for.
+ * @return {boolean} Whether the object has the key.
+ * @private
+ */
+goog.structs.Map.hasKey_ = function(obj, key) {
+ return Object.prototype.hasOwnProperty.call(obj, key);
+};
+
+// Copyright 2008 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Simple utilities for dealing with URI strings.
+ *
+ * This is intended to be a lightweight alternative to constructing goog.Uri
+ * objects. Whereas goog.Uri adds several kilobytes to the binary regardless
+ * of how much of its functionality you use, this is designed to be a set of
+ * mostly-independent utilities so that the compiler includes only what is
+ * necessary for the task. Estimated savings of porting is 5k pre-gzip and
+ * 1.5k post-gzip. To ensure the savings remain, future developers should
+ * avoid adding new functionality to existing functions, but instead create
+ * new ones and factor out shared code.
+ *
+ * Many of these utilities have limited functionality, tailored to common
+ * cases. The query parameter utilities assume that the parameter keys are
+ * already encoded, since most keys are compile-time alphanumeric strings. The
+ * query parameter mutation utilities also do not tolerate fragment identifiers.
+ *
+ * By design, these functions can be slower than goog.Uri equivalents.
+ * Repeated calls to some of functions may be quadratic in behavior for IE,
+ * although the effect is somewhat limited given the 2kb limit.
+ *
+ * One advantage of the limited functionality here is that this approach is
+ * less sensitive to differences in URI encodings than goog.Uri, since these
+ * functions operate on strings directly, rather than decoding them and
+ * then re-encoding.
+ *
+ * Uses features of RFC 3986 for parsing/formatting URIs:
+ * http://www.ietf.org/rfc/rfc3986.txt
+ *
+ * @author gboyer@google.com (Garrett Boyer) - The "lightened" design.
+ */
+
+goog.provide('goog.uri.utils');
+goog.provide('goog.uri.utils.ComponentIndex');
+goog.provide('goog.uri.utils.QueryArray');
+goog.provide('goog.uri.utils.QueryValue');
+goog.provide('goog.uri.utils.StandardQueryParam');
+
+goog.require('goog.asserts');
+goog.require('goog.string');
+
+
+/**
+ * Character codes inlined to avoid object allocations due to charCode.
+ * @enum {number}
+ * @private
+ */
+goog.uri.utils.CharCode_ = {
+ AMPERSAND: 38,
+ EQUAL: 61,
+ HASH: 35,
+ QUESTION: 63
+};
+
+
+/**
+ * Builds a URI string from already-encoded parts.
+ *
+ * No encoding is performed. Any component may be omitted as either null or
+ * undefined.
+ *
+ * @param {?string=} opt_scheme The scheme such as 'http'.
+ * @param {?string=} opt_userInfo The user name before the '@'.
+ * @param {?string=} opt_domain The domain such as 'www.google.com', already
+ * URI-encoded.
+ * @param {(string|number|null)=} opt_port The port number.
+ * @param {?string=} opt_path The path, already URI-encoded. If it is not
+ * empty, it must begin with a slash.
+ * @param {?string=} opt_queryData The URI-encoded query data.
+ * @param {?string=} opt_fragment The URI-encoded fragment identifier.
+ * @return {string} The fully combined URI.
+ */
+goog.uri.utils.buildFromEncodedParts = function(
+ opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_queryData,
+ opt_fragment) {
+ var out = '';
+
+ if (opt_scheme) {
+ out += opt_scheme + ':';
+ }
+
+ if (opt_domain) {
+ out += '//';
+
+ if (opt_userInfo) {
+ out += opt_userInfo + '@';
+ }
+
+ out += opt_domain;
+
+ if (opt_port) {
+ out += ':' + opt_port;
+ }
+ }
+
+ if (opt_path) {
+ out += opt_path;
+ }
+
+ if (opt_queryData) {
+ out += '?' + opt_queryData;
+ }
+
+ if (opt_fragment) {
+ out += '#' + opt_fragment;
+ }
+
+ return out;
+};
+
+
+/**
+ * A regular expression for breaking a URI into its component parts.
+ *
+ * {@link http://www.ietf.org/rfc/rfc3986.txt} says in Appendix B
+ * As the "first-match-wins" algorithm is identical to the "greedy"
+ * disambiguation method used by POSIX regular expressions, it is natural and
+ * commonplace to use a regular expression for parsing the potential five
+ * components of a URI reference.
+ *
+ * The following line is the regular expression for breaking-down a
+ * well-formed URI reference into its components.
+ *
+ * <pre>
+ * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+ * 12 3 4 5 6 7 8 9
+ * </pre>
+ *
+ * The numbers in the second line above are only to assist readability; they
+ * indicate the reference points for each subexpression (i.e., each paired
+ * parenthesis). We refer to the value matched for subexpression <n> as $<n>.
+ * For example, matching the above expression to
+ * <pre>
+ * http://www.ics.uci.edu/pub/ietf/uri/#Related
+ * </pre>
+ * results in the following subexpression matches:
+ * <pre>
+ * $1 = http:
+ * $2 = http
+ * $3 = //www.ics.uci.edu
+ * $4 = www.ics.uci.edu
+ * $5 = /pub/ietf/uri/
+ * $6 = <undefined>
+ * $7 = <undefined>
+ * $8 = #Related
+ * $9 = Related
+ * </pre>
+ * where <undefined> indicates that the component is not present, as is the
+ * case for the query component in the above example. Therefore, we can
+ * determine the value of the five components as
+ * <pre>
+ * scheme = $2
+ * authority = $4
+ * path = $5
+ * query = $7
+ * fragment = $9
+ * </pre>
+ *
+ * The regular expression has been modified slightly to expose the
+ * userInfo, domain, and port separately from the authority.
+ * The modified version yields
+ * <pre>
+ * $1 = http scheme
+ * $2 = <undefined> userInfo -\
+ * $3 = www.ics.uci.edu domain | authority
+ * $4 = <undefined> port -/
+ * $5 = /pub/ietf/uri/ path
+ * $6 = <undefined> query without ?
+ * $7 = Related fragment without #
+ * </pre>
+ * @type {!RegExp}
+ * @private
+ */
+goog.uri.utils.splitRe_ = new RegExp(
+ '^' +
+ '(?:' +
+ '([^:/?#.]+)' + // scheme - ignore special characters
+ // used by other URL parts such as :,
+ // ?, /, #, and .
+ ':)?' +
+ '(?://' +
+ '(?:([^/?#]*)@)?' + // userInfo
+ '([^/#?]*?)' + // domain
+ '(?::([0-9]+))?' + // port
+ '(?=[/#?]|$)' + // authority-terminating character
+ ')?' +
+ '([^?#]+)?' + // path
+ '(?:\\?([^#]*))?' + // query
+ '(?:#(.*))?' + // fragment
+ '$');
+
+
+/**
+ * The index of each URI component in the return value of goog.uri.utils.split.
+ * @enum {number}
+ */
+goog.uri.utils.ComponentIndex = {
+ SCHEME: 1,
+ USER_INFO: 2,
+ DOMAIN: 3,
+ PORT: 4,
+ PATH: 5,
+ QUERY_DATA: 6,
+ FRAGMENT: 7
+};
+
+
+/**
+ * Splits a URI into its component parts.
+ *
+ * Each component can be accessed via the component indices; for example:
+ * <pre>
+ * goog.uri.utils.split(someStr)[goog.uri.utils.CompontentIndex.QUERY_DATA];
+ * </pre>
+ *
+ * @param {string} uri The URI string to examine.
+ * @return {!Array<string|undefined>} Each component still URI-encoded.
+ * Each component that is present will contain the encoded value, whereas
+ * components that are not present will be undefined or empty, depending
+ * on the browser's regular expression implementation. Never null, since
+ * arbitrary strings may still look like path names.
+ */
+goog.uri.utils.split = function(uri) {
+ // See @return comment -- never null.
+ return /** @type {!Array<string|undefined>} */ (
+ uri.match(goog.uri.utils.splitRe_));
+};
+
+
+/**
+ * @param {?string} uri A possibly null string.
+ * @param {boolean=} opt_preserveReserved If true, percent-encoding of RFC-3986
+ * reserved characters will not be removed.
+ * @return {?string} The string URI-decoded, or null if uri is null.
+ * @private
+ */
+goog.uri.utils.decodeIfPossible_ = function(uri, opt_preserveReserved) {
+ if (!uri) {
+ return uri;
+ }
+
+ return opt_preserveReserved ? decodeURI(uri) : decodeURIComponent(uri);
+};
+
+
+/**
+ * Gets a URI component by index.
+ *
+ * It is preferred to use the getPathEncoded() variety of functions ahead,
+ * since they are more readable.
+ *
+ * @param {goog.uri.utils.ComponentIndex} componentIndex The component index.
+ * @param {string} uri The URI to examine.
+ * @return {?string} The still-encoded component, or null if the component
+ * is not present.
+ * @private
+ */
+goog.uri.utils.getComponentByIndex_ = function(componentIndex, uri) {
+ // Convert undefined, null, and empty string into null.
+ return goog.uri.utils.split(uri)[componentIndex] || null;
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The protocol or scheme, or null if none. Does not
+ * include trailing colons or slashes.
+ */
+goog.uri.utils.getScheme = function(uri) {
+ return goog.uri.utils.getComponentByIndex_(
+ goog.uri.utils.ComponentIndex.SCHEME, uri);
+};
+
+
+/**
+ * Gets the effective scheme for the URL. If the URL is relative then the
+ * scheme is derived from the page's location.
+ * @param {string} uri The URI to examine.
+ * @return {string} The protocol or scheme, always lower case.
+ */
+goog.uri.utils.getEffectiveScheme = function(uri) {
+ var scheme = goog.uri.utils.getScheme(uri);
+ if (!scheme && goog.global.self && goog.global.self.location) {
+ var protocol = goog.global.self.location.protocol;
+ scheme = protocol.substr(0, protocol.length - 1);
+ }
+ // NOTE: When called from a web worker in Firefox 3.5, location maybe null.
+ // All other browsers with web workers support self.location from the worker.
+ return scheme ? scheme.toLowerCase() : '';
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The user name still encoded, or null if none.
+ */
+goog.uri.utils.getUserInfoEncoded = function(uri) {
+ return goog.uri.utils.getComponentByIndex_(
+ goog.uri.utils.ComponentIndex.USER_INFO, uri);
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The decoded user info, or null if none.
+ */
+goog.uri.utils.getUserInfo = function(uri) {
+ return goog.uri.utils.decodeIfPossible_(
+ goog.uri.utils.getUserInfoEncoded(uri));
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The domain name still encoded, or null if none.
+ */
+goog.uri.utils.getDomainEncoded = function(uri) {
+ return goog.uri.utils.getComponentByIndex_(
+ goog.uri.utils.ComponentIndex.DOMAIN, uri);
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The decoded domain, or null if none.
+ */
+goog.uri.utils.getDomain = function(uri) {
+ return goog.uri.utils.decodeIfPossible_(
+ goog.uri.utils.getDomainEncoded(uri), true /* opt_preserveReserved */);
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?number} The port number, or null if none.
+ */
+goog.uri.utils.getPort = function(uri) {
+ // Coerce to a number. If the result of getComponentByIndex_ is null or
+ // non-numeric, the number coersion yields NaN. This will then return
+ // null for all non-numeric cases (though also zero, which isn't a relevant
+ // port number).
+ return Number(
+ goog.uri.utils.getComponentByIndex_(
+ goog.uri.utils.ComponentIndex.PORT, uri)) ||
+ null;
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The path still encoded, or null if none. Includes the
+ * leading slash, if any.
+ */
+goog.uri.utils.getPathEncoded = function(uri) {
+ return goog.uri.utils.getComponentByIndex_(
+ goog.uri.utils.ComponentIndex.PATH, uri);
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The decoded path, or null if none. Includes the leading
+ * slash, if any.
+ */
+goog.uri.utils.getPath = function(uri) {
+ return goog.uri.utils.decodeIfPossible_(
+ goog.uri.utils.getPathEncoded(uri), true /* opt_preserveReserved */);
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The query data still encoded, or null if none. Does not
+ * include the question mark itself.
+ */
+goog.uri.utils.getQueryData = function(uri) {
+ return goog.uri.utils.getComponentByIndex_(
+ goog.uri.utils.ComponentIndex.QUERY_DATA, uri);
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The fragment identifier, or null if none. Does not
+ * include the hash mark itself.
+ */
+goog.uri.utils.getFragmentEncoded = function(uri) {
+ // The hash mark may not appear in any other part of the URL.
+ var hashIndex = uri.indexOf('#');
+ return hashIndex < 0 ? null : uri.substr(hashIndex + 1);
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @param {?string} fragment The encoded fragment identifier, or null if none.
+ * Does not include the hash mark itself.
+ * @return {string} The URI with the fragment set.
+ */
+goog.uri.utils.setFragmentEncoded = function(uri, fragment) {
+ return goog.uri.utils.removeFragment(uri) + (fragment ? '#' + fragment : '');
+};
+
+
+/**
+ * @param {string} uri The URI to examine.
+ * @return {?string} The decoded fragment identifier, or null if none. Does
+ * not include the hash mark.
+ */
+goog.uri.utils.getFragment = function(uri) {
+ return goog.uri.utils.decodeIfPossible_(
+ goog.uri.utils.getFragmentEncoded(uri));
+};
+
+
+/**
+ * Extracts everything up to the port of the URI.
+ * @param {string} uri The URI string.
+ * @return {string} Everything up to and including the port.
+ */
+goog.uri.utils.getHost = function(uri) {
+ var pieces = goog.uri.utils.split(uri);
+ return goog.uri.utils.buildFromEncodedParts(
+ pieces[goog.uri.utils.ComponentIndex.SCHEME],
+ pieces[goog.uri.utils.ComponentIndex.USER_INFO],
+ pieces[goog.uri.utils.ComponentIndex.DOMAIN],
+ pieces[goog.uri.utils.ComponentIndex.PORT]);
+};
+
+
+/**
+ * Extracts the path of the URL and everything after.
+ * @param {string} uri The URI string.
+ * @return {string} The URI, starting at the path and including the query
+ * parameters and fragment identifier.
+ */
+goog.uri.utils.getPathAndAfter = function(uri) {
+ var pieces = goog.uri.utils.split(uri);
+ return goog.uri.utils.buildFromEncodedParts(
+ null, null, null, null, pieces[goog.uri.utils.ComponentIndex.PATH],
+ pieces[goog.uri.utils.ComponentIndex.QUERY_DATA],
+ pieces[goog.uri.utils.ComponentIndex.FRAGMENT]);
+};
+
+
+/**
+ * Gets the URI with the fragment identifier removed.
+ * @param {string} uri The URI to examine.
+ * @return {string} Everything preceding the hash mark.
+ */
+goog.uri.utils.removeFragment = function(uri) {
+ // The hash mark may not appear in any other part of the URL.
+ var hashIndex = uri.indexOf('#');
+ return hashIndex < 0 ? uri : uri.substr(0, hashIndex);
+};
+
+
+/**
+ * Ensures that two URI's have the exact same domain, scheme, and port.
+ *
+ * Unlike the version in goog.Uri, this checks protocol, and therefore is
+ * suitable for checking against the browser's same-origin policy.
+ *
+ * @param {string} uri1 The first URI.
+ * @param {string} uri2 The second URI.
+ * @return {boolean} Whether they have the same scheme, domain and port.
+ */
+goog.uri.utils.haveSameDomain = function(uri1, uri2) {
+ var pieces1 = goog.uri.utils.split(uri1);
+ var pieces2 = goog.uri.utils.split(uri2);
+ return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==
+ pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&
+ pieces1[goog.uri.utils.ComponentIndex.SCHEME] ==
+ pieces2[goog.uri.utils.ComponentIndex.SCHEME] &&
+ pieces1[goog.uri.utils.ComponentIndex.PORT] ==
+ pieces2[goog.uri.utils.ComponentIndex.PORT];
+};
+
+
+/**
+ * Asserts that there are no fragment or query identifiers, only in uncompiled
+ * mode.
+ * @param {string} uri The URI to examine.
+ * @private
+ */
+goog.uri.utils.assertNoFragmentsOrQueries_ = function(uri) {
+ // NOTE: would use goog.asserts here, but jscompiler doesn't know that
+ // indexOf has no side effects.
+ if (goog.DEBUG && (uri.indexOf('#') >= 0 || uri.indexOf('?') >= 0)) {
+ throw Error(
+ 'goog.uri.utils: Fragment or query identifiers are not ' +
+ 'supported: [' + uri + ']');
+ }
+};
+
+
+/**
+ * Supported query parameter values by the parameter serializing utilities.
+ *
+ * If a value is null or undefined, the key-value pair is skipped, as an easy
+ * way to omit parameters conditionally. Non-array parameters are converted
+ * to a string and URI encoded. Array values are expanded into multiple
+ * &key=value pairs, with each element stringized and URI-encoded.
+ *
+ * @typedef {*}
+ */
+goog.uri.utils.QueryValue;
+
+
+/**
+ * An array representing a set of query parameters with alternating keys
+ * and values.
+ *
+ * Keys are assumed to be URI encoded already and live at even indices. See
+ * goog.uri.utils.QueryValue for details on how parameter values are encoded.
+ *
+ * Example:
+ * <pre>
+ * var data = [
+ * // Simple param: ?name=BobBarker
+ * 'name', 'BobBarker',
+ * // Conditional param -- may be omitted entirely.
+ * 'specialDietaryNeeds', hasDietaryNeeds() ? getDietaryNeeds() : null,
+ * // Multi-valued param: &house=LosAngeles&house=NewYork&house=null
+ * 'house', ['LosAngeles', 'NewYork', null]
+ * ];
+ * </pre>
+ *
+ * @typedef {!Array<string|goog.uri.utils.QueryValue>}
+ */
+goog.uri.utils.QueryArray;
+
+
+/**
+ * Parses encoded query parameters and calls callback function for every
+ * parameter found in the string.
+ *
+ * Missing value of parameter (e.g. “…&key&…”) is treated as if the value was an
+ * empty string. Keys may be empty strings (e.g. “…&=value&…”) which also means
+ * that “…&=&…” and “…&&…” will result in an empty key and value.
+ *
+ * @param {string} encodedQuery Encoded query string excluding question mark at
+ * the beginning.
+ * @param {function(string, string)} callback Function called for every
+ * parameter found in query string. The first argument (name) will not be
+ * urldecoded (so the function is consistent with buildQueryData), but the
+ * second will. If the parameter has no value (i.e. “=” was not present)
+ * the second argument (value) will be an empty string.
+ */
+goog.uri.utils.parseQueryData = function(encodedQuery, callback) {
+ if (!encodedQuery) {
+ return;
+ }
+ var pairs = encodedQuery.split('&');
+ for (var i = 0; i < pairs.length; i++) {
+ var indexOfEquals = pairs[i].indexOf('=');
+ var name = null;
+ var value = null;
+ if (indexOfEquals >= 0) {
+ name = pairs[i].substring(0, indexOfEquals);
+ value = pairs[i].substring(indexOfEquals + 1);
+ } else {
+ name = pairs[i];
+ }
+ callback(name, value ? goog.string.urlDecode(value) : '');
+ }
+};
+
+
+/**
+ * Appends a URI and query data in a string buffer with special preconditions.
+ *
+ * Internal implementation utility, performing very few object allocations.
+ *
+ * @param {!Array<string|undefined>} buffer A string buffer. The first element
+ * must be the base URI, and may have a fragment identifier. If the array
+ * contains more than one element, the second element must be an ampersand,
+ * and may be overwritten, depending on the base URI. Undefined elements
+ * are treated as empty-string.
+ * @return {string} The concatenated URI and query data.
+ * @private
+ */
+goog.uri.utils.appendQueryData_ = function(buffer) {
+ if (buffer[1]) {
+ // At least one query parameter was added. We need to check the
+ // punctuation mark, which is currently an ampersand, and also make sure
+ // there aren't any interfering fragment identifiers.
+ var baseUri = /** @type {string} */ (buffer[0]);
+ var hashIndex = baseUri.indexOf('#');
+ if (hashIndex >= 0) {
+ // Move the fragment off the base part of the URI into the end.
+ buffer.push(baseUri.substr(hashIndex));
+ buffer[0] = baseUri = baseUri.substr(0, hashIndex);
+ }
+ var questionIndex = baseUri.indexOf('?');
+ if (questionIndex < 0) {
+ // No question mark, so we need a question mark instead of an ampersand.
+ buffer[1] = '?';
+ } else if (questionIndex == baseUri.length - 1) {
+ // Question mark is the very last character of the existing URI, so don't
+ // append an additional delimiter.
+ buffer[1] = undefined;
+ }
+ }
+
+ return buffer.join('');
+};
+
+
+/**
+ * Appends key=value pairs to an array, supporting multi-valued objects.
+ * @param {string} key The key prefix.
+ * @param {goog.uri.utils.QueryValue} value The value to serialize.
+ * @param {!Array<string>} pairs The array to which the 'key=value' strings
+ * should be appended.
+ * @private
+ */
+goog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) {
+ if (goog.isArray(value)) {
+ // Convince the compiler it's an array.
+ goog.asserts.assertArray(value);
+ for (var j = 0; j < value.length; j++) {
+ // Convert to string explicitly, to short circuit the null and array
+ // logic in this function -- this ensures that null and undefined get
+ // written as literal 'null' and 'undefined', and arrays don't get
+ // expanded out but instead encoded in the default way.
+ goog.uri.utils.appendKeyValuePairs_(key, String(value[j]), pairs);
+ }
+ } else if (value != null) {
+ // Skip a top-level null or undefined entirely.
+ pairs.push(
+ '&', key,
+ // Check for empty string. Zero gets encoded into the url as literal
+ // strings. For empty string, skip the equal sign, to be consistent
+ // with UriBuilder.java.
+ value === '' ? '' : '=', goog.string.urlEncode(value));
+ }
+};
+
+
+/**
+ * Builds a buffer of query data from a sequence of alternating keys and values.
+ *
+ * @param {!Array<string|undefined>} buffer A string buffer to append to. The
+ * first element appended will be an '&', and may be replaced by the caller.
+ * @param {!goog.uri.utils.QueryArray|!Arguments} keysAndValues An array with
+ * alternating keys and values -- see the typedef.
+ * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.
+ * @return {!Array<string|undefined>} The buffer argument.
+ * @private
+ */
+goog.uri.utils.buildQueryDataBuffer_ = function(
+ buffer, keysAndValues, opt_startIndex) {
+ goog.asserts.assert(
+ Math.max(keysAndValues.length - (opt_startIndex || 0), 0) % 2 == 0,
+ 'goog.uri.utils: Key/value lists must be even in length.');
+
+ for (var i = opt_startIndex || 0; i < keysAndValues.length; i += 2) {
+ goog.uri.utils.appendKeyValuePairs_(
+ keysAndValues[i], keysAndValues[i + 1], buffer);
+ }
+
+ return buffer;
+};
+
+
+/**
+ * Builds a query data string from a sequence of alternating keys and values.
+ * Currently generates "&key&" for empty args.
+ *
+ * @param {goog.uri.utils.QueryArray} keysAndValues Alternating keys and
+ * values. See the typedef.
+ * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.
+ * @return {string} The encoded query string, in the form 'a=1&b=2'.
+ */
+goog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) {
+ var buffer =
+ goog.uri.utils.buildQueryDataBuffer_([], keysAndValues, opt_startIndex);
+ buffer[0] = ''; // Remove the leading ampersand.
+ return buffer.join('');
+};
+
+
+/**
+ * Builds a buffer of query data from a map.
+ *
+ * @param {!Array<string|undefined>} buffer A string buffer to append to. The
+ * first element appended will be an '&', and may be replaced by the caller.
+ * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys
+ * are URI-encoded parameter keys, and the values conform to the contract
+ * specified in the goog.uri.utils.QueryValue typedef.
+ * @return {!Array<string|undefined>} The buffer argument.
+ * @private
+ */
+goog.uri.utils.buildQueryDataBufferFromMap_ = function(buffer, map) {
+ for (var key in map) {
+ goog.uri.utils.appendKeyValuePairs_(key, map[key], buffer);
+ }
+
+ return buffer;
+};
+
+
+/**
+ * Builds a query data string from a map.
+ * Currently generates "&key&" for empty args.
+ *
+ * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys
+ * are URI-encoded parameter keys, and the values are arbitrary types
+ * or arrays. Keys with a null value are dropped.
+ * @return {string} The encoded query string, in the form 'a=1&b=2'.
+ */
+goog.uri.utils.buildQueryDataFromMap = function(map) {
+ var buffer = goog.uri.utils.buildQueryDataBufferFromMap_([], map);
+ buffer[0] = '';
+ return buffer.join('');
+};
+
+
+/**
+ * Appends URI parameters to an existing URI.
+ *
+ * The variable arguments may contain alternating keys and values. Keys are
+ * assumed to be already URI encoded. The values should not be URI-encoded,
+ * and will instead be encoded by this function.
+ * <pre>
+ * appendParams('http://www.foo.com?existing=true',
+ * 'key1', 'value1',
+ * 'key2', 'value?willBeEncoded',
+ * 'key3', ['valueA', 'valueB', 'valueC'],
+ * 'key4', null);
+ * result: 'http://www.foo.com?existing=true&' +
+ * 'key1=value1&' +
+ * 'key2=value%3FwillBeEncoded&' +
+ * 'key3=valueA&key3=valueB&key3=valueC'
+ * </pre>
+ *
+ * A single call to this function will not exhibit quadratic behavior in IE,
+ * whereas multiple repeated calls may, although the effect is limited by
+ * fact that URL's generally can't exceed 2kb.
+ *
+ * @param {string} uri The original URI, which may already have query data.
+ * @param {...(goog.uri.utils.QueryArray|string|goog.uri.utils.QueryValue)}
+ * var_args
+ * An array or argument list conforming to goog.uri.utils.QueryArray.
+ * @return {string} The URI with all query parameters added.
+ */
+goog.uri.utils.appendParams = function(uri, var_args) {
+ return goog.uri.utils.appendQueryData_(
+ arguments.length == 2 ?
+ goog.uri.utils.buildQueryDataBuffer_([uri], arguments[1], 0) :
+ goog.uri.utils.buildQueryDataBuffer_([uri], arguments, 1));
+};
+
+
+/**
+ * Appends query parameters from a map.
+ *
+ * @param {string} uri The original URI, which may already have query data.
+ * @param {!Object<goog.uri.utils.QueryValue>} map An object where keys are
+ * URI-encoded parameter keys, and the values are arbitrary types or arrays.
+ * Keys with a null value are dropped.
+ * @return {string} The new parameters.
+ */
+goog.uri.utils.appendParamsFromMap = function(uri, map) {
+ return goog.uri.utils.appendQueryData_(
+ goog.uri.utils.buildQueryDataBufferFromMap_([uri], map));
+};
+
+
+/**
+ * Appends a single URI parameter.
+ *
+ * Repeated calls to this can exhibit quadratic behavior in IE6 due to the
+ * way string append works, though it should be limited given the 2kb limit.
+ *
+ * @param {string} uri The original URI, which may already have query data.
+ * @param {string} key The key, which must already be URI encoded.
+ * @param {*=} opt_value The value, which will be stringized and encoded
+ * (assumed not already to be encoded). If omitted, undefined, or null, the
+ * key will be added as a valueless parameter.
+ * @return {string} The URI with the query parameter added.
+ */
+goog.uri.utils.appendParam = function(uri, key, opt_value) {
+ var paramArr = [uri, '&', key];
+ if (goog.isDefAndNotNull(opt_value)) {
+ paramArr.push('=', goog.string.urlEncode(opt_value));
+ }
+ return goog.uri.utils.appendQueryData_(paramArr);
+};
+
+
+/**
+ * Finds the next instance of a query parameter with the specified name.
+ *
+ * Does not instantiate any objects.
+ *
+ * @param {string} uri The URI to search. May contain a fragment identifier
+ * if opt_hashIndex is specified.
+ * @param {number} startIndex The index to begin searching for the key at. A
+ * match may be found even if this is one character after the ampersand.
+ * @param {string} keyEncoded The URI-encoded key.
+ * @param {number} hashOrEndIndex Index to stop looking at. If a hash
+ * mark is present, it should be its index, otherwise it should be the
+ * length of the string.
+ * @return {number} The position of the first character in the key's name,
+ * immediately after either a question mark or a dot.
+ * @private
+ */
+goog.uri.utils.findParam_ = function(
+ uri, startIndex, keyEncoded, hashOrEndIndex) {
+ var index = startIndex;
+ var keyLength = keyEncoded.length;
+
+ // Search for the key itself and post-filter for surronuding punctuation,
+ // rather than expensively building a regexp.
+ while ((index = uri.indexOf(keyEncoded, index)) >= 0 &&
+ index < hashOrEndIndex) {
+ var precedingChar = uri.charCodeAt(index - 1);
+ // Ensure that the preceding character is '&' or '?'.
+ if (precedingChar == goog.uri.utils.CharCode_.AMPERSAND ||
+ precedingChar == goog.uri.utils.CharCode_.QUESTION) {
+ // Ensure the following character is '&', '=', '#', or NaN
+ // (end of string).
+ var followingChar = uri.charCodeAt(index + keyLength);
+ if (!followingChar || followingChar == goog.uri.utils.CharCode_.EQUAL ||
+ followingChar == goog.uri.utils.CharCode_.AMPERSAND ||
+ followingChar == goog.uri.utils.CharCode_.HASH) {
+ return index;
+ }
+ }
+ index += keyLength + 1;
+ }
+
+ return -1;
+};
+
+
+/**
+ * Regular expression for finding a hash mark or end of string.
+ * @type {RegExp}
+ * @private
+ */
+goog.uri.utils.hashOrEndRe_ = /#|$/;
+
+
+/**
+ * Determines if the URI contains a specific key.
+ *
+ * Performs no object instantiations.
+ *
+ * @param {string} uri The URI to process. May contain a fragment
+ * identifier.
+ * @param {string} keyEncoded The URI-encoded key. Case-sensitive.
+ * @return {boolean} Whether the key is present.
+ */
+goog.uri.utils.hasParam = function(uri, keyEncoded) {
+ return goog.uri.utils.findParam_(
+ uri, 0, keyEncoded, uri.search(goog.uri.utils.hashOrEndRe_)) >= 0;
+};
+
+
+/**
+ * Gets the first value of a query parameter.
+ * @param {string} uri The URI to process. May contain a fragment.
+ * @param {string} keyEncoded The URI-encoded key. Case-sensitive.
+ * @return {?string} The first value of the parameter (URI-decoded), or null
+ * if the parameter is not found.
+ */
+goog.uri.utils.getParamValue = function(uri, keyEncoded) {
+ var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
+ var foundIndex =
+ goog.uri.utils.findParam_(uri, 0, keyEncoded, hashOrEndIndex);
+
+ if (foundIndex < 0) {
+ return null;
+ } else {
+ var endPosition = uri.indexOf('&', foundIndex);
+ if (endPosition < 0 || endPosition > hashOrEndIndex) {
+ endPosition = hashOrEndIndex;
+ }
+ // Progress forth to the end of the "key=" or "key&" substring.
+ foundIndex += keyEncoded.length + 1;
+ // Use substr, because it (unlike substring) will return empty string
+ // if foundIndex > endPosition.
+ return goog.string.urlDecode(
+ uri.substr(foundIndex, endPosition - foundIndex));
+ }
+};
+
+
+/**
+ * Gets all values of a query parameter.
+ * @param {string} uri The URI to process. May contain a fragment.
+ * @param {string} keyEncoded The URI-encoded key. Case-sensitive.
+ * @return {!Array<string>} All URI-decoded values with the given key.
+ * If the key is not found, this will have length 0, but never be null.
+ */
+goog.uri.utils.getParamValues = function(uri, keyEncoded) {
+ var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
+ var position = 0;
+ var foundIndex;
+ var result = [];
+
+ while ((foundIndex = goog.uri.utils.findParam_(
+ uri, position, keyEncoded, hashOrEndIndex)) >= 0) {
+ // Find where this parameter ends, either the '&' or the end of the
+ // query parameters.
+ position = uri.indexOf('&', foundIndex);
+ if (position < 0 || position > hashOrEndIndex) {
+ position = hashOrEndIndex;
+ }
+
+ // Progress forth to the end of the "key=" or "key&" substring.
+ foundIndex += keyEncoded.length + 1;
+ // Use substr, because it (unlike substring) will return empty string
+ // if foundIndex > position.
+ result.push(
+ goog.string.urlDecode(uri.substr(foundIndex, position - foundIndex)));
+ }
+
+ return result;
+};
+
+
+/**
+ * Regexp to find trailing question marks and ampersands.
+ * @type {RegExp}
+ * @private
+ */
+goog.uri.utils.trailingQueryPunctuationRe_ = /[?&]($|#)/;
+
+
+/**
+ * Removes all instances of a query parameter.
+ * @param {string} uri The URI to process. Must not contain a fragment.
+ * @param {string} keyEncoded The URI-encoded key.
+ * @return {string} The URI with all instances of the parameter removed.
+ */
+goog.uri.utils.removeParam = function(uri, keyEncoded) {
+ var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
+ var position = 0;
+ var foundIndex;
+ var buffer = [];
+
+ // Look for a query parameter.
+ while ((foundIndex = goog.uri.utils.findParam_(
+ uri, position, keyEncoded, hashOrEndIndex)) >= 0) {
+ // Get the portion of the query string up to, but not including, the ?
+ // or & starting the parameter.
+ buffer.push(uri.substring(position, foundIndex));
+ // Progress to immediately after the '&'. If not found, go to the end.
+ // Avoid including the hash mark.
+ position = Math.min(
+ (uri.indexOf('&', foundIndex) + 1) || hashOrEndIndex, hashOrEndIndex);
+ }
+
+ // Append everything that is remaining.
+ buffer.push(uri.substr(position));
+
+ // Join the buffer, and remove trailing punctuation that remains.
+ return buffer.join('').replace(
+ goog.uri.utils.trailingQueryPunctuationRe_, '$1');
+};
+
+
+/**
+ * Replaces all existing definitions of a parameter with a single definition.
+ *
+ * Repeated calls to this can exhibit quadratic behavior due to the need to
+ * find existing instances and reconstruct the string, though it should be
+ * limited given the 2kb limit. Consider using appendParams to append multiple
+ * parameters in bulk.
+ *
+ * @param {string} uri The original URI, which may already have query data.
+ * @param {string} keyEncoded The key, which must already be URI encoded.
+ * @param {*} value The value, which will be stringized and encoded (assumed
+ * not already to be encoded).
+ * @return {string} The URI with the query parameter added.
+ */
+goog.uri.utils.setParam = function(uri, keyEncoded, value) {
+ return goog.uri.utils.appendParam(
+ goog.uri.utils.removeParam(uri, keyEncoded), keyEncoded, value);
+};
+
+
+/**
+ * Generates a URI path using a given URI and a path with checks to
+ * prevent consecutive "//". The baseUri passed in must not contain
+ * query or fragment identifiers. The path to append may not contain query or
+ * fragment identifiers.
+ *
+ * @param {string} baseUri URI to use as the base.
+ * @param {string} path Path to append.
+ * @return {string} Updated URI.
+ */
+goog.uri.utils.appendPath = function(baseUri, path) {
+ goog.uri.utils.assertNoFragmentsOrQueries_(baseUri);
+
+ // Remove any trailing '/'
+ if (goog.string.endsWith(baseUri, '/')) {
+ baseUri = baseUri.substr(0, baseUri.length - 1);
+ }
+ // Remove any leading '/'
+ if (goog.string.startsWith(path, '/')) {
+ path = path.substr(1);
+ }
+ return goog.string.buildString(baseUri, '/', path);
+};
+
+
+/**
+ * Replaces the path.
+ * @param {string} uri URI to use as the base.
+ * @param {string} path New path.
+ * @return {string} Updated URI.
+ */
+goog.uri.utils.setPath = function(uri, path) {
+ // Add any missing '/'.
+ if (!goog.string.startsWith(path, '/')) {
+ path = '/' + path;
+ }
+ var parts = goog.uri.utils.split(uri);
+ return goog.uri.utils.buildFromEncodedParts(
+ parts[goog.uri.utils.ComponentIndex.SCHEME],
+ parts[goog.uri.utils.ComponentIndex.USER_INFO],
+ parts[goog.uri.utils.ComponentIndex.DOMAIN],
+ parts[goog.uri.utils.ComponentIndex.PORT], path,
+ parts[goog.uri.utils.ComponentIndex.QUERY_DATA],
+ parts[goog.uri.utils.ComponentIndex.FRAGMENT]);
+};
+
+
+/**
+ * Standard supported query parameters.
+ * @enum {string}
+ */
+goog.uri.utils.StandardQueryParam = {
+
+ /** Unused parameter for unique-ifying. */
+ RANDOM: 'zx'
+};
+
+
+/**
+ * Sets the zx parameter of a URI to a random value.
+ * @param {string} uri Any URI.
+ * @return {string} That URI with the "zx" parameter added or replaced to
+ * contain a random string.
+ */
+goog.uri.utils.makeUnique = function(uri) {
+ return goog.uri.utils.setParam(
+ uri, goog.uri.utils.StandardQueryParam.RANDOM,
+ goog.string.getRandomString());
+};
+
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
* @fileoverview Class for parsing and formatting URIs.
*
* Use goog.Uri(string) to parse a URI string. Use goog.Uri.create(...) to
@@ -95800,6 +81364,7 @@ goog.provide('goog.Uri');
goog.provide('goog.Uri.QueryData');
goog.require('goog.array');
+goog.require('goog.asserts');
goog.require('goog.string');
goog.require('goog.structs');
goog.require('goog.structs.Map');
@@ -95897,8 +81462,8 @@ goog.Uri = function(opt_uri, opt_ignoreCase) {
// Parse in the uri string
var m;
if (opt_uri instanceof goog.Uri) {
- this.ignoreCase_ = goog.isDef(opt_ignoreCase) ?
- opt_ignoreCase : opt_uri.getIgnoreCase();
+ this.ignoreCase_ =
+ goog.isDef(opt_ignoreCase) ? opt_ignoreCase : opt_uri.getIgnoreCase();
this.setScheme(opt_uri.getScheme());
this.setUserInfo(opt_uri.getUserInfo());
this.setDomain(opt_uri.getDomain());
@@ -95959,8 +81524,10 @@ goog.Uri.prototype.toString = function() {
var scheme = this.getScheme();
if (scheme) {
- out.push(goog.Uri.encodeSpecialChars_(
- scheme, goog.Uri.reDisallowedInSchemeOrUserInfo_, true), ':');
+ out.push(
+ goog.Uri.encodeSpecialChars_(
+ scheme, goog.Uri.reDisallowedInSchemeOrUserInfo_, true),
+ ':');
}
var domain = this.getDomain();
@@ -95969,8 +81536,10 @@ goog.Uri.prototype.toString = function() {
var userInfo = this.getUserInfo();
if (userInfo) {
- out.push(goog.Uri.encodeSpecialChars_(
- userInfo, goog.Uri.reDisallowedInSchemeOrUserInfo_, true), '@');
+ out.push(
+ goog.Uri.encodeSpecialChars_(
+ userInfo, goog.Uri.reDisallowedInSchemeOrUserInfo_, true),
+ '@');
}
out.push(goog.Uri.removeDoubleEncoding_(goog.string.urlEncode(domain)));
@@ -95986,12 +81555,11 @@ goog.Uri.prototype.toString = function() {
if (this.hasDomain() && path.charAt(0) != '/') {
out.push('/');
}
- out.push(goog.Uri.encodeSpecialChars_(
- path,
- path.charAt(0) == '/' ?
- goog.Uri.reDisallowedInAbsolutePath_ :
- goog.Uri.reDisallowedInRelativePath_,
- true));
+ out.push(
+ goog.Uri.encodeSpecialChars_(
+ path, path.charAt(0) == '/' ? goog.Uri.reDisallowedInAbsolutePath_ :
+ goog.Uri.reDisallowedInRelativePath_,
+ true));
}
var query = this.getEncodedQuery();
@@ -96001,8 +81569,9 @@ goog.Uri.prototype.toString = function() {
var fragment = this.getFragment();
if (fragment) {
- out.push('#', goog.Uri.encodeSpecialChars_(
- fragment, goog.Uri.reDisallowedInFragment_));
+ out.push(
+ '#', goog.Uri.encodeSpecialChars_(
+ fragment, goog.Uri.reDisallowedInFragment_));
}
return out.join('');
};
@@ -96123,8 +81692,8 @@ goog.Uri.prototype.getScheme = function() {
*/
goog.Uri.prototype.setScheme = function(newScheme, opt_decode) {
this.enforceReadOnly();
- this.scheme_ = opt_decode ? goog.Uri.decodeOrEmpty_(newScheme, true) :
- newScheme;
+ this.scheme_ =
+ opt_decode ? goog.Uri.decodeOrEmpty_(newScheme, true) : newScheme;
// remove an : at the end of the scheme so somebody can pass in
// window.location.protocol
@@ -96161,8 +81730,8 @@ goog.Uri.prototype.getUserInfo = function() {
*/
goog.Uri.prototype.setUserInfo = function(newUserInfo, opt_decode) {
this.enforceReadOnly();
- this.userInfo_ = opt_decode ? goog.Uri.decodeOrEmpty_(newUserInfo) :
- newUserInfo;
+ this.userInfo_ =
+ opt_decode ? goog.Uri.decodeOrEmpty_(newUserInfo) : newUserInfo;
return this;
};
@@ -96193,8 +81762,8 @@ goog.Uri.prototype.getDomain = function() {
*/
goog.Uri.prototype.setDomain = function(newDomain, opt_decode) {
this.enforceReadOnly();
- this.domain_ = opt_decode ? goog.Uri.decodeOrEmpty_(newDomain, true) :
- newDomain;
+ this.domain_ =
+ opt_decode ? goog.Uri.decodeOrEmpty_(newDomain, true) : newDomain;
return this;
};
@@ -96301,8 +81870,8 @@ goog.Uri.prototype.setQueryData = function(queryData, opt_decode) {
if (!opt_decode) {
// QueryData accepts encoded query string, so encode it if
// opt_decode flag is not true.
- queryData = goog.Uri.encodeSpecialChars_(queryData,
- goog.Uri.reDisallowedInQuery_);
+ queryData = goog.Uri.encodeSpecialChars_(
+ queryData, goog.Uri.reDisallowedInQuery_);
}
this.queryData_ = new goog.Uri.QueryData(queryData, null, this.ignoreCase_);
}
@@ -96445,8 +82014,8 @@ goog.Uri.prototype.getFragment = function() {
*/
goog.Uri.prototype.setFragment = function(newFragment, opt_decode) {
this.enforceReadOnly();
- this.fragment_ = opt_decode ? goog.Uri.decodeOrEmpty_(newFragment) :
- newFragment;
+ this.fragment_ =
+ opt_decode ? goog.Uri.decodeOrEmpty_(newFragment) : newFragment;
return this;
};
@@ -96468,7 +82037,7 @@ goog.Uri.prototype.hasSameDomainAs = function(uri2) {
return ((!this.hasDomain() && !uri2.hasDomain()) ||
this.getDomain() == uri2.getDomain()) &&
((!this.hasPort() && !uri2.hasPort()) ||
- this.getPort() == uri2.getPort());
+ this.getPort() == uri2.getPort());
};
@@ -96571,8 +82140,8 @@ goog.Uri.prototype.getIgnoreCase = function() {
* @return {!goog.Uri} The new URI object.
*/
goog.Uri.parse = function(uri, opt_ignoreCase) {
- return uri instanceof goog.Uri ?
- uri.clone() : new goog.Uri(uri, opt_ignoreCase);
+ return uri instanceof goog.Uri ? uri.clone() :
+ new goog.Uri(uri, opt_ignoreCase);
};
@@ -96591,8 +82160,9 @@ goog.Uri.parse = function(uri, opt_ignoreCase) {
*
* @return {!goog.Uri} The new URI object.
*/
-goog.Uri.create = function(opt_scheme, opt_userInfo, opt_domain, opt_port,
- opt_path, opt_query, opt_fragment, opt_ignoreCase) {
+goog.Uri.create = function(
+ opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_query,
+ opt_fragment, opt_ignoreCase) {
var uri = new goog.Uri(null, opt_ignoreCase);
@@ -96641,8 +82211,8 @@ goog.Uri.removeDotSegments = function(path) {
if (path == '..' || path == '.') {
return '';
- } else if (!goog.string.contains(path, './') &&
- !goog.string.contains(path, '/.')) {
+ } else if (
+ !goog.string.contains(path, './') && !goog.string.contains(path, '/.')) {
// This optimization detects uris which do not contain dot-segments,
// and as a consequence do not require any processing.
return path;
@@ -96652,7 +82222,7 @@ goog.Uri.removeDotSegments = function(path) {
var segments = path.split('/');
var out = [];
- for (var pos = 0; pos < segments.length; ) {
+ for (var pos = 0; pos < segments.length;) {
var segment = segments[pos++];
if (segment == '.') {
@@ -96695,8 +82265,8 @@ goog.Uri.decodeOrEmpty_ = function(val, opt_preserveReserved) {
// decodeURI has the same output for '%2f' and '%252f'. We double encode %25
// so that we can distinguish between the 2 inputs. This is later undone by
// removeDoubleEncoding_.
- return opt_preserveReserved ?
- decodeURI(val.replace(/%25/g, '%2525')) : decodeURIComponent(val);
+ return opt_preserveReserved ? decodeURI(val.replace(/%25/g, '%2525')) :
+ decodeURIComponent(val);
};
@@ -96712,11 +82282,10 @@ goog.Uri.decodeOrEmpty_ = function(val, opt_preserveReserved) {
* @return {?string} null iff unescapedPart == null.
* @private
*/
-goog.Uri.encodeSpecialChars_ = function(unescapedPart, extra,
- opt_removeDoubleEncoding) {
+goog.Uri.encodeSpecialChars_ = function(
+ unescapedPart, extra, opt_removeDoubleEncoding) {
if (goog.isString(unescapedPart)) {
- var encoded = encodeURI(unescapedPart).
- replace(extra, goog.Uri.encodeChar_);
+ var encoded = encodeURI(unescapedPart).replace(extra, goog.Uri.encodeChar_);
if (opt_removeDoubleEncoding) {
// encodeURI double-escapes %XX sequences used to represent restricted
// characters in some URI components, remove the double escaping here.
@@ -96805,9 +82374,9 @@ goog.Uri.haveSameDomain = function(uri1String, uri2String) {
var pieces1 = goog.uri.utils.split(uri1String);
var pieces2 = goog.uri.utils.split(uri2String);
return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==
- pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&
- pieces1[goog.uri.utils.ComponentIndex.PORT] ==
- pieces2[goog.uri.utils.ComponentIndex.PORT];
+ pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&
+ pieces1[goog.uri.utils.ComponentIndex.PORT] ==
+ pieces2[goog.uri.utils.ComponentIndex.PORT];
};
@@ -96965,7 +82534,7 @@ goog.Uri.QueryData.prototype.add = function(key, value) {
this.keyMap_.set(key, (values = []));
}
values.push(value);
- this.count_++;
+ this.count_ = goog.asserts.assertNumber(this.count_) + 1;
return this;
};
@@ -96983,7 +82552,8 @@ goog.Uri.QueryData.prototype.remove = function(key) {
this.invalidateCache_();
// Decrement parameter count.
- this.count_ -= this.keyMap_.get(key).length;
+ this.count_ =
+ goog.asserts.assertNumber(this.count_) - this.keyMap_.get(key).length;
return this.keyMap_.remove(key);
}
return false;
@@ -97043,7 +82613,7 @@ goog.Uri.QueryData.prototype.containsValue = function(value) {
goog.Uri.QueryData.prototype.getKeys = function() {
this.ensureKeyMapInitialized_();
// We need to get the values to know how many keys to add.
- var vals = /** @type {!Array<*>} */ (this.keyMap_.getValues());
+ var vals = this.keyMap_.getValues();
var keys = this.keyMap_.getKeys();
var rv = [];
for (var i = 0; i < keys.length; i++) {
@@ -97099,10 +82669,11 @@ goog.Uri.QueryData.prototype.set = function(key, value) {
// ordering.
key = this.getKeyName_(key);
if (this.containsKey(key)) {
- this.count_ -= this.keyMap_.get(key).length;
+ this.count_ =
+ goog.asserts.assertNumber(this.count_) - this.keyMap_.get(key).length;
}
this.keyMap_.set(key, [value]);
- this.count_++;
+ this.count_ = goog.asserts.assertNumber(this.count_) + 1;
return this;
};
@@ -97138,7 +82709,7 @@ goog.Uri.QueryData.prototype.setValues = function(key, values) {
if (values.length > 0) {
this.invalidateCache_();
this.keyMap_.set(this.getKeyName_(key), goog.array.clone(values));
- this.count_ += values.length;
+ this.count_ = goog.asserts.assertNumber(this.count_) + values.length;
}
};
@@ -97207,12 +82778,11 @@ goog.Uri.QueryData.prototype.invalidateCache_ = function() {
*/
goog.Uri.QueryData.prototype.filterKeys = function(keys) {
this.ensureKeyMapInitialized_();
- this.keyMap_.forEach(
- function(value, key) {
- if (!goog.array.contains(keys, key)) {
- this.remove(key);
- }
- }, this);
+ this.keyMap_.forEach(function(value, key) {
+ if (!goog.array.contains(keys, key)) {
+ this.remove(key);
+ }
+ }, this);
return this;
};
@@ -97259,14 +82829,13 @@ goog.Uri.QueryData.prototype.setIgnoreCase = function(ignoreCase) {
if (resetKeys) {
this.ensureKeyMapInitialized_();
this.invalidateCache_();
- this.keyMap_.forEach(
- function(value, key) {
- var lowerCase = key.toLowerCase();
- if (key != lowerCase) {
- this.remove(key);
- this.setValues(lowerCase, value);
- }
- }, this);
+ this.keyMap_.forEach(function(value, key) {
+ var lowerCase = key.toLowerCase();
+ if (key != lowerCase) {
+ this.remove(key);
+ this.setValues(lowerCase, value);
+ }
+ }, this);
}
this.ignoreCase_ = ignoreCase;
};
@@ -97282,11 +82851,8 @@ goog.Uri.QueryData.prototype.setIgnoreCase = function(ignoreCase) {
goog.Uri.QueryData.prototype.extend = function(var_args) {
for (var i = 0; i < arguments.length; i++) {
var data = arguments[i];
- goog.structs.forEach(data,
- /** @this {goog.Uri.QueryData} */
- function(value, key) {
- this.add(key, value);
- }, this);
+ goog.structs.forEach(
+ data, function(value, key) { this.add(key, value); }, this);
}
};
@@ -97296,7 +82862,6 @@ goog.provide('ol.style.Text');
goog.require('ol.style.Fill');
-
/**
* @classdesc
* Set text style for vector features.
@@ -97593,20 +83158,17 @@ ol.style.Text.prototype.setTextBaseline = function(textBaseline) {
// FIXME http://earth.google.com/kml/1.0 namespace?
// FIXME why does node.getAttribute return an unknown type?
-// FIXME text
// FIXME serialize arbitrary feature properties
// FIXME don't parse style if extractStyles is false
goog.provide('ol.format.KML');
goog.require('goog.Uri');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
goog.require('goog.object');
goog.require('ol');
goog.require('ol.Feature');
-goog.require('ol.FeatureStyleFunction');
goog.require('ol.array');
goog.require('ol.color');
goog.require('ol.format.Feature');
@@ -97624,6 +83186,7 @@ goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
goog.require('ol.math');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.style.Fill');
goog.require('ol.style.Icon');
@@ -97637,21 +83200,6 @@ goog.require('ol.xml');
/**
- * @typedef {{x: number, xunits: (ol.style.IconAnchorUnits|undefined),
- * y: number, yunits: (ol.style.IconAnchorUnits|undefined)}}
- */
-ol.format.KMLVec2_;
-
-
-/**
- * @typedef {{flatCoordinates: Array.<number>,
- * whens: Array.<number>}}
- */
-ol.format.KMLGxTrackObject_;
-
-
-
-/**
* @classdesc
* Feature format for reading and writing data in the KML format.
*
@@ -97912,7 +83460,6 @@ ol.format.KML.ICON_ANCHOR_UNITS_MAP_ = {
* @private
*/
ol.format.KML.createNameStyleFunction_ = function(foundStyle, name) {
- /** @type {?ol.style.Text} */
var textStyle = null;
var textOffset = [0, 0];
var textAlign = 'start';
@@ -97926,7 +83473,7 @@ ol.format.KML.createNameStyleFunction_ = function(foundStyle, name) {
textAlign = 'left';
}
}
- if (!goog.object.isEmpty(foundStyle.getText())) {
+ if (!ol.object.isEmpty(foundStyle.getText())) {
textStyle = /** @type {ol.style.Text} */
(goog.object.clone(foundStyle.getText()));
textStyle.setText(name);
@@ -97972,7 +83519,6 @@ ol.format.KML.createFeatureStyleFunction_ = function(style, styleUrl,
var drawName = showPointNames;
/** @type {ol.style.Style|undefined} */
var nameStyle;
- /** @type {string} */
var name = '';
if (drawName) {
if (this.getGeometry()) {
@@ -97982,7 +83528,7 @@ ol.format.KML.createFeatureStyleFunction_ = function(style, styleUrl,
}
if (drawName) {
- name = /** @type {string} */ (this.getProperties()['name']);
+ name = /** @type {string} */ (this.get('name'));
drawName = drawName && name;
}
@@ -98023,9 +83569,9 @@ ol.format.KML.createFeatureStyleFunction_ = function(style, styleUrl,
* @private
*/
ol.format.KML.findStyle_ = function(styleValue, defaultStyle, sharedStyles) {
- if (goog.isArray(styleValue)) {
+ if (Array.isArray(styleValue)) {
return styleValue;
- } else if (goog.isString(styleValue)) {
+ } else if (typeof styleValue === 'string') {
// KML files in the wild occasionally forget the leading `#` on styleUrls
// defined in the same document. Add a leading `#` if it enables to find
// a style.
@@ -98126,7 +83672,7 @@ ol.format.KML.readURI_ = function(node) {
/**
* @param {Node} node Node.
* @private
- * @return {ol.format.KMLVec2_} Vec2.
+ * @return {ol.KMLVec2_} Vec2.
*/
ol.format.KML.readVec2_ = function(node) {
var xunits = node.getAttribute('xunits');
@@ -98162,8 +83708,7 @@ ol.format.KML.readScale_ = function(node) {
* @return {Array.<ol.style.Style>|string|undefined} StyleMap.
*/
ol.format.KML.readStyleMapValue_ = function(node, objectStack) {
- return ol.xml.pushParseAndPop(
- /** @type {Array.<ol.style.Style>|string|undefined} */ (undefined),
+ return ol.xml.pushParseAndPop(undefined,
ol.format.KML.STYLE_MAP_PARSERS_, node, objectStack);
};
@@ -98202,7 +83747,7 @@ ol.format.KML.IconStyleParser_ = function(node, objectStack) {
src = ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_;
}
var anchor, anchorXUnits, anchorYUnits;
- var hotSpot = /** @type {ol.format.KMLVec2_|undefined} */
+ var hotSpot = /** @type {ol.KMLVec2_|undefined} */
(object['hotSpot']);
if (hotSpot) {
anchor = [hotSpot.x, hotSpot.y];
@@ -98379,8 +83924,8 @@ ol.format.KML.readFlatLinearRing_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'LinearRing',
'localName should be LinearRing');
- return /** @type {Array.<number>} */ (ol.xml.pushParseAndPop(
- null, ol.format.KML.FLAT_LINEAR_RING_PARSERS_, node, objectStack));
+ return ol.xml.pushParseAndPop(null,
+ ol.format.KML.FLAT_LINEAR_RING_PARSERS_, node, objectStack);
};
@@ -98396,7 +83941,7 @@ ol.format.KML.gxCoordParser_ = function(node, objectStack) {
ol.format.KML.GX_NAMESPACE_URIS_, node.namespaceURI),
'namespaceURI of the node should be known to the KML parser');
goog.asserts.assert(node.localName == 'coord', 'localName should be coord');
- var gxTrackObject = /** @type {ol.format.KMLGxTrackObject_} */
+ var gxTrackObject = /** @type {ol.KMLGxTrackObject_} */
(objectStack[objectStack.length - 1]);
goog.asserts.assert(goog.isObject(gxTrackObject),
'gxTrackObject should be an Object');
@@ -98430,8 +83975,7 @@ ol.format.KML.readGxMultiTrack_ = function(node, objectStack) {
'namespaceURI of the node should be known to the KML parser');
goog.asserts.assert(node.localName == 'MultiTrack',
'localName should be MultiTrack');
- var lineStrings = ol.xml.pushParseAndPop(
- /** @type {Array.<ol.geom.LineString>} */ ([]),
+ var lineStrings = ol.xml.pushParseAndPop([],
ol.format.KML.GX_MULTITRACK_GEOMETRY_PARSERS_, node, objectStack);
if (!lineStrings) {
return undefined;
@@ -98456,7 +84000,7 @@ ol.format.KML.readGxTrack_ = function(node, objectStack) {
'namespaceURI of the node should be known to the KML parser');
goog.asserts.assert(node.localName == 'Track', 'localName should be Track');
var gxTrackObject = ol.xml.pushParseAndPop(
- /** @type {ol.format.KMLGxTrackObject_} */ ({
+ /** @type {ol.KMLGxTrackObject_} */ ({
flatCoordinates: [],
whens: []
}), ol.format.KML.GX_TRACK_PARSERS_, node, objectStack);
@@ -98508,8 +84052,8 @@ ol.format.KML.readIcon_ = function(node, objectStack) {
ol.format.KML.readFlatCoordinatesFromNode_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
- return /** @type {Array.<number>} */ (ol.xml.pushParseAndPop(null,
- ol.format.KML.GEOMETRY_FLAT_COORDINATES_PARSERS_, node, objectStack));
+ return ol.xml.pushParseAndPop(null,
+ ol.format.KML.GEOMETRY_FLAT_COORDINATES_PARSERS_, node, objectStack);
};
@@ -98524,7 +84068,7 @@ ol.format.KML.readLineString_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'LineString',
'localName should be LineString');
- var properties = ol.xml.pushParseAndPop(/** @type {Object<string,*>} */ ({}),
+ var properties = ol.xml.pushParseAndPop({},
ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node,
objectStack);
var flatCoordinates =
@@ -98551,7 +84095,7 @@ ol.format.KML.readLinearRing_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'LinearRing',
'localName should be LinearRing');
- var properties = ol.xml.pushParseAndPop(/** @type {Object<string,*>} */ ({}),
+ var properties = ol.xml.pushParseAndPop({},
ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node,
objectStack);
var flatCoordinates =
@@ -98579,8 +84123,7 @@ ol.format.KML.readMultiGeometry_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'MultiGeometry',
'localName should be MultiGeometry');
- var geometries = ol.xml.pushParseAndPop(
- /** @type {Array.<ol.geom.Geometry>} */ ([]),
+ var geometries = ol.xml.pushParseAndPop([],
ol.format.KML.MULTI_GEOMETRY_PARSERS_, node, objectStack);
if (!geometries) {
return null;
@@ -98599,9 +84142,7 @@ ol.format.KML.readMultiGeometry_ = function(node, objectStack) {
}
}
if (homogeneous) {
- /** @type {ol.geom.GeometryLayout} */
var layout;
- /** @type {Array.<number>} */
var flatCoordinates;
if (type == ol.geom.GeometryType.POINT) {
var point = geometries[0];
@@ -98615,7 +84156,7 @@ ol.format.KML.readMultiGeometry_ = function(node, objectStack) {
'geometry should be an ol.geom.Point');
goog.asserts.assert(geometry.getLayout() == layout,
'geometry layout should be consistent');
- goog.array.extend(flatCoordinates, geometry.getFlatCoordinates());
+ ol.array.extend(flatCoordinates, geometry.getFlatCoordinates());
}
var multiPoint = new ol.geom.MultiPoint(null);
multiPoint.setFlatCoordinates(layout, flatCoordinates);
@@ -98653,7 +84194,7 @@ ol.format.KML.readPoint_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'Point', 'localName should be Point');
- var properties = ol.xml.pushParseAndPop(/** @type {Object<string,*>} */ ({}),
+ var properties = ol.xml.pushParseAndPop({},
ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node,
objectStack);
var flatCoordinates =
@@ -98685,8 +84226,7 @@ ol.format.KML.readPolygon_ = function(node, objectStack) {
var properties = ol.xml.pushParseAndPop(/** @type {Object<string,*>} */ ({}),
ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node,
objectStack);
- var flatLinearRings = ol.xml.pushParseAndPop(
- /** @type {Array.<Array.<number>>} */ ([null]),
+ var flatLinearRings = ol.xml.pushParseAndPop([null],
ol.format.KML.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack);
if (flatLinearRings && flatLinearRings[0]) {
var polygon = new ol.geom.Polygon(null);
@@ -98694,7 +84234,7 @@ ol.format.KML.readPolygon_ = function(node, objectStack) {
var ends = [flatCoordinates.length];
var i, ii;
for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
- goog.array.extend(flatCoordinates, flatLinearRings[i]);
+ ol.array.extend(flatCoordinates, flatLinearRings[i]);
ends.push(flatCoordinates.length);
}
polygon.setFlatCoordinates(
@@ -98757,8 +84297,8 @@ ol.format.KML.readStyle_ = function(node, objectStack) {
* Reads an array of geometries and creates arrays for common geometry
* properties. Then sets them to the multi geometry.
* @param {ol.geom.MultiPoint|ol.geom.MultiLineString|ol.geom.MultiPolygon}
- * multiGeometry
- * @param {Array.<ol.geom.Geometry>} geometries
+ * multiGeometry A multi-geometry.
+ * @param {Array.<ol.geom.Geometry>} geometries List of geometries.
* @private
*/
ol.format.KML.setCommonGeometryProperties_ = function(multiGeometry,
@@ -98870,9 +84410,9 @@ ol.format.KML.PlacemarkStyleMapParser_ = function(node, objectStack) {
var placemarkObject = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(placemarkObject),
'placemarkObject should be an Object');
- if (goog.isArray(styleMapValue)) {
+ if (Array.isArray(styleMapValue)) {
placemarkObject['Style'] = styleMapValue;
- } else if (goog.isString(styleMapValue)) {
+ } else if (typeof styleMapValue === 'string') {
placemarkObject['styleUrl'] = styleMapValue;
} else {
goog.asserts.fail('styleMapValue has an unknown type');
@@ -98924,13 +84464,13 @@ ol.format.KML.innerBoundaryIsParser_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'innerBoundaryIs',
'localName should be innerBoundaryIs');
- var flatLinearRing = ol.xml.pushParseAndPop(
- /** @type {Array.<number>|undefined} */ (undefined),
+ /** @type {Array.<number>|undefined} */
+ var flatLinearRing = ol.xml.pushParseAndPop(undefined,
ol.format.KML.INNER_BOUNDARY_IS_PARSERS_, node, objectStack);
if (flatLinearRing) {
var flatLinearRings = /** @type {Array.<Array.<number>>} */
(objectStack[objectStack.length - 1]);
- goog.asserts.assert(goog.isArray(flatLinearRings),
+ goog.asserts.assert(Array.isArray(flatLinearRings),
'flatLinearRings should be an array');
goog.asserts.assert(flatLinearRings.length > 0,
'flatLinearRings array should not be empty');
@@ -98949,13 +84489,13 @@ ol.format.KML.outerBoundaryIsParser_ = function(node, objectStack) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'outerBoundaryIs',
'localName should be outerBoundaryIs');
- var flatLinearRing = ol.xml.pushParseAndPop(
- /** @type {Array.<number>|undefined} */ (undefined),
+ /** @type {Array.<number>|undefined} */
+ var flatLinearRing = ol.xml.pushParseAndPop(undefined,
ol.format.KML.OUTER_BOUNDARY_IS_PARSERS_, node, objectStack);
if (flatLinearRing) {
var flatLinearRings = /** @type {Array.<Array.<number>>} */
(objectStack[objectStack.length - 1]);
- goog.asserts.assert(goog.isArray(flatLinearRings),
+ goog.asserts.assert(Array.isArray(flatLinearRings),
'flatLinearRings should be an array');
goog.asserts.assert(flatLinearRings.length > 0,
'flatLinearRings array should not be empty');
@@ -98986,7 +84526,7 @@ ol.format.KML.whenParser_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'when', 'localName should be when');
- var gxTrackObject = /** @type {ol.format.KMLGxTrackObject_} */
+ var gxTrackObject = /** @type {ol.KMLGxTrackObject_} */
(objectStack[objectStack.length - 1]);
goog.asserts.assert(goog.isObject(gxTrackObject),
'gxTrackObject should be an Object');
@@ -99019,7 +84559,7 @@ ol.format.KML.whenParser_ = function(node, objectStack) {
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.DATA_PARSERS_ = ol.xml.makeStructureNS(
@@ -99030,7 +84570,7 @@ ol.format.KML.DATA_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.EXTENDED_DATA_PARSERS_ = ol.xml.makeStructureNS(
@@ -99042,7 +84582,7 @@ ol.format.KML.EXTENDED_DATA_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_ = ol.xml.makeStructureNS(
@@ -99054,7 +84594,7 @@ ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.FLAT_LINEAR_RING_PARSERS_ = ol.xml.makeStructureNS(
@@ -99065,7 +84605,7 @@ ol.format.KML.FLAT_LINEAR_RING_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.FLAT_LINEAR_RINGS_PARSERS_ = ol.xml.makeStructureNS(
@@ -99077,7 +84617,7 @@ ol.format.KML.FLAT_LINEAR_RINGS_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.GX_TRACK_PARSERS_ = ol.xml.makeStructureNS(
@@ -99091,7 +84631,7 @@ ol.format.KML.GX_TRACK_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.GEOMETRY_FLAT_COORDINATES_PARSERS_ = ol.xml.makeStructureNS(
@@ -99102,7 +84642,7 @@ ol.format.KML.GEOMETRY_FLAT_COORDINATES_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.ICON_PARSERS_ = ol.xml.makeStructureNS(
@@ -99119,7 +84659,7 @@ ol.format.KML.ICON_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.ICON_STYLE_PARSERS_ = ol.xml.makeStructureNS(
@@ -99133,7 +84673,7 @@ ol.format.KML.ICON_STYLE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.INNER_BOUNDARY_IS_PARSERS_ = ol.xml.makeStructureNS(
@@ -99144,7 +84684,7 @@ ol.format.KML.INNER_BOUNDARY_IS_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.LABEL_STYLE_PARSERS_ = ol.xml.makeStructureNS(
@@ -99156,7 +84696,7 @@ ol.format.KML.LABEL_STYLE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.LINE_STYLE_PARSERS_ = ol.xml.makeStructureNS(
@@ -99168,7 +84708,7 @@ ol.format.KML.LINE_STYLE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.MULTI_GEOMETRY_PARSERS_ = ol.xml.makeStructureNS(
@@ -99183,7 +84723,7 @@ ol.format.KML.MULTI_GEOMETRY_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.GX_MULTITRACK_GEOMETRY_PARSERS_ = ol.xml.makeStructureNS(
@@ -99194,7 +84734,7 @@ ol.format.KML.GX_MULTITRACK_GEOMETRY_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.NETWORK_LINK_PARSERS_ = ol.xml.makeStructureNS(
@@ -99212,7 +84752,7 @@ ol.format.KML.NETWORK_LINK_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.LINK_PARSERS_ = ol.xml.makeStructureNS(
@@ -99223,7 +84763,7 @@ ol.format.KML.LINK_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.OUTER_BOUNDARY_IS_PARSERS_ = ol.xml.makeStructureNS(
@@ -99234,7 +84774,7 @@ ol.format.KML.OUTER_BOUNDARY_IS_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.PAIR_PARSERS_ = ol.xml.makeStructureNS(
@@ -99247,7 +84787,7 @@ ol.format.KML.PAIR_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.PLACEMARK_PARSERS_ = ol.xml.makeStructureNS(
@@ -99284,7 +84824,7 @@ ol.format.KML.PLACEMARK_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.POLY_STYLE_PARSERS_ = ol.xml.makeStructureNS(
@@ -99297,7 +84837,7 @@ ol.format.KML.POLY_STYLE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.SCHEMA_DATA_PARSERS_ = ol.xml.makeStructureNS(
@@ -99308,7 +84848,7 @@ ol.format.KML.SCHEMA_DATA_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.STYLE_PARSERS_ = ol.xml.makeStructureNS(
@@ -99322,7 +84862,7 @@ ol.format.KML.STYLE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.KML.STYLE_MAP_PARSERS_ = ol.xml.makeStructureNS(
@@ -99348,7 +84888,7 @@ ol.format.KML.prototype.getExtensions = function() {
ol.format.KML.prototype.readDocumentOrFolder_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
- var localName = ol.xml.getLocalName(node);
+ var localName = node.localName;
goog.asserts.assert(localName == 'Document' || localName == 'Folder',
'localName should be Document or Folder');
// FIXME use scope somehow
@@ -99357,11 +84897,11 @@ ol.format.KML.prototype.readDocumentOrFolder_ = function(node, objectStack) {
'Document': ol.xml.makeArrayExtender(this.readDocumentOrFolder_, this),
'Folder': ol.xml.makeArrayExtender(this.readDocumentOrFolder_, this),
'Placemark': ol.xml.makeArrayPusher(this.readPlacemark_, this),
- 'Style': goog.bind(this.readSharedStyle_, this),
- 'StyleMap': goog.bind(this.readSharedStyleMap_, this)
+ 'Style': this.readSharedStyle_.bind(this),
+ 'StyleMap': this.readSharedStyleMap_.bind(this)
});
- var features = ol.xml.pushParseAndPop(/** @type {Array.<ol.Feature>} */ ([]),
- parsersNS, node, objectStack, this);
+ /** @type {Array.<ol.Feature>} */
+ var features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack, this);
if (features) {
return features;
} else {
@@ -99472,7 +85012,9 @@ ol.format.KML.prototype.readSharedStyleMap_ = function(node, objectStack) {
/**
- * Read the first feature from a KML source.
+ * Read the first feature from a KML source. MultiGeometries are converted into
+ * GeometryCollections if they are a mix of geometry types, and into MultiPoint/
+ * MultiLineString/MultiPolygon if they are all of the same type.
*
* @function
* @param {Document|Node|Object|string} source Source.
@@ -99505,7 +85047,9 @@ ol.format.KML.prototype.readFeatureFromNode = function(node, opt_options) {
/**
- * Read all features from a KML source.
+ * Read all features from a KML source. MultiGeometries are converted into
+ * GeometryCollections if they are a mix of geometry types, and into MultiPoint/
+ * MultiLineString/MultiPolygon if they are all of the same type.
*
* @function
* @param {Document|Node|Object|string} source Source.
@@ -99526,7 +85070,7 @@ ol.format.KML.prototype.readFeaturesFromNode = function(node, opt_options) {
return [];
}
var features;
- var localName = ol.xml.getLocalName(node);
+ var localName = node.localName;
if (localName == 'Document' || localName == 'Folder') {
features = this.readDocumentOrFolder_(
node, [this.getReadOptions(node, opt_options)]);
@@ -99549,7 +85093,7 @@ ol.format.KML.prototype.readFeaturesFromNode = function(node, opt_options) {
for (n = node.firstElementChild; n; n = n.nextElementSibling) {
var fs = this.readFeaturesFromNode(n, opt_options);
if (fs) {
- goog.array.extend(features, fs);
+ ol.array.extend(features, fs);
}
}
return features;
@@ -99571,7 +85115,7 @@ ol.format.KML.prototype.readName = function(source) {
return this.readNameFromDocument(/** @type {Document} */ (source));
} else if (ol.xml.isNode(source)) {
return this.readNameFromNode(/** @type {Node} */ (source));
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
return this.readNameFromDocument(doc);
} else {
@@ -99612,7 +85156,7 @@ ol.format.KML.prototype.readNameFromNode = function(node) {
}
}
for (n = node.firstElementChild; n; n = n.nextElementSibling) {
- var localName = ol.xml.getLocalName(n);
+ var localName = n.localName;
if (ol.array.includes(ol.format.KML.NAMESPACE_URIS_, n.namespaceURI) &&
(localName == 'Document' ||
localName == 'Folder' ||
@@ -99638,14 +85182,14 @@ ol.format.KML.prototype.readNameFromNode = function(node) {
ol.format.KML.prototype.readNetworkLinks = function(source) {
var networkLinks = [];
if (ol.xml.isDocument(source)) {
- goog.array.extend(networkLinks, this.readNetworkLinksFromDocument(
+ ol.array.extend(networkLinks, this.readNetworkLinksFromDocument(
/** @type {Document} */ (source)));
} else if (ol.xml.isNode(source)) {
- goog.array.extend(networkLinks, this.readNetworkLinksFromNode(
+ ol.array.extend(networkLinks, this.readNetworkLinksFromNode(
/** @type {Node} */ (source)));
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
- goog.array.extend(networkLinks, this.readNetworkLinksFromDocument(doc));
+ ol.array.extend(networkLinks, this.readNetworkLinksFromDocument(doc));
} else {
goog.asserts.fail('unknown type for source');
}
@@ -99661,7 +85205,7 @@ ol.format.KML.prototype.readNetworkLinksFromDocument = function(doc) {
var n, networkLinks = [];
for (n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
- goog.array.extend(networkLinks, this.readNetworkLinksFromNode(n));
+ ol.array.extend(networkLinks, this.readNetworkLinksFromNode(n));
}
}
return networkLinks;
@@ -99683,12 +85227,12 @@ ol.format.KML.prototype.readNetworkLinksFromNode = function(node) {
}
}
for (n = node.firstElementChild; n; n = n.nextElementSibling) {
- var localName = ol.xml.getLocalName(n);
+ var localName = n.localName;
if (ol.array.includes(ol.format.KML.NAMESPACE_URIS_, n.namespaceURI) &&
(localName == 'Document' ||
localName == 'Folder' ||
localName == 'kml')) {
- goog.array.extend(networkLinks, this.readNetworkLinksFromNode(n));
+ ol.array.extend(networkLinks, this.readNetworkLinksFromNode(n));
}
}
return networkLinks;
@@ -99730,8 +85274,7 @@ ol.format.KML.writeColorTextNode_ = function(node, color) {
* @param {Array.<*>} objectStack Object stack.
* @private
*/
-ol.format.KML.writeCoordinatesTextNode_ =
- function(node, coordinates, objectStack) {
+ol.format.KML.writeCoordinatesTextNode_ = function(node, coordinates, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
@@ -99776,7 +85319,7 @@ ol.format.KML.writeCoordinatesTextNode_ =
* @private
*/
ol.format.KML.writeDocument_ = function(node, features, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
ol.xml.pushSerializeAndPop(context, ol.format.KML.DOCUMENT_SERIALIZERS_,
ol.format.KML.DOCUMENT_NODE_FACTORY_, features, objectStack, undefined,
this);
@@ -99790,7 +85333,7 @@ ol.format.KML.writeDocument_ = function(node, features, objectStack) {
* @private
*/
ol.format.KML.writeIcon_ = function(node, icon, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
var parentNode = objectStack[objectStack.length - 1].node;
var orderedKeys = ol.format.KML.ICON_SEQUENCE_[parentNode.namespaceURI];
var values = ol.xml.makeSequence(icon, orderedKeys);
@@ -99812,7 +85355,7 @@ ol.format.KML.writeIcon_ = function(node, icon, objectStack) {
* @private
*/
ol.format.KML.writeIconStyle_ = function(node, style, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
var properties = {};
var src = style.getSrc();
var size = style.getSize();
@@ -99833,7 +85376,7 @@ ol.format.KML.writeIconStyle_ = function(node, style, objectStack) {
}
if (anchor && anchor[0] !== 0 && anchor[1] !== size[1]) {
- var /** @type {ol.format.KMLVec2_} */ hotSpot = {
+ var /** @type {ol.KMLVec2_} */ hotSpot = {
x: anchor[0],
xunits: ol.style.IconAnchorUnits.PIXELS,
y: size[1] - anchor[1],
@@ -99870,7 +85413,7 @@ ol.format.KML.writeIconStyle_ = function(node, style, objectStack) {
* @private
*/
ol.format.KML.writeLabelStyle_ = function(node, style, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
var properties = {};
var fill = style.getFill();
if (fill) {
@@ -99896,7 +85439,7 @@ ol.format.KML.writeLabelStyle_ = function(node, style, objectStack) {
* @private
*/
ol.format.KML.writeLineStyle_ = function(node, style, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
var properties = {
'color': style.getColor(),
'width': style.getWidth()
@@ -99915,22 +85458,25 @@ ol.format.KML.writeLineStyle_ = function(node, style, objectStack) {
* @param {Array.<*>} objectStack Object stack.
* @private
*/
-ol.format.KML.writeMultiGeometry_ =
- function(node, geometry, objectStack) {
+ol.format.KML.writeMultiGeometry_ = function(node, geometry, objectStack) {
goog.asserts.assert(
+ (geometry instanceof ol.geom.GeometryCollection) ||
(geometry instanceof ol.geom.MultiPoint) ||
(geometry instanceof ol.geom.MultiLineString) ||
(geometry instanceof ol.geom.MultiPolygon),
- 'geometry should be one of: ol.geom.MultiPoint, ' +
- 'ol.geom.MultiLineString or ol.geom.MultiPolygon');
- /** @type {ol.xml.NodeStackItem} */
+ 'geometry should be one of: ol.geom.GeometryCollection, ' +
+ 'ol.geom.MultiPoint, ol.geom.MultiLineString or ol.geom.MultiPolygon');
+ /** @type {ol.XmlNodeStackItem} */
var context = {node: node};
var type = geometry.getType();
/** @type {Array.<ol.geom.Geometry>} */
var geometries;
/** @type {function(*, Array.<*>, string=): (Node|undefined)} */
var factory;
- if (type == ol.geom.GeometryType.MULTI_POINT) {
+ if (type == ol.geom.GeometryType.GEOMETRY_COLLECTION) {
+ geometries = geometry.getGeometries();
+ factory = ol.format.KML.GEOMETRY_NODE_FACTORY_;
+ } else if (type == ol.geom.GeometryType.MULTI_POINT) {
geometries =
(/** @type {ol.geom.MultiPoint} */ (geometry)).getPoints();
factory = ol.format.KML.POINT_NODE_FACTORY_;
@@ -99958,7 +85504,7 @@ ol.format.KML.writeMultiGeometry_ =
* @private
*/
ol.format.KML.writeBoundaryIs_ = function(node, linearRing, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
ol.xml.pushSerializeAndPop(context,
ol.format.KML.BOUNDARY_IS_SERIALIZERS_,
ol.format.KML.LINEAR_RING_NODE_FACTORY_, [linearRing], objectStack);
@@ -99975,7 +85521,7 @@ ol.format.KML.writeBoundaryIs_ = function(node, linearRing, objectStack) {
* @private
*/
ol.format.KML.writePlacemark_ = function(node, feature, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
// set id
if (feature.getId()) {
@@ -99990,10 +85536,10 @@ ol.format.KML.writePlacemark_ = function(node, feature, objectStack) {
// FIXME the styles returned by the style function are supposed to be
// resolution-independent here
var styles = styleFunction.call(feature, 0);
- if (styles && styles.length > 0) {
- var style = styles[0];
+ if (styles) {
+ var style = Array.isArray(styles) ? styles[0] : styles;
if (this.writeStyles_) {
- properties['Style'] = styles[0];
+ properties['Style'] = style;
}
var textStyle = style.getText();
if (textStyle) {
@@ -100033,7 +85579,7 @@ ol.format.KML.writePrimitiveGeometry_ = function(node, geometry, objectStack) {
'geometry should be one of ol.geom.Point, ol.geom.LineString ' +
'or ol.geom.LinearRing');
var flatCoordinates = geometry.getFlatCoordinates();
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
context['layout'] = geometry.getLayout();
context['stride'] = geometry.getStride();
ol.xml.pushSerializeAndPop(context,
@@ -100056,7 +85602,7 @@ ol.format.KML.writePolygon_ = function(node, polygon, objectStack) {
goog.asserts.assert(linearRings.length > 0,
'linearRings should not be empty');
var outerRing = linearRings.shift();
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
// inner rings
ol.xml.pushSerializeAndPop(context,
ol.format.KML.POLYGON_SERIALIZERS_,
@@ -100077,7 +85623,7 @@ ol.format.KML.writePolygon_ = function(node, polygon, objectStack) {
* @private
*/
ol.format.KML.writePolyStyle_ = function(node, style, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
ol.xml.pushSerializeAndPop(context, ol.format.KML.POLY_STYLE_SERIALIZERS_,
ol.format.KML.COLOR_NODE_FACTORY_, [style.getColor()], objectStack);
};
@@ -100089,7 +85635,9 @@ ol.format.KML.writePolyStyle_ = function(node, style, objectStack) {
* @private
*/
ol.format.KML.writeScaleTextNode_ = function(node, scale) {
- ol.format.XSD.writeDecimalTextNode(node, scale * scale);
+ // the Math is to remove any excess decimals created by float arithmetic
+ ol.format.XSD.writeDecimalTextNode(node,
+ Math.round(scale * scale * 1e6) / 1e6);
};
@@ -100100,7 +85648,7 @@ ol.format.KML.writeScaleTextNode_ = function(node, scale) {
* @private
*/
ol.format.KML.writeStyle_ = function(node, style, objectStack) {
- var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
var properties = {};
var fillStyle = style.getFill();
var strokeStyle = style.getStroke();
@@ -100128,7 +85676,7 @@ ol.format.KML.writeStyle_ = function(node, style, objectStack) {
/**
* @param {Node} node Node to append a TextNode with the Vec2 to.
- * @param {ol.format.KMLVec2_} vec2 Vec2.
+ * @param {ol.KMLVec2_} vec2 Vec2.
* @private
*/
ol.format.KML.writeVec2_ = function(node, vec2) {
@@ -100152,7 +85700,7 @@ ol.format.KML.KML_SEQUENCE_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.KML_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100164,7 +85712,7 @@ ol.format.KML.KML_SERIALIZERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.DOCUMENT_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100185,7 +85733,8 @@ ol.format.KML.GEOMETRY_TYPE_TO_NODENAME_ = {
'Polygon': 'Polygon',
'MultiPoint': 'MultiGeometry',
'MultiLineString': 'MultiGeometry',
- 'MultiPolygon': 'MultiGeometry'
+ 'MultiPolygon': 'MultiGeometry',
+ 'GeometryCollection': 'MultiGeometry'
};
@@ -100198,15 +85747,14 @@ ol.format.KML.ICON_SEQUENCE_ = ol.xml.makeStructureNS(
ol.format.KML.NAMESPACE_URIS_, [
'href'
],
- ol.xml.makeStructureNS(
- ol.format.KML.GX_NAMESPACE_URIS_, [
- 'x', 'y', 'w', 'h'
+ ol.xml.makeStructureNS(ol.format.KML.GX_NAMESPACE_URIS_, [
+ 'x', 'y', 'w', 'h'
]));
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.ICON_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100234,7 +85782,7 @@ ol.format.KML.ICON_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.ICON_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100259,7 +85807,7 @@ ol.format.KML.LABEL_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.LABEL_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100282,7 +85830,7 @@ ol.format.KML.LINE_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.LINE_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100294,7 +85842,7 @@ ol.format.KML.LINE_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.BOUNDARY_IS_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100306,7 +85854,7 @@ ol.format.KML.BOUNDARY_IS_SERIALIZERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.MULTI_GEOMETRY_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100315,7 +85863,9 @@ ol.format.KML.MULTI_GEOMETRY_SERIALIZERS_ = ol.xml.makeStructureNS(
ol.format.KML.writePrimitiveGeometry_),
'Point': ol.xml.makeChildAppender(
ol.format.KML.writePrimitiveGeometry_),
- 'Polygon': ol.xml.makeChildAppender(ol.format.KML.writePolygon_)
+ 'Polygon': ol.xml.makeChildAppender(ol.format.KML.writePolygon_),
+ 'GeometryCollection': ol.xml.makeChildAppender(
+ ol.format.KML.writeMultiGeometry_)
});
@@ -100333,7 +85883,7 @@ ol.format.KML.PLACEMARK_SEQUENCE_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.PLACEMARK_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100363,7 +85913,7 @@ ol.format.KML.PLACEMARK_SERIALIZERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.PRIMITIVE_GEOMETRY_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100375,7 +85925,7 @@ ol.format.KML.PRIMITIVE_GEOMETRY_SERIALIZERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.POLYGON_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100389,7 +85939,7 @@ ol.format.KML.POLYGON_SERIALIZERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.POLY_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100411,7 +85961,7 @@ ol.format.KML.STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.KML.STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
@@ -100558,7 +86108,8 @@ ol.format.KML.OUTER_BOUNDARY_NODE_FACTORY_ =
/**
- * Encode an array of features in the KML format.
+ * Encode an array of features in the KML format. GeometryCollections, MultiPoints,
+ * MultiLineStrings, and MultiPolygons are output as MultiGeometries.
*
* @function
* @param {Array.<ol.Feature>} features Features.
@@ -100570,7 +86121,8 @@ ol.format.KML.prototype.writeFeatures;
/**
- * Encode an array of features in the KML format as an XML node.
+ * Encode an array of features in the KML format as an XML node. GeometryCollections,
+ * MultiPoints, MultiLineStrings, and MultiPolygons are output as MultiGeometries.
*
* @param {Array.<ol.Feature>} features Features.
* @param {olx.format.WriteOptions=} opt_options Options.
@@ -100588,7 +86140,7 @@ ol.format.KML.prototype.writeFeaturesNode = function(features, opt_options) {
ol.xml.setAttributeNS(kml, xmlSchemaInstanceUri, 'xsi:schemaLocation',
ol.format.KML.SCHEMA_LOCATION_);
- var /** @type {ol.xml.NodeStackItem} */ context = {node: kml};
+ var /** @type {ol.XmlNodeStackItem} */ context = {node: kml};
var properties = {};
if (features.length > 1) {
properties['Document'] = features;
@@ -100615,6 +86167,92 @@ var define;
* @suppress {accessControls, ambiguousFunctionDecl, checkDebuggerStatement, checkRegExp, checkTypes, checkVars, const, constantProperty, deprecated, duplicate, es5Strict, fileoverviewTags, missingProperties, nonStandardJsDocs, strictModuleDepCheck, suspiciousCode, undefinedNames, undefinedVars, unknownDefines, uselessCode, visibility}
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.pbf = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
+exports.read = function (buffer, offset, isLE, mLen, nBytes) {
+ var e, m
+ var eLen = nBytes * 8 - mLen - 1
+ var eMax = (1 << eLen) - 1
+ var eBias = eMax >> 1
+ var nBits = -7
+ var i = isLE ? (nBytes - 1) : 0
+ var d = isLE ? -1 : 1
+ var s = buffer[offset + i]
+
+ i += d
+
+ e = s & ((1 << (-nBits)) - 1)
+ s >>= (-nBits)
+ nBits += eLen
+ for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
+
+ m = e & ((1 << (-nBits)) - 1)
+ e >>= (-nBits)
+ nBits += mLen
+ for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
+
+ if (e === 0) {
+ e = 1 - eBias
+ } else if (e === eMax) {
+ return m ? NaN : ((s ? -1 : 1) * Infinity)
+ } else {
+ m = m + Math.pow(2, mLen)
+ e = e - eBias
+ }
+ return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
+}
+
+exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
+ var e, m, c
+ var eLen = nBytes * 8 - mLen - 1
+ var eMax = (1 << eLen) - 1
+ var eBias = eMax >> 1
+ var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
+ var i = isLE ? 0 : (nBytes - 1)
+ var d = isLE ? 1 : -1
+ var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
+
+ value = Math.abs(value)
+
+ if (isNaN(value) || value === Infinity) {
+ m = isNaN(value) ? 1 : 0
+ e = eMax
+ } else {
+ e = Math.floor(Math.log(value) / Math.LN2)
+ if (value * (c = Math.pow(2, -e)) < 1) {
+ e--
+ c *= 2
+ }
+ if (e + eBias >= 1) {
+ value += rt / c
+ } else {
+ value += rt * Math.pow(2, 1 - eBias)
+ }
+ if (value * c >= 2) {
+ e++
+ c /= 2
+ }
+
+ if (e + eBias >= eMax) {
+ m = 0
+ e = eMax
+ } else if (e + eBias >= 1) {
+ m = (value * c - 1) * Math.pow(2, mLen)
+ e = e + eBias
+ } else {
+ m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
+ e = 0
+ }
+ }
+
+ for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
+
+ e = (e << mLen) | m
+ eLen += mLen
+ for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
+
+ buffer[offset + i - d] |= s * 128
+}
+
+},{}],2:[function(_dereq_,module,exports){
'use strict';
// lightweight Buffer shim for pbf browser build
@@ -100775,7 +86413,7 @@ function encodeString(str) {
return bytes;
}
-},{"ieee754":3}],2:[function(_dereq_,module,exports){
+},{"ieee754":1}],3:[function(_dereq_,module,exports){
(function (global){
'use strict';
@@ -101205,93 +86843,7 @@ function writePackedFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pb
function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]); }
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./buffer":1}],3:[function(_dereq_,module,exports){
-exports.read = function (buffer, offset, isLE, mLen, nBytes) {
- var e, m
- var eLen = nBytes * 8 - mLen - 1
- var eMax = (1 << eLen) - 1
- var eBias = eMax >> 1
- var nBits = -7
- var i = isLE ? (nBytes - 1) : 0
- var d = isLE ? -1 : 1
- var s = buffer[offset + i]
-
- i += d
-
- e = s & ((1 << (-nBits)) - 1)
- s >>= (-nBits)
- nBits += eLen
- for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
-
- m = e & ((1 << (-nBits)) - 1)
- e >>= (-nBits)
- nBits += mLen
- for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
-
- if (e === 0) {
- e = 1 - eBias
- } else if (e === eMax) {
- return m ? NaN : ((s ? -1 : 1) * Infinity)
- } else {
- m = m + Math.pow(2, mLen)
- e = e - eBias
- }
- return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
-}
-
-exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
- var e, m, c
- var eLen = nBytes * 8 - mLen - 1
- var eMax = (1 << eLen) - 1
- var eBias = eMax >> 1
- var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
- var i = isLE ? 0 : (nBytes - 1)
- var d = isLE ? 1 : -1
- var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
-
- value = Math.abs(value)
-
- if (isNaN(value) || value === Infinity) {
- m = isNaN(value) ? 1 : 0
- e = eMax
- } else {
- e = Math.floor(Math.log(value) / Math.LN2)
- if (value * (c = Math.pow(2, -e)) < 1) {
- e--
- c *= 2
- }
- if (e + eBias >= 1) {
- value += rt / c
- } else {
- value += rt * Math.pow(2, 1 - eBias)
- }
- if (value * c >= 2) {
- e++
- c /= 2
- }
-
- if (e + eBias >= eMax) {
- m = 0
- e = eMax
- } else if (e + eBias >= 1) {
- m = (value * c - 1) * Math.pow(2, mLen)
- e = e + eBias
- } else {
- m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
- e = 0
- }
- }
-
- for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
-
- e = (e << mLen) | m
- eLen += mLen
- for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
-
- buffer[offset + i - d] |= s * 128
-}
-
-},{}]},{},[2])(2)
+},{"./buffer":2}]},{},[3])(3)
});
ol.ext.pbf = module.exports;
})();
@@ -101308,11 +86860,144 @@ var define;
* @suppress {accessControls, ambiguousFunctionDecl, checkDebuggerStatement, checkRegExp, checkTypes, checkVars, const, constantProperty, deprecated, duplicate, es5Strict, fileoverviewTags, missingProperties, nonStandardJsDocs, strictModuleDepCheck, suspiciousCode, undefinedNames, undefinedVars, unknownDefines, uselessCode, visibility}
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.vectortile = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
+'use strict';
+
+module.exports = Point;
+
+function Point(x, y) {
+ this.x = x;
+ this.y = y;
+}
+
+Point.prototype = {
+ clone: function() { return new Point(this.x, this.y); },
+
+ add: function(p) { return this.clone()._add(p); },
+ sub: function(p) { return this.clone()._sub(p); },
+ mult: function(k) { return this.clone()._mult(k); },
+ div: function(k) { return this.clone()._div(k); },
+ rotate: function(a) { return this.clone()._rotate(a); },
+ matMult: function(m) { return this.clone()._matMult(m); },
+ unit: function() { return this.clone()._unit(); },
+ perp: function() { return this.clone()._perp(); },
+ round: function() { return this.clone()._round(); },
+
+ mag: function() {
+ return Math.sqrt(this.x * this.x + this.y * this.y);
+ },
+
+ equals: function(p) {
+ return this.x === p.x &&
+ this.y === p.y;
+ },
+
+ dist: function(p) {
+ return Math.sqrt(this.distSqr(p));
+ },
+
+ distSqr: function(p) {
+ var dx = p.x - this.x,
+ dy = p.y - this.y;
+ return dx * dx + dy * dy;
+ },
+
+ angle: function() {
+ return Math.atan2(this.y, this.x);
+ },
+
+ angleTo: function(b) {
+ return Math.atan2(this.y - b.y, this.x - b.x);
+ },
+
+ angleWith: function(b) {
+ return this.angleWithSep(b.x, b.y);
+ },
+
+ // Find the angle of the two vectors, solving the formula for the cross product a x b = |a||b|sin(θ) for θ.
+ angleWithSep: function(x, y) {
+ return Math.atan2(
+ this.x * y - this.y * x,
+ this.x * x + this.y * y);
+ },
+
+ _matMult: function(m) {
+ var x = m[0] * this.x + m[1] * this.y,
+ y = m[2] * this.x + m[3] * this.y;
+ this.x = x;
+ this.y = y;
+ return this;
+ },
+
+ _add: function(p) {
+ this.x += p.x;
+ this.y += p.y;
+ return this;
+ },
+
+ _sub: function(p) {
+ this.x -= p.x;
+ this.y -= p.y;
+ return this;
+ },
+
+ _mult: function(k) {
+ this.x *= k;
+ this.y *= k;
+ return this;
+ },
+
+ _div: function(k) {
+ this.x /= k;
+ this.y /= k;
+ return this;
+ },
+
+ _unit: function() {
+ this._div(this.mag());
+ return this;
+ },
+
+ _perp: function() {
+ var y = this.y;
+ this.y = this.x;
+ this.x = -y;
+ return this;
+ },
+
+ _rotate: function(angle) {
+ var cos = Math.cos(angle),
+ sin = Math.sin(angle),
+ x = cos * this.x - sin * this.y,
+ y = sin * this.x + cos * this.y;
+ this.x = x;
+ this.y = y;
+ return this;
+ },
+
+ _round: function() {
+ this.x = Math.round(this.x);
+ this.y = Math.round(this.y);
+ return this;
+ }
+};
+
+// constructs Point from an array if necessary
+Point.convert = function (a) {
+ if (a instanceof Point) {
+ return a;
+ }
+ if (Array.isArray(a)) {
+ return new Point(a[0], a[1]);
+ }
+ return a;
+};
+
+},{}],2:[function(_dereq_,module,exports){
module.exports.VectorTile = _dereq_('./lib/vectortile.js');
module.exports.VectorTileFeature = _dereq_('./lib/vectortilefeature.js');
module.exports.VectorTileLayer = _dereq_('./lib/vectortilelayer.js');
-},{"./lib/vectortile.js":2,"./lib/vectortilefeature.js":3,"./lib/vectortilelayer.js":4}],2:[function(_dereq_,module,exports){
+},{"./lib/vectortile.js":3,"./lib/vectortilefeature.js":4,"./lib/vectortilelayer.js":5}],3:[function(_dereq_,module,exports){
'use strict';
var VectorTileLayer = _dereq_('./vectortilelayer');
@@ -101331,7 +87016,7 @@ function readTile(tag, layers, pbf) {
}
-},{"./vectortilelayer":4}],3:[function(_dereq_,module,exports){
+},{"./vectortilelayer":5}],4:[function(_dereq_,module,exports){
'use strict';
var Point = _dereq_('point-geometry');
@@ -101465,10 +87150,10 @@ VectorTileFeature.prototype.toGeoJSON = function(x, y, z) {
x0 = this.extent * x,
y0 = this.extent * y,
coords = this.loadGeometry(),
- type = VectorTileFeature.types[this.type];
+ type = VectorTileFeature.types[this.type],
+ i, j;
- for (var i = 0; i < coords.length; i++) {
- var line = coords[i];
+ function project(line) {
for (var j = 0; j < line.length; j++) {
var p = line[j], y2 = 180 - (p.y + y0) * 360 / size;
line[j] = [
@@ -101478,15 +87163,36 @@ VectorTileFeature.prototype.toGeoJSON = function(x, y, z) {
}
}
- if (type === 'Point' && coords.length === 1) {
- coords = coords[0][0];
- } else if (type === 'Point') {
- coords = coords[0];
- type = 'MultiPoint';
- } else if (type === 'LineString' && coords.length === 1) {
+ switch (this.type) {
+ case 1:
+ var points = [];
+ for (i = 0; i < coords.length; i++) {
+ points[i] = coords[i][0];
+ }
+ coords = points;
+ project(coords);
+ break;
+
+ case 2:
+ for (i = 0; i < coords.length; i++) {
+ project(coords[i]);
+ }
+ break;
+
+ case 3:
+ coords = classifyRings(coords);
+ for (i = 0; i < coords.length; i++) {
+ for (j = 0; j < coords[i].length; j++) {
+ project(coords[i][j]);
+ }
+ }
+ break;
+ }
+
+ if (coords.length === 1) {
coords = coords[0];
- } else if (type === 'LineString') {
- type = 'MultiLineString';
+ } else {
+ type = 'Multi' + type;
}
var result = {
@@ -101505,7 +87211,47 @@ VectorTileFeature.prototype.toGeoJSON = function(x, y, z) {
return result;
};
-},{"point-geometry":5}],4:[function(_dereq_,module,exports){
+// classifies an array of rings into polygons with outer rings and holes
+
+function classifyRings(rings) {
+ var len = rings.length;
+
+ if (len <= 1) return [rings];
+
+ var polygons = [],
+ polygon,
+ ccw;
+
+ for (var i = 0; i < len; i++) {
+ var area = signedArea(rings[i]);
+ if (area === 0) continue;
+
+ if (ccw === undefined) ccw = area < 0;
+
+ if (ccw === area < 0) {
+ if (polygon) polygons.push(polygon);
+ polygon = [rings[i]];
+
+ } else {
+ polygon.push(rings[i]);
+ }
+ }
+ if (polygon) polygons.push(polygon);
+
+ return polygons;
+}
+
+function signedArea(ring) {
+ var sum = 0;
+ for (var i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
+ p1 = ring[i];
+ p2 = ring[j];
+ sum += (p2.x - p1.x) * (p1.y + p2.y);
+ }
+ return sum;
+}
+
+},{"point-geometry":1}],5:[function(_dereq_,module,exports){
'use strict';
var VectorTileFeature = _dereq_('./vectortilefeature.js');
@@ -101568,140 +87314,7 @@ VectorTileLayer.prototype.feature = function(i) {
return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values);
};
-},{"./vectortilefeature.js":3}],5:[function(_dereq_,module,exports){
-'use strict';
-
-module.exports = Point;
-
-function Point(x, y) {
- this.x = x;
- this.y = y;
-}
-
-Point.prototype = {
- clone: function() { return new Point(this.x, this.y); },
-
- add: function(p) { return this.clone()._add(p); },
- sub: function(p) { return this.clone()._sub(p); },
- mult: function(k) { return this.clone()._mult(k); },
- div: function(k) { return this.clone()._div(k); },
- rotate: function(a) { return this.clone()._rotate(a); },
- matMult: function(m) { return this.clone()._matMult(m); },
- unit: function() { return this.clone()._unit(); },
- perp: function() { return this.clone()._perp(); },
- round: function() { return this.clone()._round(); },
-
- mag: function() {
- return Math.sqrt(this.x * this.x + this.y * this.y);
- },
-
- equals: function(p) {
- return this.x === p.x &&
- this.y === p.y;
- },
-
- dist: function(p) {
- return Math.sqrt(this.distSqr(p));
- },
-
- distSqr: function(p) {
- var dx = p.x - this.x,
- dy = p.y - this.y;
- return dx * dx + dy * dy;
- },
-
- angle: function() {
- return Math.atan2(this.y, this.x);
- },
-
- angleTo: function(b) {
- return Math.atan2(this.y - b.y, this.x - b.x);
- },
-
- angleWith: function(b) {
- return this.angleWithSep(b.x, b.y);
- },
-
- // Find the angle of the two vectors, solving the formula for the cross product a x b = |a||b|sin(θ) for θ.
- angleWithSep: function(x, y) {
- return Math.atan2(
- this.x * y - this.y * x,
- this.x * x + this.y * y);
- },
-
- _matMult: function(m) {
- var x = m[0] * this.x + m[1] * this.y,
- y = m[2] * this.x + m[3] * this.y;
- this.x = x;
- this.y = y;
- return this;
- },
-
- _add: function(p) {
- this.x += p.x;
- this.y += p.y;
- return this;
- },
-
- _sub: function(p) {
- this.x -= p.x;
- this.y -= p.y;
- return this;
- },
-
- _mult: function(k) {
- this.x *= k;
- this.y *= k;
- return this;
- },
-
- _div: function(k) {
- this.x /= k;
- this.y /= k;
- return this;
- },
-
- _unit: function() {
- this._div(this.mag());
- return this;
- },
-
- _perp: function() {
- var y = this.y;
- this.y = this.x;
- this.x = -y;
- return this;
- },
-
- _rotate: function(angle) {
- var cos = Math.cos(angle),
- sin = Math.sin(angle),
- x = cos * this.x - sin * this.y,
- y = sin * this.x + cos * this.y;
- this.x = x;
- this.y = y;
- return this;
- },
-
- _round: function() {
- this.x = Math.round(this.x);
- this.y = Math.round(this.y);
- return this;
- }
-};
-
-// constructs Point from an array if necessary
-Point.convert = function (a) {
- if (a instanceof Point) {
- return a;
- }
- if (Array.isArray(a)) {
- return new Point(a[0], a[1]);
- }
- return a;
-};
-
-},{}]},{},[1])(1)
+},{"./vectortilefeature.js":4}]},{},[2])(2)
});
ol.ext.vectortile = module.exports;
})();
@@ -101730,7 +87343,6 @@ goog.require('ol.proj.Units');
goog.require('ol.render.Feature');
-
/**
* @classdesc
* Feature format for reading data in the Mapbox MVT format.
@@ -101750,7 +87362,7 @@ ol.format.MVT = function(opt_options) {
* @type {ol.proj.Projection}
*/
this.defaultDataProjection = new ol.proj.Projection({
- code: 'EPSG:3857',
+ code: '',
units: ol.proj.Units.TILE_PIXELS
});
@@ -101856,6 +87468,7 @@ ol.format.MVT.prototype.readRenderFeature_ = function(rawFeature, layer) {
/**
* @inheritDoc
+ * @api
*/
ol.format.MVT.prototype.readFeatures = function(source, opt_options) {
goog.asserts.assertInstanceof(source, ArrayBuffer);
@@ -101889,6 +87502,7 @@ ol.format.MVT.prototype.readFeatures = function(source, opt_options) {
/**
* @inheritDoc
+ * @api
*/
ol.format.MVT.prototype.readProjection = function(source) {
return this.defaultDataProjection;
@@ -101915,11 +87529,11 @@ ol.format.MVT.prototype.setLayers = function(layers) {
ol.format.MVT.calculateFlatCoordinates_ = function(
coords, flatCoordinates, ends) {
var end = 0;
- var line, coord;
for (var i = 0, ii = coords.length; i < ii; ++i) {
- line = coords[i];
- for (var j = 0, jj = line.length; j < jj; ++j) {
- coord = line[j];
+ var line = coords[i];
+ var j, jj;
+ for (j = 0, jj = line.length; j < jj; ++j) {
+ var coord = line[j];
// Non-tilespace coords can be calculated here when a TileGrid and
// TileCoord are known.
flatCoordinates.push(coord.x, coord.y);
@@ -101966,13 +87580,651 @@ ol.format.MVT.readGeometry_ = function(rawFeature) {
return geom;
};
+goog.provide('ol.format.ogc.filter');
+goog.provide('ol.format.ogc.filter.Filter');
+goog.provide('ol.format.ogc.filter.Logical');
+goog.provide('ol.format.ogc.filter.LogicalBinary');
+goog.provide('ol.format.ogc.filter.And');
+goog.provide('ol.format.ogc.filter.Or');
+goog.provide('ol.format.ogc.filter.Not');
+goog.provide('ol.format.ogc.filter.Bbox');
+goog.provide('ol.format.ogc.filter.Comparison');
+goog.provide('ol.format.ogc.filter.ComparisonBinary');
+goog.provide('ol.format.ogc.filter.EqualTo');
+goog.provide('ol.format.ogc.filter.NotEqualTo');
+goog.provide('ol.format.ogc.filter.LessThan');
+goog.provide('ol.format.ogc.filter.LessThanOrEqualTo');
+goog.provide('ol.format.ogc.filter.GreaterThan');
+goog.provide('ol.format.ogc.filter.GreaterThanOrEqualTo');
+goog.provide('ol.format.ogc.filter.IsNull');
+goog.provide('ol.format.ogc.filter.IsBetween');
+goog.provide('ol.format.ogc.filter.IsLike');
+
+goog.require('ol.Extent');
+goog.require('ol.Object');
+
+
+/**
+ * Create a logical `<And>` operator between two filter conditions.
+ *
+ * @param {!ol.format.ogc.filter.Filter} conditionA First filter condition.
+ * @param {!ol.format.ogc.filter.Filter} conditionB Second filter condition.
+ * @returns {!ol.format.ogc.filter.And} `<And>` operator.
+ * @api
+ */
+ol.format.ogc.filter.and = function(conditionA, conditionB) {
+ return new ol.format.ogc.filter.And(conditionA, conditionB);
+};
+
+
+/**
+ * Create a logical `<Or>` operator between two filter conditions.
+ *
+ * @param {!ol.format.ogc.filter.Filter} conditionA First filter condition.
+ * @param {!ol.format.ogc.filter.Filter} conditionB Second filter condition.
+ * @returns {!ol.format.ogc.filter.Or} `<Or>` operator.
+ * @api
+ */
+ol.format.ogc.filter.or = function(conditionA, conditionB) {
+ return new ol.format.ogc.filter.Or(conditionA, conditionB);
+};
+
+
+/**
+ * Represents a logical `<Not>` operator for a filter condition.
+ *
+ * @param {!ol.format.ogc.filter.Filter} condition Filter condition.
+ * @returns {!ol.format.ogc.filter.Not} `<Not>` operator.
+ * @api
+ */
+ol.format.ogc.filter.not = function(condition) {
+ return new ol.format.ogc.filter.Not(condition);
+};
+
+
+/**
+ * Create a `<BBOX>` operator to test whether a geometry-valued property
+ * intersects a fixed bounding box
+ *
+ * @param {!string} geometryName Geometry name to use.
+ * @param {!ol.Extent} extent Extent.
+ * @param {string=} opt_srsName SRS name. No srsName attribute will be
+ * set on geometries when this is not provided.
+ * @returns {!ol.format.ogc.filter.Bbox} `<BBOX>` operator.
+ * @api
+ */
+ol.format.ogc.filter.bbox = function(geometryName, extent, opt_srsName) {
+ return new ol.format.ogc.filter.Bbox(geometryName, extent, opt_srsName);
+};
+
+
+/**
+ * Creates a `<PropertyIsEqualTo>` comparison operator.
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!(string|number)} expression The value to compare.
+ * @param {boolean=} opt_matchCase Case-sensitive?
+ * @returns {!ol.format.ogc.filter.EqualTo} `<PropertyIsEqualTo>` operator.
+ * @api
+ */
+ol.format.ogc.filter.equalTo = function(propertyName, expression, opt_matchCase) {
+ return new ol.format.ogc.filter.EqualTo(propertyName, expression, opt_matchCase);
+};
+
+
+/**
+ * Creates a `<PropertyIsNotEqualTo>` comparison operator.
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!(string|number)} expression The value to compare.
+ * @param {boolean=} opt_matchCase Case-sensitive?
+ * @returns {!ol.format.ogc.filter.NotEqualTo} `<PropertyIsNotEqualTo>` operator.
+ * @api
+ */
+ol.format.ogc.filter.notEqualTo = function(propertyName, expression, opt_matchCase) {
+ return new ol.format.ogc.filter.NotEqualTo(propertyName, expression, opt_matchCase);
+};
+
+
+/**
+ * Creates a `<PropertyIsLessThan>` comparison operator.
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} expression The value to compare.
+ * @returns {!ol.format.ogc.filter.LessThan} `<PropertyIsLessThan>` operator.
+ * @api
+ */
+ol.format.ogc.filter.lessThan = function(propertyName, expression) {
+ return new ol.format.ogc.filter.LessThan(propertyName, expression);
+};
+
+
+/**
+ * Creates a `<PropertyIsLessThanOrEqualTo>` comparison operator.
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} expression The value to compare.
+ * @returns {!ol.format.ogc.filter.LessThanOrEqualTo} `<PropertyIsLessThanOrEqualTo>` operator.
+ * @api
+ */
+ol.format.ogc.filter.lessThanOrEqualTo = function(propertyName, expression) {
+ return new ol.format.ogc.filter.LessThanOrEqualTo(propertyName, expression);
+};
+
+
+/**
+ * Creates a `<PropertyIsGreaterThan>` comparison operator.
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} expression The value to compare.
+ * @returns {!ol.format.ogc.filter.GreaterThan} `<PropertyIsGreaterThan>` operator.
+ * @api
+ */
+ol.format.ogc.filter.greaterThan = function(propertyName, expression) {
+ return new ol.format.ogc.filter.GreaterThan(propertyName, expression);
+};
+
+
+/**
+ * Creates a `<PropertyIsGreaterThanOrEqualTo>` comparison operator.
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} expression The value to compare.
+ * @returns {!ol.format.ogc.filter.GreaterThanOrEqualTo} `<PropertyIsGreaterThanOrEqualTo>` operator.
+ * @api
+ */
+ol.format.ogc.filter.greaterThanOrEqualTo = function(propertyName, expression) {
+ return new ol.format.ogc.filter.GreaterThanOrEqualTo(propertyName, expression);
+};
+
+
+/**
+ * Creates a `<PropertyIsNull>` comparison operator to test whether a property value
+ * is null.
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @returns {!ol.format.ogc.filter.IsNull} `<PropertyIsNull>` operator.
+ * @api
+ */
+ol.format.ogc.filter.isNull = function(propertyName) {
+ return new ol.format.ogc.filter.IsNull(propertyName);
+};
+
+
+/**
+ * Creates a `<PropertyIsBetween>` comparison operator to test whether an expression
+ * value lies within a range given by a lower and upper bound (inclusive).
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} lowerBoundary The lower bound of the range.
+ * @param {!number} upperBoundary The upper bound of the range.
+ * @returns {!ol.format.ogc.filter.IsBetween} `<PropertyIsBetween>` operator.
+ * @api
+ */
+ol.format.ogc.filter.between = function(propertyName, lowerBoundary, upperBoundary) {
+ return new ol.format.ogc.filter.IsBetween(propertyName, lowerBoundary, upperBoundary);
+};
+
+
+/**
+ * Represents a `<PropertyIsLike>` comparison operator that matches a string property
+ * value against a text pattern.
+ *
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!string} pattern Text pattern.
+ * @param {string=} opt_wildCard Pattern character which matches any sequence of
+ * zero or more string characters. Default is '*'.
+ * @param {string=} opt_singleChar pattern character which matches any single
+ * string character. Default is '.'.
+ * @param {string=} opt_escapeChar Escape character which can be used to escape
+ * the pattern characters. Default is '!'.
+ * @param {boolean=} opt_matchCase Case-sensitive?
+ * @returns {!ol.format.ogc.filter.IsLike} `<PropertyIsLike>` operator.
+ * @api
+ */
+ol.format.ogc.filter.like = function(propertyName, pattern,
+ opt_wildCard, opt_singleChar, opt_escapeChar, opt_matchCase) {
+ return new ol.format.ogc.filter.IsLike(propertyName, pattern,
+ opt_wildCard, opt_singleChar, opt_escapeChar, opt_matchCase);
+};
+
+
+/**
+ * @classdesc
+ * Abstract class; normally only used for creating subclasses and not instantiated in apps.
+ * Base class for WFS GetFeature filters.
+ *
+ * @constructor
+ * @param {!string} tagName The XML tag name for this filter.
+ * @extends {ol.Object}
+ * @api
+ */
+ol.format.ogc.filter.Filter = function(tagName) {
+
+ goog.base(this);
+
+ /**
+ * @private
+ * @type {!string}
+ */
+ this.tagName_ = tagName;
+};
+goog.inherits(ol.format.ogc.filter.Filter, ol.Object);
+
+/**
+ * The XML tag name for a filter.
+ * @returns {!string} Name.
+ */
+ol.format.ogc.filter.Filter.prototype.getTagName = function() {
+ return this.tagName_;
+};
+
+
+// Logical filters
+
+
+/**
+ * @classdesc
+ * Abstract class; normally only used for creating subclasses and not instantiated in apps.
+ * Base class for WFS GetFeature logical filters.
+ *
+ * @constructor
+ * @param {!string} tagName The XML tag name for this filter.
+ * @extends {ol.format.ogc.filter.Filter}
+ */
+ol.format.ogc.filter.Logical = function(tagName) {
+ goog.base(this, tagName);
+};
+goog.inherits(ol.format.ogc.filter.Logical, ol.format.ogc.filter.Filter);
+
+
+/**
+ * @classdesc
+ * Abstract class; normally only used for creating subclasses and not instantiated in apps.
+ * Base class for WFS GetFeature binary logical filters.
+ *
+ * @constructor
+ * @param {!string} tagName The XML tag name for this filter.
+ * @param {!ol.format.ogc.filter.Filter} conditionA First filter condition.
+ * @param {!ol.format.ogc.filter.Filter} conditionB Second filter condition.
+ * @extends {ol.format.ogc.filter.Logical}
+ */
+ol.format.ogc.filter.LogicalBinary = function(tagName, conditionA, conditionB) {
+
+ goog.base(this, tagName);
+
+ /**
+ * @public
+ * @type {!ol.format.ogc.filter.Filter}
+ */
+ this.conditionA = conditionA;
+
+ /**
+ * @public
+ * @type {!ol.format.ogc.filter.Filter}
+ */
+ this.conditionB = conditionB;
+
+};
+goog.inherits(ol.format.ogc.filter.LogicalBinary, ol.format.ogc.filter.Logical);
+
+
+/**
+ * @classdesc
+ * Represents a logical `<And>` operator between two filter conditions.
+ *
+ * @constructor
+ * @param {!ol.format.ogc.filter.Filter} conditionA First filter condition.
+ * @param {!ol.format.ogc.filter.Filter} conditionB Second filter condition.
+ * @extends {ol.format.ogc.filter.LogicalBinary}
+ * @api
+ */
+ol.format.ogc.filter.And = function(conditionA, conditionB) {
+ goog.base(this, 'And', conditionA, conditionB);
+};
+goog.inherits(ol.format.ogc.filter.And, ol.format.ogc.filter.LogicalBinary);
+
+
+/**
+ * @classdesc
+ * Represents a logical `<Or>` operator between two filter conditions.
+ *
+ * @constructor
+ * @param {!ol.format.ogc.filter.Filter} conditionA First filter condition.
+ * @param {!ol.format.ogc.filter.Filter} conditionB Second filter condition.
+ * @extends {ol.format.ogc.filter.LogicalBinary}
+ * @api
+ */
+ol.format.ogc.filter.Or = function(conditionA, conditionB) {
+ goog.base(this, 'Or', conditionA, conditionB);
+};
+goog.inherits(ol.format.ogc.filter.Or, ol.format.ogc.filter.LogicalBinary);
+
+
+/**
+ * @classdesc
+ * Represents a logical `<Not>` operator for a filter condition.
+ *
+ * @constructor
+ * @param {!ol.format.ogc.filter.Filter} condition Filter condition.
+ * @extends {ol.format.ogc.filter.Logical}
+ * @api
+ */
+ol.format.ogc.filter.Not = function(condition) {
+
+ goog.base(this, 'Not');
+
+ /**
+ * @public
+ * @type {!ol.format.ogc.filter.Filter}
+ */
+ this.condition = condition;
+};
+goog.inherits(ol.format.ogc.filter.Not, ol.format.ogc.filter.Logical);
+
+
+// Spatial filters
+
+
+/**
+ * @classdesc
+ * Represents a `<BBOX>` operator to test whether a geometry-valued property
+ * intersects a fixed bounding box
+ *
+ * @constructor
+ * @param {!string} geometryName Geometry name to use.
+ * @param {!ol.Extent} extent Extent.
+ * @param {string=} opt_srsName SRS name. No srsName attribute will be
+ * set on geometries when this is not provided.
+ * @extends {ol.format.ogc.filter.Filter}
+ * @api
+ */
+ol.format.ogc.filter.Bbox = function(geometryName, extent, opt_srsName) {
+
+ goog.base(this, 'BBOX');
+
+ /**
+ * @public
+ * @type {!string}
+ */
+ this.geometryName = geometryName;
+
+ /**
+ * @public
+ * @type {!ol.Extent}
+ */
+ this.extent = extent;
+
+ /**
+ * @public
+ * @type {string|undefined}
+ */
+ this.srsName = opt_srsName;
+};
+goog.inherits(ol.format.ogc.filter.Bbox, ol.format.ogc.filter.Filter);
+
+
+// Property comparison filters
+
+
+/**
+ * @classdesc
+ * Abstract class; normally only used for creating subclasses and not instantiated in apps.
+ * Base class for WFS GetFeature property comparison filters.
+ *
+ * @constructor
+ * @param {!string} tagName The XML tag name for this filter.
+ * @param {!string} propertyName Name of the context property to compare.
+ * @extends {ol.format.ogc.filter.Filter}
+ * @api
+ */
+ol.format.ogc.filter.Comparison = function(tagName, propertyName) {
+
+ goog.base(this, tagName);
+
+ /**
+ * @public
+ * @type {!string}
+ */
+ this.propertyName = propertyName;
+};
+goog.inherits(ol.format.ogc.filter.Comparison, ol.format.ogc.filter.Filter);
+
+
+/**
+ * @classdesc
+ * Abstract class; normally only used for creating subclasses and not instantiated in apps.
+ * Base class for WFS GetFeature property binary comparison filters.
+ *
+ * @constructor
+ * @param {!string} tagName The XML tag name for this filter.
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!(string|number)} expression The value to compare.
+ * @param {boolean=} opt_matchCase Case-sensitive?
+ * @extends {ol.format.ogc.filter.Comparison}
+ * @api
+ */
+ol.format.ogc.filter.ComparisonBinary = function(
+ tagName, propertyName, expression, opt_matchCase) {
+
+ goog.base(this, tagName, propertyName);
+
+ /**
+ * @public
+ * @type {!(string|number)}
+ */
+ this.expression = expression;
+
+ /**
+ * @public
+ * @type {boolean|undefined}
+ */
+ this.matchCase = opt_matchCase;
+};
+goog.inherits(ol.format.ogc.filter.ComparisonBinary, ol.format.ogc.filter.Comparison);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsEqualTo>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!(string|number)} expression The value to compare.
+ * @param {boolean=} opt_matchCase Case-sensitive?
+ * @extends {ol.format.ogc.filter.ComparisonBinary}
+ * @api
+ */
+ol.format.ogc.filter.EqualTo = function(propertyName, expression, opt_matchCase) {
+ goog.base(this, 'PropertyIsEqualTo', propertyName, expression, opt_matchCase);
+};
+goog.inherits(ol.format.ogc.filter.EqualTo, ol.format.ogc.filter.ComparisonBinary);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsNotEqualTo>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!(string|number)} expression The value to compare.
+ * @param {boolean=} opt_matchCase Case-sensitive?
+ * @extends {ol.format.ogc.filter.ComparisonBinary}
+ * @api
+ */
+ol.format.ogc.filter.NotEqualTo = function(propertyName, expression, opt_matchCase) {
+ goog.base(this, 'PropertyIsNotEqualTo', propertyName, expression, opt_matchCase);
+};
+goog.inherits(ol.format.ogc.filter.NotEqualTo, ol.format.ogc.filter.ComparisonBinary);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsLessThan>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} expression The value to compare.
+ * @extends {ol.format.ogc.filter.ComparisonBinary}
+ * @api
+ */
+ol.format.ogc.filter.LessThan = function(propertyName, expression) {
+ goog.base(this, 'PropertyIsLessThan', propertyName, expression);
+};
+goog.inherits(ol.format.ogc.filter.LessThan, ol.format.ogc.filter.ComparisonBinary);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsLessThanOrEqualTo>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} expression The value to compare.
+ * @extends {ol.format.ogc.filter.ComparisonBinary}
+ * @api
+ */
+ol.format.ogc.filter.LessThanOrEqualTo = function(propertyName, expression) {
+ goog.base(this, 'PropertyIsLessThanOrEqualTo', propertyName, expression);
+};
+goog.inherits(ol.format.ogc.filter.LessThanOrEqualTo, ol.format.ogc.filter.ComparisonBinary);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsGreaterThan>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} expression The value to compare.
+ * @extends {ol.format.ogc.filter.ComparisonBinary}
+ * @api
+ */
+ol.format.ogc.filter.GreaterThan = function(propertyName, expression) {
+ goog.base(this, 'PropertyIsGreaterThan', propertyName, expression);
+};
+goog.inherits(ol.format.ogc.filter.GreaterThan, ol.format.ogc.filter.ComparisonBinary);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsGreaterThanOrEqualTo>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} expression The value to compare.
+ * @extends {ol.format.ogc.filter.ComparisonBinary}
+ * @api
+ */
+ol.format.ogc.filter.GreaterThanOrEqualTo = function(propertyName, expression) {
+ goog.base(this, 'PropertyIsGreaterThanOrEqualTo', propertyName, expression);
+};
+goog.inherits(ol.format.ogc.filter.GreaterThanOrEqualTo, ol.format.ogc.filter.ComparisonBinary);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsNull>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @extends {ol.format.ogc.filter.Comparison}
+ * @api
+ */
+ol.format.ogc.filter.IsNull = function(propertyName) {
+ goog.base(this, 'PropertyIsNull', propertyName);
+};
+goog.inherits(ol.format.ogc.filter.IsNull, ol.format.ogc.filter.Comparison);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsBetween>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!number} lowerBoundary The lower bound of the range.
+ * @param {!number} upperBoundary The upper bound of the range.
+ * @extends {ol.format.ogc.filter.Comparison}
+ * @api
+ */
+ol.format.ogc.filter.IsBetween = function(propertyName, lowerBoundary, upperBoundary) {
+ goog.base(this, 'PropertyIsBetween', propertyName);
+
+ /**
+ * @public
+ * @type {!number}
+ */
+ this.lowerBoundary = lowerBoundary;
+
+ /**
+ * @public
+ * @type {!number}
+ */
+ this.upperBoundary = upperBoundary;
+};
+goog.inherits(ol.format.ogc.filter.IsBetween, ol.format.ogc.filter.Comparison);
+
+
+/**
+ * @classdesc
+ * Represents a `<PropertyIsLike>` comparison operator.
+ *
+ * @constructor
+ * @param {!string} propertyName Name of the context property to compare.
+ * @param {!string} pattern Text pattern.
+ * @param {string=} opt_wildCard Pattern character which matches any sequence of
+ * zero or more string characters. Default is '*'.
+ * @param {string=} opt_singleChar pattern character which matches any single
+ * string character. Default is '.'.
+ * @param {string=} opt_escapeChar Escape character which can be used to escape
+ * the pattern characters. Default is '!'.
+ * @param {boolean=} opt_matchCase Case-sensitive?
+ * @extends {ol.format.ogc.filter.Comparison}
+ * @api
+ */
+ol.format.ogc.filter.IsLike = function(propertyName, pattern,
+ opt_wildCard, opt_singleChar, opt_escapeChar, opt_matchCase) {
+ goog.base(this, 'PropertyIsLike', propertyName);
+
+ /**
+ * @public
+ * @type {!string}
+ */
+ this.pattern = pattern;
+
+ /**
+ * @public
+ * @type {!string}
+ */
+ this.wildCard = (opt_wildCard !== undefined) ? opt_wildCard : '*';
+
+ /**
+ * @public
+ * @type {!string}
+ */
+ this.singleChar = (opt_singleChar !== undefined) ? opt_singleChar : '.';
+
+ /**
+ * @public
+ * @type {!string}
+ */
+ this.escapeChar = (opt_escapeChar !== undefined) ? opt_escapeChar : '!';
+
+ /**
+ * @public
+ * @type {boolean|undefined}
+ */
+ this.matchCase = opt_matchCase;
+};
+goog.inherits(ol.format.ogc.filter.IsLike, ol.format.ogc.filter.Comparison);
+
// FIXME add typedef for stack state objects
goog.provide('ol.format.OSMXML');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
-goog.require('goog.object');
+goog.require('ol.array');
goog.require('ol.Feature');
goog.require('ol.format.Feature');
goog.require('ol.format.XMLFeature');
@@ -101980,11 +88232,11 @@ goog.require('ol.geom.GeometryLayout');
goog.require('ol.geom.LineString');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.xml');
-
/**
* @classdesc
* Feature format for reading data in the
@@ -102033,16 +88285,17 @@ ol.format.OSMXML.readNode_ = function(node, objectStack) {
var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
var state = /** @type {Object} */ (objectStack[objectStack.length - 1]);
var id = node.getAttribute('id');
- var coordinates = /** @type {Array.<number>} */ ([
+ /** @type {ol.Coordinate} */
+ var coordinates = [
parseFloat(node.getAttribute('lon')),
parseFloat(node.getAttribute('lat'))
- ]);
+ ];
state.nodes[id] = coordinates;
var values = ol.xml.pushParseAndPop({
tags: {}
}, ol.format.OSMXML.NODE_PARSERS_, node, objectStack);
- if (!goog.object.isEmpty(values.tags)) {
+ if (!ol.object.isEmpty(values.tags)) {
var geometry = new ol.geom.Point(coordinates);
ol.format.Feature.transformWithOptions(geometry, false, options);
var feature = new ol.Feature(geometry);
@@ -102069,10 +88322,11 @@ ol.format.OSMXML.readWay_ = function(node, objectStack) {
tags: {}
}, ol.format.OSMXML.WAY_PARSERS_, node, objectStack);
var state = /** @type {Object} */ (objectStack[objectStack.length - 1]);
- var flatCoordinates = /** @type {Array.<number>} */ ([]);
+ /** @type {Array.<number>} */
+ var flatCoordinates = [];
for (var i = 0, ii = values.ndrefs.length; i < ii; i++) {
var point = state.nodes[values.ndrefs[i]];
- goog.array.extend(flatCoordinates, point);
+ ol.array.extend(flatCoordinates, point);
}
var geometry;
if (values.ndrefs[0] == values.ndrefs[values.ndrefs.length - 1]) {
@@ -102096,7 +88350,6 @@ ol.format.OSMXML.readWay_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {ol.Feature|undefined} Track.
*/
ol.format.OSMXML.readNd_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102111,7 +88364,6 @@ ol.format.OSMXML.readNd_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {ol.Feature|undefined} Track.
*/
ol.format.OSMXML.readTag_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102134,7 +88386,7 @@ ol.format.OSMXML.NAMESPACE_URIS_ = [
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OSMXML.WAY_PARSERS_ = ol.xml.makeStructureNS(
@@ -102146,7 +88398,7 @@ ol.format.OSMXML.WAY_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OSMXML.PARSERS_ = ol.xml.makeStructureNS(
@@ -102158,7 +88410,7 @@ ol.format.OSMXML.PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OSMXML.NODE_PARSERS_ = ol.xml.makeStructureNS(
@@ -102233,12 +88485,12 @@ goog.require('goog.asserts');
goog.require('ol.xml');
-
/**
* @classdesc
* Generic format for reading non-feature XML data
*
* @constructor
+ * @struct
*/
ol.format.XML = function() {
};
@@ -102246,14 +88498,14 @@ ol.format.XML = function() {
/**
* @param {Document|Node|string} source Source.
- * @return {Object}
+ * @return {Object} The parsed result.
*/
ol.format.XML.prototype.read = function(source) {
if (ol.xml.isDocument(source)) {
return this.readFromDocument(/** @type {Document} */ (source));
} else if (ol.xml.isNode(source)) {
return this.readFromNode(/** @type {Node} */ (source));
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
return this.readFromDocument(doc);
} else {
@@ -102286,7 +88538,6 @@ goog.require('ol.format.XSD');
goog.require('ol.xml');
-
/**
* @constructor
* @extends {ol.format.XML}
@@ -102330,7 +88581,7 @@ ol.format.OWS.prototype.readFromNode = function(node) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The address.
*/
ol.format.OWS.readAddress_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102346,7 +88597,7 @@ ol.format.OWS.readAddress_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The values.
*/
ol.format.OWS.readAllowedValues_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102362,7 +88613,7 @@ ol.format.OWS.readAllowedValues_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The constraint.
*/
ol.format.OWS.readConstraint_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102383,7 +88634,7 @@ ol.format.OWS.readConstraint_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The contact info.
*/
ol.format.OWS.readContactInfo_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102399,7 +88650,7 @@ ol.format.OWS.readContactInfo_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The DCP.
*/
ol.format.OWS.readDcp_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102414,7 +88665,7 @@ ol.format.OWS.readDcp_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The GET object.
*/
ol.format.OWS.readGet_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102433,7 +88684,7 @@ ol.format.OWS.readGet_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The HTTP object.
*/
ol.format.OWS.readHttp_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102448,7 +88699,7 @@ ol.format.OWS.readHttp_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The operation.
*/
ol.format.OWS.readOperation_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102473,7 +88724,7 @@ ol.format.OWS.readOperation_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The operations metadata.
*/
ol.format.OWS.readOperationsMetadata_ = function(node,
objectStack) {
@@ -102491,7 +88742,7 @@ ol.format.OWS.readOperationsMetadata_ = function(node,
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The phone.
*/
ol.format.OWS.readPhone_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102506,7 +88757,7 @@ ol.format.OWS.readPhone_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The service identification.
*/
ol.format.OWS.readServiceIdentification_ = function(node,
objectStack) {
@@ -102524,7 +88775,7 @@ ol.format.OWS.readServiceIdentification_ = function(node,
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The service contact.
*/
ol.format.OWS.readServiceContact_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102541,7 +88792,7 @@ ol.format.OWS.readServiceContact_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {Object|undefined}
+ * @return {Object|undefined} The service provider.
*/
ol.format.OWS.readServiceProvider_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102558,7 +88809,7 @@ ol.format.OWS.readServiceProvider_ = function(node, objectStack) {
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
- * @return {string|undefined}
+ * @return {string|undefined} The value.
*/
ol.format.OWS.readValue_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -102581,7 +88832,7 @@ ol.format.OWS.NAMESPACE_URIS_ = [
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.PARSERS_ = ol.xml.makeStructureNS(
@@ -102597,7 +88848,7 @@ ol.format.OWS.PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.ADDRESS_PARSERS_ = ol.xml.makeStructureNS(
@@ -102616,7 +88867,7 @@ ol.format.OWS.ADDRESS_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.ALLOWED_VALUES_PARSERS_ = ol.xml.makeStructureNS(
@@ -102627,7 +88878,7 @@ ol.format.OWS.ALLOWED_VALUES_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.CONSTRAINT_PARSERS_ = ol.xml.makeStructureNS(
@@ -102639,7 +88890,7 @@ ol.format.OWS.CONSTRAINT_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.CONTACT_INFO_PARSERS_ = ol.xml.makeStructureNS(
@@ -102651,7 +88902,7 @@ ol.format.OWS.CONTACT_INFO_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.DCP_PARSERS_ = ol.xml.makeStructureNS(
@@ -102662,7 +88913,7 @@ ol.format.OWS.DCP_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.HTTP_PARSERS_ = ol.xml.makeStructureNS(
@@ -102674,7 +88925,7 @@ ol.format.OWS.HTTP_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.OPERATION_PARSERS_ = ol.xml.makeStructureNS(
@@ -102685,7 +88936,7 @@ ol.format.OWS.OPERATION_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.OPERATIONS_METADATA_PARSERS_ = ol.xml.makeStructureNS(
@@ -102696,7 +88947,7 @@ ol.format.OWS.OPERATIONS_METADATA_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.PHONE_PARSERS_ = ol.xml.makeStructureNS(
@@ -102708,7 +88959,7 @@ ol.format.OWS.PHONE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.REQUEST_METHOD_PARSERS_ = ol.xml.makeStructureNS(
@@ -102720,7 +88971,7 @@ ol.format.OWS.REQUEST_METHOD_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.SERVICE_CONTACT_PARSERS_ =
@@ -102736,7 +88987,7 @@ ol.format.OWS.SERVICE_CONTACT_PARSERS_ =
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.SERVICE_IDENTIFICATION_PARSERS_ =
@@ -102751,7 +89002,7 @@ ol.format.OWS.SERVICE_IDENTIFICATION_PARSERS_ =
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.OWS.SERVICE_PROVIDER_PARSERS_ =
@@ -102777,8 +89028,7 @@ goog.require('goog.asserts');
* @param {number=} opt_destOffset Destination offset.
* @return {Array.<number>} Flat coordinates.
*/
-ol.geom.flat.flip.flipXY =
- function(flatCoordinates, offset, end, stride, opt_dest, opt_destOffset) {
+ol.geom.flat.flip.flipXY = function(flatCoordinates, offset, end, stride, opt_dest, opt_destOffset) {
var dest, destOffset;
if (opt_dest !== undefined) {
dest = opt_dest;
@@ -102789,12 +89039,12 @@ ol.geom.flat.flip.flipXY =
dest = [];
destOffset = 0;
}
- var j, k;
- for (j = offset; j < end; ) {
+ var j = offset;
+ while (j < end) {
var x = flatCoordinates[j++];
dest[destOffset++] = flatCoordinates[j++];
dest[destOffset++] = x;
- for (k = 2; k < stride; ++k) {
+ for (var k = 2; k < stride; ++k) {
dest[destOffset++] = flatCoordinates[j++];
}
}
@@ -102816,7 +89066,6 @@ goog.require('ol.geom.flat.inflate');
goog.require('ol.proj');
-
/**
* @classdesc
* Feature format for reading and writing data in the Encoded
@@ -103105,8 +89354,7 @@ ol.format.Polyline.prototype.readFeatures;
/**
* @inheritDoc
*/
-ol.format.Polyline.prototype.readFeaturesFromText =
- function(text, opt_options) {
+ol.format.Polyline.prototype.readFeaturesFromText = function(text, opt_options) {
var feature = this.readFeatureFromText(text, opt_options);
return [feature];
};
@@ -103127,8 +89375,7 @@ ol.format.Polyline.prototype.readGeometry;
/**
* @inheritDoc
*/
-ol.format.Polyline.prototype.readGeometryFromText =
- function(text, opt_options) {
+ol.format.Polyline.prototype.readGeometryFromText = function(text, opt_options) {
var stride = ol.geom.SimpleGeometry.getStrideForLayout(this.geometryLayout_);
var flatCoordinates = ol.format.Polyline.decodeDeltas(
text, stride, this.factor_);
@@ -103172,8 +89419,7 @@ ol.format.Polyline.prototype.writeFeatureText = function(feature, opt_options) {
/**
* @inheritDoc
*/
-ol.format.Polyline.prototype.writeFeaturesText =
- function(features, opt_options) {
+ol.format.Polyline.prototype.writeFeaturesText = function(features, opt_options) {
goog.asserts.assert(features.length == 1,
'features array should have 1 item');
return this.writeFeatureText(features[0], opt_options);
@@ -103195,8 +89441,7 @@ ol.format.Polyline.prototype.writeGeometry;
/**
* @inheritDoc
*/
-ol.format.Polyline.prototype.writeGeometryText =
- function(geometry, opt_options) {
+ol.format.Polyline.prototype.writeGeometryText = function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.LineString,
'geometry should be an ol.geom.LineString');
geometry = /** @type {ol.geom.LineString} */
@@ -103212,7 +89457,6 @@ ol.format.Polyline.prototype.writeGeometryText =
goog.provide('ol.format.TopoJSON');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('ol.Feature');
goog.require('ol.format.Feature');
goog.require('ol.format.JSONFeature');
@@ -103222,10 +89466,10 @@ goog.require('ol.geom.MultiPoint');
goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
+goog.require('ol.object');
goog.require('ol.proj');
-
/**
* @classdesc
* Feature format for reading data in the TopoJSON format.
@@ -103511,7 +89755,7 @@ ol.format.TopoJSON.prototype.readFeaturesFromObject = function(
}
/** @type {Array.<ol.Feature>} */
var features = [];
- var topoJSONFeatures = goog.object.getValues(topoJSONTopology.objects);
+ var topoJSONFeatures = ol.object.getValues(topoJSONTopology.objects);
var i, ii;
var feature;
for (i = 0, ii = topoJSONFeatures.length; i < ii; ++i) {
@@ -103622,18 +89866,25 @@ goog.provide('ol.format.WFS');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
-goog.require('goog.object');
goog.require('ol');
goog.require('ol.format.GML3');
goog.require('ol.format.GMLBase');
+goog.require('ol.format.ogc.filter');
+goog.require('ol.format.ogc.filter.Bbox');
+goog.require('ol.format.ogc.filter.ComparisonBinary');
+goog.require('ol.format.ogc.filter.LogicalBinary');
+goog.require('ol.format.ogc.filter.Not');
+goog.require('ol.format.ogc.filter.IsBetween');
+goog.require('ol.format.ogc.filter.IsNull');
+goog.require('ol.format.ogc.filter.IsLike');
goog.require('ol.format.XMLFeature');
goog.require('ol.format.XSD');
goog.require('ol.geom.Geometry');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.xml');
-
/**
* @classdesc
* Feature format for reading and writing data in the WFS format.
@@ -103696,26 +89947,6 @@ ol.format.WFS.XMLNS = 'http://www.w3.org/2000/xmlns/';
/**
- * Number of features; bounds/extent.
- * @typedef {{numberOfFeatures: number,
- * bounds: ol.Extent}}
- * @api stable
- */
-ol.format.WFS.FeatureCollectionMetadata;
-
-
-/**
- * Total deleted; total inserted; total updated; array of insert ids.
- * @typedef {{totalDeleted: number,
- * totalInserted: number,
- * totalUpdated: number,
- * insertIds: Array.<string>}}
- * @api stable
- */
-ol.format.WFS.TransactionResponse;
-
-
-/**
* @const
* @type {string}
*/
@@ -103743,7 +89974,7 @@ ol.format.WFS.prototype.readFeaturesFromNode = function(node, opt_options) {
'featureType': this.featureType_,
'featureNS': this.featureNS_
};
- goog.object.extend(context, this.getReadOptions(node,
+ ol.object.assign(context, this.getReadOptions(node,
opt_options ? opt_options : {}));
var objectStack = [context];
this.gmlFormat_.FEATURE_COLLECTION_PARSERS[ol.format.GMLBase.GMLNS][
@@ -103763,7 +89994,7 @@ ol.format.WFS.prototype.readFeaturesFromNode = function(node, opt_options) {
* Read transaction response of the source.
*
* @param {Document|Node|Object|string} source Source.
- * @return {ol.format.WFS.TransactionResponse|undefined} Transaction response.
+ * @return {ol.WFSTransactionResponse|undefined} Transaction response.
* @api stable
*/
ol.format.WFS.prototype.readTransactionResponse = function(source) {
@@ -103772,7 +90003,7 @@ ol.format.WFS.prototype.readTransactionResponse = function(source) {
/** @type {Document} */ (source));
} else if (ol.xml.isNode(source)) {
return this.readTransactionResponseFromNode(/** @type {Node} */ (source));
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
return this.readTransactionResponseFromDocument(doc);
} else {
@@ -103786,7 +90017,7 @@ ol.format.WFS.prototype.readTransactionResponse = function(source) {
* Read feature collection metadata of the source.
*
* @param {Document|Node|Object|string} source Source.
- * @return {ol.format.WFS.FeatureCollectionMetadata|undefined}
+ * @return {ol.WFSFeatureCollectionMetadata|undefined}
* FeatureCollection metadata.
* @api stable
*/
@@ -103797,7 +90028,7 @@ ol.format.WFS.prototype.readFeatureCollectionMetadata = function(source) {
} else if (ol.xml.isNode(source)) {
return this.readFeatureCollectionMetadataFromNode(
/** @type {Node} */ (source));
- } else if (goog.isString(source)) {
+ } else if (typeof source === 'string') {
var doc = ol.xml.parse(source);
return this.readFeatureCollectionMetadataFromDocument(doc);
} else {
@@ -103809,11 +90040,10 @@ ol.format.WFS.prototype.readFeatureCollectionMetadata = function(source) {
/**
* @param {Document} doc Document.
- * @return {ol.format.WFS.FeatureCollectionMetadata|undefined}
+ * @return {ol.WFSFeatureCollectionMetadata|undefined}
* FeatureCollection metadata.
*/
-ol.format.WFS.prototype.readFeatureCollectionMetadataFromDocument =
- function(doc) {
+ol.format.WFS.prototype.readFeatureCollectionMetadataFromDocument = function(doc) {
goog.asserts.assert(doc.nodeType == goog.dom.NodeType.DOCUMENT,
'doc.nodeType should be DOCUMENT');
for (var n = doc.firstChild; n; n = n.nextSibling) {
@@ -103827,7 +90057,7 @@ ol.format.WFS.prototype.readFeatureCollectionMetadataFromDocument =
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WFS.FEATURE_COLLECTION_PARSERS_ = {
@@ -103840,7 +90070,7 @@ ol.format.WFS.FEATURE_COLLECTION_PARSERS_ = {
/**
* @param {Node} node Node.
- * @return {ol.format.WFS.FeatureCollectionMetadata|undefined}
+ * @return {ol.WFSFeatureCollectionMetadata|undefined}
* FeatureCollection metadata.
*/
ol.format.WFS.prototype.readFeatureCollectionMetadataFromNode = function(node) {
@@ -103853,14 +90083,14 @@ ol.format.WFS.prototype.readFeatureCollectionMetadataFromNode = function(node) {
node.getAttribute('numberOfFeatures'));
result['numberOfFeatures'] = value;
return ol.xml.pushParseAndPop(
- /** @type {ol.format.WFS.FeatureCollectionMetadata} */ (result),
+ /** @type {ol.WFSFeatureCollectionMetadata} */ (result),
ol.format.WFS.FEATURE_COLLECTION_PARSERS_, node, [], this.gmlFormat_);
};
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WFS.TRANSACTION_SUMMARY_PARSERS_ = {
@@ -103889,7 +90119,7 @@ ol.format.WFS.readTransactionSummary_ = function(node, objectStack) {
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WFS.OGC_FID_PARSERS_ = {
@@ -103913,7 +90143,7 @@ ol.format.WFS.fidParser_ = function(node, objectStack) {
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WFS.INSERT_RESULTS_PARSERS_ = {
@@ -103937,7 +90167,7 @@ ol.format.WFS.readInsertResults_ = function(node, objectStack) {
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WFS.TRANSACTION_RESPONSE_PARSERS_ = {
@@ -103952,7 +90182,7 @@ ol.format.WFS.TRANSACTION_RESPONSE_PARSERS_ = {
/**
* @param {Document} doc Document.
- * @return {ol.format.WFS.TransactionResponse|undefined} Transaction response.
+ * @return {ol.WFSTransactionResponse|undefined} Transaction response.
*/
ol.format.WFS.prototype.readTransactionResponseFromDocument = function(doc) {
goog.asserts.assert(doc.nodeType == goog.dom.NodeType.DOCUMENT,
@@ -103968,7 +90198,7 @@ ol.format.WFS.prototype.readTransactionResponseFromDocument = function(doc) {
/**
* @param {Node} node Node.
- * @return {ol.format.WFS.TransactionResponse|undefined} Transaction response.
+ * @return {ol.WFSTransactionResponse|undefined} Transaction response.
*/
ol.format.WFS.prototype.readTransactionResponseFromNode = function(node) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
@@ -103976,13 +90206,13 @@ ol.format.WFS.prototype.readTransactionResponseFromNode = function(node) {
goog.asserts.assert(node.localName == 'TransactionResponse',
'localName should be TransactionResponse');
return ol.xml.pushParseAndPop(
- /** @type {ol.format.WFS.TransactionResponse} */({}),
+ /** @type {ol.WFSTransactionResponse} */({}),
ol.format.WFS.TRANSACTION_RESPONSE_PARSERS_, node, []);
};
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.WFS.QUERY_SERIALIZERS_ = {
@@ -104033,6 +90263,7 @@ ol.format.WFS.writeOgcFidFilter_ = function(node, fid, objectStack) {
ol.format.WFS.writeDelete_ = function(node, feature, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
+ goog.asserts.assert(feature.getId() !== undefined, 'feature should have an id');
var featureType = context['featureType'];
var featurePrefix = context['featurePrefix'];
featurePrefix = featurePrefix ? featurePrefix :
@@ -104042,7 +90273,7 @@ ol.format.WFS.writeDelete_ = function(node, feature, objectStack) {
ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
featureNS);
var fid = feature.getId();
- if (fid) {
+ if (fid !== undefined) {
ol.format.WFS.writeOgcFidFilter_(node, fid, objectStack);
}
};
@@ -104057,6 +90288,7 @@ ol.format.WFS.writeDelete_ = function(node, feature, objectStack) {
ol.format.WFS.writeUpdate_ = function(node, feature, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
+ goog.asserts.assert(feature.getId() !== undefined, 'feature should have an id');
var featureType = context['featureType'];
var featurePrefix = context['featurePrefix'];
featurePrefix = featurePrefix ? featurePrefix :
@@ -104066,7 +90298,7 @@ ol.format.WFS.writeUpdate_ = function(node, feature, objectStack) {
ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
featureNS);
var fid = feature.getId();
- if (fid) {
+ if (fid !== undefined) {
var keys = feature.getKeys();
var values = [];
for (var i = 0, ii = keys.length; i < ii; i++) {
@@ -104129,7 +90361,7 @@ ol.format.WFS.writeNative_ = function(node, nativeElement, objectStack) {
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.WFS.TRANSACTION_SERIALIZERS_ = {
@@ -104165,60 +90397,216 @@ ol.format.WFS.writeQuery_ = function(node, featureType, objectStack) {
ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
featureNS);
}
- var item = goog.object.clone(context);
+ var item = ol.object.assign({}, context);
item.node = node;
ol.xml.pushSerializeAndPop(item,
ol.format.WFS.QUERY_SERIALIZERS_,
ol.xml.makeSimpleNodeFactory('PropertyName'), propertyNames,
objectStack);
- var bbox = context['bbox'];
- if (bbox) {
+ var filter = context['filter'];
+ if (filter) {
var child = ol.xml.createElementNS('http://www.opengis.net/ogc', 'Filter');
- ol.format.WFS.writeOgcBBOX_(child, bbox, objectStack);
node.appendChild(child);
+ ol.format.WFS.writeFilterCondition_(child, filter, objectStack);
}
};
/**
* @param {Node} node Node.
- * @param {string} value PropertyName value.
+ * @param {ol.format.ogc.filter.Filter} filter Filter.
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.WFS.writeOgcPropertyName_ = function(node, value, objectStack) {
- var property = ol.xml.createElementNS('http://www.opengis.net/ogc',
- 'PropertyName');
- ol.format.XSD.writeStringTextNode(property, value);
- node.appendChild(property);
+ol.format.WFS.writeFilterCondition_ = function(node, filter, objectStack) {
+ var item = {node: node};
+ ol.xml.pushSerializeAndPop(item,
+ ol.format.WFS.GETFEATURE_SERIALIZERS_,
+ ol.xml.makeSimpleNodeFactory(filter.getTagName()),
+ [filter], objectStack);
};
/**
* @param {Node} node Node.
- * @param {ol.Extent} bbox Bounding box.
+ * @param {ol.format.ogc.filter.Filter} filter Filter.
* @param {Array.<*>} objectStack Node stack.
* @private
*/
-ol.format.WFS.writeOgcBBOX_ = function(node, bbox, objectStack) {
+ol.format.WFS.writeBboxFilter_ = function(node, filter, objectStack) {
+ goog.asserts.assertInstanceof(filter, ol.format.ogc.filter.Bbox,
+ 'must be bbox filter');
+
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
- var geometryName = context['geometryName'];
- var bboxNode = ol.xml.createElementNS('http://www.opengis.net/ogc', 'BBOX');
- node.appendChild(bboxNode);
- ol.format.WFS.writeOgcPropertyName_(bboxNode, geometryName, objectStack);
- ol.format.GML3.prototype.writeGeometryElement(bboxNode, bbox, objectStack);
+ context.srsName = filter.srsName;
+
+ ol.format.WFS.writeOgcPropertyName_(node, filter.geometryName);
+ ol.format.GML3.prototype.writeGeometryElement(node, filter.extent, objectStack);
+};
+
+
+/**
+ * @param {Node} node Node.
+ * @param {ol.format.ogc.filter.Filter} filter Filter.
+ * @param {Array.<*>} objectStack Node stack.
+ * @private
+ */
+ol.format.WFS.writeLogicalFilter_ = function(node, filter, objectStack) {
+ goog.asserts.assertInstanceof(filter, ol.format.ogc.filter.LogicalBinary,
+ 'must be logical filter');
+ var item = {node: node};
+ var conditionA = filter.conditionA;
+ ol.xml.pushSerializeAndPop(item,
+ ol.format.WFS.GETFEATURE_SERIALIZERS_,
+ ol.xml.makeSimpleNodeFactory(conditionA.getTagName()),
+ [conditionA], objectStack);
+ var conditionB = filter.conditionB;
+ ol.xml.pushSerializeAndPop(item,
+ ol.format.WFS.GETFEATURE_SERIALIZERS_,
+ ol.xml.makeSimpleNodeFactory(conditionB.getTagName()),
+ [conditionB], objectStack);
};
/**
- * @type {Object.<string, Object.<string, ol.xml.Serializer>>}
+ * @param {Node} node Node.
+ * @param {ol.format.ogc.filter.Filter} filter Filter.
+ * @param {Array.<*>} objectStack Node stack.
+ * @private
+ */
+ol.format.WFS.writeNotFilter_ = function(node, filter, objectStack) {
+ goog.asserts.assertInstanceof(filter, ol.format.ogc.filter.Not,
+ 'must be Not filter');
+ var item = {node: node};
+ var condition = filter.condition;
+ ol.xml.pushSerializeAndPop(item,
+ ol.format.WFS.GETFEATURE_SERIALIZERS_,
+ ol.xml.makeSimpleNodeFactory(condition.getTagName()),
+ [condition], objectStack);
+};
+
+
+/**
+ * @param {Node} node Node.
+ * @param {ol.format.ogc.filter.Filter} filter Filter.
+ * @param {Array.<*>} objectStack Node stack.
+ * @private
+ */
+ol.format.WFS.writeComparisonFilter_ = function(node, filter, objectStack) {
+ goog.asserts.assertInstanceof(filter, ol.format.ogc.filter.ComparisonBinary,
+ 'must be binary comparison filter');
+ if (filter.matchCase !== undefined) {
+ node.setAttribute('matchCase', filter.matchCase.toString());
+ }
+ ol.format.WFS.writeOgcPropertyName_(node, filter.propertyName);
+ ol.format.WFS.writeOgcLiteral_(node, '' + filter.expression);
+};
+
+
+/**
+ * @param {Node} node Node.
+ * @param {ol.format.ogc.filter.Filter} filter Filter.
+ * @param {Array.<*>} objectStack Node stack.
+ * @private
+ */
+ol.format.WFS.writeIsNullFilter_ = function(node, filter, objectStack) {
+ goog.asserts.assertInstanceof(filter, ol.format.ogc.filter.IsNull,
+ 'must be IsNull comparison filter');
+ ol.format.WFS.writeOgcPropertyName_(node, filter.propertyName);
+};
+
+
+/**
+ * @param {Node} node Node.
+ * @param {ol.format.ogc.filter.Filter} filter Filter.
+ * @param {Array.<*>} objectStack Node stack.
+ * @private
+ */
+ol.format.WFS.writeIsBetweenFilter_ = function(node, filter, objectStack) {
+ goog.asserts.assertInstanceof(filter, ol.format.ogc.filter.IsBetween,
+ 'must be IsBetween comparison filter');
+ ol.format.WFS.writeOgcPropertyName_(node, filter.propertyName);
+ ol.format.WFS.writeOgcExpression_('LowerBoundary', node, '' + filter.lowerBoundary);
+ ol.format.WFS.writeOgcExpression_('UpperBoundary', node, '' + filter.upperBoundary);
+};
+
+
+/**
+ * @param {Node} node Node.
+ * @param {ol.format.ogc.filter.Filter} filter Filter.
+ * @param {Array.<*>} objectStack Node stack.
+ * @private
+ */
+ol.format.WFS.writeIsLikeFilter_ = function(node, filter, objectStack) {
+ goog.asserts.assertInstanceof(filter, ol.format.ogc.filter.IsLike,
+ 'must be IsLike comparison filter');
+ node.setAttribute('wildCard', filter.wildCard);
+ node.setAttribute('singleChar', filter.singleChar);
+ node.setAttribute('escapeChar', filter.escapeChar);
+ if (filter.matchCase !== undefined) {
+ node.setAttribute('matchCase', filter.matchCase.toString());
+ }
+ ol.format.WFS.writeOgcPropertyName_(node, filter.propertyName);
+ ol.format.WFS.writeOgcLiteral_(node, '' + filter.pattern);
+};
+
+
+/**
+ * @param {string} tagName Tag name.
+ * @param {Node} node Node.
+ * @param {string} value Value.
+ * @private
+ */
+ol.format.WFS.writeOgcExpression_ = function(tagName, node, value) {
+ var property = ol.xml.createElementNS('http://www.opengis.net/ogc', tagName);
+ ol.format.XSD.writeStringTextNode(property, value);
+ node.appendChild(property);
+};
+
+
+/**
+ * @param {Node} node Node.
+ * @param {string} value PropertyName value.
+ * @private
+ */
+ol.format.WFS.writeOgcPropertyName_ = function(node, value) {
+ ol.format.WFS.writeOgcExpression_('PropertyName', node, value);
+};
+
+
+/**
+ * @param {Node} node Node.
+ * @param {string} value PropertyName value.
+ * @private
+ */
+ol.format.WFS.writeOgcLiteral_ = function(node, value) {
+ ol.format.WFS.writeOgcExpression_('Literal', node, value);
+};
+
+
+/**
+ * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
* @private
*/
ol.format.WFS.GETFEATURE_SERIALIZERS_ = {
'http://www.opengis.net/wfs': {
- 'Query': ol.xml.makeChildAppender(
- ol.format.WFS.writeQuery_)
+ 'Query': ol.xml.makeChildAppender(ol.format.WFS.writeQuery_)
+ },
+ 'http://www.opengis.net/ogc': {
+ 'And': ol.xml.makeChildAppender(ol.format.WFS.writeLogicalFilter_),
+ 'Or': ol.xml.makeChildAppender(ol.format.WFS.writeLogicalFilter_),
+ 'Not': ol.xml.makeChildAppender(ol.format.WFS.writeNotFilter_),
+ 'BBOX': ol.xml.makeChildAppender(ol.format.WFS.writeBboxFilter_),
+ 'PropertyIsEqualTo': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
+ 'PropertyIsNotEqualTo': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
+ 'PropertyIsLessThan': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
+ 'PropertyIsLessThanOrEqualTo': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
+ 'PropertyIsGreaterThan': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
+ 'PropertyIsGreaterThanOrEqualTo': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
+ 'PropertyIsNull': ol.xml.makeChildAppender(ol.format.WFS.writeIsNullFilter_),
+ 'PropertyIsBetween': ol.xml.makeChildAppender(ol.format.WFS.writeIsBetweenFilter_),
+ 'PropertyIsLike': ol.xml.makeChildAppender(ol.format.WFS.writeIsLikeFilter_)
}
};
@@ -104232,7 +90620,7 @@ ol.format.WFS.GETFEATURE_SERIALIZERS_ = {
ol.format.WFS.writeGetFeature_ = function(node, featureTypes, objectStack) {
var context = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isObject(context), 'context should be an Object');
- var item = goog.object.clone(context);
+ var item = ol.object.assign({}, context);
item.node = node;
ol.xml.pushSerializeAndPop(item,
ol.format.WFS.GETFEATURE_SERIALIZERS_,
@@ -104253,6 +90641,7 @@ ol.format.WFS.prototype.writeGetFeature = function(options) {
'GetFeature');
node.setAttribute('service', 'WFS');
node.setAttribute('version', '1.1.0');
+ var filter;
if (options) {
if (options.handle) {
node.setAttribute('handle', options.handle);
@@ -104272,6 +90661,19 @@ ol.format.WFS.prototype.writeGetFeature = function(options) {
if (options.count !== undefined) {
node.setAttribute('count', options.count);
}
+ filter = options.filter;
+ if (options.bbox) {
+ goog.asserts.assert(options.geometryName,
+ 'geometryName must be set when using bbox filter');
+ var bbox = ol.format.ogc.filter.bbox(
+ options.geometryName, options.bbox, options.srsName);
+ if (filter) {
+ // if bbox and filter are both set, combine the two into a single filter
+ filter = ol.format.ogc.filter.and(filter, bbox);
+ } else {
+ filter = bbox;
+ }
+ }
}
ol.xml.setAttributeNS(node, 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation', this.schemaLocation_);
@@ -104281,10 +90683,10 @@ ol.format.WFS.prototype.writeGetFeature = function(options) {
featureNS: options.featureNS ? options.featureNS : this.featureNS_,
featurePrefix: options.featurePrefix,
geometryName: options.geometryName,
- bbox: options.bbox,
+ filter: filter,
propertyNames: options.propertyNames ? options.propertyNames : []
};
- goog.asserts.assert(goog.isArray(options.featureTypes),
+ goog.asserts.assert(Array.isArray(options.featureTypes),
'options.featureTypes should be an array');
ol.format.WFS.writeGetFeature_(node, options.featureTypes, [context]);
return node;
@@ -104320,7 +90722,7 @@ ol.format.WFS.prototype.writeTransaction = function(inserts, updates, deletes,
if (inserts) {
obj = {node: node, featureNS: options.featureNS,
featureType: options.featureType, featurePrefix: options.featurePrefix};
- goog.object.extend(obj, baseObj);
+ ol.object.assign(obj, baseObj);
ol.xml.pushSerializeAndPop(obj,
ol.format.WFS.TRANSACTION_SERIALIZERS_,
ol.xml.makeSimpleNodeFactory('Insert'), inserts,
@@ -104329,7 +90731,7 @@ ol.format.WFS.prototype.writeTransaction = function(inserts, updates, deletes,
if (updates) {
obj = {node: node, featureNS: options.featureNS,
featureType: options.featureType, featurePrefix: options.featurePrefix};
- goog.object.extend(obj, baseObj);
+ ol.object.assign(obj, baseObj);
ol.xml.pushSerializeAndPop(obj,
ol.format.WFS.TRANSACTION_SERIALIZERS_,
ol.xml.makeSimpleNodeFactory('Update'), updates,
@@ -104423,7 +90825,6 @@ goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
-
/**
* @classdesc
* Geometry format for reading and writing data in the `WellKnownText` (WKT)
@@ -104775,12 +91176,6 @@ ol.format.WKT.prototype.writeGeometryText = function(geometry, opt_options) {
/**
- * @typedef {{type: number, value: (number|string|undefined), position: number}}
- */
-ol.format.WKT.Token;
-
-
-/**
* @const
* @enum {number}
*/
@@ -104794,7 +91189,6 @@ ol.format.WKT.TokenType = {
};
-
/**
* Class to tokenize a WKT string.
* @param {string} wkt WKT string.
@@ -104860,7 +91254,7 @@ ol.format.WKT.Lexer.prototype.nextChar_ = function() {
/**
* Fetch and return the next token.
- * @return {!ol.format.WKT.Token} Next string token.
+ * @return {!ol.WKTToken} Next string token.
*/
ol.format.WKT.Lexer.prototype.nextToken = function() {
var c = this.nextChar_();
@@ -104931,10 +91325,9 @@ ol.format.WKT.Lexer.prototype.readText_ = function() {
};
-
/**
* Class to parse the tokens from the WKT string.
- * @param {ol.format.WKT.Lexer} lexer
+ * @param {ol.format.WKT.Lexer} lexer The lexer.
* @constructor
* @protected
*/
@@ -104947,7 +91340,7 @@ ol.format.WKT.Parser = function(lexer) {
this.lexer_ = lexer;
/**
- * @type {ol.format.WKT.Token}
+ * @type {ol.WKTToken}
* @private
*/
this.token_;
@@ -104971,7 +91364,7 @@ ol.format.WKT.Parser.prototype.consume_ = function() {
/**
* If the given type matches the current token, consume it.
- * @param {ol.format.WKT.TokenType.<number>} type Token type.
+ * @param {ol.format.WKT.TokenType} type Token type.
* @return {boolean} Whether the token matches the given type.
*/
ol.format.WKT.Parser.prototype.match = function(type) {
@@ -105248,7 +91641,7 @@ ol.format.WKT.Parser.prototype.formatErrorMessage_ = function() {
/**
- * @enum {function (new:ol.geom.Geometry, Array, ol.geom.GeometryLayout.<string>=)}
+ * @enum {function (new:ol.geom.Geometry, Array, ol.geom.GeometryLayout)}
* @private
*/
ol.format.WKT.Parser.GeometryConstructor_ = {
@@ -105278,7 +91671,6 @@ goog.provide('ol.format.WMSCapabilities');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
-goog.require('goog.object');
goog.require('ol');
goog.require('ol.format.XLink');
goog.require('ol.format.XML');
@@ -105286,7 +91678,6 @@ goog.require('ol.format.XSD');
goog.require('ol.xml');
-
/**
* @classdesc
* Format for reading WMS capabilities data
@@ -105407,8 +91798,7 @@ ol.format.WMSCapabilities.readBoundingBox_ = function(node, objectStack) {
* @param {Array.<*>} objectStack Object stack.
* @return {ol.Extent|undefined} Bounding box object.
*/
-ol.format.WMSCapabilities.readEXGeographicBoundingBox_ =
- function(node, objectStack) {
+ol.format.WMSCapabilities.readEXGeographicBoundingBox_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'EX_GeographicBoundingBox',
@@ -105432,10 +91822,10 @@ ol.format.WMSCapabilities.readEXGeographicBoundingBox_ =
eastBoundLongitude === undefined || northBoundLatitude === undefined) {
return undefined;
}
- return /** @type {ol.Extent} */ ([
+ return [
westBoundLongitude, southBoundLatitude,
eastBoundLongitude, northBoundLatitude
- ]);
+ ];
};
@@ -105477,8 +91867,7 @@ ol.format.WMSCapabilities.readService_ = function(node, objectStack) {
* @private
* @return {Object|undefined} Contact information object.
*/
-ol.format.WMSCapabilities.readContactInformation_ =
- function(node, objectStack) {
+ol.format.WMSCapabilities.readContactInformation_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType shpuld be ELEMENT');
goog.asserts.assert(node.localName == 'ContactInformation',
@@ -105495,8 +91884,7 @@ ol.format.WMSCapabilities.readContactInformation_ =
* @private
* @return {Object|undefined} Contact person object.
*/
-ol.format.WMSCapabilities.readContactPersonPrimary_ =
- function(node, objectStack) {
+ol.format.WMSCapabilities.readContactPersonPrimary_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'ContactPersonPrimary',
@@ -105513,8 +91901,7 @@ ol.format.WMSCapabilities.readContactPersonPrimary_ =
* @private
* @return {Object|undefined} Contact address object.
*/
-ol.format.WMSCapabilities.readContactAddress_ =
- function(node, objectStack) {
+ol.format.WMSCapabilities.readContactAddress_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'ContactAddress',
@@ -105569,8 +91956,8 @@ ol.format.WMSCapabilities.readLayer_ = function(node, objectStack) {
var parentLayerObject = /** @type {Object.<string,*>} */
(objectStack[objectStack.length - 1]);
- var layerObject = /** @type {Object.<string,*>} */ (ol.xml.pushParseAndPop(
- {}, ol.format.WMSCapabilities.LAYER_PARSERS_, node, objectStack));
+ var layerObject = ol.xml.pushParseAndPop(
+ {}, ol.format.WMSCapabilities.LAYER_PARSERS_, node, objectStack);
if (!layerObject) {
return undefined;
@@ -105620,9 +92007,8 @@ ol.format.WMSCapabilities.readLayer_ = function(node, objectStack) {
var addKeys = ['Style', 'CRS', 'AuthorityURL'];
addKeys.forEach(function(key) {
if (key in parentLayerObject) {
- var childValue = goog.object.setIfUndefined(layerObject, key, []);
- childValue = childValue.concat(parentLayerObject[key]);
- layerObject[key] = childValue;
+ var childValue = layerObject[key] || [];
+ layerObject[key] = childValue.concat(parentLayerObject[key]);
}
});
@@ -105672,8 +92058,7 @@ ol.format.WMSCapabilities.readDimension_ = function(node, objectStack) {
* @param {Array.<*>} objectStack Object stack.
* @return {Object|undefined} Online resource object.
*/
-ol.format.WMSCapabilities.readFormatOnlineresource_ =
- function(node, objectStack) {
+ol.format.WMSCapabilities.readFormatOnlineresource_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
return ol.xml.pushParseAndPop(
@@ -105749,8 +92134,7 @@ ol.format.WMSCapabilities.readOperationType_ = function(node, objectStack) {
* @param {Array.<*>} objectStack Object stack.
* @return {Object|undefined} Online resource object.
*/
-ol.format.WMSCapabilities.readSizedFormatOnlineresource_ =
- function(node, objectStack) {
+ol.format.WMSCapabilities.readSizedFormatOnlineresource_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
var formatOnlineresource =
@@ -105853,7 +92237,7 @@ ol.format.WMSCapabilities.NAMESPACE_URIS_ = [
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.PARSERS_ = ol.xml.makeStructureNS(
@@ -105867,7 +92251,7 @@ ol.format.WMSCapabilities.PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.CAPABILITY_PARSERS_ = ol.xml.makeStructureNS(
@@ -105883,7 +92267,7 @@ ol.format.WMSCapabilities.CAPABILITY_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.SERVICE_PARSERS_ = ol.xml.makeStructureNS(
@@ -105911,7 +92295,7 @@ ol.format.WMSCapabilities.SERVICE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.CONTACT_INFORMATION_PARSERS_ = ol.xml.makeStructureNS(
@@ -105933,7 +92317,7 @@ ol.format.WMSCapabilities.CONTACT_INFORMATION_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.CONTACT_PERSON_PARSERS_ = ol.xml.makeStructureNS(
@@ -105947,7 +92331,7 @@ ol.format.WMSCapabilities.CONTACT_PERSON_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.CONTACT_ADDRESS_PARSERS_ = ol.xml.makeStructureNS(
@@ -105964,7 +92348,7 @@ ol.format.WMSCapabilities.CONTACT_ADDRESS_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.EXCEPTION_PARSERS_ = ol.xml.makeStructureNS(
@@ -105975,7 +92359,7 @@ ol.format.WMSCapabilities.EXCEPTION_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.LAYER_PARSERS_ = ol.xml.makeStructureNS(
@@ -106016,7 +92400,7 @@ ol.format.WMSCapabilities.LAYER_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.ATTRIBUTION_PARSERS_ = ol.xml.makeStructureNS(
@@ -106031,7 +92415,7 @@ ol.format.WMSCapabilities.ATTRIBUTION_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.EX_GEOGRAPHIC_BOUNDING_BOX_PARSERS_ =
@@ -106049,7 +92433,7 @@ ol.format.WMSCapabilities.EX_GEOGRAPHIC_BOUNDING_BOX_PARSERS_ =
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.REQUEST_PARSERS_ = ol.xml.makeStructureNS(
@@ -106065,7 +92449,7 @@ ol.format.WMSCapabilities.REQUEST_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.OPERATIONTYPE_PARSERS_ = ol.xml.makeStructureNS(
@@ -106078,7 +92462,7 @@ ol.format.WMSCapabilities.OPERATIONTYPE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.DCPTYPE_PARSERS_ = ol.xml.makeStructureNS(
@@ -106090,7 +92474,7 @@ ol.format.WMSCapabilities.DCPTYPE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.HTTP_PARSERS_ = ol.xml.makeStructureNS(
@@ -106104,7 +92488,7 @@ ol.format.WMSCapabilities.HTTP_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.STYLE_PARSERS_ = ol.xml.makeStructureNS(
@@ -106123,7 +92507,7 @@ ol.format.WMSCapabilities.STYLE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.FORMAT_ONLINERESOURCE_PARSERS_ =
@@ -106136,7 +92520,7 @@ ol.format.WMSCapabilities.FORMAT_ONLINERESOURCE_PARSERS_ =
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMSCapabilities.KEYWORDLIST_PARSERS_ = ol.xml.makeStructureNS(
@@ -106146,16 +92530,15 @@ ol.format.WMSCapabilities.KEYWORDLIST_PARSERS_ = ol.xml.makeStructureNS(
goog.provide('ol.format.WMSGetFeatureInfo');
-goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
-goog.require('goog.object');
+goog.require('ol.array');
goog.require('ol.format.GML2');
goog.require('ol.format.XMLFeature');
+goog.require('ol.object');
goog.require('ol.xml');
-
/**
* @classdesc
* Format for reading WMSGetFeatureInfo format. It uses
@@ -106163,9 +92546,12 @@ goog.require('ol.xml');
*
* @constructor
* @extends {ol.format.XMLFeature}
+ * @param {olx.format.WMSGetFeatureInfoOptions=} opt_options Options.
* @api
*/
-ol.format.WMSGetFeatureInfo = function() {
+ol.format.WMSGetFeatureInfo = function(opt_options) {
+
+ var options = opt_options ? opt_options : {};
/**
* @private
@@ -106180,6 +92566,13 @@ ol.format.WMSGetFeatureInfo = function() {
*/
this.gmlFormat_ = new ol.format.GML2();
+
+ /**
+ * @private
+ * @type {Array.<string>}
+ */
+ this.layers_ = options.layers ? options.layers : null;
+
goog.base(this);
};
goog.inherits(ol.format.WMSGetFeatureInfo, ol.format.XMLFeature);
@@ -106207,13 +92600,12 @@ ol.format.WMSGetFeatureInfo.layerIdentifier_ = '_layer';
* @return {Array.<ol.Feature>} Features.
* @private
*/
-ol.format.WMSGetFeatureInfo.prototype.readFeatures_ =
- function(node, objectStack) {
+ol.format.WMSGetFeatureInfo.prototype.readFeatures_ = function(node, objectStack) {
- node.namespaceURI = this.featureNS_;
+ node.setAttribute('namespaceURI', this.featureNS_);
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT,
'node.nodeType should be ELEMENT');
- var localName = ol.xml.getLocalName(node);
+ var localName = node.localName;
/** @type {Array.<ol.Feature>} */
var features = [];
if (node.childNodes.length === 0) {
@@ -106234,7 +92626,13 @@ ol.format.WMSGetFeatureInfo.prototype.readFeatures_ =
'localName of layer node should match layerIdentifier');
var toRemove = ol.format.WMSGetFeatureInfo.layerIdentifier_;
- var featureType = layer.localName.replace(toRemove, '') +
+ var layerName = layer.localName.replace(toRemove, '');
+
+ if (this.layers_ && !ol.array.includes(this.layers_, layerName)) {
+ continue;
+ }
+
+ var featureType = layerName +
ol.format.WMSGetFeatureInfo.featureIdentifier_;
context['featureType'] = featureType;
@@ -106245,11 +92643,11 @@ ol.format.WMSGetFeatureInfo.prototype.readFeatures_ =
this.gmlFormat_.readFeatureElement, this.gmlFormat_);
var parsersNS = ol.xml.makeStructureNS(
[context['featureNS'], null], parsers);
- layer.namespaceURI = this.featureNS_;
+ layer.setAttribute('namespaceURI', this.featureNS_);
var layerFeatures = ol.xml.pushParseAndPop(
[], parsersNS, layer, objectStack, this.gmlFormat_);
if (layerFeatures) {
- goog.array.extend(features, layerFeatures);
+ ol.array.extend(features, layerFeatures);
}
}
}
@@ -106280,14 +92678,10 @@ ol.format.WMSGetFeatureInfo.prototype.readFeatures;
/**
* @inheritDoc
*/
-ol.format.WMSGetFeatureInfo.prototype.readFeaturesFromNode =
- function(node, opt_options) {
- var options = {
- 'featureType': this.featureType,
- 'featureNS': this.featureNS
- };
+ol.format.WMSGetFeatureInfo.prototype.readFeaturesFromNode = function(node, opt_options) {
+ var options = {};
if (opt_options) {
- goog.object.extend(options, this.getReadOptions(node, opt_options));
+ ol.object.assign(options, this.getReadOptions(node, opt_options));
}
return this.readFeatures_(node, [options]);
};
@@ -106304,7 +92698,6 @@ goog.require('ol.format.XSD');
goog.require('ol.xml');
-
/**
* @classdesc
* Format for reading WMTS capabilities data.
@@ -106361,13 +92754,13 @@ ol.format.WMTSCapabilities.prototype.readFromNode = function(node) {
'node.nodeType should be ELEMENT');
goog.asserts.assert(node.localName == 'Capabilities',
'localName should be Capabilities');
- this.version = node.getAttribute('version').trim();
- goog.asserts.assertString(this.version, 'this.version should be a string');
+ var version = node.getAttribute('version').trim();
+ goog.asserts.assertString(version, 'version should be a string');
var WMTSCapabilityObject = this.owsParser_.readFromNode(node);
if (!WMTSCapabilityObject) {
return null;
}
- WMTSCapabilityObject['version'] = this.version;
+ WMTSCapabilityObject['version'] = version;
WMTSCapabilityObject = ol.xml.pushParseAndPop(WMTSCapabilityObject,
ol.format.WMTSCapabilities.PARSERS_, node, []);
return WMTSCapabilityObject ? WMTSCapabilityObject : null;
@@ -106572,7 +92965,7 @@ ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_ = [
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.PARSERS_ = ol.xml.makeStructureNS(
@@ -106584,7 +92977,7 @@ ol.format.WMTSCapabilities.PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.CONTENTS_PARSERS_ = ol.xml.makeStructureNS(
@@ -106598,7 +92991,7 @@ ol.format.WMTSCapabilities.CONTENTS_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.LAYER_PARSERS_ = ol.xml.makeStructureNS(
@@ -106627,7 +93020,7 @@ ol.format.WMTSCapabilities.LAYER_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.STYLE_PARSERS_ = ol.xml.makeStructureNS(
@@ -106644,7 +93037,7 @@ ol.format.WMTSCapabilities.STYLE_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.TMS_LINKS_PARSERS_ = ol.xml.makeStructureNS(
@@ -106656,7 +93049,7 @@ ol.format.WMTSCapabilities.TMS_LINKS_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.DIMENSION_PARSERS_ = ol.xml.makeStructureNS(
@@ -106673,7 +93066,7 @@ ol.format.WMTSCapabilities.DIMENSION_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.WGS84_BBOX_READERS_ = ol.xml.makeStructureNS(
@@ -106687,7 +93080,7 @@ ol.format.WMTSCapabilities.WGS84_BBOX_READERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.TMS_PARSERS_ = ol.xml.makeStructureNS(
@@ -106706,7 +93099,7 @@ ol.format.WMTSCapabilities.TMS_PARSERS_ = ol.xml.makeStructureNS(
/**
* @const
- * @type {Object.<string, Object.<string, ol.xml.Parser>>}
+ * @type {Object.<string, Object.<string, ol.XmlParser>>}
* @private
*/
ol.format.WMTSCapabilities.TM_PARSERS_ = ol.xml.makeStructureNS(
@@ -106728,26 +93121,13 @@ ol.format.WMTSCapabilities.TM_PARSERS_ = ol.xml.makeStructureNS(
ol.format.XSD.readString)
}));
-goog.provide('ol.sphere.WGS84');
-
-goog.require('ol.Sphere');
-
-
-/**
- * A sphere with radius equal to the semi-major axis of the WGS84 ellipsoid.
- * @const
- * @type {ol.Sphere}
- */
-ol.sphere.WGS84 = new ol.Sphere(6378137);
-
// FIXME handle geolocation not supported
goog.provide('ol.Geolocation');
goog.provide('ol.GeolocationProperty');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('ol.Coordinate');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.Object');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.Polygon');
@@ -106774,7 +93154,6 @@ ol.GeolocationProperty = {
};
-
/**
* @classdesc
* Helper class for providing HTML5 Geolocation capabilities.
@@ -106795,6 +93174,7 @@ ol.GeolocationProperty = {
* window.console.log(geolocation.getPosition());
* });
*
+ * @fires error
* @constructor
* @extends {ol.Object}
* @param {olx.GeolocationOptions=} opt_options Options.
@@ -106825,12 +93205,12 @@ ol.Geolocation = function(opt_options) {
*/
this.watchId_ = undefined;
- goog.events.listen(
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.GeolocationProperty.PROJECTION),
- this.handleProjectionChanged_, false, this);
- goog.events.listen(
+ this.handleProjectionChanged_, this);
+ ol.events.listen(
this, ol.Object.getChangeEventType(ol.GeolocationProperty.TRACKING),
- this.handleTrackingChanged_, false, this);
+ this.handleTrackingChanged_, this);
if (options.projection !== undefined) {
this.setProjection(ol.proj.get(options.projection));
@@ -106877,12 +93257,12 @@ ol.Geolocation.prototype.handleTrackingChanged_ = function() {
if (ol.has.GEOLOCATION) {
var tracking = this.getTracking();
if (tracking && this.watchId_ === undefined) {
- this.watchId_ = goog.global.navigator.geolocation.watchPosition(
- goog.bind(this.positionChange_, this),
- goog.bind(this.positionError_, this),
+ this.watchId_ = ol.global.navigator.geolocation.watchPosition(
+ this.positionChange_.bind(this),
+ this.positionError_.bind(this),
this.getTrackingOptions());
} else if (!tracking && this.watchId_ !== undefined) {
- goog.global.navigator.geolocation.clearWatch(this.watchId_);
+ ol.global.navigator.geolocation.clearWatch(this.watchId_);
this.watchId_ = undefined;
}
}
@@ -106920,15 +93300,20 @@ ol.Geolocation.prototype.positionChange_ = function(position) {
this.changed();
};
+/**
+ * Triggered when the Geolocation returns an error.
+ * @event error
+ * @api
+ */
/**
* @private
* @param {GeolocationPositionError} error error object.
*/
ol.Geolocation.prototype.positionError_ = function(error) {
- error.type = goog.events.EventType.ERROR;
+ error.type = ol.events.EventType.ERROR;
this.setTracking(false);
- this.dispatchEvent(error);
+ this.dispatchEvent(/** @type {{type: string, target: undefined}} */ (error));
};
@@ -107108,7 +93493,6 @@ goog.require('ol.geom.flat.deflate');
goog.require('ol.proj');
-
/**
* @classdesc
* Circle geometry.
@@ -107143,8 +93527,7 @@ ol.geom.Circle.prototype.clone = function() {
/**
* @inheritDoc
*/
-ol.geom.Circle.prototype.closestPointXY =
- function(x, y, closestPoint, minSquaredDistance) {
+ol.geom.Circle.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
var flatCoordinates = this.flatCoordinates;
var dx = x - flatCoordinates[0];
var dy = y - flatCoordinates[1];
@@ -107286,8 +93669,7 @@ ol.geom.Circle.prototype.setCenter = function(center) {
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
* @api
*/
-ol.geom.Circle.prototype.setCenterAndRadius =
- function(center, radius, opt_layout) {
+ol.geom.Circle.prototype.setCenterAndRadius = function(center, radius, opt_layout) {
if (!center) {
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
} else {
@@ -107314,8 +93696,7 @@ ol.geom.Circle.prototype.setCenterAndRadius =
* @param {ol.geom.GeometryLayout} layout Layout.
* @param {Array.<number>} flatCoordinates Flat coordinates.
*/
-ol.geom.Circle.prototype.setFlatCoordinates =
- function(layout, flatCoordinates) {
+ol.geom.Circle.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
this.setFlatCoordinatesInternal(layout, flatCoordinates);
this.changed();
};
@@ -107361,7 +93742,6 @@ ol.geom.Circle.prototype.transform;
goog.provide('ol.geom.flat.geodesic');
goog.require('goog.asserts');
-goog.require('ol.TransformFunction');
goog.require('ol.math');
goog.require('ol.proj');
@@ -107374,8 +93754,7 @@ goog.require('ol.proj');
* @param {number} squaredTolerance Squared tolerance.
* @return {Array.<number>} Flat coordinates.
*/
-ol.geom.flat.geodesic.line_ =
- function(interpolate, transform, squaredTolerance) {
+ol.geom.flat.geodesic.line_ = function(interpolate, transform, squaredTolerance) {
// FIXME reduce garbage generation
// FIXME optimize stack operations
@@ -107501,8 +93880,7 @@ ol.geom.flat.geodesic.greatCircleArc = function(
* @param {number} squaredTolerance Squared tolerance.
* @return {Array.<number>} Flat coordinates.
*/
-ol.geom.flat.geodesic.meridian =
- function(lon, lat1, lat2, projection, squaredTolerance) {
+ol.geom.flat.geodesic.meridian = function(lon, lat1, lat2, projection, squaredTolerance) {
var epsg4326Projection = ol.proj.get('EPSG:4326');
return ol.geom.flat.geodesic.line_(
/**
@@ -107525,8 +93903,7 @@ ol.geom.flat.geodesic.meridian =
* @param {number} squaredTolerance Squared tolerance.
* @return {Array.<number>} Flat coordinates.
*/
-ol.geom.flat.geodesic.parallel =
- function(lat, lon1, lon2, projection, squaredTolerance) {
+ol.geom.flat.geodesic.parallel = function(lat, lon1, lon2, projection, squaredTolerance) {
var epsg4326Projection = ol.proj.get('EPSG:4326');
return ol.geom.flat.geodesic.line_(
/**
@@ -107552,7 +93929,6 @@ goog.require('ol.render.EventType');
goog.require('ol.style.Stroke');
-
/**
* Render a grid for a coordinate system on a map.
* @constructor
@@ -107708,8 +94084,7 @@ ol.Graticule.intervals_ = [90, 45, 30, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05,
* @return {number} Index.
* @private
*/
-ol.Graticule.prototype.addMeridian_ =
- function(lon, minLat, maxLat, squaredTolerance, extent, index) {
+ol.Graticule.prototype.addMeridian_ = function(lon, minLat, maxLat, squaredTolerance, extent, index) {
var lineString = this.getMeridian_(lon, minLat, maxLat,
squaredTolerance, index);
if (ol.extent.intersects(lineString.getExtent(), extent)) {
@@ -107729,8 +94104,7 @@ ol.Graticule.prototype.addMeridian_ =
* @return {number} Index.
* @private
*/
-ol.Graticule.prototype.addParallel_ =
- function(lat, minLon, maxLon, squaredTolerance, extent, index) {
+ol.Graticule.prototype.addParallel_ = function(lat, minLon, maxLon, squaredTolerance, extent, index) {
var lineString = this.getParallel_(lat, minLon, maxLon, squaredTolerance,
index);
if (ol.extent.intersects(lineString.getExtent(), extent)) {
@@ -107747,8 +94121,7 @@ ol.Graticule.prototype.addParallel_ =
* @param {number} squaredTolerance Squared tolerance.
* @private
*/
-ol.Graticule.prototype.createGraticule_ =
- function(extent, center, resolution, squaredTolerance) {
+ol.Graticule.prototype.createGraticule_ = function(extent, center, resolution, squaredTolerance) {
var interval = this.getInterval_(resolution);
if (interval == -1) {
@@ -107987,11 +94360,11 @@ ol.Graticule.prototype.handlePostCompose_ = function(e) {
var i, l, line;
for (i = 0, l = this.meridians_.length; i < l; ++i) {
line = this.meridians_[i];
- vectorContext.drawLineStringGeometry(line, null);
+ vectorContext.drawLineString(line, null);
}
for (i = 0, l = this.parallels_.length; i < l; ++i) {
line = this.parallels_[i];
- vectorContext.drawLineStringGeometry(line, null);
+ vectorContext.drawLineString(line, null);
}
};
@@ -108082,13 +94455,12 @@ ol.Graticule.prototype.setMap = function(map) {
goog.provide('ol.Image');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('ol.ImageBase');
goog.require('ol.ImageState');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
-
+goog.require('ol.object');
/**
@@ -108131,7 +94503,7 @@ ol.Image = function(extent, resolution, pixelRatio, attributions, src,
/**
* @private
- * @type {Array.<goog.events.Key>}
+ * @type {Array.<ol.events.Key>}
*/
this.imageListenerKeys_ = null;
@@ -108163,7 +94535,7 @@ ol.Image.prototype.getImage = function(opt_context) {
var key = goog.getUid(opt_context);
if (key in this.imageByContext_) {
return this.imageByContext_[key];
- } else if (goog.object.isEmpty(this.imageByContext_)) {
+ } else if (ol.object.isEmpty(this.imageByContext_)) {
image = this.image_;
} else {
image = /** @type {Image} */ (this.image_.cloneNode(false));
@@ -108213,10 +94585,10 @@ ol.Image.prototype.load = function() {
goog.asserts.assert(!this.imageListenerKeys_,
'this.imageListenerKeys_ should be null');
this.imageListenerKeys_ = [
- goog.events.listenOnce(this.image_, goog.events.EventType.ERROR,
- this.handleImageError_, false, this),
- goog.events.listenOnce(this.image_, goog.events.EventType.LOAD,
- this.handleImageLoad_, false, this)
+ ol.events.listenOnce(this.image_, ol.events.EventType.ERROR,
+ this.handleImageError_, this),
+ ol.events.listenOnce(this.image_, ol.events.EventType.LOAD,
+ this.handleImageLoad_, this)
];
this.imageLoadFunction_(this, this.src_);
}
@@ -108239,43 +94611,18 @@ ol.Image.prototype.setImage = function(image) {
ol.Image.prototype.unlistenImage_ = function() {
goog.asserts.assert(this.imageListenerKeys_,
'this.imageListenerKeys_ should not be null');
- this.imageListenerKeys_.forEach(goog.events.unlistenByKey);
+ this.imageListenerKeys_.forEach(ol.events.unlistenByKey);
this.imageListenerKeys_ = null;
};
-goog.provide('ol.ImageLoadFunctionType');
-
-
-/**
- * A function that takes an {@link ol.Image} for the image and a `{string}` for
- * the src as arguments. It is supposed to make it so the underlying image
- * {@link ol.Image#getImage} is assigned the content specified by the src. If
- * not specified, the default is
- *
- * function(image, src) {
- * image.getImage().src = src;
- * }
- *
- * Providing a custom `imageLoadFunction` can be useful to load images with
- * post requests or - in general - through XHR requests, where the src of the
- * image element would be set to a data URI when the content is loaded.
- *
- * @typedef {function(ol.Image, string)}
- * @api
- */
-ol.ImageLoadFunctionType;
-
goog.provide('ol.ImageTile');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('ol.Tile');
-goog.require('ol.TileCoord');
-goog.require('ol.TileLoadFunctionType');
goog.require('ol.TileState');
-
+goog.require('ol.events');
+goog.require('ol.events.EventType');
+goog.require('ol.object');
/**
@@ -108316,7 +94663,7 @@ ol.ImageTile = function(tileCoord, state, src, crossOrigin, tileLoadFunction) {
/**
* @private
- * @type {Array.<goog.events.Key>}
+ * @type {Array.<ol.events.Key>}
*/
this.imageListenerKeys_ = null;
@@ -108338,8 +94685,10 @@ ol.ImageTile.prototype.disposeInternal = function() {
this.unlistenImage_();
}
if (this.interimTile) {
- goog.dispose(this.interimTile);
+ this.interimTile.dispose();
}
+ this.state = ol.TileState.ABORT;
+ this.changed();
goog.base(this, 'disposeInternal');
};
@@ -108355,7 +94704,7 @@ ol.ImageTile.prototype.getImage = function(opt_context) {
var key = goog.getUid(opt_context);
if (key in this.imageByContext_) {
return this.imageByContext_[key];
- } else if (goog.object.isEmpty(this.imageByContext_)) {
+ } else if (ol.object.isEmpty(this.imageByContext_)) {
image = this.image_;
} else {
image = /** @type {Image} */ (this.image_.cloneNode(false));
@@ -108414,10 +94763,10 @@ ol.ImageTile.prototype.load = function() {
goog.asserts.assert(!this.imageListenerKeys_,
'this.imageListenerKeys_ should be null');
this.imageListenerKeys_ = [
- goog.events.listenOnce(this.image_, goog.events.EventType.ERROR,
- this.handleImageError_, false, this),
- goog.events.listenOnce(this.image_, goog.events.EventType.LOAD,
- this.handleImageLoad_, false, this)
+ ol.events.listenOnce(this.image_, ol.events.EventType.ERROR,
+ this.handleImageError_, this),
+ ol.events.listenOnce(this.image_, ol.events.EventType.LOAD,
+ this.handleImageLoad_, this)
];
this.tileLoadFunction_(this, this.src_);
}
@@ -108432,1745 +94781,24 @@ ol.ImageTile.prototype.load = function() {
ol.ImageTile.prototype.unlistenImage_ = function() {
goog.asserts.assert(this.imageListenerKeys_,
'this.imageListenerKeys_ should not be null');
- this.imageListenerKeys_.forEach(goog.events.unlistenByKey);
+ this.imageListenerKeys_.forEach(ol.events.unlistenByKey);
this.imageListenerKeys_ = null;
};
-// Copyright 2010 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Provides a files drag and drop event detector. It works on
- * HTML5 browsers.
- *
- * @see ../demos/filedrophandler.html
- */
-
-goog.provide('goog.events.FileDropHandler');
-goog.provide('goog.events.FileDropHandler.EventType');
-
-goog.require('goog.array');
-goog.require('goog.dom');
-goog.require('goog.events.BrowserEvent');
-goog.require('goog.events.EventHandler');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
-goog.require('goog.log');
-goog.require('goog.log.Level');
-
-
-
-/**
- * A files drag and drop event detector. Gets an {@code element} as parameter
- * and fires {@code goog.events.FileDropHandler.EventType.DROP} event when files
- * are dropped in the {@code element}.
- *
- * @param {Element|Document} element The element or document to listen on.
- * @param {boolean=} opt_preventDropOutside Whether to prevent a drop on the
- * area outside the {@code element}. Default false.
- * @constructor
- * @extends {goog.events.EventTarget}
- * @final
- */
-goog.events.FileDropHandler = function(element, opt_preventDropOutside) {
- goog.events.EventTarget.call(this);
-
- /**
- * Handler for drag/drop events.
- * @type {!goog.events.EventHandler<!goog.events.FileDropHandler>}
- * @private
- */
- this.eventHandler_ = new goog.events.EventHandler(this);
-
- var doc = element;
- if (opt_preventDropOutside) {
- doc = goog.dom.getOwnerDocument(element);
- }
-
- // Add dragenter listener to the owner document of the element.
- this.eventHandler_.listen(doc,
- goog.events.EventType.DRAGENTER,
- this.onDocDragEnter_);
-
- // Add dragover listener to the owner document of the element only if the
- // document is not the element itself.
- if (doc != element) {
- this.eventHandler_.listen(doc,
- goog.events.EventType.DRAGOVER,
- this.onDocDragOver_);
- }
-
- // Add dragover and drop listeners to the element.
- this.eventHandler_.listen(element,
- goog.events.EventType.DRAGOVER,
- this.onElemDragOver_);
- this.eventHandler_.listen(element,
- goog.events.EventType.DROP,
- this.onElemDrop_);
-};
-goog.inherits(goog.events.FileDropHandler, goog.events.EventTarget);
-
-
-/**
- * Whether the drag event contains files. It is initialized only in the
- * dragenter event. It is used in all the drag events to prevent default actions
- * only if the drag contains files. Preventing default actions is necessary to
- * go from dragenter to dragover and from dragover to drop. However we do not
- * always want to prevent default actions, e.g. when the user drags text or
- * links on a text area we should not prevent the browser default action that
- * inserts the text in the text area. It is also necessary to stop propagation
- * when handling drag events on the element to prevent them from propagating
- * to the document.
- * @private
- * @type {boolean}
- */
-goog.events.FileDropHandler.prototype.dndContainsFiles_ = false;
-
-
-/**
- * A logger, used to help us debug the algorithm.
- * @type {goog.log.Logger}
- * @private
- */
-goog.events.FileDropHandler.prototype.logger_ =
- goog.log.getLogger('goog.events.FileDropHandler');
-
-
-/**
- * The types of events fired by this class.
- * @enum {string}
- */
-goog.events.FileDropHandler.EventType = {
- DROP: goog.events.EventType.DROP
-};
-
-
-/** @override */
-goog.events.FileDropHandler.prototype.disposeInternal = function() {
- goog.events.FileDropHandler.superClass_.disposeInternal.call(this);
- this.eventHandler_.dispose();
-};
-
-
-/**
- * Dispatches the DROP event.
- * @param {goog.events.BrowserEvent} e The underlying browser event.
- * @private
- */
-goog.events.FileDropHandler.prototype.dispatch_ = function(e) {
- goog.log.fine(this.logger_, 'Firing DROP event...');
- var event = new goog.events.BrowserEvent(e.getBrowserEvent());
- event.type = goog.events.FileDropHandler.EventType.DROP;
- this.dispatchEvent(event);
-};
-
-
-/**
- * Handles dragenter on the document.
- * @param {goog.events.BrowserEvent} e The dragenter event.
- * @private
- */
-goog.events.FileDropHandler.prototype.onDocDragEnter_ = function(e) {
- goog.log.log(this.logger_, goog.log.Level.FINER,
- '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
- var dt = e.getBrowserEvent().dataTransfer;
- // Check whether the drag event contains files.
- this.dndContainsFiles_ = !!(dt &&
- ((dt.types &&
- (goog.array.contains(dt.types, 'Files') ||
- goog.array.contains(dt.types, 'public.file-url'))) ||
- (dt.files && dt.files.length > 0)));
- // If it does
- if (this.dndContainsFiles_) {
- // Prevent default actions.
- e.preventDefault();
- }
- goog.log.log(this.logger_, goog.log.Level.FINER,
- 'dndContainsFiles_: ' + this.dndContainsFiles_);
-};
-
-
-/**
- * Handles dragging something over the document.
- * @param {goog.events.BrowserEvent} e The dragover event.
- * @private
- */
-goog.events.FileDropHandler.prototype.onDocDragOver_ = function(e) {
- goog.log.log(this.logger_, goog.log.Level.FINEST,
- '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
- if (this.dndContainsFiles_) {
- // Prevent default actions.
- e.preventDefault();
- // Disable the drop on the document outside the drop zone.
- var dt = e.getBrowserEvent().dataTransfer;
- dt.dropEffect = 'none';
- }
-};
-
-
-/**
- * Handles dragging something over the element (drop zone).
- * @param {goog.events.BrowserEvent} e The dragover event.
- * @private
- */
-goog.events.FileDropHandler.prototype.onElemDragOver_ = function(e) {
- goog.log.log(this.logger_, goog.log.Level.FINEST,
- '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
- if (this.dndContainsFiles_) {
- // Prevent default actions and stop the event from propagating further to
- // the document. Both lines are needed! (See comment above).
- e.preventDefault();
- e.stopPropagation();
- // Allow the drop on the drop zone.
- var dt = e.getBrowserEvent().dataTransfer;
-
- // IE bug #811625 (https://goo.gl/UWuxX0) will throw error SCRIPT65535
- // when attempting to set property effectAllowed on IE10+.
- // See more: https://github.com/google/closure-library/issues/485.
- try {
- dt.effectAllowed = 'all';
- } catch (err) {
- }
- dt.dropEffect = 'copy';
- }
-};
-
-
-/**
- * Handles dropping something onto the element (drop zone).
- * @param {goog.events.BrowserEvent} e The drop event.
- * @private
- */
-goog.events.FileDropHandler.prototype.onElemDrop_ = function(e) {
- goog.log.log(this.logger_, goog.log.Level.FINER,
- '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
- // If the drag and drop event contains files.
- if (this.dndContainsFiles_) {
- // Prevent default actions and stop the event from propagating further to
- // the document. Both lines are needed! (See comment above).
- e.preventDefault();
- e.stopPropagation();
- // Dispatch DROP event.
- this.dispatch_(e);
- }
-};
-
-// Copyright 2007 Bob Ippolito. All Rights Reserved.
-// Modifications Copyright 2009 The Closure Library Authors. All Rights
-// Reserved.
-
-/**
- * @license Portions of this code are from MochiKit, received by
- * The Closure Authors under the MIT license. All other code is Copyright
- * 2005-2009 The Closure Authors. All Rights Reserved.
- */
-
-/**
- * @fileoverview Classes for tracking asynchronous operations and handling the
- * results. The Deferred object here is patterned after the Deferred object in
- * the Twisted python networking framework.
- *
- * See: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
- *
- * Based on the Dojo code which in turn is based on the MochiKit code.
- *
- * @author arv@google.com (Erik Arvidsson)
- * @author brenneman@google.com (Shawn Brenneman)
- */
-
-goog.provide('goog.async.Deferred');
-goog.provide('goog.async.Deferred.AlreadyCalledError');
-goog.provide('goog.async.Deferred.CanceledError');
-
-goog.require('goog.Promise');
-goog.require('goog.Thenable');
-goog.require('goog.array');
-goog.require('goog.asserts');
-goog.require('goog.debug.Error');
-
-
-
-/**
- * A Deferred represents the result of an asynchronous operation. A Deferred
- * instance has no result when it is created, and is "fired" (given an initial
- * result) by calling {@code callback} or {@code errback}.
- *
- * Once fired, the result is passed through a sequence of callback functions
- * registered with {@code addCallback} or {@code addErrback}. The functions may
- * mutate the result before it is passed to the next function in the sequence.
- *
- * Callbacks and errbacks may be added at any time, including after the Deferred
- * has been "fired". If there are no pending actions in the execution sequence
- * of a fired Deferred, any new callback functions will be called with the last
- * computed result. Adding a callback function is the only way to access the
- * result of the Deferred.
- *
- * If a Deferred operation is canceled, an optional user-provided cancellation
- * function is invoked which may perform any special cleanup, followed by firing
- * the Deferred's errback sequence with a {@code CanceledError}. If the
- * Deferred has already fired, cancellation is ignored.
- *
- * Deferreds may be templated to a specific type they produce using generics
- * with syntax such as:
- * <code>
- * /** @type {goog.async.Deferred<string>} *&#47;
- * var d = new goog.async.Deferred();
- * // Compiler can infer that foo is a string.
- * d.addCallback(function(foo) {...});
- * d.callback('string'); // Checked to be passed a string
- * </code>
- * Since deferreds are often used to produce different values across a chain,
- * the type information is not propagated across chains, but rather only
- * associated with specifically cast objects.
- *
- * @param {Function=} opt_onCancelFunction A function that will be called if the
- * Deferred is canceled. If provided, this function runs before the
- * Deferred is fired with a {@code CanceledError}.
- * @param {Object=} opt_defaultScope The default object context to call
- * callbacks and errbacks in.
- * @constructor
- * @implements {goog.Thenable<VALUE>}
- * @template VALUE
- */
-goog.async.Deferred = function(opt_onCancelFunction, opt_defaultScope) {
- /**
- * Entries in the sequence are arrays containing a callback, an errback, and
- * an optional scope. The callback or errback in an entry may be null.
- * @type {!Array<!Array>}
- * @private
- */
- this.sequence_ = [];
-
- /**
- * Optional function that will be called if the Deferred is canceled.
- * @type {Function|undefined}
- * @private
- */
- this.onCancelFunction_ = opt_onCancelFunction;
-
- /**
- * The default scope to execute callbacks and errbacks in.
- * @type {Object}
- * @private
- */
- this.defaultScope_ = opt_defaultScope || null;
-
- /**
- * Whether the Deferred has been fired.
- * @type {boolean}
- * @private
- */
- this.fired_ = false;
-
- /**
- * Whether the last result in the execution sequence was an error.
- * @type {boolean}
- * @private
- */
- this.hadError_ = false;
-
- /**
- * The current Deferred result, updated as callbacks and errbacks are
- * executed.
- * @type {*}
- * @private
- */
- this.result_ = undefined;
-
- /**
- * Whether the Deferred is blocked waiting on another Deferred to fire. If a
- * callback or errback returns a Deferred as a result, the execution sequence
- * is blocked until that Deferred result becomes available.
- * @type {boolean}
- * @private
- */
- this.blocked_ = false;
-
- /**
- * Whether this Deferred is blocking execution of another Deferred. If this
- * instance was returned as a result in another Deferred's execution
- * sequence,that other Deferred becomes blocked until this instance's
- * execution sequence completes. No additional callbacks may be added to a
- * Deferred once it is blocking another instance.
- * @type {boolean}
- * @private
- */
- this.blocking_ = false;
-
- /**
- * Whether the Deferred has been canceled without having a custom cancel
- * function.
- * @type {boolean}
- * @private
- */
- this.silentlyCanceled_ = false;
-
- /**
- * If an error is thrown during Deferred execution with no errback to catch
- * it, the error is rethrown after a timeout. Reporting the error after a
- * timeout allows execution to continue in the calling context (empty when
- * no error is scheduled).
- * @type {number}
- * @private
- */
- this.unhandledErrorId_ = 0;
-
- /**
- * If this Deferred was created by branch(), this will be the "parent"
- * Deferred.
- * @type {goog.async.Deferred}
- * @private
- */
- this.parent_ = null;
-
- /**
- * The number of Deferred objects that have been branched off this one. This
- * will be decremented whenever a branch is fired or canceled.
- * @type {number}
- * @private
- */
- this.branches_ = 0;
-
- if (goog.async.Deferred.LONG_STACK_TRACES) {
- /**
- * Holds the stack trace at time of deferred creation if the JS engine
- * provides the Error.captureStackTrace API.
- * @private {?string}
- */
- this.constructorStack_ = null;
- if (Error.captureStackTrace) {
- var target = { stack: '' };
- Error.captureStackTrace(target, goog.async.Deferred);
- // Check if Error.captureStackTrace worked. It fails in gjstest.
- if (typeof target.stack == 'string') {
- // Remove first line and force stringify to prevent memory leak due to
- // holding on to actual stack frames.
- this.constructorStack_ = target.stack.replace(/^[^\n]*\n/, '');
- }
- }
- }
-};
-
-
-/**
- * @define {boolean} Whether unhandled errors should always get rethrown to the
- * global scope. Defaults to the value of goog.DEBUG.
- */
-goog.define('goog.async.Deferred.STRICT_ERRORS', false);
-
-
-/**
- * @define {boolean} Whether to attempt to make stack traces long. Defaults to
- * the value of goog.DEBUG.
- */
-goog.define('goog.async.Deferred.LONG_STACK_TRACES', false);
-
-
-/**
- * Cancels a Deferred that has not yet been fired, or is blocked on another
- * deferred operation. If this Deferred is waiting for a blocking Deferred to
- * fire, the blocking Deferred will also be canceled.
- *
- * If this Deferred was created by calling branch() on a parent Deferred with
- * opt_propagateCancel set to true, the parent may also be canceled. If
- * opt_deepCancel is set, cancel() will be called on the parent (as well as any
- * other ancestors if the parent is also a branch). If one or more branches were
- * created with opt_propagateCancel set to true, the parent will be canceled if
- * cancel() is called on all of those branches.
- *
- * @param {boolean=} opt_deepCancel If true, cancels this Deferred's parent even
- * if cancel() hasn't been called on some of the parent's branches. Has no
- * effect on a branch without opt_propagateCancel set to true.
- */
-goog.async.Deferred.prototype.cancel = function(opt_deepCancel) {
- if (!this.hasFired()) {
- if (this.parent_) {
- // Get rid of the parent reference before potentially running the parent's
- // canceler function to ensure that this cancellation isn't
- // double-counted.
- var parent = this.parent_;
- delete this.parent_;
- if (opt_deepCancel) {
- parent.cancel(opt_deepCancel);
- } else {
- parent.branchCancel_();
- }
- }
-
- if (this.onCancelFunction_) {
- // Call in user-specified scope.
- this.onCancelFunction_.call(this.defaultScope_, this);
- } else {
- this.silentlyCanceled_ = true;
- }
- if (!this.hasFired()) {
- this.errback(new goog.async.Deferred.CanceledError(this));
- }
- } else if (this.result_ instanceof goog.async.Deferred) {
- this.result_.cancel();
- }
-};
-
-
-/**
- * Handle a single branch being canceled. Once all branches are canceled, this
- * Deferred will be canceled as well.
- *
- * @private
- */
-goog.async.Deferred.prototype.branchCancel_ = function() {
- this.branches_--;
- if (this.branches_ <= 0) {
- this.cancel();
- }
-};
-
-
-/**
- * Called after a blocking Deferred fires. Unblocks this Deferred and resumes
- * its execution sequence.
- *
- * @param {boolean} isSuccess Whether the result is a success or an error.
- * @param {*} res The result of the blocking Deferred.
- * @private
- */
-goog.async.Deferred.prototype.continue_ = function(isSuccess, res) {
- this.blocked_ = false;
- this.updateResult_(isSuccess, res);
-};
-
-
-/**
- * Updates the current result based on the success or failure of the last action
- * in the execution sequence.
- *
- * @param {boolean} isSuccess Whether the new result is a success or an error.
- * @param {*} res The result.
- * @private
- */
-goog.async.Deferred.prototype.updateResult_ = function(isSuccess, res) {
- this.fired_ = true;
- this.result_ = res;
- this.hadError_ = !isSuccess;
- this.fire_();
-};
-
-
-/**
- * Verifies that the Deferred has not yet been fired.
- *
- * @private
- * @throws {Error} If this has already been fired.
- */
-goog.async.Deferred.prototype.check_ = function() {
- if (this.hasFired()) {
- if (!this.silentlyCanceled_) {
- throw new goog.async.Deferred.AlreadyCalledError(this);
- }
- this.silentlyCanceled_ = false;
- }
-};
-
-
-/**
- * Fire the execution sequence for this Deferred by passing the starting result
- * to the first registered callback.
- * @param {VALUE=} opt_result The starting result.
- */
-goog.async.Deferred.prototype.callback = function(opt_result) {
- this.check_();
- this.assertNotDeferred_(opt_result);
- this.updateResult_(true /* isSuccess */, opt_result);
-};
-
-
-/**
- * Fire the execution sequence for this Deferred by passing the starting error
- * result to the first registered errback.
- * @param {*=} opt_result The starting error.
- */
-goog.async.Deferred.prototype.errback = function(opt_result) {
- this.check_();
- this.assertNotDeferred_(opt_result);
- this.makeStackTraceLong_(opt_result);
- this.updateResult_(false /* isSuccess */, opt_result);
-};
-
-
-/**
- * Attempt to make the error's stack trace be long in that it contains the
- * stack trace from the point where the deferred was created on top of the
- * current stack trace to give additional context.
- * @param {*} error
- * @private
- */
-goog.async.Deferred.prototype.makeStackTraceLong_ = function(error) {
- if (!goog.async.Deferred.LONG_STACK_TRACES) {
- return;
- }
- if (this.constructorStack_ && goog.isObject(error) && error.stack &&
- // Stack looks like it was system generated. See
- // https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
- (/^[^\n]+(\n [^\n]+)+/).test(error.stack)) {
- error.stack = error.stack + '\nDEFERRED OPERATION:\n' +
- this.constructorStack_;
- }
-};
-
-
-/**
- * Asserts that an object is not a Deferred.
- * @param {*} obj The object to test.
- * @throws {Error} Throws an exception if the object is a Deferred.
- * @private
- */
-goog.async.Deferred.prototype.assertNotDeferred_ = function(obj) {
- goog.asserts.assert(
- !(obj instanceof goog.async.Deferred),
- 'An execution sequence may not be initiated with a blocking Deferred.');
-};
-
-
-/**
- * Register a callback function to be called with a successful result. If no
- * value is returned by the callback function, the result value is unchanged. If
- * a new value is returned, it becomes the Deferred result and will be passed to
- * the next callback in the execution sequence.
- *
- * If the function throws an error, the error becomes the new result and will be
- * passed to the next errback in the execution chain.
- *
- * If the function returns a Deferred, the execution sequence will be blocked
- * until that Deferred fires. Its result will be passed to the next callback (or
- * errback if it is an error result) in this Deferred's execution sequence.
- *
- * @param {!function(this:T,VALUE):?} cb The function to be called with a
- * successful result.
- * @param {T=} opt_scope An optional scope to call the callback in.
- * @return {!goog.async.Deferred} This Deferred.
- * @template T
- */
-goog.async.Deferred.prototype.addCallback = function(cb, opt_scope) {
- return this.addCallbacks(cb, null, opt_scope);
-};
-
-
-/**
- * Register a callback function to be called with an error result. If no value
- * is returned by the function, the error result is unchanged. If a new error
- * value is returned or thrown, that error becomes the Deferred result and will
- * be passed to the next errback in the execution sequence.
- *
- * If the errback function handles the error by returning a non-error value,
- * that result will be passed to the next normal callback in the sequence.
- *
- * If the function returns a Deferred, the execution sequence will be blocked
- * until that Deferred fires. Its result will be passed to the next callback (or
- * errback if it is an error result) in this Deferred's execution sequence.
- *
- * @param {!function(this:T,?):?} eb The function to be called on an
- * unsuccessful result.
- * @param {T=} opt_scope An optional scope to call the errback in.
- * @return {!goog.async.Deferred<VALUE>} This Deferred.
- * @template T
- */
-goog.async.Deferred.prototype.addErrback = function(eb, opt_scope) {
- return this.addCallbacks(null, eb, opt_scope);
-};
-
-
-/**
- * Registers one function as both a callback and errback.
- *
- * @param {!function(this:T,?):?} f The function to be called on any result.
- * @param {T=} opt_scope An optional scope to call the function in.
- * @return {!goog.async.Deferred} This Deferred.
- * @template T
- */
-goog.async.Deferred.prototype.addBoth = function(f, opt_scope) {
- return this.addCallbacks(f, f, opt_scope);
-};
-
-
-/**
- * Like addBoth, but propagates uncaught exceptions in the errback.
- *
- * @param {function(this:T,?):?} f The function to be called on any result.
- * @param {T=} opt_scope An optional scope to call the function in.
- * @return {!goog.async.Deferred<VALUE>} This Deferred.
- * @template T
- */
-goog.async.Deferred.prototype.addFinally = function(f, opt_scope) {
- var self = this;
- return this.addCallbacks(f, function(err) {
- var result = f.call(self, err);
- if (!goog.isDef(result)) {
- throw err;
- }
- return result;
- }, opt_scope);
-};
-
-
-/**
- * Registers a callback function and an errback function at the same position
- * in the execution sequence. Only one of these functions will execute,
- * depending on the error state during the execution sequence.
- *
- * NOTE: This is not equivalent to {@code def.addCallback().addErrback()}! If
- * the callback is invoked, the errback will be skipped, and vice versa.
- *
- * @param {?(function(this:T,VALUE):?)} cb The function to be called on a
- * successful result.
- * @param {?(function(this:T,?):?)} eb The function to be called on an
- * unsuccessful result.
- * @param {T=} opt_scope An optional scope to call the functions in.
- * @return {!goog.async.Deferred} This Deferred.
- * @template T
- */
-goog.async.Deferred.prototype.addCallbacks = function(cb, eb, opt_scope) {
- goog.asserts.assert(!this.blocking_, 'Blocking Deferreds can not be re-used');
- this.sequence_.push([cb, eb, opt_scope]);
- if (this.hasFired()) {
- this.fire_();
- }
- return this;
-};
-
-
-/**
- * Implements {@see goog.Thenable} for seamless integration with
- * {@see goog.Promise}.
- * Deferred results are mutable and may represent multiple values over
- * their lifetime. Calling {@code then} on a Deferred returns a Promise
- * with the result of the Deferred at that point in its callback chain.
- * Note that if the Deferred result is never mutated, and only
- * {@code then} calls are made, the Deferred will behave like a Promise.
- *
- * @override
- */
-goog.async.Deferred.prototype.then = function(opt_onFulfilled, opt_onRejected,
- opt_context) {
- var resolve, reject;
- var promise = new goog.Promise(function(res, rej) {
- // Copying resolvers to outer scope, so that they are available when the
- // deferred callback fires (which may be synchronous).
- resolve = res;
- reject = rej;
- });
- this.addCallbacks(resolve, function(reason) {
- if (reason instanceof goog.async.Deferred.CanceledError) {
- promise.cancel();
- } else {
- reject(reason);
- }
- });
- return promise.then(opt_onFulfilled, opt_onRejected, opt_context);
-};
-goog.Thenable.addImplementation(goog.async.Deferred);
-
-
-/**
- * Links another Deferred to the end of this Deferred's execution sequence. The
- * result of this execution sequence will be passed as the starting result for
- * the chained Deferred, invoking either its first callback or errback.
- *
- * @param {!goog.async.Deferred} otherDeferred The Deferred to chain.
- * @return {!goog.async.Deferred} This Deferred.
- */
-goog.async.Deferred.prototype.chainDeferred = function(otherDeferred) {
- this.addCallbacks(
- otherDeferred.callback, otherDeferred.errback, otherDeferred);
- return this;
-};
-
-
-/**
- * Makes this Deferred wait for another Deferred's execution sequence to
- * complete before continuing.
- *
- * This is equivalent to adding a callback that returns {@code otherDeferred},
- * but doesn't prevent additional callbacks from being added to
- * {@code otherDeferred}.
- *
- * @param {!goog.async.Deferred|!goog.Thenable} otherDeferred The Deferred
- * to wait for.
- * @return {!goog.async.Deferred} This Deferred.
- */
-goog.async.Deferred.prototype.awaitDeferred = function(otherDeferred) {
- if (!(otherDeferred instanceof goog.async.Deferred)) {
- // The Thenable case.
- return this.addCallback(function() {
- return otherDeferred;
- });
- }
- return this.addCallback(goog.bind(otherDeferred.branch, otherDeferred));
-};
-
-
-/**
- * Creates a branch off this Deferred's execution sequence, and returns it as a
- * new Deferred. The branched Deferred's starting result will be shared with the
- * parent at the point of the branch, even if further callbacks are added to the
- * parent.
- *
- * All branches at the same stage in the execution sequence will receive the
- * same starting value.
- *
- * @param {boolean=} opt_propagateCancel If cancel() is called on every child
- * branch created with opt_propagateCancel, the parent will be canceled as
- * well.
- * @return {!goog.async.Deferred<VALUE>} A Deferred that will be started with
- * the computed result from this stage in the execution sequence.
- */
-goog.async.Deferred.prototype.branch = function(opt_propagateCancel) {
- var d = new goog.async.Deferred();
- this.chainDeferred(d);
- if (opt_propagateCancel) {
- d.parent_ = this;
- this.branches_++;
- }
- return d;
-};
-
-
-/**
- * @return {boolean} Whether the execution sequence has been started on this
- * Deferred by invoking {@code callback} or {@code errback}.
- */
-goog.async.Deferred.prototype.hasFired = function() {
- return this.fired_;
-};
-
-
-/**
- * @param {*} res The latest result in the execution sequence.
- * @return {boolean} Whether the current result is an error that should cause
- * the next errback to fire. May be overridden by subclasses to handle
- * special error types.
- * @protected
- */
-goog.async.Deferred.prototype.isError = function(res) {
- return res instanceof Error;
-};
-
-
-/**
- * @return {boolean} Whether an errback exists in the remaining sequence.
- * @private
- */
-goog.async.Deferred.prototype.hasErrback_ = function() {
- return goog.array.some(this.sequence_, function(sequenceRow) {
- // The errback is the second element in the array.
- return goog.isFunction(sequenceRow[1]);
- });
-};
-
-
-/**
- * Exhausts the execution sequence while a result is available. The result may
- * be modified by callbacks or errbacks, and execution will block if the
- * returned result is an incomplete Deferred.
- *
- * @private
- */
-goog.async.Deferred.prototype.fire_ = function() {
- if (this.unhandledErrorId_ && this.hasFired() && this.hasErrback_()) {
- // It is possible to add errbacks after the Deferred has fired. If a new
- // errback is added immediately after the Deferred encountered an unhandled
- // error, but before that error is rethrown, the error is unscheduled.
- goog.async.Deferred.unscheduleError_(this.unhandledErrorId_);
- this.unhandledErrorId_ = 0;
- }
-
- if (this.parent_) {
- this.parent_.branches_--;
- delete this.parent_;
- }
-
- var res = this.result_;
- var unhandledException = false;
- var isNewlyBlocked = false;
-
- while (this.sequence_.length && !this.blocked_) {
- var sequenceEntry = this.sequence_.shift();
-
- var callback = sequenceEntry[0];
- var errback = sequenceEntry[1];
- var scope = sequenceEntry[2];
-
- var f = this.hadError_ ? errback : callback;
- if (f) {
- /** @preserveTry */
- try {
- var ret = f.call(scope || this.defaultScope_, res);
-
- // If no result, then use previous result.
- if (goog.isDef(ret)) {
- // Bubble up the error as long as the return value hasn't changed.
- this.hadError_ = this.hadError_ && (ret == res || this.isError(ret));
- this.result_ = res = ret;
- }
-
- if (goog.Thenable.isImplementedBy(res) ||
- (typeof goog.global['Promise'] === 'function' &&
- res instanceof goog.global['Promise'])) {
- isNewlyBlocked = true;
- this.blocked_ = true;
- }
-
- } catch (ex) {
- res = ex;
- this.hadError_ = true;
- this.makeStackTraceLong_(res);
-
- if (!this.hasErrback_()) {
- // If an error is thrown with no additional errbacks in the queue,
- // prepare to rethrow the error.
- unhandledException = true;
- }
- }
- }
- }
-
- this.result_ = res;
-
- if (isNewlyBlocked) {
- var onCallback = goog.bind(this.continue_, this, true /* isSuccess */);
- var onErrback = goog.bind(this.continue_, this, false /* isSuccess */);
-
- if (res instanceof goog.async.Deferred) {
- res.addCallbacks(onCallback, onErrback);
- res.blocking_ = true;
- } else {
- res.then(onCallback, onErrback);
- }
- } else if (goog.async.Deferred.STRICT_ERRORS && this.isError(res) &&
- !(res instanceof goog.async.Deferred.CanceledError)) {
- this.hadError_ = true;
- unhandledException = true;
- }
-
- if (unhandledException) {
- // Rethrow the unhandled error after a timeout. Execution will continue, but
- // the error will be seen by global handlers and the user. The throw will
- // be canceled if another errback is appended before the timeout executes.
- // The error's original stack trace is preserved where available.
- this.unhandledErrorId_ = goog.async.Deferred.scheduleError_(res);
- }
-};
-
-
-/**
- * Creates a Deferred that has an initial result.
- *
- * @param {*=} opt_result The result.
- * @return {!goog.async.Deferred} The new Deferred.
- */
-goog.async.Deferred.succeed = function(opt_result) {
- var d = new goog.async.Deferred();
- d.callback(opt_result);
- return d;
-};
-
-
-/**
- * Creates a Deferred that fires when the given promise resolves.
- * Use only during migration to Promises.
- *
- * @param {!goog.Promise<T>} promise
- * @return {!goog.async.Deferred<T>} The new Deferred.
- * @template T
- */
-goog.async.Deferred.fromPromise = function(promise) {
- var d = new goog.async.Deferred();
- d.callback();
- d.addCallback(function() {
- return promise;
- });
- return d;
-};
-
-
-/**
- * Creates a Deferred that has an initial error result.
- *
- * @param {*} res The error result.
- * @return {!goog.async.Deferred} The new Deferred.
- */
-goog.async.Deferred.fail = function(res) {
- var d = new goog.async.Deferred();
- d.errback(res);
- return d;
-};
-
-
-/**
- * Creates a Deferred that has already been canceled.
- *
- * @return {!goog.async.Deferred} The new Deferred.
- */
-goog.async.Deferred.canceled = function() {
- var d = new goog.async.Deferred();
- d.cancel();
- return d;
-};
-
-
-/**
- * Normalizes values that may or may not be Deferreds.
- *
- * If the input value is a Deferred, the Deferred is branched (so the original
- * execution sequence is not modified) and the input callback added to the new
- * branch. The branch is returned to the caller.
- *
- * If the input value is not a Deferred, the callback will be executed
- * immediately and an already firing Deferred will be returned to the caller.
- *
- * In the following (contrived) example, if <code>isImmediate</code> is true
- * then 3 is alerted immediately, otherwise 6 is alerted after a 2-second delay.
- *
- * <pre>
- * var value;
- * if (isImmediate) {
- * value = 3;
- * } else {
- * value = new goog.async.Deferred();
- * setTimeout(function() { value.callback(6); }, 2000);
- * }
- *
- * var d = goog.async.Deferred.when(value, alert);
- * </pre>
- *
- * @param {*} value Deferred or normal value to pass to the callback.
- * @param {!function(this:T, ?):?} callback The callback to execute.
- * @param {T=} opt_scope An optional scope to call the callback in.
- * @return {!goog.async.Deferred} A new Deferred that will call the input
- * callback with the input value.
- * @template T
- */
-goog.async.Deferred.when = function(value, callback, opt_scope) {
- if (value instanceof goog.async.Deferred) {
- return value.branch(true).addCallback(callback, opt_scope);
- } else {
- return goog.async.Deferred.succeed(value).addCallback(callback, opt_scope);
- }
-};
-
-
-
-/**
- * An error sub class that is used when a Deferred has already been called.
- * @param {!goog.async.Deferred} deferred The Deferred.
- *
- * @constructor
- * @extends {goog.debug.Error}
- */
-goog.async.Deferred.AlreadyCalledError = function(deferred) {
- goog.debug.Error.call(this);
-
- /**
- * The Deferred that raised this error.
- * @type {goog.async.Deferred}
- */
- this.deferred = deferred;
-};
-goog.inherits(goog.async.Deferred.AlreadyCalledError, goog.debug.Error);
-
-
-/** @override */
-goog.async.Deferred.AlreadyCalledError.prototype.message =
- 'Deferred has already fired';
-
-
-/** @override */
-goog.async.Deferred.AlreadyCalledError.prototype.name = 'AlreadyCalledError';
-
-
-
-/**
- * An error sub class that is used when a Deferred is canceled.
- *
- * @param {!goog.async.Deferred} deferred The Deferred object.
- * @constructor
- * @extends {goog.debug.Error}
- */
-goog.async.Deferred.CanceledError = function(deferred) {
- goog.debug.Error.call(this);
-
- /**
- * The Deferred that raised this error.
- * @type {goog.async.Deferred}
- */
- this.deferred = deferred;
-};
-goog.inherits(goog.async.Deferred.CanceledError, goog.debug.Error);
-
-
-/** @override */
-goog.async.Deferred.CanceledError.prototype.message = 'Deferred was canceled';
-
-
-/** @override */
-goog.async.Deferred.CanceledError.prototype.name = 'CanceledError';
-
-
-
-/**
- * Wrapper around errors that are scheduled to be thrown by failing deferreds
- * after a timeout.
- *
- * @param {*} error Error from a failing deferred.
- * @constructor
- * @final
- * @private
- * @struct
- */
-goog.async.Deferred.Error_ = function(error) {
- /** @const @private {number} */
- this.id_ = goog.global.setTimeout(goog.bind(this.throwError, this), 0);
-
- /** @const @private {*} */
- this.error_ = error;
-};
-
-
-/**
- * Actually throws the error and removes it from the list of pending
- * deferred errors.
- */
-goog.async.Deferred.Error_.prototype.throwError = function() {
- goog.asserts.assert(goog.async.Deferred.errorMap_[this.id_],
- 'Cannot throw an error that is not scheduled.');
- delete goog.async.Deferred.errorMap_[this.id_];
- throw this.error_;
-};
-
-
-/**
- * Resets the error throw timer.
- */
-goog.async.Deferred.Error_.prototype.resetTimer = function() {
- goog.global.clearTimeout(this.id_);
-};
-
-
-/**
- * Map of unhandled errors scheduled to be rethrown in a future timestep.
- * @private {!Object<number|string, goog.async.Deferred.Error_>}
- */
-goog.async.Deferred.errorMap_ = {};
-
-
-/**
- * Schedules an error to be thrown after a delay.
- * @param {*} error Error from a failing deferred.
- * @return {number} Id of the error.
- * @private
- */
-goog.async.Deferred.scheduleError_ = function(error) {
- var deferredError = new goog.async.Deferred.Error_(error);
- goog.async.Deferred.errorMap_[deferredError.id_] = deferredError;
- return deferredError.id_;
-};
-
-
-/**
- * Unschedules an error from being thrown.
- * @param {number} id Id of the deferred error to unschedule.
- * @private
- */
-goog.async.Deferred.unscheduleError_ = function(id) {
- var error = goog.async.Deferred.errorMap_[id];
- if (error) {
- error.resetTimer();
- delete goog.async.Deferred.errorMap_[id];
- }
-};
-
-
-/**
- * Asserts that there are no pending deferred errors. If there are any
- * scheduled errors, one will be thrown immediately to make this function fail.
- */
-goog.async.Deferred.assertNoErrors = function() {
- var map = goog.async.Deferred.errorMap_;
- for (var key in map) {
- var error = map[key];
- error.resetTimer();
- error.throwError();
- }
-};
-
-// Copyright 2011 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview A wrapper for the HTML5 FileError object.
- *
- */
-
-goog.provide('goog.fs.Error');
-goog.provide('goog.fs.Error.ErrorCode');
-
-goog.require('goog.debug.Error');
-goog.require('goog.object');
-goog.require('goog.string');
-
-
-
-/**
- * A filesystem error. Since the filesystem API is asynchronous, stack traces
- * are less useful for identifying where errors come from, so this includes a
- * large amount of metadata in the message.
- *
- * @param {!DOMError} error
- * @param {string} action The action being undertaken when the error was raised.
- * @constructor
- * @extends {goog.debug.Error}
- * @final
- */
-goog.fs.Error = function(error, action) {
- /** @type {string} */
- this.name;
-
- /**
- * @type {goog.fs.Error.ErrorCode}
- * @deprecated Use the 'name' or 'message' field instead.
- */
- this.code;
-
- if (goog.isDef(error.name)) {
- this.name = error.name;
- // TODO(user): Remove warning suppression after JSCompiler stops
- // firing a spurious warning here.
- /** @suppress {deprecated} */
- this.code = goog.fs.Error.getCodeFromName_(error.name);
- } else {
- this.code = error.code;
- this.name = goog.fs.Error.getNameFromCode_(error.code);
- }
- goog.fs.Error.base(this, 'constructor',
- goog.string.subs('%s %s', this.name, action));
-};
-goog.inherits(goog.fs.Error, goog.debug.Error);
-
-
-/**
- * Names of errors that may be thrown by the File API, the File System API, or
- * the File Writer API.
- *
- * @see http://dev.w3.org/2006/webapi/FileAPI/#ErrorAndException
- * @see http://www.w3.org/TR/file-system-api/#definitions
- * @see http://dev.w3.org/2009/dap/file-system/file-writer.html#definitions
- * @enum {string}
- */
-goog.fs.Error.ErrorName = {
- ABORT: 'AbortError',
- ENCODING: 'EncodingError',
- INVALID_MODIFICATION: 'InvalidModificationError',
- INVALID_STATE: 'InvalidStateError',
- NOT_FOUND: 'NotFoundError',
- NOT_READABLE: 'NotReadableError',
- NO_MODIFICATION_ALLOWED: 'NoModificationAllowedError',
- PATH_EXISTS: 'PathExistsError',
- QUOTA_EXCEEDED: 'QuotaExceededError',
- SECURITY: 'SecurityError',
- SYNTAX: 'SyntaxError',
- TYPE_MISMATCH: 'TypeMismatchError'
-};
-
-
-/**
- * Error codes for file errors.
- * @see http://www.w3.org/TR/file-system-api/#idl-def-FileException
- *
- * @enum {number}
- * @deprecated Use the 'name' or 'message' attribute instead.
- */
-goog.fs.Error.ErrorCode = {
- NOT_FOUND: 1,
- SECURITY: 2,
- ABORT: 3,
- NOT_READABLE: 4,
- ENCODING: 5,
- NO_MODIFICATION_ALLOWED: 6,
- INVALID_STATE: 7,
- SYNTAX: 8,
- INVALID_MODIFICATION: 9,
- QUOTA_EXCEEDED: 10,
- TYPE_MISMATCH: 11,
- PATH_EXISTS: 12
-};
-
-
-/**
- * @param {goog.fs.Error.ErrorCode} code
- * @return {string} name
- * @private
- */
-goog.fs.Error.getNameFromCode_ = function(code) {
- var name = goog.object.findKey(goog.fs.Error.NameToCodeMap_, function(c) {
- return code == c;
- });
- if (!goog.isDef(name)) {
- throw new Error('Invalid code: ' + code);
- }
- return name;
-};
-
-
-/**
- * Returns the code that corresponds to the given name.
- * @param {string} name
- * @return {goog.fs.Error.ErrorCode} code
- * @private
- */
-goog.fs.Error.getCodeFromName_ = function(name) {
- return goog.fs.Error.NameToCodeMap_[name];
-};
-
-
-/**
- * Mapping from error names to values from the ErrorCode enum.
- * @see http://www.w3.org/TR/file-system-api/#definitions.
- * @private {!Object<string, goog.fs.Error.ErrorCode>}
- */
-goog.fs.Error.NameToCodeMap_ = goog.object.create(
- goog.fs.Error.ErrorName.ABORT,
- goog.fs.Error.ErrorCode.ABORT,
-
- goog.fs.Error.ErrorName.ENCODING,
- goog.fs.Error.ErrorCode.ENCODING,
-
- goog.fs.Error.ErrorName.INVALID_MODIFICATION,
- goog.fs.Error.ErrorCode.INVALID_MODIFICATION,
-
- goog.fs.Error.ErrorName.INVALID_STATE,
- goog.fs.Error.ErrorCode.INVALID_STATE,
-
- goog.fs.Error.ErrorName.NOT_FOUND,
- goog.fs.Error.ErrorCode.NOT_FOUND,
-
- goog.fs.Error.ErrorName.NOT_READABLE,
- goog.fs.Error.ErrorCode.NOT_READABLE,
-
- goog.fs.Error.ErrorName.NO_MODIFICATION_ALLOWED,
- goog.fs.Error.ErrorCode.NO_MODIFICATION_ALLOWED,
-
- goog.fs.Error.ErrorName.PATH_EXISTS,
- goog.fs.Error.ErrorCode.PATH_EXISTS,
-
- goog.fs.Error.ErrorName.QUOTA_EXCEEDED,
- goog.fs.Error.ErrorCode.QUOTA_EXCEEDED,
-
- goog.fs.Error.ErrorName.SECURITY,
- goog.fs.Error.ErrorCode.SECURITY,
-
- goog.fs.Error.ErrorName.SYNTAX,
- goog.fs.Error.ErrorCode.SYNTAX,
-
- goog.fs.Error.ErrorName.TYPE_MISMATCH,
- goog.fs.Error.ErrorCode.TYPE_MISMATCH);
-
-// Copyright 2011 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview A wrapper for the HTML5 File ProgressEvent objects.
- *
- */
-goog.provide('goog.fs.ProgressEvent');
-
-goog.require('goog.events.Event');
-
-
-
-/**
- * A wrapper for the progress events emitted by the File APIs.
- *
- * @param {!ProgressEvent} event The underlying event object.
- * @param {!Object} target The file access object emitting the event.
- * @extends {goog.events.Event}
- * @constructor
- * @final
- */
-goog.fs.ProgressEvent = function(event, target) {
- goog.fs.ProgressEvent.base(this, 'constructor', event.type, target);
-
- /**
- * The underlying event object.
- * @type {!ProgressEvent}
- * @private
- */
- this.event_ = event;
-};
-goog.inherits(goog.fs.ProgressEvent, goog.events.Event);
-
-
-/**
- * @return {boolean} Whether or not the total size of the of the file being
- * saved is known.
- */
-goog.fs.ProgressEvent.prototype.isLengthComputable = function() {
- return this.event_.lengthComputable;
-};
-
-
-/**
- * @return {number} The number of bytes saved so far.
- */
-goog.fs.ProgressEvent.prototype.getLoaded = function() {
- return this.event_.loaded;
-};
-
-
-/**
- * @return {number} The total number of bytes in the file being saved.
- */
-goog.fs.ProgressEvent.prototype.getTotal = function() {
- return this.event_.total;
-};
-
-// Copyright 2011 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview A wrapper for the HTML5 FileReader object.
- *
- */
-
-goog.provide('goog.fs.FileReader');
-goog.provide('goog.fs.FileReader.EventType');
-goog.provide('goog.fs.FileReader.ReadyState');
-
-goog.require('goog.async.Deferred');
-goog.require('goog.events.EventTarget');
-goog.require('goog.fs.Error');
-goog.require('goog.fs.ProgressEvent');
-
-
-
-/**
- * An object for monitoring the reading of files. This emits ProgressEvents of
- * the types listed in {@link goog.fs.FileReader.EventType}.
- *
- * @constructor
- * @extends {goog.events.EventTarget}
- * @final
- */
-goog.fs.FileReader = function() {
- goog.fs.FileReader.base(this, 'constructor');
-
- /**
- * The underlying FileReader object.
- *
- * @type {!FileReader}
- * @private
- */
- this.reader_ = new FileReader();
-
- this.reader_.onloadstart = goog.bind(this.dispatchProgressEvent_, this);
- this.reader_.onprogress = goog.bind(this.dispatchProgressEvent_, this);
- this.reader_.onload = goog.bind(this.dispatchProgressEvent_, this);
- this.reader_.onabort = goog.bind(this.dispatchProgressEvent_, this);
- this.reader_.onerror = goog.bind(this.dispatchProgressEvent_, this);
- this.reader_.onloadend = goog.bind(this.dispatchProgressEvent_, this);
-};
-goog.inherits(goog.fs.FileReader, goog.events.EventTarget);
-
-
-/**
- * Possible states for a FileReader.
- *
- * @enum {number}
- */
-goog.fs.FileReader.ReadyState = {
- /**
- * The object has been constructed, but there is no pending read.
- */
- INIT: 0,
- /**
- * Data is being read.
- */
- LOADING: 1,
- /**
- * The data has been read from the file, the read was aborted, or an error
- * occurred.
- */
- DONE: 2
-};
-
-
-/**
- * Events emitted by a FileReader.
- *
- * @enum {string}
- */
-goog.fs.FileReader.EventType = {
- /**
- * Emitted when the reading begins. readyState will be LOADING.
- */
- LOAD_START: 'loadstart',
- /**
- * Emitted when progress has been made in reading the file. readyState will be
- * LOADING.
- */
- PROGRESS: 'progress',
- /**
- * Emitted when the data has been successfully read. readyState will be
- * LOADING.
- */
- LOAD: 'load',
- /**
- * Emitted when the reading has been aborted. readyState will be LOADING.
- */
- ABORT: 'abort',
- /**
- * Emitted when an error is encountered or the reading has been aborted.
- * readyState will be LOADING.
- */
- ERROR: 'error',
- /**
- * Emitted when the reading is finished, whether successfully or not.
- * readyState will be DONE.
- */
- LOAD_END: 'loadend'
-};
-
-
-/**
- * Abort the reading of the file.
- */
-goog.fs.FileReader.prototype.abort = function() {
- try {
- this.reader_.abort();
- } catch (e) {
- throw new goog.fs.Error(e, 'aborting read');
- }
-};
-
-
-/**
- * @return {goog.fs.FileReader.ReadyState} The current state of the FileReader.
- */
-goog.fs.FileReader.prototype.getReadyState = function() {
- return /** @type {goog.fs.FileReader.ReadyState} */ (this.reader_.readyState);
-};
-
-
-/**
- * @return {*} The result of the file read.
- */
-goog.fs.FileReader.prototype.getResult = function() {
- return this.reader_.result;
-};
-
-
-/**
- * @return {goog.fs.Error} The error encountered while reading, if any.
- */
-goog.fs.FileReader.prototype.getError = function() {
- return this.reader_.error &&
- new goog.fs.Error(this.reader_.error, 'reading file');
-};
-
-
-/**
- * Wrap a progress event emitted by the underlying file reader and re-emit it.
- *
- * @param {!ProgressEvent} event The underlying event.
- * @private
- */
-goog.fs.FileReader.prototype.dispatchProgressEvent_ = function(event) {
- this.dispatchEvent(new goog.fs.ProgressEvent(event, this));
-};
-
-
-/** @override */
-goog.fs.FileReader.prototype.disposeInternal = function() {
- goog.fs.FileReader.base(this, 'disposeInternal');
- delete this.reader_;
-};
-
-
-/**
- * Starts reading a blob as a binary string.
- * @param {!Blob} blob The blob to read.
- */
-goog.fs.FileReader.prototype.readAsBinaryString = function(blob) {
- this.reader_.readAsBinaryString(blob);
-};
-
-
-/**
- * Reads a blob as a binary string.
- * @param {!Blob} blob The blob to read.
- * @return {!goog.async.Deferred} The deferred Blob contents as a binary string.
- * If an error occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.FileReader.readAsBinaryString = function(blob) {
- var reader = new goog.fs.FileReader();
- var d = goog.fs.FileReader.createDeferred_(reader);
- reader.readAsBinaryString(blob);
- return d;
-};
-
-
-/**
- * Starts reading a blob as an array buffer.
- * @param {!Blob} blob The blob to read.
- */
-goog.fs.FileReader.prototype.readAsArrayBuffer = function(blob) {
- this.reader_.readAsArrayBuffer(blob);
-};
-
-
-/**
- * Reads a blob as an array buffer.
- * @param {!Blob} blob The blob to read.
- * @return {!goog.async.Deferred} The deferred Blob contents as an array buffer.
- * If an error occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.FileReader.readAsArrayBuffer = function(blob) {
- var reader = new goog.fs.FileReader();
- var d = goog.fs.FileReader.createDeferred_(reader);
- reader.readAsArrayBuffer(blob);
- return d;
-};
-
-
-/**
- * Starts reading a blob as text.
- * @param {!Blob} blob The blob to read.
- * @param {string=} opt_encoding The name of the encoding to use.
- */
-goog.fs.FileReader.prototype.readAsText = function(blob, opt_encoding) {
- this.reader_.readAsText(blob, opt_encoding);
-};
-
-
-/**
- * Reads a blob as text.
- * @param {!Blob} blob The blob to read.
- * @param {string=} opt_encoding The name of the encoding to use.
- * @return {!goog.async.Deferred} The deferred Blob contents as text.
- * If an error occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.FileReader.readAsText = function(blob, opt_encoding) {
- var reader = new goog.fs.FileReader();
- var d = goog.fs.FileReader.createDeferred_(reader);
- reader.readAsText(blob, opt_encoding);
- return d;
-};
-
-
-/**
- * Starts reading a blob as a data URL.
- * @param {!Blob} blob The blob to read.
- */
-goog.fs.FileReader.prototype.readAsDataUrl = function(blob) {
- this.reader_.readAsDataURL(blob);
-};
-
-
-/**
- * Reads a blob as a data URL.
- * @param {!Blob} blob The blob to read.
- * @return {!goog.async.Deferred} The deferred Blob contents as a data URL.
- * If an error occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.FileReader.readAsDataUrl = function(blob) {
- var reader = new goog.fs.FileReader();
- var d = goog.fs.FileReader.createDeferred_(reader);
- reader.readAsDataUrl(blob);
- return d;
-};
-
-
-/**
- * Creates a new deferred object for the results of a read method.
- * @param {goog.fs.FileReader} reader The reader to create a deferred for.
- * @return {!goog.async.Deferred} The deferred results.
- * @private
- */
-goog.fs.FileReader.createDeferred_ = function(reader) {
- var deferred = new goog.async.Deferred();
- reader.listen(goog.fs.FileReader.EventType.LOAD_END,
- goog.partial(function(d, r, e) {
- var result = r.getResult();
- var error = r.getError();
- if (result != null && !error) {
- d.callback(result);
- } else {
- d.errback(error);
- }
- r.dispose();
- }, deferred, reader));
- return deferred;
-};
-
// FIXME should handle all geo-referenced data, not just vector data
goog.provide('ol.interaction.DragAndDrop');
goog.provide('ol.interaction.DragAndDropEvent');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.events.FileDropHandler');
-goog.require('goog.events.FileDropHandler.EventType');
-goog.require('goog.fs.FileReader');
-goog.require('goog.functions');
+goog.require('ol.functions');
+goog.require('ol.events');
+goog.require('ol.events.Event');
+goog.require('ol.events.EventType');
goog.require('ol.interaction.Interaction');
goog.require('ol.proj');
-
/**
* @classdesc
* Handles input of vector data by drag and drop.
@@ -110205,54 +94833,56 @@ ol.interaction.DragAndDrop = function(opt_options) {
/**
* @private
- * @type {goog.events.FileDropHandler}
+ * @type {Array.<ol.events.Key>}
*/
- this.fileDropHandler_ = null;
+ this.dropListenKeys_ = null;
/**
* @private
- * @type {goog.events.Key|undefined}
+ * @type {Element}
*/
- this.dropListenKey_ = undefined;
+ this.target = options.target ? options.target : null;
};
goog.inherits(ol.interaction.DragAndDrop, ol.interaction.Interaction);
/**
- * @inheritDoc
+ * @param {Event} event Event.
+ * @this {ol.interaction.DragAndDrop}
+ * @private
*/
-ol.interaction.DragAndDrop.prototype.disposeInternal = function() {
- if (this.dropListenKey_) {
- goog.events.unlistenByKey(this.dropListenKey_);
+ol.interaction.DragAndDrop.handleDrop_ = function(event) {
+ var files = event.dataTransfer.files;
+ var i, ii, file;
+ for (i = 0, ii = files.length; i < ii; ++i) {
+ file = files.item(i);
+ var reader = new FileReader();
+ reader.addEventListener(ol.events.EventType.LOAD,
+ this.handleResult_.bind(this, file));
+ reader.readAsText(file);
}
- goog.base(this, 'disposeInternal');
};
/**
- * @param {goog.events.BrowserEvent} event Event.
+ * @param {Event} event Event.
* @private
*/
-ol.interaction.DragAndDrop.prototype.handleDrop_ = function(event) {
- var files = event.getBrowserEvent().dataTransfer.files;
- var i, ii, file;
- for (i = 0, ii = files.length; i < ii; ++i) {
- file = files[i];
- // The empty string param is a workaround for
- // https://code.google.com/p/closure-library/issues/detail?id=524
- var reader = goog.fs.FileReader.readAsText(file, '');
- reader.addCallback(goog.partial(this.handleResult_, file), this);
- }
+ol.interaction.DragAndDrop.handleStop_ = function(event) {
+ event.stopPropagation();
+ event.preventDefault();
+ event.dataTransfer.dropEffect = 'copy';
};
/**
* @param {File} file File.
- * @param {string} result Result.
+ * @param {Event} event Load event.
* @private
*/
-ol.interaction.DragAndDrop.prototype.handleResult_ = function(file, result) {
+ol.interaction.DragAndDrop.prototype.handleResult_ = function(file, event) {
+ var result = event.target.result;
var map = this.getMap();
goog.asserts.assert(map, 'map must be set');
var projection = this.projection_;
@@ -110269,19 +94899,11 @@ ol.interaction.DragAndDrop.prototype.handleResult_ = function(file, result) {
for (i = 0, ii = formatConstructors.length; i < ii; ++i) {
var formatConstructor = formatConstructors[i];
var format = new formatConstructor();
- var readFeatures = this.tryReadFeatures_(format, result);
- if (readFeatures) {
- var featureProjection = format.readProjection(result);
- var transform = ol.proj.getTransform(featureProjection, projection);
- var j, jj;
- for (j = 0, jj = readFeatures.length; j < jj; ++j) {
- var feature = readFeatures[j];
- var geometry = feature.getGeometry();
- if (geometry) {
- geometry.applyTransform(transform);
- }
- features.push(feature);
- }
+ features = this.tryReadFeatures_(format, result, {
+ featureProjection: projection
+ });
+ if (features && features.length > 0) {
+ break;
}
}
this.dispatchEvent(
@@ -110299,29 +94921,30 @@ ol.interaction.DragAndDrop.prototype.handleResult_ = function(file, result) {
* @this {ol.interaction.DragAndDrop}
* @api
*/
-ol.interaction.DragAndDrop.handleEvent = goog.functions.TRUE;
+ol.interaction.DragAndDrop.handleEvent = ol.functions.TRUE;
/**
* @inheritDoc
*/
ol.interaction.DragAndDrop.prototype.setMap = function(map) {
- if (this.dropListenKey_) {
- goog.events.unlistenByKey(this.dropListenKey_);
- this.dropListenKey_ = undefined;
- }
- if (this.fileDropHandler_) {
- goog.dispose(this.fileDropHandler_);
- this.fileDropHandler_ = null;
+ if (this.dropListenKeys_) {
+ this.dropListenKeys_.forEach(ol.events.unlistenByKey);
+ this.dropListenKeys_ = null;
}
- goog.asserts.assert(this.dropListenKey_ === undefined,
- 'this.dropListenKey_ should be undefined');
goog.base(this, 'setMap', map);
if (map) {
- this.fileDropHandler_ = new goog.events.FileDropHandler(map.getViewport());
- this.dropListenKey_ = goog.events.listen(
- this.fileDropHandler_, goog.events.FileDropHandler.EventType.DROP,
- this.handleDrop_, false, this);
+ var dropArea = this.target ? this.target : map.getViewport();
+ this.dropListenKeys_ = [
+ ol.events.listen(dropArea, ol.events.EventType.DROP,
+ ol.interaction.DragAndDrop.handleDrop_, this),
+ ol.events.listen(dropArea, ol.events.EventType.DRAGENTER,
+ ol.interaction.DragAndDrop.handleStop_, this),
+ ol.events.listen(dropArea, ol.events.EventType.DRAGOVER,
+ ol.interaction.DragAndDrop.handleStop_, this),
+ ol.events.listen(dropArea, ol.events.EventType.DROP,
+ ol.interaction.DragAndDrop.handleStop_, this)
+ ]
}
};
@@ -110329,12 +94952,13 @@ ol.interaction.DragAndDrop.prototype.setMap = function(map) {
/**
* @param {ol.format.Feature} format Format.
* @param {string} text Text.
+ * @param {olx.format.ReadOptions} options Read options.
* @private
* @return {Array.<ol.Feature>} Features.
*/
-ol.interaction.DragAndDrop.prototype.tryReadFeatures_ = function(format, text) {
+ol.interaction.DragAndDrop.prototype.tryReadFeatures_ = function(format, text, options) {
try {
- return format.readFeatures(text);
+ return format.readFeatures(text, options);
} catch (e) {
return null;
}
@@ -110354,14 +94978,13 @@ ol.interaction.DragAndDropEventType = {
};
-
/**
* @classdesc
* Events emitted by {@link ol.interaction.DragAndDrop} instances are instances
* of this type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.interaction.DragAndDropEvent}
* @param {ol.interaction.DragAndDropEventType} type Type.
* @param {Object} target Target.
@@ -110369,8 +94992,7 @@ ol.interaction.DragAndDropEventType = {
* @param {Array.<ol.Feature>=} opt_features Features.
* @param {ol.proj.Projection=} opt_projection Projection.
*/
-ol.interaction.DragAndDropEvent =
- function(type, target, file, opt_features, opt_projection) {
+ol.interaction.DragAndDropEvent = function(type, target, file, opt_features, opt_projection) {
goog.base(this, type, target);
@@ -110396,316 +95018,17 @@ ol.interaction.DragAndDropEvent =
this.projection = opt_projection;
};
-goog.inherits(ol.interaction.DragAndDropEvent, goog.events.Event);
-
-// Copyright 2007 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview Defines a 2-element vector class that can be used for
- * coordinate math, useful for animation systems and point manipulation.
- *
- * Vec2 objects inherit from goog.math.Coordinate and may be used wherever a
- * Coordinate is required. Where appropriate, Vec2 functions accept both Vec2
- * and Coordinate objects as input.
- *
- * @author brenneman@google.com (Shawn Brenneman)
- */
-
-goog.provide('goog.math.Vec2');
-
-goog.require('goog.math');
-goog.require('goog.math.Coordinate');
-
-
-
-/**
- * Class for a two-dimensional vector object and assorted functions useful for
- * manipulating points.
- *
- * @param {number} x The x coordinate for the vector.
- * @param {number} y The y coordinate for the vector.
- * @struct
- * @constructor
- * @extends {goog.math.Coordinate}
- */
-goog.math.Vec2 = function(x, y) {
- /**
- * X-value
- * @type {number}
- */
- this.x = x;
-
- /**
- * Y-value
- * @type {number}
- */
- this.y = y;
-};
-goog.inherits(goog.math.Vec2, goog.math.Coordinate);
-
-
-/**
- * @return {!goog.math.Vec2} A random unit-length vector.
- */
-goog.math.Vec2.randomUnit = function() {
- var angle = Math.random() * Math.PI * 2;
- return new goog.math.Vec2(Math.cos(angle), Math.sin(angle));
-};
-
-
-/**
- * @return {!goog.math.Vec2} A random vector inside the unit-disc.
- */
-goog.math.Vec2.random = function() {
- var mag = Math.sqrt(Math.random());
- var angle = Math.random() * Math.PI * 2;
-
- return new goog.math.Vec2(Math.cos(angle) * mag, Math.sin(angle) * mag);
-};
-
-
-/**
- * Returns a new Vec2 object from a given coordinate.
- * @param {!goog.math.Coordinate} a The coordinate.
- * @return {!goog.math.Vec2} A new vector object.
- */
-goog.math.Vec2.fromCoordinate = function(a) {
- return new goog.math.Vec2(a.x, a.y);
-};
-
-
-/**
- * @return {!goog.math.Vec2} A new vector with the same coordinates as this one.
- * @override
- */
-goog.math.Vec2.prototype.clone = function() {
- return new goog.math.Vec2(this.x, this.y);
-};
-
-
-/**
- * Returns the magnitude of the vector measured from the origin.
- * @return {number} The length of the vector.
- */
-goog.math.Vec2.prototype.magnitude = function() {
- return Math.sqrt(this.x * this.x + this.y * this.y);
-};
-
-
-/**
- * Returns the squared magnitude of the vector measured from the origin.
- * NOTE(brenneman): Leaving out the square root is not a significant
- * optimization in JavaScript.
- * @return {number} The length of the vector, squared.
- */
-goog.math.Vec2.prototype.squaredMagnitude = function() {
- return this.x * this.x + this.y * this.y;
-};
-
-
-/**
- * @return {!goog.math.Vec2} This coordinate after scaling.
- * @override
- */
-goog.math.Vec2.prototype.scale =
- /** @type {function(number, number=):!goog.math.Vec2} */
- (goog.math.Coordinate.prototype.scale);
-
-
-/**
- * Reverses the sign of the vector. Equivalent to scaling the vector by -1.
- * @return {!goog.math.Vec2} The inverted vector.
- */
-goog.math.Vec2.prototype.invert = function() {
- this.x = -this.x;
- this.y = -this.y;
- return this;
-};
-
-
-/**
- * Normalizes the current vector to have a magnitude of 1.
- * @return {!goog.math.Vec2} The normalized vector.
- */
-goog.math.Vec2.prototype.normalize = function() {
- return this.scale(1 / this.magnitude());
-};
-
-
-/**
- * Adds another vector to this vector in-place.
- * @param {!goog.math.Coordinate} b The vector to add.
- * @return {!goog.math.Vec2} This vector with {@code b} added.
- */
-goog.math.Vec2.prototype.add = function(b) {
- this.x += b.x;
- this.y += b.y;
- return this;
-};
-
-
-/**
- * Subtracts another vector from this vector in-place.
- * @param {!goog.math.Coordinate} b The vector to subtract.
- * @return {!goog.math.Vec2} This vector with {@code b} subtracted.
- */
-goog.math.Vec2.prototype.subtract = function(b) {
- this.x -= b.x;
- this.y -= b.y;
- return this;
-};
-
-
-/**
- * Rotates this vector in-place by a given angle, specified in radians.
- * @param {number} angle The angle, in radians.
- * @return {!goog.math.Vec2} This vector rotated {@code angle} radians.
- */
-goog.math.Vec2.prototype.rotate = function(angle) {
- var cos = Math.cos(angle);
- var sin = Math.sin(angle);
- var newX = this.x * cos - this.y * sin;
- var newY = this.y * cos + this.x * sin;
- this.x = newX;
- this.y = newY;
- return this;
-};
-
-
-/**
- * Rotates a vector by a given angle, specified in radians, relative to a given
- * axis rotation point. The returned vector is a newly created instance - no
- * in-place changes are done.
- * @param {!goog.math.Vec2} v A vector.
- * @param {!goog.math.Vec2} axisPoint The rotation axis point.
- * @param {number} angle The angle, in radians.
- * @return {!goog.math.Vec2} The rotated vector in a newly created instance.
- */
-goog.math.Vec2.rotateAroundPoint = function(v, axisPoint, angle) {
- var res = v.clone();
- return res.subtract(axisPoint).rotate(angle).add(axisPoint);
-};
-
-
-/**
- * Compares this vector with another for equality.
- * @param {!goog.math.Vec2} b The other vector.
- * @return {boolean} Whether this vector has the same x and y as the given
- * vector.
- */
-goog.math.Vec2.prototype.equals = function(b) {
- return this == b || !!b && this.x == b.x && this.y == b.y;
-};
-
-
-/**
- * Returns the distance between two vectors.
- * @param {!goog.math.Coordinate} a The first vector.
- * @param {!goog.math.Coordinate} b The second vector.
- * @return {number} The distance.
- */
-goog.math.Vec2.distance = goog.math.Coordinate.distance;
-
-
-/**
- * Returns the squared distance between two vectors.
- * @param {!goog.math.Coordinate} a The first vector.
- * @param {!goog.math.Coordinate} b The second vector.
- * @return {number} The squared distance.
- */
-goog.math.Vec2.squaredDistance = goog.math.Coordinate.squaredDistance;
-
-
-/**
- * Compares vectors for equality.
- * @param {!goog.math.Coordinate} a The first vector.
- * @param {!goog.math.Coordinate} b The second vector.
- * @return {boolean} Whether the vectors have the same x and y coordinates.
- */
-goog.math.Vec2.equals = goog.math.Coordinate.equals;
-
-
-/**
- * Returns the sum of two vectors as a new Vec2.
- * @param {!goog.math.Coordinate} a The first vector.
- * @param {!goog.math.Coordinate} b The second vector.
- * @return {!goog.math.Vec2} The sum vector.
- */
-goog.math.Vec2.sum = function(a, b) {
- return new goog.math.Vec2(a.x + b.x, a.y + b.y);
-};
-
-
-/**
- * Returns the difference between two vectors as a new Vec2.
- * @param {!goog.math.Coordinate} a The first vector.
- * @param {!goog.math.Coordinate} b The second vector.
- * @return {!goog.math.Vec2} The difference vector.
- */
-goog.math.Vec2.difference = function(a, b) {
- return new goog.math.Vec2(a.x - b.x, a.y - b.y);
-};
-
-
-/**
- * Returns the dot-product of two vectors.
- * @param {!goog.math.Coordinate} a The first vector.
- * @param {!goog.math.Coordinate} b The second vector.
- * @return {number} The dot-product of the two vectors.
- */
-goog.math.Vec2.dot = function(a, b) {
- return a.x * b.x + a.y * b.y;
-};
-
-
-/**
- * Returns the determinant of two vectors.
- * @param {!goog.math.Vec2} a The first vector.
- * @param {!goog.math.Vec2} b The second vector.
- * @return {number} The determinant of the two vectors.
- */
-goog.math.Vec2.determinant = function(a, b) {
- return a.x * b.y - a.y * b.x;
-};
-
-
-/**
- * Returns a new Vec2 that is the linear interpolant between vectors a and b at
- * scale-value x.
- * @param {!goog.math.Coordinate} a Vector a.
- * @param {!goog.math.Coordinate} b Vector b.
- * @param {number} x The proportion between a and b.
- * @return {!goog.math.Vec2} The interpolated vector.
- */
-goog.math.Vec2.lerp = function(a, b, x) {
- return new goog.math.Vec2(goog.math.lerp(a.x, b.x, x),
- goog.math.lerp(a.y, b.y, x));
-};
+goog.inherits(ol.interaction.DragAndDropEvent, ol.events.Event);
goog.provide('ol.interaction.DragRotateAndZoom');
-goog.require('goog.math.Vec2');
goog.require('ol');
goog.require('ol.ViewHint');
-goog.require('ol.events.ConditionType');
goog.require('ol.events.condition');
goog.require('ol.interaction.Interaction');
goog.require('ol.interaction.Pointer');
-
/**
* @classdesc
* Allows the user to zoom and rotate the map by clicking and dragging
@@ -110779,11 +95102,10 @@ ol.interaction.DragRotateAndZoom.handleDragEvent_ = function(mapBrowserEvent) {
var map = mapBrowserEvent.map;
var size = map.getSize();
var offset = mapBrowserEvent.pixel;
- var delta = new goog.math.Vec2(
- offset[0] - size[0] / 2,
- size[1] / 2 - offset[1]);
- var theta = Math.atan2(delta.y, delta.x);
- var magnitude = delta.magnitude();
+ var deltaX = offset[0] - size[0] / 2;
+ var deltaY = size[1] / 2 - offset[1];
+ var theta = Math.atan2(deltaY, deltaX);
+ var magnitude = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var view = map.getView();
map.render();
if (this.lastAngle_ !== undefined) {
@@ -110850,19 +95172,18 @@ ol.interaction.DragRotateAndZoom.handleDownEvent_ = function(mapBrowserEvent) {
goog.provide('ol.interaction.Draw');
goog.provide('ol.interaction.DrawEvent');
goog.provide('ol.interaction.DrawEventType');
-goog.provide('ol.interaction.DrawGeometryFunctionType');
goog.provide('ol.interaction.DrawMode');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.Event');
+goog.require('ol.events');
+goog.require('ol.events.Event');
goog.require('ol.Collection');
-goog.require('ol.Coordinate');
goog.require('ol.Feature');
goog.require('ol.MapBrowserEvent');
goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.Object');
goog.require('ol.coordinate');
+goog.require('ol.functions');
goog.require('ol.events.condition');
goog.require('ol.geom.Circle');
goog.require('ol.geom.GeometryType');
@@ -110898,14 +95219,13 @@ ol.interaction.DrawEventType = {
};
-
/**
* @classdesc
* Events emitted by {@link ol.interaction.Draw} instances are instances of
* this type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.DrawEvent}
* @param {ol.interaction.DrawEventType} type Type.
* @param {ol.Feature} feature The feature drawn.
@@ -110922,8 +95242,7 @@ ol.interaction.DrawEvent = function(type, feature) {
this.feature = feature;
};
-goog.inherits(ol.interaction.DrawEvent, goog.events.Event);
-
+goog.inherits(ol.interaction.DrawEvent, ol.events.Event);
/**
@@ -111010,13 +95329,21 @@ ol.interaction.Draw = function(options) {
*/
this.maxPoints_ = options.maxPoints ? options.maxPoints : Infinity;
+ /**
+ * A function to decide if a potential finish coordinate is permissable
+ * @private
+ * @type {ol.events.ConditionType}
+ */
+ this.finishCondition_ = options.finishCondition ? options.finishCondition : ol.functions.TRUE;
+
var geometryFunction = options.geometryFunction;
if (!geometryFunction) {
if (this.type_ === ol.geom.GeometryType.CIRCLE) {
/**
* @param {ol.Coordinate|Array.<ol.Coordinate>|Array.<Array.<ol.Coordinate>>} coordinates
- * @param {ol.geom.SimpleGeometry=} opt_geometry
- * @return {ol.geom.SimpleGeometry}
+ * The coordinates.
+ * @param {ol.geom.SimpleGeometry=} opt_geometry Optional geometry.
+ * @return {ol.geom.SimpleGeometry} A geometry.
*/
geometryFunction = function(coordinates, opt_geometry) {
var circle = opt_geometry ? opt_geometry :
@@ -111040,8 +95367,9 @@ ol.interaction.Draw = function(options) {
}
/**
* @param {ol.Coordinate|Array.<ol.Coordinate>|Array.<Array.<ol.Coordinate>>} coordinates
- * @param {ol.geom.SimpleGeometry=} opt_geometry
- * @return {ol.geom.SimpleGeometry}
+ * The coordinates.
+ * @param {ol.geom.SimpleGeometry=} opt_geometry Optional geometry.
+ * @return {ol.geom.SimpleGeometry} A geometry.
*/
geometryFunction = function(coordinates, opt_geometry) {
var geometry = opt_geometry;
@@ -111149,9 +95477,9 @@ ol.interaction.Draw = function(options) {
this.freehandCondition_ = options.freehandCondition ?
options.freehandCondition : ol.events.condition.shiftKeyOnly;
- goog.events.listen(this,
+ ol.events.listen(this,
ol.Object.getChangeEventType(ol.interaction.InteractionProperty.ACTIVE),
- this.updateState_, false, this);
+ this.updateState_, this);
};
goog.inherits(ol.interaction.Draw, ol.interaction.Pointer);
@@ -111186,6 +95514,11 @@ ol.interaction.Draw.prototype.setMap = function(map) {
* @api
*/
ol.interaction.Draw.handleEvent = function(mapBrowserEvent) {
+ if ((this.mode_ === ol.interaction.DrawMode.LINE_STRING ||
+ this.mode_ === ol.interaction.DrawMode.POLYGON) &&
+ this.freehandCondition_(mapBrowserEvent)) {
+ this.freehand_ = true;
+ }
var pass = !this.freehand_;
if (this.freehand_ &&
mapBrowserEvent.type === ol.MapBrowserEvent.EventType.POINTERDRAG) {
@@ -111211,11 +95544,8 @@ ol.interaction.Draw.handleDownEvent_ = function(event) {
if (this.condition_(event)) {
this.downPx_ = event.pixel;
return true;
- } else if ((this.mode_ === ol.interaction.DrawMode.LINE_STRING ||
- this.mode_ === ol.interaction.DrawMode.POLYGON) &&
- this.freehandCondition_(event)) {
+ } else if (this.freehand_) {
this.downPx_ = event.pixel;
- this.freehand_ = true;
if (!this.finishCoordinate_) {
this.startDrawing_(event);
}
@@ -111250,7 +95580,9 @@ ol.interaction.Draw.handleUpEvent_ = function(event) {
} else if (this.mode_ === ol.interaction.DrawMode.CIRCLE) {
this.finishDrawing();
} else if (this.atFinish_(event)) {
- this.finishDrawing();
+ if (this.finishCondition_(event)) {
+ this.finishDrawing();
+ }
} else {
this.addToDrawing_(event);
}
@@ -111588,7 +95920,7 @@ ol.interaction.Draw.prototype.extend = function(feature) {
/**
* @inheritDoc
*/
-ol.interaction.Draw.prototype.shouldStopEvent = goog.functions.FALSE;
+ol.interaction.Draw.prototype.shouldStopEvent = ol.functions.FALSE;
/**
@@ -111690,19 +96022,6 @@ ol.interaction.Draw.getMode_ = function(type) {
/**
- * Function that takes coordinates and an optional existing geometry as
- * arguments, and returns a geometry. The optional existing geometry is the
- * geometry that is returned when the function is called without a second
- * argument.
- * @typedef {function(!(ol.Coordinate|Array.<ol.Coordinate>|
- * Array.<Array.<ol.Coordinate>>), ol.geom.SimpleGeometry=):
- * ol.geom.SimpleGeometry}
- * @api
- */
-ol.interaction.DrawGeometryFunctionType;
-
-
-/**
* Draw mode. This collapses multi-part geometry types with their single-part
* cousins.
* @enum {string}
@@ -111717,12 +96036,10 @@ ol.interaction.DrawMode = {
goog.provide('ol.interaction.Modify');
goog.provide('ol.interaction.ModifyEvent');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventType');
-goog.require('goog.functions');
+goog.require('ol.events');
+goog.require('ol.events.Event');
+goog.require('ol.events.EventType');
goog.require('ol');
goog.require('ol.Collection');
goog.require('ol.CollectionEventType');
@@ -111730,6 +96047,7 @@ goog.require('ol.Feature');
goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.MapBrowserPointerEvent');
goog.require('ol.ViewHint');
+goog.require('ol.array');
goog.require('ol.coordinate');
goog.require('ol.events.condition');
goog.require('ol.extent');
@@ -111765,14 +96083,13 @@ ol.ModifyEventType = {
};
-
/**
* @classdesc
* Events emitted by {@link ol.interaction.Modify} instances are instances of
* this type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.ModifyEvent}
* @param {ol.ModifyEventType} type Type.
* @param {ol.Collection.<ol.Feature>} features The features modified.
@@ -111797,18 +96114,7 @@ ol.interaction.ModifyEvent = function(type, features, mapBrowserPointerEvent) {
*/
this.mapBrowserPointerEvent = mapBrowserPointerEvent;
};
-goog.inherits(ol.interaction.ModifyEvent, goog.events.Event);
-
-
-/**
- * @typedef {{depth: (Array.<number>|undefined),
- * feature: ol.Feature,
- * geometry: ol.geom.SimpleGeometry,
- * index: (number|undefined),
- * segment: Array.<ol.Extent>}}
- */
-ol.interaction.SegmentDataType;
-
+goog.inherits(ol.interaction.ModifyEvent, ol.events.Event);
/**
@@ -111831,14 +96137,29 @@ ol.interaction.Modify = function(options) {
});
/**
+ * @private
+ * @type {ol.events.ConditionType}
+ */
+ this.condition_ = options.condition ?
+ options.condition : ol.events.condition.primaryAction;
+
+
+ /**
+ * @private
+ * @param {ol.MapBrowserEvent} mapBrowserEvent Browser event.
+ * @return {boolean} Combined condition result.
+ */
+ this.defaultDeleteCondition_ = function(mapBrowserEvent) {
+ return ol.events.condition.noModifierKeys(mapBrowserEvent) &&
+ ol.events.condition.singleClick(mapBrowserEvent);
+ }
+
+ /**
* @type {ol.events.ConditionType}
* @private
*/
this.deleteCondition_ = options.deleteCondition ?
- options.deleteCondition :
- /** @type {ol.events.ConditionType} */ (goog.functions.and(
- ol.events.condition.noModifierKeys,
- ol.events.condition.singleClick));
+ options.deleteCondition : this.defaultDeleteCondition_;
/**
* Editing vertex.
@@ -111906,7 +96227,7 @@ ol.interaction.Modify = function(options) {
* @type {Array}
* @private
*/
- this.dragSegments_ = null;
+ this.dragSegments_ = [];
/**
* Draw overlay where sketch features are drawn.
@@ -111947,10 +96268,16 @@ ol.interaction.Modify = function(options) {
this.features_ = options.features;
this.features_.forEach(this.addFeature_, this);
- goog.events.listen(this.features_, ol.CollectionEventType.ADD,
- this.handleFeatureAdd_, false, this);
- goog.events.listen(this.features_, ol.CollectionEventType.REMOVE,
- this.handleFeatureRemove_, false, this);
+ ol.events.listen(this.features_, ol.CollectionEventType.ADD,
+ this.handleFeatureAdd_, this);
+ ol.events.listen(this.features_, ol.CollectionEventType.REMOVE,
+ this.handleFeatureRemove_, this);
+
+ /**
+ * @type {ol.MapBrowserPointerEvent}
+ * @private
+ */
+ this.lastPointerEvent_ = null;
};
goog.inherits(ol.interaction.Modify, ol.interaction.Pointer);
@@ -111969,8 +96296,8 @@ ol.interaction.Modify.prototype.addFeature_ = function(feature) {
if (map) {
this.handlePointerAtPixel_(this.lastPixel_, map);
}
- goog.events.listen(feature, goog.events.EventType.CHANGE,
- this.handleFeatureChange_, false, this);
+ ol.events.listen(feature, ol.events.EventType.CHANGE,
+ this.handleFeatureChange_, this);
};
@@ -111999,8 +96326,8 @@ ol.interaction.Modify.prototype.removeFeature_ = function(feature) {
this.overlay_.getSource().removeFeature(this.vertexFeature_);
this.vertexFeature_ = null;
}
- goog.events.unlisten(feature, goog.events.EventType.CHANGE,
- this.handleFeatureChange_, false, this);
+ ol.events.unlisten(feature, ol.events.EventType.CHANGE,
+ this.handleFeatureChange_, this);
};
@@ -112048,7 +96375,7 @@ ol.interaction.Modify.prototype.handleFeatureAdd_ = function(evt) {
/**
- * @param {goog.events.Event} evt Event.
+ * @param {ol.events.Event} evt Event.
* @private
*/
ol.interaction.Modify.prototype.handleFeatureChange_ = function(evt) {
@@ -112075,8 +96402,7 @@ ol.interaction.Modify.prototype.handleFeatureRemove_ = function(evt) {
* @param {ol.geom.Point} geometry Geometry.
* @private
*/
-ol.interaction.Modify.prototype.writePointGeometry_ =
- function(feature, geometry) {
+ol.interaction.Modify.prototype.writePointGeometry_ = function(feature, geometry) {
var coordinates = geometry.getCoordinates();
var segmentData = /** @type {ol.interaction.SegmentDataType} */ ({
feature: feature,
@@ -112092,8 +96418,7 @@ ol.interaction.Modify.prototype.writePointGeometry_ =
* @param {ol.geom.MultiPoint} geometry Geometry.
* @private
*/
-ol.interaction.Modify.prototype.writeMultiPointGeometry_ =
- function(feature, geometry) {
+ol.interaction.Modify.prototype.writeMultiPointGeometry_ = function(feature, geometry) {
var points = geometry.getCoordinates();
var coordinates, i, ii, segmentData;
for (i = 0, ii = points.length; i < ii; ++i) {
@@ -112115,8 +96440,7 @@ ol.interaction.Modify.prototype.writeMultiPointGeometry_ =
* @param {ol.geom.LineString} geometry Geometry.
* @private
*/
-ol.interaction.Modify.prototype.writeLineStringGeometry_ =
- function(feature, geometry) {
+ol.interaction.Modify.prototype.writeLineStringGeometry_ = function(feature, geometry) {
var coordinates = geometry.getCoordinates();
var i, ii, segment, segmentData;
for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
@@ -112137,8 +96461,7 @@ ol.interaction.Modify.prototype.writeLineStringGeometry_ =
* @param {ol.geom.MultiLineString} geometry Geometry.
* @private
*/
-ol.interaction.Modify.prototype.writeMultiLineStringGeometry_ =
- function(feature, geometry) {
+ol.interaction.Modify.prototype.writeMultiLineStringGeometry_ = function(feature, geometry) {
var lines = geometry.getCoordinates();
var coordinates, i, ii, j, jj, segment, segmentData;
for (j = 0, jj = lines.length; j < jj; ++j) {
@@ -112163,8 +96486,7 @@ ol.interaction.Modify.prototype.writeMultiLineStringGeometry_ =
* @param {ol.geom.Polygon} geometry Geometry.
* @private
*/
-ol.interaction.Modify.prototype.writePolygonGeometry_ =
- function(feature, geometry) {
+ol.interaction.Modify.prototype.writePolygonGeometry_ = function(feature, geometry) {
var rings = geometry.getCoordinates();
var coordinates, i, ii, j, jj, segment, segmentData;
for (j = 0, jj = rings.length; j < jj; ++j) {
@@ -112189,8 +96511,7 @@ ol.interaction.Modify.prototype.writePolygonGeometry_ =
* @param {ol.geom.MultiPolygon} geometry Geometry.
* @private
*/
-ol.interaction.Modify.prototype.writeMultiPolygonGeometry_ =
- function(feature, geometry) {
+ol.interaction.Modify.prototype.writeMultiPolygonGeometry_ = function(feature, geometry) {
var polygons = geometry.getCoordinates();
var coordinates, i, ii, j, jj, k, kk, rings, segment, segmentData;
for (k = 0, kk = polygons.length; k < kk; ++k) {
@@ -112218,8 +96539,7 @@ ol.interaction.Modify.prototype.writeMultiPolygonGeometry_ =
* @param {ol.geom.GeometryCollection} geometry Geometry.
* @private
*/
-ol.interaction.Modify.prototype.writeGeometryCollectionGeometry_ =
- function(feature, geometry) {
+ol.interaction.Modify.prototype.writeGeometryCollectionGeometry_ = function(feature, geometry) {
var i, geometries = geometry.getGeometriesArray();
for (i = 0; i < geometries.length; ++i) {
this.SEGMENT_WRITERS_[geometries[i].getType()].call(
@@ -112233,8 +96553,7 @@ ol.interaction.Modify.prototype.writeGeometryCollectionGeometry_ =
* @return {ol.Feature} Vertex feature.
* @private
*/
-ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ =
- function(coordinates) {
+ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ = function(coordinates) {
var vertexFeature = this.vertexFeature_;
if (!vertexFeature) {
vertexFeature = new ol.Feature(new ol.geom.Point(coordinates));
@@ -112249,9 +96568,9 @@ ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ =
/**
- * @param {ol.interaction.SegmentDataType} a
- * @param {ol.interaction.SegmentDataType} b
- * @return {number}
+ * @param {ol.interaction.SegmentDataType} a The first segment data.
+ * @param {ol.interaction.SegmentDataType} b The second segment data.
+ * @return {number} The difference in indexes.
* @private
*/
ol.interaction.Modify.compareIndexes_ = function(a, b) {
@@ -112266,8 +96585,11 @@ ol.interaction.Modify.compareIndexes_ = function(a, b) {
* @private
*/
ol.interaction.Modify.handleDownEvent_ = function(evt) {
+ if (!this.condition_(evt)) {
+ return false;
+ }
this.handlePointerAtPixel_(evt.pixel, evt.map);
- this.dragSegments_ = [];
+ this.dragSegments_.length = 0;
this.modified_ = false;
var vertexFeature = this.vertexFeature_;
if (vertexFeature) {
@@ -112316,8 +96638,8 @@ ol.interaction.Modify.handleDownEvent_ = function(evt) {
if (insertVertices.length) {
this.willModifyFeatures_(evt);
}
- for (i = insertVertices.length - 1; i >= 0; --i) {
- this.insertVertex_.apply(this, insertVertices[i]);
+ for (var j = insertVertices.length - 1; j >= 0; --j) {
+ this.insertVertex_.apply(this, insertVertices[j]);
}
}
return !!this.vertexFeature_;
@@ -112372,6 +96694,8 @@ ol.interaction.Modify.handleDragEvent_ = function(evt) {
coordinates[depth[1]][depth[0]][segmentData.index + index] = vertex;
segment[index] = vertex;
break;
+ default:
+ // pass
}
this.setGeometryCoordinates_(geometry, coordinates);
@@ -112414,6 +96738,7 @@ ol.interaction.Modify.handleEvent = function(mapBrowserEvent) {
if (!(mapBrowserEvent instanceof ol.MapBrowserPointerEvent)) {
return true;
}
+ this.lastPointerEvent_ = mapBrowserEvent;
var handled;
if (!mapBrowserEvent.map.getView().getHints()[ol.ViewHint.INTERACTING] &&
@@ -112427,11 +96752,7 @@ ol.interaction.Modify.handleEvent = function(mapBrowserEvent) {
var geometry = this.vertexFeature_.getGeometry();
goog.asserts.assertInstanceof(geometry, ol.geom.Point,
'geometry should be an ol.geom.Point');
- this.willModifyFeatures_(mapBrowserEvent);
- handled = this.removeVertex_();
- this.dispatchEvent(new ol.interaction.ModifyEvent(
- ol.ModifyEventType.MODIFYEND, this.features_, mapBrowserEvent));
- this.modified_ = false;
+ handled = this.removePoint();
} else {
handled = true;
}
@@ -112597,6 +96918,23 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) {
this.ignoreNextSingleClick_ = true;
};
+/**
+ * Removes the vertex currently being pointed.
+ * @return {boolean} True when a vertex was removed.
+ * @api
+ */
+ol.interaction.Modify.prototype.removePoint = function() {
+ var handled = false;
+ if (this.lastPointerEvent_ && this.lastPointerEvent_.type != ol.MapBrowserEvent.EventType.POINTERDRAG) {
+ var evt = this.lastPointerEvent_;
+ this.willModifyFeatures_(evt);
+ handled = this.removeVertex_();
+ this.dispatchEvent(new ol.interaction.ModifyEvent(
+ ol.ModifyEventType.MODIFYEND, this.features_, evt));
+ this.modified_ = false;
+ }
+ return handled;
+};
/**
* Removes a vertex from all matching features.
@@ -112607,91 +96945,111 @@ ol.interaction.Modify.prototype.removeVertex_ = function() {
var dragSegments = this.dragSegments_;
var segmentsByFeature = {};
var component, coordinates, dragSegment, geometry, i, index, left;
- var newIndex, newSegment, right, segmentData, uid, deleted;
+ var newIndex, right, segmentData, uid, deleted;
for (i = dragSegments.length - 1; i >= 0; --i) {
dragSegment = dragSegments[i];
segmentData = dragSegment[0];
- geometry = segmentData.geometry;
- coordinates = geometry.getCoordinates();
uid = goog.getUid(segmentData.feature);
if (segmentData.depth) {
// separate feature components
uid += '-' + segmentData.depth.join('-');
}
- left = right = index = undefined;
+ if (!(uid in segmentsByFeature)) {
+ segmentsByFeature[uid] = {};
+ }
if (dragSegment[1] === 0) {
- right = segmentData;
- index = segmentData.index;
+ segmentsByFeature[uid].right = segmentData;
+ segmentsByFeature[uid].index = segmentData.index;
} else if (dragSegment[1] == 1) {
- left = segmentData;
- index = segmentData.index + 1;
- }
- if (!(uid in segmentsByFeature)) {
- segmentsByFeature[uid] = [left, right, index];
+ segmentsByFeature[uid].left = segmentData;
+ segmentsByFeature[uid].index = segmentData.index + 1;
}
- newSegment = segmentsByFeature[uid];
+
+ }
+ for (uid in segmentsByFeature) {
+ right = segmentsByFeature[uid].right;
+ left = segmentsByFeature[uid].left;
+ index = segmentsByFeature[uid].index;
+ newIndex = index - 1;
if (left !== undefined) {
- newSegment[0] = left;
+ segmentData = left;
+ } else {
+ segmentData = right;
}
- if (right !== undefined) {
- newSegment[1] = right;
+ if (newIndex < 0) {
+ newIndex = 0;
}
- if (newSegment[0] !== undefined && newSegment[1] !== undefined) {
- component = coordinates;
- deleted = false;
- newIndex = index - 1;
- switch (geometry.getType()) {
- case ol.geom.GeometryType.MULTI_LINE_STRING:
+ geometry = segmentData.geometry;
+ coordinates = geometry.getCoordinates();
+ component = coordinates;
+ deleted = false;
+ switch (geometry.getType()) {
+ case ol.geom.GeometryType.MULTI_LINE_STRING:
+ if (coordinates[segmentData.depth[0]].length > 2) {
coordinates[segmentData.depth[0]].splice(index, 1);
deleted = true;
- break;
- case ol.geom.GeometryType.LINE_STRING:
+ }
+ break;
+ case ol.geom.GeometryType.LINE_STRING:
+ if (coordinates.length > 2) {
coordinates.splice(index, 1);
deleted = true;
- break;
- case ol.geom.GeometryType.MULTI_POLYGON:
- component = component[segmentData.depth[1]];
- /* falls through */
- case ol.geom.GeometryType.POLYGON:
- component = component[segmentData.depth[0]];
- if (component.length > 4) {
- if (index == component.length - 1) {
- index = 0;
- }
- component.splice(index, 1);
- deleted = true;
- if (index === 0) {
- // close the ring again
- component.pop();
- component.push(component[0]);
- newIndex = component.length - 1;
- }
+ }
+ break;
+ case ol.geom.GeometryType.MULTI_POLYGON:
+ component = component[segmentData.depth[1]];
+ /* falls through */
+ case ol.geom.GeometryType.POLYGON:
+ component = component[segmentData.depth[0]];
+ if (component.length > 4) {
+ if (index == component.length - 1) {
+ index = 0;
}
- break;
- }
+ component.splice(index, 1);
+ deleted = true;
+ if (index === 0) {
+ // close the ring again
+ component.pop();
+ component.push(component[0]);
+ newIndex = component.length - 1;
+ }
+ }
+ break;
+ default:
+ // pass
+ }
- if (deleted) {
- this.rBush_.remove(newSegment[0]);
- this.rBush_.remove(newSegment[1]);
- this.setGeometryCoordinates_(geometry, coordinates);
+ if (deleted) {
+ this.setGeometryCoordinates_(geometry, coordinates);
+ var segments = [];
+ if (left !== undefined) {
+ this.rBush_.remove(left);
+ segments.push(left.segment[0]);
+ }
+ if (right !== undefined) {
+ this.rBush_.remove(right);
+ segments.push(right.segment[1]);
+ }
+ if (left !== undefined && right !== undefined) {
goog.asserts.assert(newIndex >= 0, 'newIndex should be larger than 0');
+
var newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({
depth: segmentData.depth,
feature: segmentData.feature,
geometry: segmentData.geometry,
index: newIndex,
- segment: [newSegment[0].segment[0], newSegment[1].segment[1]]
+ segment: segments
});
this.rBush_.insert(ol.extent.boundingExtent(newSegmentData.segment),
newSegmentData);
- this.updateSegmentIndices_(geometry, index, segmentData.depth, -1);
-
- if (this.vertexFeature_) {
- this.overlay_.getSource().removeFeature(this.vertexFeature_);
- this.vertexFeature_ = null;
- }
+ }
+ this.updateSegmentIndices_(geometry, index, segmentData.depth, -1);
+ if (this.vertexFeature_) {
+ this.overlay_.getSource().removeFeature(this.vertexFeature_);
+ this.vertexFeature_ = null;
}
}
+
}
return true;
};
@@ -112702,8 +97060,7 @@ ol.interaction.Modify.prototype.removeVertex_ = function() {
* @param {Array} coordinates Coordinates.
* @private
*/
-ol.interaction.Modify.prototype.setGeometryCoordinates_ =
- function(geometry, coordinates) {
+ol.interaction.Modify.prototype.setGeometryCoordinates_ = function(geometry, coordinates) {
this.changingFeature_ = true;
geometry.setCoordinates(coordinates);
this.changingFeature_ = false;
@@ -112722,9 +97079,7 @@ ol.interaction.Modify.prototype.updateSegmentIndices_ = function(
this.rBush_.forEachInExtent(geometry.getExtent(), function(segmentDataMatch) {
if (segmentDataMatch.geometry === geometry &&
(depth === undefined || segmentDataMatch.depth === undefined ||
- goog.array.equals(
- /** @type {null|{length: number}} */ (segmentDataMatch.depth),
- depth)) &&
+ ol.array.equals(segmentDataMatch.depth, depth)) &&
segmentDataMatch.index > index) {
segmentDataMatch.index += delta;
}
@@ -112745,21 +97100,19 @@ ol.interaction.Modify.getDefaultStyleFunction = function() {
goog.provide('ol.interaction.Select');
goog.provide('ol.interaction.SelectEvent');
goog.provide('ol.interaction.SelectEventType');
-goog.provide('ol.interaction.SelectFilterFunction');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.functions');
-goog.require('goog.object');
+goog.require('ol.functions');
goog.require('ol.CollectionEventType');
goog.require('ol.Feature');
goog.require('ol.array');
+goog.require('ol.events');
+goog.require('ol.events.Event');
goog.require('ol.events.condition');
goog.require('ol.geom.GeometryType');
goog.require('ol.interaction.Interaction');
goog.require('ol.layer.Vector');
+goog.require('ol.object');
goog.require('ol.source.Vector');
@@ -112777,18 +97130,6 @@ ol.interaction.SelectEventType = {
/**
- * A function that takes an {@link ol.Feature} or {@link ol.render.Feature} and
- * an {@link ol.layer.Layer} and returns `true` if the feature may be selected
- * or `false` otherwise.
- * @typedef {function((ol.Feature|ol.render.Feature), ol.layer.Layer):
- * boolean}
- * @api
- */
-ol.interaction.SelectFilterFunction;
-
-
-
-/**
* @classdesc
* Events emitted by {@link ol.interaction.Select} instances are instances of
* this type.
@@ -112799,11 +97140,10 @@ ol.interaction.SelectFilterFunction;
* @param {ol.MapBrowserEvent} mapBrowserEvent Associated
* {@link ol.MapBrowserEvent}.
* @implements {oli.SelectEvent}
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @constructor
*/
-ol.interaction.SelectEvent =
- function(type, selected, deselected, mapBrowserEvent) {
+ol.interaction.SelectEvent = function(type, selected, deselected, mapBrowserEvent) {
goog.base(this, type);
/**
@@ -112827,8 +97167,7 @@ ol.interaction.SelectEvent =
*/
this.mapBrowserEvent = mapBrowserEvent;
};
-goog.inherits(ol.interaction.SelectEvent, goog.events.Event);
-
+goog.inherits(ol.interaction.SelectEvent, ol.events.Event);
/**
@@ -112896,25 +97235,49 @@ ol.interaction.Select = function(opt_options) {
* @type {ol.interaction.SelectFilterFunction}
*/
this.filter_ = options.filter ? options.filter :
- goog.functions.TRUE;
+ ol.functions.TRUE;
+
+ var featureOverlay = new ol.layer.Vector({
+ source: new ol.source.Vector({
+ useSpatialIndex: false,
+ features: options.features,
+ wrapX: options.wrapX
+ }),
+ style: options.style ? options.style :
+ ol.interaction.Select.getDefaultStyleFunction(),
+ updateWhileAnimating: true,
+ updateWhileInteracting: true
+ });
+
+ /**
+ * @private
+ * @type {ol.layer.Vector}
+ */
+ this.featureOverlay_ = featureOverlay;
var layerFilter;
if (options.layers) {
if (goog.isFunction(options.layers)) {
- layerFilter = options.layers;
+ /**
+ * @param {ol.layer.Layer} layer Layer.
+ * @return {boolean} Include.
+ */
+ layerFilter = function(layer) {
+ goog.asserts.assertFunction(options.layers);
+ return options.layers(layer);
+ };
} else {
var layers = options.layers;
- layerFilter =
- /**
- * @param {ol.layer.Layer} layer Layer.
- * @return {boolean} Include.
- */
- function(layer) {
+ /**
+ * @param {ol.layer.Layer} layer Layer.
+ * @return {boolean} Include.
+ */
+ layerFilter = function(layer) {
return ol.array.includes(layers, layer);
};
}
} else {
- layerFilter = goog.functions.TRUE;
+ layerFilter = ol.functions.TRUE;
}
/**
@@ -112931,27 +97294,11 @@ ol.interaction.Select = function(opt_options) {
*/
this.featureLayerAssociation_ = {};
- /**
- * @private
- * @type {ol.layer.Vector}
- */
- this.featureOverlay_ = new ol.layer.Vector({
- source: new ol.source.Vector({
- useSpatialIndex: false,
- features: options.features,
- wrapX: options.wrapX
- }),
- style: options.style ? options.style :
- ol.interaction.Select.getDefaultStyleFunction(),
- updateWhileAnimating: true,
- updateWhileInteracting: true
- });
-
var features = this.featureOverlay_.getSource().getFeaturesCollection();
- goog.events.listen(features, ol.CollectionEventType.ADD,
- this.addFeature_, false, this);
- goog.events.listen(features, ol.CollectionEventType.REMOVE,
- this.removeFeature_, false, this);
+ ol.events.listen(features, ol.CollectionEventType.ADD,
+ this.addFeature_, this);
+ ol.events.listen(features, ol.CollectionEventType.REMOVE,
+ this.removeFeature_, this);
};
goog.inherits(ol.interaction.Select, ol.interaction.Interaction);
@@ -112962,8 +97309,7 @@ goog.inherits(ol.interaction.Select, ol.interaction.Interaction);
* @param {ol.layer.Layer} layer Layer.
* @private
*/
-ol.interaction.Select.prototype.addFeatureLayerAssociation_ =
- function(feature, layer) {
+ol.interaction.Select.prototype.addFeatureLayerAssociation_ = function(feature, layer) {
var key = goog.getUid(feature);
this.featureLayerAssociation_[key] = layer;
};
@@ -113014,17 +97360,19 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
var set = !add && !remove && !toggle;
var map = mapBrowserEvent.map;
var features = this.featureOverlay_.getSource().getFeaturesCollection();
- var /** @type {!Array.<ol.Feature>} */ deselected = [];
- var /** @type {!Array.<ol.Feature>} */ selected = [];
+ var deselected = [];
+ var selected = [];
var change = false;
if (set) {
// Replace the currently selected feature(s) with the feature(s) at the
// pixel, or clear the selected feature(s) if there is no feature at
// the pixel.
+ ol.object.clear(this.featureLayerAssociation_);
map.forEachFeatureAtPixel(mapBrowserEvent.pixel,
/**
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @param {ol.layer.Layer} layer Layer.
+ * @return {boolean|undefined} Continue to iterate over the features.
*/
function(feature, layer) {
if (this.filter_(feature, layer)) {
@@ -113043,16 +97391,6 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
features.clear();
}
features.extend(selected);
- // Modify object this.featureLayerAssociation_
- if (selected.length === 0) {
- goog.object.clear(this.featureLayerAssociation_);
- } else {
- if (deselected.length > 0) {
- deselected.forEach(function(feature) {
- this.removeFeatureLayerAssociation_(feature);
- }, this);
- }
- }
}
} else {
// Modify the currently selected feature(s).
@@ -113060,20 +97398,20 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
/**
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @param {ol.layer.Layer} layer Layer.
+ * @return {boolean|undefined} Continue to iterate over the features.
*/
function(feature, layer) {
- if (!ol.array.includes(features.getArray(), feature)) {
- if (add || toggle) {
- if (this.filter_(feature, layer)) {
- selected.push(feature);
- this.addFeatureLayerAssociation_(feature, layer);
- }
- }
- } else {
- if (remove || toggle) {
+ if (this.filter_(feature, layer)) {
+ if ((add || toggle) &&
+ !ol.array.includes(features.getArray(), feature)) {
+ selected.push(feature);
+ this.addFeatureLayerAssociation_(feature, layer);
+ } else if ((remove || toggle) &&
+ ol.array.includes(features.getArray(), feature)) {
deselected.push(feature);
this.removeFeatureLayerAssociation_(feature);
}
+ return !this.multi_;
}
}, this, this.layerFilter_);
var i;
@@ -113120,9 +97458,9 @@ ol.interaction.Select.prototype.setMap = function(map) {
*/
ol.interaction.Select.getDefaultStyleFunction = function() {
var styles = ol.style.createDefaultEditingStyles();
- goog.array.extend(styles[ol.geom.GeometryType.POLYGON],
+ ol.array.extend(styles[ol.geom.GeometryType.POLYGON],
styles[ol.geom.GeometryType.LINE_STRING]);
- goog.array.extend(styles[ol.geom.GeometryType.GEOMETRY_COLLECTION],
+ ol.array.extend(styles[ol.geom.GeometryType.GEOMETRY_COLLECTION],
styles[ol.geom.GeometryType.LINE_STRING]);
return function(feature, resolution) {
@@ -113165,8 +97503,7 @@ ol.interaction.Select.prototype.removeFeature_ = function(evt) {
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @private
*/
-ol.interaction.Select.prototype.removeFeatureLayerAssociation_ =
- function(feature) {
+ol.interaction.Select.prototype.removeFeatureLayerAssociation_ = function(feature) {
var key = goog.getUid(feature);
delete this.featureLayerAssociation_[key];
};
@@ -113175,28 +97512,27 @@ goog.provide('ol.interaction.Snap');
goog.provide('ol.interaction.SnapProperty');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('ol');
goog.require('ol.Collection');
goog.require('ol.CollectionEvent');
goog.require('ol.CollectionEventType');
-goog.require('ol.Extent');
goog.require('ol.Feature');
goog.require('ol.Object');
goog.require('ol.Observable');
goog.require('ol.coordinate');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
goog.require('ol.geom.Geometry');
goog.require('ol.interaction.Pointer');
+goog.require('ol.functions');
+goog.require('ol.object');
goog.require('ol.source.Vector');
goog.require('ol.source.VectorEvent');
goog.require('ol.source.VectorEventType');
goog.require('ol.structs.RBush');
-
/**
* @classdesc
* Handles snapping of vector features while modifying or drawing them. The
@@ -113223,7 +97559,7 @@ ol.interaction.Snap = function(opt_options) {
goog.base(this, {
handleEvent: ol.interaction.Snap.handleEvent_,
- handleDownEvent: goog.functions.TRUE,
+ handleDownEvent: ol.functions.TRUE,
handleUpEvent: ol.interaction.Snap.handleUpEvent_
});
@@ -113236,25 +97572,37 @@ ol.interaction.Snap = function(opt_options) {
this.source_ = options.source ? options.source : null;
/**
+ * @private
+ * @type {boolean}
+ */
+ this.vertex_ = options.vertex !== undefined ? options.vertex : true;
+
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.edge_ = options.edge !== undefined ? options.edge : true;
+
+ /**
* @type {ol.Collection.<ol.Feature>}
* @private
*/
this.features_ = options.features ? options.features : null;
/**
- * @type {Array.<goog.events.Key>}
+ * @type {Array.<ol.events.Key>}
* @private
*/
this.featuresListenerKeys_ = [];
/**
- * @type {Object.<number, goog.events.Key>}
+ * @type {Object.<number, ol.events.Key>}
* @private
*/
this.geometryChangeListenerKeys_ = {};
/**
- * @type {Object.<number, goog.events.Key>}
+ * @type {Object.<number, ol.events.Key>}
* @private
*/
this.geometryModifyListenerKeys_ = {};
@@ -113291,15 +97639,15 @@ ol.interaction.Snap = function(opt_options) {
options.pixelTolerance : 10;
/**
- * @type {function(ol.interaction.Snap.SegmentDataType, ol.interaction.Snap.SegmentDataType): number}
+ * @type {function(ol.interaction.SnapSegmentDataType, ol.interaction.SnapSegmentDataType): number}
* @private
*/
- this.sortByDistance_ = goog.bind(ol.interaction.Snap.sortByDistance, this);
+ this.sortByDistance_ = ol.interaction.Snap.sortByDistance.bind(this);
/**
* Segment RTree for each layer
- * @type {ol.structs.RBush.<ol.interaction.Snap.SegmentDataType>}
+ * @type {ol.structs.RBush.<ol.interaction.SnapSegmentDataType>}
* @private
*/
this.rBush_ = new ol.structs.RBush();
@@ -113333,24 +97681,31 @@ goog.inherits(ol.interaction.Snap, ol.interaction.Pointer);
*/
ol.interaction.Snap.prototype.addFeature = function(feature, opt_listen) {
var listen = opt_listen !== undefined ? opt_listen : true;
+ var feature_uid = goog.getUid(feature);
var geometry = feature.getGeometry();
- var segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()];
- if (segmentWriter) {
- var feature_uid = goog.getUid(feature);
- this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent(
- ol.extent.createEmpty());
- segmentWriter.call(this, feature, geometry);
-
- if (listen) {
- this.geometryModifyListenerKeys_[feature_uid] = geometry.on(
- goog.events.EventType.CHANGE,
- goog.bind(this.handleGeometryModify_, this, feature),
- this);
- this.geometryChangeListenerKeys_[feature_uid] = feature.on(
- ol.Object.getChangeEventType(feature.getGeometryName()),
- this.handleGeometryChange_, this);
+ if (geometry) {
+ var segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()];
+ if (segmentWriter) {
+ this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent(
+ ol.extent.createEmpty());
+ segmentWriter.call(this, feature, geometry);
+
+ if (listen) {
+ this.geometryModifyListenerKeys_[feature_uid] = ol.events.listen(
+ geometry,
+ ol.events.EventType.CHANGE,
+ this.handleGeometryModify_.bind(this, feature),
+ this);
+ }
}
}
+
+ if (listen) {
+ this.geometryChangeListenerKeys_[feature_uid] = ol.events.listen(
+ feature,
+ ol.Object.getChangeEventType(feature.getGeometryName()),
+ this.handleGeometryChange_, this);
+ }
};
@@ -113373,7 +97728,7 @@ ol.interaction.Snap.prototype.forEachFeatureRemove_ = function(feature) {
/**
- * @return {ol.Collection.<ol.Feature>|Array.<ol.Feature>}
+ * @return {ol.Collection.<ol.Feature>|Array.<ol.Feature>} Features.
* @private
*/
ol.interaction.Snap.prototype.getFeatures_ = function() {
@@ -113423,11 +97778,11 @@ ol.interaction.Snap.prototype.handleFeatureRemove_ = function(evt) {
/**
- * @param {goog.events.Event} evt Event.
+ * @param {ol.events.Event} evt Event.
* @private
*/
ol.interaction.Snap.prototype.handleGeometryChange_ = function(evt) {
- var feature = evt.currentTarget;
+ var feature = evt.target;
goog.asserts.assertInstanceof(feature, ol.Feature);
this.removeFeature(feature, true);
this.addFeature(feature, true);
@@ -113436,7 +97791,7 @@ ol.interaction.Snap.prototype.handleGeometryChange_ = function(evt) {
/**
* @param {ol.Feature} feature Feature which geometry was modified.
- * @param {goog.events.Event} evt Event.
+ * @param {ol.events.Event} evt Event.
* @private
*/
ol.interaction.Snap.prototype.handleGeometryModify_ = function(feature, evt) {
@@ -113476,11 +97831,13 @@ ol.interaction.Snap.prototype.removeFeature = function(feature, opt_unlisten) {
if (unlisten) {
ol.Observable.unByKey(this.geometryModifyListenerKeys_[feature_uid]);
delete this.geometryModifyListenerKeys_[feature_uid];
-
- ol.Observable.unByKey(this.geometryChangeListenerKeys_[feature_uid]);
- delete this.geometryChangeListenerKeys_[feature_uid];
}
}
+
+ if (unlisten) {
+ ol.Observable.unByKey(this.geometryChangeListenerKeys_[feature_uid]);
+ delete this.geometryChangeListenerKeys_[feature_uid];
+ }
};
@@ -113502,15 +97859,19 @@ ol.interaction.Snap.prototype.setMap = function(map) {
if (map) {
if (this.features_) {
- keys.push(this.features_.on(ol.CollectionEventType.ADD,
- this.handleFeatureAdd_, this));
- keys.push(this.features_.on(ol.CollectionEventType.REMOVE,
- this.handleFeatureRemove_, this));
+ keys.push(
+ ol.events.listen(this.features_, ol.CollectionEventType.ADD,
+ this.handleFeatureAdd_, this),
+ ol.events.listen(this.features_, ol.CollectionEventType.REMOVE,
+ this.handleFeatureRemove_, this)
+ );
} else if (this.source_) {
- keys.push(this.source_.on(ol.source.VectorEventType.ADDFEATURE,
- this.handleFeatureAdd_, this));
- keys.push(this.source_.on(ol.source.VectorEventType.REMOVEFEATURE,
- this.handleFeatureRemove_, this));
+ keys.push(
+ ol.events.listen(this.source_, ol.source.VectorEventType.ADDFEATURE,
+ this.handleFeatureAdd_, this),
+ ol.events.listen(this.source_, ol.source.VectorEventType.REMOVEFEATURE,
+ this.handleFeatureRemove_, this)
+ );
}
features.forEach(this.forEachFeatureAdd_, this);
}
@@ -113520,14 +97881,14 @@ ol.interaction.Snap.prototype.setMap = function(map) {
/**
* @inheritDoc
*/
-ol.interaction.Snap.prototype.shouldStopEvent = goog.functions.FALSE;
+ol.interaction.Snap.prototype.shouldStopEvent = ol.functions.FALSE;
/**
* @param {ol.Pixel} pixel Pixel
* @param {ol.Coordinate} pixelCoordinate Coordinate
* @param {ol.Map} map Map.
- * @return {ol.interaction.Snap.ResultType} Snap result
+ * @return {ol.interaction.SnapResultType} Snap result
*/
ol.interaction.Snap.prototype.snapTo = function(pixel, pixelCoordinate, map) {
@@ -113542,31 +97903,51 @@ ol.interaction.Snap.prototype.snapTo = function(pixel, pixelCoordinate, map) {
var snapped = false;
var vertex = null;
var vertexPixel = null;
+ var dist, pixel1, pixel2, squaredDist1, squaredDist2;
if (segments.length > 0) {
this.pixelCoordinate_ = pixelCoordinate;
segments.sort(this.sortByDistance_);
var closestSegment = segments[0].segment;
- vertex = (ol.coordinate.closestOnSegment(pixelCoordinate,
- closestSegment));
- vertexPixel = map.getPixelFromCoordinate(vertex);
- if (Math.sqrt(ol.coordinate.squaredDistance(pixel, vertexPixel)) <=
- this.pixelTolerance_) {
- snapped = true;
- var pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
- var pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
- var squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
- var squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
- var dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
+ if (this.vertex_ && !this.edge_) {
+ pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
+ pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
+ squaredDist1 = ol.coordinate.squaredDistance(pixel, pixel1);
+ squaredDist2 = ol.coordinate.squaredDistance(pixel, pixel2);
+ dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
snappedToVertex = dist <= this.pixelTolerance_;
if (snappedToVertex) {
+ snapped = true;
vertex = squaredDist1 > squaredDist2 ?
closestSegment[1] : closestSegment[0];
vertexPixel = map.getPixelFromCoordinate(vertex);
- vertexPixel = [Math.round(vertexPixel[0]), Math.round(vertexPixel[1])];
}
+ } else if (this.edge_) {
+ vertex = (ol.coordinate.closestOnSegment(pixelCoordinate,
+ closestSegment));
+ vertexPixel = map.getPixelFromCoordinate(vertex);
+ if (Math.sqrt(ol.coordinate.squaredDistance(pixel, vertexPixel)) <=
+ this.pixelTolerance_) {
+ snapped = true;
+ if (this.vertex_) {
+ pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
+ pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
+ squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
+ squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
+ dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
+ snappedToVertex = dist <= this.pixelTolerance_;
+ if (snappedToVertex) {
+ vertex = squaredDist1 > squaredDist2 ?
+ closestSegment[1] : closestSegment[0];
+ vertexPixel = map.getPixelFromCoordinate(vertex);
+ }
+ }
+ }
+ }
+ if (snapped) {
+ vertexPixel = [Math.round(vertexPixel[0]), Math.round(vertexPixel[1])];
}
}
- return /** @type {ol.interaction.Snap.ResultType} */ ({
+ return /** @type {ol.interaction.SnapResultType} */ ({
snapped: snapped,
vertex: vertex,
vertexPixel: vertexPixel
@@ -113589,8 +97970,7 @@ ol.interaction.Snap.prototype.updateFeature_ = function(feature) {
* @param {ol.geom.GeometryCollection} geometry Geometry.
* @private
*/
-ol.interaction.Snap.prototype.writeGeometryCollectionGeometry_ =
- function(feature, geometry) {
+ol.interaction.Snap.prototype.writeGeometryCollectionGeometry_ = function(feature, geometry) {
var i, geometries = geometry.getGeometriesArray();
for (i = 0; i < geometries.length; ++i) {
this.SEGMENT_WRITERS_[geometries[i].getType()].call(
@@ -113604,13 +97984,12 @@ ol.interaction.Snap.prototype.writeGeometryCollectionGeometry_ =
* @param {ol.geom.LineString} geometry Geometry.
* @private
*/
-ol.interaction.Snap.prototype.writeLineStringGeometry_ =
- function(feature, geometry) {
+ol.interaction.Snap.prototype.writeLineStringGeometry_ = function(feature, geometry) {
var coordinates = geometry.getCoordinates();
var i, ii, segment, segmentData;
for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
segment = coordinates.slice(i, i + 2);
- segmentData = /** @type {ol.interaction.Snap.SegmentDataType} */ ({
+ segmentData = /** @type {ol.interaction.SnapSegmentDataType} */ ({
feature: feature,
segment: segment
});
@@ -113624,15 +98003,14 @@ ol.interaction.Snap.prototype.writeLineStringGeometry_ =
* @param {ol.geom.MultiLineString} geometry Geometry.
* @private
*/
-ol.interaction.Snap.prototype.writeMultiLineStringGeometry_ =
- function(feature, geometry) {
+ol.interaction.Snap.prototype.writeMultiLineStringGeometry_ = function(feature, geometry) {
var lines = geometry.getCoordinates();
var coordinates, i, ii, j, jj, segment, segmentData;
for (j = 0, jj = lines.length; j < jj; ++j) {
coordinates = lines[j];
for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
segment = coordinates.slice(i, i + 2);
- segmentData = /** @type {ol.interaction.Snap.SegmentDataType} */ ({
+ segmentData = /** @type {ol.interaction.SnapSegmentDataType} */ ({
feature: feature,
segment: segment
});
@@ -113647,13 +98025,12 @@ ol.interaction.Snap.prototype.writeMultiLineStringGeometry_ =
* @param {ol.geom.MultiPoint} geometry Geometry.
* @private
*/
-ol.interaction.Snap.prototype.writeMultiPointGeometry_ =
- function(feature, geometry) {
+ol.interaction.Snap.prototype.writeMultiPointGeometry_ = function(feature, geometry) {
var points = geometry.getCoordinates();
var coordinates, i, ii, segmentData;
for (i = 0, ii = points.length; i < ii; ++i) {
coordinates = points[i];
- segmentData = /** @type {ol.interaction.Snap.SegmentDataType} */ ({
+ segmentData = /** @type {ol.interaction.SnapSegmentDataType} */ ({
feature: feature,
segment: [coordinates, coordinates]
});
@@ -113667,8 +98044,7 @@ ol.interaction.Snap.prototype.writeMultiPointGeometry_ =
* @param {ol.geom.MultiPolygon} geometry Geometry.
* @private
*/
-ol.interaction.Snap.prototype.writeMultiPolygonGeometry_ =
- function(feature, geometry) {
+ol.interaction.Snap.prototype.writeMultiPolygonGeometry_ = function(feature, geometry) {
var polygons = geometry.getCoordinates();
var coordinates, i, ii, j, jj, k, kk, rings, segment, segmentData;
for (k = 0, kk = polygons.length; k < kk; ++k) {
@@ -113677,7 +98053,7 @@ ol.interaction.Snap.prototype.writeMultiPolygonGeometry_ =
coordinates = rings[j];
for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
segment = coordinates.slice(i, i + 2);
- segmentData = /** @type {ol.interaction.Snap.SegmentDataType} */ ({
+ segmentData = /** @type {ol.interaction.SnapSegmentDataType} */ ({
feature: feature,
segment: segment
});
@@ -113693,10 +98069,9 @@ ol.interaction.Snap.prototype.writeMultiPolygonGeometry_ =
* @param {ol.geom.Point} geometry Geometry.
* @private
*/
-ol.interaction.Snap.prototype.writePointGeometry_ =
- function(feature, geometry) {
+ol.interaction.Snap.prototype.writePointGeometry_ = function(feature, geometry) {
var coordinates = geometry.getCoordinates();
- var segmentData = /** @type {ol.interaction.Snap.SegmentDataType} */ ({
+ var segmentData = /** @type {ol.interaction.SnapSegmentDataType} */ ({
feature: feature,
segment: [coordinates, coordinates]
});
@@ -113709,15 +98084,14 @@ ol.interaction.Snap.prototype.writePointGeometry_ =
* @param {ol.geom.Polygon} geometry Geometry.
* @private
*/
-ol.interaction.Snap.prototype.writePolygonGeometry_ =
- function(feature, geometry) {
+ol.interaction.Snap.prototype.writePolygonGeometry_ = function(feature, geometry) {
var rings = geometry.getCoordinates();
var coordinates, i, ii, j, jj, segment, segmentData;
for (j = 0, jj = rings.length; j < jj; ++j) {
coordinates = rings[j];
for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
segment = coordinates.slice(i, i + 2);
- segmentData = /** @type {ol.interaction.Snap.SegmentDataType} */ ({
+ segmentData = /** @type {ol.interaction.SnapSegmentDataType} */ ({
feature: feature,
segment: segment
});
@@ -113728,25 +98102,6 @@ ol.interaction.Snap.prototype.writePolygonGeometry_ =
/**
- * @typedef {{
- * snapped: {boolean},
- * vertex: (ol.Coordinate|null),
- * vertexPixel: (ol.Pixel|null)
- * }}
- */
-ol.interaction.Snap.ResultType;
-
-
-/**
- * @typedef {{
- * feature: ol.Feature,
- * segment: Array.<ol.Coordinate>
- * }}
- */
-ol.interaction.Snap.SegmentDataType;
-
-
-/**
* Handle all pointer events events.
* @param {ol.MapBrowserEvent} evt A move event.
* @return {boolean} Pass the event to other interactions.
@@ -113770,7 +98125,7 @@ ol.interaction.Snap.handleEvent_ = function(evt) {
* @private
*/
ol.interaction.Snap.handleUpEvent_ = function(evt) {
- var featuresToUpdate = goog.object.getValues(this.pendingFeatures_);
+ var featuresToUpdate = ol.object.getValues(this.pendingFeatures_);
if (featuresToUpdate.length) {
featuresToUpdate.forEach(this.updateFeature_, this);
this.pendingFeatures_ = {};
@@ -113781,9 +98136,9 @@ ol.interaction.Snap.handleUpEvent_ = function(evt) {
/**
* Sort segments by distance, helper function
- * @param {ol.interaction.Snap.SegmentDataType} a
- * @param {ol.interaction.Snap.SegmentDataType} b
- * @return {number}
+ * @param {ol.interaction.SnapSegmentDataType} a The first segment data.
+ * @param {ol.interaction.SnapSegmentDataType} b The second segment data.
+ * @return {number} The difference in distance.
* @this {ol.interaction.Snap}
*/
ol.interaction.Snap.sortByDistance = function(a, b) {
@@ -113796,8 +98151,9 @@ ol.interaction.Snap.sortByDistance = function(a, b) {
goog.provide('ol.interaction.Translate');
goog.provide('ol.interaction.TranslateEvent');
-goog.require('goog.events');
-goog.require('goog.events.Event');
+goog.require('goog.asserts');
+goog.require('ol.events');
+goog.require('ol.events.Event');
goog.require('ol.array');
goog.require('ol.interaction.Pointer');
@@ -113827,14 +98183,13 @@ ol.interaction.TranslateEventType = {
};
-
/**
* @classdesc
* Events emitted by {@link ol.interaction.Translate} instances are instances of
* this type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.interaction.TranslateEvent}
* @param {ol.interaction.TranslateEventType} type Type.
* @param {ol.Collection.<ol.Feature>} features The features translated.
@@ -113859,8 +98214,7 @@ ol.interaction.TranslateEvent = function(type, features, coordinate) {
*/
this.coordinate = coordinate;
};
-goog.inherits(ol.interaction.TranslateEvent, goog.events.Event);
-
+goog.inherits(ol.interaction.TranslateEvent, ol.events.Event);
/**
@@ -113903,6 +98257,37 @@ ol.interaction.Translate = function(options) {
*/
this.features_ = options.features !== undefined ? options.features : null;
+ var layerFilter;
+ if (options.layers) {
+ if (goog.isFunction(options.layers)) {
+ /**
+ * @param {ol.layer.Layer} layer Layer.
+ * @return {boolean} Include.
+ */
+ layerFilter = function(layer) {
+ goog.asserts.assertFunction(options.layers);
+ return options.layers(layer);
+ };
+ } else {
+ var layers = options.layers;
+ /**
+ * @param {ol.layer.Layer} layer Layer.
+ * @return {boolean} Include.
+ */
+ layerFilter = function(layer) {
+ return ol.array.includes(layers, layer);
+ };
+ }
+ } else {
+ layerFilter = ol.functions.TRUE;
+ }
+
+ /**
+ * @private
+ * @type {function(ol.layer.Layer): boolean}
+ */
+ this.layerFilter_ = layerFilter;
+
/**
* @type {ol.Feature}
* @private
@@ -113990,8 +98375,7 @@ ol.interaction.Translate.handleDragEvent_ = function(event) {
* @this {ol.interaction.Translate}
* @private
*/
-ol.interaction.Translate.handleMoveEvent_ = function(event)
- {
+ol.interaction.Translate.handleMoveEvent_ = function(event) {
var elem = event.map.getTargetElement();
var intersectingFeature = event.map.forEachFeatureAtPixel(event.pixel,
function(feature) {
@@ -114040,7 +98424,7 @@ ol.interaction.Translate.prototype.featuresAtPixel_ = function(pixel, map) {
var intersectingFeature = map.forEachFeatureAtPixel(pixel,
function(feature) {
return feature;
- });
+ }, this, this.layerFilter_);
if (this.features_ &&
ol.array.includes(this.features_.getArray(), intersectingFeature)) {
@@ -114053,13 +98437,13 @@ ol.interaction.Translate.prototype.featuresAtPixel_ = function(pixel, map) {
goog.provide('ol.layer.Heatmap');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.object');
+goog.require('ol.events');
goog.require('ol');
goog.require('ol.Object');
goog.require('ol.dom');
goog.require('ol.layer.Vector');
goog.require('ol.math');
+goog.require('ol.object');
goog.require('ol.render.EventType');
goog.require('ol.style.Icon');
goog.require('ol.style.Style');
@@ -114075,7 +98459,6 @@ ol.layer.HeatmapLayerProperty = {
};
-
/**
* @classdesc
* Layer for rendering vector data as a heatmap.
@@ -114092,7 +98475,7 @@ ol.layer.HeatmapLayerProperty = {
ol.layer.Heatmap = function(opt_options) {
var options = opt_options ? opt_options : {};
- var baseOptions = goog.object.clone(options);
+ var baseOptions = ol.object.assign({}, options);
delete baseOptions.gradient;
delete baseOptions.radius;
@@ -114125,9 +98508,9 @@ ol.layer.Heatmap = function(opt_options) {
*/
this.styleCache_ = null;
- goog.events.listen(this,
+ ol.events.listen(this,
ol.Object.getChangeEventType(ol.layer.HeatmapLayerProperty.GRADIENT),
- this.handleGradientChanged_, false, this);
+ this.handleGradientChanged_, this);
this.setGradient(options.gradient ?
options.gradient : ol.layer.Heatmap.DEFAULT_GRADIENT);
@@ -114136,16 +98519,18 @@ ol.layer.Heatmap = function(opt_options) {
this.setRadius(options.radius !== undefined ? options.radius : 8);
- goog.events.listen(this, [
- ol.Object.getChangeEventType(ol.layer.HeatmapLayerProperty.BLUR),
- ol.Object.getChangeEventType(ol.layer.HeatmapLayerProperty.RADIUS)
- ], this.handleStyleChanged_, false, this);
+ ol.events.listen(this,
+ ol.Object.getChangeEventType(ol.layer.HeatmapLayerProperty.BLUR),
+ this.handleStyleChanged_, this);
+ ol.events.listen(this,
+ ol.Object.getChangeEventType(ol.layer.HeatmapLayerProperty.RADIUS),
+ this.handleStyleChanged_, this);
this.handleStyleChanged_();
var weight = options.weight ? options.weight : 'weight';
var weightFunction;
- if (goog.isString(weight)) {
+ if (typeof weight === 'string') {
weightFunction = function(feature) {
return feature.get(weight);
};
@@ -114155,7 +98540,7 @@ ol.layer.Heatmap = function(opt_options) {
goog.asserts.assert(goog.isFunction(weightFunction),
'weightFunction should be a function');
- this.setStyle(goog.bind(function(feature, resolution) {
+ this.setStyle(function(feature, resolution) {
goog.asserts.assert(this.styleCache_, 'this.styleCache_ expected');
goog.asserts.assert(this.circleImage_ !== undefined,
'this.circleImage_ should be defined');
@@ -114176,14 +98561,13 @@ ol.layer.Heatmap = function(opt_options) {
this.styleCache_[index] = style;
}
return style;
- }, this));
+ }.bind(this));
// For performance reasons, don't sort the features before rendering.
// The render order is not relevant for a heatmap representation.
this.setRenderOrder(null);
- goog.events.listen(this, ol.render.EventType.RENDER,
- this.handleRender_, false, this);
+ ol.events.listen(this, ol.render.EventType.RENDER, this.handleRender_, this);
};
goog.inherits(ol.layer.Heatmap, ol.layer.Vector);
@@ -114197,8 +98581,8 @@ ol.layer.Heatmap.DEFAULT_GRADIENT = ['#00f', '#0ff', '#0f0', '#ff0', '#f00'];
/**
- * @param {Array.<string>} colors
- * @return {Uint8ClampedArray}
+ * @param {Array.<string>} colors A list of colored.
+ * @return {Uint8ClampedArray} An array.
* @private
*/
ol.layer.Heatmap.createGradient_ = function(colors) {
@@ -114220,7 +98604,7 @@ ol.layer.Heatmap.createGradient_ = function(colors) {
/**
- * @return {string}
+ * @return {string} Data URL for a circle.
* @private
*/
ol.layer.Heatmap.prototype.createCircle_ = function() {
@@ -114351,7 +98735,44 @@ ol.layer.Heatmap.prototype.setRadius = function(radius) {
this.set(ol.layer.HeatmapLayerProperty.RADIUS, radius);
};
-goog.provide('ol.raster.Operation');
+goog.provide('ol.net');
+
+
+/**
+ * Simple JSONP helper. Supports error callbacks and a custom callback param.
+ * The error callback will be called when no JSONP is executed after 10 seconds.
+ *
+ * @param {string} url Request url. A 'callback' query parameter will be
+ * appended.
+ * @param {Function} callback Callback on success.
+ * @param {function()=} opt_errback Callback on error.
+ * @param {string=} opt_callbackParam Custom query parameter for the JSONP
+ * callback. Default is 'callback'.
+ */
+ol.net.jsonp = function(url, callback, opt_errback, opt_callbackParam) {
+ var script = ol.global.document.createElement('script');
+ var key = 'olc_' + goog.getUid(callback);
+ function cleanup() {
+ delete ol.global[key];
+ script.parentNode.removeChild(script);
+ }
+ script.async = true;
+ script.src = url + (url.indexOf('?') == -1 ? '?' : '&') +
+ (opt_callbackParam || 'callback') + '=' + key;
+ var timer = ol.global.setTimeout(function() {
+ cleanup();
+ if (opt_errback) {
+ opt_errback();
+ }
+ }, 10000);
+ ol.global[key] = function(data) {
+ ol.global.clearTimeout(timer);
+ cleanup();
+ callback(data);
+ };
+ ol.global.document.getElementsByTagName('head')[0].appendChild(script);
+};
+
goog.provide('ol.raster.OperationType');
@@ -114365,35 +98786,6 @@ ol.raster.OperationType = {
IMAGE: 'image'
};
-
-/**
- * A function that takes an array of input data, performs some operation, and
- * returns an array of ouput data. For `'pixel'` type operations, functions
- * will be called with an array of {@link ol.raster.Pixel} data and should
- * return an array of the same. For `'image'` type operations, functions will
- * be called with an array of {@link ImageData
- * https://developer.mozilla.org/en-US/docs/Web/API/ImageData} and should return
- * an array of the same. The operations are called with a second "data"
- * argument, which can be used for storage. The data object is accessible
- * from raster events, where it can be initialized in "beforeoperations" and
- * accessed again in "afteroperations".
- *
- * @typedef {function((Array.<ol.raster.Pixel>|Array.<ImageData>), Object):
- * (Array.<ol.raster.Pixel>|Array.<ImageData>)}
- * @api
- */
-ol.raster.Operation;
-
-goog.provide('ol.raster.Pixel');
-
-
-/**
- * An array of numbers representing pixel values.
- * @typedef {Array.<number>} ol.raster.Pixel
- * @api
- */
-ol.raster.Pixel;
-
goog.provide('ol.render');
goog.require('goog.vec.Mat4');
@@ -114412,13 +98804,10 @@ goog.require('ol.vec.Mat4');
* var render = ol.render.toContext(canvas.getContext('2d'),
* { size: [100, 100] });
* render.setFillStrokeStyle(new ol.style.Fill({ color: blue }));
- * render.drawPolygonGeometry(
+ * render.drawPolygon(
* new ol.geom.Polygon([[[0, 0], [100, 100], [100, 0], [0, 0]]]));
* ```
*
- * Note that {@link ol.render.canvas.Immediate#drawAsync} and
- * {@link ol.render.canvas.Immediate#drawFeature} cannot be used.
- *
* @param {CanvasRenderingContext2D} context Canvas context.
* @param {olx.render.ToContextOptions=} opt_options Options.
* @return {ol.render.canvas.Immediate} Canvas Immediate.
@@ -114443,30 +98832,21 @@ ol.render.toContext = function(context, opt_options) {
};
goog.provide('ol.reproj.Tile');
-goog.provide('ol.reproj.TileFunctionType');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.math');
-goog.require('goog.object');
goog.require('ol.Tile');
goog.require('ol.TileState');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
goog.require('ol.math');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.reproj');
goog.require('ol.reproj.Triangulation');
/**
- * @typedef {function(number, number, number, number) : ol.Tile}
- */
-ol.reproj.TileFunctionType;
-
-
-
-/**
* @classdesc
* Class encapsulating single reprojected tile.
* See {@link ol.source.TileImage}.
@@ -114480,14 +98860,15 @@ ol.reproj.TileFunctionType;
* @param {ol.TileCoord} tileCoord Coordinate of the tile.
* @param {ol.TileCoord} wrappedTileCoord Coordinate of the tile wrapped in X.
* @param {number} pixelRatio Pixel ratio.
- * @param {ol.reproj.TileFunctionType} getTileFunction
+ * @param {number} gutter Gutter of the source tiles.
+ * @param {ol.ReprojTileFunctionType} getTileFunction
* Function returning source tiles (z, x, y, pixelRatio).
* @param {number=} opt_errorThreshold Acceptable reprojection error (in px).
* @param {boolean=} opt_renderEdges Render reprojection edges.
*/
ol.reproj.Tile = function(sourceProj, sourceTileGrid,
targetProj, targetTileGrid, tileCoord, wrappedTileCoord,
- pixelRatio, getTileFunction,
+ pixelRatio, gutter, getTileFunction,
opt_errorThreshold,
opt_renderEdges) {
goog.base(this, tileCoord, ol.TileState.IDLE);
@@ -114506,6 +98887,12 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
/**
* @private
+ * @type {number}
+ */
+ this.gutter_ = gutter;
+
+ /**
+ * @private
* @type {HTMLCanvasElement}
*/
this.canvas_ = null;
@@ -114542,7 +98929,7 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
/**
* @private
- * @type {Array.<goog.events.Key>}
+ * @type {Array.<ol.events.Key>}
*/
this.sourcesListenerKeys_ = null;
@@ -114583,7 +98970,7 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
var sourceResolution = ol.reproj.calculateSourceResolution(
sourceProj, targetProj, targetCenter, targetResolution);
- if (!goog.math.isFiniteNumber(sourceResolution) || sourceResolution <= 0) {
+ if (!isFinite(sourceResolution) || sourceResolution <= 0) {
// invalid sourceResolution -> EMPTY
// probably edges of the projections when no extent is defined
this.state = ol.TileState.EMPTY;
@@ -114671,7 +99058,7 @@ ol.reproj.Tile.prototype.getImage = function(opt_context) {
var key = goog.getUid(opt_context);
if (key in this.canvasByContext_) {
return this.canvasByContext_[key];
- } else if (goog.object.isEmpty(this.canvasByContext_)) {
+ } else if (ol.object.isEmpty(this.canvasByContext_)) {
image = this.canvas_;
} else {
image = /** @type {HTMLCanvasElement} */ (this.canvas_.cloneNode(false));
@@ -114699,21 +99086,25 @@ ol.reproj.Tile.prototype.reproject_ = function() {
}, this);
this.sourceTiles_.length = 0;
- var z = this.wrappedTileCoord_[0];
- var size = this.targetTileGrid_.getTileSize(z);
- var width = goog.isNumber(size) ? size : size[0];
- var height = goog.isNumber(size) ? size : size[1];
- var targetResolution = this.targetTileGrid_.getResolution(z);
- var sourceResolution = this.sourceTileGrid_.getResolution(this.sourceZ_);
-
- var targetExtent = this.targetTileGrid_.getTileCoordExtent(
- this.wrappedTileCoord_);
- this.canvas_ = ol.reproj.render(width, height, this.pixelRatio_,
- sourceResolution, this.sourceTileGrid_.getExtent(),
- targetResolution, targetExtent, this.triangulation_, sources,
- this.renderEdges_);
-
- this.state = ol.TileState.LOADED;
+ if (sources.length === 0) {
+ this.state = ol.TileState.ERROR;
+ } else {
+ var z = this.wrappedTileCoord_[0];
+ var size = this.targetTileGrid_.getTileSize(z);
+ var width = goog.isNumber(size) ? size : size[0];
+ var height = goog.isNumber(size) ? size : size[1];
+ var targetResolution = this.targetTileGrid_.getResolution(z);
+ var sourceResolution = this.sourceTileGrid_.getResolution(this.sourceZ_);
+
+ var targetExtent = this.targetTileGrid_.getTileCoordExtent(
+ this.wrappedTileCoord_);
+ this.canvas_ = ol.reproj.render(width, height, this.pixelRatio_,
+ sourceResolution, this.sourceTileGrid_.getExtent(),
+ targetResolution, targetExtent, this.triangulation_, sources,
+ this.gutter_, this.renderEdges_);
+
+ this.state = ol.TileState.LOADED;
+ }
this.changed();
};
@@ -114738,13 +99129,13 @@ ol.reproj.Tile.prototype.load = function() {
leftToLoad++;
var sourceListenKey;
- sourceListenKey = tile.listen(goog.events.EventType.CHANGE,
+ sourceListenKey = ol.events.listen(tile, ol.events.EventType.CHANGE,
function(e) {
var state = tile.getState();
if (state == ol.TileState.LOADED ||
state == ol.TileState.ERROR ||
state == ol.TileState.EMPTY) {
- goog.events.unlistenByKey(sourceListenKey);
+ ol.events.unlistenByKey(sourceListenKey);
leftToLoad--;
goog.asserts.assert(leftToLoad >= 0,
'leftToLoad should not be negative');
@@ -114753,7 +99144,7 @@ ol.reproj.Tile.prototype.load = function() {
this.reproject_();
}
}
- }, false, this);
+ }, this);
this.sourcesListenerKeys_.push(sourceListenKey);
}
}, this);
@@ -114766,7 +99157,7 @@ ol.reproj.Tile.prototype.load = function() {
});
if (leftToLoad === 0) {
- this.reproject_();
+ ol.global.setTimeout(this.reproject_.bind(this), 0);
}
}
};
@@ -114778,751 +99169,23 @@ ol.reproj.Tile.prototype.load = function() {
ol.reproj.Tile.prototype.unlistenSources_ = function() {
goog.asserts.assert(this.sourcesListenerKeys_,
'this.sourcesListenerKeys_ should not be null');
- this.sourcesListenerKeys_.forEach(goog.events.unlistenByKey);
+ this.sourcesListenerKeys_.forEach(ol.events.unlistenByKey);
this.sourcesListenerKeys_ = null;
};
-// Copyright 2011 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-/**
- * @fileoverview A utility to load JavaScript files via DOM script tags.
- * Refactored from goog.net.Jsonp. Works cross-domain.
- *
- */
-
-goog.provide('goog.net.jsloader');
-goog.provide('goog.net.jsloader.Error');
-goog.provide('goog.net.jsloader.ErrorCode');
-goog.provide('goog.net.jsloader.Options');
-
-goog.require('goog.array');
-goog.require('goog.async.Deferred');
-goog.require('goog.debug.Error');
-goog.require('goog.dom');
-goog.require('goog.dom.TagName');
-goog.require('goog.object');
-
-
-/**
- * The name of the property of goog.global under which the JavaScript
- * verification object is stored by the loaded script.
- * @private {string}
- */
-goog.net.jsloader.GLOBAL_VERIFY_OBJS_ = 'closure_verification';
-
-
-/**
- * The default length of time, in milliseconds, we are prepared to wait for a
- * load request to complete.
- * @type {number}
- */
-goog.net.jsloader.DEFAULT_TIMEOUT = 5000;
-
-
-/**
- * Optional parameters for goog.net.jsloader.send.
- * timeout: The length of time, in milliseconds, we are prepared to wait
- * for a load request to complete. Default it 5 seconds.
- * document: The HTML document under which to load the JavaScript. Default is
- * the current document.
- * cleanupWhenDone: If true clean up the script tag after script completes to
- * load. This is important if you just want to read data from the JavaScript
- * and then throw it away. Default is false.
- * attributes: Additional attributes to set on the script tag.
- *
- * @typedef {{
- * timeout: (number|undefined),
- * document: (HTMLDocument|undefined),
- * cleanupWhenDone: (boolean|undefined),
- * attributes: (!Object<string, string>|undefined)
- * }}
- */
-goog.net.jsloader.Options;
-
-
-/**
- * Scripts (URIs) waiting to be loaded.
- * @private {!Array<string>}
- */
-goog.net.jsloader.scriptsToLoad_ = [];
-
-
-/**
- * The deferred result of loading the URIs in scriptsToLoad_.
- * We need to return this to a caller that wants to load URIs while
- * a deferred is already working on them.
- * @private {!goog.async.Deferred<null>}
- */
-goog.net.jsloader.scriptLoadingDeferred_;
-
-
-/**
- * Loads and evaluates the JavaScript files at the specified URIs, guaranteeing
- * the order of script loads.
- *
- * Because we have to load the scripts in serial (load script 1, exec script 1,
- * load script 2, exec script 2, and so on), this will be slower than doing
- * the network fetches in parallel.
- *
- * If you need to load a large number of scripts but dependency order doesn't
- * matter, you should just call goog.net.jsloader.load N times.
- *
- * If you need to load a large number of scripts on the same domain,
- * you may want to use goog.module.ModuleLoader.
- *
- * @param {Array<string>} uris The URIs to load.
- * @param {goog.net.jsloader.Options=} opt_options Optional parameters. See
- * goog.net.jsloader.options documentation for details.
- * @return {!goog.async.Deferred} The deferred result, that may be used to add
- * callbacks
- */
-goog.net.jsloader.loadMany = function(uris, opt_options) {
- // Loading the scripts in serial introduces asynchronosity into the flow.
- // Therefore, there are race conditions where client A can kick off the load
- // sequence for client B, even though client A's scripts haven't all been
- // loaded yet.
- //
- // To work around this issue, all module loads share a queue.
- if (!uris.length) {
- return goog.async.Deferred.succeed(null);
- }
-
- var isAnotherModuleLoading = goog.net.jsloader.scriptsToLoad_.length;
- goog.array.extend(goog.net.jsloader.scriptsToLoad_, uris);
- if (isAnotherModuleLoading) {
- // jsloader is still loading some other scripts.
- // In order to prevent the race condition noted above, we just add
- // these URIs to the end of the scripts' queue and return the deferred
- // result of the ongoing script load, so the caller knows when they
- // finish loading.
- return goog.net.jsloader.scriptLoadingDeferred_;
- }
-
- uris = goog.net.jsloader.scriptsToLoad_;
- var popAndLoadNextScript = function() {
- var uri = uris.shift();
- var deferred = goog.net.jsloader.load(uri, opt_options);
- if (uris.length) {
- deferred.addBoth(popAndLoadNextScript);
- }
- return deferred;
- };
- goog.net.jsloader.scriptLoadingDeferred_ = popAndLoadNextScript();
- return goog.net.jsloader.scriptLoadingDeferred_;
-};
-
-
-/**
- * Loads and evaluates a JavaScript file.
- * When the script loads, a user callback is called.
- * It is the client's responsibility to verify that the script ran successfully.
- *
- * @param {string} uri The URI of the JavaScript.
- * @param {goog.net.jsloader.Options=} opt_options Optional parameters. See
- * goog.net.jsloader.Options documentation for details.
- * @return {!goog.async.Deferred} The deferred result, that may be used to add
- * callbacks and/or cancel the transmission.
- * The error callback will be called with a single goog.net.jsloader.Error
- * parameter.
- */
-goog.net.jsloader.load = function(uri, opt_options) {
- var options = opt_options || {};
- var doc = options.document || document;
-
- var script = goog.dom.createElement(goog.dom.TagName.SCRIPT);
- var request = {script_: script, timeout_: undefined};
- var deferred = new goog.async.Deferred(goog.net.jsloader.cancel_, request);
-
- // Set a timeout.
- var timeout = null;
- var timeoutDuration = goog.isDefAndNotNull(options.timeout) ?
- options.timeout : goog.net.jsloader.DEFAULT_TIMEOUT;
- if (timeoutDuration > 0) {
- timeout = window.setTimeout(function() {
- goog.net.jsloader.cleanup_(script, true);
- deferred.errback(new goog.net.jsloader.Error(
- goog.net.jsloader.ErrorCode.TIMEOUT,
- 'Timeout reached for loading script ' + uri));
- }, timeoutDuration);
- request.timeout_ = timeout;
- }
-
- // Hang the user callback to be called when the script completes to load.
- // NOTE(user): This callback will be called in IE even upon error. In any
- // case it is the client's responsibility to verify that the script ran
- // successfully.
- script.onload = script.onreadystatechange = function() {
- if (!script.readyState || script.readyState == 'loaded' ||
- script.readyState == 'complete') {
- var removeScriptNode = options.cleanupWhenDone || false;
- goog.net.jsloader.cleanup_(script, removeScriptNode, timeout);
- deferred.callback(null);
- }
- };
-
- // Add an error callback.
- // NOTE(user): Not supported in IE.
- script.onerror = function() {
- goog.net.jsloader.cleanup_(script, true, timeout);
- deferred.errback(new goog.net.jsloader.Error(
- goog.net.jsloader.ErrorCode.LOAD_ERROR,
- 'Error while loading script ' + uri));
- };
-
- var properties = options.attributes || {};
- goog.object.extend(properties, {
- 'type': 'text/javascript',
- 'charset': 'UTF-8',
- // NOTE(user): Safari never loads the script if we don't set
- // the src attribute before appending.
- 'src': uri
- });
- goog.dom.setProperties(script, properties);
- var scriptParent = goog.net.jsloader.getScriptParentElement_(doc);
- scriptParent.appendChild(script);
-
- return deferred;
-};
-
-
-/**
- * Loads a JavaScript file and verifies it was evaluated successfully, using a
- * verification object.
- * The verification object is set by the loaded JavaScript at the end of the
- * script.
- * We verify this object was set and return its value in the success callback.
- * If the object is not defined we trigger an error callback.
- *
- * @param {string} uri The URI of the JavaScript.
- * @param {string} verificationObjName The name of the verification object that
- * the loaded script should set.
- * @param {goog.net.jsloader.Options} options Optional parameters. See
- * goog.net.jsloader.Options documentation for details.
- * @return {!goog.async.Deferred} The deferred result, that may be used to add
- * callbacks and/or cancel the transmission.
- * The success callback will be called with a single parameter containing
- * the value of the verification object.
- * The error callback will be called with a single goog.net.jsloader.Error
- * parameter.
- */
-goog.net.jsloader.loadAndVerify = function(uri, verificationObjName, options) {
- // Define the global objects variable.
- if (!goog.global[goog.net.jsloader.GLOBAL_VERIFY_OBJS_]) {
- goog.global[goog.net.jsloader.GLOBAL_VERIFY_OBJS_] = {};
- }
- var verifyObjs = goog.global[goog.net.jsloader.GLOBAL_VERIFY_OBJS_];
-
- // Verify that the expected object does not exist yet.
- if (goog.isDef(verifyObjs[verificationObjName])) {
- // TODO(user): Error or reset variable?
- return goog.async.Deferred.fail(new goog.net.jsloader.Error(
- goog.net.jsloader.ErrorCode.VERIFY_OBJECT_ALREADY_EXISTS,
- 'Verification object ' + verificationObjName + ' already defined.'));
- }
-
- // Send request to load the JavaScript.
- var sendDeferred = goog.net.jsloader.load(uri, options);
-
- // Create a deferred object wrapping the send result.
- var deferred = new goog.async.Deferred(
- goog.bind(sendDeferred.cancel, sendDeferred));
-
- // Call user back with object that was set by the script.
- sendDeferred.addCallback(function() {
- var result = verifyObjs[verificationObjName];
- if (goog.isDef(result)) {
- deferred.callback(result);
- delete verifyObjs[verificationObjName];
- } else {
- // Error: script was not loaded properly.
- deferred.errback(new goog.net.jsloader.Error(
- goog.net.jsloader.ErrorCode.VERIFY_ERROR,
- 'Script ' + uri + ' loaded, but verification object ' +
- verificationObjName + ' was not defined.'));
- }
- });
-
- // Pass error to new deferred object.
- sendDeferred.addErrback(function(error) {
- if (goog.isDef(verifyObjs[verificationObjName])) {
- delete verifyObjs[verificationObjName];
- }
- deferred.errback(error);
- });
-
- return deferred;
-};
-
-
-/**
- * Gets the DOM element under which we should add new script elements.
- * How? Take the first head element, and if not found take doc.documentElement,
- * which always exists.
- *
- * @param {!HTMLDocument} doc The relevant document.
- * @return {!Element} The script parent element.
- * @private
- */
-goog.net.jsloader.getScriptParentElement_ = function(doc) {
- var headElements = doc.getElementsByTagName(goog.dom.TagName.HEAD);
- if (!headElements || goog.array.isEmpty(headElements)) {
- return doc.documentElement;
- } else {
- return headElements[0];
- }
-};
-
-
-/**
- * Cancels a given request.
- * @this {{script_: Element, timeout_: number}} The request context.
- * @private
- */
-goog.net.jsloader.cancel_ = function() {
- var request = this;
- if (request && request.script_) {
- var scriptNode = request.script_;
- if (scriptNode && scriptNode.tagName == goog.dom.TagName.SCRIPT) {
- goog.net.jsloader.cleanup_(scriptNode, true, request.timeout_);
- }
- }
-};
-
-
-/**
- * Removes the script node and the timeout.
- *
- * @param {Node} scriptNode The node to be cleaned up.
- * @param {boolean} removeScriptNode If true completely remove the script node.
- * @param {?number=} opt_timeout The timeout handler to cleanup.
- * @private
- */
-goog.net.jsloader.cleanup_ = function(scriptNode, removeScriptNode,
- opt_timeout) {
- if (goog.isDefAndNotNull(opt_timeout)) {
- goog.global.clearTimeout(opt_timeout);
- }
-
- scriptNode.onload = goog.nullFunction;
- scriptNode.onerror = goog.nullFunction;
- scriptNode.onreadystatechange = goog.nullFunction;
-
- // Do this after a delay (removing the script node of a running script can
- // confuse older IEs).
- if (removeScriptNode) {
- window.setTimeout(function() {
- goog.dom.removeNode(scriptNode);
- }, 0);
- }
-};
-
-
-/**
- * Possible error codes for jsloader.
- * @enum {number}
- */
-goog.net.jsloader.ErrorCode = {
- LOAD_ERROR: 0,
- TIMEOUT: 1,
- VERIFY_ERROR: 2,
- VERIFY_OBJECT_ALREADY_EXISTS: 3
-};
-
-
-
-/**
- * A jsloader error.
- *
- * @param {goog.net.jsloader.ErrorCode} code The error code.
- * @param {string=} opt_message Additional message.
- * @constructor
- * @extends {goog.debug.Error}
- * @final
- */
-goog.net.jsloader.Error = function(code, opt_message) {
- var msg = 'Jsloader error (code #' + code + ')';
- if (opt_message) {
- msg += ': ' + opt_message;
- }
- goog.net.jsloader.Error.base(this, 'constructor', msg);
-
- /**
- * The code for this error.
- *
- * @type {goog.net.jsloader.ErrorCode}
- */
- this.code = code;
-};
-goog.inherits(goog.net.jsloader.Error, goog.debug.Error);
-
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// 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.
-
-// The original file lives here: http://go/cross_domain_channel.js
-
-/**
- * @fileoverview Implements a cross-domain communication channel. A
- * typical web page is prevented by browser security from sending
- * request, such as a XMLHttpRequest, to other servers than the ones
- * from which it came. The Jsonp class provides a workaround by
- * using dynamically generated script tags. Typical usage:.
- *
- * var jsonp = new goog.net.Jsonp(new goog.Uri('http://my.host.com/servlet'));
- * var payload = { 'foo': 1, 'bar': true };
- * jsonp.send(payload, function(reply) { alert(reply) });
- *
- * This script works in all browsers that are currently supported by
- * the Google Maps API, which is IE 6.0+, Firefox 0.8+, Safari 1.2.4+,
- * Netscape 7.1+, Mozilla 1.4+, Opera 8.02+.
- *
- */
-
-goog.provide('goog.net.Jsonp');
-
-goog.require('goog.Uri');
-goog.require('goog.net.jsloader');
-
-// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
-//
-// This class allows us (Google) to send data from non-Google and thus
-// UNTRUSTED pages to our servers. Under NO CIRCUMSTANCES return
-// anything sensitive, such as session or cookie specific data. Return
-// only data that you want parties external to Google to have. Also
-// NEVER use this method to send data from web pages to untrusted
-// servers, or redirects to unknown servers (www.google.com/cache,
-// /q=xx&btnl, /url, www.googlepages.com, etc.)
-//
-// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
-
-
-
-/**
- * Creates a new cross domain channel that sends data to the specified
- * host URL. By default, if no reply arrives within 5s, the channel
- * assumes the call failed to complete successfully.
- *
- * @param {goog.Uri|string} uri The Uri of the server side code that receives
- * data posted through this channel (e.g.,
- * "http://maps.google.com/maps/geo").
- *
- * @param {string=} opt_callbackParamName The parameter name that is used to
- * specify the callback. Defaults to "callback".
- *
- * @constructor
- * @final
- */
-goog.net.Jsonp = function(uri, opt_callbackParamName) {
- /**
- * The uri_ object will be used to encode the payload that is sent to the
- * server.
- * @type {goog.Uri}
- * @private
- */
- this.uri_ = new goog.Uri(uri);
-
- /**
- * This is the callback parameter name that is added to the uri.
- * @type {string}
- * @private
- */
- this.callbackParamName_ = opt_callbackParamName ?
- opt_callbackParamName : 'callback';
-
- /**
- * The length of time, in milliseconds, this channel is prepared
- * to wait for for a request to complete. The default value is 5 seconds.
- * @type {number}
- * @private
- */
- this.timeout_ = 5000;
-};
-
-
-/**
- * The name of the property of goog.global under which the callback is
- * stored.
- */
-goog.net.Jsonp.CALLBACKS = '_callbacks_';
-
-
-/**
- * Used to generate unique callback IDs. The counter must be global because
- * all channels share a common callback object.
- * @private
- */
-goog.net.Jsonp.scriptCounter_ = 0;
-
-
-/**
- * Sets the length of time, in milliseconds, this channel is prepared
- * to wait for for a request to complete. If the call is not competed
- * within the set time span, it is assumed to have failed. To wait
- * indefinitely for a request to complete set the timout to a negative
- * number.
- *
- * @param {number} timeout The length of time before calls are
- * interrupted.
- */
-goog.net.Jsonp.prototype.setRequestTimeout = function(timeout) {
- this.timeout_ = timeout;
-};
-
-
-/**
- * Returns the current timeout value, in milliseconds.
- *
- * @return {number} The timeout value.
- */
-goog.net.Jsonp.prototype.getRequestTimeout = function() {
- return this.timeout_;
-};
-
-
-/**
- * Sends the given payload to the URL specified at the construction
- * time. The reply is delivered to the given replyCallback. If the
- * errorCallback is specified and the reply does not arrive within the
- * timeout period set on this channel, the errorCallback is invoked
- * with the original payload.
- *
- * If no reply callback is specified, then the response is expected to
- * consist of calls to globally registered functions. No &callback=
- * URL parameter will be sent in the request, and the script element
- * will be cleaned up after the timeout.
- *
- * @param {Object=} opt_payload Name-value pairs. If given, these will be
- * added as parameters to the supplied URI as GET parameters to the
- * given server URI.
- *
- * @param {Function=} opt_replyCallback A function expecting one
- * argument, called when the reply arrives, with the response data.
- *
- * @param {Function=} opt_errorCallback A function expecting one
- * argument, called on timeout, with the payload (if given), otherwise
- * null.
- *
- * @param {string=} opt_callbackParamValue Value to be used as the
- * parameter value for the callback parameter (callbackParamName).
- * To be used when the value needs to be fixed by the client for a
- * particular request, to make use of the cached responses for the request.
- * NOTE: If multiple requests are made with the same
- * opt_callbackParamValue, only the last call will work whenever the
- * response comes back.
- *
- * @return {!Object} A request descriptor that may be used to cancel this
- * transmission, or null, if the message may not be cancelled.
- */
-goog.net.Jsonp.prototype.send = function(opt_payload,
- opt_replyCallback,
- opt_errorCallback,
- opt_callbackParamValue) {
-
- var payload = opt_payload || null;
-
- var id = opt_callbackParamValue ||
- '_' + (goog.net.Jsonp.scriptCounter_++).toString(36) +
- goog.now().toString(36);
-
- if (!goog.global[goog.net.Jsonp.CALLBACKS]) {
- goog.global[goog.net.Jsonp.CALLBACKS] = {};
- }
-
- // Create a new Uri object onto which this payload will be added
- var uri = this.uri_.clone();
- if (payload) {
- goog.net.Jsonp.addPayloadToUri_(payload, uri);
- }
-
- if (opt_replyCallback) {
- var reply = goog.net.Jsonp.newReplyHandler_(id, opt_replyCallback);
- goog.global[goog.net.Jsonp.CALLBACKS][id] = reply;
-
- uri.setParameterValues(this.callbackParamName_,
- goog.net.Jsonp.CALLBACKS + '.' + id);
- }
-
- var deferred = goog.net.jsloader.load(uri.toString(),
- {timeout: this.timeout_, cleanupWhenDone: true});
- var error = goog.net.Jsonp.newErrorHandler_(id, payload, opt_errorCallback);
- deferred.addErrback(error);
-
- return {id_: id, deferred_: deferred};
-};
-
-
-/**
- * Cancels a given request. The request must be exactly the object returned by
- * the send method.
- *
- * @param {Object} request The request object returned by the send method.
- */
-goog.net.Jsonp.prototype.cancel = function(request) {
- if (request) {
- if (request.deferred_) {
- request.deferred_.cancel();
- }
- if (request.id_) {
- goog.net.Jsonp.cleanup_(request.id_, false);
- }
- }
-};
-
-
-/**
- * Creates a timeout callback that calls the given timeoutCallback with the
- * original payload.
- *
- * @param {string} id The id of the script node.
- * @param {Object} payload The payload that was sent to the server.
- * @param {Function=} opt_errorCallback The function called on timeout.
- * @return {!Function} A zero argument function that handles callback duties.
- * @private
- */
-goog.net.Jsonp.newErrorHandler_ = function(id,
- payload,
- opt_errorCallback) {
- /**
- * When we call across domains with a request, this function is the
- * timeout handler. Once it's done executing the user-specified
- * error-handler, it removes the script node and original function.
- */
- return function() {
- goog.net.Jsonp.cleanup_(id, false);
- if (opt_errorCallback) {
- opt_errorCallback(payload);
- }
- };
-};
-
-
-/**
- * Creates a reply callback that calls the given replyCallback with data
- * returned by the server.
- *
- * @param {string} id The id of the script node.
- * @param {Function} replyCallback The function called on reply.
- * @return {!Function} A reply callback function.
- * @private
- */
-goog.net.Jsonp.newReplyHandler_ = function(id, replyCallback) {
- /**
- * This function is the handler for the all-is-well response. It
- * clears the error timeout handler, calls the user's handler, then
- * removes the script node and itself.
- *
- * @param {...Object} var_args The response data sent from the server.
- */
- var handler = function(var_args) {
- goog.net.Jsonp.cleanup_(id, true);
- replyCallback.apply(undefined, arguments);
- };
- return handler;
-};
-
-
-/**
- * Removes the script node and reply handler with the given id.
- *
- * @param {string} id The id of the script node to be removed.
- * @param {boolean} deleteReplyHandler If true, delete the reply handler
- * instead of setting it to nullFunction (if we know the callback could
- * never be called again).
- * @private
- */
-goog.net.Jsonp.cleanup_ = function(id, deleteReplyHandler) {
- if (goog.global[goog.net.Jsonp.CALLBACKS][id]) {
- if (deleteReplyHandler) {
- delete goog.global[goog.net.Jsonp.CALLBACKS][id];
- } else {
- // Removing the script tag doesn't necessarily prevent the script
- // from firing, so we make the callback a noop.
- goog.global[goog.net.Jsonp.CALLBACKS][id] = goog.nullFunction;
- }
- }
-};
-
-
-/**
- * Returns URL encoded payload. The payload should be a map of name-value
- * pairs, in the form {"foo": 1, "bar": true, ...}. If the map is empty,
- * the URI will be unchanged.
- *
- * <p>The method uses hasOwnProperty() to assure the properties are on the
- * object, not on its prototype.
- *
- * @param {!Object} payload A map of value name pairs to be encoded.
- * A value may be specified as an array, in which case a query parameter
- * will be created for each value, e.g.:
- * {"foo": [1,2]} will encode to "foo=1&foo=2".
- *
- * @param {!goog.Uri} uri A Uri object onto which the payload key value pairs
- * will be encoded.
- *
- * @return {!goog.Uri} A reference to the Uri sent as a parameter.
- * @private
- */
-goog.net.Jsonp.addPayloadToUri_ = function(payload, uri) {
- for (var name in payload) {
- // NOTE(user): Safari/1.3 doesn't have hasOwnProperty(). In that
- // case, we iterate over all properties as a very lame workaround.
- if (!payload.hasOwnProperty || payload.hasOwnProperty(name)) {
- uri.setParameterValues(name, payload[name]);
- }
- }
- return uri;
-};
-
-
-// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
-//
-// This class allows us (Google) to send data from non-Google and thus
-// UNTRUSTED pages to our servers. Under NO CIRCUMSTANCES return
-// anything sensitive, such as session or cookie specific data. Return
-// only data that you want parties external to Google to have. Also
-// NEVER use this method to send data from web pages to untrusted
-// servers, or redirects to unknown servers (www.google.com/cache,
-// /q=xx&btnl, /url, www.googlepages.com, etc.)
-//
-// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
-
goog.provide('ol.source.TileImage');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('ol.ImageTile');
goog.require('ol.TileCache');
goog.require('ol.TileState');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.proj');
goog.require('ol.reproj.Tile');
goog.require('ol.source.UrlTile');
-
/**
* @classdesc
* Base class for sources providing images divided into a tile grid.
@@ -115537,12 +99200,12 @@ ol.source.TileImage = function(options) {
goog.base(this, {
attributions: options.attributions,
+ cacheSize: options.cacheSize,
extent: options.extent,
logo: options.logo,
opaque: options.opaque,
projection: options.projection,
- state: options.state !== undefined ?
- /** @type {ol.source.State} */ (options.state) : undefined,
+ state: options.state,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction ?
options.tileLoadFunction : ol.source.TileImage.defaultTileLoadFunction,
@@ -115602,14 +99265,16 @@ ol.source.TileImage.prototype.canExpireCache = function() {
if (!ol.ENABLE_RASTER_REPROJECTION) {
return goog.base(this, 'canExpireCache');
}
- var canExpire = this.tileCache.canExpireCache();
- if (canExpire) {
+ if (this.tileCache.canExpireCache()) {
return true;
} else {
- return goog.object.some(this.tileCacheForProjection, function(tileCache) {
- return tileCache.canExpireCache();
- });
+ for (var key in this.tileCacheForProjection) {
+ if (this.tileCacheForProjection[key].canExpireCache()) {
+ return true;
+ }
+ }
}
+ return false;
};
@@ -115624,9 +99289,47 @@ ol.source.TileImage.prototype.expireCache = function(projection, usedTiles) {
var usedTileCache = this.getTileCacheForProjection(projection);
this.tileCache.expireCache(this.tileCache == usedTileCache ? usedTiles : {});
- goog.object.forEach(this.tileCacheForProjection, function(tileCache) {
+ for (var id in this.tileCacheForProjection) {
+ var tileCache = this.tileCacheForProjection[id];
tileCache.expireCache(tileCache == usedTileCache ? usedTiles : {});
- });
+ }
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.source.TileImage.prototype.getGutter = function(projection) {
+ if (ol.ENABLE_RASTER_REPROJECTION &&
+ this.getProjection() && projection &&
+ !ol.proj.equivalent(this.getProjection(), projection)) {
+ return 0;
+ } else {
+ return this.getGutterInternal();
+ }
+};
+
+
+/**
+ * @protected
+ * @return {number} Gutter.
+ */
+ol.source.TileImage.prototype.getGutterInternal = function() {
+ return 0;
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.source.TileImage.prototype.getOpaque = function(projection) {
+ if (ol.ENABLE_RASTER_REPROJECTION &&
+ this.getProjection() && projection &&
+ !ol.proj.equivalent(this.getProjection(), projection)) {
+ return false;
+ } else {
+ return goog.base(this, 'getOpaque', projection);
+ }
};
@@ -115682,8 +99385,7 @@ ol.source.TileImage.prototype.getTileCacheForProjection = function(projection) {
* @return {ol.Tile} Tile.
* @private
*/
-ol.source.TileImage.prototype.createTile_ =
- function(z, x, y, pixelRatio, projection, key) {
+ol.source.TileImage.prototype.createTile_ = function(z, x, y, pixelRatio, projection, key) {
var tileCoord = [z, x, y];
var urlTileCoord = this.getTileCoordForTileUrlFunction(
tileCoord, projection);
@@ -115696,8 +99398,8 @@ ol.source.TileImage.prototype.createTile_ =
this.crossOrigin,
this.tileLoadFunction);
tile.key = key;
- goog.events.listen(tile, goog.events.EventType.CHANGE,
- this.handleTileChange, false, this);
+ ol.events.listen(tile, ol.events.EventType.CHANGE,
+ this.handleTileChange, this);
return tile;
};
@@ -115705,8 +99407,7 @@ ol.source.TileImage.prototype.createTile_ =
/**
* @inheritDoc
*/
-ol.source.TileImage.prototype.getTile =
- function(z, x, y, pixelRatio, projection) {
+ol.source.TileImage.prototype.getTile = function(z, x, y, pixelRatio, projection) {
if (!ol.ENABLE_RASTER_REPROJECTION ||
!this.getProjection() ||
!projection ||
@@ -115727,10 +99428,11 @@ ol.source.TileImage.prototype.getTile =
var tile = new ol.reproj.Tile(
sourceProjection, sourceTileGrid,
projection, targetTileGrid,
- tileCoord, wrappedTileCoord, this.getTilePixelRatio(),
- goog.bind(function(z, x, y, pixelRatio) {
+ tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio),
+ this.getGutterInternal(),
+ function(z, x, y, pixelRatio) {
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection);
- }, this), this.reprojectionErrorThreshold_,
+ }.bind(this), this.reprojectionErrorThreshold_,
this.renderReprojectionEdges_);
cache.set(tileCoordKey, tile);
@@ -115749,23 +99451,22 @@ ol.source.TileImage.prototype.getTile =
* @return {!ol.Tile} Tile.
* @protected
*/
-ol.source.TileImage.prototype.getTileInternal =
- function(z, x, y, pixelRatio, projection) {
+ol.source.TileImage.prototype.getTileInternal = function(z, x, y, pixelRatio, projection) {
var /** @type {ol.Tile} */ tile = null;
var tileCoordKey = this.getKeyZXY(z, x, y);
- var paramsKey = this.getKeyParams();
+ var key = this.getKey();
if (!this.tileCache.containsKey(tileCoordKey)) {
goog.asserts.assert(projection, 'argument projection is truthy');
- tile = this.createTile_(z, x, y, pixelRatio, projection, paramsKey);
+ tile = this.createTile_(z, x, y, pixelRatio, projection, key);
this.tileCache.set(tileCoordKey, tile);
} else {
tile = /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey));
- if (tile.key != paramsKey) {
+ if (tile.key != key) {
// The source's params changed. If the tile has an interim tile and if we
// can use it then we use it. Otherwise we create a new tile. In both
// cases we attempt to assign an interim tile to the new tile.
var /** @type {ol.Tile} */ interimTile = tile;
- if (tile.interimTile && tile.interimTile.key == paramsKey) {
+ if (tile.interimTile && tile.interimTile.key == key) {
goog.asserts.assert(tile.interimTile.getState() == ol.TileState.LOADED);
goog.asserts.assert(tile.interimTile.interimTile === null);
tile = tile.interimTile;
@@ -115773,7 +99474,7 @@ ol.source.TileImage.prototype.getTileInternal =
tile.interimTile = interimTile;
}
} else {
- tile = this.createTile_(z, x, y, pixelRatio, projection, paramsKey);
+ tile = this.createTile_(z, x, y, pixelRatio, projection, key);
if (interimTile.getState() == ol.TileState.LOADED) {
tile.interimTile = interimTile;
} else if (interimTile.interimTile &&
@@ -115804,9 +99505,9 @@ ol.source.TileImage.prototype.setRenderReprojectionEdges = function(render) {
return;
}
this.renderReprojectionEdges_ = render;
- goog.object.forEach(this.tileCacheForProjection, function(tileCache) {
- tileCache.clear();
- });
+ for (var id in this.tileCacheForProjection) {
+ this.tileCacheForProjection[id].clear();
+ }
this.changed();
};
@@ -115823,8 +99524,7 @@ ol.source.TileImage.prototype.setRenderReprojectionEdges = function(render) {
* @param {ol.tilegrid.TileGrid} tilegrid Tile grid to use for the projection.
* @api
*/
-ol.source.TileImage.prototype.setTileGridForProjection =
- function(projection, tilegrid) {
+ol.source.TileImage.prototype.setTileGridForProjection = function(projection, tilegrid) {
if (ol.ENABLE_RASTER_REPROJECTION) {
var proj = ol.proj.get(projection);
if (proj) {
@@ -115847,20 +99547,18 @@ ol.source.TileImage.defaultTileLoadFunction = function(imageTile, src) {
goog.provide('ol.source.BingMaps');
-goog.require('goog.Uri');
goog.require('goog.asserts');
-goog.require('goog.net.Jsonp');
goog.require('ol.Attribution');
goog.require('ol.TileRange');
goog.require('ol.TileUrlFunction');
goog.require('ol.extent');
+goog.require('ol.net');
goog.require('ol.proj');
goog.require('ol.source.State');
goog.require('ol.source.TileImage');
goog.require('ol.tilecoord');
-
/**
* @classdesc
* Layer source for Bing Maps tile data.
@@ -115873,6 +99571,7 @@ goog.require('ol.tilecoord');
ol.source.BingMaps = function(options) {
goog.base(this, {
+ cacheSize: options.cacheSize,
crossOrigin: 'anonymous',
opaque: true,
projection: ol.proj.get('EPSG:3857'),
@@ -115894,16 +99593,12 @@ ol.source.BingMaps = function(options) {
*/
this.maxZoom_ = options.maxZoom !== undefined ? options.maxZoom : -1;
- var uri = new goog.Uri(
- 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
- options.imagerySet);
+ var url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
+ options.imagerySet +
+ '?uriScheme=https&include=ImageryProviders&key=' + options.key;
- var jsonp = new goog.net.Jsonp(uri, 'jsonp');
- jsonp.send({
- 'include': 'ImageryProviders',
- 'uriScheme': 'https',
- 'key': options.key
- }, goog.bind(this.handleImageryMetadataResponse, this));
+ ol.net.jsonp(url, this.handleImageryMetadataResponse.bind(this), undefined,
+ 'jsonp');
};
goog.inherits(ol.source.BingMaps, ol.source.TileImage);
@@ -115926,8 +99621,7 @@ ol.source.BingMaps.TOS_ATTRIBUTION = new ol.Attribution({
/**
* @param {BingMapsImageryMetadataResponse} response Response.
*/
-ol.source.BingMaps.prototype.handleImageryMetadataResponse =
- function(response) {
+ol.source.BingMaps.prototype.handleImageryMetadataResponse = function(response) {
if (response.statusCode != 200 ||
response.statusDescription != 'OK' ||
@@ -116026,28 +99720,252 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse =
};
+goog.provide('ol.source.XYZ');
+
+goog.require('ol.source.TileImage');
+
+
+/**
+ * @classdesc
+ * Layer source for tile data with URLs in a set XYZ format that are
+ * defined in a URL template. By default, this follows the widely-used
+ * Google grid where `x` 0 and `y` 0 are in the top left. Grids like
+ * TMS where `x` 0 and `y` 0 are in the bottom left can be used by
+ * using the `{-y}` placeholder in the URL template, so long as the
+ * source does not have a custom tile grid. In this case,
+ * {@link ol.source.TileImage} can be used with a `tileUrlFunction`
+ * such as:
+ *
+ * tileUrlFunction: function(coordinate) {
+ * return 'http://mapserver.com/' + coordinate[0] + '/' +
+ * coordinate[1] + '/' + coordinate[2] + '.png';
+ * }
+ *
+ *
+ * @constructor
+ * @extends {ol.source.TileImage}
+ * @param {olx.source.XYZOptions=} opt_options XYZ options.
+ * @api stable
+ */
+ol.source.XYZ = function(opt_options) {
+ var options = opt_options || {};
+ var projection = options.projection !== undefined ?
+ options.projection : 'EPSG:3857';
+
+ var tileGrid = options.tileGrid !== undefined ? options.tileGrid :
+ ol.tilegrid.createXYZ({
+ extent: ol.tilegrid.extentFromProjection(projection),
+ maxZoom: options.maxZoom,
+ minZoom: options.minZoom,
+ tileSize: options.tileSize
+ });
+
+ goog.base(this, {
+ attributions: options.attributions,
+ cacheSize: options.cacheSize,
+ crossOrigin: options.crossOrigin,
+ logo: options.logo,
+ opaque: options.opaque,
+ projection: projection,
+ reprojectionErrorThreshold: options.reprojectionErrorThreshold,
+ tileGrid: tileGrid,
+ tileLoadFunction: options.tileLoadFunction,
+ tilePixelRatio: options.tilePixelRatio,
+ tileUrlFunction: options.tileUrlFunction,
+ url: options.url,
+ urls: options.urls,
+ wrapX: options.wrapX !== undefined ? options.wrapX : true
+ });
+
+};
+goog.inherits(ol.source.XYZ, ol.source.TileImage);
+
+goog.provide('ol.source.CartoDB');
+
+goog.require('ol.object');
+goog.require('ol.source.State');
+goog.require('ol.source.XYZ');
+
+
+/**
+ * @classdesc
+ * Layer source for the CartoDB tiles.
+ *
+ * @constructor
+ * @extends {ol.source.XYZ}
+ * @param {olx.source.CartoDBOptions} options CartoDB options.
+ * @api
+ */
+ol.source.CartoDB = function(options) {
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.account_ = options.account;
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.mapId_ = options.map || '';
+
+ /**
+ * @type {!Object}
+ * @private
+ */
+ this.config_ = options.config || {};
+
+ /**
+ * @type {!Object.<string, CartoDBLayerInfo>}
+ * @private
+ */
+ this.templateCache_ = {};
+
+ goog.base(this, {
+ attributions: options.attributions,
+ cacheSize: options.cacheSize,
+ crossOrigin: options.crossOrigin,
+ logo: options.logo,
+ maxZoom: options.maxZoom !== undefined ? options.maxZoom : 18,
+ minZoom: options.minZoom,
+ projection: options.projection,
+ state: ol.source.State.LOADING,
+ wrapX: options.wrapX
+ });
+ this.initializeMap_();
+};
+goog.inherits(ol.source.CartoDB, ol.source.XYZ);
+
+
+/**
+ * Returns the current config.
+ * @return {!Object} The current configuration.
+ * @api
+ */
+ol.source.CartoDB.prototype.getConfig = function() {
+ return this.config_;
+};
+
+
+/**
+ * Updates the carto db config.
+ * @param {Object} config a key-value lookup. Values will replace current values
+ * in the config.
+ * @api
+ */
+ol.source.CartoDB.prototype.updateConfig = function(config) {
+ ol.object.assign(this.config_, config);
+ this.initializeMap_();
+};
+
+
+/**
+ * Sets the CartoDB config
+ * @param {Object} config In the case of anonymous maps, a CartoDB configuration
+ * object.
+ * If using named maps, a key-value lookup with the template parameters.
+ * @api
+ */
+ol.source.CartoDB.prototype.setConfig = function(config) {
+ this.config_ = config || {};
+ this.initializeMap_();
+};
+
+
+/**
+ * Issue a request to initialize the CartoDB map.
+ * @private
+ */
+ol.source.CartoDB.prototype.initializeMap_ = function() {
+ var paramHash = JSON.stringify(this.config_);
+ if (this.templateCache_[paramHash]) {
+ this.applyTemplate_(this.templateCache_[paramHash]);
+ return;
+ }
+ var mapUrl = 'https://' + this.account_ + '.cartodb.com/api/v1/map';
+
+ if (this.mapId_) {
+ mapUrl += '/named/' + this.mapId_;
+ }
+
+ var client = new XMLHttpRequest();
+ client.addEventListener('load', this.handleInitResponse_.bind(this, paramHash));
+ client.addEventListener('error', this.handleInitError_.bind(this));
+ client.open('POST', mapUrl);
+ client.setRequestHeader('Content-type', 'application/json');
+ client.send(JSON.stringify(this.config_));
+};
+
+
+/**
+ * Handle map initialization response.
+ * @param {string} paramHash a hash representing the parameter set that was used
+ * for the request
+ * @param {Event} event Event.
+ * @private
+ */
+ol.source.CartoDB.prototype.handleInitResponse_ = function(paramHash, event) {
+ var client = /** @type {XMLHttpRequest} */ (event.target);
+ if (client.status >= 200 && client.status < 300) {
+ var response;
+ try {
+ response = /** @type {CartoDBLayerInfo} */(JSON.parse(client.responseText));
+ } catch (err) {
+ this.setState(ol.source.State.ERROR);
+ return;
+ }
+ this.applyTemplate_(response);
+ this.templateCache_[paramHash] = response;
+ this.setState(ol.source.State.READY);
+ } else {
+ this.setState(ol.source.State.ERROR);
+ }
+};
+
+
+/**
+ * @private
+ * @param {Event} event Event.
+ */
+ol.source.CartoDB.prototype.handleInitError_ = function(event) {
+ this.setState(ol.source.State.ERROR);
+}
+
+
+/**
+ * Apply the new tile urls returned by carto db
+ * @param {CartoDBLayerInfo} data Result of carto db call.
+ * @private
+ */
+ol.source.CartoDB.prototype.applyTemplate_ = function(data) {
+ var tilesUrl = 'https://' + data.cdn_url.https + '/' + this.account_ +
+ '/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png';
+ this.setUrl(tilesUrl);
+};
+
// FIXME keep cluster cache by resolution ?
// FIXME distance not respected because of the centroid
goog.provide('ol.source.Cluster');
goog.require('goog.asserts');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('ol.Feature');
goog.require('ol.coordinate');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
goog.require('ol.geom.Point');
goog.require('ol.source.Vector');
-
/**
* @classdesc
- * Layer source to cluster vector data.
+ * Layer source to cluster vector data. Works out of the box with point
+ * geometries. For other geometry types, or if not all geometries should be
+ * considered for clustering, a custom `geometryFunction` can be defined.
*
* @constructor
- * @param {olx.source.ClusterOptions} options
+ * @param {olx.source.ClusterOptions} options Constructor options.
* @extends {ol.source.Vector}
* @api
*/
@@ -116079,12 +99997,23 @@ ol.source.Cluster = function(options) {
this.features_ = [];
/**
+ * @param {ol.Feature} feature Feature.
+ * @return {ol.geom.Point} Cluster calculation point.
+ */
+ this.geometryFunction_ = options.geometryFunction || function(feature) {
+ var geometry = feature.getGeometry();
+ goog.asserts.assert(geometry instanceof ol.geom.Point,
+ 'feature geometry is a ol.geom.Point instance');
+ return geometry;
+ };
+
+ /**
* @type {ol.source.Vector}
* @private
*/
this.source_ = options.source;
- this.source_.on(goog.events.EventType.CHANGE,
+ this.source_.on(ol.events.EventType.CHANGE,
ol.source.Cluster.prototype.onSourceChange_, this);
};
goog.inherits(ol.source.Cluster, ol.source.Vector);
@@ -116140,74 +100069,340 @@ ol.source.Cluster.prototype.cluster_ = function() {
var features = this.source_.getFeatures();
/**
- * @type {Object.<string, boolean>}
+ * @type {!Object.<string, boolean>}
*/
var clustered = {};
for (var i = 0, ii = features.length; i < ii; i++) {
var feature = features[i];
if (!(goog.getUid(feature).toString() in clustered)) {
- var geometry = feature.getGeometry();
- goog.asserts.assert(geometry instanceof ol.geom.Point,
- 'feature geometry is a ol.geom.Point instance');
- var coordinates = geometry.getCoordinates();
- ol.extent.createOrUpdateFromCoordinate(coordinates, extent);
- ol.extent.buffer(extent, mapDistance, extent);
-
- var neighbors = this.source_.getFeaturesInExtent(extent);
- goog.asserts.assert(neighbors.length >= 1, 'at least one neighbor found');
- neighbors = neighbors.filter(function(neighbor) {
- var uid = goog.getUid(neighbor).toString();
- if (!(uid in clustered)) {
- clustered[uid] = true;
- return true;
- } else {
- return false;
- }
- });
- this.features_.push(this.createCluster_(neighbors));
+ var geometry = this.geometryFunction_(feature);
+ if (geometry) {
+ var coordinates = geometry.getCoordinates();
+ ol.extent.createOrUpdateFromCoordinate(coordinates, extent);
+ ol.extent.buffer(extent, mapDistance, extent);
+
+ var neighbors = this.source_.getFeaturesInExtent(extent);
+ goog.asserts.assert(neighbors.length >= 1, 'at least one neighbor found');
+ neighbors = neighbors.filter(function(neighbor) {
+ var uid = goog.getUid(neighbor).toString();
+ if (!(uid in clustered)) {
+ clustered[uid] = true;
+ return true;
+ } else {
+ return false;
+ }
+ });
+ this.features_.push(this.createCluster_(neighbors));
+ }
}
}
goog.asserts.assert(
- goog.object.getCount(clustered) == this.source_.getFeatures().length,
+ Object.keys(clustered).length == this.source_.getFeatures().length,
'number of clustered equals number of features in the source');
};
/**
* @param {Array.<ol.Feature>} features Features
- * @return {ol.Feature}
+ * @return {ol.Feature} The cluster feature.
* @private
*/
ol.source.Cluster.prototype.createCluster_ = function(features) {
- var length = features.length;
var centroid = [0, 0];
- for (var i = 0; i < length; i++) {
- var geometry = features[i].getGeometry();
- goog.asserts.assert(geometry instanceof ol.geom.Point,
- 'feature geometry is a ol.geom.Point instance');
- var coordinates = geometry.getCoordinates();
- ol.coordinate.add(centroid, coordinates);
+ for (var i = features.length - 1; i >= 0; --i) {
+ var geometry = this.geometryFunction_(features[i]);
+ if (geometry) {
+ ol.coordinate.add(centroid, geometry.getCoordinates());
+ } else {
+ features.splice(i, 1);
+ }
}
- ol.coordinate.scale(centroid, 1 / length);
+ ol.coordinate.scale(centroid, 1 / features.length);
var cluster = new ol.Feature(new ol.geom.Point(centroid));
cluster.set('features', features);
return cluster;
};
-goog.provide('ol.source.ImageMapGuide');
+goog.provide('ol.source.ImageArcGISRest');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
+goog.require('goog.asserts');
goog.require('goog.uri.utils');
+goog.require('ol');
goog.require('ol.Image');
-goog.require('ol.ImageLoadFunctionType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
+goog.require('ol.object');
+goog.require('ol.proj');
goog.require('ol.source.Image');
+/**
+ * @classdesc
+ * Source for data from ArcGIS Rest services providing single, untiled images.
+ * Useful when underlying map service has labels.
+ *
+ * If underlying map service is not using labels,
+ * take advantage of ol image caching and use
+ * {@link ol.source.TileArcGISRest} data source.
+ *
+ * @constructor
+ * @fires ol.source.ImageEvent
+ * @extends {ol.source.Image}
+ * @param {olx.source.ImageArcGISRestOptions=} opt_options Image ArcGIS Rest Options.
+ * @api
+ */
+ol.source.ImageArcGISRest = function(opt_options) {
+
+ var options = opt_options || {};
+
+ goog.base(this, {
+ attributions: options.attributions,
+ logo: options.logo,
+ projection: options.projection,
+ resolutions: options.resolutions
+ });
+
+ /**
+ * @private
+ * @type {?string}
+ */
+ this.crossOrigin_ =
+ options.crossOrigin !== undefined ? options.crossOrigin : null;
+
+ /**
+ * @private
+ * @type {string|undefined}
+ */
+ this.url_ = options.url;
+
+ /**
+ * @private
+ * @type {ol.ImageLoadFunctionType}
+ */
+ this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
+ options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction;
+
+
+ /**
+ * @private
+ * @type {!Object}
+ */
+ this.params_ = options.params || {};
+
+ /**
+ * @private
+ * @type {ol.Image}
+ */
+ this.image_ = null;
+
+ /**
+ * @private
+ * @type {ol.Size}
+ */
+ this.imageSize_ = [0, 0];
+
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this.renderedRevision_ = 0;
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
+
+};
+goog.inherits(ol.source.ImageArcGISRest, ol.source.Image);
+
+
+/**
+ * Get the user-provided params, i.e. those passed to the constructor through
+ * the "params" option, and possibly updated using the updateParams method.
+ * @return {Object} Params.
+ * @api stable
+ */
+ol.source.ImageArcGISRest.prototype.getParams = function() {
+ return this.params_;
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.source.ImageArcGISRest.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
+
+ if (this.url_ === undefined) {
+ return null;
+ }
+
+ resolution = this.findNearestResolution(resolution);
+
+ var image = this.image_;
+ if (image &&
+ this.renderedRevision_ == this.getRevision() &&
+ image.getResolution() == resolution &&
+ image.getPixelRatio() == pixelRatio &&
+ ol.extent.containsExtent(image.getExtent(), extent)) {
+ return image;
+ }
+
+ var params = {
+ 'F': 'image',
+ 'FORMAT': 'PNG32',
+ 'TRANSPARENT': true
+ };
+ ol.object.assign(params, this.params_);
+
+ extent = extent.slice();
+ var centerX = (extent[0] + extent[2]) / 2;
+ var centerY = (extent[1] + extent[3]) / 2;
+ if (this.ratio_ != 1) {
+ var halfWidth = this.ratio_ * ol.extent.getWidth(extent) / 2;
+ var halfHeight = this.ratio_ * ol.extent.getHeight(extent) / 2;
+ extent[0] = centerX - halfWidth;
+ extent[1] = centerY - halfHeight;
+ extent[2] = centerX + halfWidth;
+ extent[3] = centerY + halfHeight;
+ }
+
+ var imageResolution = resolution / pixelRatio;
+
+ // Compute an integer width and height.
+ var width = Math.ceil(ol.extent.getWidth(extent) / imageResolution);
+ var height = Math.ceil(ol.extent.getHeight(extent) / imageResolution);
+
+ // Modify the extent to match the integer width and height.
+ extent[0] = centerX - imageResolution * width / 2;
+ extent[2] = centerX + imageResolution * width / 2;
+ extent[1] = centerY - imageResolution * height / 2;
+ extent[3] = centerY + imageResolution * height / 2;
+
+ this.imageSize_[0] = width;
+ this.imageSize_[1] = height;
+
+ var url = this.getRequestUrl_(extent, this.imageSize_, pixelRatio,
+ projection, params);
+
+ this.image_ = new ol.Image(extent, resolution, pixelRatio,
+ this.getAttributions(), url, this.crossOrigin_, this.imageLoadFunction_);
+
+ this.renderedRevision_ = this.getRevision();
+
+ ol.events.listen(this.image_, ol.events.EventType.CHANGE,
+ this.handleImageChange, this);
+
+ return this.image_;
+
+};
+
+
+/**
+ * Return the image load function of the source.
+ * @return {ol.ImageLoadFunctionType} The image load function.
+ * @api
+ */
+ol.source.ImageArcGISRest.prototype.getImageLoadFunction = function() {
+ return this.imageLoadFunction_;
+};
+
+
+/**
+ * @param {ol.Extent} extent Extent.
+ * @param {ol.Size} size Size.
+ * @param {number} pixelRatio Pixel ratio.
+ * @param {ol.proj.Projection} projection Projection.
+ * @param {Object} params Params.
+ * @return {string} Request URL.
+ * @private
+ */
+ol.source.ImageArcGISRest.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
+
+ goog.asserts.assert(this.url_ !== undefined, 'url is defined');
+
+ // ArcGIS Server only wants the numeric portion of the projection ID.
+ var srid = projection.getCode().split(':').pop();
+
+ params['SIZE'] = size[0] + ',' + size[1];
+ params['BBOX'] = extent.join(',');
+ params['BBOXSR'] = srid;
+ params['IMAGESR'] = srid;
+ params['DPI'] = 90 * pixelRatio;
+
+ var url = this.url_;
+
+ var modifiedUrl = url
+ .replace(/MapServer\/?$/, 'MapServer/export')
+ .replace(/ImageServer\/?$/, 'ImageServer/exportImage');
+ if (modifiedUrl == url) {
+ goog.asserts.fail('Unknown Rest Service', url);
+ }
+ return goog.uri.utils.appendParamsFromMap(modifiedUrl, params);
+};
+
+
+/**
+ * Return the URL used for this ArcGIS source.
+ * @return {string|undefined} URL.
+ * @api stable
+ */
+ol.source.ImageArcGISRest.prototype.getUrl = function() {
+ return this.url_;
+};
+
+
+/**
+ * Set the image load function of the source.
+ * @param {ol.ImageLoadFunctionType} imageLoadFunction Image load function.
+ * @api
+ */
+ol.source.ImageArcGISRest.prototype.setImageLoadFunction = function(imageLoadFunction) {
+ this.image_ = null;
+ this.imageLoadFunction_ = imageLoadFunction;
+ this.changed();
+};
+
+
+/**
+ * Set the URL to use for requests.
+ * @param {string|undefined} url URL.
+ * @api stable
+ */
+ol.source.ImageArcGISRest.prototype.setUrl = function(url) {
+ if (url != this.url_) {
+ this.url_ = url;
+ this.image_ = null;
+ this.changed();
+ }
+};
+
+
+/**
+ * Update the user-provided params.
+ * @param {Object} params Params.
+ * @api stable
+ */
+ol.source.ImageArcGISRest.prototype.updateParams = function(params) {
+ ol.object.assign(this.params_, params);
+ this.image_ = null;
+ this.changed();
+};
+
+goog.provide('ol.source.ImageMapGuide');
+
+goog.require('ol.events');
+goog.require('ol.events.EventType');
+goog.require('goog.uri.utils');
+goog.require('ol.Image');
+goog.require('ol.extent');
+goog.require('ol.object');
+goog.require('ol.source.Image');
+
/**
* @classdesc
@@ -116242,9 +100437,9 @@ ol.source.ImageMapGuide = function(options) {
/**
* @private
- * @type {Object}
+ * @type {!Object}
*/
- this.params_ = options.params !== undefined ? options.params : {};
+ this.params_ = options.params || {};
/**
* @private
@@ -116315,8 +100510,7 @@ ol.source.ImageMapGuide.prototype.getParams = function() {
/**
* @inheritDoc
*/
-ol.source.ImageMapGuide.prototype.getImageInternal =
- function(extent, resolution, pixelRatio, projection) {
+ol.source.ImageMapGuide.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
resolution = this.findNearestResolution(resolution);
pixelRatio = this.hidpi_ ? pixelRatio : 1;
@@ -116343,8 +100537,8 @@ ol.source.ImageMapGuide.prototype.getImageInternal =
image = new ol.Image(extent, resolution, pixelRatio,
this.getAttributions(), imageUrl, this.crossOrigin_,
this.imageLoadFunction_);
- goog.events.listen(image, goog.events.EventType.CHANGE,
- this.handleImageChange, false, this);
+ ol.events.listen(image, ol.events.EventType.CHANGE,
+ this.handleImageChange, this);
} else {
image = null;
}
@@ -116392,7 +100586,7 @@ ol.source.ImageMapGuide.getScale = function(extent, size, metersPerUnit, dpi) {
* @api stable
*/
ol.source.ImageMapGuide.prototype.updateParams = function(params) {
- goog.object.extend(this.params_, params);
+ ol.object.assign(this.params_, params);
this.changed();
};
@@ -116405,8 +100599,7 @@ ol.source.ImageMapGuide.prototype.updateParams = function(params) {
* @param {ol.proj.Projection} projection Projection.
* @return {string} The mapagent map image request URL.
*/
-ol.source.ImageMapGuide.prototype.getUrl =
- function(baseUrl, params, extent, size, projection) {
+ol.source.ImageMapGuide.prototype.getUrl = function(baseUrl, params, extent, size, projection) {
var scale = ol.source.ImageMapGuide.getScale(extent, size,
this.metersPerUnit_, this.displayDpi_);
var center = ol.extent.getCenter(extent);
@@ -116423,7 +100616,7 @@ ol.source.ImageMapGuide.prototype.getUrl =
'SETVIEWCENTERX': center[0],
'SETVIEWCENTERY': center[1]
};
- goog.object.extend(baseParams, params);
+ ol.object.assign(baseParams, params);
return goog.uri.utils.appendParamsFromMap(baseUrl, baseParams);
};
@@ -116442,17 +100635,16 @@ ol.source.ImageMapGuide.prototype.setImageLoadFunction = function(
goog.provide('ol.source.ImageStatic');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.Image');
-goog.require('ol.ImageLoadFunctionType');
goog.require('ol.ImageState');
+goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.proj');
goog.require('ol.source.Image');
-
/**
* @classdesc
* A layer source for displaying a single, static image.
@@ -116463,10 +100655,6 @@ goog.require('ol.source.Image');
* @api stable
*/
ol.source.ImageStatic = function(options) {
-
- var attributions = options.attributions !== undefined ?
- options.attributions : null;
-
var imageExtent = options.imageExtent;
var crossOrigin = options.crossOrigin !== undefined ?
@@ -116477,7 +100665,7 @@ ol.source.ImageStatic = function(options) {
options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction;
goog.base(this, {
- attributions: attributions,
+ attributions: options.attributions,
logo: options.logo,
projection: ol.proj.get(options.projection)
});
@@ -116486,7 +100674,7 @@ ol.source.ImageStatic = function(options) {
* @private
* @type {ol.Image}
*/
- this.image_ = new ol.Image(imageExtent, undefined, 1, attributions,
+ this.image_ = new ol.Image(imageExtent, undefined, 1, this.getAttributions(),
options.url, crossOrigin, imageLoadFunction);
/**
@@ -116495,8 +100683,8 @@ ol.source.ImageStatic = function(options) {
*/
this.imageSize_ = options.imageSize ? options.imageSize : null;
- goog.events.listen(this.image_, goog.events.EventType.CHANGE,
- this.handleImageChange, false, this);
+ ol.events.listen(this.image_, ol.events.EventType.CHANGE,
+ this.handleImageChange, this);
};
goog.inherits(ol.source.ImageStatic, ol.source.Image);
@@ -116505,8 +100693,7 @@ goog.inherits(ol.source.ImageStatic, ol.source.Image);
/**
* @inheritDoc
*/
-ol.source.ImageStatic.prototype.getImageInternal =
- function(extent, resolution, pixelRatio, projection) {
+ol.source.ImageStatic.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
if (ol.extent.intersects(extent, this.image_.getExtent())) {
return this.image_;
}
@@ -116526,17 +100713,16 @@ ol.source.ImageStatic.prototype.handleImageChange = function(evt) {
imageWidth = this.imageSize_[0];
imageHeight = this.imageSize_[1];
} else {
- imageWidth = image.width;
- imageHeight = image.height;
+ // TODO: remove the type cast when a closure-compiler > 20160315 is used.
+ // see: https://github.com/google/closure-compiler/pull/1664
+ imageWidth = /** @type {number} */ (image.width);
+ imageHeight = /** @type {number} */ (image.height);
}
var resolution = ol.extent.getHeight(imageExtent) / imageHeight;
var targetWidth = Math.ceil(ol.extent.getWidth(imageExtent) / resolution);
if (targetWidth != imageWidth) {
- var canvas = /** @type {HTMLCanvasElement} */
- (document.createElement('canvas'));
- canvas.width = targetWidth;
- canvas.height = /** @type {number} */ (imageHeight);
- var context = canvas.getContext('2d');
+ var context = ol.dom.createCanvasContext2D(targetWidth, imageHeight);
+ var canvas = context.canvas;
context.drawImage(image, 0, 0, imageWidth, imageHeight,
0, 0, canvas.width, canvas.height);
this.image_.setImage(canvas);
@@ -116568,20 +100754,18 @@ ol.source.wms.ServerType = {
goog.provide('ol.source.ImageWMS');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
-goog.require('goog.string');
goog.require('goog.uri.utils');
goog.require('ol');
goog.require('ol.Image');
-goog.require('ol.ImageLoadFunctionType');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.source.Image');
goog.require('ol.source.wms');
goog.require('ol.source.wms.ServerType');
-
+goog.require('ol.string');
/**
@@ -116627,9 +100811,9 @@ ol.source.ImageWMS = function(opt_options) {
/**
* @private
- * @type {Object}
+ * @type {!Object}
*/
- this.params_ = options.params;
+ this.params_ = options.params || {};
/**
* @private
@@ -116701,8 +100885,7 @@ ol.source.ImageWMS.GETFEATUREINFO_IMAGE_SIZE_ = [101, 101];
* @return {string|undefined} GetFeatureInfo URL.
* @api stable
*/
-ol.source.ImageWMS.prototype.getGetFeatureInfoUrl =
- function(coordinate, resolution, projection, params) {
+ol.source.ImageWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resolution, projection, params) {
goog.asserts.assert(!('VERSION' in params),
'key VERSION is not allowed in params');
@@ -116723,7 +100906,7 @@ ol.source.ImageWMS.prototype.getGetFeatureInfoUrl =
'TRANSPARENT': true,
'QUERY_LAYERS': this.params_['LAYERS']
};
- goog.object.extend(baseParams, this.params_, params);
+ ol.object.assign(baseParams, this.params_, params);
var x = Math.floor((coordinate[0] - extent[0]) / resolution);
var y = Math.floor((extent[3] - coordinate[1]) / resolution);
@@ -116750,8 +100933,7 @@ ol.source.ImageWMS.prototype.getParams = function() {
/**
* @inheritDoc
*/
-ol.source.ImageWMS.prototype.getImageInternal =
- function(extent, resolution, pixelRatio, projection) {
+ol.source.ImageWMS.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
if (this.url_ === undefined) {
return null;
@@ -116796,7 +100978,7 @@ ol.source.ImageWMS.prototype.getImageInternal =
'FORMAT': 'image/png',
'TRANSPARENT': true
};
- goog.object.extend(params, this.params_);
+ ol.object.assign(params, this.params_);
this.imageSize_[0] = Math.ceil(imageWidth * this.ratio_);
this.imageSize_[1] = Math.ceil(imageHeight * this.ratio_);
@@ -116809,8 +100991,8 @@ ol.source.ImageWMS.prototype.getImageInternal =
this.renderedRevision_ = this.getRevision();
- goog.events.listen(this.image_, goog.events.EventType.CHANGE,
- this.handleImageChange, false, this);
+ ol.events.listen(this.image_, ol.events.EventType.CHANGE,
+ this.handleImageChange, this);
return this.image_;
@@ -116836,17 +101018,14 @@ ol.source.ImageWMS.prototype.getImageLoadFunction = function() {
* @return {string} Request URL.
* @private
*/
-ol.source.ImageWMS.prototype.getRequestUrl_ =
- function(extent, size, pixelRatio, projection, params) {
+ol.source.ImageWMS.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
goog.asserts.assert(this.url_ !== undefined, 'url is defined');
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
if (!('STYLES' in this.params_)) {
- /* jshint -W053 */
- params['STYLES'] = new String('');
- /* jshint +W053 */
+ params['STYLES'] = '';
}
if (pixelRatio != 1) {
@@ -116931,7 +101110,7 @@ ol.source.ImageWMS.prototype.setUrl = function(url) {
* @api stable
*/
ol.source.ImageWMS.prototype.updateParams = function(params) {
- goog.object.extend(this.params_, params);
+ ol.object.assign(this.params_, params);
this.updateV13_();
this.image_ = null;
this.changed();
@@ -116942,67 +101121,9 @@ ol.source.ImageWMS.prototype.updateParams = function(params) {
* @private
*/
ol.source.ImageWMS.prototype.updateV13_ = function() {
- var version =
- goog.object.get(this.params_, 'VERSION', ol.DEFAULT_WMS_VERSION);
- this.v13_ = goog.string.compareVersions(version, '1.3') >= 0;
-};
-
-goog.provide('ol.source.XYZ');
-
-goog.require('ol.source.TileImage');
-
-
-
-/**
- * @classdesc
- * Layer source for tile data with URLs in a set XYZ format that are
- * defined in a URL template. By default, this follows the widely-used
- * Google grid where `x` 0 and `y` 0 are in the top left. Grids like
- * TMS where `x` 0 and `y` 0 are in the bottom left can be used by
- * using the `{-y}` placeholder in the URL template, so long as the
- * source does not have a custom tile grid. In this case,
- * {@link ol.source.TileImage} can be used with a `tileUrlFunction`
- * such as:
- *
- * tileUrlFunction: function(coordinate) {
- * return 'http://mapserver.com/' + coordinate[0] + '/' +
- * coordinate[1] + '/' + coordinate[2] + '.png';
- * }
- *
- *
- * @constructor
- * @extends {ol.source.TileImage}
- * @param {olx.source.XYZOptions} options XYZ options.
- * @api stable
- */
-ol.source.XYZ = function(options) {
- var projection = options.projection !== undefined ?
- options.projection : 'EPSG:3857';
-
- var tileGrid = options.tileGrid !== undefined ? options.tileGrid :
- ol.tilegrid.createXYZ({
- extent: ol.tilegrid.extentFromProjection(projection),
- maxZoom: options.maxZoom,
- tileSize: options.tileSize
- });
-
- goog.base(this, {
- attributions: options.attributions,
- crossOrigin: options.crossOrigin,
- logo: options.logo,
- projection: projection,
- reprojectionErrorThreshold: options.reprojectionErrorThreshold,
- tileGrid: tileGrid,
- tileLoadFunction: options.tileLoadFunction,
- tilePixelRatio: options.tilePixelRatio,
- tileUrlFunction: options.tileUrlFunction,
- url: options.url,
- urls: options.urls,
- wrapX: options.wrapX !== undefined ? options.wrapX : true
- });
-
+ var version = this.params_['VERSION'] || ol.DEFAULT_WMS_VERSION;
+ this.v13_ = ol.string.compareVersions(version, '1.3') >= 0;
};
-goog.inherits(ol.source.XYZ, ol.source.TileImage);
goog.provide('ol.source.OSM');
@@ -117010,7 +101131,6 @@ goog.require('ol.Attribution');
goog.require('ol.source.XYZ');
-
/**
* @classdesc
* Layer source for the OpenStreetMap tile server.
@@ -117039,8 +101159,9 @@ ol.source.OSM = function(opt_options) {
goog.base(this, {
attributions: attributions,
+ cacheSize: options.cacheSize,
crossOrigin: crossOrigin,
- opaque: true,
+ opaque: options.opaque !== undefined ? options.opaque : true,
maxZoom: options.maxZoom !== undefined ? options.maxZoom : 19,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
tileLoadFunction: options.tileLoadFunction,
@@ -117073,7 +101194,6 @@ goog.require('ol.source.OSM');
goog.require('ol.source.XYZ');
-
/**
* @classdesc
* Layer source for the MapQuest tile server.
@@ -117104,11 +101224,12 @@ ol.source.MapQuest = function(opt_options) {
goog.base(this, {
attributions: layerConfig.attributions,
+ cacheSize: options.cacheSize,
crossOrigin: 'anonymous',
logo: 'https://developer.mapquest.com/content/osm/mq_logo.png',
maxZoom: layerConfig.maxZoom,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
- opaque: true,
+ opaque: layerConfig.opaque,
tileLoadFunction: options.tileLoadFunction,
url: url
});
@@ -117127,11 +101248,12 @@ ol.source.MapQuest.TILE_ATTRIBUTION = new ol.Attribution({
/**
- * @type {Object.<string, {maxZoom: number, attributions: (Array.<ol.Attribution>)}>}
+ * @type {Object.<string, {maxZoom: number, opaque: boolean, attributions: (Array.<ol.Attribution>)}>}
*/
ol.source.MapQuestConfig = {
'osm': {
maxZoom: 19,
+ opaque: true,
attributions: [
ol.source.MapQuest.TILE_ATTRIBUTION,
ol.source.OSM.ATTRIBUTION
@@ -117139,6 +101261,7 @@ ol.source.MapQuestConfig = {
},
'sat': {
maxZoom: 18,
+ opaque: true,
attributions: [
ol.source.MapQuest.TILE_ATTRIBUTION,
new ol.Attribution({
@@ -117149,6 +101272,7 @@ ol.source.MapQuestConfig = {
},
'hyb': {
maxZoom: 18,
+ opaque: false,
attributions: [
ol.source.MapQuest.TILE_ATTRIBUTION,
ol.source.OSM.ATTRIBUTION
@@ -117183,16 +101307,32 @@ var Processor = _dereq_('./processor');
exports.Processor = Processor;
},{"./processor":2}],2:[function(_dereq_,module,exports){
-/* eslint-disable dot-notation */
+var newImageData = _dereq_('./util').newImageData;
/**
- * Create a function for running operations.
+ * Create a function for running operations. This function is serialized for
+ * use in a worker.
* @param {function(Array, Object):*} operation The operation.
* @return {function(Object):ArrayBuffer} A function that takes an object with
* buffers, meta, imageOps, width, and height properties and returns an array
* buffer.
*/
function createMinion(operation) {
+ var workerHasImageData = true;
+ try {
+ new ImageData(10, 10);
+ } catch (_) {
+ workerHasImageData = false;
+ }
+
+ function newWorkerImageData(data, width, height) {
+ if (workerHasImageData) {
+ return new ImageData(data, width, height);
+ } else {
+ return {data: data, width: width, height: height};
+ }
+ }
+
return function(data) {
// bracket notation for minification support
var buffers = data['buffers'];
@@ -117208,7 +101348,7 @@ function createMinion(operation) {
if (imageOps) {
var images = new Array(numBuffers);
for (b = 0; b < numBuffers; ++b) {
- images[b] = new ImageData(
+ images[b] = newWorkerImageData(
new Uint8ClampedArray(buffers[b]), width, height);
}
output = operation(images, meta).data;
@@ -117242,7 +101382,7 @@ function createMinion(operation) {
/**
* Create a worker for running operations.
* @param {Object} config Configuration.
- * @param {function(Object)} onMessage Called with a message event.
+ * @param {function(MessageEvent)} onMessage Called with a message event.
* @return {Worker} The worker.
*/
function createWorker(config, onMessage) {
@@ -117251,12 +101391,10 @@ function createWorker(config, onMessage) {
});
var lines = lib.concat([
- 'var __minion__ = (' + createMinion.toString() + ')(',
- config.operation.toString(),
- ');',
- 'self.addEventListener("message", function(__event__) {',
- 'var buffer = __minion__(__event__.data);',
- 'self.postMessage({buffer: buffer, meta: __event__.data.meta}, [buffer]);',
+ 'var __minion__ = (' + createMinion.toString() + ')(', config.operation.toString(), ');',
+ 'self.addEventListener("message", function(event) {',
+ ' var buffer = __minion__(event.data);',
+ ' self.postMessage({buffer: buffer, meta: event.data.meta}, [buffer]);',
'});'
]);
@@ -117270,7 +101408,7 @@ function createWorker(config, onMessage) {
/**
* Create a faux worker for running operations.
* @param {Object} config Configuration.
- * @param {function(Object)} onMessage Called with a message event.
+ * @param {function(MessageEvent)} onMessage Called with a message event.
* @return {Object} The faux worker.
*/
function createFauxWorker(config, onMessage) {
@@ -117278,7 +101416,7 @@ function createFauxWorker(config, onMessage) {
return {
postMessage: function(data) {
setTimeout(function() {
- onMessage({data: {buffer: minion(data), meta: data.meta}});
+ onMessage({'data': {'buffer': minion(data), 'meta': data['meta']}});
}, 0);
}
};
@@ -117399,7 +101537,7 @@ Processor.prototype._dispatch = function() {
/**
* Handle messages from the worker.
* @param {number} index The worker index.
- * @param {Object} event The message event.
+ * @param {MessageEvent} event The message event.
*/
Processor.prototype._onWorkerMessage = function(index, event) {
if (this._destroyed) {
@@ -117438,12 +101576,34 @@ Processor.prototype._resolveJob = function() {
this._job = null;
this._dataLookup = {};
job.callback(null,
- new ImageData(data, job.inputs[0].width, job.inputs[0].height), meta);
+ newImageData(data, job.inputs[0].width, job.inputs[0].height), meta);
this._dispatch();
};
module.exports = Processor;
+},{"./util":3}],3:[function(_dereq_,module,exports){
+var hasImageData = true;
+try {
+ new ImageData(10, 10);
+} catch (_) {
+ hasImageData = false;
+}
+
+var context = document.createElement('canvas').getContext('2d');
+
+function newImageData(data, width, height) {
+ if (hasImageData) {
+ return new ImageData(data, width, height);
+ } else {
+ var imageData = context.createImageData(width, height);
+ imageData.data.set(data);
+ return imageData;
+ }
+}
+
+exports.newImageData = newImageData;
+
},{}]},{},[1])(1)
});
ol.ext.pixelworks = module.exports;
@@ -117454,18 +101614,18 @@ goog.provide('ol.source.RasterEvent');
goog.provide('ol.source.RasterEventType');
goog.require('goog.asserts');
-goog.require('goog.events');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventType');
-goog.require('goog.object');
goog.require('goog.vec.Mat4');
goog.require('ol.ImageCanvas');
goog.require('ol.TileQueue');
goog.require('ol.dom');
+goog.require('ol.events');
+goog.require('ol.events.Event');
+goog.require('ol.events.EventType');
goog.require('ol.ext.pixelworks');
goog.require('ol.extent');
goog.require('ol.layer.Image');
goog.require('ol.layer.Tile');
+goog.require('ol.object');
goog.require('ol.raster.OperationType');
goog.require('ol.renderer.canvas.ImageLayer');
goog.require('ol.renderer.canvas.TileLayer');
@@ -117474,7 +101634,6 @@ goog.require('ol.source.State');
goog.require('ol.source.Tile');
-
/**
* @classdesc
* A source that transforms data from any number of input sources using an array
@@ -117483,6 +101642,7 @@ goog.require('ol.source.Tile');
*
* @constructor
* @extends {ol.source.Image}
+ * @fires ol.source.RasterEvent
* @param {olx.source.RasterOptions} options Options.
* @api
*/
@@ -117514,8 +101674,8 @@ ol.source.Raster = function(options) {
this.renderers_ = ol.source.Raster.createRenderers_(options.sources);
for (var r = 0, rr = this.renderers_.length; r < rr; ++r) {
- goog.events.listen(this.renderers_[r], goog.events.EventType.CHANGE,
- this.changed, false, this);
+ ol.events.listen(this.renderers_[r], ol.events.EventType.CHANGE,
+ this.changed, this);
}
/**
@@ -117529,8 +101689,10 @@ ol.source.Raster = function(options) {
* @type {ol.TileQueue}
*/
this.tileQueue_ = new ol.TileQueue(
- function() { return 1; },
- goog.bind(this.changed, this));
+ function() {
+ return 1;
+ },
+ this.changed.bind(this));
var layerStatesArray = ol.source.Raster.getLayerStatesArray_(this.renderers_);
var layerStates = {};
@@ -117540,7 +101702,7 @@ ol.source.Raster = function(options) {
/**
* The most recently rendered state.
- * @type {?ol.source.Raster.RenderedState}
+ * @type {?ol.SourceRasterRenderedState}
* @private
*/
this.renderedState_ = null;
@@ -117618,14 +101780,13 @@ ol.source.Raster.prototype.setOperation = function(operation, opt_lib) {
* @return {olx.FrameState} The updated frame state.
* @private
*/
-ol.source.Raster.prototype.updateFrameState_ =
- function(extent, resolution, projection) {
+ol.source.Raster.prototype.updateFrameState_ = function(extent, resolution, projection) {
var frameState = /** @type {olx.FrameState} */ (
- goog.object.clone(this.frameState_));
+ ol.object.assign({}, this.frameState_));
frameState.viewState = /** @type {olx.ViewState} */ (
- goog.object.clone(frameState.viewState));
+ ol.object.assign({}, frameState.viewState));
var center = ol.extent.getCenter(extent);
var width = Math.round(ol.extent.getWidth(extent) / resolution);
@@ -117663,22 +101824,22 @@ ol.source.Raster.prototype.isDirty_ = function(extent, resolution) {
/**
* @inheritDoc
*/
-ol.source.Raster.prototype.getImage =
- function(extent, resolution, pixelRatio, projection) {
+ol.source.Raster.prototype.getImage = function(extent, resolution, pixelRatio, projection) {
if (!this.allSourcesReady_()) {
return null;
}
- if (!this.isDirty_(extent, resolution)) {
+ var currentExtent = extent.slice();
+ if (!this.isDirty_(currentExtent, resolution)) {
return this.renderedImageCanvas_;
}
var context = this.canvasContext_;
var canvas = context.canvas;
- var width = Math.round(ol.extent.getWidth(extent) / resolution);
- var height = Math.round(ol.extent.getHeight(extent) / resolution);
+ var width = Math.round(ol.extent.getWidth(currentExtent) / resolution);
+ var height = Math.round(ol.extent.getHeight(currentExtent) / resolution);
if (width !== canvas.width ||
height !== canvas.height) {
@@ -117686,16 +101847,16 @@ ol.source.Raster.prototype.getImage =
canvas.height = height;
}
- var frameState = this.updateFrameState_(extent, resolution, projection);
+ var frameState = this.updateFrameState_(currentExtent, resolution, projection);
var imageCanvas = new ol.ImageCanvas(
- extent, resolution, 1, this.getAttributions(), canvas,
+ currentExtent, resolution, 1, this.getAttributions(), canvas,
this.composeFrame_.bind(this, frameState));
this.renderedImageCanvas_ = imageCanvas;
this.renderedState_ = {
- extent: extent,
+ extent: currentExtent,
resolution: resolution,
revision: this.getRevision()
};
@@ -117764,8 +101925,7 @@ ol.source.Raster.prototype.composeFrame_ = function(frameState, callback) {
* @param {Object} data The user data.
* @private
*/
-ol.source.Raster.prototype.onWorkerComplete_ =
- function(frameState, callback, err, output, data) {
+ol.source.Raster.prototype.onWorkerComplete_ = function(frameState, callback, err, output, data) {
if (err) {
callback(err);
return;
@@ -117791,45 +101951,28 @@ ol.source.Raster.prototype.onWorkerComplete_ =
* Get image data from a renderer.
* @param {ol.renderer.canvas.Layer} renderer Layer renderer.
* @param {olx.FrameState} frameState The frame state.
- * @param {ol.layer.LayerState} layerState The layer state.
+ * @param {ol.LayerState} layerState The layer state.
* @return {ImageData} The image data.
* @private
*/
ol.source.Raster.getImageData_ = function(renderer, frameState, layerState) {
- renderer.prepareFrame(frameState, layerState);
- // We should be able to call renderer.composeFrame(), but this is inefficient
- // for tiled sources (we've already rendered to an intermediate canvas in the
- // prepareFrame call and we don't need to render again to the output canvas).
- // TODO: make all canvas renderers render to a single canvas
- var image = renderer.getImage();
- if (!image) {
+ if (!renderer.prepareFrame(frameState, layerState)) {
return null;
}
- var imageTransform = renderer.getImageTransform();
- var dx = Math.round(goog.vec.Mat4.getElement(imageTransform, 0, 3));
- var dy = Math.round(goog.vec.Mat4.getElement(imageTransform, 1, 3));
var width = frameState.size[0];
var height = frameState.size[1];
- if (image instanceof Image) {
- if (!ol.source.Raster.context_) {
+ if (!ol.source.Raster.context_) {
+ ol.source.Raster.context_ = ol.dom.createCanvasContext2D(width, height);
+ } else {
+ var canvas = ol.source.Raster.context_.canvas;
+ if (canvas.width !== width || canvas.height !== height) {
ol.source.Raster.context_ = ol.dom.createCanvasContext2D(width, height);
} else {
- var canvas = ol.source.Raster.context_.canvas;
- if (canvas.width !== width || canvas.height !== height) {
- ol.source.Raster.context_ = ol.dom.createCanvasContext2D(width, height);
- } else {
- ol.source.Raster.context_.clearRect(0, 0, width, height);
- }
+ ol.source.Raster.context_.clearRect(0, 0, width, height);
}
- var dw = Math.round(
- image.width * goog.vec.Mat4.getElement(imageTransform, 0, 0));
- var dh = Math.round(
- image.height * goog.vec.Mat4.getElement(imageTransform, 1, 1));
- ol.source.Raster.context_.drawImage(image, dx, dy, dw, dh);
- return ol.source.Raster.context_.getImageData(0, 0, width, height);
- } else {
- return image.getContext('2d').getImageData(-dx, -dy, width, height);
}
+ renderer.composeFrame(frameState, layerState, ol.source.Raster.context_);
+ return ol.source.Raster.context_.getImageData(0, 0, width, height);
};
@@ -117844,7 +101987,7 @@ ol.source.Raster.context_ = null;
/**
* Get a list of layer states from a list of renderers.
* @param {Array.<ol.renderer.canvas.Layer>} renderers Layer renderers.
- * @return {Array.<ol.layer.LayerState>} The layer states.
+ * @return {Array.<ol.LayerState>} The layer states.
* @private
*/
ol.source.Raster.getLayerStatesArray_ = function(renderers) {
@@ -117914,21 +102057,12 @@ ol.source.Raster.createTileRenderer_ = function(source) {
/**
- * @typedef {{revision: number,
- * resolution: number,
- * extent: ol.Extent}}
- */
-ol.source.Raster.RenderedState;
-
-
-
-/**
* @classdesc
* Events emitted by {@link ol.source.Raster} instances are instances of this
* type.
*
* @constructor
- * @extends {goog.events.Event}
+ * @extends {ol.events.Event}
* @implements {oli.source.RasterEvent}
* @param {string} type Type.
* @param {olx.FrameState} frameState The frame state.
@@ -117960,7 +102094,7 @@ ol.source.RasterEvent = function(type, frameState, data) {
this.data = data;
};
-goog.inherits(ol.source.RasterEvent, goog.events.Event);
+goog.inherits(ol.source.RasterEvent, ol.events.Event);
/**
@@ -118054,13 +102188,12 @@ ol.source.StamenProviderConfig = {
maxZoom: 20
},
'watercolor': {
- minZoom: 3,
+ minZoom: 1,
maxZoom: 16
}
};
-
/**
* @classdesc
* Layer source for the Stamen tile server.
@@ -118088,10 +102221,10 @@ ol.source.Stamen = function(options) {
goog.base(this, {
attributions: ol.source.Stamen.ATTRIBUTIONS,
+ cacheSize: options.cacheSize,
crossOrigin: 'anonymous',
maxZoom: providerConfig.maxZoom,
- // FIXME uncomment the following when tilegrid supports minZoom
- //minZoom: providerConfig.minZoom,
+ minZoom: providerConfig.minZoom,
opaque: layerConfig.opaque,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
tileLoadFunction: options.tileLoadFunction,
@@ -118118,20 +102251,17 @@ ol.source.Stamen.ATTRIBUTIONS = [
goog.provide('ol.source.TileArcGISRest');
goog.require('goog.asserts');
-goog.require('goog.math');
-goog.require('goog.object');
-goog.require('goog.string');
goog.require('goog.uri.utils');
goog.require('ol');
-goog.require('ol.TileCoord');
goog.require('ol.extent');
+goog.require('ol.object');
+goog.require('ol.math');
goog.require('ol.proj');
goog.require('ol.size');
goog.require('ol.source.TileImage');
goog.require('ol.tilecoord');
-
/**
* @classdesc
* Layer source for tile data from ArcGIS Rest services. Map and Image
@@ -118150,17 +102280,15 @@ ol.source.TileArcGISRest = function(opt_options) {
var options = opt_options || {};
- var params = options.params !== undefined ? options.params : {};
-
goog.base(this, {
attributions: options.attributions,
+ cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
logo: options.logo,
projection: options.projection,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
- tileUrlFunction: goog.bind(this.tileUrlFunction_, this),
url: options.url,
urls: options.urls,
wrapX: options.wrapX !== undefined ? options.wrapX : true
@@ -118168,9 +102296,9 @@ ol.source.TileArcGISRest = function(opt_options) {
/**
* @private
- * @type {Object}
+ * @type {!Object}
*/
- this.params_ = params;
+ this.params_ = options.params || {};
/**
* @private
@@ -118203,8 +102331,7 @@ ol.source.TileArcGISRest.prototype.getParams = function() {
* @return {string|undefined} Request URL.
* @private
*/
-ol.source.TileArcGISRest.prototype.getRequestUrl_ =
- function(tileCoord, tileSize, tileExtent,
+ol.source.TileArcGISRest.prototype.getRequestUrl_ = function(tileCoord, tileSize, tileExtent,
pixelRatio, projection, params) {
var urls = this.urls;
@@ -118227,55 +102354,32 @@ ol.source.TileArcGISRest.prototype.getRequestUrl_ =
if (urls.length == 1) {
url = urls[0];
} else {
- var index = goog.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);
+ var index = ol.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);
url = urls[index];
}
- if (!goog.string.endsWith(url, '/')) {
- url = url + '/';
- }
-
- // If a MapServer, use export. If an ImageServer, use exportImage.
- if (goog.string.endsWith(url, 'MapServer/')) {
- url = url + 'export';
- }
- else if (goog.string.endsWith(url, 'ImageServer/')) {
- url = url + 'exportImage';
- }
- else {
+ var modifiedUrl = url
+ .replace(/MapServer\/?$/, 'MapServer/export')
+ .replace(/ImageServer\/?$/, 'ImageServer/exportImage');
+ if (modifiedUrl == url) {
goog.asserts.fail('Unknown Rest Service', url);
}
-
- return goog.uri.utils.appendParamsFromMap(url, params);
+ return goog.uri.utils.appendParamsFromMap(modifiedUrl, params);
};
/**
- * @param {number} z Z.
- * @param {number} pixelRatio Pixel ratio.
- * @param {ol.proj.Projection} projection Projection.
- * @return {ol.Size} Size.
+ * @inheritDoc
*/
-ol.source.TileArcGISRest.prototype.getTilePixelSize =
- function(z, pixelRatio, projection) {
- var tileSize = goog.base(this, 'getTilePixelSize', z, pixelRatio, projection);
- if (pixelRatio == 1) {
- return tileSize;
- } else {
- return ol.size.scale(tileSize, pixelRatio, this.tmpSize);
- }
+ol.source.TileArcGISRest.prototype.getTilePixelRatio = function(pixelRatio) {
+ return pixelRatio;
};
/**
- * @param {ol.TileCoord} tileCoord Tile coordinate.
- * @param {number} pixelRatio Pixel ratio.
- * @param {ol.proj.Projection} projection Projection.
- * @return {string|undefined} Tile URL.
- * @private
+ * @inheritDoc
*/
-ol.source.TileArcGISRest.prototype.tileUrlFunction_ =
- function(tileCoord, pixelRatio, projection) {
+ol.source.TileArcGISRest.prototype.fixedTileUrlFunction = function(tileCoord, pixelRatio, projection) {
var tileGrid = this.getTileGrid();
if (!tileGrid) {
@@ -118301,7 +102405,7 @@ ol.source.TileArcGISRest.prototype.tileUrlFunction_ =
'FORMAT': 'PNG32',
'TRANSPARENT': true
};
- goog.object.extend(baseParams, this.params_);
+ ol.object.assign(baseParams, this.params_);
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
pixelRatio, projection, baseParams);
@@ -118314,20 +102418,17 @@ ol.source.TileArcGISRest.prototype.tileUrlFunction_ =
* @api stable
*/
ol.source.TileArcGISRest.prototype.updateParams = function(params) {
- goog.object.extend(this.params_, params);
+ ol.object.assign(this.params_, params);
this.changed();
};
goog.provide('ol.source.TileDebug');
goog.require('ol.Tile');
-goog.require('ol.TileCoord');
goog.require('ol.TileState');
goog.require('ol.dom');
goog.require('ol.size');
goog.require('ol.source.Tile');
-goog.require('ol.tilecoord');
-
/**
@@ -118395,7 +102496,6 @@ ol.DebugTile_.prototype.getImage = function(opt_context) {
};
-
/**
* @classdesc
* A pseudo tile source, which does not fetch tiles from a server, but renders
@@ -118433,8 +102533,8 @@ ol.source.TileDebug.prototype.getTile = function(z, x, y) {
var tileSize = ol.size.toSize(this.tileGrid.getTileSize(z));
var tileCoord = [z, x, y];
var textTileCoord = this.getTileCoordForTileUrlFunction(tileCoord);
- var text = !textTileCoord ? '' : ol.tilecoord.toString(
- this.getTileCoordForTileUrlFunction(textTileCoord));
+ var text = !textTileCoord ? '' :
+ this.getTileCoordForTileUrlFunction(textTileCoord).toString();
var tile = new ol.DebugTile_(tileCoord, tileSize, text);
this.tileCache.set(tileCoordKey, tile);
return tile;
@@ -118451,17 +102551,16 @@ goog.provide('ol.source.TileJSON');
goog.provide('ol.tilejson');
goog.require('goog.asserts');
-goog.require('goog.net.Jsonp');
goog.require('ol.Attribution');
goog.require('ol.TileRange');
goog.require('ol.TileUrlFunction');
goog.require('ol.extent');
+goog.require('ol.net');
goog.require('ol.proj');
goog.require('ol.source.State');
goog.require('ol.source.TileImage');
-
/**
* @classdesc
* Layer source for tile data in TileJSON format.
@@ -118473,8 +102572,15 @@ goog.require('ol.source.TileImage');
*/
ol.source.TileJSON = function(options) {
+ /**
+ * @type {TileJSON}
+ * @private
+ */
+ this.tileJSON_ = null;
+
goog.base(this, {
attributions: options.attributions,
+ cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
projection: ol.proj.get('EPSG:3857'),
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
@@ -118483,15 +102589,61 @@ ol.source.TileJSON = function(options) {
wrapX: options.wrapX !== undefined ? options.wrapX : true
});
- var request = new goog.net.Jsonp(options.url);
- request.send(undefined, goog.bind(this.handleTileJSONResponse, this),
- goog.bind(this.handleTileJSONError, this));
+ if (options.jsonp) {
+ ol.net.jsonp(options.url, this.handleTileJSONResponse.bind(this),
+ this.handleTileJSONError.bind(this));
+ } else {
+ var client = new XMLHttpRequest();
+ client.addEventListener('load', this.onXHRLoad_.bind(this));
+ client.addEventListener('error', this.onXHRError_.bind(this));
+ client.open('GET', options.url);
+ client.send();
+ }
};
goog.inherits(ol.source.TileJSON, ol.source.TileImage);
/**
+ * @private
+ * @param {Event} event The load event.
+ */
+ol.source.TileJSON.prototype.onXHRLoad_ = function(event) {
+ var client = /** @type {XMLHttpRequest} */ (event.target);
+ if (client.status >= 200 && client.status < 300) {
+ var response;
+ try {
+ response = /** @type {TileJSON} */(JSON.parse(client.responseText));
+ } catch (err) {
+ this.handleTileJSONError();
+ return;
+ }
+ this.handleTileJSONResponse(response);
+ } else {
+ this.handleTileJSONError();
+ }
+};
+
+
+/**
+ * @private
+ * @param {Event} event The error event.
+ */
+ol.source.TileJSON.prototype.onXHRError_ = function(event) {
+ this.handleTileJSONError();
+};
+
+
+/**
+ * @return {TileJSON} The tilejson object.
+ * @api
+ */
+ol.source.TileJSON.prototype.getTileJSON = function() {
+ return this.tileJSON_;
+};
+
+
+/**
* @protected
* @param {TileJSON} tileJSON Tile JSON.
*/
@@ -118540,7 +102692,7 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
})
]);
}
-
+ this.tileJSON_ = tileJSON;
this.setState(ol.source.State.READY);
};
@@ -118557,20 +102709,19 @@ goog.provide('ol.source.TileUTFGrid');
goog.require('goog.asserts');
goog.require('goog.async.nextTick');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.net.Jsonp');
goog.require('ol.Attribution');
goog.require('ol.Tile');
goog.require('ol.TileState');
goog.require('ol.TileUrlFunction');
+goog.require('ol.events');
+goog.require('ol.events.EventType');
goog.require('ol.extent');
+goog.require('ol.net');
goog.require('ol.proj');
goog.require('ol.source.State');
goog.require('ol.source.Tile');
-
/**
* @classdesc
* Layer source for UTFGrid interaction data loaded from TileJSON format.
@@ -118605,13 +102756,63 @@ ol.source.TileUTFGrid = function(options) {
*/
this.template_ = undefined;
- var request = new goog.net.Jsonp(options.url);
- request.send(undefined, goog.bind(this.handleTileJSONResponse, this));
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.jsonp_ = options.jsonp || false;
+
+ if (options.url) {
+ if (this.jsonp_) {
+ ol.net.jsonp(options.url, this.handleTileJSONResponse.bind(this),
+ this.handleTileJSONError.bind(this));
+ } else {
+ var client = new XMLHttpRequest();
+ client.addEventListener('load', this.onXHRLoad_.bind(this));
+ client.addEventListener('error', this.onXHRError_.bind(this));
+ client.open('GET', options.url);
+ client.send();
+ }
+ } else if (options.tileJSON) {
+ this.handleTileJSONResponse(options.tileJSON);
+ } else {
+ goog.asserts.fail('Either url or tileJSON options must be provided');
+ }
};
goog.inherits(ol.source.TileUTFGrid, ol.source.Tile);
/**
+ * @private
+ * @param {Event} event The load event.
+ */
+ol.source.TileUTFGrid.prototype.onXHRLoad_ = function(event) {
+ var client = /** @type {XMLHttpRequest} */ (event.target);
+ if (client.status >= 200 && client.status < 300) {
+ var response;
+ try {
+ response = /** @type {TileJSON} */(JSON.parse(client.responseText));
+ } catch (err) {
+ this.handleTileJSONError();
+ return;
+ }
+ this.handleTileJSONResponse(response);
+ } else {
+ this.handleTileJSONError();
+ }
+};
+
+
+/**
+ * @private
+ * @param {Event} event The error event.
+ */
+ol.source.TileUTFGrid.prototype.onXHRError_ = function(event) {
+ this.handleTileJSONError();
+};
+
+
+/**
* Return the template from TileJSON.
* @return {string|undefined} The template from TileJSON.
* @api
@@ -118627,7 +102828,7 @@ ol.source.TileUTFGrid.prototype.getTemplate = function() {
* in case of an error).
* @param {ol.Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
- * @param {function(this: T, Object)} callback Callback.
+ * @param {function(this: T, *)} callback Callback.
* @param {T=} opt_this The object to use as `this` in the callback.
* @param {boolean=} opt_request If `true` the callback is always async.
* The tile data is requested if not yet loaded.
@@ -118655,6 +102856,14 @@ ol.source.TileUTFGrid.prototype.forDataAtCoordinateAndResolution = function(
/**
+ * @protected
+ */
+ol.source.TileUTFGrid.prototype.handleTileJSONError = function() {
+ this.setState(ol.source.State.ERROR);
+};
+
+
+/**
* TODO: very similar to ol.source.TileJSON#handleTileJSONResponse
* @protected
* @param {TileJSON} tileJSON Tile JSON.
@@ -118721,8 +102930,7 @@ ol.source.TileUTFGrid.prototype.handleTileJSONResponse = function(tileJSON) {
/**
* @inheritDoc
*/
-ol.source.TileUTFGrid.prototype.getTile =
- function(z, x, y, pixelRatio, projection) {
+ol.source.TileUTFGrid.prototype.getTile = function(z, x, y, pixelRatio, projection) {
var tileCoordKey = this.getKeyZXY(z, x, y);
if (this.tileCache.containsKey(tileCoordKey)) {
return /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey));
@@ -118737,7 +102945,8 @@ ol.source.TileUTFGrid.prototype.getTile =
tileUrl !== undefined ? ol.TileState.IDLE : ol.TileState.EMPTY,
tileUrl !== undefined ? tileUrl : '',
this.tileGrid.getTileCoordExtent(tileCoord),
- this.preemptive_);
+ this.preemptive_,
+ this.jsonp_);
this.tileCache.set(tileCoordKey, tile);
return tile;
}
@@ -118755,7 +102964,6 @@ ol.source.TileUTFGrid.prototype.useTile = function(z, x, y) {
};
-
/**
* @constructor
* @extends {ol.Tile}
@@ -118764,10 +102972,10 @@ ol.source.TileUTFGrid.prototype.useTile = function(z, x, y) {
* @param {string} src Image source URI.
* @param {ol.Extent} extent Extent of the tile.
* @param {boolean} preemptive Load the tile when visible (before it's needed).
+ * @param {boolean} jsonp Load the tile as a script.
* @private
*/
-ol.source.TileUTFGridTile_ =
- function(tileCoord, state, src, extent, preemptive) {
+ol.source.TileUTFGridTile_ = function(tileCoord, state, src, extent, preemptive, jsonp) {
goog.base(this, tileCoord, state);
@@ -118806,6 +103014,14 @@ ol.source.TileUTFGridTile_ =
* @type {Object.<string, Object>|undefined}
*/
this.data_ = null;
+
+
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.jsonp_ = jsonp;
+
};
goog.inherits(ol.source.TileUTFGridTile_, ol.Tile);
@@ -118824,10 +103040,10 @@ ol.source.TileUTFGridTile_.prototype.getImage = function(opt_context) {
/**
* Synchronously returns data at given coordinate (if available).
* @param {ol.Coordinate} coordinate Coordinate.
- * @return {Object}
+ * @return {*} The data.
*/
ol.source.TileUTFGridTile_.prototype.getData = function(coordinate) {
- if (!this.grid_ || !this.keys_ || !this.data_) {
+ if (!this.grid_ || !this.keys_) {
return null;
}
var xRelative = (coordinate[0] - this.extent_[0]) /
@@ -118837,7 +103053,7 @@ ol.source.TileUTFGridTile_.prototype.getData = function(coordinate) {
var row = this.grid_[Math.floor((1 - yRelative) * this.grid_.length)];
- if (!goog.isString(row)) {
+ if (typeof row !== 'string') {
return null;
}
@@ -118850,7 +103066,16 @@ ol.source.TileUTFGridTile_.prototype.getData = function(coordinate) {
}
code -= 32;
- return (code in this.keys_) ? this.data_[this.keys_[code]] : null;
+ var data = null;
+ if (code in this.keys_) {
+ var id = this.keys_[code];
+ if (this.data_ && id in this.data_) {
+ data = this.data_[id];
+ } else {
+ data = id;
+ }
+ }
+ return data;
};
@@ -118858,18 +103083,17 @@ ol.source.TileUTFGridTile_.prototype.getData = function(coordinate) {
* Calls the callback (synchronously by default) with the available data
* for given coordinate (or `null` if not yet loaded).
* @param {ol.Coordinate} coordinate Coordinate.
- * @param {function(this: T, Object)} callback Callback.
+ * @param {function(this: T, *)} callback Callback.
* @param {T=} opt_this The object to use as `this` in the callback.
* @param {boolean=} opt_request If `true` the callback is always async.
* The tile data is requested if not yet loaded.
* @template T
*/
-ol.source.TileUTFGridTile_.prototype.forDataAtCoordinate =
- function(coordinate, callback, opt_this, opt_request) {
+ol.source.TileUTFGridTile_.prototype.forDataAtCoordinate = function(coordinate, callback, opt_this, opt_request) {
if (this.state == ol.TileState.IDLE && opt_request === true) {
- goog.events.listenOnce(this, goog.events.EventType.CHANGE, function(e) {
+ ol.events.listenOnce(this, ol.events.EventType.CHANGE, function(e) {
callback.call(opt_this, this.getData(coordinate));
- }, false, this);
+ }, this);
this.loadInternal_();
} else {
if (opt_request === true) {
@@ -118901,7 +103125,7 @@ ol.source.TileUTFGridTile_.prototype.handleError_ = function() {
/**
- * @param {!UTFGridJSON} json
+ * @param {!UTFGridJSON} json UTFGrid data.
* @private
*/
ol.source.TileUTFGridTile_.prototype.handleLoad_ = function(json) {
@@ -118920,14 +103144,51 @@ ol.source.TileUTFGridTile_.prototype.handleLoad_ = function(json) {
ol.source.TileUTFGridTile_.prototype.loadInternal_ = function() {
if (this.state == ol.TileState.IDLE) {
this.state = ol.TileState.LOADING;
- var request = new goog.net.Jsonp(this.src_);
- request.send(undefined, goog.bind(this.handleLoad_, this),
- goog.bind(this.handleError_, this));
+ if (this.jsonp_) {
+ ol.net.jsonp(this.src_, this.handleLoad_.bind(this),
+ this.handleError_.bind(this));
+ } else {
+ var client = new XMLHttpRequest();
+ client.addEventListener('load', this.onXHRLoad_.bind(this));
+ client.addEventListener('error', this.onXHRError_.bind(this));
+ client.open('GET', this.src_);
+ client.send();
+ }
}
};
/**
+ * @private
+ * @param {Event} event The load event.
+ */
+ol.source.TileUTFGridTile_.prototype.onXHRLoad_ = function(event) {
+ var client = /** @type {XMLHttpRequest} */ (event.target);
+ if (client.status >= 200 && client.status < 300) {
+ var response;
+ try {
+ response = /** @type {!UTFGridJSON} */(JSON.parse(client.responseText));
+ } catch (err) {
+ this.handleError_();
+ return;
+ }
+ this.handleLoad_(response);
+ } else {
+ this.handleError_();
+ }
+};
+
+
+/**
+ * @private
+ * @param {Event} event The error event.
+ */
+ol.source.TileUTFGridTile_.prototype.onXHRError_ = function(event) {
+ this.handleError_();
+};
+
+
+/**
* Load not yet loaded URI.
*/
ol.source.TileUTFGridTile_.prototype.load = function() {
@@ -118943,20 +103204,18 @@ ol.source.TileUTFGridTile_.prototype.load = function() {
goog.provide('ol.source.TileWMS');
goog.require('goog.asserts');
-goog.require('goog.math');
-goog.require('goog.object');
-goog.require('goog.string');
goog.require('goog.uri.utils');
goog.require('ol');
-goog.require('ol.TileCoord');
goog.require('ol.extent');
+goog.require('ol.object');
+goog.require('ol.math');
goog.require('ol.proj');
goog.require('ol.size');
goog.require('ol.source.TileImage');
goog.require('ol.source.wms');
goog.require('ol.source.wms.ServerType');
goog.require('ol.tilecoord');
-
+goog.require('ol.string');
/**
@@ -118972,12 +103231,13 @@ ol.source.TileWMS = function(opt_options) {
var options = opt_options || {};
- var params = options.params !== undefined ? options.params : {};
+ var params = options.params || {};
- var transparent = goog.object.get(params, 'TRANSPARENT', true);
+ var transparent = 'TRANSPARENT' in params ? params['TRANSPARENT'] : true;
goog.base(this, {
attributions: options.attributions,
+ cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
logo: options.logo,
opaque: !transparent,
@@ -118985,7 +103245,6 @@ ol.source.TileWMS = function(opt_options) {
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
- tileUrlFunction: goog.bind(this.tileUrlFunction_, this),
url: options.url,
urls: options.urls,
wrapX: options.wrapX !== undefined ? options.wrapX : true
@@ -118999,7 +103258,7 @@ ol.source.TileWMS = function(opt_options) {
/**
* @private
- * @type {Object}
+ * @type {!Object}
*/
this.params_ = params;
@@ -119036,6 +103295,7 @@ ol.source.TileWMS = function(opt_options) {
this.tmpExtent_ = ol.extent.createEmpty();
this.updateV13_();
+ this.setKey(this.getKeyForParams_());
};
goog.inherits(ol.source.TileWMS, ol.source.TileImage);
@@ -119055,8 +103315,7 @@ goog.inherits(ol.source.TileWMS, ol.source.TileImage);
* @return {string|undefined} GetFeatureInfo URL.
* @api stable
*/
-ol.source.TileWMS.prototype.getGetFeatureInfoUrl =
- function(coordinate, resolution, projection, params) {
+ol.source.TileWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resolution, projection, params) {
goog.asserts.assert(!('VERSION' in params),
'key VERSION is not allowed in params');
@@ -119095,7 +103354,7 @@ ol.source.TileWMS.prototype.getGetFeatureInfoUrl =
'TRANSPARENT': true,
'QUERY_LAYERS': this.params_['LAYERS']
};
- goog.object.extend(baseParams, this.params_, params);
+ ol.object.assign(baseParams, this.params_, params);
var x = Math.floor((coordinate[0] - tileExtent[0]) / tileResolution);
var y = Math.floor((tileExtent[3] - coordinate[1]) / tileResolution);
@@ -119111,7 +103370,7 @@ ol.source.TileWMS.prototype.getGetFeatureInfoUrl =
/**
* @inheritDoc
*/
-ol.source.TileWMS.prototype.getGutter = function() {
+ol.source.TileWMS.prototype.getGutterInternal = function() {
return this.gutter_;
};
@@ -119145,8 +103404,7 @@ ol.source.TileWMS.prototype.getParams = function() {
* @return {string|undefined} Request URL.
* @private
*/
-ol.source.TileWMS.prototype.getRequestUrl_ =
- function(tileCoord, tileSize, tileExtent,
+ol.source.TileWMS.prototype.getRequestUrl_ = function(tileCoord, tileSize, tileExtent,
pixelRatio, projection, params) {
var urls = this.urls;
@@ -119160,9 +103418,7 @@ ol.source.TileWMS.prototype.getRequestUrl_ =
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
if (!('STYLES' in this.params_)) {
- /* jshint -W053 */
- params['STYLES'] = new String('');
- /* jshint +W053 */
+ params['STYLES'] = '';
}
if (pixelRatio != 1) {
@@ -119205,7 +103461,7 @@ ol.source.TileWMS.prototype.getRequestUrl_ =
if (urls.length == 1) {
url = urls[0];
} else {
- var index = goog.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);
+ var index = ol.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);
url = urls[index];
}
return goog.uri.utils.appendParamsFromMap(url, params);
@@ -119213,19 +103469,10 @@ ol.source.TileWMS.prototype.getRequestUrl_ =
/**
- * @param {number} z Z.
- * @param {number} pixelRatio Pixel ratio.
- * @param {ol.proj.Projection} projection Projection.
- * @return {ol.Size} Size.
+ * @inheritDoc
*/
-ol.source.TileWMS.prototype.getTilePixelSize =
- function(z, pixelRatio, projection) {
- var tileSize = goog.base(this, 'getTilePixelSize', z, pixelRatio, projection);
- if (pixelRatio == 1 || !this.hidpi_ || this.serverType_ === undefined) {
- return tileSize;
- } else {
- return ol.size.scale(tileSize, pixelRatio, this.tmpSize);
- }
+ol.source.TileWMS.prototype.getTilePixelRatio = function(pixelRatio) {
+ return (!this.hidpi_ || this.serverType_ === undefined) ? 1 : pixelRatio;
};
@@ -119243,24 +103490,28 @@ ol.source.TileWMS.prototype.resetCoordKeyPrefix_ = function() {
}
}
- var key;
- for (key in this.params_) {
- res[i++] = key + '-' + this.params_[key];
- }
-
this.coordKeyPrefix_ = res.join('#');
};
/**
- * @param {ol.TileCoord} tileCoord Tile coordinate.
- * @param {number} pixelRatio Pixel ratio.
- * @param {ol.proj.Projection} projection Projection.
- * @return {string|undefined} Tile URL.
* @private
+ * @return {string} The key for the current params.
+ */
+ol.source.TileWMS.prototype.getKeyForParams_ = function() {
+ var i = 0;
+ var res = [];
+ for (var key in this.params_) {
+ res[i++] = key + '-' + this.params_[key];
+ }
+ return res.join('/');
+};
+
+
+/**
+ * @inheritDoc
*/
-ol.source.TileWMS.prototype.tileUrlFunction_ =
- function(tileCoord, pixelRatio, projection) {
+ol.source.TileWMS.prototype.fixedTileUrlFunction = function(tileCoord, pixelRatio, projection) {
var tileGrid = this.getTileGrid();
if (!tileGrid) {
@@ -119298,7 +103549,7 @@ ol.source.TileWMS.prototype.tileUrlFunction_ =
'FORMAT': 'image/png',
'TRANSPARENT': true
};
- goog.object.extend(baseParams, this.params_);
+ ol.object.assign(baseParams, this.params_);
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
pixelRatio, projection, baseParams);
@@ -119311,10 +103562,10 @@ ol.source.TileWMS.prototype.tileUrlFunction_ =
* @api stable
*/
ol.source.TileWMS.prototype.updateParams = function(params) {
- goog.object.extend(this.params_, params);
+ ol.object.assign(this.params_, params);
this.resetCoordKeyPrefix_();
this.updateV13_();
- this.changed();
+ this.setKey(this.getKeyForParams_());
};
@@ -119322,9 +103573,8 @@ ol.source.TileWMS.prototype.updateParams = function(params) {
* @private
*/
ol.source.TileWMS.prototype.updateV13_ = function() {
- var version =
- goog.object.get(this.params_, 'VERSION', ol.DEFAULT_WMS_VERSION);
- this.v13_ = goog.string.compareVersions(version, '1.3') >= 0;
+ var version = this.params_['VERSION'] || ol.DEFAULT_WMS_VERSION;
+ this.v13_ = ol.string.compareVersions(version, '1.3') >= 0;
};
goog.provide('ol.tilegrid.WMTS');
@@ -119334,7 +103584,6 @@ goog.require('ol.proj');
goog.require('ol.tilegrid.TileGrid');
-
/**
* @classdesc
* Set the grid pattern for sources accessing WMTS tiled-image servers.
@@ -119403,8 +103652,7 @@ ol.tilegrid.WMTS.prototype.getMatrixIds = function() {
* @return {ol.tilegrid.WMTS} WMTS tileGrid instance.
* @api
*/
-ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet =
- function(matrixSet, opt_extent) {
+ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet = function(matrixSet, opt_extent) {
/** @type {!Array.<number>} */
var resolutions = [];
@@ -119467,14 +103715,12 @@ ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet =
goog.provide('ol.source.WMTS');
goog.provide('ol.source.WMTSRequestEncoding');
-goog.require('goog.array');
goog.require('goog.asserts');
-goog.require('goog.object');
goog.require('goog.uri.utils');
goog.require('ol.TileUrlFunction');
-goog.require('ol.TileUrlFunctionType');
goog.require('ol.array');
goog.require('ol.extent');
+goog.require('ol.object');
goog.require('ol.proj');
goog.require('ol.source.TileImage');
goog.require('ol.tilegrid.WMTS');
@@ -119491,7 +103737,6 @@ ol.source.WMTSRequestEncoding = {
};
-
/**
* @classdesc
* Layer source for tile data from WMTS servers.
@@ -119527,13 +103772,6 @@ ol.source.WMTS = function(options) {
* @private
* @type {string}
*/
- this.dimensionsKey_ = '';
- this.resetDimensionsKey_();
-
- /**
- * @private
- * @type {string}
- */
this.layer_ = options.layer;
/**
@@ -119579,7 +103817,7 @@ ol.source.WMTS = function(options) {
};
if (requestEncoding == ol.source.WMTSRequestEncoding.KVP) {
- goog.object.extend(context, {
+ ol.object.assign(context, {
'Service': 'WMTS',
'Request': 'GetTile',
'Version': this.version_,
@@ -119621,7 +103859,7 @@ ol.source.WMTS = function(options) {
'TileCol': tileCoord[1],
'TileRow': -tileCoord[2] - 1
};
- goog.object.extend(localContext, dimensions);
+ ol.object.assign(localContext, dimensions);
var url = template;
if (requestEncoding == ol.source.WMTSRequestEncoding.KVP) {
url = goog.uri.utils.appendParamsFromMap(url, localContext);
@@ -119642,6 +103880,7 @@ ol.source.WMTS = function(options) {
goog.base(this, {
attributions: options.attributions,
+ cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
logo: options.logo,
projection: options.projection,
@@ -119655,6 +103894,8 @@ ol.source.WMTS = function(options) {
wrapX: options.wrapX !== undefined ? options.wrapX : false
});
+ this.setKey(this.getKeyForDimensions_());
+
};
goog.inherits(ol.source.WMTS, ol.source.TileImage);
@@ -119682,14 +103923,6 @@ ol.source.WMTS.prototype.getFormat = function() {
/**
- * @inheritDoc
- */
-ol.source.WMTS.prototype.getKeyParams = function() {
- return this.dimensionsKey_;
-};
-
-
-/**
* Return the layer of the WMTS source.
* @return {string} Layer.
* @api
@@ -119741,14 +103974,15 @@ ol.source.WMTS.prototype.getVersion = function() {
/**
* @private
+ * @return {string} The key for the current dimensions.
*/
-ol.source.WMTS.prototype.resetDimensionsKey_ = function() {
+ol.source.WMTS.prototype.getKeyForDimensions_ = function() {
var i = 0;
var res = [];
for (var key in this.dimensions_) {
res[i++] = key + '-' + this.dimensions_[key];
}
- this.dimensionsKey_ = res.join('/');
+ return res.join('/');
};
@@ -119758,9 +103992,8 @@ ol.source.WMTS.prototype.resetDimensionsKey_ = function() {
* @api
*/
ol.source.WMTS.prototype.updateDimensions = function(dimensions) {
- goog.object.extend(this.dimensions_, dimensions);
- this.resetDimensionsKey_();
- this.changed();
+ ol.object.assign(this.dimensions_, dimensions);
+ this.setKey(this.getKeyForDimensions_());
};
@@ -119794,7 +104027,7 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
'config "layer" must not be null');
var layers = wmtsCap['Contents']['Layer'];
- var l = goog.array.find(layers, function(elt, index, array) {
+ var l = ol.array.find(layers, function(elt, index, array) {
return elt['Identifier'] == config['layer'];
});
goog.asserts.assert(l, 'found a matching layer in Contents/Layer');
@@ -119805,9 +104038,9 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
var idx, matrixSet;
if (l['TileMatrixSetLink'].length > 1) {
if ('projection' in config) {
- idx = goog.array.findIndex(l['TileMatrixSetLink'],
+ idx = ol.array.findIndex(l['TileMatrixSetLink'],
function(elt, index, array) {
- var tileMatrixSet = goog.array.find(tileMatrixSets, function(el) {
+ var tileMatrixSet = ol.array.find(tileMatrixSets, function(el) {
return el['Identifier'] == elt['TileMatrixSet'];
});
return tileMatrixSet['SupportedCRS'].replace(
@@ -119815,7 +104048,7 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
) == config['projection'];
});
} else {
- idx = goog.array.findIndex(l['TileMatrixSetLink'],
+ idx = ol.array.findIndex(l['TileMatrixSetLink'],
function(elt, index, array) {
return elt['TileMatrixSet'] == config['matrixSet'];
});
@@ -119835,7 +104068,7 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
if ('format' in config) {
format = config['format'];
}
- idx = goog.array.findIndex(l['Style'], function(elt, index, array) {
+ idx = ol.array.findIndex(l['Style'], function(elt, index, array) {
if ('style' in config) {
return elt['Title'] == config['style'];
} else {
@@ -119864,7 +104097,7 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
}
var matrixSets = wmtsCap['Contents']['TileMatrixSet'];
- var matrixSetObj = goog.array.find(matrixSets, function(elt, index, array) {
+ var matrixSetObj = ol.array.find(matrixSets, function(elt, index, array) {
return elt['Identifier'] == matrixSet;
});
goog.asserts.assert(matrixSetObj,
@@ -119924,7 +104157,7 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
var gets = wmtsCap['OperationsMetadata']['GetTile']['DCP']['HTTP']['Get'];
for (var i = 0, ii = gets.length; i < ii; ++i) {
- var constraint = goog.array.find(gets[i]['Constraint'],
+ var constraint = ol.array.find(gets[i]['Constraint'],
function(elt, index, array) {
return elt['name'] == 'GetEncoding';
});
@@ -119957,7 +104190,6 @@ goog.provide('ol.source.Zoomify');
goog.require('goog.asserts');
goog.require('ol');
goog.require('ol.ImageTile');
-goog.require('ol.TileCoord');
goog.require('ol.TileState');
goog.require('ol.dom');
goog.require('ol.extent');
@@ -119975,7 +104207,6 @@ ol.source.ZoomifyTierSizeCalculation = {
};
-
/**
* @classdesc
* Layer source for tile data in Zoomify format.
@@ -120076,6 +104307,7 @@ ol.source.Zoomify = function(opt_options) {
goog.base(this, {
attributions: options.attributions,
+ cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
logo: options.logo,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
@@ -120088,7 +104320,6 @@ ol.source.Zoomify = function(opt_options) {
goog.inherits(ol.source.Zoomify, ol.source.TileImage);
-
/**
* @constructor
* @extends {ol.ImageTile}
@@ -120146,21 +104377,8 @@ goog.provide('ol.style.Atlas');
goog.provide('ol.style.AtlasManager');
goog.require('goog.asserts');
-goog.require('goog.functions');
-goog.require('goog.object');
goog.require('ol');
-
-
-/**
- * Provides information for an image inside an atlas manager.
- * `offsetX` and `offsetY` is the position of the image inside
- * the atlas image `image` and the position of the hit-detection image
- * inside the hit-detection atlas image `hitImage`.
- * @typedef {{offsetX: number, offsetY: number, image: HTMLCanvasElement,
- * hitImage: HTMLCanvasElement}}
- */
-ol.style.AtlasManagerInfo;
-
+goog.require('ol.dom');
/**
@@ -120314,8 +104532,7 @@ ol.style.AtlasManager.prototype.mergeInfos_ = function(info, hitInfo) {
* @return {?ol.style.AtlasManagerInfo} The position and atlas image for the
* entry, or `null` if the image is too big.
*/
-ol.style.AtlasManager.prototype.add =
- function(id, width, height,
+ol.style.AtlasManager.prototype.add = function(id, width, height,
renderCallback, opt_renderHitCallback, opt_this) {
if (width + this.space_ > this.maxSize_ ||
height + this.space_ > this.maxSize_) {
@@ -120333,7 +104550,7 @@ ol.style.AtlasManager.prototype.add =
// the hit-detection atlas, to make sure that the offset is the same for
// the original image and the hit-detection image.
var renderHitCallback = opt_renderHitCallback !== undefined ?
- opt_renderHitCallback : goog.functions.NULL;
+ opt_renderHitCallback : ol.nullFunction
/** @type {?ol.style.AtlasInfo} */
var hitInfo = this.add_(true,
@@ -120357,8 +104574,7 @@ ol.style.AtlasManager.prototype.add =
* @return {?ol.style.AtlasInfo} The position and atlas image for the entry,
* or `null` if the image is too big.
*/
-ol.style.AtlasManager.prototype.add_ =
- function(isHitAtlas, id, width, height,
+ol.style.AtlasManager.prototype.add_ = function(isHitAtlas, id, width, height,
renderCallback, opt_this) {
var atlases = (isHitAtlas) ? this.hitAtlases_ : this.atlases_;
var atlas, info, i, ii;
@@ -120389,16 +104605,6 @@ ol.style.AtlasManager.prototype.add_ =
/**
- * Provides information for an image inside an atlas.
- * `offsetX` and `offsetY` are the position of the image inside
- * the atlas image `image`.
- * @typedef {{offsetX: number, offsetY: number, image: HTMLCanvasElement}}
- */
-ol.style.AtlasInfo;
-
-
-
-/**
* This class facilitates the creation of image atlases.
*
* Images added to an atlas will be rendered onto a single
@@ -120425,7 +104631,7 @@ ol.style.Atlas = function(size, space) {
/**
* @private
- * @type {Array.<ol.style.Atlas.Block>}
+ * @type {Array.<ol.style.AtlasBlock>}
*/
this.emptyBlocks_ = [{x: 0, y: 0, width: size, height: size}];
@@ -120437,29 +104643,24 @@ ol.style.Atlas = function(size, space) {
/**
* @private
- * @type {HTMLCanvasElement}
+ * @type {CanvasRenderingContext2D}
*/
- this.canvas_ = /** @type {HTMLCanvasElement} */
- (document.createElement('CANVAS'));
- this.canvas_.width = size;
- this.canvas_.height = size;
+ this.context_ = ol.dom.createCanvasContext2D(size, size);
/**
* @private
- * @type {CanvasRenderingContext2D}
+ * @type {HTMLCanvasElement}
*/
- this.context_ = /** @type {CanvasRenderingContext2D} */
- (this.canvas_.getContext('2d'));
+ this.canvas_ = this.context_.canvas;
};
/**
* @param {string} id The identifier of the entry to check.
- * @return {?ol.style.AtlasInfo}
+ * @return {?ol.style.AtlasInfo} The atlas info.
*/
ol.style.Atlas.prototype.get = function(id) {
- return /** @type {?ol.style.AtlasInfo} */ (
- goog.object.get(this.entries_, id, null));
+ return this.entries_[id] || null;
};
@@ -120473,8 +104674,7 @@ ol.style.Atlas.prototype.get = function(id) {
* `renderCallback`.
* @return {?ol.style.AtlasInfo} The position and atlas image for the entry.
*/
-ol.style.Atlas.prototype.add =
- function(id, width, height, renderCallback, opt_this) {
+ol.style.Atlas.prototype.add = function(id, width, height, renderCallback, opt_this) {
var block, i, ii;
for (i = 0, ii = this.emptyBlocks_.length; i < ii; ++i) {
block = this.emptyBlocks_[i];
@@ -120507,18 +104707,17 @@ ol.style.Atlas.prototype.add =
/**
* @private
* @param {number} index The index of the block.
- * @param {ol.style.Atlas.Block} block The block to split.
+ * @param {ol.style.AtlasBlock} block The block to split.
* @param {number} width The width of the entry to insert.
* @param {number} height The height of the entry to insert.
*/
-ol.style.Atlas.prototype.split_ =
- function(index, block, width, height) {
+ol.style.Atlas.prototype.split_ = function(index, block, width, height) {
var deltaWidth = block.width - width;
var deltaHeight = block.height - height;
- /** @type {ol.style.Atlas.Block} */
+ /** @type {ol.style.AtlasBlock} */
var newBlock1;
- /** @type {ol.style.Atlas.Block} */
+ /** @type {ol.style.AtlasBlock} */
var newBlock2;
if (deltaWidth > deltaHeight) {
@@ -120567,11 +104766,10 @@ ol.style.Atlas.prototype.split_ =
* blocks (that are potentially smaller) are filled first.
* @private
* @param {number} index The index of the block to remove.
- * @param {ol.style.Atlas.Block} newBlock1 The 1st block to add.
- * @param {ol.style.Atlas.Block} newBlock2 The 2nd block to add.
+ * @param {ol.style.AtlasBlock} newBlock1 The 1st block to add.
+ * @param {ol.style.AtlasBlock} newBlock2 The 2nd block to add.
*/
-ol.style.Atlas.prototype.updateBlocks_ =
- function(index, newBlock1, newBlock2) {
+ol.style.Atlas.prototype.updateBlocks_ = function(index, newBlock1, newBlock2) {
var args = [index, 1];
if (newBlock1.width > 0 && newBlock1.height > 0) {
args.push(newBlock1);
@@ -120582,20 +104780,15 @@ ol.style.Atlas.prototype.updateBlocks_ =
this.emptyBlocks_.splice.apply(this.emptyBlocks_, args);
};
-
-/**
- * @typedef {{x: number, y: number, width: number, height: number}}
- */
-ol.style.Atlas.Block;
-
goog.provide('ol.style.RegularShape');
goog.require('goog.asserts');
goog.require('ol');
goog.require('ol.color');
+goog.require('ol.colorlike');
+goog.require('ol.dom');
goog.require('ol.has');
goog.require('ol.render.canvas');
-goog.require('ol.structs.IHasChecksum');
goog.require('ol.style.AtlasManager');
goog.require('ol.style.Fill');
goog.require('ol.style.Image');
@@ -120603,7 +104796,6 @@ goog.require('ol.style.ImageState');
goog.require('ol.style.Stroke');
-
/**
* @classdesc
* Set regular shape style for vector features. The resulting shape will be
@@ -120613,7 +104805,6 @@ goog.require('ol.style.Stroke');
* @constructor
* @param {olx.style.RegularShapeOptions} options Options.
* @extends {ol.style.Image}
- * @implements {ol.structs.IHasChecksum}
* @api
*/
ol.style.RegularShape = function(options) {
@@ -120716,9 +104907,15 @@ ol.style.RegularShape = function(options) {
var snapToPixel = options.snapToPixel !== undefined ?
options.snapToPixel : true;
+ /**
+ * @type {boolean}
+ */
+ var rotateWithView = options.rotateWithView !== undefined ?
+ options.rotateWithView : false;
+
goog.base(this, {
opacity: 1,
- rotateWithView: false,
+ rotateWithView: rotateWithView,
rotation: options.rotation !== undefined ? options.rotation : 0,
scale: 1,
snapToPixel: snapToPixel
@@ -120875,22 +105072,8 @@ ol.style.RegularShape.prototype.unlistenImageChange = ol.nullFunction;
/**
- * @typedef {{
- * strokeStyle: (string|undefined),
- * strokeWidth: number,
- * size: number,
- * lineCap: string,
- * lineDash: Array.<number>,
- * lineJoin: string,
- * miterLimit: number
- * }}
- */
-ol.style.RegularShape.RenderOptions;
-
-
-/**
* @private
- * @param {ol.style.AtlasManager|undefined} atlasManager
+ * @param {ol.style.AtlasManager|undefined} atlasManager An atlas manager.
*/
ol.style.RegularShape.prototype.render_ = function(atlasManager) {
var imageSize;
@@ -120927,7 +105110,7 @@ ol.style.RegularShape.prototype.render_ = function(atlasManager) {
var size = 2 * (this.radius_ + strokeWidth) + 1;
- /** @type {ol.style.RegularShape.RenderOptions} */
+ /** @type {ol.style.RegularShapeRenderOptions} */
var renderOptions = {
strokeStyle: strokeStyle,
strokeWidth: strokeWidth,
@@ -120940,18 +105123,13 @@ ol.style.RegularShape.prototype.render_ = function(atlasManager) {
if (atlasManager === undefined) {
// no atlas manager is used, create a new canvas
- this.canvas_ = /** @type {HTMLCanvasElement} */
- (document.createElement('CANVAS'));
-
- this.canvas_.height = size;
- this.canvas_.width = size;
+ var context = ol.dom.createCanvasContext2D(size, size);
+ this.canvas_ = context.canvas;
// canvas.width and height are rounded to the closest integer
size = this.canvas_.width;
imageSize = size;
- var context = /** @type {CanvasRenderingContext2D} */
- (this.canvas_.getContext('2d'));
this.draw_(renderOptions, context, 0, 0);
this.createHitDetectionCanvas_(renderOptions);
@@ -120964,12 +105142,12 @@ ol.style.RegularShape.prototype.render_ = function(atlasManager) {
if (hasCustomHitDetectionImage) {
// render the hit-detection image into a separate atlas image
renderHitDetectionCallback =
- goog.bind(this.drawHitDetectionCanvas_, this, renderOptions);
+ this.drawHitDetectionCanvas_.bind(this, renderOptions);
}
var id = this.getChecksum();
var info = atlasManager.add(
- id, size, size, goog.bind(this.draw_, this, renderOptions),
+ id, size, size, this.draw_.bind(this, renderOptions),
renderHitDetectionCallback);
goog.asserts.assert(info, 'shape size is too large');
@@ -120995,8 +105173,8 @@ ol.style.RegularShape.prototype.render_ = function(atlasManager) {
/**
* @private
- * @param {ol.style.RegularShape.RenderOptions} renderOptions
- * @param {CanvasRenderingContext2D} context
+ * @param {ol.style.RegularShapeRenderOptions} renderOptions Render options.
+ * @param {CanvasRenderingContext2D} context The rendering context.
* @param {number} x The origin for the symbol (x).
* @param {number} y The origin for the symbol (y).
*/
@@ -121020,7 +105198,7 @@ ol.style.RegularShape.prototype.draw_ = function(renderOptions, context, x, y) {
}
if (this.fill_) {
- context.fillStyle = ol.color.asString(this.fill_.getColor());
+ context.fillStyle = ol.colorlike.asColorLike(this.fill_.getColor());
context.fill();
}
if (this.stroke_) {
@@ -121040,10 +105218,9 @@ ol.style.RegularShape.prototype.draw_ = function(renderOptions, context, x, y) {
/**
* @private
- * @param {ol.style.RegularShape.RenderOptions} renderOptions
+ * @param {ol.style.RegularShapeRenderOptions} renderOptions Render options.
*/
-ol.style.RegularShape.prototype.createHitDetectionCanvas_ =
- function(renderOptions) {
+ol.style.RegularShape.prototype.createHitDetectionCanvas_ = function(renderOptions) {
this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];
if (this.fill_) {
this.hitDetectionCanvas_ = this.canvas_;
@@ -121052,28 +105229,21 @@ ol.style.RegularShape.prototype.createHitDetectionCanvas_ =
// if no fill style is set, create an extra hit-detection image with a
// default fill style
- this.hitDetectionCanvas_ = /** @type {HTMLCanvasElement} */
- (document.createElement('CANVAS'));
- var canvas = this.hitDetectionCanvas_;
-
- canvas.height = renderOptions.size;
- canvas.width = renderOptions.size;
+ var context = ol.dom.createCanvasContext2D(renderOptions.size, renderOptions.size);
+ this.hitDetectionCanvas_ = context.canvas;
- var context = /** @type {CanvasRenderingContext2D} */
- (canvas.getContext('2d'));
this.drawHitDetectionCanvas_(renderOptions, context, 0, 0);
};
/**
* @private
- * @param {ol.style.RegularShape.RenderOptions} renderOptions
- * @param {CanvasRenderingContext2D} context
+ * @param {ol.style.RegularShapeRenderOptions} renderOptions Render options.
+ * @param {CanvasRenderingContext2D} context The context.
* @param {number} x The origin for the symbol (x).
* @param {number} y The origin for the symbol (y).
*/
-ol.style.RegularShape.prototype.drawHitDetectionCanvas_ =
- function(renderOptions, context, x, y) {
+ol.style.RegularShape.prototype.drawHitDetectionCanvas_ = function(renderOptions, context, x, y) {
// reset transform
context.setTransform(1, 0, 0, 1, 0, 0);
@@ -121107,7 +105277,7 @@ ol.style.RegularShape.prototype.drawHitDetectionCanvas_ =
/**
- * @inheritDoc
+ * @return {string} The checksum.
*/
ol.style.RegularShape.prototype.getChecksum = function() {
var strokeChecksum = this.stroke_ ?
@@ -121153,10 +105323,34 @@ ol.style.RegularShape.prototype.getChecksum = function() {
//
// This file has been auto-generated by GenJsDeps, please do not edit.
-goog.addDependency('demos/editor/equationeditor.js', ['goog.demos.editor.EquationEditor'], ['goog.ui.equation.EquationEditorDialog']);
-goog.addDependency('demos/editor/helloworld.js', ['goog.demos.editor.HelloWorld'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin']);
-goog.addDependency('demos/editor/helloworlddialog.js', ['goog.demos.editor.HelloWorldDialog', 'goog.demos.editor.HelloWorldDialog.OkEvent'], ['goog.dom.TagName', 'goog.events.Event', 'goog.string', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType']);
-goog.addDependency('demos/editor/helloworlddialogplugin.js', ['goog.demos.editor.HelloWorldDialogPlugin', 'goog.demos.editor.HelloWorldDialogPlugin.Command'], ['goog.demos.editor.HelloWorldDialog', 'goog.dom.TagName', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range', 'goog.functions', 'goog.ui.editor.AbstractDialog.EventType']);
+goog.addDependency(
+ 'demos/editor/equationeditor.js', ['goog.demos.editor.EquationEditor'],
+ ['goog.ui.equation.EquationEditorDialog']);
+goog.addDependency(
+ 'demos/editor/helloworld.js', ['goog.demos.editor.HelloWorld'],
+ ['goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin']);
+goog.addDependency(
+ 'demos/editor/helloworlddialog.js',
+ [
+ 'goog.demos.editor.HelloWorldDialog',
+ 'goog.demos.editor.HelloWorldDialog.OkEvent'
+ ],
+ [
+ 'goog.dom.TagName', 'goog.events.Event', 'goog.string',
+ 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder',
+ 'goog.ui.editor.AbstractDialog.EventType'
+ ]);
+goog.addDependency(
+ 'demos/editor/helloworlddialogplugin.js',
+ [
+ 'goog.demos.editor.HelloWorldDialogPlugin',
+ 'goog.demos.editor.HelloWorldDialogPlugin.Command'
+ ],
+ [
+ 'goog.demos.editor.HelloWorldDialog', 'goog.dom.TagName',
+ 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range',
+ 'goog.functions', 'goog.ui.editor.AbstractDialog.EventType'
+ ]);
/**
* @fileoverview Custom exports file.
@@ -121168,24 +105362,16 @@ goog.require('ol.Attribution');
goog.require('ol.Collection');
goog.require('ol.CollectionEvent');
goog.require('ol.CollectionEventType');
-goog.require('ol.Color');
-goog.require('ol.Coordinate');
-goog.require('ol.CoordinateFormatType');
goog.require('ol.DeviceOrientation');
goog.require('ol.DeviceOrientationProperty');
goog.require('ol.DragBoxEvent');
-goog.require('ol.Extent');
goog.require('ol.Feature');
-goog.require('ol.FeatureLoader');
-goog.require('ol.FeatureStyleFunction');
-goog.require('ol.FeatureUrlFunction');
goog.require('ol.Geolocation');
goog.require('ol.GeolocationProperty');
goog.require('ol.Graticule');
goog.require('ol.Image');
goog.require('ol.ImageTile');
goog.require('ol.Kinetic');
-goog.require('ol.LoadingStrategy');
goog.require('ol.Map');
goog.require('ol.MapBrowserEvent');
goog.require('ol.MapBrowserEvent.EventType');
@@ -121201,7 +105387,6 @@ goog.require('ol.Observable');
goog.require('ol.Overlay');
goog.require('ol.OverlayPositioning');
goog.require('ol.OverlayProperty');
-goog.require('ol.Size');
goog.require('ol.Sphere');
goog.require('ol.Tile');
goog.require('ol.TileState');
@@ -121211,6 +105396,7 @@ goog.require('ol.ViewHint');
goog.require('ol.ViewProperty');
goog.require('ol.animation');
goog.require('ol.color');
+goog.require('ol.colorlike');
goog.require('ol.control');
goog.require('ol.control.Attribution');
goog.require('ol.control.Control');
@@ -121226,7 +105412,7 @@ goog.require('ol.control.ZoomSlider');
goog.require('ol.control.ZoomToExtent');
goog.require('ol.coordinate');
goog.require('ol.easing');
-goog.require('ol.events.ConditionType');
+goog.require('ol.events.Event');
goog.require('ol.events.condition');
goog.require('ol.extent');
goog.require('ol.extent.Corner');
@@ -121252,6 +105438,25 @@ goog.require('ol.format.WKT');
goog.require('ol.format.WMSCapabilities');
goog.require('ol.format.WMSGetFeatureInfo');
goog.require('ol.format.WMTSCapabilities');
+goog.require('ol.format.ogc.filter');
+goog.require('ol.format.ogc.filter.And');
+goog.require('ol.format.ogc.filter.Bbox');
+goog.require('ol.format.ogc.filter.Comparison');
+goog.require('ol.format.ogc.filter.ComparisonBinary');
+goog.require('ol.format.ogc.filter.EqualTo');
+goog.require('ol.format.ogc.filter.Filter');
+goog.require('ol.format.ogc.filter.GreaterThan');
+goog.require('ol.format.ogc.filter.GreaterThanOrEqualTo');
+goog.require('ol.format.ogc.filter.IsBetween');
+goog.require('ol.format.ogc.filter.IsLike');
+goog.require('ol.format.ogc.filter.IsNull');
+goog.require('ol.format.ogc.filter.LessThan');
+goog.require('ol.format.ogc.filter.LessThanOrEqualTo');
+goog.require('ol.format.ogc.filter.Logical');
+goog.require('ol.format.ogc.filter.LogicalBinary');
+goog.require('ol.format.ogc.filter.Not');
+goog.require('ol.format.ogc.filter.NotEqualTo');
+goog.require('ol.format.ogc.filter.Or');
goog.require('ol.geom.Circle');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryCollection');
@@ -121278,7 +105483,6 @@ goog.require('ol.interaction.DragZoom');
goog.require('ol.interaction.Draw');
goog.require('ol.interaction.DrawEvent');
goog.require('ol.interaction.DrawEventType');
-goog.require('ol.interaction.DrawGeometryFunctionType');
goog.require('ol.interaction.DrawMode');
goog.require('ol.interaction.Interaction');
goog.require('ol.interaction.InteractionProperty');
@@ -121293,7 +105497,6 @@ goog.require('ol.interaction.Pointer');
goog.require('ol.interaction.Select');
goog.require('ol.interaction.SelectEvent');
goog.require('ol.interaction.SelectEventType');
-goog.require('ol.interaction.SelectFilterFunction');
goog.require('ol.interaction.Snap');
goog.require('ol.interaction.SnapProperty');
goog.require('ol.interaction.Translate');
@@ -121304,7 +105507,6 @@ goog.require('ol.layer.Heatmap');
goog.require('ol.layer.Image');
goog.require('ol.layer.Layer');
goog.require('ol.layer.LayerProperty');
-goog.require('ol.layer.LayerState');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.layer.VectorTile');
@@ -121312,7 +105514,6 @@ goog.require('ol.loadingstrategy');
goog.require('ol.proj');
goog.require('ol.proj.METERS_PER_UNIT');
goog.require('ol.proj.Projection');
-goog.require('ol.proj.ProjectionLike');
goog.require('ol.proj.Units');
goog.require('ol.proj.common');
goog.require('ol.render');
@@ -121324,8 +105525,10 @@ goog.require('ol.render.canvas.Immediate');
goog.require('ol.render.webgl.Immediate');
goog.require('ol.size');
goog.require('ol.source.BingMaps');
+goog.require('ol.source.CartoDB');
goog.require('ol.source.Cluster');
goog.require('ol.source.Image');
+goog.require('ol.source.ImageArcGISRest');
goog.require('ol.source.ImageCanvas');
goog.require('ol.source.ImageEvent');
goog.require('ol.source.ImageMapGuide');
@@ -121346,7 +105549,6 @@ goog.require('ol.source.TileDebug');
goog.require('ol.source.TileEvent');
goog.require('ol.source.TileImage');
goog.require('ol.source.TileJSON');
-goog.require('ol.source.TileOptions');
goog.require('ol.source.TileUTFGrid');
goog.require('ol.source.TileWMS');
goog.require('ol.source.UrlTile');
@@ -121362,7 +105564,6 @@ goog.require('ol.style.Atlas');
goog.require('ol.style.AtlasManager');
goog.require('ol.style.Circle');
goog.require('ol.style.Fill');
-goog.require('ol.style.GeometryFunction');
goog.require('ol.style.Icon');
goog.require('ol.style.IconAnchorUnits');
goog.require('ol.style.IconImageCache');
@@ -121372,7 +105573,6 @@ goog.require('ol.style.ImageState');
goog.require('ol.style.RegularShape');
goog.require('ol.style.Stroke');
goog.require('ol.style.Style');
-goog.require('ol.style.StyleFunction');
goog.require('ol.style.Text');
goog.require('ol.style.defaultGeometryFunction');
goog.require('ol.tilegrid.TileGrid');
@@ -121483,6 +105683,11 @@ goog.exportProperty(
ol.Collection.prototype.setAt);
goog.exportSymbol(
+ 'ol.colorlike.asColorLike',
+ ol.colorlike.asColorLike,
+ OPENLAYERS);
+
+goog.exportSymbol(
'ol.coordinate.add',
ol.coordinate.add,
OPENLAYERS);
@@ -122088,16 +106293,6 @@ goog.exportProperty(
ol.MapBrowserEvent.prototype.dragging);
goog.exportProperty(
- ol.MapBrowserEvent.prototype,
- 'preventDefault',
- ol.MapBrowserEvent.prototype.preventDefault);
-
-goog.exportProperty(
- ol.MapBrowserEvent.prototype,
- 'stopPropagation',
- ol.MapBrowserEvent.prototype.stopPropagation);
-
-goog.exportProperty(
ol.MapEvent.prototype,
'map',
ol.MapEvent.prototype.map);
@@ -122284,6 +106479,16 @@ goog.exportProperty(
goog.exportProperty(
ol.VectorTile.prototype,
+ 'setFeatures',
+ ol.VectorTile.prototype.setFeatures);
+
+goog.exportProperty(
+ ol.VectorTile.prototype,
+ 'setProjection',
+ ol.VectorTile.prototype.setProjection);
+
+goog.exportProperty(
+ ol.VectorTile.prototype,
'setLoader',
ol.VectorTile.prototype.setLoader);
@@ -122329,6 +106534,11 @@ goog.exportProperty(
goog.exportProperty(
ol.View.prototype,
+ 'getResolutions',
+ ol.View.prototype.getResolutions);
+
+goog.exportProperty(
+ ol.View.prototype,
'getRotation',
ol.View.prototype.getRotation);
@@ -122888,6 +107098,26 @@ goog.exportSymbol(
OPENLAYERS);
goog.exportSymbol(
+ 'ol.source.CartoDB',
+ ol.source.CartoDB,
+ OPENLAYERS);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getConfig',
+ ol.source.CartoDB.prototype.getConfig);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'updateConfig',
+ ol.source.CartoDB.prototype.updateConfig);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setConfig',
+ ol.source.CartoDB.prototype.setConfig);
+
+goog.exportSymbol(
'ol.source.Cluster',
ol.source.Cluster,
OPENLAYERS);
@@ -122898,6 +107128,41 @@ goog.exportProperty(
ol.source.Cluster.prototype.getSource);
goog.exportSymbol(
+ 'ol.source.ImageArcGISRest',
+ ol.source.ImageArcGISRest,
+ OPENLAYERS);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getParams',
+ ol.source.ImageArcGISRest.prototype.getParams);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getImageLoadFunction',
+ ol.source.ImageArcGISRest.prototype.getImageLoadFunction);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getUrl',
+ ol.source.ImageArcGISRest.prototype.getUrl);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'setImageLoadFunction',
+ ol.source.ImageArcGISRest.prototype.setImageLoadFunction);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'setUrl',
+ ol.source.ImageArcGISRest.prototype.setUrl);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'updateParams',
+ ol.source.ImageArcGISRest.prototype.updateParams);
+
+goog.exportSymbol(
'ol.source.ImageCanvas',
ol.source.ImageCanvas,
OPENLAYERS);
@@ -123079,6 +107344,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Source.prototype,
+ 'refresh',
+ ol.source.Source.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.Source.prototype,
'setAttributions',
ol.source.Source.prototype.setAttributions);
@@ -123127,6 +107397,11 @@ goog.exportSymbol(
ol.source.TileJSON,
OPENLAYERS);
+goog.exportProperty(
+ ol.source.TileJSON.prototype,
+ 'getTileJSON',
+ ol.source.TileJSON.prototype.getTileJSON);
+
goog.exportSymbol(
'ol.source.Tile',
ol.source.Tile,
@@ -123284,6 +107559,16 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Vector.prototype,
+ 'getFormat',
+ ol.source.Vector.prototype.getFormat);
+
+goog.exportProperty(
+ ol.source.Vector.prototype,
+ 'getUrl',
+ ol.source.Vector.prototype.getUrl);
+
+goog.exportProperty(
+ ol.source.Vector.prototype,
'removeFeature',
ol.source.Vector.prototype.removeFeature);
@@ -123409,13 +107694,13 @@ goog.exportSymbol(
goog.exportProperty(
ol.render.webgl.Immediate.prototype,
- 'drawAsync',
- ol.render.webgl.Immediate.prototype.drawAsync);
+ 'setStyle',
+ ol.render.webgl.Immediate.prototype.setStyle);
goog.exportProperty(
ol.render.webgl.Immediate.prototype,
- 'drawCircleGeometry',
- ol.render.webgl.Immediate.prototype.drawCircleGeometry);
+ 'drawGeometry',
+ ol.render.webgl.Immediate.prototype.drawGeometry);
goog.exportProperty(
ol.render.webgl.Immediate.prototype,
@@ -123423,120 +107708,25 @@ goog.exportProperty(
ol.render.webgl.Immediate.prototype.drawFeature);
goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'drawGeometryCollectionGeometry',
- ol.render.webgl.Immediate.prototype.drawGeometryCollectionGeometry);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'drawPointGeometry',
- ol.render.webgl.Immediate.prototype.drawPointGeometry);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'drawLineStringGeometry',
- ol.render.webgl.Immediate.prototype.drawLineStringGeometry);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'drawMultiLineStringGeometry',
- ol.render.webgl.Immediate.prototype.drawMultiLineStringGeometry);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'drawMultiPointGeometry',
- ol.render.webgl.Immediate.prototype.drawMultiPointGeometry);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'drawMultiPolygonGeometry',
- ol.render.webgl.Immediate.prototype.drawMultiPolygonGeometry);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'drawPolygonGeometry',
- ol.render.webgl.Immediate.prototype.drawPolygonGeometry);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'drawText',
- ol.render.webgl.Immediate.prototype.drawText);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'setFillStrokeStyle',
- ol.render.webgl.Immediate.prototype.setFillStrokeStyle);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'setImageStyle',
- ol.render.webgl.Immediate.prototype.setImageStyle);
-
-goog.exportProperty(
- ol.render.webgl.Immediate.prototype,
- 'setTextStyle',
- ol.render.webgl.Immediate.prototype.setTextStyle);
+ ol.render.canvas.Immediate.prototype,
+ 'drawCircle',
+ ol.render.canvas.Immediate.prototype.drawCircle);
goog.exportProperty(
ol.render.canvas.Immediate.prototype,
- 'drawAsync',
- ol.render.canvas.Immediate.prototype.drawAsync);
+ 'setStyle',
+ ol.render.canvas.Immediate.prototype.setStyle);
goog.exportProperty(
ol.render.canvas.Immediate.prototype,
- 'drawCircleGeometry',
- ol.render.canvas.Immediate.prototype.drawCircleGeometry);
+ 'drawGeometry',
+ ol.render.canvas.Immediate.prototype.drawGeometry);
goog.exportProperty(
ol.render.canvas.Immediate.prototype,
'drawFeature',
ol.render.canvas.Immediate.prototype.drawFeature);
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'drawPointGeometry',
- ol.render.canvas.Immediate.prototype.drawPointGeometry);
-
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'drawMultiPointGeometry',
- ol.render.canvas.Immediate.prototype.drawMultiPointGeometry);
-
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'drawLineStringGeometry',
- ol.render.canvas.Immediate.prototype.drawLineStringGeometry);
-
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'drawMultiLineStringGeometry',
- ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry);
-
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'drawPolygonGeometry',
- ol.render.canvas.Immediate.prototype.drawPolygonGeometry);
-
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'drawMultiPolygonGeometry',
- ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry);
-
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'setFillStrokeStyle',
- ol.render.canvas.Immediate.prototype.setFillStrokeStyle);
-
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'setImageStyle',
- ol.render.canvas.Immediate.prototype.setImageStyle);
-
-goog.exportProperty(
- ol.render.canvas.Immediate.prototype,
- 'setTextStyle',
- ol.render.canvas.Immediate.prototype.setTextStyle);
-
goog.exportSymbol(
'ol.proj.common.add',
ol.proj.common.add,
@@ -123608,6 +107798,11 @@ goog.exportProperty(
ol.proj.Projection.prototype.getPointResolution);
goog.exportSymbol(
+ 'ol.proj.setProj4',
+ ol.proj.setProj4,
+ OPENLAYERS);
+
+goog.exportSymbol(
'ol.proj.addEquivalentProjections',
ol.proj.addEquivalentProjections,
OPENLAYERS);
@@ -123638,6 +107833,11 @@ goog.exportSymbol(
OPENLAYERS);
goog.exportSymbol(
+ 'ol.proj.equivalent',
+ ol.proj.equivalent,
+ OPENLAYERS);
+
+goog.exportSymbol(
'ol.proj.getTransform',
ol.proj.getTransform,
OPENLAYERS);
@@ -123864,11 +108064,6 @@ goog.exportProperty(
goog.exportProperty(
ol.layer.VectorTile.prototype,
- 'getSource',
- ol.layer.VectorTile.prototype.getSource);
-
-goog.exportProperty(
- ol.layer.VectorTile.prototype,
'getUseInterimTilesOnError',
ol.layer.VectorTile.prototype.getUseInterimTilesOnError);
@@ -123922,6 +108117,11 @@ goog.exportProperty(
'coordinate',
ol.DragBoxEvent.prototype.coordinate);
+goog.exportProperty(
+ ol.DragBoxEvent.prototype,
+ 'mapBrowserEvent',
+ ol.DragBoxEvent.prototype.mapBrowserEvent);
+
goog.exportSymbol(
'ol.interaction.DragBox',
ol.interaction.DragBox,
@@ -124052,6 +108252,11 @@ goog.exportSymbol(
ol.interaction.Modify.handleEvent,
OPENLAYERS);
+goog.exportProperty(
+ ol.interaction.Modify.prototype,
+ 'removePoint',
+ ol.interaction.Modify.prototype.removePoint);
+
goog.exportSymbol(
'ol.interaction.MouseWheelZoom',
ol.interaction.MouseWheelZoom,
@@ -124224,6 +108429,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.Geometry.prototype,
+ 'rotate',
+ ol.geom.Geometry.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.Geometry.prototype,
'simplify',
ol.geom.Geometry.prototype.simplify);
@@ -124334,6 +108544,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.LineString.prototype,
+ 'getCoordinateAt',
+ ol.geom.LineString.prototype.getCoordinateAt);
+
+goog.exportProperty(
+ ol.geom.LineString.prototype,
'getLength',
ol.geom.LineString.prototype.getLength);
@@ -124849,6 +109064,16 @@ goog.exportSymbol(
goog.exportProperty(
ol.format.MVT.prototype,
+ 'readFeatures',
+ ol.format.MVT.prototype.readFeatures);
+
+goog.exportProperty(
+ ol.format.MVT.prototype,
+ 'readProjection',
+ ol.format.MVT.prototype.readProjection);
+
+goog.exportProperty(
+ ol.format.MVT.prototype,
'setLayers',
ol.format.MVT.prototype.setLayers);
@@ -125033,6 +109258,151 @@ goog.exportProperty(
ol.format.WMTSCapabilities.prototype.read);
goog.exportSymbol(
+ 'ol.format.ogc.filter.and',
+ ol.format.ogc.filter.and,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.or',
+ ol.format.ogc.filter.or,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.not',
+ ol.format.ogc.filter.not,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.bbox',
+ ol.format.ogc.filter.bbox,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.equalTo',
+ ol.format.ogc.filter.equalTo,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.notEqualTo',
+ ol.format.ogc.filter.notEqualTo,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.lessThan',
+ ol.format.ogc.filter.lessThan,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.lessThanOrEqualTo',
+ ol.format.ogc.filter.lessThanOrEqualTo,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.greaterThan',
+ ol.format.ogc.filter.greaterThan,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.greaterThanOrEqualTo',
+ ol.format.ogc.filter.greaterThanOrEqualTo,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.isNull',
+ ol.format.ogc.filter.isNull,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.between',
+ ol.format.ogc.filter.between,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.like',
+ ol.format.ogc.filter.like,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.Filter',
+ ol.format.ogc.filter.Filter,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.And',
+ ol.format.ogc.filter.And,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.Or',
+ ol.format.ogc.filter.Or,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.Not',
+ ol.format.ogc.filter.Not,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.Bbox',
+ ol.format.ogc.filter.Bbox,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.Comparison',
+ ol.format.ogc.filter.Comparison,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.ComparisonBinary',
+ ol.format.ogc.filter.ComparisonBinary,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.EqualTo',
+ ol.format.ogc.filter.EqualTo,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.NotEqualTo',
+ ol.format.ogc.filter.NotEqualTo,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.LessThan',
+ ol.format.ogc.filter.LessThan,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.LessThanOrEqualTo',
+ ol.format.ogc.filter.LessThanOrEqualTo,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.GreaterThan',
+ ol.format.ogc.filter.GreaterThan,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.GreaterThanOrEqualTo',
+ ol.format.ogc.filter.GreaterThanOrEqualTo,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.IsNull',
+ ol.format.ogc.filter.IsNull,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.IsBetween',
+ ol.format.ogc.filter.IsBetween,
+ OPENLAYERS);
+
+goog.exportSymbol(
+ 'ol.format.ogc.filter.IsLike',
+ ol.format.ogc.filter.IsLike,
+ OPENLAYERS);
+
+goog.exportSymbol(
'ol.format.GML2',
ol.format.GML2,
OPENLAYERS);
@@ -125143,6 +109513,31 @@ goog.exportSymbol(
OPENLAYERS);
goog.exportSymbol(
+ 'ol.events.condition.primaryAction',
+ ol.events.condition.primaryAction,
+ OPENLAYERS);
+
+goog.exportProperty(
+ ol.events.Event.prototype,
+ 'type',
+ ol.events.Event.prototype.type);
+
+goog.exportProperty(
+ ol.events.Event.prototype,
+ 'target',
+ ol.events.Event.prototype.target);
+
+goog.exportProperty(
+ ol.events.Event.prototype,
+ 'preventDefault',
+ ol.events.Event.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.events.Event.prototype,
+ 'stopPropagation',
+ ol.events.Event.prototype.stopPropagation);
+
+goog.exportSymbol(
'ol.control.Attribution',
ol.control.Attribution,
OPENLAYERS);
@@ -125328,6 +109723,26 @@ goog.exportSymbol(
OPENLAYERS);
goog.exportProperty(
+ ol.CollectionEvent.prototype,
+ 'type',
+ ol.CollectionEvent.prototype.type);
+
+goog.exportProperty(
+ ol.CollectionEvent.prototype,
+ 'target',
+ ol.CollectionEvent.prototype.target);
+
+goog.exportProperty(
+ ol.CollectionEvent.prototype,
+ 'preventDefault',
+ ol.CollectionEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.CollectionEvent.prototype,
+ 'stopPropagation',
+ ol.CollectionEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.Object.prototype,
'changed',
ol.Object.prototype.changed);
@@ -125693,6 +110108,26 @@ goog.exportProperty(
ol.Map.prototype.unByKey);
goog.exportProperty(
+ ol.MapEvent.prototype,
+ 'type',
+ ol.MapEvent.prototype.type);
+
+goog.exportProperty(
+ ol.MapEvent.prototype,
+ 'target',
+ ol.MapEvent.prototype.target);
+
+goog.exportProperty(
+ ol.MapEvent.prototype,
+ 'preventDefault',
+ ol.MapEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.MapEvent.prototype,
+ 'stopPropagation',
+ ol.MapEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.MapBrowserEvent.prototype,
'map',
ol.MapBrowserEvent.prototype.map);
@@ -125703,6 +110138,26 @@ goog.exportProperty(
ol.MapBrowserEvent.prototype.frameState);
goog.exportProperty(
+ ol.MapBrowserEvent.prototype,
+ 'type',
+ ol.MapBrowserEvent.prototype.type);
+
+goog.exportProperty(
+ ol.MapBrowserEvent.prototype,
+ 'target',
+ ol.MapBrowserEvent.prototype.target);
+
+goog.exportProperty(
+ ol.MapBrowserEvent.prototype,
+ 'preventDefault',
+ ol.MapBrowserEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.MapBrowserEvent.prototype,
+ 'stopPropagation',
+ ol.MapBrowserEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.MapBrowserPointerEvent.prototype,
'originalEvent',
ol.MapBrowserPointerEvent.prototype.originalEvent);
@@ -125743,6 +110198,36 @@ goog.exportProperty(
ol.MapBrowserPointerEvent.prototype.frameState);
goog.exportProperty(
+ ol.MapBrowserPointerEvent.prototype,
+ 'type',
+ ol.MapBrowserPointerEvent.prototype.type);
+
+goog.exportProperty(
+ ol.MapBrowserPointerEvent.prototype,
+ 'target',
+ ol.MapBrowserPointerEvent.prototype.target);
+
+goog.exportProperty(
+ ol.ObjectEvent.prototype,
+ 'type',
+ ol.ObjectEvent.prototype.type);
+
+goog.exportProperty(
+ ol.ObjectEvent.prototype,
+ 'target',
+ ol.ObjectEvent.prototype.target);
+
+goog.exportProperty(
+ ol.ObjectEvent.prototype,
+ 'preventDefault',
+ ol.ObjectEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.ObjectEvent.prototype,
+ 'stopPropagation',
+ ol.ObjectEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.Overlay.prototype,
'get',
ol.Overlay.prototype.get);
@@ -126129,6 +110614,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Tile.prototype,
+ 'refresh',
+ ol.source.Tile.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.Tile.prototype,
'setAttributions',
ol.source.Tile.prototype.setAttributions);
@@ -126204,6 +110694,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.UrlTile.prototype,
+ 'refresh',
+ ol.source.UrlTile.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.UrlTile.prototype,
'getAttributions',
ol.source.UrlTile.prototype.getAttributions);
@@ -126334,6 +110829,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.TileImage.prototype,
+ 'refresh',
+ ol.source.TileImage.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.TileImage.prototype,
'getAttributions',
ol.source.TileImage.prototype.getAttributions);
@@ -126474,6 +110974,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.BingMaps.prototype,
+ 'refresh',
+ ol.source.BingMaps.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.BingMaps.prototype,
'getAttributions',
ol.source.BingMaps.prototype.getAttributions);
@@ -126563,6 +111068,296 @@ goog.exportProperty(
ol.source.BingMaps.prototype.unByKey);
goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'setRenderReprojectionEdges',
+ ol.source.XYZ.prototype.setRenderReprojectionEdges);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'setTileGridForProjection',
+ ol.source.XYZ.prototype.setTileGridForProjection);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getTileLoadFunction',
+ ol.source.XYZ.prototype.getTileLoadFunction);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getTileUrlFunction',
+ ol.source.XYZ.prototype.getTileUrlFunction);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getUrls',
+ ol.source.XYZ.prototype.getUrls);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'setTileLoadFunction',
+ ol.source.XYZ.prototype.setTileLoadFunction);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'setTileUrlFunction',
+ ol.source.XYZ.prototype.setTileUrlFunction);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'setUrl',
+ ol.source.XYZ.prototype.setUrl);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'setUrls',
+ ol.source.XYZ.prototype.setUrls);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getTileGrid',
+ ol.source.XYZ.prototype.getTileGrid);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'refresh',
+ ol.source.XYZ.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getAttributions',
+ ol.source.XYZ.prototype.getAttributions);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getLogo',
+ ol.source.XYZ.prototype.getLogo);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getProjection',
+ ol.source.XYZ.prototype.getProjection);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getState',
+ ol.source.XYZ.prototype.getState);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'setAttributions',
+ ol.source.XYZ.prototype.setAttributions);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'get',
+ ol.source.XYZ.prototype.get);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getKeys',
+ ol.source.XYZ.prototype.getKeys);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getProperties',
+ ol.source.XYZ.prototype.getProperties);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'set',
+ ol.source.XYZ.prototype.set);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'setProperties',
+ ol.source.XYZ.prototype.setProperties);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'unset',
+ ol.source.XYZ.prototype.unset);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'changed',
+ ol.source.XYZ.prototype.changed);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'dispatchEvent',
+ ol.source.XYZ.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'getRevision',
+ ol.source.XYZ.prototype.getRevision);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'on',
+ ol.source.XYZ.prototype.on);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'once',
+ ol.source.XYZ.prototype.once);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'un',
+ ol.source.XYZ.prototype.un);
+
+goog.exportProperty(
+ ol.source.XYZ.prototype,
+ 'unByKey',
+ ol.source.XYZ.prototype.unByKey);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setRenderReprojectionEdges',
+ ol.source.CartoDB.prototype.setRenderReprojectionEdges);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setTileGridForProjection',
+ ol.source.CartoDB.prototype.setTileGridForProjection);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getTileLoadFunction',
+ ol.source.CartoDB.prototype.getTileLoadFunction);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getTileUrlFunction',
+ ol.source.CartoDB.prototype.getTileUrlFunction);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getUrls',
+ ol.source.CartoDB.prototype.getUrls);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setTileLoadFunction',
+ ol.source.CartoDB.prototype.setTileLoadFunction);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setTileUrlFunction',
+ ol.source.CartoDB.prototype.setTileUrlFunction);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setUrl',
+ ol.source.CartoDB.prototype.setUrl);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setUrls',
+ ol.source.CartoDB.prototype.setUrls);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getTileGrid',
+ ol.source.CartoDB.prototype.getTileGrid);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'refresh',
+ ol.source.CartoDB.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getAttributions',
+ ol.source.CartoDB.prototype.getAttributions);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getLogo',
+ ol.source.CartoDB.prototype.getLogo);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getProjection',
+ ol.source.CartoDB.prototype.getProjection);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getState',
+ ol.source.CartoDB.prototype.getState);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setAttributions',
+ ol.source.CartoDB.prototype.setAttributions);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'get',
+ ol.source.CartoDB.prototype.get);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getKeys',
+ ol.source.CartoDB.prototype.getKeys);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getProperties',
+ ol.source.CartoDB.prototype.getProperties);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'set',
+ ol.source.CartoDB.prototype.set);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'setProperties',
+ ol.source.CartoDB.prototype.setProperties);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'unset',
+ ol.source.CartoDB.prototype.unset);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'changed',
+ ol.source.CartoDB.prototype.changed);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'dispatchEvent',
+ ol.source.CartoDB.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'getRevision',
+ ol.source.CartoDB.prototype.getRevision);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'on',
+ ol.source.CartoDB.prototype.on);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'once',
+ ol.source.CartoDB.prototype.once);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'un',
+ ol.source.CartoDB.prototype.un);
+
+goog.exportProperty(
+ ol.source.CartoDB.prototype,
+ 'unByKey',
+ ol.source.CartoDB.prototype.unByKey);
+
+goog.exportProperty(
ol.source.Vector.prototype,
'getAttributions',
ol.source.Vector.prototype.getAttributions);
@@ -126584,6 +111379,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Vector.prototype,
+ 'refresh',
+ ol.source.Vector.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.Vector.prototype,
'setAttributions',
ol.source.Vector.prototype.setAttributions);
@@ -126719,6 +111519,16 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Cluster.prototype,
+ 'getFormat',
+ ol.source.Cluster.prototype.getFormat);
+
+goog.exportProperty(
+ ol.source.Cluster.prototype,
+ 'getUrl',
+ ol.source.Cluster.prototype.getUrl);
+
+goog.exportProperty(
+ ol.source.Cluster.prototype,
'removeFeature',
ol.source.Cluster.prototype.removeFeature);
@@ -126744,6 +111554,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Cluster.prototype,
+ 'refresh',
+ ol.source.Cluster.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.Cluster.prototype,
'setAttributions',
ol.source.Cluster.prototype.setAttributions);
@@ -126834,6 +111649,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Image.prototype,
+ 'refresh',
+ ol.source.Image.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.Image.prototype,
'setAttributions',
ol.source.Image.prototype.setAttributions);
@@ -126903,6 +111723,101 @@ goog.exportProperty(
ol.source.Image.prototype.unByKey);
goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getAttributions',
+ ol.source.ImageArcGISRest.prototype.getAttributions);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getLogo',
+ ol.source.ImageArcGISRest.prototype.getLogo);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getProjection',
+ ol.source.ImageArcGISRest.prototype.getProjection);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getState',
+ ol.source.ImageArcGISRest.prototype.getState);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'refresh',
+ ol.source.ImageArcGISRest.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'setAttributions',
+ ol.source.ImageArcGISRest.prototype.setAttributions);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'get',
+ ol.source.ImageArcGISRest.prototype.get);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getKeys',
+ ol.source.ImageArcGISRest.prototype.getKeys);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getProperties',
+ ol.source.ImageArcGISRest.prototype.getProperties);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'set',
+ ol.source.ImageArcGISRest.prototype.set);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'setProperties',
+ ol.source.ImageArcGISRest.prototype.setProperties);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'unset',
+ ol.source.ImageArcGISRest.prototype.unset);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'changed',
+ ol.source.ImageArcGISRest.prototype.changed);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'dispatchEvent',
+ ol.source.ImageArcGISRest.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'getRevision',
+ ol.source.ImageArcGISRest.prototype.getRevision);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'on',
+ ol.source.ImageArcGISRest.prototype.on);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'once',
+ ol.source.ImageArcGISRest.prototype.once);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'un',
+ ol.source.ImageArcGISRest.prototype.un);
+
+goog.exportProperty(
+ ol.source.ImageArcGISRest.prototype,
+ 'unByKey',
+ ol.source.ImageArcGISRest.prototype.unByKey);
+
+goog.exportProperty(
ol.source.ImageCanvas.prototype,
'getAttributions',
ol.source.ImageCanvas.prototype.getAttributions);
@@ -126924,6 +111839,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.ImageCanvas.prototype,
+ 'refresh',
+ ol.source.ImageCanvas.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.ImageCanvas.prototype,
'setAttributions',
ol.source.ImageCanvas.prototype.setAttributions);
@@ -127014,6 +111934,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.ImageMapGuide.prototype,
+ 'refresh',
+ ol.source.ImageMapGuide.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.ImageMapGuide.prototype,
'setAttributions',
ol.source.ImageMapGuide.prototype.setAttributions);
@@ -127083,6 +112008,26 @@ goog.exportProperty(
ol.source.ImageMapGuide.prototype.unByKey);
goog.exportProperty(
+ ol.source.ImageEvent.prototype,
+ 'type',
+ ol.source.ImageEvent.prototype.type);
+
+goog.exportProperty(
+ ol.source.ImageEvent.prototype,
+ 'target',
+ ol.source.ImageEvent.prototype.target);
+
+goog.exportProperty(
+ ol.source.ImageEvent.prototype,
+ 'preventDefault',
+ ol.source.ImageEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.source.ImageEvent.prototype,
+ 'stopPropagation',
+ ol.source.ImageEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.source.ImageStatic.prototype,
'getAttributions',
ol.source.ImageStatic.prototype.getAttributions);
@@ -127104,6 +112049,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.ImageStatic.prototype,
+ 'refresh',
+ ol.source.ImageStatic.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.ImageStatic.prototype,
'setAttributions',
ol.source.ImageStatic.prototype.setAttributions);
@@ -127194,6 +112144,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.ImageVector.prototype,
+ 'refresh',
+ ol.source.ImageVector.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.ImageVector.prototype,
'setAttributions',
ol.source.ImageVector.prototype.setAttributions);
@@ -127284,6 +112239,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.ImageWMS.prototype,
+ 'refresh',
+ ol.source.ImageWMS.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.ImageWMS.prototype,
'setAttributions',
ol.source.ImageWMS.prototype.setAttributions);
@@ -127353,146 +112313,6 @@ goog.exportProperty(
ol.source.ImageWMS.prototype.unByKey);
goog.exportProperty(
- ol.source.XYZ.prototype,
- 'setRenderReprojectionEdges',
- ol.source.XYZ.prototype.setRenderReprojectionEdges);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'setTileGridForProjection',
- ol.source.XYZ.prototype.setTileGridForProjection);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getTileLoadFunction',
- ol.source.XYZ.prototype.getTileLoadFunction);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getTileUrlFunction',
- ol.source.XYZ.prototype.getTileUrlFunction);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getUrls',
- ol.source.XYZ.prototype.getUrls);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'setTileLoadFunction',
- ol.source.XYZ.prototype.setTileLoadFunction);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'setTileUrlFunction',
- ol.source.XYZ.prototype.setTileUrlFunction);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'setUrl',
- ol.source.XYZ.prototype.setUrl);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'setUrls',
- ol.source.XYZ.prototype.setUrls);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getTileGrid',
- ol.source.XYZ.prototype.getTileGrid);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getAttributions',
- ol.source.XYZ.prototype.getAttributions);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getLogo',
- ol.source.XYZ.prototype.getLogo);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getProjection',
- ol.source.XYZ.prototype.getProjection);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getState',
- ol.source.XYZ.prototype.getState);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'setAttributions',
- ol.source.XYZ.prototype.setAttributions);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'get',
- ol.source.XYZ.prototype.get);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getKeys',
- ol.source.XYZ.prototype.getKeys);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getProperties',
- ol.source.XYZ.prototype.getProperties);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'set',
- ol.source.XYZ.prototype.set);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'setProperties',
- ol.source.XYZ.prototype.setProperties);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'unset',
- ol.source.XYZ.prototype.unset);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'changed',
- ol.source.XYZ.prototype.changed);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'dispatchEvent',
- ol.source.XYZ.prototype.dispatchEvent);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'getRevision',
- ol.source.XYZ.prototype.getRevision);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'on',
- ol.source.XYZ.prototype.on);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'once',
- ol.source.XYZ.prototype.once);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'un',
- ol.source.XYZ.prototype.un);
-
-goog.exportProperty(
- ol.source.XYZ.prototype,
- 'unByKey',
- ol.source.XYZ.prototype.unByKey);
-
-goog.exportProperty(
ol.source.MapQuest.prototype,
'setRenderReprojectionEdges',
ol.source.MapQuest.prototype.setRenderReprojectionEdges);
@@ -127544,6 +112364,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.MapQuest.prototype,
+ 'refresh',
+ ol.source.MapQuest.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.MapQuest.prototype,
'getAttributions',
ol.source.MapQuest.prototype.getAttributions);
@@ -127684,6 +112509,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.OSM.prototype,
+ 'refresh',
+ ol.source.OSM.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.OSM.prototype,
'getAttributions',
ol.source.OSM.prototype.getAttributions);
@@ -127794,6 +112624,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Raster.prototype,
+ 'refresh',
+ ol.source.Raster.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.Raster.prototype,
'setAttributions',
ol.source.Raster.prototype.setAttributions);
@@ -127863,6 +112698,26 @@ goog.exportProperty(
ol.source.Raster.prototype.unByKey);
goog.exportProperty(
+ ol.source.RasterEvent.prototype,
+ 'type',
+ ol.source.RasterEvent.prototype.type);
+
+goog.exportProperty(
+ ol.source.RasterEvent.prototype,
+ 'target',
+ ol.source.RasterEvent.prototype.target);
+
+goog.exportProperty(
+ ol.source.RasterEvent.prototype,
+ 'preventDefault',
+ ol.source.RasterEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.source.RasterEvent.prototype,
+ 'stopPropagation',
+ ol.source.RasterEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.source.Stamen.prototype,
'setRenderReprojectionEdges',
ol.source.Stamen.prototype.setRenderReprojectionEdges);
@@ -127914,6 +112769,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Stamen.prototype,
+ 'refresh',
+ ol.source.Stamen.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.Stamen.prototype,
'getAttributions',
ol.source.Stamen.prototype.getAttributions);
@@ -128054,6 +112914,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.TileArcGISRest.prototype,
+ 'refresh',
+ ol.source.TileArcGISRest.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.TileArcGISRest.prototype,
'getAttributions',
ol.source.TileArcGISRest.prototype.getAttributions);
@@ -128149,6 +113014,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.TileDebug.prototype,
+ 'refresh',
+ ol.source.TileDebug.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.TileDebug.prototype,
'getAttributions',
ol.source.TileDebug.prototype.getAttributions);
@@ -128289,6 +113159,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.TileJSON.prototype,
+ 'refresh',
+ ol.source.TileJSON.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.TileJSON.prototype,
'getAttributions',
ol.source.TileJSON.prototype.getAttributions);
@@ -128378,12 +113253,37 @@ goog.exportProperty(
ol.source.TileJSON.prototype.unByKey);
goog.exportProperty(
+ ol.source.TileEvent.prototype,
+ 'type',
+ ol.source.TileEvent.prototype.type);
+
+goog.exportProperty(
+ ol.source.TileEvent.prototype,
+ 'target',
+ ol.source.TileEvent.prototype.target);
+
+goog.exportProperty(
+ ol.source.TileEvent.prototype,
+ 'preventDefault',
+ ol.source.TileEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.source.TileEvent.prototype,
+ 'stopPropagation',
+ ol.source.TileEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.source.TileUTFGrid.prototype,
'getTileGrid',
ol.source.TileUTFGrid.prototype.getTileGrid);
goog.exportProperty(
ol.source.TileUTFGrid.prototype,
+ 'refresh',
+ ol.source.TileUTFGrid.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.TileUTFGrid.prototype,
'getAttributions',
ol.source.TileUTFGrid.prototype.getAttributions);
@@ -128524,6 +113424,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.TileWMS.prototype,
+ 'refresh',
+ ol.source.TileWMS.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.TileWMS.prototype,
'getAttributions',
ol.source.TileWMS.prototype.getAttributions);
@@ -128613,6 +113518,26 @@ goog.exportProperty(
ol.source.TileWMS.prototype.unByKey);
goog.exportProperty(
+ ol.source.VectorEvent.prototype,
+ 'type',
+ ol.source.VectorEvent.prototype.type);
+
+goog.exportProperty(
+ ol.source.VectorEvent.prototype,
+ 'target',
+ ol.source.VectorEvent.prototype.target);
+
+goog.exportProperty(
+ ol.source.VectorEvent.prototype,
+ 'preventDefault',
+ ol.source.VectorEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.source.VectorEvent.prototype,
+ 'stopPropagation',
+ ol.source.VectorEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.source.VectorTile.prototype,
'getTileLoadFunction',
ol.source.VectorTile.prototype.getTileLoadFunction);
@@ -128654,6 +113579,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.VectorTile.prototype,
+ 'refresh',
+ ol.source.VectorTile.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.VectorTile.prototype,
'getAttributions',
ol.source.VectorTile.prototype.getAttributions);
@@ -128794,6 +113724,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.WMTS.prototype,
+ 'refresh',
+ ol.source.WMTS.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.WMTS.prototype,
'getAttributions',
ol.source.WMTS.prototype.getAttributions);
@@ -128934,6 +113869,11 @@ goog.exportProperty(
goog.exportProperty(
ol.source.Zoomify.prototype,
+ 'refresh',
+ ol.source.Zoomify.prototype.refresh);
+
+goog.exportProperty(
+ ol.source.Zoomify.prototype,
'getAttributions',
ol.source.Zoomify.prototype.getAttributions);
@@ -129518,6 +114458,46 @@ goog.exportProperty(
ol.renderer.canvas.VectorTileLayer.prototype.unByKey);
goog.exportProperty(
+ ol.render.Event.prototype,
+ 'type',
+ ol.render.Event.prototype.type);
+
+goog.exportProperty(
+ ol.render.Event.prototype,
+ 'target',
+ ol.render.Event.prototype.target);
+
+goog.exportProperty(
+ ol.render.Event.prototype,
+ 'preventDefault',
+ ol.render.Event.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.render.Event.prototype,
+ 'stopPropagation',
+ ol.render.Event.prototype.stopPropagation);
+
+goog.exportProperty(
+ ol.pointer.PointerEvent.prototype,
+ 'type',
+ ol.pointer.PointerEvent.prototype.type);
+
+goog.exportProperty(
+ ol.pointer.PointerEvent.prototype,
+ 'target',
+ ol.pointer.PointerEvent.prototype.target);
+
+goog.exportProperty(
+ ol.pointer.PointerEvent.prototype,
+ 'preventDefault',
+ ol.pointer.PointerEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.pointer.PointerEvent.prototype,
+ 'stopPropagation',
+ ol.pointer.PointerEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.layer.Base.prototype,
'get',
ol.layer.Base.prototype.get);
@@ -130394,6 +115374,11 @@ goog.exportProperty(
goog.exportProperty(
ol.layer.VectorTile.prototype,
+ 'getSource',
+ ol.layer.VectorTile.prototype.getSource);
+
+goog.exportProperty(
+ ol.layer.VectorTile.prototype,
'getStyle',
ol.layer.VectorTile.prototype.getStyle);
@@ -130768,6 +115753,46 @@ goog.exportProperty(
ol.interaction.DragAndDrop.prototype.unByKey);
goog.exportProperty(
+ ol.interaction.DragAndDropEvent.prototype,
+ 'type',
+ ol.interaction.DragAndDropEvent.prototype.type);
+
+goog.exportProperty(
+ ol.interaction.DragAndDropEvent.prototype,
+ 'target',
+ ol.interaction.DragAndDropEvent.prototype.target);
+
+goog.exportProperty(
+ ol.interaction.DragAndDropEvent.prototype,
+ 'preventDefault',
+ ol.interaction.DragAndDropEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.interaction.DragAndDropEvent.prototype,
+ 'stopPropagation',
+ ol.interaction.DragAndDropEvent.prototype.stopPropagation);
+
+goog.exportProperty(
+ ol.DragBoxEvent.prototype,
+ 'type',
+ ol.DragBoxEvent.prototype.type);
+
+goog.exportProperty(
+ ol.DragBoxEvent.prototype,
+ 'target',
+ ol.DragBoxEvent.prototype.target);
+
+goog.exportProperty(
+ ol.DragBoxEvent.prototype,
+ 'preventDefault',
+ ol.DragBoxEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.DragBoxEvent.prototype,
+ 'stopPropagation',
+ ol.DragBoxEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.interaction.Pointer.prototype,
'getActive',
ol.interaction.Pointer.prototype.getActive);
@@ -131253,6 +116278,26 @@ goog.exportProperty(
ol.interaction.DragZoom.prototype.unByKey);
goog.exportProperty(
+ ol.interaction.DrawEvent.prototype,
+ 'type',
+ ol.interaction.DrawEvent.prototype.type);
+
+goog.exportProperty(
+ ol.interaction.DrawEvent.prototype,
+ 'target',
+ ol.interaction.DrawEvent.prototype.target);
+
+goog.exportProperty(
+ ol.interaction.DrawEvent.prototype,
+ 'preventDefault',
+ ol.interaction.DrawEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.interaction.DrawEvent.prototype,
+ 'stopPropagation',
+ ol.interaction.DrawEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.interaction.Draw.prototype,
'getActive',
ol.interaction.Draw.prototype.getActive);
@@ -131493,6 +116538,26 @@ goog.exportProperty(
ol.interaction.KeyboardZoom.prototype.unByKey);
goog.exportProperty(
+ ol.interaction.ModifyEvent.prototype,
+ 'type',
+ ol.interaction.ModifyEvent.prototype.type);
+
+goog.exportProperty(
+ ol.interaction.ModifyEvent.prototype,
+ 'target',
+ ol.interaction.ModifyEvent.prototype.target);
+
+goog.exportProperty(
+ ol.interaction.ModifyEvent.prototype,
+ 'preventDefault',
+ ol.interaction.ModifyEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.interaction.ModifyEvent.prototype,
+ 'stopPropagation',
+ ol.interaction.ModifyEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.interaction.Modify.prototype,
'getActive',
ol.interaction.Modify.prototype.getActive);
@@ -131813,6 +116878,26 @@ goog.exportProperty(
ol.interaction.PinchZoom.prototype.unByKey);
goog.exportProperty(
+ ol.interaction.SelectEvent.prototype,
+ 'type',
+ ol.interaction.SelectEvent.prototype.type);
+
+goog.exportProperty(
+ ol.interaction.SelectEvent.prototype,
+ 'target',
+ ol.interaction.SelectEvent.prototype.target);
+
+goog.exportProperty(
+ ol.interaction.SelectEvent.prototype,
+ 'preventDefault',
+ ol.interaction.SelectEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.interaction.SelectEvent.prototype,
+ 'stopPropagation',
+ ol.interaction.SelectEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.interaction.Select.prototype,
'getActive',
ol.interaction.Select.prototype.getActive);
@@ -131973,6 +117058,26 @@ goog.exportProperty(
ol.interaction.Snap.prototype.unByKey);
goog.exportProperty(
+ ol.interaction.TranslateEvent.prototype,
+ 'type',
+ ol.interaction.TranslateEvent.prototype.type);
+
+goog.exportProperty(
+ ol.interaction.TranslateEvent.prototype,
+ 'target',
+ ol.interaction.TranslateEvent.prototype.target);
+
+goog.exportProperty(
+ ol.interaction.TranslateEvent.prototype,
+ 'preventDefault',
+ ol.interaction.TranslateEvent.prototype.preventDefault);
+
+goog.exportProperty(
+ ol.interaction.TranslateEvent.prototype,
+ 'stopPropagation',
+ ol.interaction.TranslateEvent.prototype.stopPropagation);
+
+goog.exportProperty(
ol.interaction.Translate.prototype,
'getActive',
ol.interaction.Translate.prototype.getActive);
@@ -132129,6 +117234,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.SimpleGeometry.prototype,
+ 'rotate',
+ ol.geom.SimpleGeometry.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.SimpleGeometry.prototype,
'simplify',
ol.geom.SimpleGeometry.prototype.simplify);
@@ -132219,6 +117329,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.Circle.prototype,
+ 'rotate',
+ ol.geom.Circle.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.Circle.prototype,
'getClosestPoint',
ol.geom.Circle.prototype.getClosestPoint);
@@ -132309,6 +117424,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.GeometryCollection.prototype,
+ 'rotate',
+ ol.geom.GeometryCollection.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.GeometryCollection.prototype,
'simplify',
ol.geom.GeometryCollection.prototype.simplify);
@@ -132399,6 +117519,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.LinearRing.prototype,
+ 'rotate',
+ ol.geom.LinearRing.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.LinearRing.prototype,
'getClosestPoint',
ol.geom.LinearRing.prototype.getClosestPoint);
@@ -132499,6 +117624,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.LineString.prototype,
+ 'rotate',
+ ol.geom.LineString.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.LineString.prototype,
'getClosestPoint',
ol.geom.LineString.prototype.getClosestPoint);
@@ -132599,6 +117729,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.MultiLineString.prototype,
+ 'rotate',
+ ol.geom.MultiLineString.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.MultiLineString.prototype,
'getClosestPoint',
ol.geom.MultiLineString.prototype.getClosestPoint);
@@ -132699,6 +117834,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.MultiPoint.prototype,
+ 'rotate',
+ ol.geom.MultiPoint.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.MultiPoint.prototype,
'getClosestPoint',
ol.geom.MultiPoint.prototype.getClosestPoint);
@@ -132799,6 +117939,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.MultiPolygon.prototype,
+ 'rotate',
+ ol.geom.MultiPolygon.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.MultiPolygon.prototype,
'getClosestPoint',
ol.geom.MultiPolygon.prototype.getClosestPoint);
@@ -132899,6 +118044,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.Point.prototype,
+ 'rotate',
+ ol.geom.Point.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.Point.prototype,
'getClosestPoint',
ol.geom.Point.prototype.getClosestPoint);
@@ -132999,6 +118149,11 @@ goog.exportProperty(
goog.exportProperty(
ol.geom.Polygon.prototype,
+ 'rotate',
+ ol.geom.Polygon.prototype.rotate);
+
+goog.exportProperty(
+ ol.geom.Polygon.prototype,
'getClosestPoint',
ol.geom.Polygon.prototype.getClosestPoint);
@@ -133083,6 +118238,1176 @@ goog.exportProperty(
ol.geom.Polygon.prototype.unByKey);
goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'get',
+ ol.format.ogc.filter.Filter.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.Filter.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.Filter.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'set',
+ ol.format.ogc.filter.Filter.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.Filter.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'unset',
+ ol.format.ogc.filter.Filter.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'changed',
+ ol.format.ogc.filter.Filter.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.Filter.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.Filter.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'on',
+ ol.format.ogc.filter.Filter.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'once',
+ ol.format.ogc.filter.Filter.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'un',
+ ol.format.ogc.filter.Filter.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Filter.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.Filter.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'get',
+ ol.format.ogc.filter.Logical.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.Logical.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.Logical.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'set',
+ ol.format.ogc.filter.Logical.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.Logical.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'unset',
+ ol.format.ogc.filter.Logical.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'changed',
+ ol.format.ogc.filter.Logical.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.Logical.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.Logical.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'on',
+ ol.format.ogc.filter.Logical.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'once',
+ ol.format.ogc.filter.Logical.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'un',
+ ol.format.ogc.filter.Logical.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Logical.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.Logical.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'get',
+ ol.format.ogc.filter.LogicalBinary.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.LogicalBinary.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.LogicalBinary.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'set',
+ ol.format.ogc.filter.LogicalBinary.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.LogicalBinary.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'unset',
+ ol.format.ogc.filter.LogicalBinary.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'changed',
+ ol.format.ogc.filter.LogicalBinary.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.LogicalBinary.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.LogicalBinary.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'on',
+ ol.format.ogc.filter.LogicalBinary.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'once',
+ ol.format.ogc.filter.LogicalBinary.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'un',
+ ol.format.ogc.filter.LogicalBinary.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LogicalBinary.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.LogicalBinary.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'get',
+ ol.format.ogc.filter.And.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.And.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.And.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'set',
+ ol.format.ogc.filter.And.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.And.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'unset',
+ ol.format.ogc.filter.And.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'changed',
+ ol.format.ogc.filter.And.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.And.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.And.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'on',
+ ol.format.ogc.filter.And.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'once',
+ ol.format.ogc.filter.And.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'un',
+ ol.format.ogc.filter.And.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.And.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.And.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'get',
+ ol.format.ogc.filter.Or.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.Or.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.Or.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'set',
+ ol.format.ogc.filter.Or.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.Or.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'unset',
+ ol.format.ogc.filter.Or.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'changed',
+ ol.format.ogc.filter.Or.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.Or.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.Or.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'on',
+ ol.format.ogc.filter.Or.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'once',
+ ol.format.ogc.filter.Or.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'un',
+ ol.format.ogc.filter.Or.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Or.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.Or.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'get',
+ ol.format.ogc.filter.Not.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.Not.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.Not.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'set',
+ ol.format.ogc.filter.Not.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.Not.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'unset',
+ ol.format.ogc.filter.Not.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'changed',
+ ol.format.ogc.filter.Not.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.Not.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.Not.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'on',
+ ol.format.ogc.filter.Not.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'once',
+ ol.format.ogc.filter.Not.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'un',
+ ol.format.ogc.filter.Not.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Not.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.Not.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'get',
+ ol.format.ogc.filter.Bbox.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.Bbox.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.Bbox.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'set',
+ ol.format.ogc.filter.Bbox.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.Bbox.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'unset',
+ ol.format.ogc.filter.Bbox.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'changed',
+ ol.format.ogc.filter.Bbox.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.Bbox.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.Bbox.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'on',
+ ol.format.ogc.filter.Bbox.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'once',
+ ol.format.ogc.filter.Bbox.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'un',
+ ol.format.ogc.filter.Bbox.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Bbox.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.Bbox.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'get',
+ ol.format.ogc.filter.Comparison.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.Comparison.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.Comparison.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'set',
+ ol.format.ogc.filter.Comparison.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.Comparison.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'unset',
+ ol.format.ogc.filter.Comparison.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'changed',
+ ol.format.ogc.filter.Comparison.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.Comparison.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.Comparison.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'on',
+ ol.format.ogc.filter.Comparison.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'once',
+ ol.format.ogc.filter.Comparison.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'un',
+ ol.format.ogc.filter.Comparison.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.Comparison.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.Comparison.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'get',
+ ol.format.ogc.filter.ComparisonBinary.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.ComparisonBinary.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.ComparisonBinary.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'set',
+ ol.format.ogc.filter.ComparisonBinary.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.ComparisonBinary.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'unset',
+ ol.format.ogc.filter.ComparisonBinary.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'changed',
+ ol.format.ogc.filter.ComparisonBinary.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.ComparisonBinary.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.ComparisonBinary.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'on',
+ ol.format.ogc.filter.ComparisonBinary.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'once',
+ ol.format.ogc.filter.ComparisonBinary.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'un',
+ ol.format.ogc.filter.ComparisonBinary.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.ComparisonBinary.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.ComparisonBinary.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'get',
+ ol.format.ogc.filter.EqualTo.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.EqualTo.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.EqualTo.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'set',
+ ol.format.ogc.filter.EqualTo.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.EqualTo.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'unset',
+ ol.format.ogc.filter.EqualTo.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'changed',
+ ol.format.ogc.filter.EqualTo.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.EqualTo.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.EqualTo.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'on',
+ ol.format.ogc.filter.EqualTo.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'once',
+ ol.format.ogc.filter.EqualTo.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'un',
+ ol.format.ogc.filter.EqualTo.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.EqualTo.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.EqualTo.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'get',
+ ol.format.ogc.filter.NotEqualTo.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.NotEqualTo.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.NotEqualTo.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'set',
+ ol.format.ogc.filter.NotEqualTo.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.NotEqualTo.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'unset',
+ ol.format.ogc.filter.NotEqualTo.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'changed',
+ ol.format.ogc.filter.NotEqualTo.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.NotEqualTo.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.NotEqualTo.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'on',
+ ol.format.ogc.filter.NotEqualTo.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'once',
+ ol.format.ogc.filter.NotEqualTo.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'un',
+ ol.format.ogc.filter.NotEqualTo.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.NotEqualTo.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.NotEqualTo.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'get',
+ ol.format.ogc.filter.LessThan.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.LessThan.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.LessThan.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'set',
+ ol.format.ogc.filter.LessThan.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.LessThan.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'unset',
+ ol.format.ogc.filter.LessThan.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'changed',
+ ol.format.ogc.filter.LessThan.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.LessThan.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.LessThan.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'on',
+ ol.format.ogc.filter.LessThan.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'once',
+ ol.format.ogc.filter.LessThan.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'un',
+ ol.format.ogc.filter.LessThan.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThan.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.LessThan.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'get',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'set',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'unset',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'changed',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'on',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'once',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'un',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.LessThanOrEqualTo.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'get',
+ ol.format.ogc.filter.GreaterThan.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.GreaterThan.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.GreaterThan.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'set',
+ ol.format.ogc.filter.GreaterThan.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.GreaterThan.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'unset',
+ ol.format.ogc.filter.GreaterThan.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'changed',
+ ol.format.ogc.filter.GreaterThan.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.GreaterThan.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.GreaterThan.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'on',
+ ol.format.ogc.filter.GreaterThan.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'once',
+ ol.format.ogc.filter.GreaterThan.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'un',
+ ol.format.ogc.filter.GreaterThan.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThan.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.GreaterThan.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'get',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'set',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'unset',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'changed',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'on',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'once',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'un',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.GreaterThanOrEqualTo.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'get',
+ ol.format.ogc.filter.IsNull.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.IsNull.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.IsNull.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'set',
+ ol.format.ogc.filter.IsNull.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.IsNull.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'unset',
+ ol.format.ogc.filter.IsNull.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'changed',
+ ol.format.ogc.filter.IsNull.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.IsNull.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.IsNull.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'on',
+ ol.format.ogc.filter.IsNull.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'once',
+ ol.format.ogc.filter.IsNull.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'un',
+ ol.format.ogc.filter.IsNull.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsNull.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.IsNull.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'get',
+ ol.format.ogc.filter.IsBetween.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.IsBetween.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.IsBetween.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'set',
+ ol.format.ogc.filter.IsBetween.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.IsBetween.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'unset',
+ ol.format.ogc.filter.IsBetween.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'changed',
+ ol.format.ogc.filter.IsBetween.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.IsBetween.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.IsBetween.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'on',
+ ol.format.ogc.filter.IsBetween.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'once',
+ ol.format.ogc.filter.IsBetween.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'un',
+ ol.format.ogc.filter.IsBetween.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsBetween.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.IsBetween.prototype.unByKey);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'get',
+ ol.format.ogc.filter.IsLike.prototype.get);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'getKeys',
+ ol.format.ogc.filter.IsLike.prototype.getKeys);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'getProperties',
+ ol.format.ogc.filter.IsLike.prototype.getProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'set',
+ ol.format.ogc.filter.IsLike.prototype.set);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'setProperties',
+ ol.format.ogc.filter.IsLike.prototype.setProperties);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'unset',
+ ol.format.ogc.filter.IsLike.prototype.unset);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'changed',
+ ol.format.ogc.filter.IsLike.prototype.changed);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'dispatchEvent',
+ ol.format.ogc.filter.IsLike.prototype.dispatchEvent);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'getRevision',
+ ol.format.ogc.filter.IsLike.prototype.getRevision);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'on',
+ ol.format.ogc.filter.IsLike.prototype.on);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'once',
+ ol.format.ogc.filter.IsLike.prototype.once);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'un',
+ ol.format.ogc.filter.IsLike.prototype.un);
+
+goog.exportProperty(
+ ol.format.ogc.filter.IsLike.prototype,
+ 'unByKey',
+ ol.format.ogc.filter.IsLike.prototype.unByKey);
+
+goog.exportProperty(
ol.format.GML2.prototype,
'readFeatures',
ol.format.GML2.prototype.readFeatures);