UNPKG

leaflet-environmental-layers

Version:

[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/publiclab/leaflet-environmental-layers/) [![npm version](https://badge.fury.io/js/leaflet-environmental-layers.svg)](http

1,857 lines (1,534 loc) 1.11 MB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ /* * heatmap.js v2.0.5 | JavaScript Heatmap Library * * Copyright 2008-2016 Patrick Wied <heatmapjs@patrick-wied.at> - All rights reserved. * Dual licensed under MIT and Beerware license * * :: 2016-09-05 01:16 */ ;(function (name, context, factory) { // Supports UMD. AMD, CommonJS/Node.js and browser context if (typeof module !== "undefined" && module.exports) { module.exports = factory(); } else if (typeof define === "function" && define.amd) { define(factory); } else { context[name] = factory(); } })("h337", this, function () { // Heatmap Config stores default values and will be merged with instance config var HeatmapConfig = { defaultRadius: 40, defaultRenderer: 'canvas2d', defaultGradient: { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"}, defaultMaxOpacity: 1, defaultMinOpacity: 0, defaultBlur: .85, defaultXField: 'x', defaultYField: 'y', defaultValueField: 'value', plugins: {} }; var Store = (function StoreClosure() { var Store = function Store(config) { this._coordinator = {}; this._data = []; this._radi = []; this._min = 10; this._max = 1; this._xField = config['xField'] || config.defaultXField; this._yField = config['yField'] || config.defaultYField; this._valueField = config['valueField'] || config.defaultValueField; if (config["radius"]) { this._cfgRadius = config["radius"]; } }; var defaultRadius = HeatmapConfig.defaultRadius; Store.prototype = { // when forceRender = false -> called from setData, omits renderall event _organiseData: function(dataPoint, forceRender) { var x = dataPoint[this._xField]; var y = dataPoint[this._yField]; var radi = this._radi; var store = this._data; var max = this._max; var min = this._min; var value = dataPoint[this._valueField] || 1; var radius = dataPoint.radius || this._cfgRadius || defaultRadius; if (!store[x]) { store[x] = []; radi[x] = []; } if (!store[x][y]) { store[x][y] = value; radi[x][y] = radius; } else { store[x][y] += value; } var storedVal = store[x][y]; if (storedVal > max) { if (!forceRender) { this._max = storedVal; } else { this.setDataMax(storedVal); } return false; } else if (storedVal < min) { if (!forceRender) { this._min = storedVal; } else { this.setDataMin(storedVal); } return false; } else { return { x: x, y: y, value: value, radius: radius, min: min, max: max }; } }, _unOrganizeData: function() { var unorganizedData = []; var data = this._data; var radi = this._radi; for (var x in data) { for (var y in data[x]) { unorganizedData.push({ x: x, y: y, radius: radi[x][y], value: data[x][y] }); } } return { min: this._min, max: this._max, data: unorganizedData }; }, _onExtremaChange: function() { this._coordinator.emit('extremachange', { min: this._min, max: this._max }); }, addData: function() { if (arguments[0].length > 0) { var dataArr = arguments[0]; var dataLen = dataArr.length; while (dataLen--) { this.addData.call(this, dataArr[dataLen]); } } else { // add to store var organisedEntry = this._organiseData(arguments[0], true); if (organisedEntry) { // if it's the first datapoint initialize the extremas with it if (this._data.length === 0) { this._min = this._max = organisedEntry.value; } this._coordinator.emit('renderpartial', { min: this._min, max: this._max, data: [organisedEntry] }); } } return this; }, setData: function(data) { var dataPoints = data.data; var pointsLen = dataPoints.length; // reset data arrays this._data = []; this._radi = []; for(var i = 0; i < pointsLen; i++) { this._organiseData(dataPoints[i], false); } this._max = data.max; this._min = data.min || 0; this._onExtremaChange(); this._coordinator.emit('renderall', this._getInternalData()); return this; }, removeData: function() { // TODO: implement }, setDataMax: function(max) { this._max = max; this._onExtremaChange(); this._coordinator.emit('renderall', this._getInternalData()); return this; }, setDataMin: function(min) { this._min = min; this._onExtremaChange(); this._coordinator.emit('renderall', this._getInternalData()); return this; }, setCoordinator: function(coordinator) { this._coordinator = coordinator; }, _getInternalData: function() { return { max: this._max, min: this._min, data: this._data, radi: this._radi }; }, getData: function() { return this._unOrganizeData(); }/*, TODO: rethink. getValueAt: function(point) { var value; var radius = 100; var x = point.x; var y = point.y; var data = this._data; if (data[x] && data[x][y]) { return data[x][y]; } else { var values = []; // radial search for datapoints based on default radius for(var distance = 1; distance < radius; distance++) { var neighbors = distance * 2 +1; var startX = x - distance; var startY = y - distance; for(var i = 0; i < neighbors; i++) { for (var o = 0; o < neighbors; o++) { if ((i == 0 || i == neighbors-1) || (o == 0 || o == neighbors-1)) { if (data[startY+i] && data[startY+i][startX+o]) { values.push(data[startY+i][startX+o]); } } else { continue; } } } } if (values.length > 0) { return Math.max.apply(Math, values); } } return false; }*/ }; return Store; })(); var Canvas2dRenderer = (function Canvas2dRendererClosure() { var _getColorPalette = function(config) { var gradientConfig = config.gradient || config.defaultGradient; var paletteCanvas = document.createElement('canvas'); var paletteCtx = paletteCanvas.getContext('2d'); paletteCanvas.width = 256; paletteCanvas.height = 1; var gradient = paletteCtx.createLinearGradient(0, 0, 256, 1); for (var key in gradientConfig) { gradient.addColorStop(key, gradientConfig[key]); } paletteCtx.fillStyle = gradient; paletteCtx.fillRect(0, 0, 256, 1); return paletteCtx.getImageData(0, 0, 256, 1).data; }; var _getPointTemplate = function(radius, blurFactor) { var tplCanvas = document.createElement('canvas'); var tplCtx = tplCanvas.getContext('2d'); var x = radius; var y = radius; tplCanvas.width = tplCanvas.height = radius*2; if (blurFactor == 1) { tplCtx.beginPath(); tplCtx.arc(x, y, radius, 0, 2 * Math.PI, false); tplCtx.fillStyle = 'rgba(0,0,0,1)'; tplCtx.fill(); } else { var gradient = tplCtx.createRadialGradient(x, y, radius*blurFactor, x, y, radius); gradient.addColorStop(0, 'rgba(0,0,0,1)'); gradient.addColorStop(1, 'rgba(0,0,0,0)'); tplCtx.fillStyle = gradient; tplCtx.fillRect(0, 0, 2*radius, 2*radius); } return tplCanvas; }; var _prepareData = function(data) { var renderData = []; var min = data.min; var max = data.max; var radi = data.radi; var data = data.data; var xValues = Object.keys(data); var xValuesLen = xValues.length; while(xValuesLen--) { var xValue = xValues[xValuesLen]; var yValues = Object.keys(data[xValue]); var yValuesLen = yValues.length; while(yValuesLen--) { var yValue = yValues[yValuesLen]; var value = data[xValue][yValue]; var radius = radi[xValue][yValue]; renderData.push({ x: xValue, y: yValue, value: value, radius: radius }); } } return { min: min, max: max, data: renderData }; }; function Canvas2dRenderer(config) { var container = config.container; var shadowCanvas = this.shadowCanvas = document.createElement('canvas'); var canvas = this.canvas = config.canvas || document.createElement('canvas'); var renderBoundaries = this._renderBoundaries = [10000, 10000, 0, 0]; var computed = getComputedStyle(config.container) || {}; canvas.className = 'heatmap-canvas'; this._width = canvas.width = shadowCanvas.width = config.width || +(computed.width.replace(/px/,'')); this._height = canvas.height = shadowCanvas.height = config.height || +(computed.height.replace(/px/,'')); this.shadowCtx = shadowCanvas.getContext('2d'); this.ctx = canvas.getContext('2d'); // @TODO: // conditional wrapper canvas.style.cssText = shadowCanvas.style.cssText = 'position:absolute;left:0;top:0;'; container.style.position = 'relative'; container.appendChild(canvas); this._palette = _getColorPalette(config); this._templates = {}; this._setStyles(config); }; Canvas2dRenderer.prototype = { renderPartial: function(data) { if (data.data.length > 0) { this._drawAlpha(data); this._colorize(); } }, renderAll: function(data) { // reset render boundaries this._clear(); if (data.data.length > 0) { this._drawAlpha(_prepareData(data)); this._colorize(); } }, _updateGradient: function(config) { this._palette = _getColorPalette(config); }, updateConfig: function(config) { if (config['gradient']) { this._updateGradient(config); } this._setStyles(config); }, setDimensions: function(width, height) { this._width = width; this._height = height; this.canvas.width = this.shadowCanvas.width = width; this.canvas.height = this.shadowCanvas.height = height; }, _clear: function() { this.shadowCtx.clearRect(0, 0, this._width, this._height); this.ctx.clearRect(0, 0, this._width, this._height); }, _setStyles: function(config) { this._blur = (config.blur == 0)?0:(config.blur || config.defaultBlur); if (config.backgroundColor) { this.canvas.style.backgroundColor = config.backgroundColor; } this._width = this.canvas.width = this.shadowCanvas.width = config.width || this._width; this._height = this.canvas.height = this.shadowCanvas.height = config.height || this._height; this._opacity = (config.opacity || 0) * 255; this._maxOpacity = (config.maxOpacity || config.defaultMaxOpacity) * 255; this._minOpacity = (config.minOpacity || config.defaultMinOpacity) * 255; this._useGradientOpacity = !!config.useGradientOpacity; }, _drawAlpha: function(data) { var min = this._min = data.min; var max = this._max = data.max; var data = data.data || []; var dataLen = data.length; // on a point basis? var blur = 1 - this._blur; while(dataLen--) { var point = data[dataLen]; var x = point.x; var y = point.y; var radius = point.radius; // if value is bigger than max // use max as value var value = Math.min(point.value, max); var rectX = x - radius; var rectY = y - radius; var shadowCtx = this.shadowCtx; var tpl; if (!this._templates[radius]) { this._templates[radius] = tpl = _getPointTemplate(radius, blur); } else { tpl = this._templates[radius]; } // value from minimum / value range // => [0, 1] var templateAlpha = (value-min)/(max-min); // this fixes #176: small values are not visible because globalAlpha < .01 cannot be read from imageData shadowCtx.globalAlpha = templateAlpha < .01 ? .01 : templateAlpha; shadowCtx.drawImage(tpl, rectX, rectY); // update renderBoundaries if (rectX < this._renderBoundaries[0]) { this._renderBoundaries[0] = rectX; } if (rectY < this._renderBoundaries[1]) { this._renderBoundaries[1] = rectY; } if (rectX + 2*radius > this._renderBoundaries[2]) { this._renderBoundaries[2] = rectX + 2*radius; } if (rectY + 2*radius > this._renderBoundaries[3]) { this._renderBoundaries[3] = rectY + 2*radius; } } }, _colorize: function() { var x = this._renderBoundaries[0]; var y = this._renderBoundaries[1]; var width = this._renderBoundaries[2] - x; var height = this._renderBoundaries[3] - y; var maxWidth = this._width; var maxHeight = this._height; var opacity = this._opacity; var maxOpacity = this._maxOpacity; var minOpacity = this._minOpacity; var useGradientOpacity = this._useGradientOpacity; if (x < 0) { x = 0; } if (y < 0) { y = 0; } if (x + width > maxWidth) { width = maxWidth - x; } if (y + height > maxHeight) { height = maxHeight - y; } var img = this.shadowCtx.getImageData(x, y, width, height); var imgData = img.data; var len = imgData.length; var palette = this._palette; for (var i = 3; i < len; i+= 4) { var alpha = imgData[i]; var offset = alpha * 4; if (!offset) { continue; } var finalAlpha; if (opacity > 0) { finalAlpha = opacity; } else { if (alpha < maxOpacity) { if (alpha < minOpacity) { finalAlpha = minOpacity; } else { finalAlpha = alpha; } } else { finalAlpha = maxOpacity; } } imgData[i-3] = palette[offset]; imgData[i-2] = palette[offset + 1]; imgData[i-1] = palette[offset + 2]; imgData[i] = useGradientOpacity ? palette[offset + 3] : finalAlpha; } img.data = imgData; this.ctx.putImageData(img, x, y); this._renderBoundaries = [1000, 1000, 0, 0]; }, getValueAt: function(point) { var value; var shadowCtx = this.shadowCtx; var img = shadowCtx.getImageData(point.x, point.y, 1, 1); var data = img.data[3]; var max = this._max; var min = this._min; value = (Math.abs(max-min) * (data/255)) >> 0; return value; }, getDataURL: function() { return this.canvas.toDataURL(); } }; return Canvas2dRenderer; })(); var Renderer = (function RendererClosure() { var rendererFn = false; if (HeatmapConfig['defaultRenderer'] === 'canvas2d') { rendererFn = Canvas2dRenderer; } return rendererFn; })(); var Util = { merge: function() { var merged = {}; var argsLen = arguments.length; for (var i = 0; i < argsLen; i++) { var obj = arguments[i] for (var key in obj) { merged[key] = obj[key]; } } return merged; } }; // Heatmap Constructor var Heatmap = (function HeatmapClosure() { var Coordinator = (function CoordinatorClosure() { function Coordinator() { this.cStore = {}; }; Coordinator.prototype = { on: function(evtName, callback, scope) { var cStore = this.cStore; if (!cStore[evtName]) { cStore[evtName] = []; } cStore[evtName].push((function(data) { return callback.call(scope, data); })); }, emit: function(evtName, data) { var cStore = this.cStore; if (cStore[evtName]) { var len = cStore[evtName].length; for (var i=0; i<len; i++) { var callback = cStore[evtName][i]; callback(data); } } } }; return Coordinator; })(); var _connect = function(scope) { var renderer = scope._renderer; var coordinator = scope._coordinator; var store = scope._store; coordinator.on('renderpartial', renderer.renderPartial, renderer); coordinator.on('renderall', renderer.renderAll, renderer); coordinator.on('extremachange', function(data) { scope._config.onExtremaChange && scope._config.onExtremaChange({ min: data.min, max: data.max, gradient: scope._config['gradient'] || scope._config['defaultGradient'] }); }); store.setCoordinator(coordinator); }; function Heatmap() { var config = this._config = Util.merge(HeatmapConfig, arguments[0] || {}); this._coordinator = new Coordinator(); if (config['plugin']) { var pluginToLoad = config['plugin']; if (!HeatmapConfig.plugins[pluginToLoad]) { throw new Error('Plugin \''+ pluginToLoad + '\' not found. Maybe it was not registered.'); } else { var plugin = HeatmapConfig.plugins[pluginToLoad]; // set plugin renderer and store this._renderer = new plugin.renderer(config); this._store = new plugin.store(config); } } else { this._renderer = new Renderer(config); this._store = new Store(config); } _connect(this); }; // @TODO: // add API documentation Heatmap.prototype = { addData: function() { this._store.addData.apply(this._store, arguments); return this; }, removeData: function() { this._store.removeData && this._store.removeData.apply(this._store, arguments); return this; }, setData: function() { this._store.setData.apply(this._store, arguments); return this; }, setDataMax: function() { this._store.setDataMax.apply(this._store, arguments); return this; }, setDataMin: function() { this._store.setDataMin.apply(this._store, arguments); return this; }, configure: function(config) { this._config = Util.merge(this._config, config); this._renderer.updateConfig(this._config); this._coordinator.emit('renderall', this._store._getInternalData()); return this; }, repaint: function() { this._coordinator.emit('renderall', this._store._getInternalData()); return this; }, getData: function() { return this._store.getData(); }, getDataURL: function() { return this._renderer.getDataURL(); }, getValueAt: function(point) { if (this._store.getValueAt) { return this._store.getValueAt(point); } else if (this._renderer.getValueAt) { return this._renderer.getValueAt(point); } else { return null; } } }; return Heatmap; })(); // core var heatmapFactory = { create: function(config) { return new Heatmap(config); }, register: function(pluginKey, plugin) { HeatmapConfig.plugins[pluginKey] = plugin; } }; return heatmapFactory; }); },{}],2:[function(require,module,exports){ /*! * jQuery JavaScript Library v3.5.1 * https://jquery.com/ * * Includes Sizzle.js * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://jquery.org/license * * Date: 2020-05-04T22:49Z */ ( function( global, factory ) { "use strict"; if ( typeof module === "object" && typeof module.exports === "object" ) { // For CommonJS and CommonJS-like environments where a proper `window` // is present, execute the factory and get jQuery. // For environments that do not have a `window` with a `document` // (such as Node.js), expose a factory as module.exports. // This accentuates the need for the creation of a real `window`. // e.g. var jQuery = require("jquery")(window); // See ticket #14549 for more info. module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); } // Pass this if window is not defined yet } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { // Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 // throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode // arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common // enough that all such attempts are guarded in a try block. "use strict"; var arr = []; var getProto = Object.getPrototypeOf; var slice = arr.slice; var flat = arr.flat ? function( array ) { return arr.flat.call( array ); } : function( array ) { return arr.concat.apply( [], array ); }; var push = arr.push; var indexOf = arr.indexOf; var class2type = {}; var toString = class2type.toString; var hasOwn = class2type.hasOwnProperty; var fnToString = hasOwn.toString; var ObjectFunctionString = fnToString.call( Object ); var support = {}; var isFunction = function isFunction( obj ) { // Support: Chrome <=57, Firefox <=52 // In some browsers, typeof returns "function" for HTML <object> elements // (i.e., `typeof document.createElement( "object" ) === "function"`). // We don't want to classify *any* DOM node as a function. return typeof obj === "function" && typeof obj.nodeType !== "number"; }; var isWindow = function isWindow( obj ) { return obj != null && obj === obj.window; }; var document = window.document; var preservedScriptAttributes = { type: true, src: true, nonce: true, noModule: true }; function DOMEval( code, node, doc ) { doc = doc || document; var i, val, script = doc.createElement( "script" ); script.text = code; if ( node ) { for ( i in preservedScriptAttributes ) { // Support: Firefox 64+, Edge 18+ // Some browsers don't support the "nonce" property on scripts. // On the other hand, just using `getAttribute` is not enough as // the `nonce` attribute is reset to an empty string whenever it // becomes browsing-context connected. // See https://github.com/whatwg/html/issues/2369 // See https://html.spec.whatwg.org/#nonce-attributes // The `node.getAttribute` check was added for the sake of // `jQuery.globalEval` so that it can fake a nonce-containing node // via an object. val = node[ i ] || node.getAttribute && node.getAttribute( i ); if ( val ) { script.setAttribute( i, val ); } } } doc.head.appendChild( script ).parentNode.removeChild( script ); } function toType( obj ) { if ( obj == null ) { return obj + ""; } // Support: Android <=2.3 only (functionish RegExp) return typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call( obj ) ] || "object" : typeof obj; } /* global Symbol */ // Defining this global in .eslintrc.json would create a danger of using the global // unguarded in another place, it seems safer to define global only for this module var version = "3.5.1", // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); }; jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: version, constructor: jQuery, // The default length of a jQuery object is 0 length: 0, toArray: function() { return slice.call( this ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { // Return all the elements in a clean array if ( num == null ) { return slice.call( this ); } // Return just the one element from the set return num < 0 ? this[ num + this.length ] : this[ num ]; }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. each: function( callback ) { return jQuery.each( this, callback ); }, map: function( callback ) { return this.pushStack( jQuery.map( this, function( elem, i ) { return callback.call( elem, i, elem ); } ) ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ) ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, even: function() { return this.pushStack( jQuery.grep( this, function( _elem, i ) { return ( i + 1 ) % 2; } ) ); }, odd: function() { return this.pushStack( jQuery.grep( this, function( _elem, i ) { return i % 2; } ) ); }, eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); }, end: function() { return this.prevObject || this.constructor(); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: arr.sort, splice: arr.splice }; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !isFunction( target ) ) { target = {}; } // Extend jQuery itself if only one argument is passed if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { copy = options[ name ]; // Prevent Object.prototype pollution // Prevent never-ending loop if ( name === "__proto__" || target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = Array.isArray( copy ) ) ) ) { src = target[ name ]; // Ensure proper type for the source value if ( copyIsArray && !Array.isArray( src ) ) { clone = []; } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { clone = {}; } else { clone = src; } copyIsArray = false; // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend( { // Unique for each copy of jQuery on the page expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), // Assume jQuery is ready without the ready module isReady: true, error: function( msg ) { throw new Error( msg ); }, noop: function() {}, isPlainObject: function( obj ) { var proto, Ctor; // Detect obvious negatives // Use toString instead of jQuery.type to catch host objects if ( !obj || toString.call( obj ) !== "[object Object]" ) { return false; } proto = getProto( obj ); // Objects with no prototype (e.g., `Object.create( null )`) are plain if ( !proto ) { return true; } // Objects with prototype are plain iff they were constructed by a global Object function Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; }, isEmptyObject: function( obj ) { var name; for ( name in obj ) { return false; } return true; }, // Evaluates a script in a provided context; falls back to the global one // if not specified. globalEval: function( code, options, doc ) { DOMEval( code, { nonce: options && options.nonce }, doc ); }, each: function( obj, callback ) { var length, i = 0; if ( isArrayLike( obj ) ) { length = obj.length; for ( ; i < length; i++ ) { if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } } else { for ( i in obj ) { if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } } return obj; }, // results is for internal usage only makeArray: function( arr, results ) { var ret = results || []; if ( arr != null ) { if ( isArrayLike( Object( arr ) ) ) { jQuery.merge( ret, typeof arr === "string" ? [ arr ] : arr ); } else { push.call( ret, arr ); } } return ret; }, inArray: function( elem, arr, i ) { return arr == null ? -1 : indexOf.call( arr, elem, i ); }, // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit merge: function( first, second ) { var len = +second.length, j = 0, i = first.length; for ( ; j < len; j++ ) { first[ i++ ] = second[ j ]; } first.length = i; return first; }, grep: function( elems, callback, invert ) { var callbackInverse, matches = [], i = 0, length = elems.length, callbackExpect = !invert; // Go through the array, only saving the items // that pass the validator function for ( ; i < length; i++ ) { callbackInverse = !callback( elems[ i ], i ); if ( callbackInverse !== callbackExpect ) { matches.push( elems[ i ] ); } } return matches; }, // arg is for internal usage only map: function( elems, callback, arg ) { var length, value, i = 0, ret = []; // Go through the array, translating each of the items to their new values if ( isArrayLike( elems ) ) { length = elems.length; for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } // Go through every key on the object, } else { for ( i in elems ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } } // Flatten any nested arrays return flat( ret ); }, // A global GUID counter for objects guid: 1, // jQuery.support is not used in Core but other projects attach their // properties to it so it needs to exist. support: support } ); if ( typeof Symbol === "function" ) { jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; } // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), function( _i, name ) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); } ); function isArrayLike( obj ) { // Support: real iOS 8.2 only (not reproducible in simulator) // `in` check used to prevent JIT error (gh-2145) // hasOwn isn't used here due to false negatives // regarding Nodelist length in IE var length = !!obj && "length" in obj && obj.length, type = toType( obj ); if ( isFunction( obj ) || isWindow( obj ) ) { return false; } return type === "array" || length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in obj; } var Sizzle = /*! * Sizzle CSS Selector Engine v2.3.5 * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://js.foundation/ * * Date: 2020-03-14 */ ( function( window ) { var i, support, Expr, getText, isXML, tokenize, compile, select, outermostContext, sortInput, hasDuplicate, // Local document vars setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains, // Instance-specific data expando = "sizzle" + 1 * new Date(), preferredDoc = window.document, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), nonnativeSelectorCache = createCache(), sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; } return 0; }, // Instance methods hasOwn = ( {} ).hasOwnProperty, arr = [], pop = arr.pop, pushNative = arr.push, push = arr.push, slice = arr.slice, // Use a stripped-down indexOf as it's faster than native // https://jsperf.com/thor-indexof-vs-for/5 indexOf = function( list, elem ) { var i = 0, len = list.length; for ( ; i < len; i++ ) { if ( list[ i ] === elem ) { return i; } } return -1; }, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + "ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // http://www.w3.org/TR/css3-selectors/#whitespace whitespace = "[\\x20\\t\\r\\n\\f]", // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2) "*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] // or strings [capture 3 or capture 4]" "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", pseudos = ":(" + identifier + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: // 1. quoted (capture 3; capture 4 or capture 5) "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6) "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2) ".*" + ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rwhitespace = new RegExp( whitespace + "+", "g" ), rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), rdescend = new RegExp( whitespace + "|>" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = { "ID": new RegExp( "^#(" + identifier + ")" ), "CLASS": new RegExp( "^\\.(" + identifier + ")" ), "TAG": new RegExp( "^(" + identifier + "|[*])" ), "ATTR": new RegExp( "^" + attributes ), "PSEUDO": new RegExp( "^" + pseudos ), "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), // For use in libraries implementing .is() // We use this for POS matching in `select` "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, rhtml = /HTML$/i, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rnative = /^[^{]+\{\s*\[native \w/, // Easily-parseable/retrievable ID or TAG or CLASS selectors rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, // CSS escapes // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), funescape = function( escape, nonHex ) { var high = "0x" + escape.slice( 1 ) - 0x10000; return nonHex ? // Strip the backslash prefix from a non-hex escape sequence nonHex : // Replace a hexadecimal escape sequence with the encoded Unicode code point // Support: IE <=11+ // For values outside the Basic Multilingual Plane (BMP), manually construct a // surrogate pair high < 0 ? String.fromCharCode( high + 0x10000 ) : String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }, // CSS string/identifier serialization // https://drafts.csswg.org/cssom/#common-serializing-idioms rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, fcssescape = function( ch, asCodePoint ) { if ( asCodePoint ) { // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER if ( ch === "\0" ) { return "\uFFFD"; } // Control characters and (dependent upon position) numbers get escaped as code points return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; } // Other potentially-special ASCII characters get backslash-escaped return "\\" + ch; }, // Used for iframes // See setDocument() // Removing the function wrapper causes a "Permission Denied" // error in IE unloadHandler = function() { setDocument(); }, inDisabledFieldset = addCombinator( function( elem ) { return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; }, { dir: "parentNode", next: "legend" } ); // Optimize for push.apply( _, NodeList ) try { push.apply( ( arr = slice.call( preferredDoc.childNodes ) ), preferredDoc.childNodes ); // Support: Android<4.0 // Detect silently failing push.apply // eslint-disable-next-line no-unused-expressions arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { push = { apply: arr.length ? // Leverage slice if possible function( target, els ) { pushNative.apply( target, slice.call( els ) ); } : // Support: IE<9 // Otherwise append directly function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( ( target[ j++ ] = els[ i++ ] ) ) {} target.length = j - 1; } }; } function Sizzle( selector, context, results, seed ) { var m, i, elem, nid, match, groups, newSelector, newContext = context && context.ownerDocument, // nodeType defaults to 9, since context defaults to document nodeType = context ? context.nodeType : 9; results = results || []; // Return early from calls with invalid selector or context if ( typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { return results; } // Try to shortcut find operations (as opposed to filters) in HTML documents if ( !seed ) { setDocument( context ); context = context || document; if ( documentIsHTML ) { // If the selector is sufficiently simple, try using a "get*By*" DOM method // (excepting DocumentFragment context, where the methods don't exist) if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { // ID selector if ( ( m = match[ 1 ] ) ) { // Document context if ( nodeType === 9 ) { if ( ( elem = context.getElementById( m ) ) ) { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if ( elem.id === m ) { results.push( elem ); return results; } } else { return results; } // Element context } else { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if ( newContext && ( elem = newContext.getElementById( m ) ) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; } } // Type selector } else if ( match[ 2 ] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Class selector } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // Take advantage of querySelectorAll if ( support.qsa && !nonnativeSelectorCache[ selector + " " ] && ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && // Support: IE 8 only // Exclude object elements ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { newSelector = selector; newContext = context; // qSA considers elements outside a scoping root when evaluating child or // descendant combinators, which is not what we want. // In such cases, we work around the behavior by prefixing every selector in the // list with an ID selector referencing the scope context. // The technique has to be used as well when a leading combinator is used // as such selectors are not recognized by querySelectorAll. // Thanks to Andrew Dupont for this technique. if ( nodeType === 1 && ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { // Expand context for sibling selectors newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; // We can use :scope instead of the ID hack if the browser // supports it & if we're not changing the context. if ( newContext !== context || !support.scope ) { // Capture the context ID, setting it first if necessary if ( ( nid = context.getAttribute( "id" ) ) ) { nid = nid.replace( rcssescape, fcssescape ); } else { context.setAttribute( "id", ( nid = expando ) ); } } // Prefix every selector in the list groups = tokenize( selector ); i = groups.length; while ( i-- ) { groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + toSelector( groups[ i ] ); } newSelector = groups.join( "," ); } try { push.apply( results, newContext.querySelectorAll( newSelector ) ); return results; } catch ( qsaError ) { nonnativeSelectorCache( selector, true ); } finally { if ( nid === expando ) { context.removeAttribute( "id" ); } } } } } // All others return select( selector.replace( rtrim, "$1" ), context, results, seed ); } /** * Create key-value caches of limited size * @returns {function(string, object)} Returns the Object data after storing it on itself with * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) * deleting the oldest entry */ function createCache() { var keys = []; function cache( key, value ) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key + " " ) > Expr.cacheLength ) { // Only keep the most recent entries delete cache[ keys.shift() ]; } return ( cache[ key + " " ] = value ); } return cache; } /** * Mark a function for special use by Sizzle * @param {Function} fn The function to mark */ function markFunction( fn ) { fn[ expando ] = true; return fn; } /** * Support testing using an element * @param {Function} fn Passed the created element and returns a boolean result */ function assert( fn ) { var el = document.createElement( "fieldset" ); try { return !!fn( el ); } catch ( e ) { return false; } finally { // Remove from its parent by default if ( el.parentNode ) { el.parentNode.removeChild( el ); } // release memory in IE el = null; } } /** * Adds the same handler for all of the specified attrs * @param {String} attrs Pipe-separated list of attributes * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { var arr = attrs.split( "|" ), i = arr.length; while ( i-- ) { Expr.attrHandle[ arr[ i ] ] = handler; } } /** * Checks document order of two siblings * @param {Element} a * @param {Element} b * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b */ function siblingCheck( a, b ) { var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex; // Use IE sourceIndex if available on both nodes if ( diff ) { return diff; } // Check if b follows a if ( cur ) { while ( ( cur = cur.nextSibling ) ) { if ( cur === b ) { return -1; } } } return a ? 1 : -1; } /** * Returns a function to use in pseudos for input types * @param {String} type */ function createInputPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === type; }; } /** * Returns a function to use in pseudos for buttons * @param {String} type */ function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return ( name === "input" || name === "button" ) && elem.type === type; }; } /** * Returns a function to use in pseudos for :enabled/:disabled * @param {Boolean} disabled true for :disabled; false for :enabled */ function createDisabledPseudo( disabled ) { // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable return function( elem ) { // Only certain elements can match :enabled or :disabled // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled if ( "form" in elem ) { // Check for inherited disabledness on relevant non-disabled elements: // * listed form-associated elements in a disabled fieldset // https://html.spec.whatwg.org/multipage/forms.html#category-listed // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled // * option elements in a disabled optgroup // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled // All such elements have a "form" property. if ( elem.parentNode && elem.disabled === false ) { // Option elements defer to a parent optgroup if present if ( "label" in elem ) { if ( "label" in elem.parentNode ) { return elem.parentNode.disabled === disabled; } else { return elem.disabled === disabled; } } // Support: IE 6 - 11 // Use the isDisabled shortcut property to check for disabled fieldset ancestors return elem.isDisabled === disabled || // Where there is no isDisabled, check manually /* jshint -W018 */ elem.isDisabled !== !disabled && inDisabledFieldset( elem ) === disabled; } return elem.disabled === disabled; // Try to winnow out elements that can't be disabled before trusting the disabled property. // Some victims get caught in our net (label, legend, menu, track), but it shouldn't // even exist on them, let alone have a boolean value. } else if ( "label" in elem ) { return elem.disabled === disabled; } // Remaining elements are neither :enabled nor :disabled return false; }; } /** * Returns a function to use in pseudos for positionals * @param {Function} fn */ function createPositionalPseudo( fn ) { return markFunction( function( argument ) { argument = +argument; return markFunction( function( seed, matches ) { var j, matchIndexes = fn( [], seed.length, argument ), i = matchIndexes.length; // Match elements found at the specified indexes while ( i-- ) { if ( seed[ ( j = matchIndexes[ i ] ) ] ) { seed[ j ] = !( matches[ j ] = seed[ j ] ); } } } ); } ); } /** * Checks a node for validity as a Sizzle context * @param {Element|Object=} context * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext( context ) { return context && typeof context.getElementsByTagName !== "undefined" && context; } // Expose support vars for convenience support = Sizzle.support = {}; /** * Detects XML nodes * @param {Element|Object} elem An element or a document * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { var namespace = elem.namespaceURI, docElem = ( elem.ownerDocument || elem ).documentElement; // Support: IE <=8 // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes // https://bugs.jquery.com/ticket/4833 return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); }; /** * Sets document-related variables once based on the current document * @param {Element|Object} [doc] An element or document object to use to set the document * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { var hasCompare, subWindow, doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected // Support: IE 11+, Edge 17 - 18+ // IE/Edge sometimes th