0

body{background-color:white;}
(function() { // If window.HTMLWidgets is already defined, then use it; otherwise create a // new object. This allows preceding code to set options that affect the // initialization process (though none currently exist). window.HTMLWidgets = window.HTMLWidgets || {}; // See if we’re running in a viewer pane. If not, we’re in a web browser. var viewerMode = window.HTMLWidgets.viewerMode = /bviewer_pane=1b/.test(window.location); // See if we’re running in Shiny mode. If not, it’s a static document. // Note that static widgets can appear in both Shiny and static modes, but // obviously, Shiny widgets can only appear in Shiny apps/documents. var shinyMode = window.HTMLWidgets.shinyMode = typeof(window.Shiny) !== “undefined” && !!window.Shiny.outputBindings; // We can’t count on jQuery being available, so we implement our own // version if necessary. function querySelectorAll(scope, selector) { if (typeof(jQuery) !== “undefined” && scope instanceof jQuery) { return scope.find(selector); } if (scope.querySelectorAll) { return scope.querySelectorAll(selector); } } function asArray(value) { if (value === null) return []; if ($.isArray(value)) return value; return [value]; } // Implement jQuery’s extend function extend(target /*, … */) { if (arguments.length == 1) { return target; } for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var prop in source) { if (source.hasOwnProperty(prop)) { target[prop] = source[prop]; } } } return target; } // IE8 doesn't support Array.forEach. function forEach(values, callback, thisArg) { if (values.forEach) { values.forEach(callback, thisArg); } else { for (var i = 0; i < values.length; i++) { callback.call(thisArg, values[i], i, values); } } } // Replaces the specified method with the return value of funcSource. // // Note that funcSource should not BE the new method, it should be a function // that RETURNS the new method. funcSource receives a single argument that is // the overridden method, it can be called from the new method. The overridden // method can be called like a regular function, it has the target permanently // bound to it so "this" will work correctly. function overrideMethod(target, methodName, funcSource) { var superFunc = target[methodName] || function() {}; var superFuncBound = function() { return superFunc.apply(target, arguments); }; target[methodName] = funcSource(superFuncBound); } // Add a method to delegator that, when invoked, calls // delegatee.methodName. If there is no such method on // the delegatee, but there was one on delegator before // delegateMethod was called, then the original version // is invoked instead. // For example: // // var a = { // method1: function() { console.log('a1'); } // method2: function() { console.log('a2'); } // }; // var b = { // method1: function() { console.log('b1'); } // }; // delegateMethod(a, b, "method1"); // delegateMethod(a, b, "method2"); // a.method1(); // a.method2(); // // The output would be "b1", "a2". function delegateMethod(delegator, delegatee, methodName) { var inherited = delegator[methodName]; delegator[methodName] = function() { var target = delegatee; var method = delegatee[methodName]; // The method doesn't exist on the delegatee. Instead, // call the method on the delegator, if it exists. if (!method) { target = delegator; method = inherited; } if (method) { return method.apply(target, arguments); } }; } // Implement a vague facsimilie of jQuery's data method function elementData(el, name, value) { if (arguments.length == 2) { return el["htmlwidget_data_" + name]; } else if (arguments.length == 3) { el["htmlwidget_data_" + name] = value; return el; } else { throw new Error("Wrong number of arguments for elementData: " + arguments.length); } } // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex function escapeRegExp(str) { return str.replace(/[-[]/{}()*+?.\^$|]/g, “\$&”); } function hasClass(el, className) { var re = new RegExp(“\b” + escapeRegExp(className) + “\b”); return re.test(el.className); } // elements – array (or array-like object) of HTML elements // className – class name to test for // include – if true, only return elements with given className; // if false, only return elements *without* given className function filterByClass(elements, className, include) { var results = []; for (var i = 0; i < elements.length; i++) { if (hasClass(elements[i], className) == include) results.push(elements[i]); } return results; } function on(obj, eventName, func) { if (obj.addEventListener) { obj.addEventListener(eventName, func, false); } else if (obj.attachEvent) { obj.attachEvent(eventName, func); } } function off(obj, eventName, func) { if (obj.removeEventListener) obj.removeEventListener(eventName, func, false); else if (obj.detachEvent) { obj.detachEvent(eventName, func); } } // Translate array of values to top/right/bottom/left, as usual with // the "padding" CSS property // https://developer.mozilla.org/en-US/docs/Web/CSS/padding function unpackPadding(value) { if (typeof(value) === “number”) value = [value]; if (value.length === 1) { return {top: value[0], right: value[0], bottom: value[0], left: value[0]}; } if (value.length === 2) { return {top: value[0], right: value[1], bottom: value[0], left: value[1]}; } if (value.length === 3) { return {top: value[0], right: value[1], bottom: value[2], left: value[1]}; } if (value.length === 4) { return {top: value[0], right: value[1], bottom: value[2], left: value[3]}; } } // Convert an unpacked padding object to a CSS value function paddingToCss(paddingObj) { return paddingObj.top + “px ” + paddingObj.right + “px ” + paddingObj.bottom + “px ” + paddingObj.left + “px”; } // Makes a number suitable for CSS function px(x) { if (typeof(x) === “number”) return x + “px”; else return x; } // Retrieves runtime widget sizing information for an element. // The return value is either null, or an object with fill, padding, // defaultWidth, defaultHeight fields. function sizingPolicy(el) { var sizingEl = document.querySelector(“script[data-for='” + el.id + “‘][type=’application/htmlwidget-sizing’]”); if (!sizingEl) return null; var sp = JSON.parse(sizingEl.textContent || sizingEl.text || “{}”); if (viewerMode) { return sp.viewer; } else { return sp.browser; } } // @param tasks Array of strings (or falsy value, in which case no-op). // Each element must be a valid JavaScript expression that yields a // function. Or, can be an array of objects with “code” and “data” // properties; in this case, the “code” property should be a string // of JS that’s an expr that yields a function, and “data” should be // an object that will be added as an additional argument when that // function is called. // @param target The object that will be “this” for each function // execution. // @param args Array of arguments to be passed to the functions. (The // same arguments will be passed to all functions.) function evalAndRun(tasks, target, args) { if (tasks) { forEach(tasks, function(task) { var theseArgs = args; if (typeof(task) === “object”) { theseArgs = theseArgs.concat([task.data]); task = task.code; } var taskFunc = tryEval(task); if (typeof(taskFunc) !== “function”) { throw new Error(“Task must be a function! Source:n” + task); } taskFunc.apply(target, theseArgs); }); } } // Attempt eval() both with and without enclosing in parentheses. // Note that enclosing coerces a function declaration into // an expression that eval() can parse // (otherwise, a SyntaxError is thrown) function tryEval(code) { var result = null; try { result = eval(“(” + code + “)”); } catch(error) { if (!(error instanceof SyntaxError)) { throw error; } try { result = eval(code); } catch(e) { if (e instanceof SyntaxError) { throw error; } else { throw e; } } } return result; } function initSizing(el) { var sizing = sizingPolicy(el); if (!sizing) return; var cel = document.getElementById(“htmlwidget_container”); if (!cel) return; if (typeof(sizing.padding) !== “undefined”) { document.body.style.margin = “0”; document.body.style.padding = paddingToCss(unpackPadding(sizing.padding)); } if (sizing.fill) { document.body.style.overflow = “hidden”; document.body.style.width = “100%”; document.body.style.height = “100%”; document.documentElement.style.width = “100%”; document.documentElement.style.height = “100%”; cel.style.position = “absolute”; var pad = unpackPadding(sizing.padding); cel.style.top = pad.top + “px”; cel.style.right = pad.right + “px”; cel.style.bottom = pad.bottom + “px”; cel.style.left = pad.left + “px”; el.style.width = “100%”; el.style.height = “100%”; var rect = cel.getBoundingClientRect(); return { getWidth: function() { return rect.width; }, getHeight: function() { return rect.height; } }; } else { el.style.width = px(sizing.width); el.style.height = px(sizing.height); var rect = cel.getBoundingClientRect(); return { getWidth: function() { return rect.width; }, getHeight: function() { return rect.height; } }; } } // Default implementations for methods var defaults = { find: function(scope) { return querySelectorAll(scope, “.” + this.name); }, renderError: function(el, err) { var $el = $(el); this.clearError(el); // Add all these error classes, as Shiny does var errClass = “shiny-output-error”; if (err.type !== null) { // use the classes of the error condition as CSS class names errClass = errClass + ” ” + $.map(asArray(err.type), function(type) { return errClass + “-” + type; }).join(” “); } errClass = errClass + ” htmlwidgets-error”; // Is el inline or block? If inline or inline-block, just display:none it // and add an inline error. var display = $el.css(“display”); $el.data(“restore-display-mode”, display); if (display === “inline” || display === “inline-block”) { $el.hide(); if (err.message !== “”) { var errorSpan = $(“”).addClass(errClass); errorSpan.text(err.message); $el.after(errorSpan); } } else if (display === “block”) { // If block, add an error just after the el, set visibility:none on the // el, and position the error to be on top of the el. // Mark it with a unique ID and CSS class so we can remove it later. $el.css(“visibility”, “hidden”); if (err.message !== “”) { var errorDiv = $(“”).addClass(errClass).css(“position”, “absolute”) .css(“top”, el.offsetTop) .css(“left”, el.offsetLeft) // setting width can push out the page size, forcing otherwise // unnecessary scrollbars to appear and making it impossible for // the element to shrink; so use max-width instead .css(“maxWidth”, el.offsetWidth) .css(“height”, el.offsetHeight); errorDiv.text(err.message); $el.after(errorDiv); // Really dumb way to keep the size/position of the error in sync with // the parent element as the window is resized or whatever. var intId = setInterval(function() { if (!errorDiv[0].parentElement) { clearInterval(intId); return; } errorDiv .css(“top”, el.offsetTop) .css(“left”, el.offsetLeft) .css(“maxWidth”, el.offsetWidth) .css(“height”, el.offsetHeight); }, 500); } } }, clearError: function(el) { var $el = $(el); var display = $el.data(“restore-display-mode”); $el.data(“restore-display-mode”, null); if (display === “inline” || display === “inline-block”) { if (display) $el.css(“display”, display); $(el.nextSibling).filter(“.htmlwidgets-error”).remove(); } else if (display === “block”){ $el.css(“visibility”, “inherit”); $(el.nextSibling).filter(“.htmlwidgets-error”).remove(); } }, sizing: {} }; // Called by widget bindings to register a new type of widget. The definition // object can contain the following properties: // – name (required) – A string indicating the binding name, which will be // used by default as the CSS classname to look for. // – initialize (optional) – A function(el) that will be called once per // widget element; if a value is returned, it will be passed as the third // value to renderValue. // – renderValue (required) – A function(el, data, initValue) that will be // called with data. Static contexts will cause this to be called once per // element; Shiny apps will cause this to be called multiple times per // element, as the data changes. window.HTMLWidgets.widget = function(definition) { if (!definition.name) { throw new Error(“Widget must have a name”); } if (!definition.type) { throw new Error(“Widget must have a type”); } // Currently we only support output widgets if (definition.type !== “output”) { throw new Error(“Unrecognized widget type ‘” + definition.type + “‘”); } // TODO: Verify that .name is a valid CSS classname // Support new-style instance-bound definitions. Old-style class-bound // definitions have one widget “object” per widget per type/class of // widget; the renderValue and resize methods on such widget objects // take el and instance arguments, because the widget object can’t // store them. New-style instance-bound definitions have one widget // object per widget instance; the definition that’s passed in doesn’t // provide renderValue or resize methods at all, just the single method // factory(el, width, height) // which returns an object that has renderValue(x) and resize(w, h). // This enables a far more natural programming style for the widget // author, who can store per-instance state using either OO-style // instance fields or functional-style closure variables (I guess this // is in contrast to what can only be called C-style pseudo-OO which is // what we required before). if (definition.factory) { definition = createLegacyDefinitionAdapter(definition); } if (!definition.renderValue) { throw new Error(“Widget must have a renderValue function”); } // For static rendering (non-Shiny), use a simple widget registration // scheme. We also use this scheme for Shiny apps/documents that also // contain static widgets. window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || []; // Merge defaults into the definition; don’t mutate the original definition. var staticBinding = extend({}, defaults, definition); overrideMethod(staticBinding, “find”, function(superfunc) { return function(scope) { var results = superfunc(scope); // Filter out Shiny outputs, we only want the static kind return filterByClass(results, “html-widget-output”, false); }; }); window.HTMLWidgets.widgets.push(staticBinding); if (shinyMode) { // Shiny is running. Register the definition with an output binding. // The definition itself will not be the output binding, instead // we will make an output binding object that delegates to the // definition. This is because we foolishly used the same method // name (renderValue) for htmlwidgets definition and Shiny bindings // but they actually have quite different semantics (the Shiny // bindings receive data that includes lots of metadata that it // strips off before calling htmlwidgets renderValue). We can’t // just ignore the difference because in some widgets it’s helpful // to call this.renderValue() from inside of resize(), and if // we’re not delegating, then that call will go to the Shiny // version instead of the htmlwidgets version. // Merge defaults with definition, without mutating either. var bindingDef = extend({}, defaults, definition); // This object will be our actual Shiny binding. var shinyBinding = new Shiny.OutputBinding(); // With a few exceptions, we’ll want to simply use the bindingDef’s // version of methods if they are available, otherwise fall back to // Shiny’s defaults. NOTE: If Shiny’s output bindings gain additional // methods in the future, and we want them to be overrideable by // HTMLWidget binding definitions, then we’ll need to add them to this // list. delegateMethod(shinyBinding, bindingDef, “getId”); delegateMethod(shinyBinding, bindingDef, “onValueChange”); delegateMethod(shinyBinding, bindingDef, “onValueError”); delegateMethod(shinyBinding, bindingDef, “renderError”); delegateMethod(shinyBinding, bindingDef, “clearError”); delegateMethod(shinyBinding, bindingDef, “showProgress”); // The find, renderValue, and resize are handled differently, because we // want to actually decorate the behavior of the bindingDef methods. shinyBinding.find = function(scope) { var results = bindingDef.find(scope); // Only return elements that are Shiny outputs, not static ones var dynamicResults = results.filter(“.html-widget-output”); // It’s possible that whatever caused Shiny to think there might be // new dynamic outputs, also caused there to be new static outputs. // Since there might be lots of different htmlwidgets bindings, we // schedule execution for later–no need to staticRender multiple // times. if (results.length !== dynamicResults.length) scheduleStaticRender(); return dynamicResults; }; // Wrap renderValue to handle initialization, which unfortunately isn’t // supported natively by Shiny at the time of this writing. shinyBinding.renderValue = function(el, data) { Shiny.renderDependencies(data.deps); // Resolve strings marked as javascript literals to objects if (!(data.evals instanceof Array)) data.evals = [data.evals]; for (var i = 0; data.evals && i < data.evals.length; i++) { window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]); } if (!bindingDef.renderOnNullValue) { if (data.x === null) { el.style.visibility = "hidden"; return; } else { el.style.visibility = "inherit"; } } if (!elementData(el, "initialized")) { initSizing(el); elementData(el, "initialized", true); if (bindingDef.initialize) { var rect = el.getBoundingClientRect(); var result = bindingDef.initialize(el, rect.width, rect.height); elementData(el, "init_result", result); } } bindingDef.renderValue(el, data.x, elementData(el, "init_result")); evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]); }; // Only override resize if bindingDef implements it if (bindingDef.resize) { shinyBinding.resize = function(el, width, height) { // Shiny can call resize before initialize/renderValue have been // called, which doesn't make sense for widgets. if (elementData(el, "initialized")) { bindingDef.resize(el, width, height, elementData(el, "init_result")); } }; } Shiny.outputBindings.register(shinyBinding, bindingDef.name); } }; var scheduleStaticRenderTimerId = null; function scheduleStaticRender() { if (!scheduleStaticRenderTimerId) { scheduleStaticRenderTimerId = setTimeout(function() { scheduleStaticRenderTimerId = null; window.HTMLWidgets.staticRender(); }, 1); } } // Render static widgets after the document finishes loading // Statically render all elements that are of this widget's class window.HTMLWidgets.staticRender = function() { var bindings = window.HTMLWidgets.widgets || []; forEach(bindings, function(binding) { var matches = binding.find(document.documentElement); forEach(matches, function(el) { var sizeObj = initSizing(el, binding); var getSize = function(el) { if (sizeObj) { return {w: sizeObj.getWidth(), h: sizeObj.getHeight()} } else { var rect = el.getBoundingClientRect(); return {w: rect.width, h: rect.height} } }; if (hasClass(el, "html-widget-static-bound")) return; el.className = el.className + " html-widget-static-bound"; var initResult; if (binding.initialize) { var size = getSize(el); initResult = binding.initialize(el, size.w, size.h); elementData(el, "init_result", initResult); } if (binding.resize) { var lastSize = getSize(el); var resizeHandler = function(e) { var size = getSize(el); if (size.w === 0 && size.h === 0) return; if (size.w === lastSize.w && size.h === lastSize.h) return; lastSize = size; binding.resize(el, size.w, size.h, initResult); }; on(window, "resize", resizeHandler); // This is needed for cases where we're running in a Shiny // app, but the widget itself is not a Shiny output, but // rather a simple static widget. One example of this is // an rmarkdown document that has runtime:shiny and widget // that isn't in a render function. Shiny only knows to // call resize handlers for Shiny outputs, not for static // widgets, so we do it ourselves. if (window.jQuery) { window.jQuery(document).on( "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets", resizeHandler ); window.jQuery(document).on( "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets", resizeHandler ); } // This is needed for the specific case of ioslides, which // flips slides between display:none and display:block. // Ideally we would not have to have ioslide-specific code // here, but rather have ioslides raise a generic event, // but the rmarkdown package just went to CRAN so the // window to getting that fixed may be long. if (window.addEventListener) { // It's OK to limit this to window.addEventListener // browsers because ioslides itself only supports // such browsers. on(document, "slideenter", resizeHandler); on(document, "slideleave", resizeHandler); } } var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']"); if (scriptData) { var data = JSON.parse(scriptData.textContent || scriptData.text); // Resolve strings marked as javascript literals to objects if (!(data.evals instanceof Array)) data.evals = [data.evals]; for (var k = 0; data.evals && k = 3; } /* / Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery’s / on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now / really means $(setTimeout(fn)). / https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous / / Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny / one tick later than it did before, which means staticRender() is / called renderValue() earlier than (advanced) widget authors might be expecting. / https://github.com/rstudio/shiny/issues/2630 / / For a concrete example, leaflet has some methods (e.g., updateBounds) / which reference Shiny methods registered in initShiny (e.g., setInputValue). / Since leaflet is privy to this life-cycle, it knows to use setTimeout() to / delay execution of those methods (until Shiny methods are ready) / https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268 / / Ideally widget authors wouldn’t need to use this setTimeout() hack that / leaflet uses to call Shiny methods on a staticRender(). In the long run, / the logic initShiny should be broken up so that method registration happens / right away, but binding happens later. */ function maybeStaticRenderLater() { if (shinyMode && has_jQuery3()) { window.jQuery(window.HTMLWidgets.staticRender); } else { window.HTMLWidgets.staticRender(); } } if (document.addEventListener) { document.addEventListener(“DOMContentLoaded”, function() { document.removeEventListener(“DOMContentLoaded”, arguments.callee, false); maybeStaticRenderLater(); }, false); } else if (document.attachEvent) { document.attachEvent(“onreadystatechange”, function() { if (document.readyState === “complete”) { document.detachEvent(“onreadystatechange”, arguments.callee); maybeStaticRenderLater(); } }); } window.HTMLWidgets.getAttachmentUrl = function(depname, key) { // If no key, default to the first item if (typeof(key) === “undefined”) key = 1; var link = document.getElementById(depname + “-” + key + “-attachment”); if (!link) { throw new Error(“Attachment ” + depname + “/” + key + ” not found in document”); } return link.getAttribute(“href”); }; window.HTMLWidgets.dataframeToD3 = function(df) { var names = []; var length; for (var name in df) { if (df.hasOwnProperty(name)) names.push(name); if (typeof(df[name]) !== “object” || typeof(df[name].length) === “undefined”) { throw new Error(“All fields must be arrays”); } else if (typeof(length) !== “undefined” && length !== df[name].length) { throw new Error(“All fields must be arrays of the same length”); } length = df[name].length; } var results = []; var item; for (var row = 0; row < length; row++) { item = {}; for (var col = 0; col < names.length; col++) { item[names[col]] = df[names[col]][row]; } results.push(item); } return results; }; window.HTMLWidgets.transposeArray2D = function(array) { if (array.length === 0) return array; var newArray = array[0].map(function(col, i) { return array.map(function(row) { return row[i] }) }); return newArray; }; // Split value at splitChar, but allow splitChar to be escaped // using escapeChar. Any other characters escaped by escapeChar // will be included as usual (including escapeChar itself). function splitWithEscape(value, splitChar, escapeChar) { var results = []; var escapeMode = false; var currentResult = ""; for (var pos = 0; pos < value.length; pos++) { if (!escapeMode) { if (value[pos] === splitChar) { results.push(currentResult); currentResult = ""; } else if (value[pos] === escapeChar) { escapeMode = true; } else { currentResult += value[pos]; } } else { currentResult += value[pos]; escapeMode = false; } } if (currentResult !== "") { results.push(currentResult); } return results; } // Function authored by Yihui/JJ Allaire window.HTMLWidgets.evaluateStringMember = function(o, member) { var parts = splitWithEscape(member, '.', '\'); for (var i = 0, l = parts.length; i < l; i++) { var part = parts[i]; // part may be a character or 'numeric' member name if (o !== null && typeof o === "object" && part in o) { if (i == (l – 1)) { // if we are at the end of the line then evalulate if (typeof o[part] === "string") o[part] = tryEval(o[part]); } else { // otherwise continue to next embedded object o = o[part]; } } } }; // Retrieve the HTMLWidget instance (i.e. the return value of an // HTMLWidget binding's initialize() or factory() function) // associated with an element, or null if none. window.HTMLWidgets.getInstance = function(el) { return elementData(el, "init_result"); }; // Finds the first element in the scope that matches the selector, // and returns the HTMLWidget instance (i.e. the return value of // an HTMLWidget binding's initialize() or factory() function) // associated with that element, if any. If no element matches the // selector, or the first matching element has no HTMLWidget // instance associated with it, then null is returned. // // The scope argument is optional, and defaults to window.document. window.HTMLWidgets.find = function(scope, selector) { if (arguments.length == 1) { selector = scope; scope = document; } var el = scope.querySelector(selector); if (el === null) { return null; } else { return window.HTMLWidgets.getInstance(el); } }; // Finds all elements in the scope that match the selector, and // returns the HTMLWidget instances (i.e. the return values of // an HTMLWidget binding's initialize() or factory() function) // associated with the elements, in an array. If elements that // match the selector don't have an associated HTMLWidget // instance, the returned array will contain nulls. // // The scope argument is optional, and defaults to window.document. window.HTMLWidgets.findAll = function(scope, selector) { if (arguments.length == 1) { selector = scope; scope = document; } var nodes = scope.querySelectorAll(selector); var results = []; for (var i = 0; i a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for(“boolean”==typeof g&&(j=g,g=arguments[h]||{},h++),”object”==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h–);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:”jQuery”+(m+Math.random()).replace(/D/g,””),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return”function”===n.type(a)},isArray:Array.isArray||function(a){return”array”===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||”object”!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,”constructor”)&&!k.call(a.constructor.prototype,”isPrototypeOf”))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+””:”object”==typeof a||”function”==typeof a?i[j.call(a)]||”object”:typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,”ms-“).replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?””:(a+””).replace(o,””)},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,”string”==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return”string”==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),”function”==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each(“Boolean Number String Function Array Date RegExp Object Error Symbol”.split(” “),function(a,b){i[“[object “+b+”]”]=b.toLowerCase()});function s(a){var b=!!a&&”length”in a&&a.length,c=n.type(a);return”function”===c||n.isWindow(a)?!1:”array”===c||0===b||”number”==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=”sizzle”+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1′;var i=t.firstChild;return i.style.behavior=”url(#default#VML)”,i&&”object”==typeof i.adj}catch(t){return!1}}(),$i=(Object.freeze||Object)({ie:wi,ielt9:Li,edge:Pi,webkit:bi,android:Ti,android23:zi,androidStock:Ci,opera:Zi,chrome:Si,gecko:Ei,safari:ki,phantom:Ai,opera12:Ii,win:Bi,ie3d:Oi,webkit3d:Ri,gecko3d:Di,any3d:Ni,mobile:ji,mobileWebkit:Wi,mobileWebkit3d:Hi,msPointer:Fi,pointer:Ui,touch:Vi,mobileOpera:qi,mobileGecko:Gi,retina:Ki,canvas:Yi,svg:Xi,vml:Ji}),Qi=Fi?”MSPointerDown”:”pointerdown”,te=Fi?”MSPointerMove”:”pointermove”,ie=Fi?”MSPointerUp”:”pointerup”,ee=Fi?”MSPointerCancel”:”pointercancel”,ne=[“INPUT”,”SELECT”,”OPTION”],oe={},se=!1,re=0,ae=Fi?”MSPointerDown”:Ui?”pointerdown”:”touchstart”,he=Fi?”MSPointerUp”:Ui?”pointerup”:”touchend”,ue=”_leaflet_”,le=”_leaflet_events”,ce=Bi&&Si?2*window.devicePixelRatio:Ei?window.devicePixelRatio:1,_e={},de=(Object.freeze||Object)({on:V,off:q,stopPropagation:Y,disableScrollPropagation:X,disableClickPropagation:J,preventDefault:$,stop:Q,getMousePosition:tt,getWheelDelta:it,fakeStop:et,skipped:nt,isExternalTarget:ot,addListener:V,removeListener:q}),pe=xt([“transform”,”WebkitTransform”,”OTransform”,”MozTransform”,”msTransform”]),me=xt([“webkitTransition”,”transition”,”OTransition”,”MozTransition”,”msTransition”]),fe=”webkitTransition”===me||”OTransition”===me?me+”End”:”transitionend”;if(“onselectstart”in document)mi=function(){V(window,”selectstart”,$)},fi=function(){q(window,”selectstart”,$)};else{var ge=xt([“userSelect”,”WebkitUserSelect”,”OUserSelect”,”MozUserSelect”,”msUserSelect”]);mi=function(){if(ge){var t=document.documentElement.style;gi=t[ge],t[ge]=”none”}},fi=function(){ge&&(document.documentElement.style[ge]=gi,gi=void 0)}}var ve,ye,xe=(Object.freeze||Object)({TRANSFORM:pe,TRANSITION:me,TRANSITION_END:fe,get:rt,getStyle:at,create:ht,remove:ut,empty:lt,toFront:ct,toBack:_t,hasClass:dt,addClass:pt,removeClass:mt,setClass:ft,getClass:gt,setOpacity:vt,testProp:xt,setTransform:wt,setPosition:Lt,getPosition:Pt,disableTextSelection:mi,enableTextSelection:fi,disableImageDrag:bt,enableImageDrag:Tt,preventOutline:zt,restoreOutline:Mt}),we=ui.extend({run:function(t,i,e,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=e||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=Pt(t),this._offset=i.subtract(this._startPos),this._startTime=+new Date,this.fire(“start”),this._animate()},stop:function(){this._inProgress&&(this._step(!0),this._complete())},_animate:function(){this._animId=f(this._animate,this),this._step()},_step:function(t){var i=+new Date-this._startTime,e=1e3*this._duration;i0&&this._map.getContainer().focus()}}),be=function(t){return new Pe(t)};Le.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.remove(),this},_initControlPos:function(){function t(t,o){var s=e+t+” “+e+o;i[t+o]=ht(“div”,s,n)}var i=this._controlCorners={},e=”leaflet-“,n=this._controlContainer=ht(“div”,e+”control-container”,this._container);t(“top”,”left”),t(“top”,”right”),t(“bottom”,”left”),t(“bottom”,”right”)},_clearControlPos:function(){for(var t in this._controlCorners)ut(this._controlCorners[t]);ut(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var Te=Pe.extend({options:{collapsed:!0,position:”topright”,autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(t,i,e,n){return e1)this._moved=!0;else{var i=t.touches&&1===t.touches.length?t.touches[0]:t,e=new x(i.clientX,i.clientY).subtract(this._startPoint);(e.x||e.y)&&(Math.abs(e.x)+Math.abs(e.y)’)}}catch(t){return function(t){return document.createElement(“1 base layers are visible; if so, hide all but the first one if (_this4.hasLayer(layer)) { if (firstLayer) { firstLayer = false; } else { _this4.removeLayer(layer); } } } }); var overlay = {}; _jquery2[“default”].each((0, _util.asArray)(overlayGroups), function (i, g) { var layer = _this4.layerManager.getLayerGroup(g, true); if (layer) { overlay[g] = layer; } }); this.currentLayersControl = _leaflet2[“default”].control.layers(base, overlay, options); this.addControl(this.currentLayersControl);
}; methods.removeLayersControl = function () { if (this.currentLayersControl) { this.removeControl(this.currentLayersControl); this.currentLayersControl = null; }
}; methods.addScaleBar = function (options) { // Only allow one scale bar at a time methods.removeScaleBar.call(this); var scaleBar = _leaflet2[“default”].control.scale(options).addTo(this); this.currentScaleBar = scaleBar;
}; methods.removeScaleBar = function () { if (this.currentScaleBar) { this.currentScaleBar.remove(); this.currentScaleBar = null; }
}; methods.hideGroup = function (group) { var _this5 = this; _jquery2[“default”].each((0, _util.asArray)(group), function (i, g) { var layer = _this5.layerManager.getLayerGroup(g, true); if (layer) { _this5.removeLayer(layer); } });
}; methods.showGroup = function (group) { var _this6 = this; _jquery2[“default”].each((0, _util.asArray)(group), function (i, g) { var layer = _this6.layerManager.getLayerGroup(g, true); if (layer) { _this6.addLayer(layer); } });
}; function setupShowHideGroupsOnZoom(map) { if (map.leafletr._hasInitializedShowHideGroups) { return; } map.leafletr._hasInitializedShowHideGroups = true; function setVisibility(layer, visible, group) { if (visible !== map.hasLayer(layer)) { if (visible) { map.addLayer(layer); map.fire(“groupadd”, { “name”: group, “layer”: layer }); } else { map.removeLayer(layer); map.fire(“groupremove”, { “name”: group, “layer”: layer }); } } } function showHideGroupsOnZoom() { if (!map.layerManager) return; var zoom = map.getZoom(); map.layerManager.getAllGroupNames().forEach(function (group) { var layer = map.layerManager.getLayerGroup(group, false); if (layer && typeof layer.zoomLevels !== “undefined”) { setVisibility(layer, layer.zoomLevels === true || layer.zoomLevels.indexOf(zoom) >= 0, group); } }); } map.showHideGroupsOnZoom = showHideGroupsOnZoom; map.on(“zoomend”, showHideGroupsOnZoom);
} methods.setGroupOptions = function (group, options) { var _this7 = this; _jquery2[“default”].each((0, _util.asArray)(group), function (i, g) { var layer = _this7.layerManager.getLayerGroup(g, true); // This slightly tortured check is because 0 is a valid value for zoomLevels if (typeof options.zoomLevels !== “undefined” && options.zoomLevels !== null) { layer.zoomLevels = (0, _util.asArray)(options.zoomLevels); } }); setupShowHideGroupsOnZoom(this); this.showHideGroupsOnZoom();
}; methods.addRasterImage = function (uri, bounds, opacity, attribution, layerId, group) { // uri is a data URI containing an image. We want to paint this image as a // layer at (top-left) bounds[0] to (bottom-right) bounds[1]. // We can’t simply use ImageOverlay, as it uses bilinear scaling which looks // awful as you zoom in (and sometimes shifts positions or disappears). // Instead, we’ll use a TileLayer.Canvas to draw pieces of the image. // First, some helper functions. // degree2tile converts latitude, longitude, and zoom to x and y tile // numbers. The tile numbers returned can be non-integral, as there’s no // reason to expect that the lat/lng inputs are exactly on the border of two // tiles. // // We’ll use this to convert the bounds we got from the server, into coords // in tile-space at a given zoom level. Note that once we do the conversion, // we don’t to do any more trigonometry to convert between pixel coordinates // and tile coordinates; the source image pixel coords, destination canvas // pixel coords, and tile coords all can be scaled linearly. function degree2tile(lat, lng, zoom) { // See http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames var latRad = lat * Math.PI / 180; var n = Math.pow(2, zoom); var x = (lng + 180) / 360 * n; var y = (1 – Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2 * n; return { x: x, y: y }; } // Given a range [from,to) and either one or two numbers, returns true if // there is any overlap between [x,x1) and the range–or if x1 is omitted, // then returns true if x is within [from,to). function overlap(from, to, x, /* optional */ x1) { if (arguments.length == 3) x1 = x; return x = from; } function getCanvasSmoothingProperty(ctx) { var candidates = [“imageSmoothingEnabled”, “mozImageSmoothingEnabled”, “webkitImageSmoothingEnabled”, “msImageSmoothingEnabled”]; for (var i = 0; i < candidates.length; i++) { if (typeof ctx[candidates[i]] !== "undefined") { return candidates[i]; } } return null; } // Our general strategy is to: // 1. Load the data URI in an Image() object, so we can get its pixel // dimensions and the underlying image data. (We could have done this // by not encoding as PNG at all but just send an array of RGBA values // from the server, but that would inflate the JSON too much.) // 2. Create a hidden canvas that we use just to extract the image data // from the Image (using Context2D.getImageData()). // 3. Create a TileLayer.Canvas and add it to the map. // We want to synchronously create and attach the TileLayer.Canvas (so an // immediate call to clearRasters() will be respected, for example), but // Image loads its data asynchronously. Fortunately we can resolve this // by putting TileLayer.Canvas into async mode, which will let us create // and attach the layer but have it wait until the image is loaded before // it actually draws anything. // These are the variables that we will populate once the image is loaded. var imgData = null; // 1d row-major array, four [0-255] integers per pixel var imgDataMipMapper = null; var w = null; // image width in pixels var h = null; // image height in pixels // We'll use this array to store callbacks that need to be invoked once // imgData, w, and h have been resolved. var imgDataCallbacks = []; // Consumers of imgData, w, and h can call this to be notified when data // is available. function getImageData(callback) { if (imgData != null) { // Must not invoke the callback immediately; it's too confusing and // fragile to have a function invoke the callback *either* immediately // or in the future. Better to be consistent here. setTimeout(function () { callback(imgData, w, h, imgDataMipMapper); }, 0); } else { imgDataCallbacks.push(callback); } } var img = new Image(); img.onload = function () { // Save size w = img.width; h = img.height; // Create a dummy canvas to extract the image data var imgDataCanvas = document.createElement("canvas"); imgDataCanvas.width = w; imgDataCanvas.height = h; imgDataCanvas.style.display = "none"; document.body.appendChild(imgDataCanvas); var imgDataCtx = imgDataCanvas.getContext("2d"); imgDataCtx.drawImage(img, 0, 0); // Save the image data. imgData = imgDataCtx.getImageData(0, 0, w, h).data; imgDataMipMapper = new _mipmapper2["default"](img); // Done with the canvas, remove it from the page so it can be gc'd. document.body.removeChild(imgDataCanvas); // Alert any getImageData callers who are waiting. for (var i = 0; i = 256 && imgRes.y >= 256) { // Use built-in scaling // Turn off anti-aliasing if necessary if (smoothingProperty) { ctx[smoothingProperty] = imgRes.x >= 256 && imgRes.y >= 256; } // Don’t necessarily draw with the full-size image; if we’re // downscaling, use the mipmapper to get a pre-downscaled image // (see comments on Mipmapper class for why this matters). mipmapper.getBySize(extent.x * 256, extent.y * 256, function (mip) { // It’s possible that the image will go off the edge of the canvas– // that’s OK, the canvas should clip appropriately. ctx.drawImage(mip, // Convert abs tile coords to rel tile coords, then *256 to convert // to rel pixel coords (topLeft.x – tilePoint.x) * 256, (topLeft.y – tilePoint.y) * 256, // Always draw the whole thing and let canvas clip; so we can just // convert from size in tile coords straight to pixels extent.x * 256, extent.y * 256); }); } else { // Use manual nearest-neighbor interpolation // Calculate the source image pixel coordinates that correspond with // the top-left and bottom-right of this tile. (If the source image // only partially overlaps the tile, we use max/min to limit the // sourceStart/End to only reflect the overlapping portion.) var sourceStart = { x: Math.max(0, Math.floor((tilePoint.x – topLeft.x) * imgRes.x)), y: Math.max(0, Math.floor((tilePoint.y – topLeft.y) * imgRes.y)) }; var sourceEnd = { x: Math.min(w, Math.ceil((tilePoint.x + 1 – topLeft.x) * imgRes.x)), y: Math.min(h, Math.ceil((tilePoint.y + 1 – topLeft.y) * imgRes.y)) }; // The size, in dest pixels, that each source pixel should occupy. // This might be greater or less than 1 (e.g. if x and y resolution // are very different). var pixelSize = { x: 256 / imgRes.x, y: 256 / imgRes.y }; // For each pixel in the source image that overlaps the tile… for (var row = sourceStart.y; row < sourceEnd.y; row++) { for (var col = sourceStart.x; col < sourceEnd.x; col++) { // …extract the pixel data… var i = (row * w + col) * 4; var r = imgData[i]; var g = imgData[i + 1]; var b = imgData[i + 2]; var a = imgData[i + 3]; ctx.fillStyle = "rgba(" + [r, g, b, a / 255].join(",") + ")"; // …calculate the corresponding pixel coord in the dest image // where it should be drawn… var pixelPos = { x: (col / imgRes.x + topLeft.x – tilePoint.x) * 256, y: (row / imgRes.y + topLeft.y – tilePoint.y) * 256 }; // …and draw a rectangle there. ctx.fillRect(Math.round(pixelPos.x), Math.round(pixelPos.y), // Looks crazy, but this is necessary to prevent rounding from // causing overlap between this rect and its neighbors. The // minuend is the location of the next pixel, while the // subtrahend is the position of the current pixel (to turn an // absolute coordinate to a width/height). Yes, I had to look // up minuend and subtrahend. Math.round(pixelPos.x + pixelSize.x) – Math.round(pixelPos.x), Math.round(pixelPos.y + pixelSize.y) – Math.round(pixelPos.y)); } } } } catch (e) { error = e; } finally { done(error, canvas); } }); return canvas; }; this.layerManager.addLayer(canvasTiles, "image", layerId, group);
}; methods.removeImage = function (layerId) { this.layerManager.removeLayer("image", layerId);
}; methods.clearImages = function () { this.layerManager.clearLayers("image");
}; methods.addMeasure = function (options) { // if a measureControl already exists, then remove it and // replace with a new one methods.removeMeasure.call(this); this.measureControl = _leaflet2["default"].control.measure(options); this.addControl(this.measureControl);
}; methods.removeMeasure = function () { if (this.measureControl) { this.removeControl(this.measureControl); this.measureControl = null; }
}; methods.addSelect = function (ctGroup) { var _this8 = this; methods.removeSelect.call(this); this._selectButton = _leaflet2["default"].easyButton({ states: [{ stateName: "select-inactive", icon: "ion-qr-scanner", title: "Make a selection", onClick: function onClick(btn, map) { btn.state("select-active"); _this8._locationFilter = new _leaflet2["default"].LocationFilter2(); if (ctGroup) { var selectionHandle = new global.crosstalk.SelectionHandle(ctGroup); selectionHandle.on("change", function (e) { if (e.sender !== selectionHandle) { if (_this8._locationFilter) { _this8._locationFilter.disable(); btn.state("select-inactive"); } } }); var handler = function handler(e) { _this8.layerManager.brush(_this8._locationFilter.getBounds(), { sender: selectionHandle }); }; _this8._locationFilter.on("enabled", handler); _this8._locationFilter.on("change", handler); _this8._locationFilter.on("disabled", function () { selectionHandle.close(); _this8._locationFilter = null; }); } _this8._locationFilter.addTo(map); } }, { stateName: "select-active", icon: "ion-close-round", title: "Dismiss selection", onClick: function onClick(btn, map) { btn.state("select-inactive"); _this8._locationFilter.disable(); // If explicitly dismissed, clear the crosstalk selections _this8.layerManager.unbrush(); } }] }); this._selectButton.addTo(this);
}; methods.removeSelect = function () { if (this._locationFilter) { this._locationFilter.disable(); } if (this._selectButton) { this.removeControl(this._selectButton); this._selectButton = null; }
}; methods.createMapPane = function (name, zIndex) { this.createPane(name); this.getPane(name).style.zIndex = zIndex;
}; }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./cluster-layer-store":1,"./crs_utils":3,"./dataframe":4,"./global/htmlwidgets":8,"./global/jquery":9,"./global/leaflet":10,"./global/shiny":12,"./mipmapper":16,"./util":17}],16:[function(require,module,exports){
"use strict"; Object.defineProperty(exports, "__esModule", { value: true
}); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } // This class simulates a mipmap, which shrinks images by powers of two. This
// stepwise reduction results in "pixel-perfect downscaling" (where every
// pixel of the original image has some contribution to the downscaled image)
// as opposed to a single-step downscaling which will discard a lot of data
// (and with sparse images at small scales can give very surprising results).
var Mipmapper = /*#__PURE__*/function () { function Mipmapper(img) { _classCallCheck(this, Mipmapper); this._layers = [img]; } // The various functions on this class take a callback function BUT MAY OR MAY // NOT actually behave asynchronously. _createClass(Mipmapper, [{ key: "getBySize", value: function getBySize(desiredWidth, desiredHeight, callback) { var _this = this; var i = 0; var lastImg = this._layers[0]; var testNext = function testNext() { _this.getByIndex(i, function (img) { // If current image is invalid (i.e. too small to be rendered) or // it's smaller than what we wanted, return the last known good image. if (!img || img.width < desiredWidth || img.height < desiredHeight) { callback(lastImg); return; } else { lastImg = img; i++; testNext(); return; } }); }; testNext(); } }, { key: "getByIndex", value: function getByIndex(i, callback) { var _this2 = this; if (this._layers[i]) { callback(this._layers[i]); return; } this.getByIndex(i – 1, function (prevImg) { if (!prevImg) { // prevImg could not be calculated (too small, possibly) callback(null); return; } if (prevImg.width < 2 || prevImg.height < 2) { // Can't reduce this image any further callback(null); return; } // If reduce ever becomes truly asynchronous, we should stuff a promise or // something into this._layers[i] before calling this.reduce(), to prevent // redundant reduce operations from happening. _this2.reduce(prevImg, function (reducedImg) { _this2._layers[i] = reducedImg; callback(reducedImg); return; }); }); } }, { key: "reduce", value: function reduce(img, callback) { var imgDataCanvas = document.createElement("canvas"); imgDataCanvas.width = Math.ceil(img.width / 2); imgDataCanvas.height = Math.ceil(img.height / 2); imgDataCanvas.style.display = "none"; document.body.appendChild(imgDataCanvas); try { var imgDataCtx = imgDataCanvas.getContext("2d"); imgDataCtx.drawImage(img, 0, 0, img.width / 2, img.height / 2); callback(imgDataCanvas); } finally { document.body.removeChild(imgDataCanvas); } } }]); return Mipmapper;
}(); exports["default"] = Mipmapper; },{}],17:[function(require,module,exports){
"use strict"; Object.defineProperty(exports, "__esModule", { value: true
});
exports.log = log;
exports.recycle = recycle;
exports.asArray = asArray; function log(message) { /* eslint-disable no-console */ if (console && console.log) console.log(message); /* eslint-enable no-console */
} function recycle(values, length, inPlace) { if (length === 0 && !inPlace) return []; if (!(values instanceof Array)) { if (inPlace) { throw new Error("Can't do in-place recycling of a non-Array value"); } values = [values]; } if (typeof length === "undefined") length = values.length; var dest = inPlace ? values : []; var origLength = values.length; while (dest.length length) { dest.splice(length, dest.length – length); } return dest;
} function asArray(value) { if (value instanceof Array) return value;else return [value];
} },{}]},{},[13]); (function (root, factory) { if (typeof define === ‘function’ && define.amd) { // AMD. Register as an anonymous module. define([‘leaflet’], factory); } else if (typeof modules === ‘object’ && module.exports) { // define a Common JS module that relies on ‘leaflet’ module.exports = factory(require(‘leaflet’)); } else { // Assume Leaflet is loaded into global object L already factory(L); }
}(this, function (L) { ‘use strict’; L.TileLayer.Provider = L.TileLayer.extend({ initialize: function (arg, options) { var providers = L.TileLayer.Provider.providers; var parts = arg.split(‘.’); var providerName = parts[0]; var variantName = parts[1]; if (!providers[providerName]) { throw ‘No such provider (‘ + providerName + ‘)’; } var provider = { url: providers[providerName].url, options: providers[providerName].options }; // overwrite values in provider from variant. if (variantName && ‘variants’ in providers[providerName]) { if (!(variantName in providers[providerName].variants)) { throw ‘No such variant of ‘ + providerName + ‘ (‘ + variantName + ‘)’; } var variant = providers[providerName].variants[variantName]; var variantOptions; if (typeof variant === ‘string’) { variantOptions = { variant: variant }; } else { variantOptions = variant.options; } provider = { url: variant.url || provider.url, options: L.Util.extend({}, provider.options, variantOptions) }; } // replace attribution placeholders with their values from toplevel provider attribution, // recursively var attributionReplacer = function (attr) { if (attr.indexOf(‘{attribution.’) === -1) { return attr; } return attr.replace(/{attribution.(w*)}/g, function (match, attributionName) { return attributionReplacer(providers[attributionName].options.attribution); } ); }; provider.options.attribution = attributionReplacer(provider.options.attribution); // Compute final options combining provider options with any user overrides var layerOpts = L.Util.extend({}, provider.options, options); L.TileLayer.prototype.initialize.call(this, provider.url, layerOpts); } }); /** * Definition of providers. * see http://leafletjs.com/reference.html#tilelayer for options in the options map. */ L.TileLayer.Provider.providers = { OpenStreetMap: { url: ‘//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png’, options: { maxZoom: 19, attribution: ‘© OpenStreetMap contributors’ }, variants: { Mapnik: {}, DE: { url: ‘//{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png’, options: { maxZoom: 18 } }, CH: { url: ‘//tile.osm.ch/switzerland/{z}/{x}/{y}.png’, options: { maxZoom: 18, bounds: [[45, 5], [48, 11]] } }, France: { url: ‘//{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png’, options: { maxZoom: 20, attribution: ‘© Openstreetmap France | {attribution.OpenStreetMap}’ } }, HOT: { url: ‘//{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png’, options: { attribution: ‘{attribution.OpenStreetMap}, ‘ + ‘Tiles style by Humanitarian OpenStreetMap Team ‘ + ‘hosted by OpenStreetMap France‘ } }, BZH: { url: ‘//tile.openstreetmap.bzh/br/{z}/{x}/{y}.png’, options: { attribution: ‘{attribution.OpenStreetMap}, Tiles courtesy of Breton OpenStreetMap Team‘, bounds: [[46.2, -5.5], [50, 0.7]] } } } }, OpenSeaMap: { url: ‘//tiles.openseamap.org/seamark/{z}/{x}/{y}.png’, options: { attribution: ‘Map data: © OpenSeaMap contributors’ } }, OpenPtMap: { url: ‘http://openptmap.org/tiles/{z}/{x}/{y}.png’, options: { maxZoom: 17, attribution: ‘Map data: © OpenPtMap contributors’ } }, OpenTopoMap: { url: ‘https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png’, options: { maxZoom: 17, attribution: ‘Map data: {attribution.OpenStreetMap}, SRTM | Map style: © OpenTopoMap (CC-BY-SA)’ } }, OpenRailwayMap: { url: ‘https://{s}.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png’, options: { maxZoom: 19, attribution: ‘Map data: {attribution.OpenStreetMap} | Map style: © OpenRailwayMap (CC-BY-SA)’ } }, OpenFireMap: { url: ‘http://openfiremap.org/hytiles/{z}/{x}/{y}.png’, options: { maxZoom: 19, attribution: ‘Map data: {attribution.OpenStreetMap} | Map style: © OpenFireMap (CC-BY-SA)’ } }, SafeCast: { url: ‘//s3.amazonaws.com/te512.safecast.org/{z}/{x}/{y}.png’, options: { maxZoom: 16, attribution: ‘Map data: {attribution.OpenStreetMap} | Map style: © SafeCast (CC-BY-SA)’ } }, Thunderforest: { url: ‘https://{s}.tile.thunderforest.com/{variant}/{z}/{x}/{y}.png?apikey={apikey}’, options: { attribution: ‘© Thunderforest, {attribution.OpenStreetMap}’, variant: ‘cycle’, apikey: ”, maxZoom: 22 }, variants: { OpenCycleMap: ‘cycle’, Transport: { options: { variant: ‘transport’ } }, TransportDark: { options: { variant: ‘transport-dark’ } }, SpinalMap: { options: { variant: ‘spinal-map’ } }, Landscape: ‘landscape’, Outdoors: ‘outdoors’, Pioneer: ‘pioneer’, MobileAtlas: ‘mobile-atlas’, Neighbourhood: ‘neighbourhood’ } }, OpenMapSurfer: { url: ‘https://maps.heigit.org/openmapsurfer/tiles/{variant}/webmercator/{z}/{x}/{y}.png’, options: { maxZoom: 19, variant: ‘roads’, attribution: ‘Imagery from GIScience Research Group @ University of Heidelberg | Map data ‘ }, variants: { Roads: { options: { variant: ‘roads’, attribution: ‘{attribution.OpenMapSurfer}{attribution.OpenStreetMap}’ } }, Hybrid: { options: { variant: ‘hybrid’, attribution: ‘{attribution.OpenMapSurfer}{attribution.OpenStreetMap}’ } }, AdminBounds: { options: { variant: ‘adminb’, maxZoom: 18, attribution: ‘{attribution.OpenMapSurfer}{attribution.OpenStreetMap}’ } }, ContourLines: { options: { variant: ‘asterc’, maxZoom: 18, minZoom: 13, attribution: ‘{attribution.OpenMapSurfer} ASTER GDEM‘ } }, Hillshade: { options: { variant: ‘asterh’, maxZoom: 18, attribution: ‘{attribution.OpenMapSurfer} ASTER GDEM, SRTM‘ } }, ElementsAtRisk: { options: { variant: ‘elements_at_risk’, attribution: ‘{attribution.OpenMapSurfer}{attribution.OpenStreetMap}’ } } } }, Hydda: { url: ‘//{s}.tile.openstreetmap.se/hydda/{variant}/{z}/{x}/{y}.png’, options: { maxZoom: 18, variant: ‘full’, attribution: ‘Tiles courtesy of OpenStreetMap Sweden — Map data {attribution.OpenStreetMap}’ }, variants: { Full: ‘full’, Base: ‘base’, RoadsAndLabels: ‘roads_and_labels’ } }, MapBox: { url: ‘https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}{r}.png?access_token={accessToken}’, options: { attribution: ‘© Mapbox ‘ + ‘{attribution.OpenStreetMap} ‘ + ‘Improve this map‘, subdomains: ‘abcd’, id: ‘mapbox.streets’, accessToken: ”, } }, Stamen: { url: ‘//stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}{r}.{ext}’, options: { attribution: ‘Map tiles by Stamen Design, ‘ + ‘CC BY 3.0 — ‘ + ‘Map data {attribution.OpenStreetMap}’, subdomains: ‘abcd’, minZoom: 0, maxZoom: 20, variant: ‘toner’, ext: ‘png’ }, variants: { Toner: ‘toner’, TonerBackground: ‘toner-background’, TonerHybrid: ‘toner-hybrid’, TonerLines: ‘toner-lines’, TonerLabels: ‘toner-labels’, TonerLite: ‘toner-lite’, Watercolor: { url: ‘//stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}.{ext}’, options: { variant: ‘watercolor’, ext: ‘jpg’, minZoom: 1, maxZoom: 16 } }, Terrain: { options: { variant: ‘terrain’, minZoom: 0, maxZoom: 18 } }, TerrainBackground: { options: { variant: ‘terrain-background’, minZoom: 0, maxZoom: 18 } }, TerrainLabels: { options: { variant: ‘terrain-labels’, minZoom: 0, maxZoom: 18 } }, TopOSMRelief: { url: ‘//stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}.{ext}’, options: { variant: ‘toposm-color-relief’, ext: ‘jpg’, bounds: [[22, -132], [51, -56]] } }, TopOSMFeatures: { options: { variant: ‘toposm-features’, bounds: [[22, -132], [51, -56]], opacity: 0.9 } } } }, TomTom: { url: ‘https://{s}.api.tomtom.com/map/1/tile/{variant}/{style}/{z}/{x}/{y}.{ext}?key={apikey}’, options: { variant: ‘basic’, maxZoom: 22, attribution: ‘© 1992 – ‘ + new Date().getFullYear() + ‘ TomTom. ‘, subdomains: ‘abcd’, style: ‘main’, ext: ‘png’, apikey: ”, }, variants: { Basic: ‘basic’, Hybrid: ‘hybrid’, Labels: ‘labels’ } }, Esri: { url: ‘//server.arcgisonline.com/ArcGIS/rest/services/{variant}/MapServer/tile/{z}/{y}/{x}’, options: { variant: ‘World_Street_Map’, attribution: ‘Tiles © Esri’ }, variants: { WorldStreetMap: { options: { attribution: ‘{attribution.Esri} — ‘ + ‘Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012’ } }, DeLorme: { options: { variant: ‘Specialty/DeLorme_World_Base_Map’, minZoom: 1, maxZoom: 11, attribution: ‘{attribution.Esri} — Copyright: ©2012 DeLorme’ } }, WorldTopoMap: { options: { variant: ‘World_Topo_Map’, attribution: ‘{attribution.Esri} — ‘ + ‘Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community’ } }, WorldImagery: { options: { variant: ‘World_Imagery’, attribution: ‘{attribution.Esri} — ‘ + ‘Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community’ } }, WorldTerrain: { options: { variant: ‘World_Terrain_Base’, maxZoom: 13, attribution: ‘{attribution.Esri} — ‘ + ‘Source: USGS, Esri, TANA, DeLorme, and NPS’ } }, WorldShadedRelief: { options: { variant: ‘World_Shaded_Relief’, maxZoom: 13, attribution: ‘{attribution.Esri} — Source: Esri’ } }, WorldPhysical: { options: { variant: ‘World_Physical_Map’, maxZoom: 8, attribution: ‘{attribution.Esri} — Source: US National Park Service’ } }, OceanBasemap: { options: { variant: ‘Ocean_Basemap’, maxZoom: 13, attribution: ‘{attribution.Esri} — Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri’ } }, NatGeoWorldMap: { options: { variant: ‘NatGeo_World_Map’, maxZoom: 16, attribution: ‘{attribution.Esri} — National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC’ } }, WorldGrayCanvas: { options: { variant: ‘Canvas/World_Light_Gray_Base’, maxZoom: 16, attribution: ‘{attribution.Esri} — Esri, DeLorme, NAVTEQ’ } } } }, OpenWeatherMap: { url: ‘http://{s}.tile.openweathermap.org/map/{variant}/{z}/{x}/{y}.png?appid={apiKey}’, options: { maxZoom: 19, attribution: ‘Map data © OpenWeatherMap‘, apiKey:”, opacity: 0.5 }, variants: { Clouds: ‘clouds’, CloudsClassic: ‘clouds_cls’, Precipitation: ‘precipitation’, PrecipitationClassic: ‘precipitation_cls’, Rain: ‘rain’, RainClassic: ‘rain_cls’, Pressure: ‘pressure’, PressureContour: ‘pressure_cntr’, Wind: ‘wind’, Temperature: ‘temp’, Snow: ‘snow’ } }, HERE: { /* * HERE maps, formerly Nokia maps. * These basemaps are free, but you need an API key. Please sign up at * https://developer.here.com/plans */ url: ‘https://{s}.{base}.maps.api.here.com/maptile/2.1/’ + ‘{type}/{mapID}/{variant}/{z}/{x}/{y}/{size}/{format}?’ + ‘app_id={app_id}&app_code={app_code}&lg={language}’, options: { attribution: ‘Map © 1987-‘ + new Date().getFullYear() + ‘ HERE‘, subdomains: ‘1234’, mapID: ‘newest’, ‘app_id’: ”, ‘app_code’: ”, base: ‘base’, variant: ‘normal.day’, maxZoom: 20, type: ‘maptile’, language: ‘eng’, format: ‘png8’, size: ‘256’ }, variants: { normalDay: ‘normal.day’, normalDayCustom: ‘normal.day.custom’, normalDayGrey: ‘normal.day.grey’, normalDayMobile: ‘normal.day.mobile’, normalDayGreyMobile: ‘normal.day.grey.mobile’, normalDayTransit: ‘normal.day.transit’, normalDayTransitMobile: ‘normal.day.transit.mobile’, normalDayTraffic: { options: { variant: ‘normal.traffic.day’, base: ‘traffic’, type: ‘traffictile’ } }, normalNight: ‘normal.night’, normalNightMobile: ‘normal.night.mobile’, normalNightGrey: ‘normal.night.grey’, normalNightGreyMobile: ‘normal.night.grey.mobile’, normalNightTransit: ‘normal.night.transit’, normalNightTransitMobile: ‘normal.night.transit.mobile’, reducedDay: ‘reduced.day’, reducedNight: ‘reduced.night’, basicMap: { options: { type: ‘basetile’ } }, mapLabels: { options: { type: ‘labeltile’, format: ‘png’ } }, trafficFlow: { options: { base: ‘traffic’, type: ‘flowtile’ } }, carnavDayGrey: ‘carnav.day.grey’, hybridDay: { options: { base: ‘aerial’, variant: ‘hybrid.day’ } }, hybridDayMobile: { options: { base: ‘aerial’, variant: ‘hybrid.day.mobile’ } }, hybridDayTransit: { options: { base: ‘aerial’, variant: ‘hybrid.day.transit’ } }, hybridDayGrey: { options: { base: ‘aerial’, variant: ‘hybrid.grey.day’ } }, hybridDayTraffic: { options: { variant: ‘hybrid.traffic.day’, base: ‘traffic’, type: ‘traffictile’ } }, pedestrianDay: ‘pedestrian.day’, pedestrianNight: ‘pedestrian.night’, satelliteDay: { options: { base: ‘aerial’, variant: ‘satellite.day’ } }, terrainDay: { options: { base: ‘aerial’, variant: ‘terrain.day’ } }, terrainDayMobile: { options: { base: ‘aerial’, variant: ‘terrain.day.mobile’ } } } }, FreeMapSK: { url: ‘http://t{s}.freemap.sk/T/{z}/{x}/{y}.jpeg’, options: { minZoom: 8, maxZoom: 16, subdomains: ‘1234’, bounds: [[47.204642, 15.996093], [49.830896, 22.576904]], attribution: ‘{attribution.OpenStreetMap}, vizualization CC-By-SA 2.0 Freemap.sk‘ } }, MtbMap: { url: ‘http://tile.mtbmap.cz/mtbmap_tiles/{z}/{x}/{y}.png’, options: { attribution: ‘{attribution.OpenStreetMap} & USGS’ } }, CartoDB: { url: ‘https://{s}.basemaps.cartocdn.com/{variant}/{z}/{x}/{y}{r}.png’, options: { attribution: ‘{attribution.OpenStreetMap} © CARTO‘, subdomains: ‘abcd’, maxZoom: 19, variant: ‘light_all’ }, variants: { Positron: ‘light_all’, PositronNoLabels: ‘light_nolabels’, PositronOnlyLabels: ‘light_only_labels’, DarkMatter: ‘dark_all’, DarkMatterNoLabels: ‘dark_nolabels’, DarkMatterOnlyLabels: ‘dark_only_labels’, Voyager: ‘rastertiles/voyager’, VoyagerNoLabels: ‘rastertiles/voyager_nolabels’, VoyagerOnlyLabels: ‘rastertiles/voyager_only_labels’, VoyagerLabelsUnder: ‘rastertiles/voyager_labels_under’ } }, HikeBike: { url: ‘https://tiles.wmflabs.org/{variant}/{z}/{x}/{y}.png’, options: { maxZoom: 19, attribution: ‘{attribution.OpenStreetMap}’, variant: ‘hikebike’ }, variants: { HikeBike: {}, HillShading: { options: { maxZoom: 15, variant: ‘hillshading’ } } } }, BasemapAT: { url: ‘//maps{s}.wien.gv.at/basemap/{variant}/normal/google3857/{z}/{y}/{x}.{format}’, options: { maxZoom: 19, attribution: ‘Datenquelle: basemap.at‘, subdomains: [”, ‘1’, ‘2’, ‘3’, ‘4’], format: ‘png’, bounds: [[46.358770, 8.782379], [49.037872, 17.189532]], variant: ‘geolandbasemap’ }, variants: { basemap: { options: { maxZoom: 20, // currently only in Vienna variant: ‘geolandbasemap’ } }, grau: ‘bmapgrau’, overlay: ‘bmapoverlay’, highdpi: { options: { variant: ‘bmaphidpi’, format: ‘jpeg’ } }, orthofoto: { options: { maxZoom: 20, // currently only in Vienna variant: ‘bmaporthofoto30cm’, format: ‘jpeg’ } } } }, nlmaps: { url: ‘//geodata.nationaalgeoregister.nl/tiles/service/wmts/{variant}/EPSG:3857/{z}/{x}/{y}.png’, options: { minZoom: 6, maxZoom: 19, bounds: [[50.5, 3.25], [54, 7.6]], attribution: ‘Kaartgegevens © Kadaster‘ }, variants: { ‘standaard’: ‘brtachtergrondkaart’, ‘pastel’: ‘brtachtergrondkaartpastel’, ‘grijs’: ‘brtachtergrondkaartgrijs’, ‘luchtfoto’: { ‘url’: ‘//geodata.nationaalgeoregister.nl/luchtfoto/rgb/wmts/1.0.0/2016_ortho25/EPSG:3857/{z}/{x}/{y}.png’, } } }, NASAGIBS: { url: ‘https://map1.vis.earthdata.nasa.gov/wmts-webmerc/{variant}/default/{time}/{tilematrixset}{maxZoom}/{z}/{y}/{x}.{format}’, options: { attribution: ‘Imagery provided by services from the Global Imagery Browse Services (GIBS), operated by the NASA/GSFC/Earth Science Data and Information System ‘ + ‘(ESDIS) with funding provided by NASA/HQ.’, bounds: [[-85.0511287776, -179.999999975], [85.0511287776, 179.999999975]], minZoom: 1, maxZoom: 9, format: ‘jpg’, time: ”, tilematrixset: ‘GoogleMapsCompatible_Level’ }, variants: { ModisTerraTrueColorCR: ‘MODIS_Terra_CorrectedReflectance_TrueColor’, ModisTerraBands367CR: ‘MODIS_Terra_CorrectedReflectance_Bands367’, ViirsEarthAtNight2012: { options: { variant: ‘VIIRS_CityLights_2012’, maxZoom: 8 } }, ModisTerraLSTDay: { options: { variant: ‘MODIS_Terra_Land_Surface_Temp_Day’, format: ‘png’, maxZoom: 7, opacity: 0.75 } }, ModisTerraSnowCover: { options: { variant: ‘MODIS_Terra_Snow_Cover’, format: ‘png’, maxZoom: 8, opacity: 0.75 } }, ModisTerraAOD: { options: { variant: ‘MODIS_Terra_Aerosol’, format: ‘png’, maxZoom: 6, opacity: 0.75 } }, ModisTerraChlorophyll: { options: { variant: ‘MODIS_Terra_Chlorophyll_A’, format: ‘png’, maxZoom: 7, opacity: 0.75 } } } }, NLS: { // NLS maps are copyright National library of Scotland. // http://maps.nls.uk/projects/api/index.html // Please contact NLS for anything other than non-commercial low volume usage // // Map sources: Ordnance Survey 1:1m to 1:63K, 1920s-1940s // z0-9 – 1:1m // z10-11 – quarter inch (1:253440) // z12-18 – one inch (1:63360) url: ‘//nls-{s}.tileserver.com/nls/{z}/{x}/{y}.jpg’, options: { attribution: ‘National Library of Scotland Historic Maps‘, bounds: [[49.6, -12], [61.7, 3]], minZoom: 1, maxZoom: 18, subdomains: ‘0123’, } }, JusticeMap: { // Justice Map (http://www.justicemap.org/) // Visualize race and income data for your community, county and country. // Includes tools for data journalists, bloggers and community activists. url: ‘http://www.justicemap.org/tile/{size}/{variant}/{z}/{x}/{y}.png’, options: { attribution: ‘Justice Map‘, // one of ‘county’, ‘tract’, ‘block’ size: ‘county’, // Bounds for USA, including Alaska and Hawaii bounds: [[14, -180], [72, -56]] }, variants: { income: ‘income’, americanIndian: ‘indian’, asian: ‘asian’, black: ‘black’, hispanic: ‘hispanic’, multi: ‘multi’, nonWhite: ‘nonwhite’, white: ‘white’, plurality: ‘plural’ } }, Wikimedia: { url: ‘https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}{r}.png’, options: { attribution: ‘Wikimedia‘, minZoom: 1, maxZoom: 19 } }, GeoportailFrance: { url: ‘https://wxs.ign.fr/{apikey}/geoportail/wmts?REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&STYLE={style}&TILEMATRIXSET=PM&FORMAT={format}&LAYER={variant}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}’, options: { attribution: ‘Geoportail France‘, bounds: [[-75, -180], [81, 180]], minZoom: 2, maxZoom: 18, // Get your own geoportail apikey here : http://professionnels.ign.fr/ign/contrats/ // NB : ‘choisirgeoportail’ is a demonstration key that comes with no guarantee apikey: ‘choisirgeoportail’, format: ‘image/jpeg’, style : ‘normal’, variant: ‘GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD’ }, variants: { parcels: { options : { variant: ‘CADASTRALPARCELS.PARCELS’, maxZoom: 20, style : ‘bdparcellaire’, format: ‘image/png’ } }, ignMaps: ‘GEOGRAPHICALGRIDSYSTEMS.MAPS’, maps: ‘GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD’, orthos: { options: { maxZoom: 19, variant: ‘ORTHOIMAGERY.ORTHOPHOTOS’ } } } }, OneMapSG: { url: ‘//maps-{s}.onemap.sg/v3/{variant}/{z}/{x}/{y}.png’, options: { variant: ‘Default’, minZoom: 11, maxZoom: 18, bounds: [[1.56073, 104.11475], [1.16, 103.502]], attribution: ‘ New OneMap | Map data © contributors, Singapore Land Authority‘ }, variants: { Default: ‘Default’, Night: ‘Night’, Original: ‘Original’, Grey: ‘Grey’, LandLot: ‘LandLot’ } } }; L.tileLayer.provider = function (provider, options) { return new L.TileLayer.Provider(provider, options); }; return L;
})); LeafletWidget.methods.addProviderTiles = function(provider, layerId, group, options) { this.layerManager.addLayer(L.tileLayer.provider(provider, options), “tile”, layerId, group);
}; LeafletWidget.methods.addFlatGeoBuf = function (layerId, group, url, popup, label, style, options, className, scale, scaleFields) { var map = this; var gl = false; var pane; if (options === null || options.pane === undefined) { pane = ‘overlayPane’; } else { pane = options.pane; } var data_fl = document.getElementById(layerId + ‘-1-attachment’); if (data_fl === null) { data_fl = url; } else { data_fl = data_fl.href; } var popUp; var colnames = []; function handleHeaderMeta(headerMeta) { headerMeta.columns.forEach(function(col) { colnames.push(col.name); }); } function handleResponse(response) { // use fgb JavaScript API to iterate stream into results (features as geojson) // NOTE: would be more efficient with a special purpose Leaflet deserializer let it = flatgeobuf.deserialize(response.body, undefined, handleHeaderMeta); var cntr = 0; // handle result function handleResult(result) { if (!result.done) { if (gl) { map.layerManager.addLayer( L.glify.shapes({ map: map, data: result.value, className: group }).glLayer, null, null, group); it.next().then(handleResult); } else { if (popup) { pop = makePopup(popup, className); } else { pop = null; } if (scaleFields === undefined & result.value.properties !== undefined) { var vls = Object.values(style); scaleFields = []; vls.forEach(function(name) { //if (name in colnames) { if (colnames.includes(name)) { scaleFields.push(true); } else { scaleFields.push(false); } }); } lyr = L.geoJSON(result.value, { pointToLayer: function (feature, latlng) { return L.circleMarker(latlng, options); }, style: function(feature) { return updateStyle(style, feature, scale, scaleFields); }, onEachFeature: pop, pane: pane }); if (label) { if (Object.keys(result.value.properties).includes(label)) { lyr.bindTooltip(function (layer) { return layer.feature.properties[label].toString(); }, {sticky: true}); } else if (typeof(label) === Object || (typeof(label) === ‘object’ && label.length > 1)) { var lb = label[cntr]; lyr.bindTooltip(function (layer) { return(lb); }, {sticky: true}); } else { lyr.bindTooltip(function (layer) { return(label); }, {sticky: true}); } } map.layerManager.addLayer(lyr, null, null, group); it.next().then(handleResult); } } cntr += 1; } it.next().then(handleResult); } fetch(data_fl) //, {mode: ‘no-cors’}) .then(handleResponse); //map.fitBounds(lyr.getBounds()); //map.layerManager.addLayer(layer, null, null, group);
}; function makePopup(popup, className) { if (popup === true) { pop = function(feature, layer) { popUp = json2table(feature.properties, className); layer.bindPopup(popUp, { maxWidth: 2000 }); }; } else if (typeof(popup) === “string”) { pop = function(feature, layer) { if (feature.properties !== undefined && popup in feature.properties) { popup = popup.split(); popUp = json2table( pick(feature.properties, popup), className ); } else { popUp = popup; } layer.bindPopup(popUp, { maxWidth: 2000 }); }; } else if (typeof(popup) === “object”) { pop = function(feature, layer) { if (feature.properties.mvFeatureId !== undefined) { var idx = feature.properties.mvFeatureId; layer.bindPopup(popup[idx – 1], { maxWidth: 2000 }); } if (feature.properties.mvFeatureId === undefined) { console.log(“cannot bind popup to layer without id! Please file an issue at https://github.com/r-spatial/leafem/issues“); layer.bindPopup(“”); } }; } else { pop = function(feature, layer) { popUp = json2table( pick(feature.properties, popup), className ); layer.bindPopup(popUp, { maxWidth: 2000 }); }; } return pop;
} function json2table(json, cls) { var cols = Object.keys(json); var vals = Object.values(json); var tab = “”; for (let i = 0; i < cols.length; i++) { tab += "

” + cols[i] + “ ” + “

” + vals[i] + “ 

“; } return “

” + tab + “

“; } /** * from https://gomakethings.com/how-to-create-a-new-object-with-only-a-subject-of-properties-using-vanilla-js/ * * * Create a new object composed of properties picked from another object * (c) 2018 Chris Ferdinandi, MIT License, https://gomakethings.com * @param {Object} obj The object to pick properties from * @param {Array} props An array of properties to use * @return {Object} The new object */
function pick(obj, props) { ‘use strict’; // Make sure object and properties are provided if (!obj || !props) return; // Create new object var picked = {}; // Loop through props and push to new object props.forEach(function(prop) { picked[prop] = obj[prop]; }); // Return new object return picked; } function updateStyle(style_obj, feature, scale, scaleValues) { var cols = Object.keys(style_obj); var vals = Object.values(style_obj); var out = {}; for (let i = 0; i >>0)+4294967296*this.high}equals(t){return this.low==t.low&&this.high==t.high}}var c,u;h.ZERO=new h(0,0),function(t){t[t.UTF8_BYTES=1]=”UTF8_BYTES”,t[t.UTF16_STRING=2]=”UTF16_STRING”}(c||(c={}));class l{constructor(t){this.bytes_=t,this.position_=0}static allocate(t){return new l(new Uint8Array(t))}clear(){this.position_=0}bytes(){return this.bytes_}position(){return this.position_}setPosition(t){this.position_=t}capacity(){return this.bytes_.length}readInt8(t){return this.readUint8(t)24}readUint8(t){return this.bytes_[t]}readInt16(t){return this.readUint16(t)16}readUint16(t){return this.bytes_[t]|this.bytes_[t+1]>8,this.bytes_[t+2]=e>>16,this.bytes_[t+3]=e>>24}writeUint32(t,e){this.bytes_[t]=e,this.bytes_[t+1]=e>>8,this.bytes_[t+2]=e>>16,this.bytes_[t+3]=e>>24}writeInt64(t,e){this.writeInt32(t,e.low),this.writeInt32(t+4,e.high)}writeUint64(t,e){this.writeUint32(t,e.low),this.writeUint32(t+4,e.high)}writeFloat32(t,e){i[0]=e,this.writeInt32(t,s[0])}writeFloat64(t,e){o[0]=e,this.writeInt32(t,s[a?0:1]),this.writeInt32(t+4,s[a?1:0])}getBufferIdentifier(){if(this.bytes_.length