2 (function(l, r) { if (l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (window.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(window.document);
7 function add_location(element, file, line, column, char) {
8 element.__svelte_meta = {
9 loc: { file, line, column, char }
15 function blank_object() {
16 return Object.create(null);
18 function run_all(fns) {
21 function is_function(thing) {
22 return typeof thing === 'function';
24 function safe_not_equal(a, b) {
25 return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
27 function is_empty(obj) {
28 return Object.keys(obj).length === 0;
30 function subscribe(store, ...callbacks) {
34 const unsub = store.subscribe(...callbacks);
35 return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
37 function get_store_value(store) {
39 subscribe(store, _ => value = _)();
42 function action_destroyer(action_result) {
43 return action_result && is_function(action_result.destroy) ? action_result.destroy : noop;
46 function append(target, node) {
47 target.appendChild(node);
49 function insert(target, node, anchor) {
50 target.insertBefore(node, anchor || null);
52 function detach(node) {
53 node.parentNode.removeChild(node);
55 function destroy_each(iterations, detaching) {
56 for (let i = 0; i < iterations.length; i += 1) {
58 iterations[i].d(detaching);
61 function element(name) {
62 return document.createElement(name);
65 return document.createTextNode(data);
73 function listen(node, event, handler, options) {
74 node.addEventListener(event, handler, options);
75 return () => node.removeEventListener(event, handler, options);
77 function prevent_default(fn) {
78 return function (event) {
79 event.preventDefault();
81 return fn.call(this, event);
84 function stop_propagation(fn) {
85 return function (event) {
86 event.stopPropagation();
88 return fn.call(this, event);
91 function attr(node, attribute, value) {
93 node.removeAttribute(attribute);
94 else if (node.getAttribute(attribute) !== value)
95 node.setAttribute(attribute, value);
97 function children(element) {
98 return Array.from(element.childNodes);
100 function set_style(node, key, value, important) {
101 node.style.setProperty(key, value, important ? 'important' : '');
103 function select_option(select, value) {
104 for (let i = 0; i < select.options.length; i += 1) {
105 const option = select.options[i];
106 if (option.__value === value) {
107 option.selected = true;
112 function toggle_class(element, name, toggle) {
113 element.classList[toggle ? 'add' : 'remove'](name);
115 function custom_event(type, detail) {
116 const e = document.createEvent('CustomEvent');
117 e.initCustomEvent(type, false, false, detail);
121 let current_component;
122 function set_current_component(component) {
123 current_component = component;
125 function get_current_component() {
126 if (!current_component)
127 throw new Error('Function called outside component initialization');
128 return current_component;
130 function onMount(fn) {
131 get_current_component().$$.on_mount.push(fn);
134 const dirty_components = [];
135 const binding_callbacks = [];
136 const render_callbacks = [];
137 const flush_callbacks = [];
138 const resolved_promise = Promise.resolve();
139 let update_scheduled = false;
140 function schedule_update() {
141 if (!update_scheduled) {
142 update_scheduled = true;
143 resolved_promise.then(flush);
146 function add_render_callback(fn) {
147 render_callbacks.push(fn);
149 let flushing = false;
150 const seen_callbacks = new Set();
156 // first, call beforeUpdate functions
157 // and update components
158 for (let i = 0; i < dirty_components.length; i += 1) {
159 const component = dirty_components[i];
160 set_current_component(component);
161 update(component.$$);
163 set_current_component(null);
164 dirty_components.length = 0;
165 while (binding_callbacks.length)
166 binding_callbacks.pop()();
167 // then, once components are updated, call
168 // afterUpdate functions. This may cause
169 // subsequent updates...
170 for (let i = 0; i < render_callbacks.length; i += 1) {
171 const callback = render_callbacks[i];
172 if (!seen_callbacks.has(callback)) {
173 // ...so guard against infinite loops
174 seen_callbacks.add(callback);
178 render_callbacks.length = 0;
179 } while (dirty_components.length);
180 while (flush_callbacks.length) {
181 flush_callbacks.pop()();
183 update_scheduled = false;
185 seen_callbacks.clear();
187 function update($$) {
188 if ($$.fragment !== null) {
190 run_all($$.before_update);
191 const dirty = $$.dirty;
193 $$.fragment && $$.fragment.p($$.ctx, dirty);
194 $$.after_update.forEach(add_render_callback);
197 const outroing = new Set();
199 function group_outros() {
203 p: outros // parent group
206 function check_outros() {
212 function transition_in(block, local) {
213 if (block && block.i) {
214 outroing.delete(block);
218 function transition_out(block, local, detach, callback) {
219 if (block && block.o) {
220 if (outroing.has(block))
223 outros.c.push(() => {
224 outroing.delete(block);
235 const globals = (typeof window !== 'undefined'
237 : typeof globalThis !== 'undefined'
240 function create_component(block) {
243 function mount_component(component, target, anchor) {
244 const { fragment, on_mount, on_destroy, after_update } = component.$$;
245 fragment && fragment.m(target, anchor);
246 // onMount happens before the initial afterUpdate
247 add_render_callback(() => {
248 const new_on_destroy = on_mount.map(run).filter(is_function);
250 on_destroy.push(...new_on_destroy);
253 // Edge case - component was destroyed immediately,
254 // most likely as a result of a binding initialising
255 run_all(new_on_destroy);
257 component.$$.on_mount = [];
259 after_update.forEach(add_render_callback);
261 function destroy_component(component, detaching) {
262 const $$ = component.$$;
263 if ($$.fragment !== null) {
264 run_all($$.on_destroy);
265 $$.fragment && $$.fragment.d(detaching);
266 // TODO null out other refs, including component.$$ (but need to
267 // preserve final state?)
268 $$.on_destroy = $$.fragment = null;
272 function make_dirty(component, i) {
273 if (component.$$.dirty[0] === -1) {
274 dirty_components.push(component);
276 component.$$.dirty.fill(0);
278 component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
280 function init(component, options, instance, create_fragment, not_equal, props, dirty = [-1]) {
281 const parent_component = current_component;
282 set_current_component(component);
283 const prop_values = options.props || {};
284 const $$ = component.$$ = {
291 bound: blank_object(),
297 context: new Map(parent_component ? parent_component.$$.context : []),
299 callbacks: blank_object(),
305 ? instance(component, prop_values, (i, ret, ...rest) => {
306 const value = rest.length ? rest[0] : ret;
307 if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
308 if (!$$.skip_bound && $$.bound[i])
311 make_dirty(component, i);
318 run_all($$.before_update);
319 // `false` as a special case of no DOM component
320 $$.fragment = create_fragment ? create_fragment($$.ctx) : false;
321 if (options.target) {
322 if (options.hydrate) {
323 const nodes = children(options.target);
324 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
325 $$.fragment && $$.fragment.l(nodes);
326 nodes.forEach(detach);
329 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
330 $$.fragment && $$.fragment.c();
333 transition_in(component.$$.fragment);
334 mount_component(component, options.target, options.anchor);
337 set_current_component(parent_component);
340 * Base class for Svelte components. Used when dev=false.
342 class SvelteComponent {
344 destroy_component(this, 1);
345 this.$destroy = noop;
347 $on(type, callback) {
348 const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
349 callbacks.push(callback);
351 const index = callbacks.indexOf(callback);
353 callbacks.splice(index, 1);
357 if (this.$$set && !is_empty($$props)) {
358 this.$$.skip_bound = true;
360 this.$$.skip_bound = false;
365 function dispatch_dev(type, detail) {
366 document.dispatchEvent(custom_event(type, Object.assign({ version: '3.31.2' }, detail)));
368 function append_dev(target, node) {
369 dispatch_dev('SvelteDOMInsert', { target, node });
370 append(target, node);
372 function insert_dev(target, node, anchor) {
373 dispatch_dev('SvelteDOMInsert', { target, node, anchor });
374 insert(target, node, anchor);
376 function detach_dev(node) {
377 dispatch_dev('SvelteDOMRemove', { node });
380 function listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation) {
381 const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];
382 if (has_prevent_default)
383 modifiers.push('preventDefault');
384 if (has_stop_propagation)
385 modifiers.push('stopPropagation');
386 dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });
387 const dispose = listen(node, event, handler, options);
389 dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });
393 function attr_dev(node, attribute, value) {
394 attr(node, attribute, value);
396 dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });
398 dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });
400 function prop_dev(node, property, value) {
401 node[property] = value;
402 dispatch_dev('SvelteDOMSetProperty', { node, property, value });
404 function set_data_dev(text, data) {
406 if (text.wholeText === data)
408 dispatch_dev('SvelteDOMSetData', { node: text, data });
411 function validate_each_argument(arg) {
412 if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {
413 let msg = '{#each} only iterates over array-like objects.';
414 if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {
415 msg += ' You can use a spread to convert this iterable into an array.';
417 throw new Error(msg);
420 function validate_slots(name, slot, keys) {
421 for (const slot_key of Object.keys(slot)) {
422 if (!~keys.indexOf(slot_key)) {
423 console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
428 * Base class for Svelte components with some minor dev-enhancements. Used when dev=true.
430 class SvelteComponentDev extends SvelteComponent {
431 constructor(options) {
432 if (!options || (!options.target && !options.$$inline)) {
433 throw new Error("'target' is a required option");
439 this.$destroy = () => {
440 console.warn('Component was already destroyed'); // eslint-disable-line no-console
447 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
449 function createCommonjsModule(fn) {
450 var module = { exports: {} };
451 return fn(module, module.exports), module.exports;
455 * jQuery JavaScript Library v3.5.1
456 * https://jquery.com/
459 * https://sizzlejs.com/
461 * Copyright JS Foundation and other contributors
462 * Released under the MIT license
463 * https://jquery.org/license
465 * Date: 2020-05-04T22:49Z
468 var jquery = createCommonjsModule(function (module) {
469 ( function( global, factory ) {
473 // For CommonJS and CommonJS-like environments where a proper `window`
474 // is present, execute the factory and get jQuery.
475 // For environments that do not have a `window` with a `document`
476 // (such as Node.js), expose a factory as module.exports.
477 // This accentuates the need for the creation of a real `window`.
478 // e.g. var jQuery = require("jquery")(window);
479 // See ticket #14549 for more info.
480 module.exports = global.document ?
481 factory( global, true ) :
484 throw new Error( "jQuery requires a window with a document" );
490 // Pass this if window is not defined yet
491 } )( typeof window !== "undefined" ? window : commonjsGlobal, function( window, noGlobal ) {
495 var getProto = Object.getPrototypeOf;
497 var slice = arr.slice;
499 var flat = arr.flat ? function( array ) {
500 return arr.flat.call( array );
501 } : function( array ) {
502 return arr.concat.apply( [], array );
508 var indexOf = arr.indexOf;
512 var toString = class2type.toString;
514 var hasOwn = class2type.hasOwnProperty;
516 var fnToString = hasOwn.toString;
518 var ObjectFunctionString = fnToString.call( Object );
522 var isFunction = function isFunction( obj ) {
524 // Support: Chrome <=57, Firefox <=52
525 // In some browsers, typeof returns "function" for HTML <object> elements
526 // (i.e., `typeof document.createElement( "object" ) === "function"`).
527 // We don't want to classify *any* DOM node as a function.
528 return typeof obj === "function" && typeof obj.nodeType !== "number";
532 var isWindow = function isWindow( obj ) {
533 return obj != null && obj === obj.window;
537 var document = window.document;
541 var preservedScriptAttributes = {
548 function DOMEval( code, node, doc ) {
549 doc = doc || document;
552 script = doc.createElement( "script" );
556 for ( i in preservedScriptAttributes ) {
558 // Support: Firefox 64+, Edge 18+
559 // Some browsers don't support the "nonce" property on scripts.
560 // On the other hand, just using `getAttribute` is not enough as
561 // the `nonce` attribute is reset to an empty string whenever it
562 // becomes browsing-context connected.
563 // See https://github.com/whatwg/html/issues/2369
564 // See https://html.spec.whatwg.org/#nonce-attributes
565 // The `node.getAttribute` check was added for the sake of
566 // `jQuery.globalEval` so that it can fake a nonce-containing node
568 val = node[ i ] || node.getAttribute && node.getAttribute( i );
570 script.setAttribute( i, val );
574 doc.head.appendChild( script ).parentNode.removeChild( script );
578 function toType( obj ) {
583 // Support: Android <=2.3 only (functionish RegExp)
584 return typeof obj === "object" || typeof obj === "function" ?
585 class2type[ toString.call( obj ) ] || "object" :
589 // Defining this global in .eslintrc.json would create a danger of using the global
590 // unguarded in another place, it seems safer to define global only for this module
597 // Define a local copy of jQuery
598 jQuery = function( selector, context ) {
600 // The jQuery object is actually just the init constructor 'enhanced'
601 // Need init if jQuery is called (just allow error to be thrown if not included)
602 return new jQuery.fn.init( selector, context );
605 jQuery.fn = jQuery.prototype = {
607 // The current version of jQuery being used
612 // The default length of a jQuery object is 0
615 toArray: function() {
616 return slice.call( this );
619 // Get the Nth element in the matched element set OR
620 // Get the whole matched element set as a clean array
621 get: function( num ) {
623 // Return all the elements in a clean array
625 return slice.call( this );
628 // Return just the one element from the set
629 return num < 0 ? this[ num + this.length ] : this[ num ];
632 // Take an array of elements and push it onto the stack
633 // (returning the new matched element set)
634 pushStack: function( elems ) {
636 // Build a new jQuery matched element set
637 var ret = jQuery.merge( this.constructor(), elems );
639 // Add the old object onto the stack (as a reference)
640 ret.prevObject = this;
642 // Return the newly-formed element set
646 // Execute a callback for every element in the matched set.
647 each: function( callback ) {
648 return jQuery.each( this, callback );
651 map: function( callback ) {
652 return this.pushStack( jQuery.map( this, function( elem, i ) {
653 return callback.call( elem, i, elem );
658 return this.pushStack( slice.apply( this, arguments ) );
666 return this.eq( -1 );
670 return this.pushStack( jQuery.grep( this, function( _elem, i ) {
671 return ( i + 1 ) % 2;
676 return this.pushStack( jQuery.grep( this, function( _elem, i ) {
682 var len = this.length,
683 j = +i + ( i < 0 ? len : 0 );
684 return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
688 return this.prevObject || this.constructor();
691 // For internal use only.
692 // Behaves like an Array's method, not like a jQuery method.
698 jQuery.extend = jQuery.fn.extend = function() {
699 var options, name, src, copy, copyIsArray, clone,
700 target = arguments[ 0 ] || {},
702 length = arguments.length,
705 // Handle a deep copy situation
706 if ( typeof target === "boolean" ) {
709 // Skip the boolean and the target
710 target = arguments[ i ] || {};
714 // Handle case when target is a string or something (possible in deep copy)
715 if ( typeof target !== "object" && !isFunction( target ) ) {
719 // Extend jQuery itself if only one argument is passed
720 if ( i === length ) {
725 for ( ; i < length; i++ ) {
727 // Only deal with non-null/undefined values
728 if ( ( options = arguments[ i ] ) != null ) {
730 // Extend the base object
731 for ( name in options ) {
732 copy = options[ name ];
734 // Prevent Object.prototype pollution
735 // Prevent never-ending loop
736 if ( name === "__proto__" || target === copy ) {
740 // Recurse if we're merging plain objects or arrays
741 if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
742 ( copyIsArray = Array.isArray( copy ) ) ) ) {
743 src = target[ name ];
745 // Ensure proper type for the source value
746 if ( copyIsArray && !Array.isArray( src ) ) {
748 } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
755 // Never move original objects, clone them
756 target[ name ] = jQuery.extend( deep, clone, copy );
758 // Don't bring in undefined values
759 } else if ( copy !== undefined ) {
760 target[ name ] = copy;
766 // Return the modified object
772 // Unique for each copy of jQuery on the page
773 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
775 // Assume jQuery is ready without the ready module
778 error: function( msg ) {
779 throw new Error( msg );
784 isPlainObject: function( obj ) {
787 // Detect obvious negatives
788 // Use toString instead of jQuery.type to catch host objects
789 if ( !obj || toString.call( obj ) !== "[object Object]" ) {
793 proto = getProto( obj );
795 // Objects with no prototype (e.g., `Object.create( null )`) are plain
800 // Objects with prototype are plain iff they were constructed by a global Object function
801 Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
802 return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
805 isEmptyObject: function( obj ) {
808 for ( name in obj ) {
814 // Evaluates a script in a provided context; falls back to the global one
816 globalEval: function( code, options, doc ) {
817 DOMEval( code, { nonce: options && options.nonce }, doc );
820 each: function( obj, callback ) {
823 if ( isArrayLike( obj ) ) {
825 for ( ; i < length; i++ ) {
826 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
832 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
841 // results is for internal usage only
842 makeArray: function( arr, results ) {
843 var ret = results || [];
846 if ( isArrayLike( Object( arr ) ) ) {
848 typeof arr === "string" ?
852 push.call( ret, arr );
859 inArray: function( elem, arr, i ) {
860 return arr == null ? -1 : indexOf.call( arr, elem, i );
863 // Support: Android <=4.0 only, PhantomJS 1 only
864 // push.apply(_, arraylike) throws on ancient WebKit
865 merge: function( first, second ) {
866 var len = +second.length,
870 for ( ; j < len; j++ ) {
871 first[ i++ ] = second[ j ];
879 grep: function( elems, callback, invert ) {
883 length = elems.length,
884 callbackExpect = !invert;
886 // Go through the array, only saving the items
887 // that pass the validator function
888 for ( ; i < length; i++ ) {
889 callbackInverse = !callback( elems[ i ], i );
890 if ( callbackInverse !== callbackExpect ) {
891 matches.push( elems[ i ] );
898 // arg is for internal usage only
899 map: function( elems, callback, arg ) {
904 // Go through the array, translating each of the items to their new values
905 if ( isArrayLike( elems ) ) {
906 length = elems.length;
907 for ( ; i < length; i++ ) {
908 value = callback( elems[ i ], i, arg );
910 if ( value != null ) {
915 // Go through every key on the object,
918 value = callback( elems[ i ], i, arg );
920 if ( value != null ) {
926 // Flatten any nested arrays
930 // A global GUID counter for objects
933 // jQuery.support is not used in Core but other projects attach their
934 // properties to it so it needs to exist.
938 if ( typeof Symbol === "function" ) {
939 jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
942 // Populate the class2type map
943 jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
944 function( _i, name ) {
945 class2type[ "[object " + name + "]" ] = name.toLowerCase();
948 function isArrayLike( obj ) {
950 // Support: real iOS 8.2 only (not reproducible in simulator)
951 // `in` check used to prevent JIT error (gh-2145)
952 // hasOwn isn't used here due to false negatives
953 // regarding Nodelist length in IE
954 var length = !!obj && "length" in obj && obj.length,
955 type = toType( obj );
957 if ( isFunction( obj ) || isWindow( obj ) ) {
961 return type === "array" || length === 0 ||
962 typeof length === "number" && length > 0 && ( length - 1 ) in obj;
966 * Sizzle CSS Selector Engine v2.3.5
967 * https://sizzlejs.com/
969 * Copyright JS Foundation and other contributors
970 * Released under the MIT license
971 * https://js.foundation/
975 ( function( window ) {
988 // Local document vars
998 // Instance-specific data
999 expando = "sizzle" + 1 * new Date(),
1000 preferredDoc = window.document,
1003 classCache = createCache(),
1004 tokenCache = createCache(),
1005 compilerCache = createCache(),
1006 nonnativeSelectorCache = createCache(),
1007 sortOrder = function( a, b ) {
1009 hasDuplicate = true;
1015 hasOwn = ( {} ).hasOwnProperty,
1018 pushNative = arr.push,
1022 // Use a stripped-down indexOf as it's faster than native
1023 // https://jsperf.com/thor-indexof-vs-for/5
1024 indexOf = function( list, elem ) {
1027 for ( ; i < len; i++ ) {
1028 if ( list[ i ] === elem ) {
1035 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" +
1036 "ismap|loop|multiple|open|readonly|required|scoped",
1038 // Regular expressions
1040 // http://www.w3.org/TR/css3-selectors/#whitespace
1041 whitespace = "[\\x20\\t\\r\\n\\f]",
1043 // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
1044 identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
1045 "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
1047 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
1048 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
1050 // Operator (capture 2)
1051 "*([*^$|!~]?=)" + whitespace +
1053 // "Attribute values must be CSS identifiers [capture 5]
1054 // or strings [capture 3 or capture 4]"
1055 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
1056 whitespace + "*\\]",
1058 pseudos = ":(" + identifier + ")(?:\\((" +
1060 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
1061 // 1. quoted (capture 3; capture 4 or capture 5)
1062 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
1064 // 2. simple (capture 6)
1065 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
1067 // 3. anything else (capture 2)
1071 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
1072 rwhitespace = new RegExp( whitespace + "+", "g" ),
1073 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" +
1074 whitespace + "+$", "g" ),
1076 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
1077 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace +
1079 rdescend = new RegExp( whitespace + "|>" ),
1081 rpseudo = new RegExp( pseudos ),
1082 ridentifier = new RegExp( "^" + identifier + "$" ),
1085 "ID": new RegExp( "^#(" + identifier + ")" ),
1086 "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
1087 "TAG": new RegExp( "^(" + identifier + "|[*])" ),
1088 "ATTR": new RegExp( "^" + attributes ),
1089 "PSEUDO": new RegExp( "^" + pseudos ),
1090 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
1091 whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
1092 whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
1093 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
1095 // For use in libraries implementing .is()
1096 // We use this for POS matching in `select`
1097 "needsContext": new RegExp( "^" + whitespace +
1098 "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
1099 "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
1103 rinputs = /^(?:input|select|textarea|button)$/i,
1106 rnative = /^[^{]+\{\s*\[native \w/,
1108 // Easily-parseable/retrievable ID or TAG or CLASS selectors
1109 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
1114 // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
1115 runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ),
1116 funescape = function( escape, nonHex ) {
1117 var high = "0x" + escape.slice( 1 ) - 0x10000;
1121 // Strip the backslash prefix from a non-hex escape sequence
1124 // Replace a hexadecimal escape sequence with the encoded Unicode code point
1125 // Support: IE <=11+
1126 // For values outside the Basic Multilingual Plane (BMP), manually construct a
1129 String.fromCharCode( high + 0x10000 ) :
1130 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
1133 // CSS string/identifier serialization
1134 // https://drafts.csswg.org/cssom/#common-serializing-idioms
1135 rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
1136 fcssescape = function( ch, asCodePoint ) {
1137 if ( asCodePoint ) {
1139 // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
1140 if ( ch === "\0" ) {
1144 // Control characters and (dependent upon position) numbers get escaped as code points
1145 return ch.slice( 0, -1 ) + "\\" +
1146 ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
1149 // Other potentially-special ASCII characters get backslash-escaped
1154 // See setDocument()
1155 // Removing the function wrapper causes a "Permission Denied"
1157 unloadHandler = function() {
1161 inDisabledFieldset = addCombinator(
1163 return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
1165 { dir: "parentNode", next: "legend" }
1168 // Optimize for push.apply( _, NodeList )
1171 ( arr = slice.call( preferredDoc.childNodes ) ),
1172 preferredDoc.childNodes
1175 // Support: Android<4.0
1176 // Detect silently failing push.apply
1177 // eslint-disable-next-line no-unused-expressions
1178 arr[ preferredDoc.childNodes.length ].nodeType;
1180 push = { apply: arr.length ?
1182 // Leverage slice if possible
1183 function( target, els ) {
1184 pushNative.apply( target, slice.call( els ) );
1188 // Otherwise append directly
1189 function( target, els ) {
1190 var j = target.length,
1193 // Can't trust NodeList.length
1194 while ( ( target[ j++ ] = els[ i++ ] ) ) {}
1195 target.length = j - 1;
1200 function Sizzle( selector, context, results, seed ) {
1201 var m, i, elem, nid, match, groups, newSelector,
1202 newContext = context && context.ownerDocument,
1204 // nodeType defaults to 9, since context defaults to document
1205 nodeType = context ? context.nodeType : 9;
1207 results = results || [];
1209 // Return early from calls with invalid selector or context
1210 if ( typeof selector !== "string" || !selector ||
1211 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
1216 // Try to shortcut find operations (as opposed to filters) in HTML documents
1218 setDocument( context );
1219 context = context || document;
1221 if ( documentIsHTML ) {
1223 // If the selector is sufficiently simple, try using a "get*By*" DOM method
1224 // (excepting DocumentFragment context, where the methods don't exist)
1225 if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
1228 if ( ( m = match[ 1 ] ) ) {
1231 if ( nodeType === 9 ) {
1232 if ( ( elem = context.getElementById( m ) ) ) {
1234 // Support: IE, Opera, Webkit
1235 // TODO: identify versions
1236 // getElementById can match elements by name instead of ID
1237 if ( elem.id === m ) {
1238 results.push( elem );
1248 // Support: IE, Opera, Webkit
1249 // TODO: identify versions
1250 // getElementById can match elements by name instead of ID
1251 if ( newContext && ( elem = newContext.getElementById( m ) ) &&
1252 contains( context, elem ) &&
1255 results.push( elem );
1261 } else if ( match[ 2 ] ) {
1262 push.apply( results, context.getElementsByTagName( selector ) );
1266 } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName &&
1267 context.getElementsByClassName ) {
1269 push.apply( results, context.getElementsByClassName( m ) );
1274 // Take advantage of querySelectorAll
1276 !nonnativeSelectorCache[ selector + " " ] &&
1277 ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) &&
1279 // Support: IE 8 only
1280 // Exclude object elements
1281 ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) {
1283 newSelector = selector;
1284 newContext = context;
1286 // qSA considers elements outside a scoping root when evaluating child or
1287 // descendant combinators, which is not what we want.
1288 // In such cases, we work around the behavior by prefixing every selector in the
1289 // list with an ID selector referencing the scope context.
1290 // The technique has to be used as well when a leading combinator is used
1291 // as such selectors are not recognized by querySelectorAll.
1292 // Thanks to Andrew Dupont for this technique.
1293 if ( nodeType === 1 &&
1294 ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {
1296 // Expand context for sibling selectors
1297 newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
1300 // We can use :scope instead of the ID hack if the browser
1301 // supports it & if we're not changing the context.
1302 if ( newContext !== context || !support.scope ) {
1304 // Capture the context ID, setting it first if necessary
1305 if ( ( nid = context.getAttribute( "id" ) ) ) {
1306 nid = nid.replace( rcssescape, fcssescape );
1308 context.setAttribute( "id", ( nid = expando ) );
1312 // Prefix every selector in the list
1313 groups = tokenize( selector );
1316 groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
1317 toSelector( groups[ i ] );
1319 newSelector = groups.join( "," );
1323 push.apply( results,
1324 newContext.querySelectorAll( newSelector )
1327 } catch ( qsaError ) {
1328 nonnativeSelectorCache( selector, true );
1330 if ( nid === expando ) {
1331 context.removeAttribute( "id" );
1339 return select( selector.replace( rtrim, "$1" ), context, results, seed );
1343 * Create key-value caches of limited size
1344 * @returns {function(string, object)} Returns the Object data after storing it on itself with
1345 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
1346 * deleting the oldest entry
1348 function createCache() {
1351 function cache( key, value ) {
1353 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
1354 if ( keys.push( key + " " ) > Expr.cacheLength ) {
1356 // Only keep the most recent entries
1357 delete cache[ keys.shift() ];
1359 return ( cache[ key + " " ] = value );
1365 * Mark a function for special use by Sizzle
1366 * @param {Function} fn The function to mark
1368 function markFunction( fn ) {
1369 fn[ expando ] = true;
1374 * Support testing using an element
1375 * @param {Function} fn Passed the created element and returns a boolean result
1377 function assert( fn ) {
1378 var el = document.createElement( "fieldset" );
1386 // Remove from its parent by default
1387 if ( el.parentNode ) {
1388 el.parentNode.removeChild( el );
1391 // release memory in IE
1397 * Adds the same handler for all of the specified attrs
1398 * @param {String} attrs Pipe-separated list of attributes
1399 * @param {Function} handler The method that will be applied
1401 function addHandle( attrs, handler ) {
1402 var arr = attrs.split( "|" ),
1406 Expr.attrHandle[ arr[ i ] ] = handler;
1411 * Checks document order of two siblings
1412 * @param {Element} a
1413 * @param {Element} b
1414 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
1416 function siblingCheck( a, b ) {
1418 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
1419 a.sourceIndex - b.sourceIndex;
1421 // Use IE sourceIndex if available on both nodes
1426 // Check if b follows a
1428 while ( ( cur = cur.nextSibling ) ) {
1439 * Returns a function to use in pseudos for input types
1440 * @param {String} type
1442 function createInputPseudo( type ) {
1443 return function( elem ) {
1444 var name = elem.nodeName.toLowerCase();
1445 return name === "input" && elem.type === type;
1450 * Returns a function to use in pseudos for buttons
1451 * @param {String} type
1453 function createButtonPseudo( type ) {
1454 return function( elem ) {
1455 var name = elem.nodeName.toLowerCase();
1456 return ( name === "input" || name === "button" ) && elem.type === type;
1461 * Returns a function to use in pseudos for :enabled/:disabled
1462 * @param {Boolean} disabled true for :disabled; false for :enabled
1464 function createDisabledPseudo( disabled ) {
1466 // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
1467 return function( elem ) {
1469 // Only certain elements can match :enabled or :disabled
1470 // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
1471 // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
1472 if ( "form" in elem ) {
1474 // Check for inherited disabledness on relevant non-disabled elements:
1475 // * listed form-associated elements in a disabled fieldset
1476 // https://html.spec.whatwg.org/multipage/forms.html#category-listed
1477 // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
1478 // * option elements in a disabled optgroup
1479 // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
1480 // All such elements have a "form" property.
1481 if ( elem.parentNode && elem.disabled === false ) {
1483 // Option elements defer to a parent optgroup if present
1484 if ( "label" in elem ) {
1485 if ( "label" in elem.parentNode ) {
1486 return elem.parentNode.disabled === disabled;
1488 return elem.disabled === disabled;
1492 // Support: IE 6 - 11
1493 // Use the isDisabled shortcut property to check for disabled fieldset ancestors
1494 return elem.isDisabled === disabled ||
1496 // Where there is no isDisabled, check manually
1498 elem.isDisabled !== !disabled &&
1499 inDisabledFieldset( elem ) === disabled;
1502 return elem.disabled === disabled;
1504 // Try to winnow out elements that can't be disabled before trusting the disabled property.
1505 // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
1506 // even exist on them, let alone have a boolean value.
1507 } else if ( "label" in elem ) {
1508 return elem.disabled === disabled;
1511 // Remaining elements are neither :enabled nor :disabled
1517 * Returns a function to use in pseudos for positionals
1518 * @param {Function} fn
1520 function createPositionalPseudo( fn ) {
1521 return markFunction( function( argument ) {
1522 argument = +argument;
1523 return markFunction( function( seed, matches ) {
1525 matchIndexes = fn( [], seed.length, argument ),
1526 i = matchIndexes.length;
1528 // Match elements found at the specified indexes
1530 if ( seed[ ( j = matchIndexes[ i ] ) ] ) {
1531 seed[ j ] = !( matches[ j ] = seed[ j ] );
1539 * Checks a node for validity as a Sizzle context
1540 * @param {Element|Object=} context
1541 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1543 function testContext( context ) {
1544 return context && typeof context.getElementsByTagName !== "undefined" && context;
1547 // Expose support vars for convenience
1548 support = Sizzle.support = {};
1552 * @param {Element|Object} elem An element or a document
1553 * @returns {Boolean} True iff elem is a non-HTML XML node
1555 isXML = Sizzle.isXML = function( elem ) {
1556 var namespace = elem.namespaceURI,
1557 docElem = ( elem.ownerDocument || elem ).documentElement;
1560 // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
1561 // https://bugs.jquery.com/ticket/4833
1562 return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
1566 * Sets document-related variables once based on the current document
1567 * @param {Element|Object} [doc] An element or document object to use to set the document
1568 * @returns {Object} Returns the current document
1570 setDocument = Sizzle.setDocument = function( node ) {
1571 var hasCompare, subWindow,
1572 doc = node ? node.ownerDocument || node : preferredDoc;
1574 // Return early if doc is invalid or already selected
1575 // Support: IE 11+, Edge 17 - 18+
1576 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1577 // two documents; shallow comparisons work.
1578 // eslint-disable-next-line eqeqeq
1579 if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
1583 // Update global variables
1585 docElem = document.documentElement;
1586 documentIsHTML = !isXML( document );
1588 // Support: IE 9 - 11+, Edge 12 - 18+
1589 // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
1590 // Support: IE 11+, Edge 17 - 18+
1591 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1592 // two documents; shallow comparisons work.
1593 // eslint-disable-next-line eqeqeq
1594 if ( preferredDoc != document &&
1595 ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
1597 // Support: IE 11, Edge
1598 if ( subWindow.addEventListener ) {
1599 subWindow.addEventListener( "unload", unloadHandler, false );
1601 // Support: IE 9 - 10 only
1602 } else if ( subWindow.attachEvent ) {
1603 subWindow.attachEvent( "onunload", unloadHandler );
1607 // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,
1608 // Safari 4 - 5 only, Opera <=11.6 - 12.x only
1609 // IE/Edge & older browsers don't support the :scope pseudo-class.
1610 // Support: Safari 6.0 only
1611 // Safari 6.0 supports :scope but it's an alias of :root there.
1612 support.scope = assert( function( el ) {
1613 docElem.appendChild( el ).appendChild( document.createElement( "div" ) );
1614 return typeof el.querySelectorAll !== "undefined" &&
1615 !el.querySelectorAll( ":scope fieldset div" ).length;
1619 ---------------------------------------------------------------------- */
1622 // Verify that getAttribute really returns attributes and not properties
1623 // (excepting IE8 booleans)
1624 support.attributes = assert( function( el ) {
1626 return !el.getAttribute( "className" );
1630 ---------------------------------------------------------------------- */
1632 // Check if getElementsByTagName("*") returns only elements
1633 support.getElementsByTagName = assert( function( el ) {
1634 el.appendChild( document.createComment( "" ) );
1635 return !el.getElementsByTagName( "*" ).length;
1639 support.getElementsByClassName = rnative.test( document.getElementsByClassName );
1642 // Check if getElementById returns elements by name
1643 // The broken getElementById methods don't pick up programmatically-set names,
1644 // so use a roundabout getElementsByName test
1645 support.getById = assert( function( el ) {
1646 docElem.appendChild( el ).id = expando;
1647 return !document.getElementsByName || !document.getElementsByName( expando ).length;
1650 // ID filter and find
1651 if ( support.getById ) {
1652 Expr.filter[ "ID" ] = function( id ) {
1653 var attrId = id.replace( runescape, funescape );
1654 return function( elem ) {
1655 return elem.getAttribute( "id" ) === attrId;
1658 Expr.find[ "ID" ] = function( id, context ) {
1659 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1660 var elem = context.getElementById( id );
1661 return elem ? [ elem ] : [];
1665 Expr.filter[ "ID" ] = function( id ) {
1666 var attrId = id.replace( runescape, funescape );
1667 return function( elem ) {
1668 var node = typeof elem.getAttributeNode !== "undefined" &&
1669 elem.getAttributeNode( "id" );
1670 return node && node.value === attrId;
1674 // Support: IE 6 - 7 only
1675 // getElementById is not reliable as a find shortcut
1676 Expr.find[ "ID" ] = function( id, context ) {
1677 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1679 elem = context.getElementById( id );
1683 // Verify the id attribute
1684 node = elem.getAttributeNode( "id" );
1685 if ( node && node.value === id ) {
1689 // Fall back on getElementsByName
1690 elems = context.getElementsByName( id );
1692 while ( ( elem = elems[ i++ ] ) ) {
1693 node = elem.getAttributeNode( "id" );
1694 if ( node && node.value === id ) {
1706 Expr.find[ "TAG" ] = support.getElementsByTagName ?
1707 function( tag, context ) {
1708 if ( typeof context.getElementsByTagName !== "undefined" ) {
1709 return context.getElementsByTagName( tag );
1711 // DocumentFragment nodes don't have gEBTN
1712 } else if ( support.qsa ) {
1713 return context.querySelectorAll( tag );
1717 function( tag, context ) {
1722 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1723 results = context.getElementsByTagName( tag );
1725 // Filter out possible comments
1726 if ( tag === "*" ) {
1727 while ( ( elem = results[ i++ ] ) ) {
1728 if ( elem.nodeType === 1 ) {
1739 Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) {
1740 if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
1741 return context.getElementsByClassName( className );
1745 /* QSA/matchesSelector
1746 ---------------------------------------------------------------------- */
1748 // QSA and matchesSelector support
1750 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1753 // qSa(:focus) reports false when true (Chrome 21)
1754 // We allow this because of a bug in IE8/9 that throws an error
1755 // whenever `document.activeElement` is accessed on an iframe
1756 // So, we allow :focus to pass through QSA all the time to avoid the IE error
1757 // See https://bugs.jquery.com/ticket/13378
1760 if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) {
1763 // Regex strategy adopted from Diego Perini
1764 assert( function( el ) {
1768 // Select is set to empty string on purpose
1769 // This is to test IE's treatment of not explicitly
1770 // setting a boolean content attribute,
1771 // since its presence should be enough
1772 // https://bugs.jquery.com/ticket/12359
1773 docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
1774 "<select id='" + expando + "-\r\\' msallowcapture=''>" +
1775 "<option selected=''></option></select>";
1777 // Support: IE8, Opera 11-12.16
1778 // Nothing should be selected when empty strings follow ^= or $= or *=
1779 // The test attribute must be unknown in Opera but "safe" for WinRT
1780 // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1781 if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) {
1782 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1786 // Boolean attributes and "value" are not treated correctly
1787 if ( !el.querySelectorAll( "[selected]" ).length ) {
1788 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1791 // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
1792 if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1793 rbuggyQSA.push( "~=" );
1796 // Support: IE 11+, Edge 15 - 18+
1797 // IE 11/Edge don't find elements on a `[name='']` query in some cases.
1798 // Adding a temporary attribute to the document before the selection works
1799 // around the issue.
1800 // Interestingly, IE 10 & older don't seem to have the issue.
1801 input = document.createElement( "input" );
1802 input.setAttribute( "name", "" );
1803 el.appendChild( input );
1804 if ( !el.querySelectorAll( "[name='']" ).length ) {
1805 rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
1806 whitespace + "*(?:''|\"\")" );
1809 // Webkit/Opera - :checked should return selected option elements
1810 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1811 // IE8 throws error here and will not see later tests
1812 if ( !el.querySelectorAll( ":checked" ).length ) {
1813 rbuggyQSA.push( ":checked" );
1816 // Support: Safari 8+, iOS 8+
1817 // https://bugs.webkit.org/show_bug.cgi?id=136851
1818 // In-page `selector#id sibling-combinator selector` fails
1819 if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
1820 rbuggyQSA.push( ".#.+[+~]" );
1823 // Support: Firefox <=3.6 - 5 only
1824 // Old Firefox doesn't throw on a badly-escaped identifier.
1825 el.querySelectorAll( "\\\f" );
1826 rbuggyQSA.push( "[\\r\\n\\f]" );
1829 assert( function( el ) {
1830 el.innerHTML = "<a href='' disabled='disabled'></a>" +
1831 "<select disabled='disabled'><option/></select>";
1833 // Support: Windows 8 Native Apps
1834 // The type and name attributes are restricted during .innerHTML assignment
1835 var input = document.createElement( "input" );
1836 input.setAttribute( "type", "hidden" );
1837 el.appendChild( input ).setAttribute( "name", "D" );
1840 // Enforce case-sensitivity of name attribute
1841 if ( el.querySelectorAll( "[name=d]" ).length ) {
1842 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1845 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1846 // IE8 throws error here and will not see later tests
1847 if ( el.querySelectorAll( ":enabled" ).length !== 2 ) {
1848 rbuggyQSA.push( ":enabled", ":disabled" );
1852 // IE's :disabled selector does not pick up the children of disabled fieldsets
1853 docElem.appendChild( el ).disabled = true;
1854 if ( el.querySelectorAll( ":disabled" ).length !== 2 ) {
1855 rbuggyQSA.push( ":enabled", ":disabled" );
1858 // Support: Opera 10 - 11 only
1859 // Opera 10-11 does not throw on post-comma invalid pseudos
1860 el.querySelectorAll( "*,:x" );
1861 rbuggyQSA.push( ",.*:" );
1865 if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches ||
1866 docElem.webkitMatchesSelector ||
1867 docElem.mozMatchesSelector ||
1868 docElem.oMatchesSelector ||
1869 docElem.msMatchesSelector ) ) ) ) {
1871 assert( function( el ) {
1873 // Check to see if it's possible to do matchesSelector
1874 // on a disconnected node (IE 9)
1875 support.disconnectedMatch = matches.call( el, "*" );
1877 // This should fail with an exception
1878 // Gecko does not error, returns false instead
1879 matches.call( el, "[s!='']:x" );
1880 rbuggyMatches.push( "!=", pseudos );
1884 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
1885 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) );
1888 ---------------------------------------------------------------------- */
1889 hasCompare = rnative.test( docElem.compareDocumentPosition );
1891 // Element contains another
1892 // Purposefully self-exclusive
1893 // As in, an element does not contain itself
1894 contains = hasCompare || rnative.test( docElem.contains ) ?
1896 var adown = a.nodeType === 9 ? a.documentElement : a,
1897 bup = b && b.parentNode;
1898 return a === bup || !!( bup && bup.nodeType === 1 && (
1900 adown.contains( bup ) :
1901 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1906 while ( ( b = b.parentNode ) ) {
1916 ---------------------------------------------------------------------- */
1918 // Document order sorting
1919 sortOrder = hasCompare ?
1922 // Flag for duplicate removal
1924 hasDuplicate = true;
1928 // Sort on method existence if only one input has compareDocumentPosition
1929 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1934 // Calculate position if both inputs belong to the same document
1935 // Support: IE 11+, Edge 17 - 18+
1936 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1937 // two documents; shallow comparisons work.
1938 // eslint-disable-next-line eqeqeq
1939 compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?
1940 a.compareDocumentPosition( b ) :
1942 // Otherwise we know they are disconnected
1945 // Disconnected nodes
1947 ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {
1949 // Choose the first element that is related to our preferred document
1950 // Support: IE 11+, Edge 17 - 18+
1951 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1952 // two documents; shallow comparisons work.
1953 // eslint-disable-next-line eqeqeq
1954 if ( a == document || a.ownerDocument == preferredDoc &&
1955 contains( preferredDoc, a ) ) {
1959 // Support: IE 11+, Edge 17 - 18+
1960 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1961 // two documents; shallow comparisons work.
1962 // eslint-disable-next-line eqeqeq
1963 if ( b == document || b.ownerDocument == preferredDoc &&
1964 contains( preferredDoc, b ) ) {
1968 // Maintain original order
1970 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1974 return compare & 4 ? -1 : 1;
1978 // Exit early if the nodes are identical
1980 hasDuplicate = true;
1991 // Parentless nodes are either documents or disconnected
1992 if ( !aup || !bup ) {
1994 // Support: IE 11+, Edge 17 - 18+
1995 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1996 // two documents; shallow comparisons work.
1997 /* eslint-disable eqeqeq */
1998 return a == document ? -1 :
2000 /* eslint-enable eqeqeq */
2004 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
2007 // If the nodes are siblings, we can do a quick check
2008 } else if ( aup === bup ) {
2009 return siblingCheck( a, b );
2012 // Otherwise we need full lists of their ancestors for comparison
2014 while ( ( cur = cur.parentNode ) ) {
2018 while ( ( cur = cur.parentNode ) ) {
2022 // Walk down the tree looking for a discrepancy
2023 while ( ap[ i ] === bp[ i ] ) {
2029 // Do a sibling check if the nodes have a common ancestor
2030 siblingCheck( ap[ i ], bp[ i ] ) :
2032 // Otherwise nodes in our document sort first
2033 // Support: IE 11+, Edge 17 - 18+
2034 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2035 // two documents; shallow comparisons work.
2036 /* eslint-disable eqeqeq */
2037 ap[ i ] == preferredDoc ? -1 :
2038 bp[ i ] == preferredDoc ? 1 :
2039 /* eslint-enable eqeqeq */
2046 Sizzle.matches = function( expr, elements ) {
2047 return Sizzle( expr, null, null, elements );
2050 Sizzle.matchesSelector = function( elem, expr ) {
2051 setDocument( elem );
2053 if ( support.matchesSelector && documentIsHTML &&
2054 !nonnativeSelectorCache[ expr + " " ] &&
2055 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
2056 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
2059 var ret = matches.call( elem, expr );
2061 // IE 9's matchesSelector returns false on disconnected nodes
2062 if ( ret || support.disconnectedMatch ||
2064 // As well, disconnected nodes are said to be in a document
2066 elem.document && elem.document.nodeType !== 11 ) {
2070 nonnativeSelectorCache( expr, true );
2074 return Sizzle( expr, document, null, [ elem ] ).length > 0;
2077 Sizzle.contains = function( context, elem ) {
2079 // Set document vars if needed
2080 // Support: IE 11+, Edge 17 - 18+
2081 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2082 // two documents; shallow comparisons work.
2083 // eslint-disable-next-line eqeqeq
2084 if ( ( context.ownerDocument || context ) != document ) {
2085 setDocument( context );
2087 return contains( context, elem );
2090 Sizzle.attr = function( elem, name ) {
2092 // Set document vars if needed
2093 // Support: IE 11+, Edge 17 - 18+
2094 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2095 // two documents; shallow comparisons work.
2096 // eslint-disable-next-line eqeqeq
2097 if ( ( elem.ownerDocument || elem ) != document ) {
2098 setDocument( elem );
2101 var fn = Expr.attrHandle[ name.toLowerCase() ],
2103 // Don't get fooled by Object.prototype properties (jQuery #13807)
2104 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
2105 fn( elem, name, !documentIsHTML ) :
2108 return val !== undefined ?
2110 support.attributes || !documentIsHTML ?
2111 elem.getAttribute( name ) :
2112 ( val = elem.getAttributeNode( name ) ) && val.specified ?
2117 Sizzle.escape = function( sel ) {
2118 return ( sel + "" ).replace( rcssescape, fcssescape );
2121 Sizzle.error = function( msg ) {
2122 throw new Error( "Syntax error, unrecognized expression: " + msg );
2126 * Document sorting and removing duplicates
2127 * @param {ArrayLike} results
2129 Sizzle.uniqueSort = function( results ) {
2135 // Unless we *know* we can detect duplicates, assume their presence
2136 hasDuplicate = !support.detectDuplicates;
2137 sortInput = !support.sortStable && results.slice( 0 );
2138 results.sort( sortOrder );
2140 if ( hasDuplicate ) {
2141 while ( ( elem = results[ i++ ] ) ) {
2142 if ( elem === results[ i ] ) {
2143 j = duplicates.push( i );
2147 results.splice( duplicates[ j ], 1 );
2151 // Clear input after sorting to release objects
2152 // See https://github.com/jquery/sizzle/pull/225
2159 * Utility function for retrieving the text value of an array of DOM nodes
2160 * @param {Array|Element} elem
2162 getText = Sizzle.getText = function( elem ) {
2166 nodeType = elem.nodeType;
2170 // If no nodeType, this is expected to be an array
2171 while ( ( node = elem[ i++ ] ) ) {
2173 // Do not traverse comment nodes
2174 ret += getText( node );
2176 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
2178 // Use textContent for elements
2179 // innerText usage removed for consistency of new lines (jQuery #11153)
2180 if ( typeof elem.textContent === "string" ) {
2181 return elem.textContent;
2184 // Traverse its children
2185 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2186 ret += getText( elem );
2189 } else if ( nodeType === 3 || nodeType === 4 ) {
2190 return elem.nodeValue;
2193 // Do not include comment or processing instruction nodes
2198 Expr = Sizzle.selectors = {
2200 // Can be adjusted by the user
2203 createPseudo: markFunction,
2212 ">": { dir: "parentNode", first: true },
2213 " ": { dir: "parentNode" },
2214 "+": { dir: "previousSibling", first: true },
2215 "~": { dir: "previousSibling" }
2219 "ATTR": function( match ) {
2220 match[ 1 ] = match[ 1 ].replace( runescape, funescape );
2222 // Move the given value to match[3] whether quoted or unquoted
2223 match[ 3 ] = ( match[ 3 ] || match[ 4 ] ||
2224 match[ 5 ] || "" ).replace( runescape, funescape );
2226 if ( match[ 2 ] === "~=" ) {
2227 match[ 3 ] = " " + match[ 3 ] + " ";
2230 return match.slice( 0, 4 );
2233 "CHILD": function( match ) {
2235 /* matches from matchExpr["CHILD"]
2236 1 type (only|nth|...)
2237 2 what (child|of-type)
2238 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
2239 4 xn-component of xn+y argument ([+-]?\d*n|)
2240 5 sign of xn-component
2242 7 sign of y-component
2245 match[ 1 ] = match[ 1 ].toLowerCase();
2247 if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {
2249 // nth-* requires argument
2250 if ( !match[ 3 ] ) {
2251 Sizzle.error( match[ 0 ] );
2254 // numeric x and y parameters for Expr.filter.CHILD
2255 // remember that false/true cast respectively to 0/1
2256 match[ 4 ] = +( match[ 4 ] ?
2257 match[ 5 ] + ( match[ 6 ] || 1 ) :
2258 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) );
2259 match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );
2261 // other types prohibit arguments
2262 } else if ( match[ 3 ] ) {
2263 Sizzle.error( match[ 0 ] );
2269 "PSEUDO": function( match ) {
2271 unquoted = !match[ 6 ] && match[ 2 ];
2273 if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) {
2277 // Accept quoted arguments as-is
2279 match[ 2 ] = match[ 4 ] || match[ 5 ] || "";
2281 // Strip excess characters from unquoted arguments
2282 } else if ( unquoted && rpseudo.test( unquoted ) &&
2284 // Get excess from tokenize (recursively)
2285 ( excess = tokenize( unquoted, true ) ) &&
2287 // advance to the next closing parenthesis
2288 ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) {
2290 // excess is a negative index
2291 match[ 0 ] = match[ 0 ].slice( 0, excess );
2292 match[ 2 ] = unquoted.slice( 0, excess );
2295 // Return only captures needed by the pseudo filter method (type and argument)
2296 return match.slice( 0, 3 );
2302 "TAG": function( nodeNameSelector ) {
2303 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
2304 return nodeNameSelector === "*" ?
2309 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
2313 "CLASS": function( className ) {
2314 var pattern = classCache[ className + " " ];
2317 ( pattern = new RegExp( "(^|" + whitespace +
2318 ")" + className + "(" + whitespace + "|$)" ) ) && classCache(
2319 className, function( elem ) {
2320 return pattern.test(
2321 typeof elem.className === "string" && elem.className ||
2322 typeof elem.getAttribute !== "undefined" &&
2323 elem.getAttribute( "class" ) ||
2329 "ATTR": function( name, operator, check ) {
2330 return function( elem ) {
2331 var result = Sizzle.attr( elem, name );
2333 if ( result == null ) {
2334 return operator === "!=";
2342 /* eslint-disable max-len */
2344 return operator === "=" ? result === check :
2345 operator === "!=" ? result !== check :
2346 operator === "^=" ? check && result.indexOf( check ) === 0 :
2347 operator === "*=" ? check && result.indexOf( check ) > -1 :
2348 operator === "$=" ? check && result.slice( -check.length ) === check :
2349 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
2350 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
2352 /* eslint-enable max-len */
2357 "CHILD": function( type, what, _argument, first, last ) {
2358 var simple = type.slice( 0, 3 ) !== "nth",
2359 forward = type.slice( -4 ) !== "last",
2360 ofType = what === "of-type";
2362 return first === 1 && last === 0 ?
2364 // Shortcut for :nth-*(n)
2366 return !!elem.parentNode;
2369 function( elem, _context, xml ) {
2370 var cache, uniqueCache, outerCache, node, nodeIndex, start,
2371 dir = simple !== forward ? "nextSibling" : "previousSibling",
2372 parent = elem.parentNode,
2373 name = ofType && elem.nodeName.toLowerCase(),
2374 useCache = !xml && !ofType,
2379 // :(first|last|only)-(child|of-type)
2383 while ( ( node = node[ dir ] ) ) {
2385 node.nodeName.toLowerCase() === name :
2386 node.nodeType === 1 ) {
2392 // Reverse direction for :only-* (if we haven't yet done so)
2393 start = dir = type === "only" && !start && "nextSibling";
2398 start = [ forward ? parent.firstChild : parent.lastChild ];
2400 // non-xml :nth-child(...) stores cache data on `parent`
2401 if ( forward && useCache ) {
2403 // Seek `elem` from a previously-cached index
2405 // ...in a gzip-friendly way
2407 outerCache = node[ expando ] || ( node[ expando ] = {} );
2409 // Support: IE <9 only
2410 // Defend against cloned attroperties (jQuery gh-1709)
2411 uniqueCache = outerCache[ node.uniqueID ] ||
2412 ( outerCache[ node.uniqueID ] = {} );
2414 cache = uniqueCache[ type ] || [];
2415 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
2416 diff = nodeIndex && cache[ 2 ];
2417 node = nodeIndex && parent.childNodes[ nodeIndex ];
2419 while ( ( node = ++nodeIndex && node && node[ dir ] ||
2421 // Fallback to seeking `elem` from the start
2422 ( diff = nodeIndex = 0 ) || start.pop() ) ) {
2424 // When found, cache indexes on `parent` and break
2425 if ( node.nodeType === 1 && ++diff && node === elem ) {
2426 uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
2433 // Use previously-cached element index if available
2436 // ...in a gzip-friendly way
2438 outerCache = node[ expando ] || ( node[ expando ] = {} );
2440 // Support: IE <9 only
2441 // Defend against cloned attroperties (jQuery gh-1709)
2442 uniqueCache = outerCache[ node.uniqueID ] ||
2443 ( outerCache[ node.uniqueID ] = {} );
2445 cache = uniqueCache[ type ] || [];
2446 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
2450 // xml :nth-child(...)
2451 // or :nth-last-child(...) or :nth(-last)?-of-type(...)
2452 if ( diff === false ) {
2454 // Use the same loop as above to seek `elem` from the start
2455 while ( ( node = ++nodeIndex && node && node[ dir ] ||
2456 ( diff = nodeIndex = 0 ) || start.pop() ) ) {
2459 node.nodeName.toLowerCase() === name :
2460 node.nodeType === 1 ) &&
2463 // Cache the index of each encountered element
2465 outerCache = node[ expando ] ||
2466 ( node[ expando ] = {} );
2468 // Support: IE <9 only
2469 // Defend against cloned attroperties (jQuery gh-1709)
2470 uniqueCache = outerCache[ node.uniqueID ] ||
2471 ( outerCache[ node.uniqueID ] = {} );
2473 uniqueCache[ type ] = [ dirruns, diff ];
2476 if ( node === elem ) {
2484 // Incorporate the offset, then check against cycle size
2486 return diff === first || ( diff % first === 0 && diff / first >= 0 );
2491 "PSEUDO": function( pseudo, argument ) {
2493 // pseudo-class names are case-insensitive
2494 // http://www.w3.org/TR/selectors/#pseudo-classes
2495 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
2496 // Remember that setFilters inherits from pseudos
2498 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
2499 Sizzle.error( "unsupported pseudo: " + pseudo );
2501 // The user may use createPseudo to indicate that
2502 // arguments are needed to create the filter function
2503 // just as Sizzle does
2504 if ( fn[ expando ] ) {
2505 return fn( argument );
2508 // But maintain support for old signatures
2509 if ( fn.length > 1 ) {
2510 args = [ pseudo, pseudo, "", argument ];
2511 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
2512 markFunction( function( seed, matches ) {
2514 matched = fn( seed, argument ),
2517 idx = indexOf( seed, matched[ i ] );
2518 seed[ idx ] = !( matches[ idx ] = matched[ i ] );
2522 return fn( elem, 0, args );
2532 // Potentially complex pseudos
2533 "not": markFunction( function( selector ) {
2535 // Trim the selector passed to compile
2536 // to avoid treating leading and trailing
2537 // spaces as combinators
2540 matcher = compile( selector.replace( rtrim, "$1" ) );
2542 return matcher[ expando ] ?
2543 markFunction( function( seed, matches, _context, xml ) {
2545 unmatched = matcher( seed, null, xml, [] ),
2548 // Match elements unmatched by `matcher`
2550 if ( ( elem = unmatched[ i ] ) ) {
2551 seed[ i ] = !( matches[ i ] = elem );
2555 function( elem, _context, xml ) {
2557 matcher( input, null, xml, results );
2559 // Don't keep the element (issue #299)
2561 return !results.pop();
2565 "has": markFunction( function( selector ) {
2566 return function( elem ) {
2567 return Sizzle( selector, elem ).length > 0;
2571 "contains": markFunction( function( text ) {
2572 text = text.replace( runescape, funescape );
2573 return function( elem ) {
2574 return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
2578 // "Whether an element is represented by a :lang() selector
2579 // is based solely on the element's language value
2580 // being equal to the identifier C,
2581 // or beginning with the identifier C immediately followed by "-".
2582 // The matching of C against the element's language value is performed case-insensitively.
2583 // The identifier C does not have to be a valid language name."
2584 // http://www.w3.org/TR/selectors/#lang-pseudo
2585 "lang": markFunction( function( lang ) {
2587 // lang value must be a valid identifier
2588 if ( !ridentifier.test( lang || "" ) ) {
2589 Sizzle.error( "unsupported lang: " + lang );
2591 lang = lang.replace( runescape, funescape ).toLowerCase();
2592 return function( elem ) {
2595 if ( ( elemLang = documentIsHTML ?
2597 elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
2599 elemLang = elemLang.toLowerCase();
2600 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
2602 } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
2608 "target": function( elem ) {
2609 var hash = window.location && window.location.hash;
2610 return hash && hash.slice( 1 ) === elem.id;
2613 "root": function( elem ) {
2614 return elem === docElem;
2617 "focus": function( elem ) {
2618 return elem === document.activeElement &&
2619 ( !document.hasFocus || document.hasFocus() ) &&
2620 !!( elem.type || elem.href || ~elem.tabIndex );
2623 // Boolean properties
2624 "enabled": createDisabledPseudo( false ),
2625 "disabled": createDisabledPseudo( true ),
2627 "checked": function( elem ) {
2629 // In CSS3, :checked should return both checked and selected elements
2630 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2631 var nodeName = elem.nodeName.toLowerCase();
2632 return ( nodeName === "input" && !!elem.checked ) ||
2633 ( nodeName === "option" && !!elem.selected );
2636 "selected": function( elem ) {
2638 // Accessing this property makes selected-by-default
2639 // options in Safari work properly
2640 if ( elem.parentNode ) {
2641 // eslint-disable-next-line no-unused-expressions
2642 elem.parentNode.selectedIndex;
2645 return elem.selected === true;
2649 "empty": function( elem ) {
2651 // http://www.w3.org/TR/selectors/#empty-pseudo
2652 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
2653 // but not by others (comment: 8; processing instruction: 7; etc.)
2654 // nodeType < 6 works because attributes (2) do not appear as children
2655 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2656 if ( elem.nodeType < 6 ) {
2663 "parent": function( elem ) {
2664 return !Expr.pseudos[ "empty" ]( elem );
2667 // Element/input types
2668 "header": function( elem ) {
2669 return rheader.test( elem.nodeName );
2672 "input": function( elem ) {
2673 return rinputs.test( elem.nodeName );
2676 "button": function( elem ) {
2677 var name = elem.nodeName.toLowerCase();
2678 return name === "input" && elem.type === "button" || name === "button";
2681 "text": function( elem ) {
2683 return elem.nodeName.toLowerCase() === "input" &&
2684 elem.type === "text" &&
2687 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
2688 ( ( attr = elem.getAttribute( "type" ) ) == null ||
2689 attr.toLowerCase() === "text" );
2692 // Position-in-collection
2693 "first": createPositionalPseudo( function() {
2697 "last": createPositionalPseudo( function( _matchIndexes, length ) {
2698 return [ length - 1 ];
2701 "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) {
2702 return [ argument < 0 ? argument + length : argument ];
2705 "even": createPositionalPseudo( function( matchIndexes, length ) {
2707 for ( ; i < length; i += 2 ) {
2708 matchIndexes.push( i );
2710 return matchIndexes;
2713 "odd": createPositionalPseudo( function( matchIndexes, length ) {
2715 for ( ; i < length; i += 2 ) {
2716 matchIndexes.push( i );
2718 return matchIndexes;
2721 "lt": createPositionalPseudo( function( matchIndexes, length, argument ) {
2722 var i = argument < 0 ?
2727 for ( ; --i >= 0; ) {
2728 matchIndexes.push( i );
2730 return matchIndexes;
2733 "gt": createPositionalPseudo( function( matchIndexes, length, argument ) {
2734 var i = argument < 0 ? argument + length : argument;
2735 for ( ; ++i < length; ) {
2736 matchIndexes.push( i );
2738 return matchIndexes;
2743 Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ];
2745 // Add button/input type pseudos
2746 for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2747 Expr.pseudos[ i ] = createInputPseudo( i );
2749 for ( i in { submit: true, reset: true } ) {
2750 Expr.pseudos[ i ] = createButtonPseudo( i );
2753 // Easy API for creating new setFilters
2754 function setFilters() {}
2755 setFilters.prototype = Expr.filters = Expr.pseudos;
2756 Expr.setFilters = new setFilters();
2758 tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2759 var matched, match, tokens, type,
2760 soFar, groups, preFilters,
2761 cached = tokenCache[ selector + " " ];
2764 return parseOnly ? 0 : cached.slice( 0 );
2769 preFilters = Expr.preFilter;
2773 // Comma and first run
2774 if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
2777 // Don't consume trailing commas as valid
2778 soFar = soFar.slice( match[ 0 ].length ) || soFar;
2780 groups.push( ( tokens = [] ) );
2786 if ( ( match = rcombinators.exec( soFar ) ) ) {
2787 matched = match.shift();
2791 // Cast descendant combinators to space
2792 type: match[ 0 ].replace( rtrim, " " )
2794 soFar = soFar.slice( matched.length );
2798 for ( type in Expr.filter ) {
2799 if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
2800 ( match = preFilters[ type ]( match ) ) ) ) {
2801 matched = match.shift();
2807 soFar = soFar.slice( matched.length );
2816 // Return the length of the invalid excess
2817 // if we're just parsing
2818 // Otherwise, throw an error or return tokens
2822 Sizzle.error( selector ) :
2825 tokenCache( selector, groups ).slice( 0 );
2828 function toSelector( tokens ) {
2830 len = tokens.length,
2832 for ( ; i < len; i++ ) {
2833 selector += tokens[ i ].value;
2838 function addCombinator( matcher, combinator, base ) {
2839 var dir = combinator.dir,
2840 skip = combinator.next,
2842 checkNonElements = base && key === "parentNode",
2845 return combinator.first ?
2847 // Check against closest ancestor/preceding element
2848 function( elem, context, xml ) {
2849 while ( ( elem = elem[ dir ] ) ) {
2850 if ( elem.nodeType === 1 || checkNonElements ) {
2851 return matcher( elem, context, xml );
2857 // Check against all ancestor/preceding elements
2858 function( elem, context, xml ) {
2859 var oldCache, uniqueCache, outerCache,
2860 newCache = [ dirruns, doneName ];
2862 // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
2864 while ( ( elem = elem[ dir ] ) ) {
2865 if ( elem.nodeType === 1 || checkNonElements ) {
2866 if ( matcher( elem, context, xml ) ) {
2872 while ( ( elem = elem[ dir ] ) ) {
2873 if ( elem.nodeType === 1 || checkNonElements ) {
2874 outerCache = elem[ expando ] || ( elem[ expando ] = {} );
2876 // Support: IE <9 only
2877 // Defend against cloned attroperties (jQuery gh-1709)
2878 uniqueCache = outerCache[ elem.uniqueID ] ||
2879 ( outerCache[ elem.uniqueID ] = {} );
2881 if ( skip && skip === elem.nodeName.toLowerCase() ) {
2882 elem = elem[ dir ] || elem;
2883 } else if ( ( oldCache = uniqueCache[ key ] ) &&
2884 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2886 // Assign to newCache so results back-propagate to previous elements
2887 return ( newCache[ 2 ] = oldCache[ 2 ] );
2890 // Reuse newcache so results back-propagate to previous elements
2891 uniqueCache[ key ] = newCache;
2893 // A match means we're done; a fail means we have to keep checking
2894 if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
2905 function elementMatcher( matchers ) {
2906 return matchers.length > 1 ?
2907 function( elem, context, xml ) {
2908 var i = matchers.length;
2910 if ( !matchers[ i ]( elem, context, xml ) ) {
2919 function multipleContexts( selector, contexts, results ) {
2921 len = contexts.length;
2922 for ( ; i < len; i++ ) {
2923 Sizzle( selector, contexts[ i ], results );
2928 function condense( unmatched, map, filter, context, xml ) {
2932 len = unmatched.length,
2933 mapped = map != null;
2935 for ( ; i < len; i++ ) {
2936 if ( ( elem = unmatched[ i ] ) ) {
2937 if ( !filter || filter( elem, context, xml ) ) {
2938 newUnmatched.push( elem );
2946 return newUnmatched;
2949 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2950 if ( postFilter && !postFilter[ expando ] ) {
2951 postFilter = setMatcher( postFilter );
2953 if ( postFinder && !postFinder[ expando ] ) {
2954 postFinder = setMatcher( postFinder, postSelector );
2956 return markFunction( function( seed, results, context, xml ) {
2960 preexisting = results.length,
2962 // Get initial elements from seed or context
2963 elems = seed || multipleContexts(
2965 context.nodeType ? [ context ] : context,
2969 // Prefilter to get matcher input, preserving a map for seed-results synchronization
2970 matcherIn = preFilter && ( seed || !selector ) ?
2971 condense( elems, preMap, preFilter, context, xml ) :
2974 matcherOut = matcher ?
2976 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2977 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2979 // ...intermediate processing is necessary
2982 // ...otherwise use results directly
2986 // Find primary matches
2988 matcher( matcherIn, matcherOut, context, xml );
2993 temp = condense( matcherOut, postMap );
2994 postFilter( temp, [], context, xml );
2996 // Un-match failing elements by moving them back to matcherIn
2999 if ( ( elem = temp[ i ] ) ) {
3000 matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
3006 if ( postFinder || preFilter ) {
3009 // Get the final matcherOut by condensing this intermediate into postFinder contexts
3011 i = matcherOut.length;
3013 if ( ( elem = matcherOut[ i ] ) ) {
3015 // Restore matcherIn since elem is not yet a final match
3016 temp.push( ( matcherIn[ i ] = elem ) );
3019 postFinder( null, ( matcherOut = [] ), temp, xml );
3022 // Move matched elements from seed to results to keep them synchronized
3023 i = matcherOut.length;
3025 if ( ( elem = matcherOut[ i ] ) &&
3026 ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) {
3028 seed[ temp ] = !( results[ temp ] = elem );
3033 // Add elements to results, through postFinder if defined
3035 matcherOut = condense(
3036 matcherOut === results ?
3037 matcherOut.splice( preexisting, matcherOut.length ) :
3041 postFinder( null, results, matcherOut, xml );
3043 push.apply( results, matcherOut );
3049 function matcherFromTokens( tokens ) {
3050 var checkContext, matcher, j,
3051 len = tokens.length,
3052 leadingRelative = Expr.relative[ tokens[ 0 ].type ],
3053 implicitRelative = leadingRelative || Expr.relative[ " " ],
3054 i = leadingRelative ? 1 : 0,
3056 // The foundational matcher ensures that elements are reachable from top-level context(s)
3057 matchContext = addCombinator( function( elem ) {
3058 return elem === checkContext;
3059 }, implicitRelative, true ),
3060 matchAnyContext = addCombinator( function( elem ) {
3061 return indexOf( checkContext, elem ) > -1;
3062 }, implicitRelative, true ),
3063 matchers = [ function( elem, context, xml ) {
3064 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
3065 ( checkContext = context ).nodeType ?
3066 matchContext( elem, context, xml ) :
3067 matchAnyContext( elem, context, xml ) );
3069 // Avoid hanging onto element (issue #299)
3070 checkContext = null;
3074 for ( ; i < len; i++ ) {
3075 if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
3076 matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
3078 matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
3080 // Return special upon seeing a positional matcher
3081 if ( matcher[ expando ] ) {
3083 // Find the next relative operator (if any) for proper handling
3085 for ( ; j < len; j++ ) {
3086 if ( Expr.relative[ tokens[ j ].type ] ) {
3091 i > 1 && elementMatcher( matchers ),
3092 i > 1 && toSelector(
3094 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
3097 .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
3098 ).replace( rtrim, "$1" ),
3100 i < j && matcherFromTokens( tokens.slice( i, j ) ),
3101 j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
3102 j < len && toSelector( tokens )
3105 matchers.push( matcher );
3109 return elementMatcher( matchers );
3112 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
3113 var bySet = setMatchers.length > 0,
3114 byElement = elementMatchers.length > 0,
3115 superMatcher = function( seed, context, xml, results, outermost ) {
3116 var elem, j, matcher,
3119 unmatched = seed && [],
3121 contextBackup = outermostContext,
3123 // We must always have either seed elements or outermost context
3124 elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ),
3126 // Use integer dirruns iff this is the outermost matcher
3127 dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
3132 // Support: IE 11+, Edge 17 - 18+
3133 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
3134 // two documents; shallow comparisons work.
3135 // eslint-disable-next-line eqeqeq
3136 outermostContext = context == document || context || outermost;
3139 // Add elements passing elementMatchers directly to results
3140 // Support: IE<9, Safari
3141 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
3142 for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
3143 if ( byElement && elem ) {
3146 // Support: IE 11+, Edge 17 - 18+
3147 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
3148 // two documents; shallow comparisons work.
3149 // eslint-disable-next-line eqeqeq
3150 if ( !context && elem.ownerDocument != document ) {
3151 setDocument( elem );
3152 xml = !documentIsHTML;
3154 while ( ( matcher = elementMatchers[ j++ ] ) ) {
3155 if ( matcher( elem, context || document, xml ) ) {
3156 results.push( elem );
3161 dirruns = dirrunsUnique;
3165 // Track unmatched elements for set filters
3168 // They will have gone through all possible matchers
3169 if ( ( elem = !matcher && elem ) ) {
3173 // Lengthen the array for every element, matched or not
3175 unmatched.push( elem );
3180 // `i` is now the count of elements visited above, and adding it to `matchedCount`
3181 // makes the latter nonnegative.
3184 // Apply set filters to unmatched elements
3185 // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
3186 // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
3187 // no element matchers and no seed.
3188 // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
3189 // case, which will result in a "00" `matchedCount` that differs from `i` but is also
3190 // numerically zero.
3191 if ( bySet && i !== matchedCount ) {
3193 while ( ( matcher = setMatchers[ j++ ] ) ) {
3194 matcher( unmatched, setMatched, context, xml );
3199 // Reintegrate element matches to eliminate the need for sorting
3200 if ( matchedCount > 0 ) {
3202 if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
3203 setMatched[ i ] = pop.call( results );
3208 // Discard index placeholder values to get only actual matches
3209 setMatched = condense( setMatched );
3212 // Add matches to results
3213 push.apply( results, setMatched );
3215 // Seedless set matches succeeding multiple successful matchers stipulate sorting
3216 if ( outermost && !seed && setMatched.length > 0 &&
3217 ( matchedCount + setMatchers.length ) > 1 ) {
3219 Sizzle.uniqueSort( results );
3223 // Override manipulation of globals by nested matchers
3225 dirruns = dirrunsUnique;
3226 outermostContext = contextBackup;
3233 markFunction( superMatcher ) :
3237 compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
3240 elementMatchers = [],
3241 cached = compilerCache[ selector + " " ];
3245 // Generate a function of recursive functions that can be used to check each element
3247 match = tokenize( selector );
3251 cached = matcherFromTokens( match[ i ] );
3252 if ( cached[ expando ] ) {
3253 setMatchers.push( cached );
3255 elementMatchers.push( cached );
3259 // Cache the compiled function
3260 cached = compilerCache(
3262 matcherFromGroupMatchers( elementMatchers, setMatchers )
3265 // Save selector and tokenization
3266 cached.selector = selector;
3272 * A low-level selection function that works with Sizzle's compiled
3273 * selector functions
3274 * @param {String|Function} selector A selector or a pre-compiled
3275 * selector function built with Sizzle.compile
3276 * @param {Element} context
3277 * @param {Array} [results]
3278 * @param {Array} [seed] A set of elements to match against
3280 select = Sizzle.select = function( selector, context, results, seed ) {
3281 var i, tokens, token, type, find,
3282 compiled = typeof selector === "function" && selector,
3283 match = !seed && tokenize( ( selector = compiled.selector || selector ) );
3285 results = results || [];
3287 // Try to minimize operations if there is only one selector in the list and no seed
3288 // (the latter of which guarantees us context)
3289 if ( match.length === 1 ) {
3291 // Reduce context if the leading compound selector is an ID
3292 tokens = match[ 0 ] = match[ 0 ].slice( 0 );
3293 if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
3294 context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
3296 context = ( Expr.find[ "ID" ]( token.matches[ 0 ]
3297 .replace( runescape, funescape ), context ) || [] )[ 0 ];
3301 // Precompiled matchers will still verify ancestry, so step up a level
3302 } else if ( compiled ) {
3303 context = context.parentNode;
3306 selector = selector.slice( tokens.shift().value.length );
3309 // Fetch a seed set for right-to-left matching
3310 i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length;
3312 token = tokens[ i ];
3314 // Abort if we hit a combinator
3315 if ( Expr.relative[ ( type = token.type ) ] ) {
3318 if ( ( find = Expr.find[ type ] ) ) {
3320 // Search, expanding context for leading sibling combinators
3322 token.matches[ 0 ].replace( runescape, funescape ),
3323 rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||
3327 // If seed is empty or no tokens remain, we can return early
3328 tokens.splice( i, 1 );
3329 selector = seed.length && toSelector( tokens );
3331 push.apply( results, seed );
3341 // Compile and execute a filtering function if one is not provided
3342 // Provide `match` to avoid retokenization if we modified the selector above
3343 ( compiled || compile( selector, match ) )(
3348 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
3353 // One-time assignments
3356 support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;
3358 // Support: Chrome 14-35+
3359 // Always assume duplicates if they aren't passed to the comparison function
3360 support.detectDuplicates = !!hasDuplicate;
3362 // Initialize against the default document
3365 // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
3366 // Detached nodes confoundingly follow *each other*
3367 support.sortDetached = assert( function( el ) {
3369 // Should return 1, but returns 4 (following)
3370 return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
3374 // Prevent attribute/property "interpolation"
3375 // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
3376 if ( !assert( function( el ) {
3377 el.innerHTML = "<a href='#'></a>";
3378 return el.firstChild.getAttribute( "href" ) === "#";
3380 addHandle( "type|href|height|width", function( elem, name, isXML ) {
3382 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
3388 // Use defaultValue in place of getAttribute("value")
3389 if ( !support.attributes || !assert( function( el ) {
3390 el.innerHTML = "<input/>";
3391 el.firstChild.setAttribute( "value", "" );
3392 return el.firstChild.getAttribute( "value" ) === "";
3394 addHandle( "value", function( elem, _name, isXML ) {
3395 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
3396 return elem.defaultValue;
3402 // Use getAttributeNode to fetch booleans when getAttribute lies
3403 if ( !assert( function( el ) {
3404 return el.getAttribute( "disabled" ) == null;
3406 addHandle( booleans, function( elem, name, isXML ) {
3409 return elem[ name ] === true ? name.toLowerCase() :
3410 ( val = elem.getAttributeNode( name ) ) && val.specified ?
3423 jQuery.find = Sizzle;
3424 jQuery.expr = Sizzle.selectors;
3427 jQuery.expr[ ":" ] = jQuery.expr.pseudos;
3428 jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
3429 jQuery.text = Sizzle.getText;
3430 jQuery.isXMLDoc = Sizzle.isXML;
3431 jQuery.contains = Sizzle.contains;
3432 jQuery.escapeSelector = Sizzle.escape;
3437 var dir = function( elem, dir, until ) {
3439 truncate = until !== undefined;
3441 while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
3442 if ( elem.nodeType === 1 ) {
3443 if ( truncate && jQuery( elem ).is( until ) ) {
3446 matched.push( elem );
3453 var siblings = function( n, elem ) {
3456 for ( ; n; n = n.nextSibling ) {
3457 if ( n.nodeType === 1 && n !== elem ) {
3466 var rneedsContext = jQuery.expr.match.needsContext;
3470 function nodeName( elem, name ) {
3472 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
3474 }var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
3478 // Implement the identical functionality for filter and not
3479 function winnow( elements, qualifier, not ) {
3480 if ( isFunction( qualifier ) ) {
3481 return jQuery.grep( elements, function( elem, i ) {
3482 return !!qualifier.call( elem, i, elem ) !== not;
3487 if ( qualifier.nodeType ) {
3488 return jQuery.grep( elements, function( elem ) {
3489 return ( elem === qualifier ) !== not;
3493 // Arraylike of elements (jQuery, arguments, Array)
3494 if ( typeof qualifier !== "string" ) {
3495 return jQuery.grep( elements, function( elem ) {
3496 return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
3500 // Filtered directly for both simple and complex selectors
3501 return jQuery.filter( qualifier, elements, not );
3504 jQuery.filter = function( expr, elems, not ) {
3505 var elem = elems[ 0 ];
3508 expr = ":not(" + expr + ")";
3511 if ( elems.length === 1 && elem.nodeType === 1 ) {
3512 return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
3515 return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
3516 return elem.nodeType === 1;
3521 find: function( selector ) {
3526 if ( typeof selector !== "string" ) {
3527 return this.pushStack( jQuery( selector ).filter( function() {
3528 for ( i = 0; i < len; i++ ) {
3529 if ( jQuery.contains( self[ i ], this ) ) {
3536 ret = this.pushStack( [] );
3538 for ( i = 0; i < len; i++ ) {
3539 jQuery.find( selector, self[ i ], ret );
3542 return len > 1 ? jQuery.uniqueSort( ret ) : ret;
3544 filter: function( selector ) {
3545 return this.pushStack( winnow( this, selector || [], false ) );
3547 not: function( selector ) {
3548 return this.pushStack( winnow( this, selector || [], true ) );
3550 is: function( selector ) {
3554 // If this is a positional/relative selector, check membership in the returned set
3555 // so $("p:first").is("p:last") won't return true for a doc with two "p".
3556 typeof selector === "string" && rneedsContext.test( selector ) ?
3557 jQuery( selector ) :
3565 // Initialize a jQuery object
3568 // A central reference to the root jQuery(document)
3571 // A simple way to check for HTML strings
3572 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
3573 // Strict HTML recognition (#11290: must start with <)
3574 // Shortcut simple #id case for speed
3575 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
3577 init = jQuery.fn.init = function( selector, context, root ) {
3580 // HANDLE: $(""), $(null), $(undefined), $(false)
3585 // Method init() accepts an alternate rootjQuery
3586 // so migrate can support jQuery.sub (gh-2101)
3587 root = root || rootjQuery;
3589 // Handle HTML strings
3590 if ( typeof selector === "string" ) {
3591 if ( selector[ 0 ] === "<" &&
3592 selector[ selector.length - 1 ] === ">" &&
3593 selector.length >= 3 ) {
3595 // Assume that strings that start and end with <> are HTML and skip the regex check
3596 match = [ null, selector, null ];
3599 match = rquickExpr.exec( selector );
3602 // Match html or make sure no context is specified for #id
3603 if ( match && ( match[ 1 ] || !context ) ) {
3605 // HANDLE: $(html) -> $(array)
3607 context = context instanceof jQuery ? context[ 0 ] : context;
3609 // Option to run scripts is true for back-compat
3610 // Intentionally let the error be thrown if parseHTML is not present
3611 jQuery.merge( this, jQuery.parseHTML(
3613 context && context.nodeType ? context.ownerDocument || context : document,
3617 // HANDLE: $(html, props)
3618 if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
3619 for ( match in context ) {
3621 // Properties of context are called as methods if possible
3622 if ( isFunction( this[ match ] ) ) {
3623 this[ match ]( context[ match ] );
3625 // ...and otherwise set as attributes
3627 this.attr( match, context[ match ] );
3636 elem = document.getElementById( match[ 2 ] );
3640 // Inject the element directly into the jQuery object
3647 // HANDLE: $(expr, $(...))
3648 } else if ( !context || context.jquery ) {
3649 return ( context || root ).find( selector );
3651 // HANDLE: $(expr, context)
3652 // (which is just equivalent to: $(context).find(expr)
3654 return this.constructor( context ).find( selector );
3657 // HANDLE: $(DOMElement)
3658 } else if ( selector.nodeType ) {
3659 this[ 0 ] = selector;
3663 // HANDLE: $(function)
3664 // Shortcut for document ready
3665 } else if ( isFunction( selector ) ) {
3666 return root.ready !== undefined ?
3667 root.ready( selector ) :
3669 // Execute immediately if ready is not present
3673 return jQuery.makeArray( selector, this );
3676 // Give the init function the jQuery prototype for later instantiation
3677 init.prototype = jQuery.fn;
3679 // Initialize central reference
3680 rootjQuery = jQuery( document );
3683 var rparentsprev = /^(?:parents|prev(?:Until|All))/,
3685 // Methods guaranteed to produce a unique set when starting from a unique set
3686 guaranteedUnique = {
3694 has: function( target ) {
3695 var targets = jQuery( target, this ),
3698 return this.filter( function() {
3700 for ( ; i < l; i++ ) {
3701 if ( jQuery.contains( this, targets[ i ] ) ) {
3708 closest: function( selectors, context ) {
3713 targets = typeof selectors !== "string" && jQuery( selectors );
3715 // Positional selectors never match, since there's no _selection_ context
3716 if ( !rneedsContext.test( selectors ) ) {
3717 for ( ; i < l; i++ ) {
3718 for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
3720 // Always skip document fragments
3721 if ( cur.nodeType < 11 && ( targets ?
3722 targets.index( cur ) > -1 :
3724 // Don't pass non-elements to Sizzle
3725 cur.nodeType === 1 &&
3726 jQuery.find.matchesSelector( cur, selectors ) ) ) {
3728 matched.push( cur );
3735 return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
3738 // Determine the position of an element within the set
3739 index: function( elem ) {
3741 // No argument, return index in parent
3743 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
3746 // Index in selector
3747 if ( typeof elem === "string" ) {
3748 return indexOf.call( jQuery( elem ), this[ 0 ] );
3751 // Locate the position of the desired element
3752 return indexOf.call( this,
3754 // If it receives a jQuery object, the first element is used
3755 elem.jquery ? elem[ 0 ] : elem
3759 add: function( selector, context ) {
3760 return this.pushStack(
3762 jQuery.merge( this.get(), jQuery( selector, context ) )
3767 addBack: function( selector ) {
3768 return this.add( selector == null ?
3769 this.prevObject : this.prevObject.filter( selector )
3774 function sibling( cur, dir ) {
3775 while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
3780 parent: function( elem ) {
3781 var parent = elem.parentNode;
3782 return parent && parent.nodeType !== 11 ? parent : null;
3784 parents: function( elem ) {
3785 return dir( elem, "parentNode" );
3787 parentsUntil: function( elem, _i, until ) {
3788 return dir( elem, "parentNode", until );
3790 next: function( elem ) {
3791 return sibling( elem, "nextSibling" );
3793 prev: function( elem ) {
3794 return sibling( elem, "previousSibling" );
3796 nextAll: function( elem ) {
3797 return dir( elem, "nextSibling" );
3799 prevAll: function( elem ) {
3800 return dir( elem, "previousSibling" );
3802 nextUntil: function( elem, _i, until ) {
3803 return dir( elem, "nextSibling", until );
3805 prevUntil: function( elem, _i, until ) {
3806 return dir( elem, "previousSibling", until );
3808 siblings: function( elem ) {
3809 return siblings( ( elem.parentNode || {} ).firstChild, elem );
3811 children: function( elem ) {
3812 return siblings( elem.firstChild );
3814 contents: function( elem ) {
3815 if ( elem.contentDocument != null &&
3818 // <object> elements with no `data` attribute has an object
3819 // `contentDocument` with a `null` prototype.
3820 getProto( elem.contentDocument ) ) {
3822 return elem.contentDocument;
3825 // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
3826 // Treat the template element as a regular one in browsers that
3827 // don't support it.
3828 if ( nodeName( elem, "template" ) ) {
3829 elem = elem.content || elem;
3832 return jQuery.merge( [], elem.childNodes );
3834 }, function( name, fn ) {
3835 jQuery.fn[ name ] = function( until, selector ) {
3836 var matched = jQuery.map( this, fn, until );
3838 if ( name.slice( -5 ) !== "Until" ) {
3842 if ( selector && typeof selector === "string" ) {
3843 matched = jQuery.filter( selector, matched );
3846 if ( this.length > 1 ) {
3848 // Remove duplicates
3849 if ( !guaranteedUnique[ name ] ) {
3850 jQuery.uniqueSort( matched );
3853 // Reverse order for parents* and prev-derivatives
3854 if ( rparentsprev.test( name ) ) {
3859 return this.pushStack( matched );
3862 var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
3866 // Convert String-formatted options into Object-formatted ones
3867 function createOptions( options ) {
3869 jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
3870 object[ flag ] = true;
3876 * Create a callback list using the following parameters:
3878 * options: an optional list of space-separated options that will change how
3879 * the callback list behaves or a more traditional option object
3881 * By default a callback list will act like an event callback list and can be
3882 * "fired" multiple times.
3886 * once: will ensure the callback list can only be fired once (like a Deferred)
3888 * memory: will keep track of previous values and will call any callback added
3889 * after the list has been fired right away with the latest "memorized"
3890 * values (like a Deferred)
3892 * unique: will ensure a callback can only be added once (no duplicate in the list)
3894 * stopOnFalse: interrupt callings when a callback returns false
3897 jQuery.Callbacks = function( options ) {
3899 // Convert options from String-formatted to Object-formatted if needed
3900 // (we check in cache first)
3901 options = typeof options === "string" ?
3902 createOptions( options ) :
3903 jQuery.extend( {}, options );
3905 var // Flag to know if list is currently firing
3908 // Last fire value for non-forgettable lists
3911 // Flag to know if list was already fired
3914 // Flag to prevent firing
3917 // Actual callback list
3920 // Queue of execution data for repeatable lists
3923 // Index of currently firing callback (modified by add/remove as needed)
3929 // Enforce single-firing
3930 locked = locked || options.once;
3932 // Execute callbacks for all pending executions,
3933 // respecting firingIndex overrides and runtime changes
3934 fired = firing = true;
3935 for ( ; queue.length; firingIndex = -1 ) {
3936 memory = queue.shift();
3937 while ( ++firingIndex < list.length ) {
3939 // Run callback and check for early termination
3940 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
3941 options.stopOnFalse ) {
3943 // Jump to end and forget the data so .add doesn't re-fire
3944 firingIndex = list.length;
3950 // Forget the data if we're done with it
3951 if ( !options.memory ) {
3957 // Clean up if we're done firing for good
3960 // Keep an empty list if we have data for future add calls
3964 // Otherwise, this object is spent
3971 // Actual Callbacks object
3974 // Add a callback or a collection of callbacks to the list
3978 // If we have memory from a past run, we should fire after adding
3979 if ( memory && !firing ) {
3980 firingIndex = list.length - 1;
3981 queue.push( memory );
3984 ( function add( args ) {
3985 jQuery.each( args, function( _, arg ) {
3986 if ( isFunction( arg ) ) {
3987 if ( !options.unique || !self.has( arg ) ) {
3990 } else if ( arg && arg.length && toType( arg ) !== "string" ) {
3992 // Inspect recursively
3998 if ( memory && !firing ) {
4005 // Remove a callback from the list
4006 remove: function() {
4007 jQuery.each( arguments, function( _, arg ) {
4009 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
4010 list.splice( index, 1 );
4012 // Handle firing indexes
4013 if ( index <= firingIndex ) {
4021 // Check if a given callback is in the list.
4022 // If no argument is given, return whether or not list has callbacks attached.
4023 has: function( fn ) {
4025 jQuery.inArray( fn, list ) > -1 :
4029 // Remove all callbacks from the list
4037 // Disable .fire and .add
4038 // Abort any current/pending executions
4039 // Clear all callbacks and values
4040 disable: function() {
4041 locked = queue = [];
4045 disabled: function() {
4050 // Also disable .add unless we have memory (since it would have no effect)
4051 // Abort any pending executions
4053 locked = queue = [];
4054 if ( !memory && !firing ) {
4059 locked: function() {
4063 // Call all callbacks with the given context and arguments
4064 fireWith: function( context, args ) {
4067 args = [ context, args.slice ? args.slice() : args ];
4076 // Call all the callbacks with the given arguments
4078 self.fireWith( this, arguments );
4082 // To know if the callbacks have already been called at least once
4092 function Identity( v ) {
4095 function Thrower( ex ) {
4099 function adoptValue( value, resolve, reject, noValue ) {
4104 // Check for promise aspect first to privilege synchronous behavior
4105 if ( value && isFunction( ( method = value.promise ) ) ) {
4106 method.call( value ).done( resolve ).fail( reject );
4109 } else if ( value && isFunction( ( method = value.then ) ) ) {
4110 method.call( value, resolve, reject );
4112 // Other non-thenables
4115 // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
4116 // * false: [ value ].slice( 0 ) => resolve( value )
4117 // * true: [ value ].slice( 1 ) => resolve()
4118 resolve.apply( undefined, [ value ].slice( noValue ) );
4121 // For Promises/A+, convert exceptions into rejections
4122 // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
4123 // Deferred#then to conditionally suppress rejection.
4126 // Support: Android 4.0 only
4127 // Strict mode functions invoked without .call/.apply get global-object context
4128 reject.apply( undefined, [ value ] );
4134 Deferred: function( func ) {
4137 // action, add listener, callbacks,
4138 // ... .then handlers, argument index, [final state]
4139 [ "notify", "progress", jQuery.Callbacks( "memory" ),
4140 jQuery.Callbacks( "memory" ), 2 ],
4141 [ "resolve", "done", jQuery.Callbacks( "once memory" ),
4142 jQuery.Callbacks( "once memory" ), 0, "resolved" ],
4143 [ "reject", "fail", jQuery.Callbacks( "once memory" ),
4144 jQuery.Callbacks( "once memory" ), 1, "rejected" ]
4151 always: function() {
4152 deferred.done( arguments ).fail( arguments );
4155 "catch": function( fn ) {
4156 return promise.then( null, fn );
4159 // Keep pipe for back-compat
4160 pipe: function( /* fnDone, fnFail, fnProgress */ ) {
4161 var fns = arguments;
4163 return jQuery.Deferred( function( newDefer ) {
4164 jQuery.each( tuples, function( _i, tuple ) {
4166 // Map tuples (progress, done, fail) to arguments (done, fail, progress)
4167 var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
4169 // deferred.progress(function() { bind to newDefer or newDefer.notify })
4170 // deferred.done(function() { bind to newDefer or newDefer.resolve })
4171 // deferred.fail(function() { bind to newDefer or newDefer.reject })
4172 deferred[ tuple[ 1 ] ]( function() {
4173 var returned = fn && fn.apply( this, arguments );
4174 if ( returned && isFunction( returned.promise ) ) {
4176 .progress( newDefer.notify )
4177 .done( newDefer.resolve )
4178 .fail( newDefer.reject );
4180 newDefer[ tuple[ 0 ] + "With" ](
4182 fn ? [ returned ] : arguments
4190 then: function( onFulfilled, onRejected, onProgress ) {
4192 function resolve( depth, deferred, handler, special ) {
4196 mightThrow = function() {
4199 // Support: Promises/A+ section 2.3.3.3.3
4200 // https://promisesaplus.com/#point-59
4201 // Ignore double-resolution attempts
4202 if ( depth < maxDepth ) {
4206 returned = handler.apply( that, args );
4208 // Support: Promises/A+ section 2.3.1
4209 // https://promisesaplus.com/#point-48
4210 if ( returned === deferred.promise() ) {
4211 throw new TypeError( "Thenable self-resolution" );
4214 // Support: Promises/A+ sections 2.3.3.1, 3.5
4215 // https://promisesaplus.com/#point-54
4216 // https://promisesaplus.com/#point-75
4217 // Retrieve `then` only once
4220 // Support: Promises/A+ section 2.3.4
4221 // https://promisesaplus.com/#point-64
4222 // Only check objects and functions for thenability
4223 ( typeof returned === "object" ||
4224 typeof returned === "function" ) &&
4227 // Handle a returned thenable
4228 if ( isFunction( then ) ) {
4230 // Special processors (notify) just wait for resolution
4234 resolve( maxDepth, deferred, Identity, special ),
4235 resolve( maxDepth, deferred, Thrower, special )
4238 // Normal processors (resolve) also hook into progress
4241 // ...and disregard older resolution values
4246 resolve( maxDepth, deferred, Identity, special ),
4247 resolve( maxDepth, deferred, Thrower, special ),
4248 resolve( maxDepth, deferred, Identity,
4249 deferred.notifyWith )
4253 // Handle all other returned values
4256 // Only substitute handlers pass on context
4257 // and multiple values (non-spec behavior)
4258 if ( handler !== Identity ) {
4260 args = [ returned ];
4263 // Process the value(s)
4264 // Default process is resolve
4265 ( special || deferred.resolveWith )( that, args );
4269 // Only normal processors (resolve) catch and reject exceptions
4277 if ( jQuery.Deferred.exceptionHook ) {
4278 jQuery.Deferred.exceptionHook( e,
4279 process.stackTrace );
4282 // Support: Promises/A+ section 2.3.3.3.4.1
4283 // https://promisesaplus.com/#point-61
4284 // Ignore post-resolution exceptions
4285 if ( depth + 1 >= maxDepth ) {
4287 // Only substitute handlers pass on context
4288 // and multiple values (non-spec behavior)
4289 if ( handler !== Thrower ) {
4294 deferred.rejectWith( that, args );
4299 // Support: Promises/A+ section 2.3.3.3.1
4300 // https://promisesaplus.com/#point-57
4301 // Re-resolve promises immediately to dodge false rejection from
4302 // subsequent errors
4307 // Call an optional hook to record the stack, in case of exception
4308 // since it's otherwise lost when execution goes async
4309 if ( jQuery.Deferred.getStackHook ) {
4310 process.stackTrace = jQuery.Deferred.getStackHook();
4312 window.setTimeout( process );
4317 return jQuery.Deferred( function( newDefer ) {
4319 // progress_handlers.add( ... )
4320 tuples[ 0 ][ 3 ].add(
4324 isFunction( onProgress ) ?
4331 // fulfilled_handlers.add( ... )
4332 tuples[ 1 ][ 3 ].add(
4336 isFunction( onFulfilled ) ?
4342 // rejected_handlers.add( ... )
4343 tuples[ 2 ][ 3 ].add(
4347 isFunction( onRejected ) ?
4355 // Get a promise for this deferred
4356 // If obj is provided, the promise aspect is added to the object
4357 promise: function( obj ) {
4358 return obj != null ? jQuery.extend( obj, promise ) : promise;
4363 // Add list-specific methods
4364 jQuery.each( tuples, function( i, tuple ) {
4365 var list = tuple[ 2 ],
4366 stateString = tuple[ 5 ];
4368 // promise.progress = list.add
4369 // promise.done = list.add
4370 // promise.fail = list.add
4371 promise[ tuple[ 1 ] ] = list.add;
4374 if ( stateString ) {
4378 // state = "resolved" (i.e., fulfilled)
4379 // state = "rejected"
4380 state = stateString;
4383 // rejected_callbacks.disable
4384 // fulfilled_callbacks.disable
4385 tuples[ 3 - i ][ 2 ].disable,
4387 // rejected_handlers.disable
4388 // fulfilled_handlers.disable
4389 tuples[ 3 - i ][ 3 ].disable,
4391 // progress_callbacks.lock
4392 tuples[ 0 ][ 2 ].lock,
4394 // progress_handlers.lock
4395 tuples[ 0 ][ 3 ].lock
4399 // progress_handlers.fire
4400 // fulfilled_handlers.fire
4401 // rejected_handlers.fire
4402 list.add( tuple[ 3 ].fire );
4404 // deferred.notify = function() { deferred.notifyWith(...) }
4405 // deferred.resolve = function() { deferred.resolveWith(...) }
4406 // deferred.reject = function() { deferred.rejectWith(...) }
4407 deferred[ tuple[ 0 ] ] = function() {
4408 deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
4412 // deferred.notifyWith = list.fireWith
4413 // deferred.resolveWith = list.fireWith
4414 // deferred.rejectWith = list.fireWith
4415 deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
4418 // Make the deferred a promise
4419 promise.promise( deferred );
4421 // Call given func if any
4423 func.call( deferred, deferred );
4431 when: function( singleValue ) {
4434 // count of uncompleted subordinates
4435 remaining = arguments.length,
4437 // count of unprocessed arguments
4440 // subordinate fulfillment data
4441 resolveContexts = Array( i ),
4442 resolveValues = slice.call( arguments ),
4444 // the master Deferred
4445 master = jQuery.Deferred(),
4447 // subordinate callback factory
4448 updateFunc = function( i ) {
4449 return function( value ) {
4450 resolveContexts[ i ] = this;
4451 resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
4452 if ( !( --remaining ) ) {
4453 master.resolveWith( resolveContexts, resolveValues );
4458 // Single- and empty arguments are adopted like Promise.resolve
4459 if ( remaining <= 1 ) {
4460 adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
4463 // Use .then() to unwrap secondary thenables (cf. gh-3000)
4464 if ( master.state() === "pending" ||
4465 isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
4467 return master.then();
4471 // Multiple arguments are aggregated like Promise.all array elements
4473 adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
4476 return master.promise();
4481 // These usually indicate a programmer mistake during development,
4482 // warn about them ASAP rather than swallowing them by default.
4483 var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
4485 jQuery.Deferred.exceptionHook = function( error, stack ) {
4487 // Support: IE 8 - 9 only
4488 // Console exists when dev tools are open, which can happen at any time
4489 if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
4490 window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
4497 jQuery.readyException = function( error ) {
4498 window.setTimeout( function() {
4506 // The deferred used on DOM ready
4507 var readyList = jQuery.Deferred();
4509 jQuery.fn.ready = function( fn ) {
4514 // Wrap jQuery.readyException in a function so that the lookup
4515 // happens at the time of error handling instead of callback
4517 .catch( function( error ) {
4518 jQuery.readyException( error );
4526 // Is the DOM ready to be used? Set to true once it occurs.
4529 // A counter to track how many items to wait for before
4530 // the ready event fires. See #6781
4533 // Handle when the DOM is ready
4534 ready: function( wait ) {
4536 // Abort if there are pending holds or we're already ready
4537 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
4541 // Remember that the DOM is ready
4542 jQuery.isReady = true;
4544 // If a normal DOM Ready event fired, decrement, and wait if need be
4545 if ( wait !== true && --jQuery.readyWait > 0 ) {
4549 // If there are functions bound, to execute
4550 readyList.resolveWith( document, [ jQuery ] );
4554 jQuery.ready.then = readyList.then;
4556 // The ready event handler and self cleanup method
4557 function completed() {
4558 document.removeEventListener( "DOMContentLoaded", completed );
4559 window.removeEventListener( "load", completed );
4563 // Catch cases where $(document).ready() is called
4564 // after the browser event has already occurred.
4565 // Support: IE <=9 - 10 only
4566 // Older IE sometimes signals "interactive" too soon
4567 if ( document.readyState === "complete" ||
4568 ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
4570 // Handle it asynchronously to allow scripts the opportunity to delay ready
4571 window.setTimeout( jQuery.ready );
4575 // Use the handy event callback
4576 document.addEventListener( "DOMContentLoaded", completed );
4578 // A fallback to window.onload, that will always work
4579 window.addEventListener( "load", completed );
4585 // Multifunctional method to get and set values of a collection
4586 // The value/s can optionally be executed if it's a function
4587 var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
4593 if ( toType( key ) === "object" ) {
4596 access( elems, fn, i, key[ i ], true, emptyGet, raw );
4600 } else if ( value !== undefined ) {
4603 if ( !isFunction( value ) ) {
4609 // Bulk operations run against the entire set
4611 fn.call( elems, value );
4614 // ...except when executing function values
4617 fn = function( elem, _key, value ) {
4618 return bulk.call( jQuery( elem ), value );
4624 for ( ; i < len; i++ ) {
4626 elems[ i ], key, raw ?
4628 value.call( elems[ i ], i, fn( elems[ i ], key ) )
4640 return fn.call( elems );
4643 return len ? fn( elems[ 0 ], key ) : emptyGet;
4647 // Matches dashed string for camelizing
4648 var rmsPrefix = /^-ms-/,
4649 rdashAlpha = /-([a-z])/g;
4651 // Used by camelCase as callback to replace()
4652 function fcamelCase( _all, letter ) {
4653 return letter.toUpperCase();
4656 // Convert dashed to camelCase; used by the css and data modules
4657 // Support: IE <=9 - 11, Edge 12 - 15
4658 // Microsoft forgot to hump their vendor prefix (#9572)
4659 function camelCase( string ) {
4660 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
4662 var acceptData = function( owner ) {
4666 // - Node.ELEMENT_NODE
4667 // - Node.DOCUMENT_NODE
4670 return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
4677 this.expando = jQuery.expando + Data.uid++;
4684 cache: function( owner ) {
4686 // Check if the owner object already has a cache
4687 var value = owner[ this.expando ];
4689 // If not, create one
4693 // We can accept data for non-element nodes in modern browsers,
4694 // but we should not, see #8335.
4695 // Always return an empty object.
4696 if ( acceptData( owner ) ) {
4698 // If it is a node unlikely to be stringify-ed or looped over
4699 // use plain assignment
4700 if ( owner.nodeType ) {
4701 owner[ this.expando ] = value;
4703 // Otherwise secure it in a non-enumerable property
4704 // configurable must be true to allow the property to be
4705 // deleted when data is removed
4707 Object.defineProperty( owner, this.expando, {
4717 set: function( owner, data, value ) {
4719 cache = this.cache( owner );
4721 // Handle: [ owner, key, value ] args
4722 // Always use camelCase key (gh-2257)
4723 if ( typeof data === "string" ) {
4724 cache[ camelCase( data ) ] = value;
4726 // Handle: [ owner, { properties } ] args
4729 // Copy the properties one-by-one to the cache object
4730 for ( prop in data ) {
4731 cache[ camelCase( prop ) ] = data[ prop ];
4736 get: function( owner, key ) {
4737 return key === undefined ?
4738 this.cache( owner ) :
4740 // Always use camelCase key (gh-2257)
4741 owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
4743 access: function( owner, key, value ) {
4745 // In cases where either:
4747 // 1. No key was specified
4748 // 2. A string key was specified, but no value provided
4750 // Take the "read" path and allow the get method to determine
4751 // which value to return, respectively either:
4753 // 1. The entire cache object
4754 // 2. The data stored at the key
4756 if ( key === undefined ||
4757 ( ( key && typeof key === "string" ) && value === undefined ) ) {
4759 return this.get( owner, key );
4762 // When the key is not a string, or both a key and value
4763 // are specified, set or extend (existing objects) with either:
4765 // 1. An object of properties
4766 // 2. A key and value
4768 this.set( owner, key, value );
4770 // Since the "set" path can have two possible entry points
4771 // return the expected data based on which path was taken[*]
4772 return value !== undefined ? value : key;
4774 remove: function( owner, key ) {
4776 cache = owner[ this.expando ];
4778 if ( cache === undefined ) {
4782 if ( key !== undefined ) {
4784 // Support array or space separated string of keys
4785 if ( Array.isArray( key ) ) {
4787 // If key is an array of keys...
4788 // We always set camelCase keys, so remove that.
4789 key = key.map( camelCase );
4791 key = camelCase( key );
4793 // If a key with the spaces exists, use it.
4794 // Otherwise, create an array by matching non-whitespace
4795 key = key in cache ?
4797 ( key.match( rnothtmlwhite ) || [] );
4803 delete cache[ key[ i ] ];
4807 // Remove the expando if there's no more data
4808 if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
4810 // Support: Chrome <=35 - 45
4811 // Webkit & Blink performance suffers when deleting properties
4812 // from DOM nodes, so set to undefined instead
4813 // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
4814 if ( owner.nodeType ) {
4815 owner[ this.expando ] = undefined;
4817 delete owner[ this.expando ];
4821 hasData: function( owner ) {
4822 var cache = owner[ this.expando ];
4823 return cache !== undefined && !jQuery.isEmptyObject( cache );
4826 var dataPriv = new Data();
4828 var dataUser = new Data();
4832 // Implementation Summary
4834 // 1. Enforce API surface and semantic compatibility with 1.9.x branch
4835 // 2. Improve the module's maintainability by reducing the storage
4836 // paths to a single mechanism.
4837 // 3. Use the same single mechanism to support "private" and "user" data.
4838 // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
4839 // 5. Avoid exposing implementation details on user objects (eg. expando properties)
4840 // 6. Provide a clear path for implementation upgrade to WeakMap in 2014
4842 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
4843 rmultiDash = /[A-Z]/g;
4845 function getData( data ) {
4846 if ( data === "true" ) {
4850 if ( data === "false" ) {
4854 if ( data === "null" ) {
4858 // Only convert to a number if it doesn't change the string
4859 if ( data === +data + "" ) {
4863 if ( rbrace.test( data ) ) {
4864 return JSON.parse( data );
4870 function dataAttr( elem, key, data ) {
4873 // If nothing was found internally, try to fetch any
4874 // data from the HTML5 data-* attribute
4875 if ( data === undefined && elem.nodeType === 1 ) {
4876 name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
4877 data = elem.getAttribute( name );
4879 if ( typeof data === "string" ) {
4881 data = getData( data );
4884 // Make sure we set the data so it isn't changed later
4885 dataUser.set( elem, key, data );
4894 hasData: function( elem ) {
4895 return dataUser.hasData( elem ) || dataPriv.hasData( elem );
4898 data: function( elem, name, data ) {
4899 return dataUser.access( elem, name, data );
4902 removeData: function( elem, name ) {
4903 dataUser.remove( elem, name );
4906 // TODO: Now that all calls to _data and _removeData have been replaced
4907 // with direct calls to dataPriv methods, these can be deprecated.
4908 _data: function( elem, name, data ) {
4909 return dataPriv.access( elem, name, data );
4912 _removeData: function( elem, name ) {
4913 dataPriv.remove( elem, name );
4918 data: function( key, value ) {
4921 attrs = elem && elem.attributes;
4924 if ( key === undefined ) {
4925 if ( this.length ) {
4926 data = dataUser.get( elem );
4928 if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
4932 // Support: IE 11 only
4933 // The attrs elements can be null (#14894)
4935 name = attrs[ i ].name;
4936 if ( name.indexOf( "data-" ) === 0 ) {
4937 name = camelCase( name.slice( 5 ) );
4938 dataAttr( elem, name, data[ name ] );
4942 dataPriv.set( elem, "hasDataAttrs", true );
4949 // Sets multiple values
4950 if ( typeof key === "object" ) {
4951 return this.each( function() {
4952 dataUser.set( this, key );
4956 return access( this, function( value ) {
4959 // The calling jQuery object (element matches) is not empty
4960 // (and therefore has an element appears at this[ 0 ]) and the
4961 // `value` parameter was not undefined. An empty jQuery object
4962 // will result in `undefined` for elem = this[ 0 ] which will
4963 // throw an exception if an attempt to read a data cache is made.
4964 if ( elem && value === undefined ) {
4966 // Attempt to get data from the cache
4967 // The key will always be camelCased in Data
4968 data = dataUser.get( elem, key );
4969 if ( data !== undefined ) {
4973 // Attempt to "discover" the data in
4974 // HTML5 custom data-* attrs
4975 data = dataAttr( elem, key );
4976 if ( data !== undefined ) {
4980 // We tried really hard, but the data doesn't exist.
4985 this.each( function() {
4987 // We always store the camelCased key
4988 dataUser.set( this, key, value );
4990 }, null, value, arguments.length > 1, null, true );
4993 removeData: function( key ) {
4994 return this.each( function() {
4995 dataUser.remove( this, key );
5002 queue: function( elem, type, data ) {
5006 type = ( type || "fx" ) + "queue";
5007 queue = dataPriv.get( elem, type );
5009 // Speed up dequeue by getting out quickly if this is just a lookup
5011 if ( !queue || Array.isArray( data ) ) {
5012 queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
5021 dequeue: function( elem, type ) {
5022 type = type || "fx";
5024 var queue = jQuery.queue( elem, type ),
5025 startLength = queue.length,
5027 hooks = jQuery._queueHooks( elem, type ),
5029 jQuery.dequeue( elem, type );
5032 // If the fx queue is dequeued, always remove the progress sentinel
5033 if ( fn === "inprogress" ) {
5040 // Add a progress sentinel to prevent the fx queue from being
5041 // automatically dequeued
5042 if ( type === "fx" ) {
5043 queue.unshift( "inprogress" );
5046 // Clear up the last queue stop function
5048 fn.call( elem, next, hooks );
5051 if ( !startLength && hooks ) {
5056 // Not public - generate a queueHooks object, or return the current one
5057 _queueHooks: function( elem, type ) {
5058 var key = type + "queueHooks";
5059 return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
5060 empty: jQuery.Callbacks( "once memory" ).add( function() {
5061 dataPriv.remove( elem, [ type + "queue", key ] );
5068 queue: function( type, data ) {
5071 if ( typeof type !== "string" ) {
5077 if ( arguments.length < setter ) {
5078 return jQuery.queue( this[ 0 ], type );
5081 return data === undefined ?
5083 this.each( function() {
5084 var queue = jQuery.queue( this, type, data );
5086 // Ensure a hooks for this queue
5087 jQuery._queueHooks( this, type );
5089 if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
5090 jQuery.dequeue( this, type );
5094 dequeue: function( type ) {
5095 return this.each( function() {
5096 jQuery.dequeue( this, type );
5099 clearQueue: function( type ) {
5100 return this.queue( type || "fx", [] );
5103 // Get a promise resolved when queues of a certain type
5104 // are emptied (fx is the type by default)
5105 promise: function( type, obj ) {
5108 defer = jQuery.Deferred(),
5111 resolve = function() {
5112 if ( !( --count ) ) {
5113 defer.resolveWith( elements, [ elements ] );
5117 if ( typeof type !== "string" ) {
5121 type = type || "fx";
5124 tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
5125 if ( tmp && tmp.empty ) {
5127 tmp.empty.add( resolve );
5131 return defer.promise( obj );
5134 var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
5136 var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
5139 var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
5141 var documentElement = document.documentElement;
5145 var isAttached = function( elem ) {
5146 return jQuery.contains( elem.ownerDocument, elem );
5148 composed = { composed: true };
5150 // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
5151 // Check attachment across shadow DOM boundaries when possible (gh-3504)
5152 // Support: iOS 10.0-10.2 only
5153 // Early iOS 10 versions support `attachShadow` but not `getRootNode`,
5154 // leading to errors. We need to check for `getRootNode`.
5155 if ( documentElement.getRootNode ) {
5156 isAttached = function( elem ) {
5157 return jQuery.contains( elem.ownerDocument, elem ) ||
5158 elem.getRootNode( composed ) === elem.ownerDocument;
5161 var isHiddenWithinTree = function( elem, el ) {
5163 // isHiddenWithinTree might be called from jQuery#filter function;
5164 // in that case, element will be second argument
5167 // Inline style trumps all
5168 return elem.style.display === "none" ||
5169 elem.style.display === "" &&
5171 // Otherwise, check computed style
5172 // Support: Firefox <=43 - 45
5173 // Disconnected elements can have computed display: none, so first confirm that elem is
5175 isAttached( elem ) &&
5177 jQuery.css( elem, "display" ) === "none";
5182 function adjustCSS( elem, prop, valueParts, tween ) {
5183 var adjusted, scale,
5185 currentValue = tween ?
5190 return jQuery.css( elem, prop, "" );
5192 initial = currentValue(),
5193 unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
5195 // Starting value computation is required for potential unit mismatches
5196 initialInUnit = elem.nodeType &&
5197 ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
5198 rcssNum.exec( jQuery.css( elem, prop ) );
5200 if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
5202 // Support: Firefox <=54
5203 // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
5204 initial = initial / 2;
5206 // Trust units reported by jQuery.css
5207 unit = unit || initialInUnit[ 3 ];
5209 // Iteratively approximate from a nonzero starting point
5210 initialInUnit = +initial || 1;
5212 while ( maxIterations-- ) {
5214 // Evaluate and update our best guess (doubling guesses that zero out).
5215 // Finish if the scale equals or crosses 1 (making the old*new product non-positive).
5216 jQuery.style( elem, prop, initialInUnit + unit );
5217 if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
5220 initialInUnit = initialInUnit / scale;
5224 initialInUnit = initialInUnit * 2;
5225 jQuery.style( elem, prop, initialInUnit + unit );
5227 // Make sure we update the tween properties later on
5228 valueParts = valueParts || [];
5232 initialInUnit = +initialInUnit || +initial || 0;
5234 // Apply relative offset (+=/-=) if specified
5235 adjusted = valueParts[ 1 ] ?
5236 initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
5240 tween.start = initialInUnit;
5241 tween.end = adjusted;
5248 var defaultDisplayMap = {};
5250 function getDefaultDisplay( elem ) {
5252 doc = elem.ownerDocument,
5253 nodeName = elem.nodeName,
5254 display = defaultDisplayMap[ nodeName ];
5260 temp = doc.body.appendChild( doc.createElement( nodeName ) );
5261 display = jQuery.css( temp, "display" );
5263 temp.parentNode.removeChild( temp );
5265 if ( display === "none" ) {
5268 defaultDisplayMap[ nodeName ] = display;
5273 function showHide( elements, show ) {
5277 length = elements.length;
5279 // Determine new display value for elements that need to change
5280 for ( ; index < length; index++ ) {
5281 elem = elements[ index ];
5282 if ( !elem.style ) {
5286 display = elem.style.display;
5289 // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
5290 // check is required in this first loop unless we have a nonempty display value (either
5291 // inline or about-to-be-restored)
5292 if ( display === "none" ) {
5293 values[ index ] = dataPriv.get( elem, "display" ) || null;
5294 if ( !values[ index ] ) {
5295 elem.style.display = "";
5298 if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
5299 values[ index ] = getDefaultDisplay( elem );
5302 if ( display !== "none" ) {
5303 values[ index ] = "none";
5305 // Remember what we're overwriting
5306 dataPriv.set( elem, "display", display );
5311 // Set the display of the elements in a second loop to avoid constant reflow
5312 for ( index = 0; index < length; index++ ) {
5313 if ( values[ index ] != null ) {
5314 elements[ index ].style.display = values[ index ];
5323 return showHide( this, true );
5326 return showHide( this );
5328 toggle: function( state ) {
5329 if ( typeof state === "boolean" ) {
5330 return state ? this.show() : this.hide();
5333 return this.each( function() {
5334 if ( isHiddenWithinTree( this ) ) {
5335 jQuery( this ).show();
5337 jQuery( this ).hide();
5342 var rcheckableType = ( /^(?:checkbox|radio)$/i );
5344 var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
5346 var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
5351 var fragment = document.createDocumentFragment(),
5352 div = fragment.appendChild( document.createElement( "div" ) ),
5353 input = document.createElement( "input" );
5355 // Support: Android 4.0 - 4.3 only
5356 // Check state lost if the name is set (#11217)
5357 // Support: Windows Web Apps (WWA)
5358 // `name` and `type` must use .setAttribute for WWA (#14901)
5359 input.setAttribute( "type", "radio" );
5360 input.setAttribute( "checked", "checked" );
5361 input.setAttribute( "name", "t" );
5363 div.appendChild( input );
5365 // Support: Android <=4.1 only
5366 // Older WebKit doesn't clone checked state correctly in fragments
5367 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
5369 // Support: IE <=11 only
5370 // Make sure textarea (and checkbox) defaultValue is properly cloned
5371 div.innerHTML = "<textarea>x</textarea>";
5372 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
5374 // Support: IE <=9 only
5375 // IE <=9 replaces <option> tags with their contents when inserted outside of
5376 // the select element.
5377 div.innerHTML = "<option></option>";
5378 support.option = !!div.lastChild;
5382 // We have to close these tags to support XHTML (#13200)
5385 // XHTML parsers do not magically insert elements in the
5386 // same way that tag soup parsers do. So we cannot shorten
5387 // this by omitting <tbody> or other required elements.
5388 thead: [ 1, "<table>", "</table>" ],
5389 col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
5390 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5391 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5393 _default: [ 0, "", "" ]
5396 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5397 wrapMap.th = wrapMap.td;
5399 // Support: IE <=9 only
5400 if ( !support.option ) {
5401 wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ];
5405 function getAll( context, tag ) {
5407 // Support: IE <=9 - 11 only
5408 // Use typeof to avoid zero-argument method invocation on host objects (#15151)
5411 if ( typeof context.getElementsByTagName !== "undefined" ) {
5412 ret = context.getElementsByTagName( tag || "*" );
5414 } else if ( typeof context.querySelectorAll !== "undefined" ) {
5415 ret = context.querySelectorAll( tag || "*" );
5421 if ( tag === undefined || tag && nodeName( context, tag ) ) {
5422 return jQuery.merge( [ context ], ret );
5429 // Mark scripts as having already been evaluated
5430 function setGlobalEval( elems, refElements ) {
5434 for ( ; i < l; i++ ) {
5438 !refElements || dataPriv.get( refElements[ i ], "globalEval" )
5444 var rhtml = /<|&#?\w+;/;
5446 function buildFragment( elems, context, scripts, selection, ignored ) {
5447 var elem, tmp, tag, wrap, attached, j,
5448 fragment = context.createDocumentFragment(),
5453 for ( ; i < l; i++ ) {
5456 if ( elem || elem === 0 ) {
5458 // Add nodes directly
5459 if ( toType( elem ) === "object" ) {
5461 // Support: Android <=4.0 only, PhantomJS 1 only
5462 // push.apply(_, arraylike) throws on ancient WebKit
5463 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
5465 // Convert non-html into a text node
5466 } else if ( !rhtml.test( elem ) ) {
5467 nodes.push( context.createTextNode( elem ) );
5469 // Convert html into DOM nodes
5471 tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
5473 // Deserialize a standard representation
5474 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
5475 wrap = wrapMap[ tag ] || wrapMap._default;
5476 tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
5478 // Descend through wrappers to the right content
5481 tmp = tmp.lastChild;
5484 // Support: Android <=4.0 only, PhantomJS 1 only
5485 // push.apply(_, arraylike) throws on ancient WebKit
5486 jQuery.merge( nodes, tmp.childNodes );
5488 // Remember the top-level container
5489 tmp = fragment.firstChild;
5491 // Ensure the created nodes are orphaned (#12392)
5492 tmp.textContent = "";
5497 // Remove wrapper from fragment
5498 fragment.textContent = "";
5501 while ( ( elem = nodes[ i++ ] ) ) {
5503 // Skip elements already in the context collection (trac-4087)
5504 if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
5506 ignored.push( elem );
5511 attached = isAttached( elem );
5513 // Append to fragment
5514 tmp = getAll( fragment.appendChild( elem ), "script" );
5516 // Preserve script evaluation history
5518 setGlobalEval( tmp );
5521 // Capture executables
5524 while ( ( elem = tmp[ j++ ] ) ) {
5525 if ( rscriptType.test( elem.type || "" ) ) {
5526 scripts.push( elem );
5538 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
5539 rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
5541 function returnTrue() {
5545 function returnFalse() {
5549 // Support: IE <=9 - 11+
5550 // focus() and blur() are asynchronous, except when they are no-op.
5551 // So expect focus to be synchronous when the element is already active,
5552 // and blur to be synchronous when the element is not already active.
5553 // (focus and blur are always synchronous in other supported browsers,
5554 // this just defines when we can count on it).
5555 function expectSync( elem, type ) {
5556 return ( elem === safeActiveElement() ) === ( type === "focus" );
5559 // Support: IE <=9 only
5560 // Accessing document.activeElement can throw unexpectedly
5561 // https://bugs.jquery.com/ticket/13393
5562 function safeActiveElement() {
5564 return document.activeElement;
5568 function on( elem, types, selector, data, fn, one ) {
5571 // Types can be a map of types/handlers
5572 if ( typeof types === "object" ) {
5574 // ( types-Object, selector, data )
5575 if ( typeof selector !== "string" ) {
5577 // ( types-Object, data )
5578 data = data || selector;
5579 selector = undefined;
5581 for ( type in types ) {
5582 on( elem, type, selector, data, types[ type ], one );
5587 if ( data == null && fn == null ) {
5591 data = selector = undefined;
5592 } else if ( fn == null ) {
5593 if ( typeof selector === "string" ) {
5595 // ( types, selector, fn )
5600 // ( types, data, fn )
5603 selector = undefined;
5606 if ( fn === false ) {
5614 fn = function( event ) {
5616 // Can use an empty set, since event contains the info
5617 jQuery().off( event );
5618 return origFn.apply( this, arguments );
5621 // Use same guid so caller can remove using origFn
5622 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
5624 return elem.each( function() {
5625 jQuery.event.add( this, types, fn, data, selector );
5630 * Helper functions for managing events -- not part of the public interface.
5631 * Props to Dean Edwards' addEvent library for many of the ideas.
5637 add: function( elem, types, handler, data, selector ) {
5639 var handleObjIn, eventHandle, tmp,
5640 events, t, handleObj,
5641 special, handlers, type, namespaces, origType,
5642 elemData = dataPriv.get( elem );
5644 // Only attach events to objects that accept data
5645 if ( !acceptData( elem ) ) {
5649 // Caller can pass in an object of custom data in lieu of the handler
5650 if ( handler.handler ) {
5651 handleObjIn = handler;
5652 handler = handleObjIn.handler;
5653 selector = handleObjIn.selector;
5656 // Ensure that invalid selectors throw exceptions at attach time
5657 // Evaluate against documentElement in case elem is a non-element node (e.g., document)
5659 jQuery.find.matchesSelector( documentElement, selector );
5662 // Make sure that the handler has a unique ID, used to find/remove it later
5663 if ( !handler.guid ) {
5664 handler.guid = jQuery.guid++;
5667 // Init the element's event structure and main handler, if this is the first
5668 if ( !( events = elemData.events ) ) {
5669 events = elemData.events = Object.create( null );
5671 if ( !( eventHandle = elemData.handle ) ) {
5672 eventHandle = elemData.handle = function( e ) {
5674 // Discard the second event of a jQuery.event.trigger() and
5675 // when an event is called after a page has unloaded
5676 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
5677 jQuery.event.dispatch.apply( elem, arguments ) : undefined;
5681 // Handle multiple events separated by a space
5682 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5685 tmp = rtypenamespace.exec( types[ t ] ) || [];
5686 type = origType = tmp[ 1 ];
5687 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5689 // There *must* be a type, no attaching namespace-only handlers
5694 // If event changes its type, use the special event handlers for the changed type
5695 special = jQuery.event.special[ type ] || {};
5697 // If selector defined, determine special event api type, otherwise given type
5698 type = ( selector ? special.delegateType : special.bindType ) || type;
5700 // Update special based on newly reset type
5701 special = jQuery.event.special[ type ] || {};
5703 // handleObj is passed to all event handlers
5704 handleObj = jQuery.extend( {
5711 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
5712 namespace: namespaces.join( "." )
5715 // Init the event handler queue if we're the first
5716 if ( !( handlers = events[ type ] ) ) {
5717 handlers = events[ type ] = [];
5718 handlers.delegateCount = 0;
5720 // Only use addEventListener if the special events handler returns false
5721 if ( !special.setup ||
5722 special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
5724 if ( elem.addEventListener ) {
5725 elem.addEventListener( type, eventHandle );
5730 if ( special.add ) {
5731 special.add.call( elem, handleObj );
5733 if ( !handleObj.handler.guid ) {
5734 handleObj.handler.guid = handler.guid;
5738 // Add to the element's handler list, delegates in front
5740 handlers.splice( handlers.delegateCount++, 0, handleObj );
5742 handlers.push( handleObj );
5745 // Keep track of which events have ever been used, for event optimization
5746 jQuery.event.global[ type ] = true;
5751 // Detach an event or set of events from an element
5752 remove: function( elem, types, handler, selector, mappedTypes ) {
5754 var j, origCount, tmp,
5755 events, t, handleObj,
5756 special, handlers, type, namespaces, origType,
5757 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
5759 if ( !elemData || !( events = elemData.events ) ) {
5763 // Once for each type.namespace in types; type may be omitted
5764 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5767 tmp = rtypenamespace.exec( types[ t ] ) || [];
5768 type = origType = tmp[ 1 ];
5769 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5771 // Unbind all events (on this namespace, if provided) for the element
5773 for ( type in events ) {
5774 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
5779 special = jQuery.event.special[ type ] || {};
5780 type = ( selector ? special.delegateType : special.bindType ) || type;
5781 handlers = events[ type ] || [];
5783 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
5785 // Remove matching events
5786 origCount = j = handlers.length;
5788 handleObj = handlers[ j ];
5790 if ( ( mappedTypes || origType === handleObj.origType ) &&
5791 ( !handler || handler.guid === handleObj.guid ) &&
5792 ( !tmp || tmp.test( handleObj.namespace ) ) &&
5793 ( !selector || selector === handleObj.selector ||
5794 selector === "**" && handleObj.selector ) ) {
5795 handlers.splice( j, 1 );
5797 if ( handleObj.selector ) {
5798 handlers.delegateCount--;
5800 if ( special.remove ) {
5801 special.remove.call( elem, handleObj );
5806 // Remove generic event handler if we removed something and no more handlers exist
5807 // (avoids potential for endless recursion during removal of special event handlers)
5808 if ( origCount && !handlers.length ) {
5809 if ( !special.teardown ||
5810 special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
5812 jQuery.removeEvent( elem, type, elemData.handle );
5815 delete events[ type ];
5819 // Remove data and the expando if it's no longer used
5820 if ( jQuery.isEmptyObject( events ) ) {
5821 dataPriv.remove( elem, "handle events" );
5825 dispatch: function( nativeEvent ) {
5827 var i, j, ret, matched, handleObj, handlerQueue,
5828 args = new Array( arguments.length ),
5830 // Make a writable jQuery.Event from the native event object
5831 event = jQuery.event.fix( nativeEvent ),
5834 dataPriv.get( this, "events" ) || Object.create( null )
5835 )[ event.type ] || [],
5836 special = jQuery.event.special[ event.type ] || {};
5838 // Use the fix-ed jQuery.Event rather than the (read-only) native event
5841 for ( i = 1; i < arguments.length; i++ ) {
5842 args[ i ] = arguments[ i ];
5845 event.delegateTarget = this;
5847 // Call the preDispatch hook for the mapped type, and let it bail if desired
5848 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5852 // Determine handlers
5853 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5855 // Run delegates first; they may want to stop propagation beneath us
5857 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
5858 event.currentTarget = matched.elem;
5861 while ( ( handleObj = matched.handlers[ j++ ] ) &&
5862 !event.isImmediatePropagationStopped() ) {
5864 // If the event is namespaced, then each handler is only invoked if it is
5865 // specially universal or its namespaces are a superset of the event's.
5866 if ( !event.rnamespace || handleObj.namespace === false ||
5867 event.rnamespace.test( handleObj.namespace ) ) {
5869 event.handleObj = handleObj;
5870 event.data = handleObj.data;
5872 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
5873 handleObj.handler ).apply( matched.elem, args );
5875 if ( ret !== undefined ) {
5876 if ( ( event.result = ret ) === false ) {
5877 event.preventDefault();
5878 event.stopPropagation();
5885 // Call the postDispatch hook for the mapped type
5886 if ( special.postDispatch ) {
5887 special.postDispatch.call( this, event );
5890 return event.result;
5893 handlers: function( event, handlers ) {
5894 var i, handleObj, sel, matchedHandlers, matchedSelectors,
5896 delegateCount = handlers.delegateCount,
5899 // Find delegate handlers
5900 if ( delegateCount &&
5903 // Black-hole SVG <use> instance trees (trac-13180)
5906 // Support: Firefox <=42
5907 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
5908 // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
5909 // Support: IE 11 only
5910 // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
5911 !( event.type === "click" && event.button >= 1 ) ) {
5913 for ( ; cur !== this; cur = cur.parentNode || this ) {
5915 // Don't check non-elements (#13208)
5916 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
5917 if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
5918 matchedHandlers = [];
5919 matchedSelectors = {};
5920 for ( i = 0; i < delegateCount; i++ ) {
5921 handleObj = handlers[ i ];
5923 // Don't conflict with Object.prototype properties (#13203)
5924 sel = handleObj.selector + " ";
5926 if ( matchedSelectors[ sel ] === undefined ) {
5927 matchedSelectors[ sel ] = handleObj.needsContext ?
5928 jQuery( sel, this ).index( cur ) > -1 :
5929 jQuery.find( sel, this, null, [ cur ] ).length;
5931 if ( matchedSelectors[ sel ] ) {
5932 matchedHandlers.push( handleObj );
5935 if ( matchedHandlers.length ) {
5936 handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
5942 // Add the remaining (directly-bound) handlers
5944 if ( delegateCount < handlers.length ) {
5945 handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
5948 return handlerQueue;
5951 addProp: function( name, hook ) {
5952 Object.defineProperty( jQuery.Event.prototype, name, {
5956 get: isFunction( hook ) ?
5958 if ( this.originalEvent ) {
5959 return hook( this.originalEvent );
5963 if ( this.originalEvent ) {
5964 return this.originalEvent[ name ];
5968 set: function( value ) {
5969 Object.defineProperty( this, name, {
5979 fix: function( originalEvent ) {
5980 return originalEvent[ jQuery.expando ] ?
5982 new jQuery.Event( originalEvent );
5988 // Prevent triggered image.load events from bubbling to window.load
5993 // Utilize native event to ensure correct state for checkable inputs
5994 setup: function( data ) {
5996 // For mutual compressibility with _default, replace `this` access with a local var.
5997 // `|| data` is dead code meant only to preserve the variable through minification.
5998 var el = this || data;
6000 // Claim the first handler
6001 if ( rcheckableType.test( el.type ) &&
6002 el.click && nodeName( el, "input" ) ) {
6004 // dataPriv.set( el, "click", ... )
6005 leverageNative( el, "click", returnTrue );
6008 // Return false to allow normal processing in the caller
6011 trigger: function( data ) {
6013 // For mutual compressibility with _default, replace `this` access with a local var.
6014 // `|| data` is dead code meant only to preserve the variable through minification.
6015 var el = this || data;
6017 // Force setup before triggering a click
6018 if ( rcheckableType.test( el.type ) &&
6019 el.click && nodeName( el, "input" ) ) {
6021 leverageNative( el, "click" );
6024 // Return non-false to allow normal event-path propagation
6028 // For cross-browser consistency, suppress native .click() on links
6029 // Also prevent it if we're currently inside a leveraged native-event stack
6030 _default: function( event ) {
6031 var target = event.target;
6032 return rcheckableType.test( target.type ) &&
6033 target.click && nodeName( target, "input" ) &&
6034 dataPriv.get( target, "click" ) ||
6035 nodeName( target, "a" );
6040 postDispatch: function( event ) {
6042 // Support: Firefox 20+
6043 // Firefox doesn't alert if the returnValue field is not set.
6044 if ( event.result !== undefined && event.originalEvent ) {
6045 event.originalEvent.returnValue = event.result;
6052 // Ensure the presence of an event listener that handles manually-triggered
6053 // synthetic events by interrupting progress until reinvoked in response to
6054 // *native* events that it fires directly, ensuring that state changes have
6055 // already occurred before other listeners are invoked.
6056 function leverageNative( el, type, expectSync ) {
6058 // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
6059 if ( !expectSync ) {
6060 if ( dataPriv.get( el, type ) === undefined ) {
6061 jQuery.event.add( el, type, returnTrue );
6066 // Register the controller as a special universal handler for all event namespaces
6067 dataPriv.set( el, type, false );
6068 jQuery.event.add( el, type, {
6070 handler: function( event ) {
6071 var notAsync, result,
6072 saved = dataPriv.get( this, type );
6074 if ( ( event.isTrigger & 1 ) && this[ type ] ) {
6076 // Interrupt processing of the outer synthetic .trigger()ed event
6077 // Saved data should be false in such cases, but might be a leftover capture object
6078 // from an async native handler (gh-4350)
6079 if ( !saved.length ) {
6081 // Store arguments for use when handling the inner native event
6082 // There will always be at least one argument (an event object), so this array
6083 // will not be confused with a leftover capture object.
6084 saved = slice.call( arguments );
6085 dataPriv.set( this, type, saved );
6087 // Trigger the native event and capture its result
6088 // Support: IE <=9 - 11+
6089 // focus() and blur() are asynchronous
6090 notAsync = expectSync( this, type );
6092 result = dataPriv.get( this, type );
6093 if ( saved !== result || notAsync ) {
6094 dataPriv.set( this, type, false );
6098 if ( saved !== result ) {
6100 // Cancel the outer synthetic event
6101 event.stopImmediatePropagation();
6102 event.preventDefault();
6103 return result.value;
6106 // If this is an inner synthetic event for an event with a bubbling surrogate
6107 // (focus or blur), assume that the surrogate already propagated from triggering the
6108 // native event and prevent that from happening again here.
6109 // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
6110 // bubbling surrogate propagates *after* the non-bubbling base), but that seems
6111 // less bad than duplication.
6112 } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
6113 event.stopPropagation();
6116 // If this is a native event triggered above, everything is now in order
6117 // Fire an inner synthetic event with the original arguments
6118 } else if ( saved.length ) {
6120 // ...and capture the result
6121 dataPriv.set( this, type, {
6122 value: jQuery.event.trigger(
6124 // Support: IE <=9 - 11+
6125 // Extend with the prototype to reset the above stopImmediatePropagation()
6126 jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
6132 // Abort handling of the native event
6133 event.stopImmediatePropagation();
6139 jQuery.removeEvent = function( elem, type, handle ) {
6141 // This "if" is needed for plain objects
6142 if ( elem.removeEventListener ) {
6143 elem.removeEventListener( type, handle );
6147 jQuery.Event = function( src, props ) {
6149 // Allow instantiation without the 'new' keyword
6150 if ( !( this instanceof jQuery.Event ) ) {
6151 return new jQuery.Event( src, props );
6155 if ( src && src.type ) {
6156 this.originalEvent = src;
6157 this.type = src.type;
6159 // Events bubbling up the document may have been marked as prevented
6160 // by a handler lower down the tree; reflect the correct value.
6161 this.isDefaultPrevented = src.defaultPrevented ||
6162 src.defaultPrevented === undefined &&
6164 // Support: Android <=2.3 only
6165 src.returnValue === false ?
6169 // Create target properties
6170 // Support: Safari <=6 - 7 only
6171 // Target should not be a text node (#504, #13143)
6172 this.target = ( src.target && src.target.nodeType === 3 ) ?
6173 src.target.parentNode :
6176 this.currentTarget = src.currentTarget;
6177 this.relatedTarget = src.relatedTarget;
6184 // Put explicitly provided properties onto the event object
6186 jQuery.extend( this, props );
6189 // Create a timestamp if incoming event doesn't have one
6190 this.timeStamp = src && src.timeStamp || Date.now();
6193 this[ jQuery.expando ] = true;
6196 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
6197 // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
6198 jQuery.Event.prototype = {
6199 constructor: jQuery.Event,
6200 isDefaultPrevented: returnFalse,
6201 isPropagationStopped: returnFalse,
6202 isImmediatePropagationStopped: returnFalse,
6205 preventDefault: function() {
6206 var e = this.originalEvent;
6208 this.isDefaultPrevented = returnTrue;
6210 if ( e && !this.isSimulated ) {
6214 stopPropagation: function() {
6215 var e = this.originalEvent;
6217 this.isPropagationStopped = returnTrue;
6219 if ( e && !this.isSimulated ) {
6220 e.stopPropagation();
6223 stopImmediatePropagation: function() {
6224 var e = this.originalEvent;
6226 this.isImmediatePropagationStopped = returnTrue;
6228 if ( e && !this.isSimulated ) {
6229 e.stopImmediatePropagation();
6232 this.stopPropagation();
6236 // Includes all common event props including KeyEvent and MouseEvent specific props
6241 changedTouches: true,
6265 targetTouches: true,
6269 which: function( event ) {
6270 var button = event.button;
6272 // Add which for key events
6273 if ( event.which == null && rkeyEvent.test( event.type ) ) {
6274 return event.charCode != null ? event.charCode : event.keyCode;
6277 // Add which for click: 1 === left; 2 === middle; 3 === right
6278 if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
6296 }, jQuery.event.addProp );
6298 jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
6299 jQuery.event.special[ type ] = {
6301 // Utilize native event if possible so blur/focus sequence is correct
6304 // Claim the first handler
6305 // dataPriv.set( this, "focus", ... )
6306 // dataPriv.set( this, "blur", ... )
6307 leverageNative( this, type, expectSync );
6309 // Return false to allow normal processing in the caller
6312 trigger: function() {
6314 // Force setup before trigger
6315 leverageNative( this, type );
6317 // Return non-false to allow normal event-path propagation
6321 delegateType: delegateType
6325 // Create mouseenter/leave events using mouseover/out and event-time checks
6326 // so that event delegation works in jQuery.
6327 // Do the same for pointerenter/pointerleave and pointerover/pointerout
6329 // Support: Safari 7 only
6330 // Safari sends mouseenter too often; see:
6331 // https://bugs.chromium.org/p/chromium/issues/detail?id=470258
6332 // for the description of the bug (it existed in older Chrome versions as well).
6334 mouseenter: "mouseover",
6335 mouseleave: "mouseout",
6336 pointerenter: "pointerover",
6337 pointerleave: "pointerout"
6338 }, function( orig, fix ) {
6339 jQuery.event.special[ orig ] = {
6343 handle: function( event ) {
6346 related = event.relatedTarget,
6347 handleObj = event.handleObj;
6349 // For mouseenter/leave call the handler if related is outside the target.
6350 // NB: No relatedTarget if the mouse left/entered the browser window
6351 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
6352 event.type = handleObj.origType;
6353 ret = handleObj.handler.apply( this, arguments );
6363 on: function( types, selector, data, fn ) {
6364 return on( this, types, selector, data, fn );
6366 one: function( types, selector, data, fn ) {
6367 return on( this, types, selector, data, fn, 1 );
6369 off: function( types, selector, fn ) {
6370 var handleObj, type;
6371 if ( types && types.preventDefault && types.handleObj ) {
6373 // ( event ) dispatched jQuery.Event
6374 handleObj = types.handleObj;
6375 jQuery( types.delegateTarget ).off(
6376 handleObj.namespace ?
6377 handleObj.origType + "." + handleObj.namespace :
6384 if ( typeof types === "object" ) {
6386 // ( types-object [, selector] )
6387 for ( type in types ) {
6388 this.off( type, selector, types[ type ] );
6392 if ( selector === false || typeof selector === "function" ) {
6396 selector = undefined;
6398 if ( fn === false ) {
6401 return this.each( function() {
6402 jQuery.event.remove( this, types, fn, selector );
6410 // Support: IE <=10 - 11, Edge 12 - 13 only
6411 // In IE/Edge using regex groups here causes severe slowdowns.
6412 // See https://connect.microsoft.com/IE/feedback/details/1736512/
6413 rnoInnerhtml = /<script|<style|<link/i,
6415 // checked="checked" or checked
6416 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
6417 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
6419 // Prefer a tbody over its parent table for containing new rows
6420 function manipulationTarget( elem, content ) {
6421 if ( nodeName( elem, "table" ) &&
6422 nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
6424 return jQuery( elem ).children( "tbody" )[ 0 ] || elem;
6430 // Replace/restore the type attribute of script elements for safe DOM manipulation
6431 function disableScript( elem ) {
6432 elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
6435 function restoreScript( elem ) {
6436 if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
6437 elem.type = elem.type.slice( 5 );
6439 elem.removeAttribute( "type" );
6445 function cloneCopyEvent( src, dest ) {
6446 var i, l, type, pdataOld, udataOld, udataCur, events;
6448 if ( dest.nodeType !== 1 ) {
6452 // 1. Copy private data: events, handlers, etc.
6453 if ( dataPriv.hasData( src ) ) {
6454 pdataOld = dataPriv.get( src );
6455 events = pdataOld.events;
6458 dataPriv.remove( dest, "handle events" );
6460 for ( type in events ) {
6461 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6462 jQuery.event.add( dest, type, events[ type ][ i ] );
6468 // 2. Copy user data
6469 if ( dataUser.hasData( src ) ) {
6470 udataOld = dataUser.access( src );
6471 udataCur = jQuery.extend( {}, udataOld );
6473 dataUser.set( dest, udataCur );
6477 // Fix IE bugs, see support tests
6478 function fixInput( src, dest ) {
6479 var nodeName = dest.nodeName.toLowerCase();
6481 // Fails to persist the checked state of a cloned checkbox or radio button.
6482 if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
6483 dest.checked = src.checked;
6485 // Fails to return the selected option to the default selected state when cloning options
6486 } else if ( nodeName === "input" || nodeName === "textarea" ) {
6487 dest.defaultValue = src.defaultValue;
6491 function domManip( collection, args, callback, ignored ) {
6493 // Flatten any nested arrays
6494 args = flat( args );
6496 var fragment, first, scripts, hasScripts, node, doc,
6498 l = collection.length,
6501 valueIsFunction = isFunction( value );
6503 // We can't cloneNode fragments that contain checked, in WebKit
6504 if ( valueIsFunction ||
6505 ( l > 1 && typeof value === "string" &&
6506 !support.checkClone && rchecked.test( value ) ) ) {
6507 return collection.each( function( index ) {
6508 var self = collection.eq( index );
6509 if ( valueIsFunction ) {
6510 args[ 0 ] = value.call( this, index, self.html() );
6512 domManip( self, args, callback, ignored );
6517 fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
6518 first = fragment.firstChild;
6520 if ( fragment.childNodes.length === 1 ) {
6524 // Require either new content or an interest in ignored elements to invoke the callback
6525 if ( first || ignored ) {
6526 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6527 hasScripts = scripts.length;
6529 // Use the original fragment for the last item
6530 // instead of the first because it can end up
6531 // being emptied incorrectly in certain situations (#8070).
6532 for ( ; i < l; i++ ) {
6535 if ( i !== iNoClone ) {
6536 node = jQuery.clone( node, true, true );
6538 // Keep references to cloned scripts for later restoration
6541 // Support: Android <=4.0 only, PhantomJS 1 only
6542 // push.apply(_, arraylike) throws on ancient WebKit
6543 jQuery.merge( scripts, getAll( node, "script" ) );
6547 callback.call( collection[ i ], node, i );
6551 doc = scripts[ scripts.length - 1 ].ownerDocument;
6554 jQuery.map( scripts, restoreScript );
6556 // Evaluate executable scripts on first document insertion
6557 for ( i = 0; i < hasScripts; i++ ) {
6558 node = scripts[ i ];
6559 if ( rscriptType.test( node.type || "" ) &&
6560 !dataPriv.access( node, "globalEval" ) &&
6561 jQuery.contains( doc, node ) ) {
6563 if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) {
6565 // Optional AJAX dependency, but won't run scripts if not present
6566 if ( jQuery._evalUrl && !node.noModule ) {
6567 jQuery._evalUrl( node.src, {
6568 nonce: node.nonce || node.getAttribute( "nonce" )
6572 DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
6583 function remove( elem, selector, keepData ) {
6585 nodes = selector ? jQuery.filter( selector, elem ) : elem,
6588 for ( ; ( node = nodes[ i ] ) != null; i++ ) {
6589 if ( !keepData && node.nodeType === 1 ) {
6590 jQuery.cleanData( getAll( node ) );
6593 if ( node.parentNode ) {
6594 if ( keepData && isAttached( node ) ) {
6595 setGlobalEval( getAll( node, "script" ) );
6597 node.parentNode.removeChild( node );
6605 htmlPrefilter: function( html ) {
6609 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6610 var i, l, srcElements, destElements,
6611 clone = elem.cloneNode( true ),
6612 inPage = isAttached( elem );
6614 // Fix IE cloning issues
6615 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
6616 !jQuery.isXMLDoc( elem ) ) {
6618 // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
6619 destElements = getAll( clone );
6620 srcElements = getAll( elem );
6622 for ( i = 0, l = srcElements.length; i < l; i++ ) {
6623 fixInput( srcElements[ i ], destElements[ i ] );
6627 // Copy the events from the original to the clone
6628 if ( dataAndEvents ) {
6629 if ( deepDataAndEvents ) {
6630 srcElements = srcElements || getAll( elem );
6631 destElements = destElements || getAll( clone );
6633 for ( i = 0, l = srcElements.length; i < l; i++ ) {
6634 cloneCopyEvent( srcElements[ i ], destElements[ i ] );
6637 cloneCopyEvent( elem, clone );
6641 // Preserve script evaluation history
6642 destElements = getAll( clone, "script" );
6643 if ( destElements.length > 0 ) {
6644 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6647 // Return the cloned set
6651 cleanData: function( elems ) {
6652 var data, elem, type,
6653 special = jQuery.event.special,
6656 for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
6657 if ( acceptData( elem ) ) {
6658 if ( ( data = elem[ dataPriv.expando ] ) ) {
6659 if ( data.events ) {
6660 for ( type in data.events ) {
6661 if ( special[ type ] ) {
6662 jQuery.event.remove( elem, type );
6664 // This is a shortcut to avoid jQuery.event.remove's overhead
6666 jQuery.removeEvent( elem, type, data.handle );
6671 // Support: Chrome <=35 - 45+
6672 // Assign undefined instead of using delete, see Data#remove
6673 elem[ dataPriv.expando ] = undefined;
6675 if ( elem[ dataUser.expando ] ) {
6677 // Support: Chrome <=35 - 45+
6678 // Assign undefined instead of using delete, see Data#remove
6679 elem[ dataUser.expando ] = undefined;
6687 detach: function( selector ) {
6688 return remove( this, selector, true );
6691 remove: function( selector ) {
6692 return remove( this, selector );
6695 text: function( value ) {
6696 return access( this, function( value ) {
6697 return value === undefined ?
6698 jQuery.text( this ) :
6699 this.empty().each( function() {
6700 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6701 this.textContent = value;
6704 }, null, value, arguments.length );
6707 append: function() {
6708 return domManip( this, arguments, function( elem ) {
6709 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6710 var target = manipulationTarget( this, elem );
6711 target.appendChild( elem );
6716 prepend: function() {
6717 return domManip( this, arguments, function( elem ) {
6718 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6719 var target = manipulationTarget( this, elem );
6720 target.insertBefore( elem, target.firstChild );
6725 before: function() {
6726 return domManip( this, arguments, function( elem ) {
6727 if ( this.parentNode ) {
6728 this.parentNode.insertBefore( elem, this );
6734 return domManip( this, arguments, function( elem ) {
6735 if ( this.parentNode ) {
6736 this.parentNode.insertBefore( elem, this.nextSibling );
6745 for ( ; ( elem = this[ i ] ) != null; i++ ) {
6746 if ( elem.nodeType === 1 ) {
6748 // Prevent memory leaks
6749 jQuery.cleanData( getAll( elem, false ) );
6751 // Remove any remaining nodes
6752 elem.textContent = "";
6759 clone: function( dataAndEvents, deepDataAndEvents ) {
6760 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6761 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6763 return this.map( function() {
6764 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6768 html: function( value ) {
6769 return access( this, function( value ) {
6770 var elem = this[ 0 ] || {},
6774 if ( value === undefined && elem.nodeType === 1 ) {
6775 return elem.innerHTML;
6778 // See if we can take a shortcut and just use innerHTML
6779 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6780 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
6782 value = jQuery.htmlPrefilter( value );
6785 for ( ; i < l; i++ ) {
6786 elem = this[ i ] || {};
6788 // Remove element nodes and prevent memory leaks
6789 if ( elem.nodeType === 1 ) {
6790 jQuery.cleanData( getAll( elem, false ) );
6791 elem.innerHTML = value;
6797 // If using innerHTML throws an exception, use the fallback method
6802 this.empty().append( value );
6804 }, null, value, arguments.length );
6807 replaceWith: function() {
6810 // Make the changes, replacing each non-ignored context element with the new content
6811 return domManip( this, arguments, function( elem ) {
6812 var parent = this.parentNode;
6814 if ( jQuery.inArray( this, ignored ) < 0 ) {
6815 jQuery.cleanData( getAll( this ) );
6817 parent.replaceChild( elem, this );
6821 // Force callback invocation
6828 prependTo: "prepend",
6829 insertBefore: "before",
6830 insertAfter: "after",
6831 replaceAll: "replaceWith"
6832 }, function( name, original ) {
6833 jQuery.fn[ name ] = function( selector ) {
6836 insert = jQuery( selector ),
6837 last = insert.length - 1,
6840 for ( ; i <= last; i++ ) {
6841 elems = i === last ? this : this.clone( true );
6842 jQuery( insert[ i ] )[ original ]( elems );
6844 // Support: Android <=4.0 only, PhantomJS 1 only
6845 // .get() because push.apply(_, arraylike) throws on ancient WebKit
6846 push.apply( ret, elems.get() );
6849 return this.pushStack( ret );
6852 var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6854 var getStyles = function( elem ) {
6856 // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
6857 // IE throws on elements created in popups
6858 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6859 var view = elem.ownerDocument.defaultView;
6861 if ( !view || !view.opener ) {
6865 return view.getComputedStyle( elem );
6868 var swap = function( elem, options, callback ) {
6872 // Remember the old values, and insert the new ones
6873 for ( name in options ) {
6874 old[ name ] = elem.style[ name ];
6875 elem.style[ name ] = options[ name ];
6878 ret = callback.call( elem );
6880 // Revert the old values
6881 for ( name in options ) {
6882 elem.style[ name ] = old[ name ];
6889 var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6895 // Executing both pixelPosition & boxSizingReliable tests require only one layout
6896 // so they're executed at the same time to save the second computation.
6897 function computeStyleTests() {
6899 // This is a singleton, we need to execute it only once
6904 container.style.cssText = "position:absolute;left:-11111px;width:60px;" +
6905 "margin-top:1px;padding:0;border:0";
6907 "position:relative;display:block;box-sizing:border-box;overflow:scroll;" +
6908 "margin:auto;border:1px;padding:1px;" +
6910 documentElement.appendChild( container ).appendChild( div );
6912 var divStyle = window.getComputedStyle( div );
6913 pixelPositionVal = divStyle.top !== "1%";
6915 // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
6916 reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;
6918 // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3
6919 // Some styles come back with percentage values, even though they shouldn't
6920 div.style.right = "60%";
6921 pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;
6923 // Support: IE 9 - 11 only
6924 // Detect misreporting of content dimensions for box-sizing:border-box elements
6925 boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;
6927 // Support: IE 9 only
6928 // Detect overflow:scroll screwiness (gh-3699)
6929 // Support: Chrome <=64
6930 // Don't get tricked when zoom affects offsetWidth (gh-4029)
6931 div.style.position = "absolute";
6932 scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;
6934 documentElement.removeChild( container );
6936 // Nullify the div so it wouldn't be stored in the memory and
6937 // it will also be a sign that checks already performed
6941 function roundPixelMeasures( measure ) {
6942 return Math.round( parseFloat( measure ) );
6945 var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
6946 reliableTrDimensionsVal, reliableMarginLeftVal,
6947 container = document.createElement( "div" ),
6948 div = document.createElement( "div" );
6950 // Finish early in limited (non-browser) environments
6955 // Support: IE <=9 - 11 only
6956 // Style of cloned element affects source element cloned (#8908)
6957 div.style.backgroundClip = "content-box";
6958 div.cloneNode( true ).style.backgroundClip = "";
6959 support.clearCloneStyle = div.style.backgroundClip === "content-box";
6961 jQuery.extend( support, {
6962 boxSizingReliable: function() {
6963 computeStyleTests();
6964 return boxSizingReliableVal;
6966 pixelBoxStyles: function() {
6967 computeStyleTests();
6968 return pixelBoxStylesVal;
6970 pixelPosition: function() {
6971 computeStyleTests();
6972 return pixelPositionVal;
6974 reliableMarginLeft: function() {
6975 computeStyleTests();
6976 return reliableMarginLeftVal;
6978 scrollboxSize: function() {
6979 computeStyleTests();
6980 return scrollboxSizeVal;
6983 // Support: IE 9 - 11+, Edge 15 - 18+
6984 // IE/Edge misreport `getComputedStyle` of table rows with width/height
6985 // set in CSS while `offset*` properties report correct values.
6986 // Behavior in IE 9 is more subtle than in newer versions & it passes
6987 // some versions of this test; make sure not to make it pass there!
6988 reliableTrDimensions: function() {
6989 var table, tr, trChild, trStyle;
6990 if ( reliableTrDimensionsVal == null ) {
6991 table = document.createElement( "table" );
6992 tr = document.createElement( "tr" );
6993 trChild = document.createElement( "div" );
6995 table.style.cssText = "position:absolute;left:-11111px";
6996 tr.style.height = "1px";
6997 trChild.style.height = "9px";
7000 .appendChild( table )
7002 .appendChild( trChild );
7004 trStyle = window.getComputedStyle( tr );
7005 reliableTrDimensionsVal = parseInt( trStyle.height ) > 3;
7007 documentElement.removeChild( table );
7009 return reliableTrDimensionsVal;
7015 function curCSS( elem, name, computed ) {
7016 var width, minWidth, maxWidth, ret,
7018 // Support: Firefox 51+
7019 // Retrieving style before computed somehow
7020 // fixes an issue with getting wrong values
7021 // on detached elements
7024 computed = computed || getStyles( elem );
7026 // getPropertyValue is needed for:
7027 // .css('filter') (IE 9 only, #12537)
7028 // .css('--customProperty) (#3144)
7030 ret = computed.getPropertyValue( name ) || computed[ name ];
7032 if ( ret === "" && !isAttached( elem ) ) {
7033 ret = jQuery.style( elem, name );
7036 // A tribute to the "awesome hack by Dean Edwards"
7037 // Android Browser returns percentage for some values,
7038 // but width seems to be reliably pixels.
7039 // This is against the CSSOM draft spec:
7040 // https://drafts.csswg.org/cssom/#resolved-values
7041 if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {
7043 // Remember the original values
7044 width = style.width;
7045 minWidth = style.minWidth;
7046 maxWidth = style.maxWidth;
7048 // Put in the new values to get a computed value out
7049 style.minWidth = style.maxWidth = style.width = ret;
7050 ret = computed.width;
7052 // Revert the changed values
7053 style.width = width;
7054 style.minWidth = minWidth;
7055 style.maxWidth = maxWidth;
7059 return ret !== undefined ?
7061 // Support: IE <=9 - 11 only
7062 // IE returns zIndex value as an integer.
7068 function addGetHookIf( conditionFn, hookFn ) {
7070 // Define the hook, we'll check on the first run if it's really needed.
7073 if ( conditionFn() ) {
7075 // Hook not needed (or it's not possible to use it due
7076 // to missing dependency), remove it.
7081 // Hook needed; redefine it so that the support test is not executed again.
7082 return ( this.get = hookFn ).apply( this, arguments );
7088 var cssPrefixes = [ "Webkit", "Moz", "ms" ],
7089 emptyStyle = document.createElement( "div" ).style,
7092 // Return a vendor-prefixed property or undefined
7093 function vendorPropName( name ) {
7095 // Check for vendor prefixed names
7096 var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
7097 i = cssPrefixes.length;
7100 name = cssPrefixes[ i ] + capName;
7101 if ( name in emptyStyle ) {
7107 // Return a potentially-mapped jQuery.cssProps or vendor prefixed property
7108 function finalPropName( name ) {
7109 var final = jQuery.cssProps[ name ] || vendorProps[ name ];
7114 if ( name in emptyStyle ) {
7117 return vendorProps[ name ] = vendorPropName( name ) || name;
7123 // Swappable if display is none or starts with table
7124 // except "table", "table-cell", or "table-caption"
7125 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
7126 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
7127 rcustomProp = /^--/,
7128 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
7129 cssNormalTransform = {
7134 function setPositiveNumber( _elem, value, subtract ) {
7136 // Any relative (+/-) values have already been
7137 // normalized at this point
7138 var matches = rcssNum.exec( value );
7141 // Guard against undefined "subtract", e.g., when used as in cssHooks
7142 Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
7146 function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
7147 var i = dimension === "width" ? 1 : 0,
7151 // Adjustment may not be necessary
7152 if ( box === ( isBorderBox ? "border" : "content" ) ) {
7156 for ( ; i < 4; i += 2 ) {
7158 // Both box models exclude margin
7159 if ( box === "margin" ) {
7160 delta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
7163 // If we get here with a content-box, we're seeking "padding" or "border" or "margin"
7164 if ( !isBorderBox ) {
7167 delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7169 // For "border" or "margin", add border
7170 if ( box !== "padding" ) {
7171 delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7173 // But still keep track of it otherwise
7175 extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7178 // If we get here with a border-box (content + padding + border), we're seeking "content" or
7179 // "padding" or "margin"
7182 // For "content", subtract padding
7183 if ( box === "content" ) {
7184 delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7187 // For "content" or "padding", subtract border
7188 if ( box !== "margin" ) {
7189 delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7194 // Account for positive content-box scroll gutter when requested by providing computedVal
7195 if ( !isBorderBox && computedVal >= 0 ) {
7197 // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
7198 // Assuming integer scroll gutter, subtract the rest and round down
7199 delta += Math.max( 0, Math.ceil(
7200 elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
7206 // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter
7207 // Use an explicit zero to avoid NaN (gh-3964)
7214 function getWidthOrHeight( elem, dimension, extra ) {
7216 // Start with computed style
7217 var styles = getStyles( elem ),
7219 // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).
7220 // Fake content-box until we know it's needed to know the true value.
7221 boxSizingNeeded = !support.boxSizingReliable() || extra,
7222 isBorderBox = boxSizingNeeded &&
7223 jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7224 valueIsBorderBox = isBorderBox,
7226 val = curCSS( elem, dimension, styles ),
7227 offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );
7229 // Support: Firefox <=54
7230 // Return a confounding non-pixel value or feign ignorance, as appropriate.
7231 if ( rnumnonpx.test( val ) ) {
7239 // Support: IE 9 - 11 only
7240 // Use offsetWidth/offsetHeight for when box sizing is unreliable.
7241 // In those cases, the computed value can be trusted to be border-box.
7242 if ( ( !support.boxSizingReliable() && isBorderBox ||
7244 // Support: IE 10 - 11+, Edge 15 - 18+
7245 // IE/Edge misreport `getComputedStyle` of table rows with width/height
7246 // set in CSS while `offset*` properties report correct values.
7247 // Interestingly, in some cases IE 9 doesn't suffer from this issue.
7248 !support.reliableTrDimensions() && nodeName( elem, "tr" ) ||
7250 // Fall back to offsetWidth/offsetHeight when value is "auto"
7251 // This happens for inline elements with no explicit setting (gh-3571)
7254 // Support: Android <=4.1 - 4.3 only
7255 // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
7256 !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&
7258 // Make sure the element is visible & connected
7259 elem.getClientRects().length ) {
7261 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
7263 // Where available, offsetWidth/offsetHeight approximate border box dimensions.
7264 // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
7265 // retrieved value as a content box dimension.
7266 valueIsBorderBox = offsetProp in elem;
7267 if ( valueIsBorderBox ) {
7268 val = elem[ offsetProp ];
7272 // Normalize "" and auto
7273 val = parseFloat( val ) || 0;
7275 // Adjust for the element's box model
7280 extra || ( isBorderBox ? "border" : "content" ),
7284 // Provide the current computed size to request scroll gutter calculation (gh-3589)
7292 // Add in style property hooks for overriding the default
7293 // behavior of getting and setting a style property
7296 get: function( elem, computed ) {
7299 // We should always get a number back from opacity
7300 var ret = curCSS( elem, "opacity" );
7301 return ret === "" ? "1" : ret;
7307 // Don't automatically add "px" to these possibly-unitless properties
7309 "animationIterationCount": true,
7310 "columnCount": true,
7311 "fillOpacity": true,
7317 "gridColumnEnd": true,
7318 "gridColumnStart": true,
7321 "gridRowStart": true,
7331 // Add in properties whose names you wish to fix before
7332 // setting or getting the value
7335 // Get and set the style property on a DOM Node
7336 style: function( elem, name, value, extra ) {
7338 // Don't set styles on text and comment nodes
7339 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
7343 // Make sure that we're working with the right name
7344 var ret, type, hooks,
7345 origName = camelCase( name ),
7346 isCustomProp = rcustomProp.test( name ),
7349 // Make sure that we're working with the right name. We don't
7350 // want to query the value if it is a CSS custom property
7351 // since they are user-defined.
7352 if ( !isCustomProp ) {
7353 name = finalPropName( origName );
7356 // Gets hook for the prefixed version, then unprefixed version
7357 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
7359 // Check if we're setting a value
7360 if ( value !== undefined ) {
7361 type = typeof value;
7363 // Convert "+=" or "-=" to relative numbers (#7345)
7364 if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
7365 value = adjustCSS( elem, name, ret );
7371 // Make sure that null and NaN values aren't set (#7116)
7372 if ( value == null || value !== value ) {
7376 // If a number was passed in, add the unit (except for certain CSS properties)
7377 // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append
7378 // "px" to a few hardcoded values.
7379 if ( type === "number" && !isCustomProp ) {
7380 value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
7383 // background-* props affect original clone's values
7384 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
7385 style[ name ] = "inherit";
7388 // If a hook was provided, use that value, otherwise just set the specified value
7389 if ( !hooks || !( "set" in hooks ) ||
7390 ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
7392 if ( isCustomProp ) {
7393 style.setProperty( name, value );
7395 style[ name ] = value;
7401 // If a hook was provided get the non-computed value from there
7402 if ( hooks && "get" in hooks &&
7403 ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
7408 // Otherwise just get the value from the style object
7409 return style[ name ];
7413 css: function( elem, name, extra, styles ) {
7414 var val, num, hooks,
7415 origName = camelCase( name ),
7416 isCustomProp = rcustomProp.test( name );
7418 // Make sure that we're working with the right name. We don't
7419 // want to modify the value if it is a CSS custom property
7420 // since they are user-defined.
7421 if ( !isCustomProp ) {
7422 name = finalPropName( origName );
7425 // Try prefixed name followed by the unprefixed name
7426 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
7428 // If a hook was provided get the computed value from there
7429 if ( hooks && "get" in hooks ) {
7430 val = hooks.get( elem, true, extra );
7433 // Otherwise, if a way to get the computed value exists, use that
7434 if ( val === undefined ) {
7435 val = curCSS( elem, name, styles );
7438 // Convert "normal" to computed value
7439 if ( val === "normal" && name in cssNormalTransform ) {
7440 val = cssNormalTransform[ name ];
7443 // Make numeric if forced or a qualifier was provided and val looks numeric
7444 if ( extra === "" || extra ) {
7445 num = parseFloat( val );
7446 return extra === true || isFinite( num ) ? num || 0 : val;
7453 jQuery.each( [ "height", "width" ], function( _i, dimension ) {
7454 jQuery.cssHooks[ dimension ] = {
7455 get: function( elem, computed, extra ) {
7458 // Certain elements can have dimension info if we invisibly show them
7459 // but it must have a current display style that would benefit
7460 return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
7462 // Support: Safari 8+
7463 // Table columns in Safari have non-zero offsetWidth & zero
7464 // getBoundingClientRect().width unless display is changed.
7465 // Support: IE <=11 only
7466 // Running getBoundingClientRect on a disconnected node
7467 // in IE throws an error.
7468 ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
7469 swap( elem, cssShow, function() {
7470 return getWidthOrHeight( elem, dimension, extra );
7472 getWidthOrHeight( elem, dimension, extra );
7476 set: function( elem, value, extra ) {
7478 styles = getStyles( elem ),
7480 // Only read styles.position if the test has a chance to fail
7481 // to avoid forcing a reflow.
7482 scrollboxSizeBuggy = !support.scrollboxSize() &&
7483 styles.position === "absolute",
7485 // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)
7486 boxSizingNeeded = scrollboxSizeBuggy || extra,
7487 isBorderBox = boxSizingNeeded &&
7488 jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7499 // Account for unreliable border-box dimensions by comparing offset* to computed and
7500 // faking a content-box to get border and padding (gh-3699)
7501 if ( isBorderBox && scrollboxSizeBuggy ) {
7502 subtract -= Math.ceil(
7503 elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
7504 parseFloat( styles[ dimension ] ) -
7505 boxModelAdjustment( elem, dimension, "border", false, styles ) -
7510 // Convert to pixels if value adjustment is needed
7511 if ( subtract && ( matches = rcssNum.exec( value ) ) &&
7512 ( matches[ 3 ] || "px" ) !== "px" ) {
7514 elem.style[ dimension ] = value;
7515 value = jQuery.css( elem, dimension );
7518 return setPositiveNumber( elem, value, subtract );
7523 jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
7524 function( elem, computed ) {
7526 return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
7527 elem.getBoundingClientRect().left -
7528 swap( elem, { marginLeft: 0 }, function() {
7529 return elem.getBoundingClientRect().left;
7536 // These hooks are used by animate to expand properties
7541 }, function( prefix, suffix ) {
7542 jQuery.cssHooks[ prefix + suffix ] = {
7543 expand: function( value ) {
7547 // Assumes a single number if not a string
7548 parts = typeof value === "string" ? value.split( " " ) : [ value ];
7550 for ( ; i < 4; i++ ) {
7551 expanded[ prefix + cssExpand[ i ] + suffix ] =
7552 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7559 if ( prefix !== "margin" ) {
7560 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7565 css: function( name, value ) {
7566 return access( this, function( elem, name, value ) {
7571 if ( Array.isArray( name ) ) {
7572 styles = getStyles( elem );
7575 for ( ; i < len; i++ ) {
7576 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
7582 return value !== undefined ?
7583 jQuery.style( elem, name, value ) :
7584 jQuery.css( elem, name );
7585 }, name, value, arguments.length > 1 );
7590 function Tween( elem, options, prop, end, easing ) {
7591 return new Tween.prototype.init( elem, options, prop, end, easing );
7593 jQuery.Tween = Tween;
7597 init: function( elem, options, prop, end, easing, unit ) {
7600 this.easing = easing || jQuery.easing._default;
7601 this.options = options;
7602 this.start = this.now = this.cur();
7604 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
7607 var hooks = Tween.propHooks[ this.prop ];
7609 return hooks && hooks.get ?
7611 Tween.propHooks._default.get( this );
7613 run: function( percent ) {
7615 hooks = Tween.propHooks[ this.prop ];
7617 if ( this.options.duration ) {
7618 this.pos = eased = jQuery.easing[ this.easing ](
7619 percent, this.options.duration * percent, 0, 1, this.options.duration
7622 this.pos = eased = percent;
7624 this.now = ( this.end - this.start ) * eased + this.start;
7626 if ( this.options.step ) {
7627 this.options.step.call( this.elem, this.now, this );
7630 if ( hooks && hooks.set ) {
7633 Tween.propHooks._default.set( this );
7639 Tween.prototype.init.prototype = Tween.prototype;
7643 get: function( tween ) {
7646 // Use a property on the element directly when it is not a DOM element,
7647 // or when there is no matching style property that exists.
7648 if ( tween.elem.nodeType !== 1 ||
7649 tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
7650 return tween.elem[ tween.prop ];
7653 // Passing an empty string as a 3rd parameter to .css will automatically
7654 // attempt a parseFloat and fallback to a string if the parse fails.
7655 // Simple values such as "10px" are parsed to Float;
7656 // complex values such as "rotate(1rad)" are returned as-is.
7657 result = jQuery.css( tween.elem, tween.prop, "" );
7659 // Empty strings, null, undefined and "auto" are converted to 0.
7660 return !result || result === "auto" ? 0 : result;
7662 set: function( tween ) {
7664 // Use step hook for back compat.
7665 // Use cssHook if its there.
7666 // Use .style if available and use plain properties where available.
7667 if ( jQuery.fx.step[ tween.prop ] ) {
7668 jQuery.fx.step[ tween.prop ]( tween );
7669 } else if ( tween.elem.nodeType === 1 && (
7670 jQuery.cssHooks[ tween.prop ] ||
7671 tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
7672 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
7674 tween.elem[ tween.prop ] = tween.now;
7680 // Support: IE <=9 only
7681 // Panic based approach to setting things on disconnected nodes
7682 Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
7683 set: function( tween ) {
7684 if ( tween.elem.nodeType && tween.elem.parentNode ) {
7685 tween.elem[ tween.prop ] = tween.now;
7691 linear: function( p ) {
7694 swing: function( p ) {
7695 return 0.5 - Math.cos( p * Math.PI ) / 2;
7700 jQuery.fx = Tween.prototype.init;
7702 // Back compat <1.8 extension point
7703 jQuery.fx.step = {};
7710 rfxtypes = /^(?:toggle|show|hide)$/,
7711 rrun = /queueHooks$/;
7713 function schedule() {
7715 if ( document.hidden === false && window.requestAnimationFrame ) {
7716 window.requestAnimationFrame( schedule );
7718 window.setTimeout( schedule, jQuery.fx.interval );
7725 // Animations created synchronously will run synchronously
7726 function createFxNow() {
7727 window.setTimeout( function() {
7730 return ( fxNow = Date.now() );
7733 // Generate parameters to create a standard animation
7734 function genFx( type, includeWidth ) {
7737 attrs = { height: type };
7739 // If we include width, step value is 1 to do all cssExpand values,
7740 // otherwise step value is 2 to skip over Left and Right
7741 includeWidth = includeWidth ? 1 : 0;
7742 for ( ; i < 4; i += 2 - includeWidth ) {
7743 which = cssExpand[ i ];
7744 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
7747 if ( includeWidth ) {
7748 attrs.opacity = attrs.width = type;
7754 function createTween( value, prop, animation ) {
7756 collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
7758 length = collection.length;
7759 for ( ; index < length; index++ ) {
7760 if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
7762 // We're done with this property
7768 function defaultPrefilter( elem, props, opts ) {
7769 var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
7770 isBox = "width" in props || "height" in props,
7774 hidden = elem.nodeType && isHiddenWithinTree( elem ),
7775 dataShow = dataPriv.get( elem, "fxshow" );
7777 // Queue-skipping animations hijack the fx hooks
7778 if ( !opts.queue ) {
7779 hooks = jQuery._queueHooks( elem, "fx" );
7780 if ( hooks.unqueued == null ) {
7782 oldfire = hooks.empty.fire;
7783 hooks.empty.fire = function() {
7784 if ( !hooks.unqueued ) {
7791 anim.always( function() {
7793 // Ensure the complete handler is called before this completes
7794 anim.always( function() {
7796 if ( !jQuery.queue( elem, "fx" ).length ) {
7803 // Detect show/hide animations
7804 for ( prop in props ) {
7805 value = props[ prop ];
7806 if ( rfxtypes.test( value ) ) {
7807 delete props[ prop ];
7808 toggle = toggle || value === "toggle";
7809 if ( value === ( hidden ? "hide" : "show" ) ) {
7811 // Pretend to be hidden if this is a "show" and
7812 // there is still data from a stopped show/hide
7813 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
7816 // Ignore all other no-op show/hide data
7821 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
7825 // Bail out if this is a no-op like .hide().hide()
7826 propTween = !jQuery.isEmptyObject( props );
7827 if ( !propTween && jQuery.isEmptyObject( orig ) ) {
7831 // Restrict "overflow" and "display" styles during box animations
7832 if ( isBox && elem.nodeType === 1 ) {
7834 // Support: IE <=9 - 11, Edge 12 - 15
7835 // Record all 3 overflow attributes because IE does not infer the shorthand
7836 // from identically-valued overflowX and overflowY and Edge just mirrors
7837 // the overflowX value there.
7838 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
7840 // Identify a display type, preferring old show/hide data over the CSS cascade
7841 restoreDisplay = dataShow && dataShow.display;
7842 if ( restoreDisplay == null ) {
7843 restoreDisplay = dataPriv.get( elem, "display" );
7845 display = jQuery.css( elem, "display" );
7846 if ( display === "none" ) {
7847 if ( restoreDisplay ) {
7848 display = restoreDisplay;
7851 // Get nonempty value(s) by temporarily forcing visibility
7852 showHide( [ elem ], true );
7853 restoreDisplay = elem.style.display || restoreDisplay;
7854 display = jQuery.css( elem, "display" );
7855 showHide( [ elem ] );
7859 // Animate inline elements as inline-block
7860 if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
7861 if ( jQuery.css( elem, "float" ) === "none" ) {
7863 // Restore the original display value at the end of pure show/hide animations
7865 anim.done( function() {
7866 style.display = restoreDisplay;
7868 if ( restoreDisplay == null ) {
7869 display = style.display;
7870 restoreDisplay = display === "none" ? "" : display;
7873 style.display = "inline-block";
7878 if ( opts.overflow ) {
7879 style.overflow = "hidden";
7880 anim.always( function() {
7881 style.overflow = opts.overflow[ 0 ];
7882 style.overflowX = opts.overflow[ 1 ];
7883 style.overflowY = opts.overflow[ 2 ];
7887 // Implement show/hide animations
7889 for ( prop in orig ) {
7891 // General show/hide setup for this element animation
7894 if ( "hidden" in dataShow ) {
7895 hidden = dataShow.hidden;
7898 dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
7901 // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
7903 dataShow.hidden = !hidden;
7906 // Show elements before animating them
7908 showHide( [ elem ], true );
7911 /* eslint-disable no-loop-func */
7913 anim.done( function() {
7915 /* eslint-enable no-loop-func */
7917 // The final step of a "hide" animation is actually hiding the element
7919 showHide( [ elem ] );
7921 dataPriv.remove( elem, "fxshow" );
7922 for ( prop in orig ) {
7923 jQuery.style( elem, prop, orig[ prop ] );
7928 // Per-property setup
7929 propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7930 if ( !( prop in dataShow ) ) {
7931 dataShow[ prop ] = propTween.start;
7933 propTween.end = propTween.start;
7934 propTween.start = 0;
7940 function propFilter( props, specialEasing ) {
7941 var index, name, easing, value, hooks;
7943 // camelCase, specialEasing and expand cssHook pass
7944 for ( index in props ) {
7945 name = camelCase( index );
7946 easing = specialEasing[ name ];
7947 value = props[ index ];
7948 if ( Array.isArray( value ) ) {
7949 easing = value[ 1 ];
7950 value = props[ index ] = value[ 0 ];
7953 if ( index !== name ) {
7954 props[ name ] = value;
7955 delete props[ index ];
7958 hooks = jQuery.cssHooks[ name ];
7959 if ( hooks && "expand" in hooks ) {
7960 value = hooks.expand( value );
7961 delete props[ name ];
7963 // Not quite $.extend, this won't overwrite existing keys.
7964 // Reusing 'index' because we have the correct "name"
7965 for ( index in value ) {
7966 if ( !( index in props ) ) {
7967 props[ index ] = value[ index ];
7968 specialEasing[ index ] = easing;
7972 specialEasing[ name ] = easing;
7977 function Animation( elem, properties, options ) {
7981 length = Animation.prefilters.length,
7982 deferred = jQuery.Deferred().always( function() {
7984 // Don't match elem in the :animated selector
7991 var currentTime = fxNow || createFxNow(),
7992 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7994 // Support: Android 2.3 only
7995 // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
7996 temp = remaining / animation.duration || 0,
7999 length = animation.tweens.length;
8001 for ( ; index < length; index++ ) {
8002 animation.tweens[ index ].run( percent );
8005 deferred.notifyWith( elem, [ animation, percent, remaining ] );
8007 // If there's more to do, yield
8008 if ( percent < 1 && length ) {
8012 // If this was an empty animation, synthesize a final progress notification
8014 deferred.notifyWith( elem, [ animation, 1, 0 ] );
8017 // Resolve the animation and report its conclusion
8018 deferred.resolveWith( elem, [ animation ] );
8021 animation = deferred.promise( {
8023 props: jQuery.extend( {}, properties ),
8024 opts: jQuery.extend( true, {
8026 easing: jQuery.easing._default
8028 originalProperties: properties,
8029 originalOptions: options,
8030 startTime: fxNow || createFxNow(),
8031 duration: options.duration,
8033 createTween: function( prop, end ) {
8034 var tween = jQuery.Tween( elem, animation.opts, prop, end,
8035 animation.opts.specialEasing[ prop ] || animation.opts.easing );
8036 animation.tweens.push( tween );
8039 stop: function( gotoEnd ) {
8042 // If we are going to the end, we want to run all the tweens
8043 // otherwise we skip this part
8044 length = gotoEnd ? animation.tweens.length : 0;
8049 for ( ; index < length; index++ ) {
8050 animation.tweens[ index ].run( 1 );
8053 // Resolve when we played the last frame; otherwise, reject
8055 deferred.notifyWith( elem, [ animation, 1, 0 ] );
8056 deferred.resolveWith( elem, [ animation, gotoEnd ] );
8058 deferred.rejectWith( elem, [ animation, gotoEnd ] );
8063 props = animation.props;
8065 propFilter( props, animation.opts.specialEasing );
8067 for ( ; index < length; index++ ) {
8068 result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
8070 if ( isFunction( result.stop ) ) {
8071 jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
8072 result.stop.bind( result );
8078 jQuery.map( props, createTween, animation );
8080 if ( isFunction( animation.opts.start ) ) {
8081 animation.opts.start.call( elem, animation );
8084 // Attach callbacks from options
8086 .progress( animation.opts.progress )
8087 .done( animation.opts.done, animation.opts.complete )
8088 .fail( animation.opts.fail )
8089 .always( animation.opts.always );
8092 jQuery.extend( tick, {
8095 queue: animation.opts.queue
8102 jQuery.Animation = jQuery.extend( Animation, {
8105 "*": [ function( prop, value ) {
8106 var tween = this.createTween( prop, value );
8107 adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
8112 tweener: function( props, callback ) {
8113 if ( isFunction( props ) ) {
8117 props = props.match( rnothtmlwhite );
8122 length = props.length;
8124 for ( ; index < length; index++ ) {
8125 prop = props[ index ];
8126 Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
8127 Animation.tweeners[ prop ].unshift( callback );
8131 prefilters: [ defaultPrefilter ],
8133 prefilter: function( callback, prepend ) {
8135 Animation.prefilters.unshift( callback );
8137 Animation.prefilters.push( callback );
8142 jQuery.speed = function( speed, easing, fn ) {
8143 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
8144 complete: fn || !fn && easing ||
8145 isFunction( speed ) && speed,
8147 easing: fn && easing || easing && !isFunction( easing ) && easing
8150 // Go to the end state if fx are off
8151 if ( jQuery.fx.off ) {
8155 if ( typeof opt.duration !== "number" ) {
8156 if ( opt.duration in jQuery.fx.speeds ) {
8157 opt.duration = jQuery.fx.speeds[ opt.duration ];
8160 opt.duration = jQuery.fx.speeds._default;
8165 // Normalize opt.queue - true/undefined/null -> "fx"
8166 if ( opt.queue == null || opt.queue === true ) {
8171 opt.old = opt.complete;
8173 opt.complete = function() {
8174 if ( isFunction( opt.old ) ) {
8175 opt.old.call( this );
8179 jQuery.dequeue( this, opt.queue );
8187 fadeTo: function( speed, to, easing, callback ) {
8189 // Show any hidden elements after setting opacity to 0
8190 return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
8192 // Animate to the value specified
8193 .end().animate( { opacity: to }, speed, easing, callback );
8195 animate: function( prop, speed, easing, callback ) {
8196 var empty = jQuery.isEmptyObject( prop ),
8197 optall = jQuery.speed( speed, easing, callback ),
8198 doAnimation = function() {
8200 // Operate on a copy of prop so per-property easing won't be lost
8201 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
8203 // Empty animations, or finishing resolves immediately
8204 if ( empty || dataPriv.get( this, "finish" ) ) {
8208 doAnimation.finish = doAnimation;
8210 return empty || optall.queue === false ?
8211 this.each( doAnimation ) :
8212 this.queue( optall.queue, doAnimation );
8214 stop: function( type, clearQueue, gotoEnd ) {
8215 var stopQueue = function( hooks ) {
8216 var stop = hooks.stop;
8221 if ( typeof type !== "string" ) {
8222 gotoEnd = clearQueue;
8227 this.queue( type || "fx", [] );
8230 return this.each( function() {
8232 index = type != null && type + "queueHooks",
8233 timers = jQuery.timers,
8234 data = dataPriv.get( this );
8237 if ( data[ index ] && data[ index ].stop ) {
8238 stopQueue( data[ index ] );
8241 for ( index in data ) {
8242 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
8243 stopQueue( data[ index ] );
8248 for ( index = timers.length; index--; ) {
8249 if ( timers[ index ].elem === this &&
8250 ( type == null || timers[ index ].queue === type ) ) {
8252 timers[ index ].anim.stop( gotoEnd );
8254 timers.splice( index, 1 );
8258 // Start the next in the queue if the last step wasn't forced.
8259 // Timers currently will call their complete callbacks, which
8260 // will dequeue but only if they were gotoEnd.
8261 if ( dequeue || !gotoEnd ) {
8262 jQuery.dequeue( this, type );
8266 finish: function( type ) {
8267 if ( type !== false ) {
8268 type = type || "fx";
8270 return this.each( function() {
8272 data = dataPriv.get( this ),
8273 queue = data[ type + "queue" ],
8274 hooks = data[ type + "queueHooks" ],
8275 timers = jQuery.timers,
8276 length = queue ? queue.length : 0;
8278 // Enable finishing flag on private data
8281 // Empty the queue first
8282 jQuery.queue( this, type, [] );
8284 if ( hooks && hooks.stop ) {
8285 hooks.stop.call( this, true );
8288 // Look for any active animations, and finish them
8289 for ( index = timers.length; index--; ) {
8290 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
8291 timers[ index ].anim.stop( true );
8292 timers.splice( index, 1 );
8296 // Look for any animations in the old queue and finish them
8297 for ( index = 0; index < length; index++ ) {
8298 if ( queue[ index ] && queue[ index ].finish ) {
8299 queue[ index ].finish.call( this );
8303 // Turn off finishing flag
8309 jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
8310 var cssFn = jQuery.fn[ name ];
8311 jQuery.fn[ name ] = function( speed, easing, callback ) {
8312 return speed == null || typeof speed === "boolean" ?
8313 cssFn.apply( this, arguments ) :
8314 this.animate( genFx( name, true ), speed, easing, callback );
8318 // Generate shortcuts for custom animations
8320 slideDown: genFx( "show" ),
8321 slideUp: genFx( "hide" ),
8322 slideToggle: genFx( "toggle" ),
8323 fadeIn: { opacity: "show" },
8324 fadeOut: { opacity: "hide" },
8325 fadeToggle: { opacity: "toggle" }
8326 }, function( name, props ) {
8327 jQuery.fn[ name ] = function( speed, easing, callback ) {
8328 return this.animate( props, speed, easing, callback );
8333 jQuery.fx.tick = function() {
8336 timers = jQuery.timers;
8340 for ( ; i < timers.length; i++ ) {
8341 timer = timers[ i ];
8343 // Run the timer and safely remove it when done (allowing for external removal)
8344 if ( !timer() && timers[ i ] === timer ) {
8345 timers.splice( i--, 1 );
8349 if ( !timers.length ) {
8355 jQuery.fx.timer = function( timer ) {
8356 jQuery.timers.push( timer );
8360 jQuery.fx.interval = 13;
8361 jQuery.fx.start = function() {
8370 jQuery.fx.stop = function() {
8374 jQuery.fx.speeds = {
8383 // Based off of the plugin by Clint Helfers, with permission.
8384 // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
8385 jQuery.fn.delay = function( time, type ) {
8386 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
8387 type = type || "fx";
8389 return this.queue( type, function( next, hooks ) {
8390 var timeout = window.setTimeout( next, time );
8391 hooks.stop = function() {
8392 window.clearTimeout( timeout );
8399 var input = document.createElement( "input" ),
8400 select = document.createElement( "select" ),
8401 opt = select.appendChild( document.createElement( "option" ) );
8403 input.type = "checkbox";
8405 // Support: Android <=4.3 only
8406 // Default value for a checkbox should be "on"
8407 support.checkOn = input.value !== "";
8409 // Support: IE <=11 only
8410 // Must access selectedIndex to make default options select
8411 support.optSelected = opt.selected;
8413 // Support: IE <=11 only
8414 // An input loses its value after becoming a radio
8415 input = document.createElement( "input" );
8417 input.type = "radio";
8418 support.radioValue = input.value === "t";
8423 attrHandle = jQuery.expr.attrHandle;
8426 attr: function( name, value ) {
8427 return access( this, jQuery.attr, name, value, arguments.length > 1 );
8430 removeAttr: function( name ) {
8431 return this.each( function() {
8432 jQuery.removeAttr( this, name );
8438 attr: function( elem, name, value ) {
8440 nType = elem.nodeType;
8442 // Don't get/set attributes on text, comment and attribute nodes
8443 if ( nType === 3 || nType === 8 || nType === 2 ) {
8447 // Fallback to prop when attributes are not supported
8448 if ( typeof elem.getAttribute === "undefined" ) {
8449 return jQuery.prop( elem, name, value );
8452 // Attribute hooks are determined by the lowercase version
8453 // Grab necessary hook if one is defined
8454 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
8455 hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
8456 ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
8459 if ( value !== undefined ) {
8460 if ( value === null ) {
8461 jQuery.removeAttr( elem, name );
8465 if ( hooks && "set" in hooks &&
8466 ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
8470 elem.setAttribute( name, value + "" );
8474 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
8478 ret = jQuery.find.attr( elem, name );
8480 // Non-existent attributes return null, we normalize to undefined
8481 return ret == null ? undefined : ret;
8486 set: function( elem, value ) {
8487 if ( !support.radioValue && value === "radio" &&
8488 nodeName( elem, "input" ) ) {
8489 var val = elem.value;
8490 elem.setAttribute( "type", value );
8500 removeAttr: function( elem, value ) {
8504 // Attribute names can contain non-HTML whitespace characters
8505 // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
8506 attrNames = value && value.match( rnothtmlwhite );
8508 if ( attrNames && elem.nodeType === 1 ) {
8509 while ( ( name = attrNames[ i++ ] ) ) {
8510 elem.removeAttribute( name );
8516 // Hooks for boolean attributes
8518 set: function( elem, value, name ) {
8519 if ( value === false ) {
8521 // Remove boolean attributes when set to false
8522 jQuery.removeAttr( elem, name );
8524 elem.setAttribute( name, name );
8530 jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) {
8531 var getter = attrHandle[ name ] || jQuery.find.attr;
8533 attrHandle[ name ] = function( elem, name, isXML ) {
8535 lowercaseName = name.toLowerCase();
8539 // Avoid an infinite loop by temporarily removing this function from the getter
8540 handle = attrHandle[ lowercaseName ];
8541 attrHandle[ lowercaseName ] = ret;
8542 ret = getter( elem, name, isXML ) != null ?
8545 attrHandle[ lowercaseName ] = handle;
8554 var rfocusable = /^(?:input|select|textarea|button)$/i,
8555 rclickable = /^(?:a|area)$/i;
8558 prop: function( name, value ) {
8559 return access( this, jQuery.prop, name, value, arguments.length > 1 );
8562 removeProp: function( name ) {
8563 return this.each( function() {
8564 delete this[ jQuery.propFix[ name ] || name ];
8570 prop: function( elem, name, value ) {
8572 nType = elem.nodeType;
8574 // Don't get/set properties on text, comment and attribute nodes
8575 if ( nType === 3 || nType === 8 || nType === 2 ) {
8579 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
8581 // Fix name and attach hooks
8582 name = jQuery.propFix[ name ] || name;
8583 hooks = jQuery.propHooks[ name ];
8586 if ( value !== undefined ) {
8587 if ( hooks && "set" in hooks &&
8588 ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
8592 return ( elem[ name ] = value );
8595 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
8599 return elem[ name ];
8604 get: function( elem ) {
8606 // Support: IE <=9 - 11 only
8607 // elem.tabIndex doesn't always return the
8608 // correct value when it hasn't been explicitly set
8609 // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
8610 // Use proper attribute retrieval(#12072)
8611 var tabindex = jQuery.find.attr( elem, "tabindex" );
8614 return parseInt( tabindex, 10 );
8618 rfocusable.test( elem.nodeName ) ||
8619 rclickable.test( elem.nodeName ) &&
8632 "class": "className"
8636 // Support: IE <=11 only
8637 // Accessing the selectedIndex property
8638 // forces the browser to respect setting selected
8640 // The getter ensures a default option is selected
8641 // when in an optgroup
8642 // eslint rule "no-unused-expressions" is disabled for this code
8643 // since it considers such accessions noop
8644 if ( !support.optSelected ) {
8645 jQuery.propHooks.selected = {
8646 get: function( elem ) {
8648 /* eslint no-unused-expressions: "off" */
8650 var parent = elem.parentNode;
8651 if ( parent && parent.parentNode ) {
8652 parent.parentNode.selectedIndex;
8656 set: function( elem ) {
8658 /* eslint no-unused-expressions: "off" */
8660 var parent = elem.parentNode;
8662 parent.selectedIndex;
8664 if ( parent.parentNode ) {
8665 parent.parentNode.selectedIndex;
8684 jQuery.propFix[ this.toLowerCase() ] = this;
8690 // Strip and collapse whitespace according to HTML spec
8691 // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
8692 function stripAndCollapse( value ) {
8693 var tokens = value.match( rnothtmlwhite ) || [];
8694 return tokens.join( " " );
8698 function getClass( elem ) {
8699 return elem.getAttribute && elem.getAttribute( "class" ) || "";
8702 function classesToArray( value ) {
8703 if ( Array.isArray( value ) ) {
8706 if ( typeof value === "string" ) {
8707 return value.match( rnothtmlwhite ) || [];
8713 addClass: function( value ) {
8714 var classes, elem, cur, curValue, clazz, j, finalValue,
8717 if ( isFunction( value ) ) {
8718 return this.each( function( j ) {
8719 jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
8723 classes = classesToArray( value );
8725 if ( classes.length ) {
8726 while ( ( elem = this[ i++ ] ) ) {
8727 curValue = getClass( elem );
8728 cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
8732 while ( ( clazz = classes[ j++ ] ) ) {
8733 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
8738 // Only assign if different to avoid unneeded rendering.
8739 finalValue = stripAndCollapse( cur );
8740 if ( curValue !== finalValue ) {
8741 elem.setAttribute( "class", finalValue );
8750 removeClass: function( value ) {
8751 var classes, elem, cur, curValue, clazz, j, finalValue,
8754 if ( isFunction( value ) ) {
8755 return this.each( function( j ) {
8756 jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
8760 if ( !arguments.length ) {
8761 return this.attr( "class", "" );
8764 classes = classesToArray( value );
8766 if ( classes.length ) {
8767 while ( ( elem = this[ i++ ] ) ) {
8768 curValue = getClass( elem );
8770 // This expression is here for better compressibility (see addClass)
8771 cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
8775 while ( ( clazz = classes[ j++ ] ) ) {
8777 // Remove *all* instances
8778 while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
8779 cur = cur.replace( " " + clazz + " ", " " );
8783 // Only assign if different to avoid unneeded rendering.
8784 finalValue = stripAndCollapse( cur );
8785 if ( curValue !== finalValue ) {
8786 elem.setAttribute( "class", finalValue );
8795 toggleClass: function( value, stateVal ) {
8796 var type = typeof value,
8797 isValidValue = type === "string" || Array.isArray( value );
8799 if ( typeof stateVal === "boolean" && isValidValue ) {
8800 return stateVal ? this.addClass( value ) : this.removeClass( value );
8803 if ( isFunction( value ) ) {
8804 return this.each( function( i ) {
8805 jQuery( this ).toggleClass(
8806 value.call( this, i, getClass( this ), stateVal ),
8812 return this.each( function() {
8813 var className, i, self, classNames;
8815 if ( isValidValue ) {
8817 // Toggle individual class names
8819 self = jQuery( this );
8820 classNames = classesToArray( value );
8822 while ( ( className = classNames[ i++ ] ) ) {
8824 // Check each className given, space separated list
8825 if ( self.hasClass( className ) ) {
8826 self.removeClass( className );
8828 self.addClass( className );
8832 // Toggle whole class name
8833 } else if ( value === undefined || type === "boolean" ) {
8834 className = getClass( this );
8837 // Store className if set
8838 dataPriv.set( this, "__className__", className );
8841 // If the element has a class name or if we're passed `false`,
8842 // then remove the whole classname (if there was one, the above saved it).
8843 // Otherwise bring back whatever was previously saved (if anything),
8844 // falling back to the empty string if nothing was stored.
8845 if ( this.setAttribute ) {
8846 this.setAttribute( "class",
8847 className || value === false ?
8849 dataPriv.get( this, "__className__" ) || ""
8856 hasClass: function( selector ) {
8857 var className, elem,
8860 className = " " + selector + " ";
8861 while ( ( elem = this[ i++ ] ) ) {
8862 if ( elem.nodeType === 1 &&
8863 ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
8875 var rreturn = /\r/g;
8878 val: function( value ) {
8879 var hooks, ret, valueIsFunction,
8882 if ( !arguments.length ) {
8884 hooks = jQuery.valHooks[ elem.type ] ||
8885 jQuery.valHooks[ elem.nodeName.toLowerCase() ];
8889 ( ret = hooks.get( elem, "value" ) ) !== undefined
8896 // Handle most common string cases
8897 if ( typeof ret === "string" ) {
8898 return ret.replace( rreturn, "" );
8901 // Handle cases where value is null/undef or number
8902 return ret == null ? "" : ret;
8908 valueIsFunction = isFunction( value );
8910 return this.each( function( i ) {
8913 if ( this.nodeType !== 1 ) {
8917 if ( valueIsFunction ) {
8918 val = value.call( this, i, jQuery( this ).val() );
8923 // Treat null/undefined as ""; convert numbers to string
8924 if ( val == null ) {
8927 } else if ( typeof val === "number" ) {
8930 } else if ( Array.isArray( val ) ) {
8931 val = jQuery.map( val, function( value ) {
8932 return value == null ? "" : value + "";
8936 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
8938 // If set returns undefined, fall back to normal setting
8939 if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
8949 get: function( elem ) {
8951 var val = jQuery.find.attr( elem, "value" );
8952 return val != null ?
8955 // Support: IE <=10 - 11 only
8956 // option.text throws exceptions (#14686, #14858)
8957 // Strip and collapse whitespace
8958 // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
8959 stripAndCollapse( jQuery.text( elem ) );
8963 get: function( elem ) {
8964 var value, option, i,
8965 options = elem.options,
8966 index = elem.selectedIndex,
8967 one = elem.type === "select-one",
8968 values = one ? null : [],
8969 max = one ? index + 1 : options.length;
8975 i = one ? index : 0;
8978 // Loop through all the selected options
8979 for ( ; i < max; i++ ) {
8980 option = options[ i ];
8982 // Support: IE <=9 only
8983 // IE8-9 doesn't update selected after form reset (#2551)
8984 if ( ( option.selected || i === index ) &&
8986 // Don't return options that are disabled or in a disabled optgroup
8988 ( !option.parentNode.disabled ||
8989 !nodeName( option.parentNode, "optgroup" ) ) ) {
8991 // Get the specific value for the option
8992 value = jQuery( option ).val();
8994 // We don't need an array for one selects
8999 // Multi-Selects return an array
9000 values.push( value );
9007 set: function( elem, value ) {
9008 var optionSet, option,
9009 options = elem.options,
9010 values = jQuery.makeArray( value ),
9014 option = options[ i ];
9016 /* eslint-disable no-cond-assign */
9018 if ( option.selected =
9019 jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
9024 /* eslint-enable no-cond-assign */
9027 // Force browsers to behave consistently when non-matching value is set
9029 elem.selectedIndex = -1;
9037 // Radios and checkboxes getter/setter
9038 jQuery.each( [ "radio", "checkbox" ], function() {
9039 jQuery.valHooks[ this ] = {
9040 set: function( elem, value ) {
9041 if ( Array.isArray( value ) ) {
9042 return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
9046 if ( !support.checkOn ) {
9047 jQuery.valHooks[ this ].get = function( elem ) {
9048 return elem.getAttribute( "value" ) === null ? "on" : elem.value;
9056 // Return jQuery for attributes-only inclusion
9059 support.focusin = "onfocusin" in window;
9062 var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
9063 stopPropagationCallback = function( e ) {
9064 e.stopPropagation();
9067 jQuery.extend( jQuery.event, {
9069 trigger: function( event, data, elem, onlyHandlers ) {
9071 var i, cur, tmp, bubbleType, ontype, handle, special, lastElement,
9072 eventPath = [ elem || document ],
9073 type = hasOwn.call( event, "type" ) ? event.type : event,
9074 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
9076 cur = lastElement = tmp = elem = elem || document;
9078 // Don't do events on text and comment nodes
9079 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
9083 // focus/blur morphs to focusin/out; ensure we're not firing them right now
9084 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
9088 if ( type.indexOf( "." ) > -1 ) {
9090 // Namespaced trigger; create a regexp to match event type in handle()
9091 namespaces = type.split( "." );
9092 type = namespaces.shift();
9095 ontype = type.indexOf( ":" ) < 0 && "on" + type;
9097 // Caller can pass in a jQuery.Event object, Object, or just an event type string
9098 event = event[ jQuery.expando ] ?
9100 new jQuery.Event( type, typeof event === "object" && event );
9102 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
9103 event.isTrigger = onlyHandlers ? 2 : 3;
9104 event.namespace = namespaces.join( "." );
9105 event.rnamespace = event.namespace ?
9106 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
9109 // Clean up the event in case it is being reused
9110 event.result = undefined;
9111 if ( !event.target ) {
9112 event.target = elem;
9115 // Clone any incoming data and prepend the event, creating the handler arg list
9116 data = data == null ?
9118 jQuery.makeArray( data, [ event ] );
9120 // Allow special events to draw outside the lines
9121 special = jQuery.event.special[ type ] || {};
9122 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
9126 // Determine event propagation path in advance, per W3C events spec (#9951)
9127 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
9128 if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {
9130 bubbleType = special.delegateType || type;
9131 if ( !rfocusMorph.test( bubbleType + type ) ) {
9132 cur = cur.parentNode;
9134 for ( ; cur; cur = cur.parentNode ) {
9135 eventPath.push( cur );
9139 // Only add window if we got to document (e.g., not plain obj or detached DOM)
9140 if ( tmp === ( elem.ownerDocument || document ) ) {
9141 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
9145 // Fire handlers on the event path
9147 while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
9149 event.type = i > 1 ?
9151 special.bindType || type;
9155 dataPriv.get( cur, "events" ) || Object.create( null )
9157 dataPriv.get( cur, "handle" );
9159 handle.apply( cur, data );
9163 handle = ontype && cur[ ontype ];
9164 if ( handle && handle.apply && acceptData( cur ) ) {
9165 event.result = handle.apply( cur, data );
9166 if ( event.result === false ) {
9167 event.preventDefault();
9173 // If nobody prevented the default action, do it now
9174 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
9176 if ( ( !special._default ||
9177 special._default.apply( eventPath.pop(), data ) === false ) &&
9178 acceptData( elem ) ) {
9180 // Call a native DOM method on the target with the same name as the event.
9181 // Don't do default actions on window, that's where global variables be (#6170)
9182 if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {
9184 // Don't re-trigger an onFOO event when we call its FOO() method
9185 tmp = elem[ ontype ];
9188 elem[ ontype ] = null;
9191 // Prevent re-triggering of the same event, since we already bubbled it above
9192 jQuery.event.triggered = type;
9194 if ( event.isPropagationStopped() ) {
9195 lastElement.addEventListener( type, stopPropagationCallback );
9200 if ( event.isPropagationStopped() ) {
9201 lastElement.removeEventListener( type, stopPropagationCallback );
9204 jQuery.event.triggered = undefined;
9207 elem[ ontype ] = tmp;
9213 return event.result;
9216 // Piggyback on a donor event to simulate a different one
9217 // Used only for `focus(in | out)` events
9218 simulate: function( type, elem, event ) {
9219 var e = jQuery.extend(
9228 jQuery.event.trigger( e, null, elem );
9235 trigger: function( type, data ) {
9236 return this.each( function() {
9237 jQuery.event.trigger( type, data, this );
9240 triggerHandler: function( type, data ) {
9241 var elem = this[ 0 ];
9243 return jQuery.event.trigger( type, data, elem, true );
9249 // Support: Firefox <=44
9250 // Firefox doesn't have focus(in | out) events
9251 // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
9253 // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
9254 // focus(in | out) events fire after focus & blur events,
9255 // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
9256 // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
9257 if ( !support.focusin ) {
9258 jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
9260 // Attach a single capturing handler on the document while someone wants focusin/focusout
9261 var handler = function( event ) {
9262 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
9265 jQuery.event.special[ fix ] = {
9268 // Handle: regular nodes (via `this.ownerDocument`), window
9269 // (via `this.document`) & document (via `this`).
9270 var doc = this.ownerDocument || this.document || this,
9271 attaches = dataPriv.access( doc, fix );
9274 doc.addEventListener( orig, handler, true );
9276 dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
9278 teardown: function() {
9279 var doc = this.ownerDocument || this.document || this,
9280 attaches = dataPriv.access( doc, fix ) - 1;
9283 doc.removeEventListener( orig, handler, true );
9284 dataPriv.remove( doc, fix );
9287 dataPriv.access( doc, fix, attaches );
9293 var location = window.location;
9295 var nonce = { guid: Date.now() };
9297 var rquery = ( /\?/ );
9301 // Cross-browser xml parsing
9302 jQuery.parseXML = function( data ) {
9304 if ( !data || typeof data !== "string" ) {
9308 // Support: IE 9 - 11 only
9309 // IE throws on parseFromString with invalid input.
9311 xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
9316 if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
9317 jQuery.error( "Invalid XML: " + data );
9326 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
9327 rsubmittable = /^(?:input|select|textarea|keygen)/i;
9329 function buildParams( prefix, obj, traditional, add ) {
9332 if ( Array.isArray( obj ) ) {
9334 // Serialize array item.
9335 jQuery.each( obj, function( i, v ) {
9336 if ( traditional || rbracket.test( prefix ) ) {
9338 // Treat each array item as a scalar.
9343 // Item is non-scalar (array or object), encode its numeric index.
9345 prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
9353 } else if ( !traditional && toType( obj ) === "object" ) {
9355 // Serialize object item.
9356 for ( name in obj ) {
9357 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
9362 // Serialize scalar item.
9367 // Serialize an array of form elements or a set of
9368 // key/values into a query string
9369 jQuery.param = function( a, traditional ) {
9372 add = function( key, valueOrFunction ) {
9374 // If value is a function, invoke it and use its return value
9375 var value = isFunction( valueOrFunction ) ?
9379 s[ s.length ] = encodeURIComponent( key ) + "=" +
9380 encodeURIComponent( value == null ? "" : value );
9387 // If an array was passed in, assume that it is an array of form elements.
9388 if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
9390 // Serialize the form elements
9391 jQuery.each( a, function() {
9392 add( this.name, this.value );
9397 // If traditional, encode the "old" way (the way 1.3.2 or older
9398 // did it), otherwise encode params recursively.
9399 for ( prefix in a ) {
9400 buildParams( prefix, a[ prefix ], traditional, add );
9404 // Return the resulting serialization
9405 return s.join( "&" );
9409 serialize: function() {
9410 return jQuery.param( this.serializeArray() );
9412 serializeArray: function() {
9413 return this.map( function() {
9415 // Can add propHook for "elements" to filter or add form elements
9416 var elements = jQuery.prop( this, "elements" );
9417 return elements ? jQuery.makeArray( elements ) : this;
9419 .filter( function() {
9420 var type = this.type;
9422 // Use .is( ":disabled" ) so that fieldset[disabled] works
9423 return this.name && !jQuery( this ).is( ":disabled" ) &&
9424 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
9425 ( this.checked || !rcheckableType.test( type ) );
9427 .map( function( _i, elem ) {
9428 var val = jQuery( this ).val();
9430 if ( val == null ) {
9434 if ( Array.isArray( val ) ) {
9435 return jQuery.map( val, function( val ) {
9436 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9440 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9449 rantiCache = /([?&])_=[^&]*/,
9450 rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
9452 // #7653, #8125, #8152: local protocol detection
9453 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
9454 rnoContent = /^(?:GET|HEAD)$/,
9455 rprotocol = /^\/\//,
9458 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
9459 * 2) These are called:
9460 * - BEFORE asking for a transport
9461 * - AFTER param serialization (s.data is a string if s.processData is true)
9462 * 3) key is the dataType
9463 * 4) the catchall symbol "*" can be used
9464 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
9468 /* Transports bindings
9469 * 1) key is the dataType
9470 * 2) the catchall symbol "*" can be used
9471 * 3) selection will start with transport dataType and THEN go to "*" if needed
9475 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
9476 allTypes = "*/".concat( "*" ),
9478 // Anchor tag for parsing the document origin
9479 originAnchor = document.createElement( "a" );
9480 originAnchor.href = location.href;
9482 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
9483 function addToPrefiltersOrTransports( structure ) {
9485 // dataTypeExpression is optional and defaults to "*"
9486 return function( dataTypeExpression, func ) {
9488 if ( typeof dataTypeExpression !== "string" ) {
9489 func = dataTypeExpression;
9490 dataTypeExpression = "*";
9495 dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
9497 if ( isFunction( func ) ) {
9499 // For each dataType in the dataTypeExpression
9500 while ( ( dataType = dataTypes[ i++ ] ) ) {
9502 // Prepend if requested
9503 if ( dataType[ 0 ] === "+" ) {
9504 dataType = dataType.slice( 1 ) || "*";
9505 ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
9509 ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
9516 // Base inspection function for prefilters and transports
9517 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
9520 seekingTransport = ( structure === transports );
9522 function inspect( dataType ) {
9524 inspected[ dataType ] = true;
9525 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
9526 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
9527 if ( typeof dataTypeOrTransport === "string" &&
9528 !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
9530 options.dataTypes.unshift( dataTypeOrTransport );
9531 inspect( dataTypeOrTransport );
9533 } else if ( seekingTransport ) {
9534 return !( selected = dataTypeOrTransport );
9540 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
9543 // A special extend for ajax options
9544 // that takes "flat" options (not to be deep extended)
9546 function ajaxExtend( target, src ) {
9548 flatOptions = jQuery.ajaxSettings.flatOptions || {};
9550 for ( key in src ) {
9551 if ( src[ key ] !== undefined ) {
9552 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
9556 jQuery.extend( true, target, deep );
9562 /* Handles responses to an ajax request:
9563 * - finds the right dataType (mediates between content-type and expected dataType)
9564 * - returns the corresponding response
9566 function ajaxHandleResponses( s, jqXHR, responses ) {
9568 var ct, type, finalDataType, firstDataType,
9569 contents = s.contents,
9570 dataTypes = s.dataTypes;
9572 // Remove auto dataType and get content-type in the process
9573 while ( dataTypes[ 0 ] === "*" ) {
9575 if ( ct === undefined ) {
9576 ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
9580 // Check if we're dealing with a known content-type
9582 for ( type in contents ) {
9583 if ( contents[ type ] && contents[ type ].test( ct ) ) {
9584 dataTypes.unshift( type );
9590 // Check to see if we have a response for the expected dataType
9591 if ( dataTypes[ 0 ] in responses ) {
9592 finalDataType = dataTypes[ 0 ];
9595 // Try convertible dataTypes
9596 for ( type in responses ) {
9597 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
9598 finalDataType = type;
9601 if ( !firstDataType ) {
9602 firstDataType = type;
9606 // Or just use first one
9607 finalDataType = finalDataType || firstDataType;
9610 // If we found a dataType
9611 // We add the dataType to the list if needed
9612 // and return the corresponding response
9613 if ( finalDataType ) {
9614 if ( finalDataType !== dataTypes[ 0 ] ) {
9615 dataTypes.unshift( finalDataType );
9617 return responses[ finalDataType ];
9621 /* Chain conversions given the request and the original response
9622 * Also sets the responseXXX fields on the jqXHR instance
9624 function ajaxConvert( s, response, jqXHR, isSuccess ) {
9625 var conv2, current, conv, tmp, prev,
9628 // Work with a copy of dataTypes in case we need to modify it for conversion
9629 dataTypes = s.dataTypes.slice();
9631 // Create converters map with lowercased keys
9632 if ( dataTypes[ 1 ] ) {
9633 for ( conv in s.converters ) {
9634 converters[ conv.toLowerCase() ] = s.converters[ conv ];
9638 current = dataTypes.shift();
9640 // Convert to each sequential dataType
9643 if ( s.responseFields[ current ] ) {
9644 jqXHR[ s.responseFields[ current ] ] = response;
9647 // Apply the dataFilter if provided
9648 if ( !prev && isSuccess && s.dataFilter ) {
9649 response = s.dataFilter( response, s.dataType );
9653 current = dataTypes.shift();
9657 // There's only work to do if current dataType is non-auto
9658 if ( current === "*" ) {
9662 // Convert response if prev dataType is non-auto and differs from current
9663 } else if ( prev !== "*" && prev !== current ) {
9665 // Seek a direct converter
9666 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
9668 // If none found, seek a pair
9670 for ( conv2 in converters ) {
9672 // If conv2 outputs current
9673 tmp = conv2.split( " " );
9674 if ( tmp[ 1 ] === current ) {
9676 // If prev can be converted to accepted input
9677 conv = converters[ prev + " " + tmp[ 0 ] ] ||
9678 converters[ "* " + tmp[ 0 ] ];
9681 // Condense equivalence converters
9682 if ( conv === true ) {
9683 conv = converters[ conv2 ];
9685 // Otherwise, insert the intermediate dataType
9686 } else if ( converters[ conv2 ] !== true ) {
9688 dataTypes.unshift( tmp[ 1 ] );
9696 // Apply converter (if not an equivalence)
9697 if ( conv !== true ) {
9699 // Unless errors are allowed to bubble, catch and return them
9700 if ( conv && s.throws ) {
9701 response = conv( response );
9704 response = conv( response );
9707 state: "parsererror",
9708 error: conv ? e : "No conversion from " + prev + " to " + current
9717 return { state: "success", data: response };
9722 // Counter for holding the number of active queries
9725 // Last-Modified header cache for next request
9732 isLocal: rlocalProtocol.test( location.protocol ),
9736 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
9754 xml: "application/xml, text/xml",
9755 json: "application/json, text/javascript"
9766 text: "responseText",
9767 json: "responseJSON"
9771 // Keys separate source (or catchall "*") and destination types with a single space
9774 // Convert anything to text
9777 // Text to html (true = no transformation)
9780 // Evaluate text as a json expression
9781 "text json": JSON.parse,
9783 // Parse text as xml
9784 "text xml": jQuery.parseXML
9787 // For options that shouldn't be deep extended:
9788 // you can add your own custom options here if
9789 // and when you create one that shouldn't be
9790 // deep extended (see ajaxExtend)
9797 // Creates a full fledged settings object into target
9798 // with both ajaxSettings and settings fields.
9799 // If target is omitted, writes into ajaxSettings.
9800 ajaxSetup: function( target, settings ) {
9803 // Building a settings object
9804 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
9806 // Extending ajaxSettings
9807 ajaxExtend( jQuery.ajaxSettings, target );
9810 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
9811 ajaxTransport: addToPrefiltersOrTransports( transports ),
9814 ajax: function( url, options ) {
9816 // If url is an object, simulate pre-1.5 signature
9817 if ( typeof url === "object" ) {
9822 // Force options to be an object
9823 options = options || {};
9827 // URL without anti-cache param
9831 responseHeadersString,
9840 // Request state (becomes false upon send and true upon completion)
9843 // To know if global events are to be dispatched
9849 // uncached part of the url
9852 // Create the final options object
9853 s = jQuery.ajaxSetup( {}, options ),
9855 // Callbacks context
9856 callbackContext = s.context || s,
9858 // Context for global events is callbackContext if it is a DOM node or jQuery collection
9859 globalEventContext = s.context &&
9860 ( callbackContext.nodeType || callbackContext.jquery ) ?
9861 jQuery( callbackContext ) :
9865 deferred = jQuery.Deferred(),
9866 completeDeferred = jQuery.Callbacks( "once memory" ),
9868 // Status-dependent callbacks
9869 statusCode = s.statusCode || {},
9871 // Headers (they are sent all at once)
9872 requestHeaders = {},
9873 requestHeadersNames = {},
9875 // Default abort message
9876 strAbort = "canceled",
9882 // Builds headers hashtable if needed
9883 getResponseHeader: function( key ) {
9886 if ( !responseHeaders ) {
9887 responseHeaders = {};
9888 while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
9889 responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
9890 ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
9891 .concat( match[ 2 ] );
9894 match = responseHeaders[ key.toLowerCase() + " " ];
9896 return match == null ? null : match.join( ", " );
9900 getAllResponseHeaders: function() {
9901 return completed ? responseHeadersString : null;
9904 // Caches the header
9905 setRequestHeader: function( name, value ) {
9906 if ( completed == null ) {
9907 name = requestHeadersNames[ name.toLowerCase() ] =
9908 requestHeadersNames[ name.toLowerCase() ] || name;
9909 requestHeaders[ name ] = value;
9914 // Overrides response content-type header
9915 overrideMimeType: function( type ) {
9916 if ( completed == null ) {
9922 // Status-dependent callbacks
9923 statusCode: function( map ) {
9928 // Execute the appropriate callbacks
9929 jqXHR.always( map[ jqXHR.status ] );
9932 // Lazy-add the new callbacks in a way that preserves old ones
9933 for ( code in map ) {
9934 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9941 // Cancel the request
9942 abort: function( statusText ) {
9943 var finalText = statusText || strAbort;
9945 transport.abort( finalText );
9947 done( 0, finalText );
9953 deferred.promise( jqXHR );
9955 // Add protocol if not provided (prefilters might expect it)
9956 // Handle falsy url in the settings object (#10093: consistency with old signature)
9957 // We also use the url parameter if available
9958 s.url = ( ( url || s.url || location.href ) + "" )
9959 .replace( rprotocol, location.protocol + "//" );
9961 // Alias method option to type as per ticket #12004
9962 s.type = options.method || options.type || s.method || s.type;
9964 // Extract dataTypes list
9965 s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
9967 // A cross-domain request is in order when the origin doesn't match the current origin.
9968 if ( s.crossDomain == null ) {
9969 urlAnchor = document.createElement( "a" );
9971 // Support: IE <=8 - 11, Edge 12 - 15
9972 // IE throws exception on accessing the href property if url is malformed,
9973 // e.g. http://example.com:80x/
9975 urlAnchor.href = s.url;
9977 // Support: IE <=8 - 11 only
9978 // Anchor's host property isn't correctly set when s.url is relative
9979 urlAnchor.href = urlAnchor.href;
9980 s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
9981 urlAnchor.protocol + "//" + urlAnchor.host;
9984 // If there is an error parsing the URL, assume it is crossDomain,
9985 // it can be rejected by the transport if it is invalid
9986 s.crossDomain = true;
9990 // Convert data if not already a string
9991 if ( s.data && s.processData && typeof s.data !== "string" ) {
9992 s.data = jQuery.param( s.data, s.traditional );
9996 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9998 // If request was aborted inside a prefilter, stop there
10003 // We can fire global events as of now if asked to
10004 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
10005 fireGlobals = jQuery.event && s.global;
10007 // Watch for a new set of requests
10008 if ( fireGlobals && jQuery.active++ === 0 ) {
10009 jQuery.event.trigger( "ajaxStart" );
10012 // Uppercase the type
10013 s.type = s.type.toUpperCase();
10015 // Determine if request has content
10016 s.hasContent = !rnoContent.test( s.type );
10018 // Save the URL in case we're toying with the If-Modified-Since
10019 // and/or If-None-Match header later on
10020 // Remove hash to simplify url manipulation
10021 cacheURL = s.url.replace( rhash, "" );
10023 // More options handling for requests with no content
10024 if ( !s.hasContent ) {
10026 // Remember the hash so we can put it back
10027 uncached = s.url.slice( cacheURL.length );
10029 // If data is available and should be processed, append data to url
10030 if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
10031 cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
10033 // #9682: remove data so that it's not used in an eventual retry
10037 // Add or update anti-cache param if needed
10038 if ( s.cache === false ) {
10039 cacheURL = cacheURL.replace( rantiCache, "$1" );
10040 uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) +
10044 // Put hash and anti-cache on the URL that will be requested (gh-1732)
10045 s.url = cacheURL + uncached;
10047 // Change '%20' to '+' if this is encoded form body content (gh-2658)
10048 } else if ( s.data && s.processData &&
10049 ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
10050 s.data = s.data.replace( r20, "+" );
10053 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
10054 if ( s.ifModified ) {
10055 if ( jQuery.lastModified[ cacheURL ] ) {
10056 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
10058 if ( jQuery.etag[ cacheURL ] ) {
10059 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
10063 // Set the correct header, if data is being sent
10064 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
10065 jqXHR.setRequestHeader( "Content-Type", s.contentType );
10068 // Set the Accepts header for the server, depending on the dataType
10069 jqXHR.setRequestHeader(
10071 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
10072 s.accepts[ s.dataTypes[ 0 ] ] +
10073 ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
10077 // Check for headers option
10078 for ( i in s.headers ) {
10079 jqXHR.setRequestHeader( i, s.headers[ i ] );
10082 // Allow custom headers/mimetypes and early abort
10083 if ( s.beforeSend &&
10084 ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
10086 // Abort if not done already and return
10087 return jqXHR.abort();
10090 // Aborting is no longer a cancellation
10091 strAbort = "abort";
10093 // Install callbacks on deferreds
10094 completeDeferred.add( s.complete );
10095 jqXHR.done( s.success );
10096 jqXHR.fail( s.error );
10099 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
10101 // If no transport, we auto-abort
10102 if ( !transport ) {
10103 done( -1, "No Transport" );
10105 jqXHR.readyState = 1;
10107 // Send global event
10108 if ( fireGlobals ) {
10109 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
10112 // If request was aborted inside ajaxSend, stop there
10118 if ( s.async && s.timeout > 0 ) {
10119 timeoutTimer = window.setTimeout( function() {
10120 jqXHR.abort( "timeout" );
10126 transport.send( requestHeaders, done );
10129 // Rethrow post-completion exceptions
10134 // Propagate others as results
10139 // Callback for when everything is done
10140 function done( status, nativeStatusText, responses, headers ) {
10141 var isSuccess, success, error, response, modified,
10142 statusText = nativeStatusText;
10144 // Ignore repeat invocations
10151 // Clear timeout if it exists
10152 if ( timeoutTimer ) {
10153 window.clearTimeout( timeoutTimer );
10156 // Dereference transport for early garbage collection
10157 // (no matter how long the jqXHR object will be used)
10158 transport = undefined;
10160 // Cache response headers
10161 responseHeadersString = headers || "";
10164 jqXHR.readyState = status > 0 ? 4 : 0;
10166 // Determine if successful
10167 isSuccess = status >= 200 && status < 300 || status === 304;
10169 // Get response data
10171 response = ajaxHandleResponses( s, jqXHR, responses );
10174 // Use a noop converter for missing script
10175 if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) {
10176 s.converters[ "text script" ] = function() {};
10179 // Convert no matter what (that way responseXXX fields are always set)
10180 response = ajaxConvert( s, response, jqXHR, isSuccess );
10182 // If successful, handle type chaining
10185 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
10186 if ( s.ifModified ) {
10187 modified = jqXHR.getResponseHeader( "Last-Modified" );
10189 jQuery.lastModified[ cacheURL ] = modified;
10191 modified = jqXHR.getResponseHeader( "etag" );
10193 jQuery.etag[ cacheURL ] = modified;
10198 if ( status === 204 || s.type === "HEAD" ) {
10199 statusText = "nocontent";
10202 } else if ( status === 304 ) {
10203 statusText = "notmodified";
10205 // If we have data, let's convert it
10207 statusText = response.state;
10208 success = response.data;
10209 error = response.error;
10210 isSuccess = !error;
10214 // Extract error from statusText and normalize for non-aborts
10215 error = statusText;
10216 if ( status || !statusText ) {
10217 statusText = "error";
10218 if ( status < 0 ) {
10224 // Set data for the fake xhr object
10225 jqXHR.status = status;
10226 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
10230 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
10232 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
10235 // Status-dependent callbacks
10236 jqXHR.statusCode( statusCode );
10237 statusCode = undefined;
10239 if ( fireGlobals ) {
10240 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
10241 [ jqXHR, s, isSuccess ? success : error ] );
10245 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
10247 if ( fireGlobals ) {
10248 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
10250 // Handle the global AJAX counter
10251 if ( !( --jQuery.active ) ) {
10252 jQuery.event.trigger( "ajaxStop" );
10260 getJSON: function( url, data, callback ) {
10261 return jQuery.get( url, data, callback, "json" );
10264 getScript: function( url, callback ) {
10265 return jQuery.get( url, undefined, callback, "script" );
10269 jQuery.each( [ "get", "post" ], function( _i, method ) {
10270 jQuery[ method ] = function( url, data, callback, type ) {
10272 // Shift arguments if data argument was omitted
10273 if ( isFunction( data ) ) {
10274 type = type || callback;
10279 // The url can be an options object (which then must have .url)
10280 return jQuery.ajax( jQuery.extend( {
10286 }, jQuery.isPlainObject( url ) && url ) );
10290 jQuery.ajaxPrefilter( function( s ) {
10292 for ( i in s.headers ) {
10293 if ( i.toLowerCase() === "content-type" ) {
10294 s.contentType = s.headers[ i ] || "";
10300 jQuery._evalUrl = function( url, options, doc ) {
10301 return jQuery.ajax( {
10304 // Make this explicit, since user can override this through ajaxSetup (#11264)
10306 dataType: "script",
10311 // Only evaluate the response if it is successful (gh-4126)
10312 // dataFilter is not invoked for failure responses, so using it instead
10313 // of the default converter is kludgy but it works.
10315 "text script": function() {}
10317 dataFilter: function( response ) {
10318 jQuery.globalEval( response, options, doc );
10324 jQuery.fn.extend( {
10325 wrapAll: function( html ) {
10329 if ( isFunction( html ) ) {
10330 html = html.call( this[ 0 ] );
10333 // The elements to wrap the target around
10334 wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
10336 if ( this[ 0 ].parentNode ) {
10337 wrap.insertBefore( this[ 0 ] );
10340 wrap.map( function() {
10343 while ( elem.firstElementChild ) {
10344 elem = elem.firstElementChild;
10348 } ).append( this );
10354 wrapInner: function( html ) {
10355 if ( isFunction( html ) ) {
10356 return this.each( function( i ) {
10357 jQuery( this ).wrapInner( html.call( this, i ) );
10361 return this.each( function() {
10362 var self = jQuery( this ),
10363 contents = self.contents();
10365 if ( contents.length ) {
10366 contents.wrapAll( html );
10369 self.append( html );
10374 wrap: function( html ) {
10375 var htmlIsFunction = isFunction( html );
10377 return this.each( function( i ) {
10378 jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );
10382 unwrap: function( selector ) {
10383 this.parent( selector ).not( "body" ).each( function() {
10384 jQuery( this ).replaceWith( this.childNodes );
10391 jQuery.expr.pseudos.hidden = function( elem ) {
10392 return !jQuery.expr.pseudos.visible( elem );
10394 jQuery.expr.pseudos.visible = function( elem ) {
10395 return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
10401 jQuery.ajaxSettings.xhr = function() {
10403 return new window.XMLHttpRequest();
10407 var xhrSuccessStatus = {
10409 // File protocol always yields status code 0, assume 200
10412 // Support: IE <=9 only
10413 // #1450: sometimes IE returns 1223 when it should be 204
10416 xhrSupported = jQuery.ajaxSettings.xhr();
10418 support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
10419 support.ajax = xhrSupported = !!xhrSupported;
10421 jQuery.ajaxTransport( function( options ) {
10422 var callback, errorCallback;
10424 // Cross domain only allowed if supported through XMLHttpRequest
10425 if ( support.cors || xhrSupported && !options.crossDomain ) {
10427 send: function( headers, complete ) {
10429 xhr = options.xhr();
10439 // Apply custom fields if provided
10440 if ( options.xhrFields ) {
10441 for ( i in options.xhrFields ) {
10442 xhr[ i ] = options.xhrFields[ i ];
10446 // Override mime type if needed
10447 if ( options.mimeType && xhr.overrideMimeType ) {
10448 xhr.overrideMimeType( options.mimeType );
10451 // X-Requested-With header
10452 // For cross-domain requests, seeing as conditions for a preflight are
10453 // akin to a jigsaw puzzle, we simply never set it to be sure.
10454 // (it can always be set on a per-request basis or even using ajaxSetup)
10455 // For same-domain requests, won't change header if already provided.
10456 if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
10457 headers[ "X-Requested-With" ] = "XMLHttpRequest";
10461 for ( i in headers ) {
10462 xhr.setRequestHeader( i, headers[ i ] );
10466 callback = function( type ) {
10467 return function() {
10469 callback = errorCallback = xhr.onload =
10470 xhr.onerror = xhr.onabort = xhr.ontimeout =
10471 xhr.onreadystatechange = null;
10473 if ( type === "abort" ) {
10475 } else if ( type === "error" ) {
10477 // Support: IE <=9 only
10478 // On a manual native abort, IE9 throws
10479 // errors on any property access that is not readyState
10480 if ( typeof xhr.status !== "number" ) {
10481 complete( 0, "error" );
10485 // File: protocol always yields status 0; see #8605, #14207
10492 xhrSuccessStatus[ xhr.status ] || xhr.status,
10495 // Support: IE <=9 only
10496 // IE9 has no XHR2 but throws on binary (trac-11426)
10497 // For XHR2 non-text, let the caller handle it (gh-2498)
10498 ( xhr.responseType || "text" ) !== "text" ||
10499 typeof xhr.responseText !== "string" ?
10500 { binary: xhr.response } :
10501 { text: xhr.responseText },
10502 xhr.getAllResponseHeaders()
10509 // Listen to events
10510 xhr.onload = callback();
10511 errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" );
10513 // Support: IE 9 only
10514 // Use onreadystatechange to replace onabort
10515 // to handle uncaught aborts
10516 if ( xhr.onabort !== undefined ) {
10517 xhr.onabort = errorCallback;
10519 xhr.onreadystatechange = function() {
10521 // Check readyState before timeout as it changes
10522 if ( xhr.readyState === 4 ) {
10524 // Allow onerror to be called first,
10525 // but that will not handle a native abort
10526 // Also, save errorCallback to a variable
10527 // as xhr.onerror cannot be accessed
10528 window.setTimeout( function() {
10537 // Create the abort callback
10538 callback = callback( "abort" );
10542 // Do send the request (this may raise an exception)
10543 xhr.send( options.hasContent && options.data || null );
10546 // #14683: Only rethrow if this hasn't been notified as an error yet
10553 abort: function() {
10565 // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
10566 jQuery.ajaxPrefilter( function( s ) {
10567 if ( s.crossDomain ) {
10568 s.contents.script = false;
10572 // Install script dataType
10573 jQuery.ajaxSetup( {
10575 script: "text/javascript, application/javascript, " +
10576 "application/ecmascript, application/x-ecmascript"
10579 script: /\b(?:java|ecma)script\b/
10582 "text script": function( text ) {
10583 jQuery.globalEval( text );
10589 // Handle cache's special case and crossDomain
10590 jQuery.ajaxPrefilter( "script", function( s ) {
10591 if ( s.cache === undefined ) {
10594 if ( s.crossDomain ) {
10599 // Bind script tag hack transport
10600 jQuery.ajaxTransport( "script", function( s ) {
10602 // This transport only deals with cross domain or forced-by-attrs requests
10603 if ( s.crossDomain || s.scriptAttrs ) {
10604 var script, callback;
10606 send: function( _, complete ) {
10607 script = jQuery( "<script>" )
10608 .attr( s.scriptAttrs || {} )
10609 .prop( { charset: s.scriptCharset, src: s.url } )
10610 .on( "load error", callback = function( evt ) {
10614 complete( evt.type === "error" ? 404 : 200, evt.type );
10618 // Use native DOM manipulation to avoid our domManip AJAX trickery
10619 document.head.appendChild( script[ 0 ] );
10621 abort: function() {
10633 var oldCallbacks = [],
10634 rjsonp = /(=)\?(?=&|$)|\?\?/;
10636 // Default jsonp settings
10637 jQuery.ajaxSetup( {
10639 jsonpCallback: function() {
10640 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) );
10641 this[ callback ] = true;
10646 // Detect, normalize options and install callbacks for jsonp requests
10647 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
10649 var callbackName, overwritten, responseContainer,
10650 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
10652 typeof s.data === "string" &&
10653 ( s.contentType || "" )
10654 .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
10655 rjsonp.test( s.data ) && "data"
10658 // Handle iff the expected data type is "jsonp" or we have a parameter to set
10659 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
10661 // Get callback name, remembering preexisting value associated with it
10662 callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
10663 s.jsonpCallback() :
10666 // Insert callback into url or form data
10668 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
10669 } else if ( s.jsonp !== false ) {
10670 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
10673 // Use data converter to retrieve json after script execution
10674 s.converters[ "script json" ] = function() {
10675 if ( !responseContainer ) {
10676 jQuery.error( callbackName + " was not called" );
10678 return responseContainer[ 0 ];
10681 // Force json dataType
10682 s.dataTypes[ 0 ] = "json";
10684 // Install callback
10685 overwritten = window[ callbackName ];
10686 window[ callbackName ] = function() {
10687 responseContainer = arguments;
10690 // Clean-up function (fires after converters)
10691 jqXHR.always( function() {
10693 // If previous value didn't exist - remove it
10694 if ( overwritten === undefined ) {
10695 jQuery( window ).removeProp( callbackName );
10697 // Otherwise restore preexisting value
10699 window[ callbackName ] = overwritten;
10702 // Save back as free
10703 if ( s[ callbackName ] ) {
10705 // Make sure that re-using the options doesn't screw things around
10706 s.jsonpCallback = originalSettings.jsonpCallback;
10708 // Save the callback name for future use
10709 oldCallbacks.push( callbackName );
10712 // Call if it was a function and we have a response
10713 if ( responseContainer && isFunction( overwritten ) ) {
10714 overwritten( responseContainer[ 0 ] );
10717 responseContainer = overwritten = undefined;
10720 // Delegate to script
10728 // Support: Safari 8 only
10729 // In Safari 8 documents created via document.implementation.createHTMLDocument
10730 // collapse sibling forms: the second one becomes a child of the first one.
10731 // Because of that, this security measure has to be disabled in Safari 8.
10732 // https://bugs.webkit.org/show_bug.cgi?id=137337
10733 support.createHTMLDocument = ( function() {
10734 var body = document.implementation.createHTMLDocument( "" ).body;
10735 body.innerHTML = "<form></form><form></form>";
10736 return body.childNodes.length === 2;
10740 // Argument "data" should be string of html
10741 // context (optional): If specified, the fragment will be created in this context,
10742 // defaults to document
10743 // keepScripts (optional): If true, will include scripts passed in the html string
10744 jQuery.parseHTML = function( data, context, keepScripts ) {
10745 if ( typeof data !== "string" ) {
10748 if ( typeof context === "boolean" ) {
10749 keepScripts = context;
10753 var base, parsed, scripts;
10757 // Stop scripts or inline event handlers from being executed immediately
10758 // by using document.implementation
10759 if ( support.createHTMLDocument ) {
10760 context = document.implementation.createHTMLDocument( "" );
10762 // Set the base href for the created document
10763 // so any parsed elements with URLs
10764 // are based on the document's URL (gh-2965)
10765 base = context.createElement( "base" );
10766 base.href = document.location.href;
10767 context.head.appendChild( base );
10769 context = document;
10773 parsed = rsingleTag.exec( data );
10774 scripts = !keepScripts && [];
10778 return [ context.createElement( parsed[ 1 ] ) ];
10781 parsed = buildFragment( [ data ], context, scripts );
10783 if ( scripts && scripts.length ) {
10784 jQuery( scripts ).remove();
10787 return jQuery.merge( [], parsed.childNodes );
10792 * Load a url into a page
10794 jQuery.fn.load = function( url, params, callback ) {
10795 var selector, type, response,
10797 off = url.indexOf( " " );
10800 selector = stripAndCollapse( url.slice( off ) );
10801 url = url.slice( 0, off );
10804 // If it's a function
10805 if ( isFunction( params ) ) {
10807 // We assume that it's the callback
10809 params = undefined;
10811 // Otherwise, build a param string
10812 } else if ( params && typeof params === "object" ) {
10816 // If we have elements to modify, make the request
10817 if ( self.length > 0 ) {
10821 // If "type" variable is undefined, then "GET" method will be used.
10822 // Make value of this field explicit since
10823 // user can override it through ajaxSetup method
10824 type: type || "GET",
10827 } ).done( function( responseText ) {
10829 // Save response for use in complete callback
10830 response = arguments;
10832 self.html( selector ?
10834 // If a selector was specified, locate the right elements in a dummy div
10835 // Exclude scripts to avoid IE 'Permission Denied' errors
10836 jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
10838 // Otherwise use the full result
10841 // If the request succeeds, this function gets "data", "status", "jqXHR"
10842 // but they are ignored because response was set above.
10843 // If it fails, this function gets "jqXHR", "status", "error"
10844 } ).always( callback && function( jqXHR, status ) {
10845 self.each( function() {
10846 callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
10857 jQuery.expr.pseudos.animated = function( elem ) {
10858 return jQuery.grep( jQuery.timers, function( fn ) {
10859 return elem === fn.elem;
10867 setOffset: function( elem, options, i ) {
10868 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
10869 position = jQuery.css( elem, "position" ),
10870 curElem = jQuery( elem ),
10873 // Set position first, in-case top/left are set even on static elem
10874 if ( position === "static" ) {
10875 elem.style.position = "relative";
10878 curOffset = curElem.offset();
10879 curCSSTop = jQuery.css( elem, "top" );
10880 curCSSLeft = jQuery.css( elem, "left" );
10881 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
10882 ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
10884 // Need to be able to calculate position if either
10885 // top or left is auto and position is either absolute or fixed
10886 if ( calculatePosition ) {
10887 curPosition = curElem.position();
10888 curTop = curPosition.top;
10889 curLeft = curPosition.left;
10892 curTop = parseFloat( curCSSTop ) || 0;
10893 curLeft = parseFloat( curCSSLeft ) || 0;
10896 if ( isFunction( options ) ) {
10898 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
10899 options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
10902 if ( options.top != null ) {
10903 props.top = ( options.top - curOffset.top ) + curTop;
10905 if ( options.left != null ) {
10906 props.left = ( options.left - curOffset.left ) + curLeft;
10909 if ( "using" in options ) {
10910 options.using.call( elem, props );
10913 if ( typeof props.top === "number" ) {
10916 if ( typeof props.left === "number" ) {
10917 props.left += "px";
10919 curElem.css( props );
10924 jQuery.fn.extend( {
10926 // offset() relates an element's border box to the document origin
10927 offset: function( options ) {
10929 // Preserve chaining for setter
10930 if ( arguments.length ) {
10931 return options === undefined ?
10933 this.each( function( i ) {
10934 jQuery.offset.setOffset( this, options, i );
10945 // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
10946 // Support: IE <=11 only
10947 // Running getBoundingClientRect on a
10948 // disconnected node in IE throws an error
10949 if ( !elem.getClientRects().length ) {
10950 return { top: 0, left: 0 };
10953 // Get document-relative position by adding viewport scroll to viewport-relative gBCR
10954 rect = elem.getBoundingClientRect();
10955 win = elem.ownerDocument.defaultView;
10957 top: rect.top + win.pageYOffset,
10958 left: rect.left + win.pageXOffset
10962 // position() relates an element's margin box to its offset parent's padding box
10963 // This corresponds to the behavior of CSS absolute positioning
10964 position: function() {
10965 if ( !this[ 0 ] ) {
10969 var offsetParent, offset, doc,
10971 parentOffset = { top: 0, left: 0 };
10973 // position:fixed elements are offset from the viewport, which itself always has zero offset
10974 if ( jQuery.css( elem, "position" ) === "fixed" ) {
10976 // Assume position:fixed implies availability of getBoundingClientRect
10977 offset = elem.getBoundingClientRect();
10980 offset = this.offset();
10982 // Account for the *real* offset parent, which can be the document or its root element
10983 // when a statically positioned element is identified
10984 doc = elem.ownerDocument;
10985 offsetParent = elem.offsetParent || doc.documentElement;
10986 while ( offsetParent &&
10987 ( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
10988 jQuery.css( offsetParent, "position" ) === "static" ) {
10990 offsetParent = offsetParent.parentNode;
10992 if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {
10994 // Incorporate borders into its offset, since they are outside its content origin
10995 parentOffset = jQuery( offsetParent ).offset();
10996 parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
10997 parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
11001 // Subtract parent offsets and element margins
11003 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
11004 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
11008 // This method will return documentElement in the following cases:
11009 // 1) For the element inside the iframe without offsetParent, this method will return
11010 // documentElement of the parent window
11011 // 2) For the hidden or detached element
11012 // 3) For body or html element, i.e. in case of the html node - it will return itself
11014 // but those exceptions were never presented as a real life use-cases
11015 // and might be considered as more preferable results.
11017 // This logic, however, is not guaranteed and can change at any point in the future
11018 offsetParent: function() {
11019 return this.map( function() {
11020 var offsetParent = this.offsetParent;
11022 while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
11023 offsetParent = offsetParent.offsetParent;
11026 return offsetParent || documentElement;
11031 // Create scrollLeft and scrollTop methods
11032 jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
11033 var top = "pageYOffset" === prop;
11035 jQuery.fn[ method ] = function( val ) {
11036 return access( this, function( elem, method, val ) {
11038 // Coalesce documents and windows
11040 if ( isWindow( elem ) ) {
11042 } else if ( elem.nodeType === 9 ) {
11043 win = elem.defaultView;
11046 if ( val === undefined ) {
11047 return win ? win[ prop ] : elem[ method ];
11052 !top ? val : win.pageXOffset,
11053 top ? val : win.pageYOffset
11057 elem[ method ] = val;
11059 }, method, val, arguments.length );
11063 // Support: Safari <=7 - 9.1, Chrome <=37 - 49
11064 // Add the top/left cssHooks using jQuery.fn.position
11065 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
11066 // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
11067 // getComputedStyle returns percent when specified for top/left/bottom/right;
11068 // rather than make the css module depend on the offset module, just check for it here
11069 jQuery.each( [ "top", "left" ], function( _i, prop ) {
11070 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
11071 function( elem, computed ) {
11073 computed = curCSS( elem, prop );
11075 // If curCSS returns percentage, fallback to offset
11076 return rnumnonpx.test( computed ) ?
11077 jQuery( elem ).position()[ prop ] + "px" :
11085 // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
11086 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
11087 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
11088 function( defaultExtra, funcName ) {
11090 // Margin is only for outerHeight, outerWidth
11091 jQuery.fn[ funcName ] = function( margin, value ) {
11092 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
11093 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
11095 return access( this, function( elem, type, value ) {
11098 if ( isWindow( elem ) ) {
11100 // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
11101 return funcName.indexOf( "outer" ) === 0 ?
11102 elem[ "inner" + name ] :
11103 elem.document.documentElement[ "client" + name ];
11106 // Get document width or height
11107 if ( elem.nodeType === 9 ) {
11108 doc = elem.documentElement;
11110 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
11111 // whichever is greatest
11113 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
11114 elem.body[ "offset" + name ], doc[ "offset" + name ],
11115 doc[ "client" + name ]
11119 return value === undefined ?
11121 // Get width or height on the element, requesting but not forcing parseFloat
11122 jQuery.css( elem, type, extra ) :
11124 // Set width or height on the element
11125 jQuery.style( elem, type, value, extra );
11126 }, type, chainable ? margin : undefined, chainable );
11139 ], function( _i, type ) {
11140 jQuery.fn[ type ] = function( fn ) {
11141 return this.on( type, fn );
11148 jQuery.fn.extend( {
11150 bind: function( types, data, fn ) {
11151 return this.on( types, null, data, fn );
11153 unbind: function( types, fn ) {
11154 return this.off( types, null, fn );
11157 delegate: function( selector, types, data, fn ) {
11158 return this.on( types, selector, data, fn );
11160 undelegate: function( selector, types, fn ) {
11162 // ( namespace ) or ( selector, types [, fn] )
11163 return arguments.length === 1 ?
11164 this.off( selector, "**" ) :
11165 this.off( types, selector || "**", fn );
11168 hover: function( fnOver, fnOut ) {
11169 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
11173 jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
11174 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
11175 "change select submit keydown keypress keyup contextmenu" ).split( " " ),
11176 function( _i, name ) {
11178 // Handle event binding
11179 jQuery.fn[ name ] = function( data, fn ) {
11180 return arguments.length > 0 ?
11181 this.on( name, null, data, fn ) :
11182 this.trigger( name );
11189 // Support: Android <=4.0 only
11190 // Make sure we trim BOM and NBSP
11191 var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
11193 // Bind a function to a context, optionally partially applying any
11195 // jQuery.proxy is deprecated to promote standards (specifically Function#bind)
11196 // However, it is not slated for removal any time soon
11197 jQuery.proxy = function( fn, context ) {
11198 var tmp, args, proxy;
11200 if ( typeof context === "string" ) {
11201 tmp = fn[ context ];
11206 // Quick check to determine if target is callable, in the spec
11207 // this throws a TypeError, but we will just return undefined.
11208 if ( !isFunction( fn ) ) {
11213 args = slice.call( arguments, 2 );
11214 proxy = function() {
11215 return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
11218 // Set the guid of unique handler to the same of original handler, so it can be removed
11219 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
11224 jQuery.holdReady = function( hold ) {
11226 jQuery.readyWait++;
11228 jQuery.ready( true );
11231 jQuery.isArray = Array.isArray;
11232 jQuery.parseJSON = JSON.parse;
11233 jQuery.nodeName = nodeName;
11234 jQuery.isFunction = isFunction;
11235 jQuery.isWindow = isWindow;
11236 jQuery.camelCase = camelCase;
11237 jQuery.type = toType;
11239 jQuery.now = Date.now;
11241 jQuery.isNumeric = function( obj ) {
11243 // As of jQuery 3.0, isNumeric is limited to
11244 // strings and numbers (primitives or objects)
11245 // that can be coerced to finite numbers (gh-2662)
11246 var type = jQuery.type( obj );
11247 return ( type === "number" || type === "string" ) &&
11249 // parseFloat NaNs numeric-cast false positives ("")
11250 // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
11251 // subtraction forces infinities to NaN
11252 !isNaN( obj - parseFloat( obj ) );
11255 jQuery.trim = function( text ) {
11256 return text == null ?
11258 ( text + "" ).replace( rtrim, "" );
11266 // Map over jQuery in case of overwrite
11267 _jQuery = window.jQuery,
11269 // Map over the $ in case of overwrite
11272 jQuery.noConflict = function( deep ) {
11273 if ( window.$ === jQuery ) {
11277 if ( deep && window.jQuery === jQuery ) {
11278 window.jQuery = _jQuery;
11284 // Expose jQuery and $ identifiers, even in AMD
11285 // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
11286 // and CommonJS for browser emulators (#13566)
11287 if ( typeof noGlobal === "undefined" ) {
11288 window.jQuery = window.$ = jQuery;
11298 var jquery$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), jquery, {
11303 * Bootstrap v4.6.0 (https://getbootstrap.com/)
11304 * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
11305 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
11308 createCommonjsModule(function (module, exports) {
11309 (function (global, factory) {
11310 factory(exports, jquery) ;
11311 }(commonjsGlobal, (function (exports, $) {
11312 function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11314 var $__default = /*#__PURE__*/_interopDefaultLegacy($);
11316 function _defineProperties(target, props) {
11317 for (var i = 0; i < props.length; i++) {
11318 var descriptor = props[i];
11319 descriptor.enumerable = descriptor.enumerable || false;
11320 descriptor.configurable = true;
11321 if ("value" in descriptor) descriptor.writable = true;
11322 Object.defineProperty(target, descriptor.key, descriptor);
11326 function _createClass(Constructor, protoProps, staticProps) {
11327 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
11328 if (staticProps) _defineProperties(Constructor, staticProps);
11329 return Constructor;
11332 function _extends() {
11333 _extends = Object.assign || function (target) {
11334 for (var i = 1; i < arguments.length; i++) {
11335 var source = arguments[i];
11337 for (var key in source) {
11338 if (Object.prototype.hasOwnProperty.call(source, key)) {
11339 target[key] = source[key];
11347 return _extends.apply(this, arguments);
11350 function _inheritsLoose(subClass, superClass) {
11351 subClass.prototype = Object.create(superClass.prototype);
11352 subClass.prototype.constructor = subClass;
11353 subClass.__proto__ = superClass;
11357 * --------------------------------------------------------------------------
11358 * Bootstrap (v4.6.0): util.js
11359 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
11360 * --------------------------------------------------------------------------
11363 * ------------------------------------------------------------------------
11364 * Private TransitionEnd Helpers
11365 * ------------------------------------------------------------------------
11368 var TRANSITION_END = 'transitionend';
11369 var MAX_UID = 1000000;
11370 var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
11372 function toType(obj) {
11373 if (obj === null || typeof obj === 'undefined') {
11377 return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
11380 function getSpecialTransitionEndEvent() {
11382 bindType: TRANSITION_END,
11383 delegateType: TRANSITION_END,
11384 handle: function handle(event) {
11385 if ($__default['default'](event.target).is(this)) {
11386 return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
11394 function transitionEndEmulator(duration) {
11397 var called = false;
11398 $__default['default'](this).one(Util.TRANSITION_END, function () {
11401 setTimeout(function () {
11403 Util.triggerTransitionEnd(_this);
11409 function setTransitionEndSupport() {
11410 $__default['default'].fn.emulateTransitionEnd = transitionEndEmulator;
11411 $__default['default'].event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
11414 * --------------------------------------------------------------------------
11416 * --------------------------------------------------------------------------
11421 TRANSITION_END: 'bsTransitionEnd',
11422 getUID: function getUID(prefix) {
11424 prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
11425 } while (document.getElementById(prefix));
11429 getSelectorFromElement: function getSelectorFromElement(element) {
11430 var selector = element.getAttribute('data-target');
11432 if (!selector || selector === '#') {
11433 var hrefAttr = element.getAttribute('href');
11434 selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : '';
11438 return document.querySelector(selector) ? selector : null;
11443 getTransitionDurationFromElement: function getTransitionDurationFromElement(element) {
11446 } // Get transition-duration of the element
11449 var transitionDuration = $__default['default'](element).css('transition-duration');
11450 var transitionDelay = $__default['default'](element).css('transition-delay');
11451 var floatTransitionDuration = parseFloat(transitionDuration);
11452 var floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found
11454 if (!floatTransitionDuration && !floatTransitionDelay) {
11456 } // If multiple durations are defined, take the first
11459 transitionDuration = transitionDuration.split(',')[0];
11460 transitionDelay = transitionDelay.split(',')[0];
11461 return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
11463 reflow: function reflow(element) {
11464 return element.offsetHeight;
11466 triggerTransitionEnd: function triggerTransitionEnd(element) {
11467 $__default['default'](element).trigger(TRANSITION_END);
11469 supportsTransitionEnd: function supportsTransitionEnd() {
11470 return Boolean(TRANSITION_END);
11472 isElement: function isElement(obj) {
11473 return (obj[0] || obj).nodeType;
11475 typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
11476 for (var property in configTypes) {
11477 if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
11478 var expectedTypes = configTypes[property];
11479 var value = config[property];
11480 var valueType = value && Util.isElement(value) ? 'element' : toType(value);
11482 if (!new RegExp(expectedTypes).test(valueType)) {
11483 throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\"."));
11488 findShadowRoot: function findShadowRoot(element) {
11489 if (!document.documentElement.attachShadow) {
11491 } // Can find the shadow root otherwise it'll return the document
11494 if (typeof element.getRootNode === 'function') {
11495 var root = element.getRootNode();
11496 return root instanceof ShadowRoot ? root : null;
11499 if (element instanceof ShadowRoot) {
11501 } // when we don't find a shadow root
11504 if (!element.parentNode) {
11508 return Util.findShadowRoot(element.parentNode);
11510 jQueryDetection: function jQueryDetection() {
11511 if (typeof $__default['default'] === 'undefined') {
11512 throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.');
11515 var version = $__default['default'].fn.jquery.split(' ')[0].split('.');
11522 if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {
11523 throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');
11527 Util.jQueryDetection();
11528 setTransitionEndSupport();
11531 * ------------------------------------------------------------------------
11533 * ------------------------------------------------------------------------
11536 var NAME = 'alert';
11537 var VERSION = '4.6.0';
11538 var DATA_KEY = 'bs.alert';
11539 var EVENT_KEY = "." + DATA_KEY;
11540 var DATA_API_KEY = '.data-api';
11541 var JQUERY_NO_CONFLICT = $__default['default'].fn[NAME];
11542 var SELECTOR_DISMISS = '[data-dismiss="alert"]';
11543 var EVENT_CLOSE = "close" + EVENT_KEY;
11544 var EVENT_CLOSED = "closed" + EVENT_KEY;
11545 var EVENT_CLICK_DATA_API = "click" + EVENT_KEY + DATA_API_KEY;
11546 var CLASS_NAME_ALERT = 'alert';
11547 var CLASS_NAME_FADE = 'fade';
11548 var CLASS_NAME_SHOW = 'show';
11550 * ------------------------------------------------------------------------
11552 * ------------------------------------------------------------------------
11555 var Alert = /*#__PURE__*/function () {
11556 function Alert(element) {
11557 this._element = element;
11561 var _proto = Alert.prototype;
11564 _proto.close = function close(element) {
11565 var rootElement = this._element;
11568 rootElement = this._getRootElement(element);
11571 var customEvent = this._triggerCloseEvent(rootElement);
11573 if (customEvent.isDefaultPrevented()) {
11577 this._removeElement(rootElement);
11580 _proto.dispose = function dispose() {
11581 $__default['default'].removeData(this._element, DATA_KEY);
11582 this._element = null;
11586 _proto._getRootElement = function _getRootElement(element) {
11587 var selector = Util.getSelectorFromElement(element);
11588 var parent = false;
11591 parent = document.querySelector(selector);
11595 parent = $__default['default'](element).closest("." + CLASS_NAME_ALERT)[0];
11601 _proto._triggerCloseEvent = function _triggerCloseEvent(element) {
11602 var closeEvent = $__default['default'].Event(EVENT_CLOSE);
11603 $__default['default'](element).trigger(closeEvent);
11607 _proto._removeElement = function _removeElement(element) {
11610 $__default['default'](element).removeClass(CLASS_NAME_SHOW);
11612 if (!$__default['default'](element).hasClass(CLASS_NAME_FADE)) {
11613 this._destroyElement(element);
11618 var transitionDuration = Util.getTransitionDurationFromElement(element);
11619 $__default['default'](element).one(Util.TRANSITION_END, function (event) {
11620 return _this._destroyElement(element, event);
11621 }).emulateTransitionEnd(transitionDuration);
11624 _proto._destroyElement = function _destroyElement(element) {
11625 $__default['default'](element).detach().trigger(EVENT_CLOSED).remove();
11629 Alert._jQueryInterface = function _jQueryInterface(config) {
11630 return this.each(function () {
11631 var $element = $__default['default'](this);
11632 var data = $element.data(DATA_KEY);
11635 data = new Alert(this);
11636 $element.data(DATA_KEY, data);
11639 if (config === 'close') {
11640 data[config](this);
11645 Alert._handleDismiss = function _handleDismiss(alertInstance) {
11646 return function (event) {
11648 event.preventDefault();
11651 alertInstance.close(this);
11655 _createClass(Alert, null, [{
11657 get: function get() {
11665 * ------------------------------------------------------------------------
11666 * Data Api implementation
11667 * ------------------------------------------------------------------------
11671 $__default['default'](document).on(EVENT_CLICK_DATA_API, SELECTOR_DISMISS, Alert._handleDismiss(new Alert()));
11673 * ------------------------------------------------------------------------
11675 * ------------------------------------------------------------------------
11678 $__default['default'].fn[NAME] = Alert._jQueryInterface;
11679 $__default['default'].fn[NAME].Constructor = Alert;
11681 $__default['default'].fn[NAME].noConflict = function () {
11682 $__default['default'].fn[NAME] = JQUERY_NO_CONFLICT;
11683 return Alert._jQueryInterface;
11687 * ------------------------------------------------------------------------
11689 * ------------------------------------------------------------------------
11692 var NAME$1 = 'button';
11693 var VERSION$1 = '4.6.0';
11694 var DATA_KEY$1 = 'bs.button';
11695 var EVENT_KEY$1 = "." + DATA_KEY$1;
11696 var DATA_API_KEY$1 = '.data-api';
11697 var JQUERY_NO_CONFLICT$1 = $__default['default'].fn[NAME$1];
11698 var CLASS_NAME_ACTIVE = 'active';
11699 var CLASS_NAME_BUTTON = 'btn';
11700 var CLASS_NAME_FOCUS = 'focus';
11701 var SELECTOR_DATA_TOGGLE_CARROT = '[data-toggle^="button"]';
11702 var SELECTOR_DATA_TOGGLES = '[data-toggle="buttons"]';
11703 var SELECTOR_DATA_TOGGLE = '[data-toggle="button"]';
11704 var SELECTOR_DATA_TOGGLES_BUTTONS = '[data-toggle="buttons"] .btn';
11705 var SELECTOR_INPUT = 'input:not([type="hidden"])';
11706 var SELECTOR_ACTIVE = '.active';
11707 var SELECTOR_BUTTON = '.btn';
11708 var EVENT_CLICK_DATA_API$1 = "click" + EVENT_KEY$1 + DATA_API_KEY$1;
11709 var EVENT_FOCUS_BLUR_DATA_API = "focus" + EVENT_KEY$1 + DATA_API_KEY$1 + " " + ("blur" + EVENT_KEY$1 + DATA_API_KEY$1);
11710 var EVENT_LOAD_DATA_API = "load" + EVENT_KEY$1 + DATA_API_KEY$1;
11712 * ------------------------------------------------------------------------
11714 * ------------------------------------------------------------------------
11717 var Button = /*#__PURE__*/function () {
11718 function Button(element) {
11719 this._element = element;
11720 this.shouldAvoidTriggerChange = false;
11724 var _proto = Button.prototype;
11727 _proto.toggle = function toggle() {
11728 var triggerChangeEvent = true;
11729 var addAriaPressed = true;
11730 var rootElement = $__default['default'](this._element).closest(SELECTOR_DATA_TOGGLES)[0];
11733 var input = this._element.querySelector(SELECTOR_INPUT);
11736 if (input.type === 'radio') {
11737 if (input.checked && this._element.classList.contains(CLASS_NAME_ACTIVE)) {
11738 triggerChangeEvent = false;
11740 var activeElement = rootElement.querySelector(SELECTOR_ACTIVE);
11742 if (activeElement) {
11743 $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE);
11748 if (triggerChangeEvent) {
11749 // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input
11750 if (input.type === 'checkbox' || input.type === 'radio') {
11751 input.checked = !this._element.classList.contains(CLASS_NAME_ACTIVE);
11754 if (!this.shouldAvoidTriggerChange) {
11755 $__default['default'](input).trigger('change');
11760 addAriaPressed = false;
11764 if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) {
11765 if (addAriaPressed) {
11766 this._element.setAttribute('aria-pressed', !this._element.classList.contains(CLASS_NAME_ACTIVE));
11769 if (triggerChangeEvent) {
11770 $__default['default'](this._element).toggleClass(CLASS_NAME_ACTIVE);
11775 _proto.dispose = function dispose() {
11776 $__default['default'].removeData(this._element, DATA_KEY$1);
11777 this._element = null;
11781 Button._jQueryInterface = function _jQueryInterface(config, avoidTriggerChange) {
11782 return this.each(function () {
11783 var $element = $__default['default'](this);
11784 var data = $element.data(DATA_KEY$1);
11787 data = new Button(this);
11788 $element.data(DATA_KEY$1, data);
11791 data.shouldAvoidTriggerChange = avoidTriggerChange;
11793 if (config === 'toggle') {
11799 _createClass(Button, null, [{
11801 get: function get() {
11809 * ------------------------------------------------------------------------
11810 * Data Api implementation
11811 * ------------------------------------------------------------------------
11815 $__default['default'](document).on(EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE_CARROT, function (event) {
11816 var button = event.target;
11817 var initialButton = button;
11819 if (!$__default['default'](button).hasClass(CLASS_NAME_BUTTON)) {
11820 button = $__default['default'](button).closest(SELECTOR_BUTTON)[0];
11823 if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) {
11824 event.preventDefault(); // work around Firefox bug #1540995
11826 var inputBtn = button.querySelector(SELECTOR_INPUT);
11828 if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) {
11829 event.preventDefault(); // work around Firefox bug #1540995
11834 if (initialButton.tagName === 'INPUT' || button.tagName !== 'LABEL') {
11835 Button._jQueryInterface.call($__default['default'](button), 'toggle', initialButton.tagName === 'INPUT');
11838 }).on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, function (event) {
11839 var button = $__default['default'](event.target).closest(SELECTOR_BUTTON)[0];
11840 $__default['default'](button).toggleClass(CLASS_NAME_FOCUS, /^focus(in)?$/.test(event.type));
11842 $__default['default'](window).on(EVENT_LOAD_DATA_API, function () {
11843 // ensure correct active class is set to match the controls' actual values/states
11844 // find all checkboxes/readio buttons inside data-toggle groups
11845 var buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLES_BUTTONS));
11847 for (var i = 0, len = buttons.length; i < len; i++) {
11848 var button = buttons[i];
11849 var input = button.querySelector(SELECTOR_INPUT);
11851 if (input.checked || input.hasAttribute('checked')) {
11852 button.classList.add(CLASS_NAME_ACTIVE);
11854 button.classList.remove(CLASS_NAME_ACTIVE);
11856 } // find all button toggles
11859 buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE));
11861 for (var _i = 0, _len = buttons.length; _i < _len; _i++) {
11862 var _button = buttons[_i];
11864 if (_button.getAttribute('aria-pressed') === 'true') {
11865 _button.classList.add(CLASS_NAME_ACTIVE);
11867 _button.classList.remove(CLASS_NAME_ACTIVE);
11872 * ------------------------------------------------------------------------
11874 * ------------------------------------------------------------------------
11877 $__default['default'].fn[NAME$1] = Button._jQueryInterface;
11878 $__default['default'].fn[NAME$1].Constructor = Button;
11880 $__default['default'].fn[NAME$1].noConflict = function () {
11881 $__default['default'].fn[NAME$1] = JQUERY_NO_CONFLICT$1;
11882 return Button._jQueryInterface;
11886 * ------------------------------------------------------------------------
11888 * ------------------------------------------------------------------------
11891 var NAME$2 = 'carousel';
11892 var VERSION$2 = '4.6.0';
11893 var DATA_KEY$2 = 'bs.carousel';
11894 var EVENT_KEY$2 = "." + DATA_KEY$2;
11895 var DATA_API_KEY$2 = '.data-api';
11896 var JQUERY_NO_CONFLICT$2 = $__default['default'].fn[NAME$2];
11897 var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
11899 var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
11901 var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
11903 var SWIPE_THRESHOLD = 40;
11912 var DefaultType = {
11913 interval: '(number|boolean)',
11914 keyboard: 'boolean',
11915 slide: '(boolean|string)',
11916 pause: '(string|boolean)',
11920 var DIRECTION_NEXT = 'next';
11921 var DIRECTION_PREV = 'prev';
11922 var DIRECTION_LEFT = 'left';
11923 var DIRECTION_RIGHT = 'right';
11924 var EVENT_SLIDE = "slide" + EVENT_KEY$2;
11925 var EVENT_SLID = "slid" + EVENT_KEY$2;
11926 var EVENT_KEYDOWN = "keydown" + EVENT_KEY$2;
11927 var EVENT_MOUSEENTER = "mouseenter" + EVENT_KEY$2;
11928 var EVENT_MOUSELEAVE = "mouseleave" + EVENT_KEY$2;
11929 var EVENT_TOUCHSTART = "touchstart" + EVENT_KEY$2;
11930 var EVENT_TOUCHMOVE = "touchmove" + EVENT_KEY$2;
11931 var EVENT_TOUCHEND = "touchend" + EVENT_KEY$2;
11932 var EVENT_POINTERDOWN = "pointerdown" + EVENT_KEY$2;
11933 var EVENT_POINTERUP = "pointerup" + EVENT_KEY$2;
11934 var EVENT_DRAG_START = "dragstart" + EVENT_KEY$2;
11935 var EVENT_LOAD_DATA_API$1 = "load" + EVENT_KEY$2 + DATA_API_KEY$2;
11936 var EVENT_CLICK_DATA_API$2 = "click" + EVENT_KEY$2 + DATA_API_KEY$2;
11937 var CLASS_NAME_CAROUSEL = 'carousel';
11938 var CLASS_NAME_ACTIVE$1 = 'active';
11939 var CLASS_NAME_SLIDE = 'slide';
11940 var CLASS_NAME_RIGHT = 'carousel-item-right';
11941 var CLASS_NAME_LEFT = 'carousel-item-left';
11942 var CLASS_NAME_NEXT = 'carousel-item-next';
11943 var CLASS_NAME_PREV = 'carousel-item-prev';
11944 var CLASS_NAME_POINTER_EVENT = 'pointer-event';
11945 var SELECTOR_ACTIVE$1 = '.active';
11946 var SELECTOR_ACTIVE_ITEM = '.active.carousel-item';
11947 var SELECTOR_ITEM = '.carousel-item';
11948 var SELECTOR_ITEM_IMG = '.carousel-item img';
11949 var SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';
11950 var SELECTOR_INDICATORS = '.carousel-indicators';
11951 var SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]';
11952 var SELECTOR_DATA_RIDE = '[data-ride="carousel"]';
11953 var PointerType = {
11958 * ------------------------------------------------------------------------
11960 * ------------------------------------------------------------------------
11963 var Carousel = /*#__PURE__*/function () {
11964 function Carousel(element, config) {
11965 this._items = null;
11966 this._interval = null;
11967 this._activeElement = null;
11968 this._isPaused = false;
11969 this._isSliding = false;
11970 this.touchTimeout = null;
11971 this.touchStartX = 0;
11972 this.touchDeltaX = 0;
11973 this._config = this._getConfig(config);
11974 this._element = element;
11975 this._indicatorsElement = this._element.querySelector(SELECTOR_INDICATORS);
11976 this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;
11977 this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent);
11979 this._addEventListeners();
11983 var _proto = Carousel.prototype;
11986 _proto.next = function next() {
11987 if (!this._isSliding) {
11988 this._slide(DIRECTION_NEXT);
11992 _proto.nextWhenVisible = function nextWhenVisible() {
11993 var $element = $__default['default'](this._element); // Don't call next when the page isn't visible
11994 // or the carousel or its parent isn't visible
11996 if (!document.hidden && $element.is(':visible') && $element.css('visibility') !== 'hidden') {
12001 _proto.prev = function prev() {
12002 if (!this._isSliding) {
12003 this._slide(DIRECTION_PREV);
12007 _proto.pause = function pause(event) {
12009 this._isPaused = true;
12012 if (this._element.querySelector(SELECTOR_NEXT_PREV)) {
12013 Util.triggerTransitionEnd(this._element);
12017 clearInterval(this._interval);
12018 this._interval = null;
12021 _proto.cycle = function cycle(event) {
12023 this._isPaused = false;
12026 if (this._interval) {
12027 clearInterval(this._interval);
12028 this._interval = null;
12031 if (this._config.interval && !this._isPaused) {
12032 this._updateInterval();
12034 this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
12038 _proto.to = function to(index) {
12041 this._activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM);
12043 var activeIndex = this._getItemIndex(this._activeElement);
12045 if (index > this._items.length - 1 || index < 0) {
12049 if (this._isSliding) {
12050 $__default['default'](this._element).one(EVENT_SLID, function () {
12051 return _this.to(index);
12056 if (activeIndex === index) {
12062 var direction = index > activeIndex ? DIRECTION_NEXT : DIRECTION_PREV;
12064 this._slide(direction, this._items[index]);
12067 _proto.dispose = function dispose() {
12068 $__default['default'](this._element).off(EVENT_KEY$2);
12069 $__default['default'].removeData(this._element, DATA_KEY$2);
12070 this._items = null;
12071 this._config = null;
12072 this._element = null;
12073 this._interval = null;
12074 this._isPaused = null;
12075 this._isSliding = null;
12076 this._activeElement = null;
12077 this._indicatorsElement = null;
12081 _proto._getConfig = function _getConfig(config) {
12082 config = _extends({}, Default, config);
12083 Util.typeCheckConfig(NAME$2, config, DefaultType);
12087 _proto._handleSwipe = function _handleSwipe() {
12088 var absDeltax = Math.abs(this.touchDeltaX);
12090 if (absDeltax <= SWIPE_THRESHOLD) {
12094 var direction = absDeltax / this.touchDeltaX;
12095 this.touchDeltaX = 0; // swipe left
12097 if (direction > 0) {
12102 if (direction < 0) {
12107 _proto._addEventListeners = function _addEventListeners() {
12110 if (this._config.keyboard) {
12111 $__default['default'](this._element).on(EVENT_KEYDOWN, function (event) {
12112 return _this2._keydown(event);
12116 if (this._config.pause === 'hover') {
12117 $__default['default'](this._element).on(EVENT_MOUSEENTER, function (event) {
12118 return _this2.pause(event);
12119 }).on(EVENT_MOUSELEAVE, function (event) {
12120 return _this2.cycle(event);
12124 if (this._config.touch) {
12125 this._addTouchEventListeners();
12129 _proto._addTouchEventListeners = function _addTouchEventListeners() {
12132 if (!this._touchSupported) {
12136 var start = function start(event) {
12137 if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {
12138 _this3.touchStartX = event.originalEvent.clientX;
12139 } else if (!_this3._pointerEvent) {
12140 _this3.touchStartX = event.originalEvent.touches[0].clientX;
12144 var move = function move(event) {
12145 // ensure swiping with one touch and not pinching
12146 if (event.originalEvent.touches && event.originalEvent.touches.length > 1) {
12147 _this3.touchDeltaX = 0;
12149 _this3.touchDeltaX = event.originalEvent.touches[0].clientX - _this3.touchStartX;
12153 var end = function end(event) {
12154 if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {
12155 _this3.touchDeltaX = event.originalEvent.clientX - _this3.touchStartX;
12158 _this3._handleSwipe();
12160 if (_this3._config.pause === 'hover') {
12161 // If it's a touch-enabled device, mouseenter/leave are fired as
12162 // part of the mouse compatibility events on first tap - the carousel
12163 // would stop cycling until user tapped out of it;
12164 // here, we listen for touchend, explicitly pause the carousel
12165 // (as if it's the second time we tap on it, mouseenter compat event
12166 // is NOT fired) and after a timeout (to allow for mouse compatibility
12167 // events to fire) we explicitly restart cycling
12170 if (_this3.touchTimeout) {
12171 clearTimeout(_this3.touchTimeout);
12174 _this3.touchTimeout = setTimeout(function (event) {
12175 return _this3.cycle(event);
12176 }, TOUCHEVENT_COMPAT_WAIT + _this3._config.interval);
12180 $__default['default'](this._element.querySelectorAll(SELECTOR_ITEM_IMG)).on(EVENT_DRAG_START, function (e) {
12181 return e.preventDefault();
12184 if (this._pointerEvent) {
12185 $__default['default'](this._element).on(EVENT_POINTERDOWN, function (event) {
12186 return start(event);
12188 $__default['default'](this._element).on(EVENT_POINTERUP, function (event) {
12192 this._element.classList.add(CLASS_NAME_POINTER_EVENT);
12194 $__default['default'](this._element).on(EVENT_TOUCHSTART, function (event) {
12195 return start(event);
12197 $__default['default'](this._element).on(EVENT_TOUCHMOVE, function (event) {
12198 return move(event);
12200 $__default['default'](this._element).on(EVENT_TOUCHEND, function (event) {
12206 _proto._keydown = function _keydown(event) {
12207 if (/input|textarea/i.test(event.target.tagName)) {
12211 switch (event.which) {
12212 case ARROW_LEFT_KEYCODE:
12213 event.preventDefault();
12217 case ARROW_RIGHT_KEYCODE:
12218 event.preventDefault();
12224 _proto._getItemIndex = function _getItemIndex(element) {
12225 this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(SELECTOR_ITEM)) : [];
12226 return this._items.indexOf(element);
12229 _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {
12230 var isNextDirection = direction === DIRECTION_NEXT;
12231 var isPrevDirection = direction === DIRECTION_PREV;
12233 var activeIndex = this._getItemIndex(activeElement);
12235 var lastItemIndex = this._items.length - 1;
12236 var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
12238 if (isGoingToWrap && !this._config.wrap) {
12239 return activeElement;
12242 var delta = direction === DIRECTION_PREV ? -1 : 1;
12243 var itemIndex = (activeIndex + delta) % this._items.length;
12244 return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
12247 _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {
12248 var targetIndex = this._getItemIndex(relatedTarget);
12250 var fromIndex = this._getItemIndex(this._element.querySelector(SELECTOR_ACTIVE_ITEM));
12252 var slideEvent = $__default['default'].Event(EVENT_SLIDE, {
12253 relatedTarget: relatedTarget,
12254 direction: eventDirectionName,
12258 $__default['default'](this._element).trigger(slideEvent);
12262 _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
12263 if (this._indicatorsElement) {
12264 var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE$1));
12265 $__default['default'](indicators).removeClass(CLASS_NAME_ACTIVE$1);
12267 var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
12269 if (nextIndicator) {
12270 $__default['default'](nextIndicator).addClass(CLASS_NAME_ACTIVE$1);
12275 _proto._updateInterval = function _updateInterval() {
12276 var element = this._activeElement || this._element.querySelector(SELECTOR_ACTIVE_ITEM);
12282 var elementInterval = parseInt(element.getAttribute('data-interval'), 10);
12284 if (elementInterval) {
12285 this._config.defaultInterval = this._config.defaultInterval || this._config.interval;
12286 this._config.interval = elementInterval;
12288 this._config.interval = this._config.defaultInterval || this._config.interval;
12292 _proto._slide = function _slide(direction, element) {
12295 var activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM);
12297 var activeElementIndex = this._getItemIndex(activeElement);
12299 var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
12301 var nextElementIndex = this._getItemIndex(nextElement);
12303 var isCycling = Boolean(this._interval);
12304 var directionalClassName;
12305 var orderClassName;
12306 var eventDirectionName;
12308 if (direction === DIRECTION_NEXT) {
12309 directionalClassName = CLASS_NAME_LEFT;
12310 orderClassName = CLASS_NAME_NEXT;
12311 eventDirectionName = DIRECTION_LEFT;
12313 directionalClassName = CLASS_NAME_RIGHT;
12314 orderClassName = CLASS_NAME_PREV;
12315 eventDirectionName = DIRECTION_RIGHT;
12318 if (nextElement && $__default['default'](nextElement).hasClass(CLASS_NAME_ACTIVE$1)) {
12319 this._isSliding = false;
12323 var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
12325 if (slideEvent.isDefaultPrevented()) {
12329 if (!activeElement || !nextElement) {
12330 // Some weirdness is happening, so we bail
12334 this._isSliding = true;
12340 this._setActiveIndicatorElement(nextElement);
12342 this._activeElement = nextElement;
12343 var slidEvent = $__default['default'].Event(EVENT_SLID, {
12344 relatedTarget: nextElement,
12345 direction: eventDirectionName,
12346 from: activeElementIndex,
12347 to: nextElementIndex
12350 if ($__default['default'](this._element).hasClass(CLASS_NAME_SLIDE)) {
12351 $__default['default'](nextElement).addClass(orderClassName);
12352 Util.reflow(nextElement);
12353 $__default['default'](activeElement).addClass(directionalClassName);
12354 $__default['default'](nextElement).addClass(directionalClassName);
12355 var transitionDuration = Util.getTransitionDurationFromElement(activeElement);
12356 $__default['default'](activeElement).one(Util.TRANSITION_END, function () {
12357 $__default['default'](nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(CLASS_NAME_ACTIVE$1);
12358 $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE$1 + " " + orderClassName + " " + directionalClassName);
12359 _this4._isSliding = false;
12360 setTimeout(function () {
12361 return $__default['default'](_this4._element).trigger(slidEvent);
12363 }).emulateTransitionEnd(transitionDuration);
12365 $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE$1);
12366 $__default['default'](nextElement).addClass(CLASS_NAME_ACTIVE$1);
12367 this._isSliding = false;
12368 $__default['default'](this._element).trigger(slidEvent);
12377 Carousel._jQueryInterface = function _jQueryInterface(config) {
12378 return this.each(function () {
12379 var data = $__default['default'](this).data(DATA_KEY$2);
12381 var _config = _extends({}, Default, $__default['default'](this).data());
12383 if (typeof config === 'object') {
12384 _config = _extends({}, _config, config);
12387 var action = typeof config === 'string' ? config : _config.slide;
12390 data = new Carousel(this, _config);
12391 $__default['default'](this).data(DATA_KEY$2, data);
12394 if (typeof config === 'number') {
12396 } else if (typeof action === 'string') {
12397 if (typeof data[action] === 'undefined') {
12398 throw new TypeError("No method named \"" + action + "\"");
12402 } else if (_config.interval && _config.ride) {
12409 Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
12410 var selector = Util.getSelectorFromElement(this);
12416 var target = $__default['default'](selector)[0];
12418 if (!target || !$__default['default'](target).hasClass(CLASS_NAME_CAROUSEL)) {
12422 var config = _extends({}, $__default['default'](target).data(), $__default['default'](this).data());
12424 var slideIndex = this.getAttribute('data-slide-to');
12427 config.interval = false;
12430 Carousel._jQueryInterface.call($__default['default'](target), config);
12433 $__default['default'](target).data(DATA_KEY$2).to(slideIndex);
12436 event.preventDefault();
12439 _createClass(Carousel, null, [{
12441 get: function get() {
12446 get: function get() {
12454 * ------------------------------------------------------------------------
12455 * Data Api implementation
12456 * ------------------------------------------------------------------------
12460 $__default['default'](document).on(EVENT_CLICK_DATA_API$2, SELECTOR_DATA_SLIDE, Carousel._dataApiClickHandler);
12461 $__default['default'](window).on(EVENT_LOAD_DATA_API$1, function () {
12462 var carousels = [].slice.call(document.querySelectorAll(SELECTOR_DATA_RIDE));
12464 for (var i = 0, len = carousels.length; i < len; i++) {
12465 var $carousel = $__default['default'](carousels[i]);
12467 Carousel._jQueryInterface.call($carousel, $carousel.data());
12471 * ------------------------------------------------------------------------
12473 * ------------------------------------------------------------------------
12476 $__default['default'].fn[NAME$2] = Carousel._jQueryInterface;
12477 $__default['default'].fn[NAME$2].Constructor = Carousel;
12479 $__default['default'].fn[NAME$2].noConflict = function () {
12480 $__default['default'].fn[NAME$2] = JQUERY_NO_CONFLICT$2;
12481 return Carousel._jQueryInterface;
12485 * ------------------------------------------------------------------------
12487 * ------------------------------------------------------------------------
12490 var NAME$3 = 'collapse';
12491 var VERSION$3 = '4.6.0';
12492 var DATA_KEY$3 = 'bs.collapse';
12493 var EVENT_KEY$3 = "." + DATA_KEY$3;
12494 var DATA_API_KEY$3 = '.data-api';
12495 var JQUERY_NO_CONFLICT$3 = $__default['default'].fn[NAME$3];
12500 var DefaultType$1 = {
12502 parent: '(string|element)'
12504 var EVENT_SHOW = "show" + EVENT_KEY$3;
12505 var EVENT_SHOWN = "shown" + EVENT_KEY$3;
12506 var EVENT_HIDE = "hide" + EVENT_KEY$3;
12507 var EVENT_HIDDEN = "hidden" + EVENT_KEY$3;
12508 var EVENT_CLICK_DATA_API$3 = "click" + EVENT_KEY$3 + DATA_API_KEY$3;
12509 var CLASS_NAME_SHOW$1 = 'show';
12510 var CLASS_NAME_COLLAPSE = 'collapse';
12511 var CLASS_NAME_COLLAPSING = 'collapsing';
12512 var CLASS_NAME_COLLAPSED = 'collapsed';
12513 var DIMENSION_WIDTH = 'width';
12514 var DIMENSION_HEIGHT = 'height';
12515 var SELECTOR_ACTIVES = '.show, .collapsing';
12516 var SELECTOR_DATA_TOGGLE$1 = '[data-toggle="collapse"]';
12518 * ------------------------------------------------------------------------
12520 * ------------------------------------------------------------------------
12523 var Collapse = /*#__PURE__*/function () {
12524 function Collapse(element, config) {
12525 this._isTransitioning = false;
12526 this._element = element;
12527 this._config = this._getConfig(config);
12528 this._triggerArray = [].slice.call(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]")));
12529 var toggleList = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE$1));
12531 for (var i = 0, len = toggleList.length; i < len; i++) {
12532 var elem = toggleList[i];
12533 var selector = Util.getSelectorFromElement(elem);
12534 var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) {
12535 return foundElem === element;
12538 if (selector !== null && filterElement.length > 0) {
12539 this._selector = selector;
12541 this._triggerArray.push(elem);
12545 this._parent = this._config.parent ? this._getParent() : null;
12547 if (!this._config.parent) {
12548 this._addAriaAndCollapsedClass(this._element, this._triggerArray);
12551 if (this._config.toggle) {
12557 var _proto = Collapse.prototype;
12560 _proto.toggle = function toggle() {
12561 if ($__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {
12568 _proto.show = function show() {
12571 if (this._isTransitioning || $__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {
12578 if (this._parent) {
12579 actives = [].slice.call(this._parent.querySelectorAll(SELECTOR_ACTIVES)).filter(function (elem) {
12580 if (typeof _this._config.parent === 'string') {
12581 return elem.getAttribute('data-parent') === _this._config.parent;
12584 return elem.classList.contains(CLASS_NAME_COLLAPSE);
12587 if (actives.length === 0) {
12593 activesData = $__default['default'](actives).not(this._selector).data(DATA_KEY$3);
12595 if (activesData && activesData._isTransitioning) {
12600 var startEvent = $__default['default'].Event(EVENT_SHOW);
12601 $__default['default'](this._element).trigger(startEvent);
12603 if (startEvent.isDefaultPrevented()) {
12608 Collapse._jQueryInterface.call($__default['default'](actives).not(this._selector), 'hide');
12610 if (!activesData) {
12611 $__default['default'](actives).data(DATA_KEY$3, null);
12615 var dimension = this._getDimension();
12617 $__default['default'](this._element).removeClass(CLASS_NAME_COLLAPSE).addClass(CLASS_NAME_COLLAPSING);
12618 this._element.style[dimension] = 0;
12620 if (this._triggerArray.length) {
12621 $__default['default'](this._triggerArray).removeClass(CLASS_NAME_COLLAPSED).attr('aria-expanded', true);
12624 this.setTransitioning(true);
12626 var complete = function complete() {
12627 $__default['default'](_this._element).removeClass(CLASS_NAME_COLLAPSING).addClass(CLASS_NAME_COLLAPSE + " " + CLASS_NAME_SHOW$1);
12628 _this._element.style[dimension] = '';
12630 _this.setTransitioning(false);
12632 $__default['default'](_this._element).trigger(EVENT_SHOWN);
12635 var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
12636 var scrollSize = "scroll" + capitalizedDimension;
12637 var transitionDuration = Util.getTransitionDurationFromElement(this._element);
12638 $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
12639 this._element.style[dimension] = this._element[scrollSize] + "px";
12642 _proto.hide = function hide() {
12645 if (this._isTransitioning || !$__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {
12649 var startEvent = $__default['default'].Event(EVENT_HIDE);
12650 $__default['default'](this._element).trigger(startEvent);
12652 if (startEvent.isDefaultPrevented()) {
12656 var dimension = this._getDimension();
12658 this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px";
12659 Util.reflow(this._element);
12660 $__default['default'](this._element).addClass(CLASS_NAME_COLLAPSING).removeClass(CLASS_NAME_COLLAPSE + " " + CLASS_NAME_SHOW$1);
12661 var triggerArrayLength = this._triggerArray.length;
12663 if (triggerArrayLength > 0) {
12664 for (var i = 0; i < triggerArrayLength; i++) {
12665 var trigger = this._triggerArray[i];
12666 var selector = Util.getSelectorFromElement(trigger);
12668 if (selector !== null) {
12669 var $elem = $__default['default']([].slice.call(document.querySelectorAll(selector)));
12671 if (!$elem.hasClass(CLASS_NAME_SHOW$1)) {
12672 $__default['default'](trigger).addClass(CLASS_NAME_COLLAPSED).attr('aria-expanded', false);
12678 this.setTransitioning(true);
12680 var complete = function complete() {
12681 _this2.setTransitioning(false);
12683 $__default['default'](_this2._element).removeClass(CLASS_NAME_COLLAPSING).addClass(CLASS_NAME_COLLAPSE).trigger(EVENT_HIDDEN);
12686 this._element.style[dimension] = '';
12687 var transitionDuration = Util.getTransitionDurationFromElement(this._element);
12688 $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
12691 _proto.setTransitioning = function setTransitioning(isTransitioning) {
12692 this._isTransitioning = isTransitioning;
12695 _proto.dispose = function dispose() {
12696 $__default['default'].removeData(this._element, DATA_KEY$3);
12697 this._config = null;
12698 this._parent = null;
12699 this._element = null;
12700 this._triggerArray = null;
12701 this._isTransitioning = null;
12705 _proto._getConfig = function _getConfig(config) {
12706 config = _extends({}, Default$1, config);
12707 config.toggle = Boolean(config.toggle); // Coerce string values
12709 Util.typeCheckConfig(NAME$3, config, DefaultType$1);
12713 _proto._getDimension = function _getDimension() {
12714 var hasWidth = $__default['default'](this._element).hasClass(DIMENSION_WIDTH);
12715 return hasWidth ? DIMENSION_WIDTH : DIMENSION_HEIGHT;
12718 _proto._getParent = function _getParent() {
12723 if (Util.isElement(this._config.parent)) {
12724 parent = this._config.parent; // It's a jQuery object
12726 if (typeof this._config.parent.jquery !== 'undefined') {
12727 parent = this._config.parent[0];
12730 parent = document.querySelector(this._config.parent);
12733 var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]";
12734 var children = [].slice.call(parent.querySelectorAll(selector));
12735 $__default['default'](children).each(function (i, element) {
12736 _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
12741 _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
12742 var isOpen = $__default['default'](element).hasClass(CLASS_NAME_SHOW$1);
12744 if (triggerArray.length) {
12745 $__default['default'](triggerArray).toggleClass(CLASS_NAME_COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
12750 Collapse._getTargetFromElement = function _getTargetFromElement(element) {
12751 var selector = Util.getSelectorFromElement(element);
12752 return selector ? document.querySelector(selector) : null;
12755 Collapse._jQueryInterface = function _jQueryInterface(config) {
12756 return this.each(function () {
12757 var $element = $__default['default'](this);
12758 var data = $element.data(DATA_KEY$3);
12760 var _config = _extends({}, Default$1, $element.data(), typeof config === 'object' && config ? config : {});
12762 if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
12763 _config.toggle = false;
12767 data = new Collapse(this, _config);
12768 $element.data(DATA_KEY$3, data);
12771 if (typeof config === 'string') {
12772 if (typeof data[config] === 'undefined') {
12773 throw new TypeError("No method named \"" + config + "\"");
12781 _createClass(Collapse, null, [{
12783 get: function get() {
12788 get: function get() {
12796 * ------------------------------------------------------------------------
12797 * Data Api implementation
12798 * ------------------------------------------------------------------------
12802 $__default['default'](document).on(EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$1, function (event) {
12803 // preventDefault only for <a> elements (which change the URL) not inside the collapsible element
12804 if (event.currentTarget.tagName === 'A') {
12805 event.preventDefault();
12808 var $trigger = $__default['default'](this);
12809 var selector = Util.getSelectorFromElement(this);
12810 var selectors = [].slice.call(document.querySelectorAll(selector));
12811 $__default['default'](selectors).each(function () {
12812 var $target = $__default['default'](this);
12813 var data = $target.data(DATA_KEY$3);
12814 var config = data ? 'toggle' : $trigger.data();
12816 Collapse._jQueryInterface.call($target, config);
12820 * ------------------------------------------------------------------------
12822 * ------------------------------------------------------------------------
12825 $__default['default'].fn[NAME$3] = Collapse._jQueryInterface;
12826 $__default['default'].fn[NAME$3].Constructor = Collapse;
12828 $__default['default'].fn[NAME$3].noConflict = function () {
12829 $__default['default'].fn[NAME$3] = JQUERY_NO_CONFLICT$3;
12830 return Collapse._jQueryInterface;
12834 * @fileOverview Kickass library to create and place poppers near their reference elements.
12837 * Copyright (c) 2016 Federico Zivolo and contributors
12839 * Permission is hereby granted, free of charge, to any person obtaining a copy
12840 * of this software and associated documentation files (the "Software"), to deal
12841 * in the Software without restriction, including without limitation the rights
12842 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12843 * copies of the Software, and to permit persons to whom the Software is
12844 * furnished to do so, subject to the following conditions:
12846 * The above copyright notice and this permission notice shall be included in all
12847 * copies or substantial portions of the Software.
12849 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12850 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12851 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
12852 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
12853 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12854 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
12857 var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined';
12859 var timeoutDuration = function () {
12860 var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
12861 for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
12862 if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
12869 function microtaskDebounce(fn) {
12870 var called = false;
12871 return function () {
12876 window.Promise.resolve().then(function () {
12883 function taskDebounce(fn) {
12884 var scheduled = false;
12885 return function () {
12888 setTimeout(function () {
12891 }, timeoutDuration);
12896 var supportsMicroTasks = isBrowser && window.Promise;
12899 * Create a debounced version of a method, that's asynchronously deferred
12900 * but called in the minimum time possible.
12903 * @memberof Popper.Utils
12904 * @argument {Function} fn
12905 * @returns {Function}
12907 var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
12910 * Check if the given variable is a function
12912 * @memberof Popper.Utils
12913 * @argument {Any} functionToCheck - variable to check
12914 * @returns {Boolean} answer to: is a function?
12916 function isFunction(functionToCheck) {
12918 return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
12922 * Get CSS computed property of the given element
12924 * @memberof Popper.Utils
12925 * @argument {Eement} element
12926 * @argument {String} property
12928 function getStyleComputedProperty(element, property) {
12929 if (element.nodeType !== 1) {
12932 // NOTE: 1 DOM access here
12933 var window = element.ownerDocument.defaultView;
12934 var css = window.getComputedStyle(element, null);
12935 return property ? css[property] : css;
12939 * Returns the parentNode or the host of the element
12941 * @memberof Popper.Utils
12942 * @argument {Element} element
12943 * @returns {Element} parent
12945 function getParentNode(element) {
12946 if (element.nodeName === 'HTML') {
12949 return element.parentNode || element.host;
12953 * Returns the scrolling parent of the given element
12955 * @memberof Popper.Utils
12956 * @argument {Element} element
12957 * @returns {Element} scroll parent
12959 function getScrollParent(element) {
12960 // Return body, `getScroll` will take care to get the correct `scrollTop` from it
12962 return document.body;
12965 switch (element.nodeName) {
12968 return element.ownerDocument.body;
12970 return element.body;
12973 // Firefox want us to check `-x` and `-y` variations as well
12975 var _getStyleComputedProp = getStyleComputedProperty(element),
12976 overflow = _getStyleComputedProp.overflow,
12977 overflowX = _getStyleComputedProp.overflowX,
12978 overflowY = _getStyleComputedProp.overflowY;
12980 if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
12984 return getScrollParent(getParentNode(element));
12988 * Returns the reference node of the reference object, or the reference object itself.
12990 * @memberof Popper.Utils
12991 * @param {Element|Object} reference - the reference element (the popper will be relative to this)
12992 * @returns {Element} parent
12994 function getReferenceNode(reference) {
12995 return reference && reference.referenceNode ? reference.referenceNode : reference;
12998 var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
12999 var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
13002 * Determines if the browser is Internet Explorer
13004 * @memberof Popper.Utils
13005 * @param {Number} version to check
13006 * @returns {Boolean} isIE
13008 function isIE(version) {
13009 if (version === 11) {
13012 if (version === 10) {
13015 return isIE11 || isIE10;
13019 * Returns the offset parent of the given element
13021 * @memberof Popper.Utils
13022 * @argument {Element} element
13023 * @returns {Element} offset parent
13025 function getOffsetParent(element) {
13027 return document.documentElement;
13030 var noOffsetParent = isIE(10) ? document.body : null;
13032 // NOTE: 1 DOM access here
13033 var offsetParent = element.offsetParent || null;
13034 // Skip hidden elements which don't have an offsetParent
13035 while (offsetParent === noOffsetParent && element.nextElementSibling) {
13036 offsetParent = (element = element.nextElementSibling).offsetParent;
13039 var nodeName = offsetParent && offsetParent.nodeName;
13041 if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
13042 return element ? element.ownerDocument.documentElement : document.documentElement;
13045 // .offsetParent will return the closest TH, TD or TABLE in case
13046 // no offsetParent is present, I hate this job...
13047 if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
13048 return getOffsetParent(offsetParent);
13051 return offsetParent;
13054 function isOffsetContainer(element) {
13055 var nodeName = element.nodeName;
13057 if (nodeName === 'BODY') {
13060 return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
13064 * Finds the root node (document, shadowDOM root) of the given element
13066 * @memberof Popper.Utils
13067 * @argument {Element} node
13068 * @returns {Element} root node
13070 function getRoot(node) {
13071 if (node.parentNode !== null) {
13072 return getRoot(node.parentNode);
13079 * Finds the offset parent common to the two provided nodes
13081 * @memberof Popper.Utils
13082 * @argument {Element} element1
13083 * @argument {Element} element2
13084 * @returns {Element} common offset parent
13086 function findCommonOffsetParent(element1, element2) {
13087 // This check is needed to avoid errors in case one of the elements isn't defined for any reason
13088 if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
13089 return document.documentElement;
13092 // Here we make sure to give as "start" the element that comes first in the DOM
13093 var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
13094 var start = order ? element1 : element2;
13095 var end = order ? element2 : element1;
13097 // Get common ancestor container
13098 var range = document.createRange();
13099 range.setStart(start, 0);
13100 range.setEnd(end, 0);
13101 var commonAncestorContainer = range.commonAncestorContainer;
13103 // Both nodes are inside #document
13105 if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
13106 if (isOffsetContainer(commonAncestorContainer)) {
13107 return commonAncestorContainer;
13110 return getOffsetParent(commonAncestorContainer);
13113 // one of the nodes is inside shadowDOM, find which one
13114 var element1root = getRoot(element1);
13115 if (element1root.host) {
13116 return findCommonOffsetParent(element1root.host, element2);
13118 return findCommonOffsetParent(element1, getRoot(element2).host);
13123 * Gets the scroll value of the given element in the given side (top and left)
13125 * @memberof Popper.Utils
13126 * @argument {Element} element
13127 * @argument {String} side `top` or `left`
13128 * @returns {number} amount of scrolled pixels
13130 function getScroll(element) {
13131 var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
13133 var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
13134 var nodeName = element.nodeName;
13136 if (nodeName === 'BODY' || nodeName === 'HTML') {
13137 var html = element.ownerDocument.documentElement;
13138 var scrollingElement = element.ownerDocument.scrollingElement || html;
13139 return scrollingElement[upperSide];
13142 return element[upperSide];
13146 * Sum or subtract the element scroll values (left and top) from a given rect object
13148 * @memberof Popper.Utils
13149 * @param {Object} rect - Rect object you want to change
13150 * @param {HTMLElement} element - The element from the function reads the scroll values
13151 * @param {Boolean} subtract - set to true if you want to subtract the scroll values
13152 * @return {Object} rect - The modifier rect object
13154 function includeScroll(rect, element) {
13155 var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
13157 var scrollTop = getScroll(element, 'top');
13158 var scrollLeft = getScroll(element, 'left');
13159 var modifier = subtract ? -1 : 1;
13160 rect.top += scrollTop * modifier;
13161 rect.bottom += scrollTop * modifier;
13162 rect.left += scrollLeft * modifier;
13163 rect.right += scrollLeft * modifier;
13168 * Helper to detect borders of a given element
13170 * @memberof Popper.Utils
13171 * @param {CSSStyleDeclaration} styles
13172 * Result of `getStyleComputedProperty` on the given element
13173 * @param {String} axis - `x` or `y`
13174 * @return {number} borders - The borders size of the given axis
13177 function getBordersSize(styles, axis) {
13178 var sideA = axis === 'x' ? 'Left' : 'Top';
13179 var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
13181 return parseFloat(styles['border' + sideA + 'Width']) + parseFloat(styles['border' + sideB + 'Width']);
13184 function getSize(axis, body, html, computedStyle) {
13185 return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
13188 function getWindowSizes(document) {
13189 var body = document.body;
13190 var html = document.documentElement;
13191 var computedStyle = isIE(10) && getComputedStyle(html);
13194 height: getSize('Height', body, html, computedStyle),
13195 width: getSize('Width', body, html, computedStyle)
13199 var classCallCheck = function (instance, Constructor) {
13200 if (!(instance instanceof Constructor)) {
13201 throw new TypeError("Cannot call a class as a function");
13205 var createClass = function () {
13206 function defineProperties(target, props) {
13207 for (var i = 0; i < props.length; i++) {
13208 var descriptor = props[i];
13209 descriptor.enumerable = descriptor.enumerable || false;
13210 descriptor.configurable = true;
13211 if ("value" in descriptor) descriptor.writable = true;
13212 Object.defineProperty(target, descriptor.key, descriptor);
13216 return function (Constructor, protoProps, staticProps) {
13217 if (protoProps) defineProperties(Constructor.prototype, protoProps);
13218 if (staticProps) defineProperties(Constructor, staticProps);
13219 return Constructor;
13227 var defineProperty = function (obj, key, value) {
13229 Object.defineProperty(obj, key, {
13232 configurable: true,
13242 var _extends$1 = Object.assign || function (target) {
13243 for (var i = 1; i < arguments.length; i++) {
13244 var source = arguments[i];
13246 for (var key in source) {
13247 if (Object.prototype.hasOwnProperty.call(source, key)) {
13248 target[key] = source[key];
13257 * Given element offsets, generate an output similar to getBoundingClientRect
13259 * @memberof Popper.Utils
13260 * @argument {Object} offsets
13261 * @returns {Object} ClientRect like output
13263 function getClientRect(offsets) {
13264 return _extends$1({}, offsets, {
13265 right: offsets.left + offsets.width,
13266 bottom: offsets.top + offsets.height
13271 * Get bounding client rect of given element
13273 * @memberof Popper.Utils
13274 * @param {HTMLElement} element
13275 * @return {Object} client rect
13277 function getBoundingClientRect(element) {
13280 // IE10 10 FIX: Please, don't ask, the element isn't
13281 // considered in DOM in some circumstances...
13282 // This isn't reproducible in IE10 compatibility mode of IE11
13285 rect = element.getBoundingClientRect();
13286 var scrollTop = getScroll(element, 'top');
13287 var scrollLeft = getScroll(element, 'left');
13288 rect.top += scrollTop;
13289 rect.left += scrollLeft;
13290 rect.bottom += scrollTop;
13291 rect.right += scrollLeft;
13293 rect = element.getBoundingClientRect();
13300 width: rect.right - rect.left,
13301 height: rect.bottom - rect.top
13304 // subtract scrollbar size from sizes
13305 var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
13306 var width = sizes.width || element.clientWidth || result.width;
13307 var height = sizes.height || element.clientHeight || result.height;
13309 var horizScrollbar = element.offsetWidth - width;
13310 var vertScrollbar = element.offsetHeight - height;
13312 // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
13313 // we make this check conditional for performance reasons
13314 if (horizScrollbar || vertScrollbar) {
13315 var styles = getStyleComputedProperty(element);
13316 horizScrollbar -= getBordersSize(styles, 'x');
13317 vertScrollbar -= getBordersSize(styles, 'y');
13319 result.width -= horizScrollbar;
13320 result.height -= vertScrollbar;
13323 return getClientRect(result);
13326 function getOffsetRectRelativeToArbitraryNode(children, parent) {
13327 var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
13329 var isIE10 = isIE(10);
13330 var isHTML = parent.nodeName === 'HTML';
13331 var childrenRect = getBoundingClientRect(children);
13332 var parentRect = getBoundingClientRect(parent);
13333 var scrollParent = getScrollParent(children);
13335 var styles = getStyleComputedProperty(parent);
13336 var borderTopWidth = parseFloat(styles.borderTopWidth);
13337 var borderLeftWidth = parseFloat(styles.borderLeftWidth);
13339 // In cases where the parent is fixed, we must ignore negative scroll in offset calc
13340 if (fixedPosition && isHTML) {
13341 parentRect.top = Math.max(parentRect.top, 0);
13342 parentRect.left = Math.max(parentRect.left, 0);
13344 var offsets = getClientRect({
13345 top: childrenRect.top - parentRect.top - borderTopWidth,
13346 left: childrenRect.left - parentRect.left - borderLeftWidth,
13347 width: childrenRect.width,
13348 height: childrenRect.height
13350 offsets.marginTop = 0;
13351 offsets.marginLeft = 0;
13353 // Subtract margins of documentElement in case it's being used as parent
13354 // we do this only on HTML because it's the only element that behaves
13355 // differently when margins are applied to it. The margins are included in
13356 // the box of the documentElement, in the other cases not.
13357 if (!isIE10 && isHTML) {
13358 var marginTop = parseFloat(styles.marginTop);
13359 var marginLeft = parseFloat(styles.marginLeft);
13361 offsets.top -= borderTopWidth - marginTop;
13362 offsets.bottom -= borderTopWidth - marginTop;
13363 offsets.left -= borderLeftWidth - marginLeft;
13364 offsets.right -= borderLeftWidth - marginLeft;
13366 // Attach marginTop and marginLeft because in some circumstances we may need them
13367 offsets.marginTop = marginTop;
13368 offsets.marginLeft = marginLeft;
13371 if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
13372 offsets = includeScroll(offsets, parent);
13378 function getViewportOffsetRectRelativeToArtbitraryNode(element) {
13379 var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
13381 var html = element.ownerDocument.documentElement;
13382 var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
13383 var width = Math.max(html.clientWidth, window.innerWidth || 0);
13384 var height = Math.max(html.clientHeight, window.innerHeight || 0);
13386 var scrollTop = !excludeScroll ? getScroll(html) : 0;
13387 var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
13390 top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
13391 left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
13396 return getClientRect(offset);
13400 * Check if the given element is fixed or is inside a fixed parent
13402 * @memberof Popper.Utils
13403 * @argument {Element} element
13404 * @argument {Element} customContainer
13405 * @returns {Boolean} answer to "isFixed?"
13407 function isFixed(element) {
13408 var nodeName = element.nodeName;
13409 if (nodeName === 'BODY' || nodeName === 'HTML') {
13412 if (getStyleComputedProperty(element, 'position') === 'fixed') {
13415 var parentNode = getParentNode(element);
13419 return isFixed(parentNode);
13423 * Finds the first parent of an element that has a transformed property defined
13425 * @memberof Popper.Utils
13426 * @argument {Element} element
13427 * @returns {Element} first transformed parent or documentElement
13430 function getFixedPositionOffsetParent(element) {
13431 // This check is needed to avoid errors in case one of the elements isn't defined for any reason
13432 if (!element || !element.parentElement || isIE()) {
13433 return document.documentElement;
13435 var el = element.parentElement;
13436 while (el && getStyleComputedProperty(el, 'transform') === 'none') {
13437 el = el.parentElement;
13439 return el || document.documentElement;
13443 * Computed the boundaries limits and return them
13445 * @memberof Popper.Utils
13446 * @param {HTMLElement} popper
13447 * @param {HTMLElement} reference
13448 * @param {number} padding
13449 * @param {HTMLElement} boundariesElement - Element used to define the boundaries
13450 * @param {Boolean} fixedPosition - Is in fixed position mode
13451 * @returns {Object} Coordinates of the boundaries
13453 function getBoundaries(popper, reference, padding, boundariesElement) {
13454 var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
13456 // NOTE: 1 DOM access here
13458 var boundaries = { top: 0, left: 0 };
13459 var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));
13461 // Handle viewport case
13462 if (boundariesElement === 'viewport') {
13463 boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
13465 // Handle other cases based on DOM element used as boundaries
13466 var boundariesNode = void 0;
13467 if (boundariesElement === 'scrollParent') {
13468 boundariesNode = getScrollParent(getParentNode(reference));
13469 if (boundariesNode.nodeName === 'BODY') {
13470 boundariesNode = popper.ownerDocument.documentElement;
13472 } else if (boundariesElement === 'window') {
13473 boundariesNode = popper.ownerDocument.documentElement;
13475 boundariesNode = boundariesElement;
13478 var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
13480 // In case of HTML, we need a different computation
13481 if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
13482 var _getWindowSizes = getWindowSizes(popper.ownerDocument),
13483 height = _getWindowSizes.height,
13484 width = _getWindowSizes.width;
13486 boundaries.top += offsets.top - offsets.marginTop;
13487 boundaries.bottom = height + offsets.top;
13488 boundaries.left += offsets.left - offsets.marginLeft;
13489 boundaries.right = width + offsets.left;
13491 // for all the other DOM elements, this one is good
13492 boundaries = offsets;
13497 padding = padding || 0;
13498 var isPaddingNumber = typeof padding === 'number';
13499 boundaries.left += isPaddingNumber ? padding : padding.left || 0;
13500 boundaries.top += isPaddingNumber ? padding : padding.top || 0;
13501 boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
13502 boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
13507 function getArea(_ref) {
13508 var width = _ref.width,
13509 height = _ref.height;
13511 return width * height;
13515 * Utility used to transform the `auto` placement to the placement with more
13518 * @memberof Popper.Utils
13519 * @argument {Object} data - The data object generated by update method
13520 * @argument {Object} options - Modifiers configuration and options
13521 * @returns {Object} The data object, properly modified
13523 function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
13524 var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
13526 if (placement.indexOf('auto') === -1) {
13530 var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
13534 width: boundaries.width,
13535 height: refRect.top - boundaries.top
13538 width: boundaries.right - refRect.right,
13539 height: boundaries.height
13542 width: boundaries.width,
13543 height: boundaries.bottom - refRect.bottom
13546 width: refRect.left - boundaries.left,
13547 height: boundaries.height
13551 var sortedAreas = Object.keys(rects).map(function (key) {
13552 return _extends$1({
13555 area: getArea(rects[key])
13557 }).sort(function (a, b) {
13558 return b.area - a.area;
13561 var filteredAreas = sortedAreas.filter(function (_ref2) {
13562 var width = _ref2.width,
13563 height = _ref2.height;
13564 return width >= popper.clientWidth && height >= popper.clientHeight;
13567 var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
13569 var variation = placement.split('-')[1];
13571 return computedPlacement + (variation ? '-' + variation : '');
13575 * Get offsets to the reference element
13577 * @memberof Popper.Utils
13578 * @param {Object} state
13579 * @param {Element} popper - the popper element
13580 * @param {Element} reference - the reference element (the popper will be relative to this)
13581 * @param {Element} fixedPosition - is in fixed position mode
13582 * @returns {Object} An object containing the offsets which will be applied to the popper
13584 function getReferenceOffsets(state, popper, reference) {
13585 var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
13587 var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));
13588 return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
13592 * Get the outer sizes of the given element (offset size + margins)
13594 * @memberof Popper.Utils
13595 * @argument {Element} element
13596 * @returns {Object} object containing width and height properties
13598 function getOuterSizes(element) {
13599 var window = element.ownerDocument.defaultView;
13600 var styles = window.getComputedStyle(element);
13601 var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
13602 var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
13604 width: element.offsetWidth + y,
13605 height: element.offsetHeight + x
13611 * Get the opposite placement of the given one
13613 * @memberof Popper.Utils
13614 * @argument {String} placement
13615 * @returns {String} flipped placement
13617 function getOppositePlacement(placement) {
13618 var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
13619 return placement.replace(/left|right|bottom|top/g, function (matched) {
13620 return hash[matched];
13625 * Get offsets to the popper
13627 * @memberof Popper.Utils
13628 * @param {Object} position - CSS position the Popper will get applied
13629 * @param {HTMLElement} popper - the popper element
13630 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
13631 * @param {String} placement - one of the valid placement options
13632 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
13634 function getPopperOffsets(popper, referenceOffsets, placement) {
13635 placement = placement.split('-')[0];
13637 // Get popper node sizes
13638 var popperRect = getOuterSizes(popper);
13640 // Add position, width and height to our offsets object
13641 var popperOffsets = {
13642 width: popperRect.width,
13643 height: popperRect.height
13646 // depending by the popper placement we have to compute its offsets slightly differently
13647 var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
13648 var mainSide = isHoriz ? 'top' : 'left';
13649 var secondarySide = isHoriz ? 'left' : 'top';
13650 var measurement = isHoriz ? 'height' : 'width';
13651 var secondaryMeasurement = !isHoriz ? 'height' : 'width';
13653 popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
13654 if (placement === secondarySide) {
13655 popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
13657 popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
13660 return popperOffsets;
13664 * Mimics the `find` method of Array
13666 * @memberof Popper.Utils
13667 * @argument {Array} arr
13670 * @returns index or -1
13672 function find(arr, check) {
13673 // use native find if supported
13674 if (Array.prototype.find) {
13675 return arr.find(check);
13678 // use `filter` to obtain the same behavior of `find`
13679 return arr.filter(check)[0];
13683 * Return the index of the matching object
13685 * @memberof Popper.Utils
13686 * @argument {Array} arr
13689 * @returns index or -1
13691 function findIndex(arr, prop, value) {
13692 // use native findIndex if supported
13693 if (Array.prototype.findIndex) {
13694 return arr.findIndex(function (cur) {
13695 return cur[prop] === value;
13699 // use `find` + `indexOf` if `findIndex` isn't supported
13700 var match = find(arr, function (obj) {
13701 return obj[prop] === value;
13703 return arr.indexOf(match);
13707 * Loop trough the list of modifiers and run them in order,
13708 * each of them will then edit the data object.
13710 * @memberof Popper.Utils
13711 * @param {dataObject} data
13712 * @param {Array} modifiers
13713 * @param {String} ends - Optional modifier name used as stopper
13714 * @returns {dataObject}
13716 function runModifiers(modifiers, data, ends) {
13717 var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
13719 modifiersToRun.forEach(function (modifier) {
13720 if (modifier['function']) {
13721 // eslint-disable-line dot-notation
13722 console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
13724 var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
13725 if (modifier.enabled && isFunction(fn)) {
13726 // Add properties to offsets to make them a complete clientRect object
13727 // we do this before each modifier to make sure the previous one doesn't
13728 // mess with these values
13729 data.offsets.popper = getClientRect(data.offsets.popper);
13730 data.offsets.reference = getClientRect(data.offsets.reference);
13732 data = fn(data, modifier);
13740 * Updates the position of the popper, computing the new offsets and applying
13741 * the new style.<br />
13742 * Prefer `scheduleUpdate` over `update` because of performance reasons.
13746 function update() {
13747 // if popper is destroyed, don't perform any further update
13748 if (this.state.isDestroyed) {
13761 // compute reference element offsets
13762 data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
13764 // compute auto placement, store placement inside the data object,
13765 // modifiers will be able to edit `placement` if needed
13766 // and refer to originalPlacement to know the original value
13767 data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
13769 // store the computed placement inside `originalPlacement`
13770 data.originalPlacement = data.placement;
13772 data.positionFixed = this.options.positionFixed;
13774 // compute the popper offsets
13775 data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
13777 data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
13779 // run the modifiers
13780 data = runModifiers(this.modifiers, data);
13782 // the first `update` will call `onCreate` callback
13783 // the other ones will call `onUpdate` callback
13784 if (!this.state.isCreated) {
13785 this.state.isCreated = true;
13786 this.options.onCreate(data);
13788 this.options.onUpdate(data);
13793 * Helper used to know if the given modifier is enabled.
13795 * @memberof Popper.Utils
13796 * @returns {Boolean}
13798 function isModifierEnabled(modifiers, modifierName) {
13799 return modifiers.some(function (_ref) {
13800 var name = _ref.name,
13801 enabled = _ref.enabled;
13802 return enabled && name === modifierName;
13807 * Get the prefixed supported property name
13809 * @memberof Popper.Utils
13810 * @argument {String} property (camelCase)
13811 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
13813 function getSupportedPropertyName(property) {
13814 var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
13815 var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
13817 for (var i = 0; i < prefixes.length; i++) {
13818 var prefix = prefixes[i];
13819 var toCheck = prefix ? '' + prefix + upperProp : property;
13820 if (typeof document.body.style[toCheck] !== 'undefined') {
13828 * Destroys the popper.
13832 function destroy() {
13833 this.state.isDestroyed = true;
13835 // touch DOM only if `applyStyle` modifier is enabled
13836 if (isModifierEnabled(this.modifiers, 'applyStyle')) {
13837 this.popper.removeAttribute('x-placement');
13838 this.popper.style.position = '';
13839 this.popper.style.top = '';
13840 this.popper.style.left = '';
13841 this.popper.style.right = '';
13842 this.popper.style.bottom = '';
13843 this.popper.style.willChange = '';
13844 this.popper.style[getSupportedPropertyName('transform')] = '';
13847 this.disableEventListeners();
13849 // remove the popper if user explicitly asked for the deletion on destroy
13850 // do not use `remove` because IE11 doesn't support it
13851 if (this.options.removeOnDestroy) {
13852 this.popper.parentNode.removeChild(this.popper);
13858 * Get the window associated with the element
13859 * @argument {Element} element
13860 * @returns {Window}
13862 function getWindow(element) {
13863 var ownerDocument = element.ownerDocument;
13864 return ownerDocument ? ownerDocument.defaultView : window;
13867 function attachToScrollParents(scrollParent, event, callback, scrollParents) {
13868 var isBody = scrollParent.nodeName === 'BODY';
13869 var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
13870 target.addEventListener(event, callback, { passive: true });
13873 attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
13875 scrollParents.push(target);
13879 * Setup needed event listeners used to update the popper position
13881 * @memberof Popper.Utils
13884 function setupEventListeners(reference, options, state, updateBound) {
13885 // Resize event listener on window
13886 state.updateBound = updateBound;
13887 getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
13889 // Scroll event listener on scroll parents
13890 var scrollElement = getScrollParent(reference);
13891 attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
13892 state.scrollElement = scrollElement;
13893 state.eventsEnabled = true;
13899 * It will add resize/scroll events and start recalculating
13900 * position of the popper element when they are triggered.
13904 function enableEventListeners() {
13905 if (!this.state.eventsEnabled) {
13906 this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
13911 * Remove event listeners used to update the popper position
13913 * @memberof Popper.Utils
13916 function removeEventListeners(reference, state) {
13917 // Remove resize event listener on window
13918 getWindow(reference).removeEventListener('resize', state.updateBound);
13920 // Remove scroll event listener on scroll parents
13921 state.scrollParents.forEach(function (target) {
13922 target.removeEventListener('scroll', state.updateBound);
13926 state.updateBound = null;
13927 state.scrollParents = [];
13928 state.scrollElement = null;
13929 state.eventsEnabled = false;
13934 * It will remove resize/scroll events and won't recalculate popper position
13935 * when they are triggered. It also won't trigger `onUpdate` callback anymore,
13936 * unless you call `update` method manually.
13940 function disableEventListeners() {
13941 if (this.state.eventsEnabled) {
13942 cancelAnimationFrame(this.scheduleUpdate);
13943 this.state = removeEventListeners(this.reference, this.state);
13948 * Tells if a given input is a number
13950 * @memberof Popper.Utils
13951 * @param {*} input to check
13952 * @return {Boolean}
13954 function isNumeric(n) {
13955 return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
13959 * Set the style to the given popper
13961 * @memberof Popper.Utils
13962 * @argument {Element} element - Element to apply the style to
13963 * @argument {Object} styles
13964 * Object with a list of properties and values which will be applied to the element
13966 function setStyles(element, styles) {
13967 Object.keys(styles).forEach(function (prop) {
13969 // add unit if the value is numeric and is one of the following
13970 if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
13973 element.style[prop] = styles[prop] + unit;
13978 * Set the attributes to the given popper
13980 * @memberof Popper.Utils
13981 * @argument {Element} element - Element to apply the attributes to
13982 * @argument {Object} styles
13983 * Object with a list of properties and values which will be applied to the element
13985 function setAttributes(element, attributes) {
13986 Object.keys(attributes).forEach(function (prop) {
13987 var value = attributes[prop];
13988 if (value !== false) {
13989 element.setAttribute(prop, attributes[prop]);
13991 element.removeAttribute(prop);
13998 * @memberof Modifiers
13999 * @argument {Object} data - The data object generated by `update` method
14000 * @argument {Object} data.styles - List of style properties - values to apply to popper element
14001 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
14002 * @argument {Object} options - Modifiers configuration and options
14003 * @returns {Object} The same data object
14005 function applyStyle(data) {
14006 // any property present in `data.styles` will be applied to the popper,
14007 // in this way we can make the 3rd party modifiers add custom styles to it
14008 // Be aware, modifiers could override the properties defined in the previous
14009 // lines of this modifier!
14010 setStyles(data.instance.popper, data.styles);
14012 // any property present in `data.attributes` will be applied to the popper,
14013 // they will be set as HTML attributes of the element
14014 setAttributes(data.instance.popper, data.attributes);
14016 // if arrowElement is defined and arrowStyles has some properties
14017 if (data.arrowElement && Object.keys(data.arrowStyles).length) {
14018 setStyles(data.arrowElement, data.arrowStyles);
14025 * Set the x-placement attribute before everything else because it could be used
14026 * to add margins to the popper margins needs to be calculated to get the
14027 * correct popper offsets.
14029 * @memberof Popper.modifiers
14030 * @param {HTMLElement} reference - The reference element used to position the popper
14031 * @param {HTMLElement} popper - The HTML element used as popper
14032 * @param {Object} options - Popper.js options
14034 function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
14035 // compute reference element offsets
14036 var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
14038 // compute auto placement, store placement inside the data object,
14039 // modifiers will be able to edit `placement` if needed
14040 // and refer to originalPlacement to know the original value
14041 var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
14043 popper.setAttribute('x-placement', placement);
14045 // Apply `position` to popper before anything else because
14046 // without the position applied we can't guarantee correct computations
14047 setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
14054 * @memberof Popper.Utils
14055 * @argument {Object} data - The data object generated by `update` method
14056 * @argument {Boolean} shouldRound - If the offsets should be rounded at all
14057 * @returns {Object} The popper's position offsets rounded
14059 * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
14060 * good as it can be within reason.
14061 * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
14063 * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
14064 * as well on High DPI screens).
14066 * Firefox prefers no rounding for positioning and does not have blurriness on
14067 * high DPI screens.
14069 * Only horizontal placement and left/right values need to be considered.
14071 function getRoundedOffsets(data, shouldRound) {
14072 var _data$offsets = data.offsets,
14073 popper = _data$offsets.popper,
14074 reference = _data$offsets.reference;
14075 var round = Math.round,
14076 floor = Math.floor;
14078 var noRound = function noRound(v) {
14082 var referenceWidth = round(reference.width);
14083 var popperWidth = round(popper.width);
14085 var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
14086 var isVariation = data.placement.indexOf('-') !== -1;
14087 var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
14088 var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
14090 var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
14091 var verticalToInteger = !shouldRound ? noRound : round;
14094 left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
14095 top: verticalToInteger(popper.top),
14096 bottom: verticalToInteger(popper.bottom),
14097 right: horizontalToInteger(popper.right)
14101 var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
14105 * @memberof Modifiers
14106 * @argument {Object} data - The data object generated by `update` method
14107 * @argument {Object} options - Modifiers configuration and options
14108 * @returns {Object} The data object, properly modified
14110 function computeStyle(data, options) {
14113 var popper = data.offsets.popper;
14115 // Remove this legacy support in Popper.js v2
14117 var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
14118 return modifier.name === 'applyStyle';
14119 }).gpuAcceleration;
14120 if (legacyGpuAccelerationOption !== undefined) {
14121 console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
14123 var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
14125 var offsetParent = getOffsetParent(data.instance.popper);
14126 var offsetParentRect = getBoundingClientRect(offsetParent);
14130 position: popper.position
14133 var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
14135 var sideA = x === 'bottom' ? 'top' : 'bottom';
14136 var sideB = y === 'right' ? 'left' : 'right';
14138 // if gpuAcceleration is set to `true` and transform is supported,
14139 // we use `translate3d` to apply the position to the popper we
14140 // automatically use the supported prefixed version if needed
14141 var prefixedProperty = getSupportedPropertyName('transform');
14143 // now, let's make a step back and look at this code closely (wtf?)
14144 // If the content of the popper grows once it's been positioned, it
14145 // may happen that the popper gets misplaced because of the new content
14146 // overflowing its reference element
14147 // To avoid this problem, we provide two options (x and y), which allow
14148 // the consumer to define the offset origin.
14149 // If we position a popper on top of a reference element, we can set
14150 // `x` to `top` to make the popper grow towards its top instead of
14154 if (sideA === 'bottom') {
14155 // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
14156 // and not the bottom of the html element
14157 if (offsetParent.nodeName === 'HTML') {
14158 top = -offsetParent.clientHeight + offsets.bottom;
14160 top = -offsetParentRect.height + offsets.bottom;
14165 if (sideB === 'right') {
14166 if (offsetParent.nodeName === 'HTML') {
14167 left = -offsetParent.clientWidth + offsets.right;
14169 left = -offsetParentRect.width + offsets.right;
14172 left = offsets.left;
14174 if (gpuAcceleration && prefixedProperty) {
14175 styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
14178 styles.willChange = 'transform';
14180 // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
14181 var invertTop = sideA === 'bottom' ? -1 : 1;
14182 var invertLeft = sideB === 'right' ? -1 : 1;
14183 styles[sideA] = top * invertTop;
14184 styles[sideB] = left * invertLeft;
14185 styles.willChange = sideA + ', ' + sideB;
14190 'x-placement': data.placement
14193 // Update `data` attributes, styles and arrowStyles
14194 data.attributes = _extends$1({}, attributes, data.attributes);
14195 data.styles = _extends$1({}, styles, data.styles);
14196 data.arrowStyles = _extends$1({}, data.offsets.arrow, data.arrowStyles);
14202 * Helper used to know if the given modifier depends from another one.<br />
14203 * It checks if the needed modifier is listed and enabled.
14205 * @memberof Popper.Utils
14206 * @param {Array} modifiers - list of modifiers
14207 * @param {String} requestingName - name of requesting modifier
14208 * @param {String} requestedName - name of requested modifier
14209 * @returns {Boolean}
14211 function isModifierRequired(modifiers, requestingName, requestedName) {
14212 var requesting = find(modifiers, function (_ref) {
14213 var name = _ref.name;
14214 return name === requestingName;
14217 var isRequired = !!requesting && modifiers.some(function (modifier) {
14218 return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
14222 var _requesting = '`' + requestingName + '`';
14223 var requested = '`' + requestedName + '`';
14224 console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
14231 * @memberof Modifiers
14232 * @argument {Object} data - The data object generated by update method
14233 * @argument {Object} options - Modifiers configuration and options
14234 * @returns {Object} The data object, properly modified
14236 function arrow(data, options) {
14237 var _data$offsets$arrow;
14239 // arrow depends on keepTogether in order to work
14240 if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
14244 var arrowElement = options.element;
14246 // if arrowElement is a string, suppose it's a CSS selector
14247 if (typeof arrowElement === 'string') {
14248 arrowElement = data.instance.popper.querySelector(arrowElement);
14250 // if arrowElement is not found, don't run the modifier
14251 if (!arrowElement) {
14255 // if the arrowElement isn't a query selector we must check that the
14256 // provided DOM node is child of its popper node
14257 if (!data.instance.popper.contains(arrowElement)) {
14258 console.warn('WARNING: `arrow.element` must be child of its popper element!');
14263 var placement = data.placement.split('-')[0];
14264 var _data$offsets = data.offsets,
14265 popper = _data$offsets.popper,
14266 reference = _data$offsets.reference;
14268 var isVertical = ['left', 'right'].indexOf(placement) !== -1;
14270 var len = isVertical ? 'height' : 'width';
14271 var sideCapitalized = isVertical ? 'Top' : 'Left';
14272 var side = sideCapitalized.toLowerCase();
14273 var altSide = isVertical ? 'left' : 'top';
14274 var opSide = isVertical ? 'bottom' : 'right';
14275 var arrowElementSize = getOuterSizes(arrowElement)[len];
14278 // extends keepTogether behavior making sure the popper and its
14279 // reference have enough pixels in conjunction
14283 if (reference[opSide] - arrowElementSize < popper[side]) {
14284 data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
14286 // bottom/right side
14287 if (reference[side] + arrowElementSize > popper[opSide]) {
14288 data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
14290 data.offsets.popper = getClientRect(data.offsets.popper);
14292 // compute center of the popper
14293 var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
14295 // Compute the sideValue using the updated popper offsets
14296 // take popper margin in account because we don't have this info available
14297 var css = getStyleComputedProperty(data.instance.popper);
14298 var popperMarginSide = parseFloat(css['margin' + sideCapitalized]);
14299 var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width']);
14300 var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
14302 // prevent arrowElement from being placed not contiguously to its popper
14303 sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
14305 data.arrowElement = arrowElement;
14306 data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
14312 * Get the opposite placement variation of the given one
14314 * @memberof Popper.Utils
14315 * @argument {String} placement variation
14316 * @returns {String} flipped placement variation
14318 function getOppositeVariation(variation) {
14319 if (variation === 'end') {
14321 } else if (variation === 'start') {
14328 * List of accepted placements to use as values of the `placement` option.<br />
14329 * Valid placements are:
14336 * Each placement can have a variation from this list:
14340 * Variations are interpreted easily if you think of them as the left to right
14341 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
14343 * Vertically (`left` and `right`), `start` is top and `end` is bottom.
14345 * Some valid examples are:
14346 * - `top-end` (on top of reference, right aligned)
14347 * - `right-start` (on right of reference, top aligned)
14348 * - `bottom` (on bottom, centered)
14349 * - `auto-end` (on the side with more space available, alignment depends by placement)
14355 * @method placements
14358 var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];
14360 // Get rid of `auto` `auto-start` and `auto-end`
14361 var validPlacements = placements.slice(3);
14364 * Given an initial placement, returns all the subsequent placements
14365 * clockwise (or counter-clockwise).
14368 * @memberof Popper.Utils
14369 * @argument {String} placement - A valid placement (it accepts variations)
14370 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
14371 * @returns {Array} placements including their variations
14373 function clockwise(placement) {
14374 var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
14376 var index = validPlacements.indexOf(placement);
14377 var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
14378 return counter ? arr.reverse() : arr;
14383 CLOCKWISE: 'clockwise',
14384 COUNTERCLOCKWISE: 'counterclockwise'
14389 * @memberof Modifiers
14390 * @argument {Object} data - The data object generated by update method
14391 * @argument {Object} options - Modifiers configuration and options
14392 * @returns {Object} The data object, properly modified
14394 function flip(data, options) {
14395 // if `inner` modifier is enabled, we can't use the `flip` modifier
14396 if (isModifierEnabled(data.instance.modifiers, 'inner')) {
14400 if (data.flipped && data.placement === data.originalPlacement) {
14401 // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
14405 var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
14407 var placement = data.placement.split('-')[0];
14408 var placementOpposite = getOppositePlacement(placement);
14409 var variation = data.placement.split('-')[1] || '';
14411 var flipOrder = [];
14413 switch (options.behavior) {
14414 case BEHAVIORS.FLIP:
14415 flipOrder = [placement, placementOpposite];
14417 case BEHAVIORS.CLOCKWISE:
14418 flipOrder = clockwise(placement);
14420 case BEHAVIORS.COUNTERCLOCKWISE:
14421 flipOrder = clockwise(placement, true);
14424 flipOrder = options.behavior;
14427 flipOrder.forEach(function (step, index) {
14428 if (placement !== step || flipOrder.length === index + 1) {
14432 placement = data.placement.split('-')[0];
14433 placementOpposite = getOppositePlacement(placement);
14435 var popperOffsets = data.offsets.popper;
14436 var refOffsets = data.offsets.reference;
14438 // using floor because the reference offsets may contain decimals we are not going to consider here
14439 var floor = Math.floor;
14440 var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
14442 var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
14443 var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
14444 var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
14445 var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
14447 var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
14449 // flip the variation if required
14450 var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
14452 // flips variation if reference element overflows boundaries
14453 var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
14455 // flips variation if popper content overflows boundaries
14456 var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);
14458 var flippedVariation = flippedVariationByRef || flippedVariationByContent;
14460 if (overlapsRef || overflowsBoundaries || flippedVariation) {
14461 // this boolean to detect any flip loop
14462 data.flipped = true;
14464 if (overlapsRef || overflowsBoundaries) {
14465 placement = flipOrder[index + 1];
14468 if (flippedVariation) {
14469 variation = getOppositeVariation(variation);
14472 data.placement = placement + (variation ? '-' + variation : '');
14474 // this object contains `position`, we want to preserve it along with
14475 // any additional property we may add in the future
14476 data.offsets.popper = _extends$1({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
14478 data = runModifiers(data.instance.modifiers, data, 'flip');
14486 * @memberof Modifiers
14487 * @argument {Object} data - The data object generated by update method
14488 * @argument {Object} options - Modifiers configuration and options
14489 * @returns {Object} The data object, properly modified
14491 function keepTogether(data) {
14492 var _data$offsets = data.offsets,
14493 popper = _data$offsets.popper,
14494 reference = _data$offsets.reference;
14496 var placement = data.placement.split('-')[0];
14497 var floor = Math.floor;
14498 var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
14499 var side = isVertical ? 'right' : 'bottom';
14500 var opSide = isVertical ? 'left' : 'top';
14501 var measurement = isVertical ? 'width' : 'height';
14503 if (popper[side] < floor(reference[opSide])) {
14504 data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
14506 if (popper[opSide] > floor(reference[side])) {
14507 data.offsets.popper[opSide] = floor(reference[side]);
14514 * Converts a string containing value + unit into a px value number
14516 * @memberof {modifiers~offset}
14518 * @argument {String} str - Value + unit string
14519 * @argument {String} measurement - `height` or `width`
14520 * @argument {Object} popperOffsets
14521 * @argument {Object} referenceOffsets
14522 * @returns {Number|String}
14523 * Value in pixels, or original string if no values were extracted
14525 function toValue(str, measurement, popperOffsets, referenceOffsets) {
14526 // separate value from unit
14527 var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
14528 var value = +split[1];
14529 var unit = split[2];
14531 // If it's not a number it's an operator, I guess
14536 if (unit.indexOf('%') === 0) {
14537 var element = void 0;
14540 element = popperOffsets;
14545 element = referenceOffsets;
14548 var rect = getClientRect(element);
14549 return rect[measurement] / 100 * value;
14550 } else if (unit === 'vh' || unit === 'vw') {
14551 // if is a vh or vw, we calculate the size based on the viewport
14553 if (unit === 'vh') {
14554 size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
14556 size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
14558 return size / 100 * value;
14560 // if is an explicit pixel unit, we get rid of the unit and keep the value
14561 // if is an implicit unit, it's px, and we return just the value
14567 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
14569 * @memberof {modifiers~offset}
14571 * @argument {String} offset
14572 * @argument {Object} popperOffsets
14573 * @argument {Object} referenceOffsets
14574 * @argument {String} basePlacement
14575 * @returns {Array} a two cells array with x and y offsets in numbers
14577 function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
14578 var offsets = [0, 0];
14580 // Use height if placement is left or right and index is 0 otherwise use width
14581 // in this way the first offset will use an axis and the second one
14582 // will use the other one
14583 var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
14585 // Split the offset string to obtain a list of values and operands
14586 // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
14587 var fragments = offset.split(/(\+|\-)/).map(function (frag) {
14588 return frag.trim();
14591 // Detect if the offset string contains a pair of values or a single one
14592 // they could be separated by comma or space
14593 var divider = fragments.indexOf(find(fragments, function (frag) {
14594 return frag.search(/,|\s/) !== -1;
14597 if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
14598 console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
14601 // If divider is found, we divide the list of values and operands to divide
14602 // them by ofset X and Y.
14603 var splitRegex = /\s*,\s*|\s+/;
14604 var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
14606 // Convert the values with units to absolute pixels to allow our computations
14607 ops = ops.map(function (op, index) {
14608 // Most of the units rely on the orientation of the popper
14609 var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
14610 var mergeWithPrevious = false;
14612 // This aggregates any `+` or `-` sign that aren't considered operators
14613 // e.g.: 10 + +5 => [10, +, +5]
14614 .reduce(function (a, b) {
14615 if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
14616 a[a.length - 1] = b;
14617 mergeWithPrevious = true;
14619 } else if (mergeWithPrevious) {
14620 a[a.length - 1] += b;
14621 mergeWithPrevious = false;
14624 return a.concat(b);
14627 // Here we convert the string values into number values (in px)
14628 .map(function (str) {
14629 return toValue(str, measurement, popperOffsets, referenceOffsets);
14633 // Loop trough the offsets arrays and execute the operations
14634 ops.forEach(function (op, index) {
14635 op.forEach(function (frag, index2) {
14636 if (isNumeric(frag)) {
14637 offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
14646 * @memberof Modifiers
14647 * @argument {Object} data - The data object generated by update method
14648 * @argument {Object} options - Modifiers configuration and options
14649 * @argument {Number|String} options.offset=0
14650 * The offset value as described in the modifier description
14651 * @returns {Object} The data object, properly modified
14653 function offset(data, _ref) {
14654 var offset = _ref.offset;
14655 var placement = data.placement,
14656 _data$offsets = data.offsets,
14657 popper = _data$offsets.popper,
14658 reference = _data$offsets.reference;
14660 var basePlacement = placement.split('-')[0];
14662 var offsets = void 0;
14663 if (isNumeric(+offset)) {
14664 offsets = [+offset, 0];
14666 offsets = parseOffset(offset, popper, reference, basePlacement);
14669 if (basePlacement === 'left') {
14670 popper.top += offsets[0];
14671 popper.left -= offsets[1];
14672 } else if (basePlacement === 'right') {
14673 popper.top += offsets[0];
14674 popper.left += offsets[1];
14675 } else if (basePlacement === 'top') {
14676 popper.left += offsets[0];
14677 popper.top -= offsets[1];
14678 } else if (basePlacement === 'bottom') {
14679 popper.left += offsets[0];
14680 popper.top += offsets[1];
14683 data.popper = popper;
14689 * @memberof Modifiers
14690 * @argument {Object} data - The data object generated by `update` method
14691 * @argument {Object} options - Modifiers configuration and options
14692 * @returns {Object} The data object, properly modified
14694 function preventOverflow(data, options) {
14695 var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
14697 // If offsetParent is the reference element, we really want to
14698 // go one step up and use the next offsetParent as reference to
14699 // avoid to make this modifier completely useless and look like broken
14700 if (data.instance.reference === boundariesElement) {
14701 boundariesElement = getOffsetParent(boundariesElement);
14704 // NOTE: DOM access here
14705 // resets the popper's position so that the document size can be calculated excluding
14706 // the size of the popper element itself
14707 var transformProp = getSupportedPropertyName('transform');
14708 var popperStyles = data.instance.popper.style; // assignment to help minification
14709 var top = popperStyles.top,
14710 left = popperStyles.left,
14711 transform = popperStyles[transformProp];
14713 popperStyles.top = '';
14714 popperStyles.left = '';
14715 popperStyles[transformProp] = '';
14717 var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
14719 // NOTE: DOM access here
14720 // restores the original style properties after the offsets have been computed
14721 popperStyles.top = top;
14722 popperStyles.left = left;
14723 popperStyles[transformProp] = transform;
14725 options.boundaries = boundaries;
14727 var order = options.priority;
14728 var popper = data.offsets.popper;
14731 primary: function primary(placement) {
14732 var value = popper[placement];
14733 if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
14734 value = Math.max(popper[placement], boundaries[placement]);
14736 return defineProperty({}, placement, value);
14738 secondary: function secondary(placement) {
14739 var mainSide = placement === 'right' ? 'left' : 'top';
14740 var value = popper[mainSide];
14741 if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
14742 value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
14744 return defineProperty({}, mainSide, value);
14748 order.forEach(function (placement) {
14749 var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
14750 popper = _extends$1({}, popper, check[side](placement));
14753 data.offsets.popper = popper;
14760 * @memberof Modifiers
14761 * @argument {Object} data - The data object generated by `update` method
14762 * @argument {Object} options - Modifiers configuration and options
14763 * @returns {Object} The data object, properly modified
14765 function shift(data) {
14766 var placement = data.placement;
14767 var basePlacement = placement.split('-')[0];
14768 var shiftvariation = placement.split('-')[1];
14770 // if shift shiftvariation is specified, run the modifier
14771 if (shiftvariation) {
14772 var _data$offsets = data.offsets,
14773 reference = _data$offsets.reference,
14774 popper = _data$offsets.popper;
14776 var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
14777 var side = isVertical ? 'left' : 'top';
14778 var measurement = isVertical ? 'width' : 'height';
14780 var shiftOffsets = {
14781 start: defineProperty({}, side, reference[side]),
14782 end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
14785 data.offsets.popper = _extends$1({}, popper, shiftOffsets[shiftvariation]);
14793 * @memberof Modifiers
14794 * @argument {Object} data - The data object generated by update method
14795 * @argument {Object} options - Modifiers configuration and options
14796 * @returns {Object} The data object, properly modified
14798 function hide(data) {
14799 if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
14803 var refRect = data.offsets.reference;
14804 var bound = find(data.instance.modifiers, function (modifier) {
14805 return modifier.name === 'preventOverflow';
14808 if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
14809 // Avoid unnecessary DOM access if visibility hasn't changed
14810 if (data.hide === true) {
14815 data.attributes['x-out-of-boundaries'] = '';
14817 // Avoid unnecessary DOM access if visibility hasn't changed
14818 if (data.hide === false) {
14823 data.attributes['x-out-of-boundaries'] = false;
14831 * @memberof Modifiers
14832 * @argument {Object} data - The data object generated by `update` method
14833 * @argument {Object} options - Modifiers configuration and options
14834 * @returns {Object} The data object, properly modified
14836 function inner(data) {
14837 var placement = data.placement;
14838 var basePlacement = placement.split('-')[0];
14839 var _data$offsets = data.offsets,
14840 popper = _data$offsets.popper,
14841 reference = _data$offsets.reference;
14843 var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
14845 var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
14847 popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
14849 data.placement = getOppositePlacement(placement);
14850 data.offsets.popper = getClientRect(popper);
14856 * Modifier function, each modifier can have a function of this type assigned
14857 * to its `fn` property.<br />
14858 * These functions will be called on each update, this means that you must
14859 * make sure they are performant enough to avoid performance bottlenecks.
14861 * @function ModifierFn
14862 * @argument {dataObject} data - The data object generated by `update` method
14863 * @argument {Object} options - Modifiers configuration and options
14864 * @returns {dataObject} The data object, properly modified
14868 * Modifiers are plugins used to alter the behavior of your poppers.<br />
14869 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
14870 * needed by the library.
14872 * Usually you don't want to override the `order`, `fn` and `onLoad` props.
14873 * All the other properties are configurations that could be tweaked.
14874 * @namespace modifiers
14878 * Modifier used to shift the popper on the start or end of its reference
14880 * It will read the variation of the `placement` property.<br />
14881 * It can be one either `-end` or `-start`.
14882 * @memberof modifiers
14886 /** @prop {number} order=100 - Index used to define the order of execution */
14888 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
14890 /** @prop {ModifierFn} */
14895 * The `offset` modifier can shift your popper on both its axis.
14897 * It accepts the following units:
14898 * - `px` or unit-less, interpreted as pixels
14899 * - `%` or `%r`, percentage relative to the length of the reference element
14900 * - `%p`, percentage relative to the length of the popper element
14901 * - `vw`, CSS viewport width unit
14902 * - `vh`, CSS viewport height unit
14904 * For length is intended the main axis relative to the placement of the popper.<br />
14905 * This means that if the placement is `top` or `bottom`, the length will be the
14906 * `width`. In case of `left` or `right`, it will be the `height`.
14908 * You can provide a single value (as `Number` or `String`), or a pair of values
14909 * as `String` divided by a comma or one (or more) white spaces.<br />
14910 * The latter is a deprecated method because it leads to confusion and will be
14911 * removed in v2.<br />
14912 * Additionally, it accepts additions and subtractions between different units.
14913 * Note that multiplications and divisions aren't supported.
14915 * Valid examples are:
14923 * '-10px + 5vh, 5px - 6%'
14925 * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
14926 * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
14927 * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
14929 * @memberof modifiers
14933 /** @prop {number} order=200 - Index used to define the order of execution */
14935 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
14937 /** @prop {ModifierFn} */
14939 /** @prop {Number|String} offset=0
14940 * The offset value as described in the modifier description
14946 * Modifier used to prevent the popper from being positioned outside the boundary.
14948 * A scenario exists where the reference itself is not within the boundaries.<br />
14949 * We can say it has "escaped the boundaries" — or just "escaped".<br />
14950 * In this case we need to decide whether the popper should either:
14952 * - detach from the reference and remain "trapped" in the boundaries, or
14953 * - if it should ignore the boundary and "escape with its reference"
14955 * When `escapeWithReference` is set to`true` and reference is completely
14956 * outside its boundaries, the popper will overflow (or completely leave)
14957 * the boundaries in order to remain attached to the edge of the reference.
14959 * @memberof modifiers
14963 /** @prop {number} order=300 - Index used to define the order of execution */
14965 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
14967 /** @prop {ModifierFn} */
14968 fn: preventOverflow,
14970 * @prop {Array} [priority=['left','right','top','bottom']]
14971 * Popper will try to prevent overflow following these priorities by default,
14972 * then, it could overflow on the left and on top of the `boundariesElement`
14974 priority: ['left', 'right', 'top', 'bottom'],
14976 * @prop {number} padding=5
14977 * Amount of pixel used to define a minimum distance between the boundaries
14978 * and the popper. This makes sure the popper always has a little padding
14979 * between the edges of its container
14983 * @prop {String|HTMLElement} boundariesElement='scrollParent'
14984 * Boundaries used by the modifier. Can be `scrollParent`, `window`,
14985 * `viewport` or any DOM element.
14987 boundariesElement: 'scrollParent'
14991 * Modifier used to make sure the reference and its popper stay near each other
14992 * without leaving any gap between the two. Especially useful when the arrow is
14993 * enabled and you want to ensure that it points to its reference element.
14994 * It cares only about the first axis. You can still have poppers with margin
14995 * between the popper and its reference element.
14996 * @memberof modifiers
15000 /** @prop {number} order=400 - Index used to define the order of execution */
15002 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
15004 /** @prop {ModifierFn} */
15009 * This modifier is used to move the `arrowElement` of the popper to make
15010 * sure it is positioned between the reference element and its popper element.
15011 * It will read the outer size of the `arrowElement` node to detect how many
15012 * pixels of conjunction are needed.
15014 * It has no effect if no `arrowElement` is provided.
15015 * @memberof modifiers
15019 /** @prop {number} order=500 - Index used to define the order of execution */
15021 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
15023 /** @prop {ModifierFn} */
15025 /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
15026 element: '[x-arrow]'
15030 * Modifier used to flip the popper's placement when it starts to overlap its
15031 * reference element.
15033 * Requires the `preventOverflow` modifier before it in order to work.
15035 * **NOTE:** this modifier will interrupt the current update cycle and will
15036 * restart it if it detects the need to flip the placement.
15037 * @memberof modifiers
15041 /** @prop {number} order=600 - Index used to define the order of execution */
15043 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
15045 /** @prop {ModifierFn} */
15048 * @prop {String|Array} behavior='flip'
15049 * The behavior used to change the popper's placement. It can be one of
15050 * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
15051 * placements (with optional variations)
15055 * @prop {number} padding=5
15056 * The popper will flip if it hits the edges of the `boundariesElement`
15060 * @prop {String|HTMLElement} boundariesElement='viewport'
15061 * The element which will define the boundaries of the popper position.
15062 * The popper will never be placed outside of the defined boundaries
15063 * (except if `keepTogether` is enabled)
15065 boundariesElement: 'viewport',
15067 * @prop {Boolean} flipVariations=false
15068 * The popper will switch placement variation between `-start` and `-end` when
15069 * the reference element overlaps its boundaries.
15071 * The original placement should have a set variation.
15073 flipVariations: false,
15075 * @prop {Boolean} flipVariationsByContent=false
15076 * The popper will switch placement variation between `-start` and `-end` when
15077 * the popper element overlaps its reference boundaries.
15079 * The original placement should have a set variation.
15081 flipVariationsByContent: false
15085 * Modifier used to make the popper flow toward the inner of the reference element.
15086 * By default, when this modifier is disabled, the popper will be placed outside
15087 * the reference element.
15088 * @memberof modifiers
15092 /** @prop {number} order=700 - Index used to define the order of execution */
15094 /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
15096 /** @prop {ModifierFn} */
15101 * Modifier used to hide the popper when its reference element is outside of the
15102 * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
15103 * be used to hide with a CSS selector the popper when its reference is
15104 * out of boundaries.
15106 * Requires the `preventOverflow` modifier before it in order to work.
15107 * @memberof modifiers
15111 /** @prop {number} order=800 - Index used to define the order of execution */
15113 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
15115 /** @prop {ModifierFn} */
15120 * Computes the style that will be applied to the popper element to gets
15121 * properly positioned.
15123 * Note that this modifier will not touch the DOM, it just prepares the styles
15124 * so that `applyStyle` modifier can apply it. This separation is useful
15125 * in case you need to replace `applyStyle` with a custom implementation.
15127 * This modifier has `850` as `order` value to maintain backward compatibility
15128 * with previous versions of Popper.js. Expect the modifiers ordering method
15129 * to change in future major versions of the library.
15131 * @memberof modifiers
15135 /** @prop {number} order=850 - Index used to define the order of execution */
15137 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
15139 /** @prop {ModifierFn} */
15142 * @prop {Boolean} gpuAcceleration=true
15143 * If true, it uses the CSS 3D transformation to position the popper.
15144 * Otherwise, it will use the `top` and `left` properties
15146 gpuAcceleration: true,
15148 * @prop {string} [x='bottom']
15149 * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
15150 * Change this if your popper should grow in a direction different from `bottom`
15154 * @prop {string} [x='left']
15155 * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
15156 * Change this if your popper should grow in a direction different from `right`
15162 * Applies the computed styles to the popper element.
15164 * All the DOM manipulations are limited to this modifier. This is useful in case
15165 * you want to integrate Popper.js inside a framework or view library and you
15166 * want to delegate all the DOM manipulations to it.
15168 * Note that if you disable this modifier, you must make sure the popper element
15169 * has its position set to `absolute` before Popper.js can do its work!
15171 * Just disable this modifier and define your own to achieve the desired effect.
15173 * @memberof modifiers
15177 /** @prop {number} order=900 - Index used to define the order of execution */
15179 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
15181 /** @prop {ModifierFn} */
15183 /** @prop {Function} */
15184 onLoad: applyStyleOnLoad,
15186 * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
15187 * @prop {Boolean} gpuAcceleration=true
15188 * If true, it uses the CSS 3D transformation to position the popper.
15189 * Otherwise, it will use the `top` and `left` properties
15191 gpuAcceleration: undefined
15196 * The `dataObject` is an object containing all the information used by Popper.js.
15197 * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
15199 * @property {Object} data.instance The Popper.js instance
15200 * @property {String} data.placement Placement applied to popper
15201 * @property {String} data.originalPlacement Placement originally defined on init
15202 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
15203 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
15204 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
15205 * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
15206 * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
15207 * @property {Object} data.boundaries Offsets of the popper boundaries
15208 * @property {Object} data.offsets The measurements of popper, reference and arrow elements
15209 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
15210 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
15211 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
15215 * Default options provided to Popper.js constructor.<br />
15216 * These can be overridden using the `options` argument of Popper.js.<br />
15217 * To override an option, simply pass an object with the same
15218 * structure of the `options` object, as the 3rd argument. For example:
15220 * new Popper(ref, pop, {
15222 * preventOverflow: { enabled: false }
15232 * Popper's placement.
15233 * @prop {Popper.placements} placement='bottom'
15235 placement: 'bottom',
15238 * Set this to true if you want popper to position it self in 'fixed' mode
15239 * @prop {Boolean} positionFixed=false
15241 positionFixed: false,
15244 * Whether events (resize, scroll) are initially enabled.
15245 * @prop {Boolean} eventsEnabled=true
15247 eventsEnabled: true,
15250 * Set to true if you want to automatically remove the popper when
15251 * you call the `destroy` method.
15252 * @prop {Boolean} removeOnDestroy=false
15254 removeOnDestroy: false,
15257 * Callback called when the popper is created.<br />
15258 * By default, it is set to no-op.<br />
15259 * Access Popper.js instance with `data.instance`.
15262 onCreate: function onCreate() {},
15265 * Callback called when the popper is updated. This callback is not called
15266 * on the initialization/creation of the popper, but only on subsequent
15268 * By default, it is set to no-op.<br />
15269 * Access Popper.js instance with `data.instance`.
15272 onUpdate: function onUpdate() {},
15275 * List of modifiers used to modify the offsets before they are applied to the popper.
15276 * They provide most of the functionalities of Popper.js.
15277 * @prop {modifiers}
15279 modifiers: modifiers
15283 * @callback onCreate
15284 * @param {dataObject} data
15288 * @callback onUpdate
15289 * @param {dataObject} data
15294 var Popper = function () {
15296 * Creates a new Popper.js instance.
15298 * @param {Element|referenceObject} reference - The reference element used to position the popper
15299 * @param {Element} popper - The HTML / XML element used as the popper
15300 * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
15301 * @return {Object} instance - The generated Popper.js instance
15303 function Popper(reference, popper) {
15306 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
15307 classCallCheck(this, Popper);
15309 this.scheduleUpdate = function () {
15310 return requestAnimationFrame(_this.update);
15313 // make update() debounced, so that it only runs at most once-per-tick
15314 this.update = debounce(this.update.bind(this));
15316 // with {} we create a new object with the options inside it
15317 this.options = _extends$1({}, Popper.Defaults, options);
15321 isDestroyed: false,
15326 // get reference and popper elements (allow jQuery wrappers)
15327 this.reference = reference && reference.jquery ? reference[0] : reference;
15328 this.popper = popper && popper.jquery ? popper[0] : popper;
15330 // Deep merge modifiers options
15331 this.options.modifiers = {};
15332 Object.keys(_extends$1({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
15333 _this.options.modifiers[name] = _extends$1({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
15336 // Refactoring modifiers' list (Object => Array)
15337 this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
15338 return _extends$1({
15340 }, _this.options.modifiers[name]);
15342 // sort the modifiers by order
15343 .sort(function (a, b) {
15344 return a.order - b.order;
15347 // modifiers have the ability to execute arbitrary code when Popper.js get inited
15348 // such code is executed in the same order of its modifier
15349 // they could add new properties to their options configuration
15350 // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
15351 this.modifiers.forEach(function (modifierOptions) {
15352 if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
15353 modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
15357 // fire the first update to position the popper in the right place
15360 var eventsEnabled = this.options.eventsEnabled;
15361 if (eventsEnabled) {
15362 // setup event listeners, they will take care of update the position in specific situations
15363 this.enableEventListeners();
15366 this.state.eventsEnabled = eventsEnabled;
15369 // We can't use class properties because they don't get listed in the
15370 // class prototype and break stuff like Sinon stubs
15373 createClass(Popper, [{
15375 value: function update$$1() {
15376 return update.call(this);
15380 value: function destroy$$1() {
15381 return destroy.call(this);
15384 key: 'enableEventListeners',
15385 value: function enableEventListeners$$1() {
15386 return enableEventListeners.call(this);
15389 key: 'disableEventListeners',
15390 value: function disableEventListeners$$1() {
15391 return disableEventListeners.call(this);
15395 * Schedules an update. It will run on the next UI update available.
15396 * @method scheduleUpdate
15402 * Collection of utilities useful when writing custom modifiers.
15403 * Starting from version 1.7, this method is available only if you
15404 * include `popper-utils.js` before `popper.js`.
15406 * **DEPRECATION**: This way to access PopperUtils is deprecated
15407 * and will be removed in v2! Use the PopperUtils module directly instead.
15408 * Due to the high instability of the methods contained in Utils, we can't
15409 * guarantee them to follow semver. Use them at your own risk!
15413 * @deprecated since version 1.8
15423 * The `referenceObject` is an object that provides an interface compatible with Popper.js
15424 * and lets you use it as replacement of a real DOM node.<br />
15425 * You can use this method to position a popper relatively to a set of coordinates
15426 * in case you don't have a DOM node to use as reference.
15429 * new Popper(referenceObject, popperNode);
15432 * NB: This feature isn't supported in Internet Explorer 10.
15433 * @name referenceObject
15434 * @property {Function} data.getBoundingClientRect
15435 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
15436 * @property {number} data.clientWidth
15437 * An ES6 getter that will return the width of the virtual reference element.
15438 * @property {number} data.clientHeight
15439 * An ES6 getter that will return the height of the virtual reference element.
15443 Popper.Utils = (typeof window !== 'undefined' ? window : commonjsGlobal).PopperUtils;
15444 Popper.placements = placements;
15445 Popper.Defaults = Defaults;
15448 * ------------------------------------------------------------------------
15450 * ------------------------------------------------------------------------
15453 var NAME$4 = 'dropdown';
15454 var VERSION$4 = '4.6.0';
15455 var DATA_KEY$4 = 'bs.dropdown';
15456 var EVENT_KEY$4 = "." + DATA_KEY$4;
15457 var DATA_API_KEY$4 = '.data-api';
15458 var JQUERY_NO_CONFLICT$4 = $__default['default'].fn[NAME$4];
15459 var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
15461 var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
15463 var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key
15465 var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
15467 var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
15469 var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
15471 var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE);
15472 var EVENT_HIDE$1 = "hide" + EVENT_KEY$4;
15473 var EVENT_HIDDEN$1 = "hidden" + EVENT_KEY$4;
15474 var EVENT_SHOW$1 = "show" + EVENT_KEY$4;
15475 var EVENT_SHOWN$1 = "shown" + EVENT_KEY$4;
15476 var EVENT_CLICK = "click" + EVENT_KEY$4;
15477 var EVENT_CLICK_DATA_API$4 = "click" + EVENT_KEY$4 + DATA_API_KEY$4;
15478 var EVENT_KEYDOWN_DATA_API = "keydown" + EVENT_KEY$4 + DATA_API_KEY$4;
15479 var EVENT_KEYUP_DATA_API = "keyup" + EVENT_KEY$4 + DATA_API_KEY$4;
15480 var CLASS_NAME_DISABLED = 'disabled';
15481 var CLASS_NAME_SHOW$2 = 'show';
15482 var CLASS_NAME_DROPUP = 'dropup';
15483 var CLASS_NAME_DROPRIGHT = 'dropright';
15484 var CLASS_NAME_DROPLEFT = 'dropleft';
15485 var CLASS_NAME_MENURIGHT = 'dropdown-menu-right';
15486 var CLASS_NAME_POSITION_STATIC = 'position-static';
15487 var SELECTOR_DATA_TOGGLE$2 = '[data-toggle="dropdown"]';
15488 var SELECTOR_FORM_CHILD = '.dropdown form';
15489 var SELECTOR_MENU = '.dropdown-menu';
15490 var SELECTOR_NAVBAR_NAV = '.navbar-nav';
15491 var SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';
15492 var PLACEMENT_TOP = 'top-start';
15493 var PLACEMENT_TOPEND = 'top-end';
15494 var PLACEMENT_BOTTOM = 'bottom-start';
15495 var PLACEMENT_BOTTOMEND = 'bottom-end';
15496 var PLACEMENT_RIGHT = 'right-start';
15497 var PLACEMENT_LEFT = 'left-start';
15501 boundary: 'scrollParent',
15502 reference: 'toggle',
15503 display: 'dynamic',
15506 var DefaultType$2 = {
15507 offset: '(number|string|function)',
15509 boundary: '(string|element)',
15510 reference: '(string|element)',
15512 popperConfig: '(null|object)'
15515 * ------------------------------------------------------------------------
15517 * ------------------------------------------------------------------------
15520 var Dropdown = /*#__PURE__*/function () {
15521 function Dropdown(element, config) {
15522 this._element = element;
15523 this._popper = null;
15524 this._config = this._getConfig(config);
15525 this._menu = this._getMenuElement();
15526 this._inNavbar = this._detectNavbar();
15528 this._addEventListeners();
15532 var _proto = Dropdown.prototype;
15535 _proto.toggle = function toggle() {
15536 if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED)) {
15540 var isActive = $__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2);
15542 Dropdown._clearMenus();
15551 _proto.show = function show(usePopper) {
15552 if (usePopper === void 0) {
15556 if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED) || $__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2)) {
15560 var relatedTarget = {
15561 relatedTarget: this._element
15563 var showEvent = $__default['default'].Event(EVENT_SHOW$1, relatedTarget);
15565 var parent = Dropdown._getParentFromElement(this._element);
15567 $__default['default'](parent).trigger(showEvent);
15569 if (showEvent.isDefaultPrevented()) {
15571 } // Totally disable Popper for Dropdowns in Navbar
15574 if (!this._inNavbar && usePopper) {
15576 * Check for Popper dependency
15577 * Popper - https://popper.js.org
15579 if (typeof Popper === 'undefined') {
15580 throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
15583 var referenceElement = this._element;
15585 if (this._config.reference === 'parent') {
15586 referenceElement = parent;
15587 } else if (Util.isElement(this._config.reference)) {
15588 referenceElement = this._config.reference; // Check if it's jQuery element
15590 if (typeof this._config.reference.jquery !== 'undefined') {
15591 referenceElement = this._config.reference[0];
15593 } // If boundary is not `scrollParent`, then set position to `static`
15594 // to allow the menu to "escape" the scroll parent's boundaries
15595 // https://github.com/twbs/bootstrap/issues/24251
15598 if (this._config.boundary !== 'scrollParent') {
15599 $__default['default'](parent).addClass(CLASS_NAME_POSITION_STATIC);
15602 this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig());
15603 } // If this is a touch-enabled device we add extra
15604 // empty mouseover listeners to the body's immediate children;
15605 // only needed because of broken event delegation on iOS
15606 // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
15609 if ('ontouchstart' in document.documentElement && $__default['default'](parent).closest(SELECTOR_NAVBAR_NAV).length === 0) {
15610 $__default['default'](document.body).children().on('mouseover', null, $__default['default'].noop);
15613 this._element.focus();
15615 this._element.setAttribute('aria-expanded', true);
15617 $__default['default'](this._menu).toggleClass(CLASS_NAME_SHOW$2);
15618 $__default['default'](parent).toggleClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_SHOWN$1, relatedTarget));
15621 _proto.hide = function hide() {
15622 if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED) || !$__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2)) {
15626 var relatedTarget = {
15627 relatedTarget: this._element
15629 var hideEvent = $__default['default'].Event(EVENT_HIDE$1, relatedTarget);
15631 var parent = Dropdown._getParentFromElement(this._element);
15633 $__default['default'](parent).trigger(hideEvent);
15635 if (hideEvent.isDefaultPrevented()) {
15639 if (this._popper) {
15640 this._popper.destroy();
15643 $__default['default'](this._menu).toggleClass(CLASS_NAME_SHOW$2);
15644 $__default['default'](parent).toggleClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_HIDDEN$1, relatedTarget));
15647 _proto.dispose = function dispose() {
15648 $__default['default'].removeData(this._element, DATA_KEY$4);
15649 $__default['default'](this._element).off(EVENT_KEY$4);
15650 this._element = null;
15653 if (this._popper !== null) {
15654 this._popper.destroy();
15656 this._popper = null;
15660 _proto.update = function update() {
15661 this._inNavbar = this._detectNavbar();
15663 if (this._popper !== null) {
15664 this._popper.scheduleUpdate();
15669 _proto._addEventListeners = function _addEventListeners() {
15672 $__default['default'](this._element).on(EVENT_CLICK, function (event) {
15673 event.preventDefault();
15674 event.stopPropagation();
15680 _proto._getConfig = function _getConfig(config) {
15681 config = _extends({}, this.constructor.Default, $__default['default'](this._element).data(), config);
15682 Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType);
15686 _proto._getMenuElement = function _getMenuElement() {
15688 var parent = Dropdown._getParentFromElement(this._element);
15691 this._menu = parent.querySelector(SELECTOR_MENU);
15698 _proto._getPlacement = function _getPlacement() {
15699 var $parentDropdown = $__default['default'](this._element.parentNode);
15700 var placement = PLACEMENT_BOTTOM; // Handle dropup
15702 if ($parentDropdown.hasClass(CLASS_NAME_DROPUP)) {
15703 placement = $__default['default'](this._menu).hasClass(CLASS_NAME_MENURIGHT) ? PLACEMENT_TOPEND : PLACEMENT_TOP;
15704 } else if ($parentDropdown.hasClass(CLASS_NAME_DROPRIGHT)) {
15705 placement = PLACEMENT_RIGHT;
15706 } else if ($parentDropdown.hasClass(CLASS_NAME_DROPLEFT)) {
15707 placement = PLACEMENT_LEFT;
15708 } else if ($__default['default'](this._menu).hasClass(CLASS_NAME_MENURIGHT)) {
15709 placement = PLACEMENT_BOTTOMEND;
15715 _proto._detectNavbar = function _detectNavbar() {
15716 return $__default['default'](this._element).closest('.navbar').length > 0;
15719 _proto._getOffset = function _getOffset() {
15724 if (typeof this._config.offset === 'function') {
15725 offset.fn = function (data) {
15726 data.offsets = _extends({}, data.offsets, _this2._config.offset(data.offsets, _this2._element) || {});
15730 offset.offset = this._config.offset;
15736 _proto._getPopperConfig = function _getPopperConfig() {
15737 var popperConfig = {
15738 placement: this._getPlacement(),
15740 offset: this._getOffset(),
15742 enabled: this._config.flip
15745 boundariesElement: this._config.boundary
15748 }; // Disable Popper if we have a static display
15750 if (this._config.display === 'static') {
15751 popperConfig.modifiers.applyStyle = {
15756 return _extends({}, popperConfig, this._config.popperConfig);
15760 Dropdown._jQueryInterface = function _jQueryInterface(config) {
15761 return this.each(function () {
15762 var data = $__default['default'](this).data(DATA_KEY$4);
15764 var _config = typeof config === 'object' ? config : null;
15767 data = new Dropdown(this, _config);
15768 $__default['default'](this).data(DATA_KEY$4, data);
15771 if (typeof config === 'string') {
15772 if (typeof data[config] === 'undefined') {
15773 throw new TypeError("No method named \"" + config + "\"");
15781 Dropdown._clearMenus = function _clearMenus(event) {
15782 if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
15786 var toggles = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE$2));
15788 for (var i = 0, len = toggles.length; i < len; i++) {
15789 var parent = Dropdown._getParentFromElement(toggles[i]);
15791 var context = $__default['default'](toggles[i]).data(DATA_KEY$4);
15792 var relatedTarget = {
15793 relatedTarget: toggles[i]
15796 if (event && event.type === 'click') {
15797 relatedTarget.clickEvent = event;
15804 var dropdownMenu = context._menu;
15806 if (!$__default['default'](parent).hasClass(CLASS_NAME_SHOW$2)) {
15810 if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $__default['default'].contains(parent, event.target)) {
15814 var hideEvent = $__default['default'].Event(EVENT_HIDE$1, relatedTarget);
15815 $__default['default'](parent).trigger(hideEvent);
15817 if (hideEvent.isDefaultPrevented()) {
15819 } // If this is a touch-enabled device we remove the extra
15820 // empty mouseover listeners we added for iOS support
15823 if ('ontouchstart' in document.documentElement) {
15824 $__default['default'](document.body).children().off('mouseover', null, $__default['default'].noop);
15827 toggles[i].setAttribute('aria-expanded', 'false');
15829 if (context._popper) {
15830 context._popper.destroy();
15833 $__default['default'](dropdownMenu).removeClass(CLASS_NAME_SHOW$2);
15834 $__default['default'](parent).removeClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_HIDDEN$1, relatedTarget));
15838 Dropdown._getParentFromElement = function _getParentFromElement(element) {
15840 var selector = Util.getSelectorFromElement(element);
15843 parent = document.querySelector(selector);
15846 return parent || element.parentNode;
15847 } // eslint-disable-next-line complexity
15850 Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
15851 // If not input/textarea:
15852 // - And not a key in REGEXP_KEYDOWN => not a dropdown command
15853 // If input/textarea:
15854 // - If space key => not a dropdown command
15855 // - If key is other than escape
15856 // - If key is not up or down => not a dropdown command
15857 // - If trigger inside the menu => not a dropdown command
15858 if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $__default['default'](event.target).closest(SELECTOR_MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {
15862 if (this.disabled || $__default['default'](this).hasClass(CLASS_NAME_DISABLED)) {
15866 var parent = Dropdown._getParentFromElement(this);
15868 var isActive = $__default['default'](parent).hasClass(CLASS_NAME_SHOW$2);
15870 if (!isActive && event.which === ESCAPE_KEYCODE) {
15874 event.preventDefault();
15875 event.stopPropagation();
15877 if (!isActive || event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE) {
15878 if (event.which === ESCAPE_KEYCODE) {
15879 $__default['default'](parent.querySelector(SELECTOR_DATA_TOGGLE$2)).trigger('focus');
15882 $__default['default'](this).trigger('click');
15886 var items = [].slice.call(parent.querySelectorAll(SELECTOR_VISIBLE_ITEMS)).filter(function (item) {
15887 return $__default['default'](item).is(':visible');
15890 if (items.length === 0) {
15894 var index = items.indexOf(event.target);
15896 if (event.which === ARROW_UP_KEYCODE && index > 0) {
15901 if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
15910 items[index].focus();
15913 _createClass(Dropdown, null, [{
15915 get: function get() {
15920 get: function get() {
15924 key: "DefaultType",
15925 get: function get() {
15926 return DefaultType$2;
15933 * ------------------------------------------------------------------------
15934 * Data Api implementation
15935 * ------------------------------------------------------------------------
15939 $__default['default'](document).on(EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$2, Dropdown._dataApiKeydownHandler).on(EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown._dataApiKeydownHandler).on(EVENT_CLICK_DATA_API$4 + " " + EVENT_KEYUP_DATA_API, Dropdown._clearMenus).on(EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$2, function (event) {
15940 event.preventDefault();
15941 event.stopPropagation();
15943 Dropdown._jQueryInterface.call($__default['default'](this), 'toggle');
15944 }).on(EVENT_CLICK_DATA_API$4, SELECTOR_FORM_CHILD, function (e) {
15945 e.stopPropagation();
15948 * ------------------------------------------------------------------------
15950 * ------------------------------------------------------------------------
15953 $__default['default'].fn[NAME$4] = Dropdown._jQueryInterface;
15954 $__default['default'].fn[NAME$4].Constructor = Dropdown;
15956 $__default['default'].fn[NAME$4].noConflict = function () {
15957 $__default['default'].fn[NAME$4] = JQUERY_NO_CONFLICT$4;
15958 return Dropdown._jQueryInterface;
15962 * ------------------------------------------------------------------------
15964 * ------------------------------------------------------------------------
15967 var NAME$5 = 'modal';
15968 var VERSION$5 = '4.6.0';
15969 var DATA_KEY$5 = 'bs.modal';
15970 var EVENT_KEY$5 = "." + DATA_KEY$5;
15971 var DATA_API_KEY$5 = '.data-api';
15972 var JQUERY_NO_CONFLICT$5 = $__default['default'].fn[NAME$5];
15973 var ESCAPE_KEYCODE$1 = 27; // KeyboardEvent.which value for Escape (Esc) key
15981 var DefaultType$3 = {
15982 backdrop: '(boolean|string)',
15983 keyboard: 'boolean',
15987 var EVENT_HIDE$2 = "hide" + EVENT_KEY$5;
15988 var EVENT_HIDE_PREVENTED = "hidePrevented" + EVENT_KEY$5;
15989 var EVENT_HIDDEN$2 = "hidden" + EVENT_KEY$5;
15990 var EVENT_SHOW$2 = "show" + EVENT_KEY$5;
15991 var EVENT_SHOWN$2 = "shown" + EVENT_KEY$5;
15992 var EVENT_FOCUSIN = "focusin" + EVENT_KEY$5;
15993 var EVENT_RESIZE = "resize" + EVENT_KEY$5;
15994 var EVENT_CLICK_DISMISS = "click.dismiss" + EVENT_KEY$5;
15995 var EVENT_KEYDOWN_DISMISS = "keydown.dismiss" + EVENT_KEY$5;
15996 var EVENT_MOUSEUP_DISMISS = "mouseup.dismiss" + EVENT_KEY$5;
15997 var EVENT_MOUSEDOWN_DISMISS = "mousedown.dismiss" + EVENT_KEY$5;
15998 var EVENT_CLICK_DATA_API$5 = "click" + EVENT_KEY$5 + DATA_API_KEY$5;
15999 var CLASS_NAME_SCROLLABLE = 'modal-dialog-scrollable';
16000 var CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure';
16001 var CLASS_NAME_BACKDROP = 'modal-backdrop';
16002 var CLASS_NAME_OPEN = 'modal-open';
16003 var CLASS_NAME_FADE$1 = 'fade';
16004 var CLASS_NAME_SHOW$3 = 'show';
16005 var CLASS_NAME_STATIC = 'modal-static';
16006 var SELECTOR_DIALOG = '.modal-dialog';
16007 var SELECTOR_MODAL_BODY = '.modal-body';
16008 var SELECTOR_DATA_TOGGLE$3 = '[data-toggle="modal"]';
16009 var SELECTOR_DATA_DISMISS = '[data-dismiss="modal"]';
16010 var SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
16011 var SELECTOR_STICKY_CONTENT = '.sticky-top';
16013 * ------------------------------------------------------------------------
16015 * ------------------------------------------------------------------------
16018 var Modal = /*#__PURE__*/function () {
16019 function Modal(element, config) {
16020 this._config = this._getConfig(config);
16021 this._element = element;
16022 this._dialog = element.querySelector(SELECTOR_DIALOG);
16023 this._backdrop = null;
16024 this._isShown = false;
16025 this._isBodyOverflowing = false;
16026 this._ignoreBackdropClick = false;
16027 this._isTransitioning = false;
16028 this._scrollbarWidth = 0;
16032 var _proto = Modal.prototype;
16035 _proto.toggle = function toggle(relatedTarget) {
16036 return this._isShown ? this.hide() : this.show(relatedTarget);
16039 _proto.show = function show(relatedTarget) {
16042 if (this._isShown || this._isTransitioning) {
16046 if ($__default['default'](this._element).hasClass(CLASS_NAME_FADE$1)) {
16047 this._isTransitioning = true;
16050 var showEvent = $__default['default'].Event(EVENT_SHOW$2, {
16051 relatedTarget: relatedTarget
16053 $__default['default'](this._element).trigger(showEvent);
16055 if (this._isShown || showEvent.isDefaultPrevented()) {
16059 this._isShown = true;
16061 this._checkScrollbar();
16063 this._setScrollbar();
16065 this._adjustDialog();
16067 this._setEscapeEvent();
16069 this._setResizeEvent();
16071 $__default['default'](this._element).on(EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, function (event) {
16072 return _this.hide(event);
16074 $__default['default'](this._dialog).on(EVENT_MOUSEDOWN_DISMISS, function () {
16075 $__default['default'](_this._element).one(EVENT_MOUSEUP_DISMISS, function (event) {
16076 if ($__default['default'](event.target).is(_this._element)) {
16077 _this._ignoreBackdropClick = true;
16082 this._showBackdrop(function () {
16083 return _this._showElement(relatedTarget);
16087 _proto.hide = function hide(event) {
16091 event.preventDefault();
16094 if (!this._isShown || this._isTransitioning) {
16098 var hideEvent = $__default['default'].Event(EVENT_HIDE$2);
16099 $__default['default'](this._element).trigger(hideEvent);
16101 if (!this._isShown || hideEvent.isDefaultPrevented()) {
16105 this._isShown = false;
16106 var transition = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1);
16109 this._isTransitioning = true;
16112 this._setEscapeEvent();
16114 this._setResizeEvent();
16116 $__default['default'](document).off(EVENT_FOCUSIN);
16117 $__default['default'](this._element).removeClass(CLASS_NAME_SHOW$3);
16118 $__default['default'](this._element).off(EVENT_CLICK_DISMISS);
16119 $__default['default'](this._dialog).off(EVENT_MOUSEDOWN_DISMISS);
16122 var transitionDuration = Util.getTransitionDurationFromElement(this._element);
16123 $__default['default'](this._element).one(Util.TRANSITION_END, function (event) {
16124 return _this2._hideModal(event);
16125 }).emulateTransitionEnd(transitionDuration);
16131 _proto.dispose = function dispose() {
16132 [window, this._element, this._dialog].forEach(function (htmlElement) {
16133 return $__default['default'](htmlElement).off(EVENT_KEY$5);
16136 * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API`
16137 * Do not move `document` in `htmlElements` array
16138 * It will remove `EVENT_CLICK_DATA_API` event that should remain
16141 $__default['default'](document).off(EVENT_FOCUSIN);
16142 $__default['default'].removeData(this._element, DATA_KEY$5);
16143 this._config = null;
16144 this._element = null;
16145 this._dialog = null;
16146 this._backdrop = null;
16147 this._isShown = null;
16148 this._isBodyOverflowing = null;
16149 this._ignoreBackdropClick = null;
16150 this._isTransitioning = null;
16151 this._scrollbarWidth = null;
16154 _proto.handleUpdate = function handleUpdate() {
16155 this._adjustDialog();
16159 _proto._getConfig = function _getConfig(config) {
16160 config = _extends({}, Default$3, config);
16161 Util.typeCheckConfig(NAME$5, config, DefaultType$3);
16165 _proto._triggerBackdropTransition = function _triggerBackdropTransition() {
16168 var hideEventPrevented = $__default['default'].Event(EVENT_HIDE_PREVENTED);
16169 $__default['default'](this._element).trigger(hideEventPrevented);
16171 if (hideEventPrevented.isDefaultPrevented()) {
16175 var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
16177 if (!isModalOverflowing) {
16178 this._element.style.overflowY = 'hidden';
16181 this._element.classList.add(CLASS_NAME_STATIC);
16183 var modalTransitionDuration = Util.getTransitionDurationFromElement(this._dialog);
16184 $__default['default'](this._element).off(Util.TRANSITION_END);
16185 $__default['default'](this._element).one(Util.TRANSITION_END, function () {
16186 _this3._element.classList.remove(CLASS_NAME_STATIC);
16188 if (!isModalOverflowing) {
16189 $__default['default'](_this3._element).one(Util.TRANSITION_END, function () {
16190 _this3._element.style.overflowY = '';
16191 }).emulateTransitionEnd(_this3._element, modalTransitionDuration);
16193 }).emulateTransitionEnd(modalTransitionDuration);
16195 this._element.focus();
16198 _proto._showElement = function _showElement(relatedTarget) {
16201 var transition = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1);
16202 var modalBody = this._dialog ? this._dialog.querySelector(SELECTOR_MODAL_BODY) : null;
16204 if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
16205 // Don't move modal's DOM position
16206 document.body.appendChild(this._element);
16209 this._element.style.display = 'block';
16211 this._element.removeAttribute('aria-hidden');
16213 this._element.setAttribute('aria-modal', true);
16215 this._element.setAttribute('role', 'dialog');
16217 if ($__default['default'](this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {
16218 modalBody.scrollTop = 0;
16220 this._element.scrollTop = 0;
16224 Util.reflow(this._element);
16227 $__default['default'](this._element).addClass(CLASS_NAME_SHOW$3);
16229 if (this._config.focus) {
16230 this._enforceFocus();
16233 var shownEvent = $__default['default'].Event(EVENT_SHOWN$2, {
16234 relatedTarget: relatedTarget
16237 var transitionComplete = function transitionComplete() {
16238 if (_this4._config.focus) {
16239 _this4._element.focus();
16242 _this4._isTransitioning = false;
16243 $__default['default'](_this4._element).trigger(shownEvent);
16247 var transitionDuration = Util.getTransitionDurationFromElement(this._dialog);
16248 $__default['default'](this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration);
16250 transitionComplete();
16254 _proto._enforceFocus = function _enforceFocus() {
16257 $__default['default'](document).off(EVENT_FOCUSIN) // Guard against infinite focus loop
16258 .on(EVENT_FOCUSIN, function (event) {
16259 if (document !== event.target && _this5._element !== event.target && $__default['default'](_this5._element).has(event.target).length === 0) {
16260 _this5._element.focus();
16265 _proto._setEscapeEvent = function _setEscapeEvent() {
16268 if (this._isShown) {
16269 $__default['default'](this._element).on(EVENT_KEYDOWN_DISMISS, function (event) {
16270 if (_this6._config.keyboard && event.which === ESCAPE_KEYCODE$1) {
16271 event.preventDefault();
16274 } else if (!_this6._config.keyboard && event.which === ESCAPE_KEYCODE$1) {
16275 _this6._triggerBackdropTransition();
16278 } else if (!this._isShown) {
16279 $__default['default'](this._element).off(EVENT_KEYDOWN_DISMISS);
16283 _proto._setResizeEvent = function _setResizeEvent() {
16286 if (this._isShown) {
16287 $__default['default'](window).on(EVENT_RESIZE, function (event) {
16288 return _this7.handleUpdate(event);
16291 $__default['default'](window).off(EVENT_RESIZE);
16295 _proto._hideModal = function _hideModal() {
16298 this._element.style.display = 'none';
16300 this._element.setAttribute('aria-hidden', true);
16302 this._element.removeAttribute('aria-modal');
16304 this._element.removeAttribute('role');
16306 this._isTransitioning = false;
16308 this._showBackdrop(function () {
16309 $__default['default'](document.body).removeClass(CLASS_NAME_OPEN);
16311 _this8._resetAdjustments();
16313 _this8._resetScrollbar();
16315 $__default['default'](_this8._element).trigger(EVENT_HIDDEN$2);
16319 _proto._removeBackdrop = function _removeBackdrop() {
16320 if (this._backdrop) {
16321 $__default['default'](this._backdrop).remove();
16322 this._backdrop = null;
16326 _proto._showBackdrop = function _showBackdrop(callback) {
16329 var animate = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1) ? CLASS_NAME_FADE$1 : '';
16331 if (this._isShown && this._config.backdrop) {
16332 this._backdrop = document.createElement('div');
16333 this._backdrop.className = CLASS_NAME_BACKDROP;
16336 this._backdrop.classList.add(animate);
16339 $__default['default'](this._backdrop).appendTo(document.body);
16340 $__default['default'](this._element).on(EVENT_CLICK_DISMISS, function (event) {
16341 if (_this9._ignoreBackdropClick) {
16342 _this9._ignoreBackdropClick = false;
16346 if (event.target !== event.currentTarget) {
16350 if (_this9._config.backdrop === 'static') {
16351 _this9._triggerBackdropTransition();
16358 Util.reflow(this._backdrop);
16361 $__default['default'](this._backdrop).addClass(CLASS_NAME_SHOW$3);
16372 var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);
16373 $__default['default'](this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration);
16374 } else if (!this._isShown && this._backdrop) {
16375 $__default['default'](this._backdrop).removeClass(CLASS_NAME_SHOW$3);
16377 var callbackRemove = function callbackRemove() {
16378 _this9._removeBackdrop();
16385 if ($__default['default'](this._element).hasClass(CLASS_NAME_FADE$1)) {
16386 var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);
16388 $__default['default'](this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration);
16392 } else if (callback) {
16395 } // ----------------------------------------------------------------------
16396 // the following methods are used to handle overflowing modals
16397 // todo (fat): these should probably be refactored out of modal.js
16398 // ----------------------------------------------------------------------
16401 _proto._adjustDialog = function _adjustDialog() {
16402 var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
16404 if (!this._isBodyOverflowing && isModalOverflowing) {
16405 this._element.style.paddingLeft = this._scrollbarWidth + "px";
16408 if (this._isBodyOverflowing && !isModalOverflowing) {
16409 this._element.style.paddingRight = this._scrollbarWidth + "px";
16413 _proto._resetAdjustments = function _resetAdjustments() {
16414 this._element.style.paddingLeft = '';
16415 this._element.style.paddingRight = '';
16418 _proto._checkScrollbar = function _checkScrollbar() {
16419 var rect = document.body.getBoundingClientRect();
16420 this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth;
16421 this._scrollbarWidth = this._getScrollbarWidth();
16424 _proto._setScrollbar = function _setScrollbar() {
16425 var _this10 = this;
16427 if (this._isBodyOverflowing) {
16428 // Note: DOMNode.style.paddingRight returns the actual value or '' if not set
16429 // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
16430 var fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT));
16431 var stickyContent = [].slice.call(document.querySelectorAll(SELECTOR_STICKY_CONTENT)); // Adjust fixed content padding
16433 $__default['default'](fixedContent).each(function (index, element) {
16434 var actualPadding = element.style.paddingRight;
16435 var calculatedPadding = $__default['default'](element).css('padding-right');
16436 $__default['default'](element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this10._scrollbarWidth + "px");
16437 }); // Adjust sticky content margin
16439 $__default['default'](stickyContent).each(function (index, element) {
16440 var actualMargin = element.style.marginRight;
16441 var calculatedMargin = $__default['default'](element).css('margin-right');
16442 $__default['default'](element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this10._scrollbarWidth + "px");
16443 }); // Adjust body padding
16445 var actualPadding = document.body.style.paddingRight;
16446 var calculatedPadding = $__default['default'](document.body).css('padding-right');
16447 $__default['default'](document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
16450 $__default['default'](document.body).addClass(CLASS_NAME_OPEN);
16453 _proto._resetScrollbar = function _resetScrollbar() {
16454 // Restore fixed content padding
16455 var fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT));
16456 $__default['default'](fixedContent).each(function (index, element) {
16457 var padding = $__default['default'](element).data('padding-right');
16458 $__default['default'](element).removeData('padding-right');
16459 element.style.paddingRight = padding ? padding : '';
16460 }); // Restore sticky content
16462 var elements = [].slice.call(document.querySelectorAll("" + SELECTOR_STICKY_CONTENT));
16463 $__default['default'](elements).each(function (index, element) {
16464 var margin = $__default['default'](element).data('margin-right');
16466 if (typeof margin !== 'undefined') {
16467 $__default['default'](element).css('margin-right', margin).removeData('margin-right');
16469 }); // Restore body padding
16471 var padding = $__default['default'](document.body).data('padding-right');
16472 $__default['default'](document.body).removeData('padding-right');
16473 document.body.style.paddingRight = padding ? padding : '';
16476 _proto._getScrollbarWidth = function _getScrollbarWidth() {
16478 var scrollDiv = document.createElement('div');
16479 scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER;
16480 document.body.appendChild(scrollDiv);
16481 var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;
16482 document.body.removeChild(scrollDiv);
16483 return scrollbarWidth;
16487 Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
16488 return this.each(function () {
16489 var data = $__default['default'](this).data(DATA_KEY$5);
16491 var _config = _extends({}, Default$3, $__default['default'](this).data(), typeof config === 'object' && config ? config : {});
16494 data = new Modal(this, _config);
16495 $__default['default'](this).data(DATA_KEY$5, data);
16498 if (typeof config === 'string') {
16499 if (typeof data[config] === 'undefined') {
16500 throw new TypeError("No method named \"" + config + "\"");
16503 data[config](relatedTarget);
16504 } else if (_config.show) {
16505 data.show(relatedTarget);
16510 _createClass(Modal, null, [{
16512 get: function get() {
16517 get: function get() {
16525 * ------------------------------------------------------------------------
16526 * Data Api implementation
16527 * ------------------------------------------------------------------------
16531 $__default['default'](document).on(EVENT_CLICK_DATA_API$5, SELECTOR_DATA_TOGGLE$3, function (event) {
16532 var _this11 = this;
16535 var selector = Util.getSelectorFromElement(this);
16538 target = document.querySelector(selector);
16541 var config = $__default['default'](target).data(DATA_KEY$5) ? 'toggle' : _extends({}, $__default['default'](target).data(), $__default['default'](this).data());
16543 if (this.tagName === 'A' || this.tagName === 'AREA') {
16544 event.preventDefault();
16547 var $target = $__default['default'](target).one(EVENT_SHOW$2, function (showEvent) {
16548 if (showEvent.isDefaultPrevented()) {
16549 // Only register focus restorer if modal will actually get shown
16553 $target.one(EVENT_HIDDEN$2, function () {
16554 if ($__default['default'](_this11).is(':visible')) {
16560 Modal._jQueryInterface.call($__default['default'](target), config, this);
16563 * ------------------------------------------------------------------------
16565 * ------------------------------------------------------------------------
16568 $__default['default'].fn[NAME$5] = Modal._jQueryInterface;
16569 $__default['default'].fn[NAME$5].Constructor = Modal;
16571 $__default['default'].fn[NAME$5].noConflict = function () {
16572 $__default['default'].fn[NAME$5] = JQUERY_NO_CONFLICT$5;
16573 return Modal._jQueryInterface;
16577 * --------------------------------------------------------------------------
16578 * Bootstrap (v4.6.0): tools/sanitizer.js
16579 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
16580 * --------------------------------------------------------------------------
16582 var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];
16583 var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
16584 var DefaultWhitelist = {
16585 // Global attributes allowed on any supplied element below.
16586 '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
16587 a: ['target', 'href', 'title', 'rel'],
16603 img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
16618 * A pattern that recognizes a commonly useful subset of URLs that are safe.
16620 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
16623 var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi;
16625 * A pattern that matches safe data URLs. Only matches image, video and audio types.
16627 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
16630 var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;
16632 function allowedAttribute(attr, allowedAttributeList) {
16633 var attrName = attr.nodeName.toLowerCase();
16635 if (allowedAttributeList.indexOf(attrName) !== -1) {
16636 if (uriAttrs.indexOf(attrName) !== -1) {
16637 return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN));
16643 var regExp = allowedAttributeList.filter(function (attrRegex) {
16644 return attrRegex instanceof RegExp;
16645 }); // Check if a regular expression validates the attribute.
16647 for (var i = 0, len = regExp.length; i < len; i++) {
16648 if (attrName.match(regExp[i])) {
16656 function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
16657 if (unsafeHtml.length === 0) {
16661 if (sanitizeFn && typeof sanitizeFn === 'function') {
16662 return sanitizeFn(unsafeHtml);
16665 var domParser = new window.DOMParser();
16666 var createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
16667 var whitelistKeys = Object.keys(whiteList);
16668 var elements = [].slice.call(createdDocument.body.querySelectorAll('*'));
16670 var _loop = function _loop(i, len) {
16671 var el = elements[i];
16672 var elName = el.nodeName.toLowerCase();
16674 if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) {
16675 el.parentNode.removeChild(el);
16679 var attributeList = [].slice.call(el.attributes);
16680 var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []);
16681 attributeList.forEach(function (attr) {
16682 if (!allowedAttribute(attr, whitelistedAttributes)) {
16683 el.removeAttribute(attr.nodeName);
16688 for (var i = 0, len = elements.length; i < len; i++) {
16689 var _ret = _loop(i);
16691 if (_ret === "continue") continue;
16694 return createdDocument.body.innerHTML;
16698 * ------------------------------------------------------------------------
16700 * ------------------------------------------------------------------------
16703 var NAME$6 = 'tooltip';
16704 var VERSION$6 = '4.6.0';
16705 var DATA_KEY$6 = 'bs.tooltip';
16706 var EVENT_KEY$6 = "." + DATA_KEY$6;
16707 var JQUERY_NO_CONFLICT$6 = $__default['default'].fn[NAME$6];
16708 var CLASS_PREFIX = 'bs-tooltip';
16709 var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
16710 var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'];
16711 var DefaultType$4 = {
16712 animation: 'boolean',
16713 template: 'string',
16714 title: '(string|element|function)',
16716 delay: '(number|object)',
16718 selector: '(string|boolean)',
16719 placement: '(string|function)',
16720 offset: '(number|string|function)',
16721 container: '(string|element|boolean)',
16722 fallbackPlacement: '(string|array)',
16723 boundary: '(string|element)',
16724 customClass: '(string|function)',
16725 sanitize: 'boolean',
16726 sanitizeFn: '(null|function)',
16727 whiteList: 'object',
16728 popperConfig: '(null|object)'
16730 var AttachmentMap = {
16739 template: '<div class="tooltip" role="tooltip">' + '<div class="arrow"></div>' + '<div class="tooltip-inner"></div></div>',
16740 trigger: 'hover focus',
16748 fallbackPlacement: 'flip',
16749 boundary: 'scrollParent',
16753 whiteList: DefaultWhitelist,
16756 var HOVER_STATE_SHOW = 'show';
16757 var HOVER_STATE_OUT = 'out';
16759 HIDE: "hide" + EVENT_KEY$6,
16760 HIDDEN: "hidden" + EVENT_KEY$6,
16761 SHOW: "show" + EVENT_KEY$6,
16762 SHOWN: "shown" + EVENT_KEY$6,
16763 INSERTED: "inserted" + EVENT_KEY$6,
16764 CLICK: "click" + EVENT_KEY$6,
16765 FOCUSIN: "focusin" + EVENT_KEY$6,
16766 FOCUSOUT: "focusout" + EVENT_KEY$6,
16767 MOUSEENTER: "mouseenter" + EVENT_KEY$6,
16768 MOUSELEAVE: "mouseleave" + EVENT_KEY$6
16770 var CLASS_NAME_FADE$2 = 'fade';
16771 var CLASS_NAME_SHOW$4 = 'show';
16772 var SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
16773 var SELECTOR_ARROW = '.arrow';
16774 var TRIGGER_HOVER = 'hover';
16775 var TRIGGER_FOCUS = 'focus';
16776 var TRIGGER_CLICK = 'click';
16777 var TRIGGER_MANUAL = 'manual';
16779 * ------------------------------------------------------------------------
16781 * ------------------------------------------------------------------------
16784 var Tooltip = /*#__PURE__*/function () {
16785 function Tooltip(element, config) {
16786 if (typeof Popper === 'undefined') {
16787 throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
16791 this._isEnabled = true;
16793 this._hoverState = '';
16794 this._activeTrigger = {};
16795 this._popper = null; // Protected
16797 this.element = element;
16798 this.config = this._getConfig(config);
16801 this._setListeners();
16805 var _proto = Tooltip.prototype;
16808 _proto.enable = function enable() {
16809 this._isEnabled = true;
16812 _proto.disable = function disable() {
16813 this._isEnabled = false;
16816 _proto.toggleEnabled = function toggleEnabled() {
16817 this._isEnabled = !this._isEnabled;
16820 _proto.toggle = function toggle(event) {
16821 if (!this._isEnabled) {
16826 var dataKey = this.constructor.DATA_KEY;
16827 var context = $__default['default'](event.currentTarget).data(dataKey);
16830 context = new this.constructor(event.currentTarget, this._getDelegateConfig());
16831 $__default['default'](event.currentTarget).data(dataKey, context);
16834 context._activeTrigger.click = !context._activeTrigger.click;
16836 if (context._isWithActiveTrigger()) {
16837 context._enter(null, context);
16839 context._leave(null, context);
16842 if ($__default['default'](this.getTipElement()).hasClass(CLASS_NAME_SHOW$4)) {
16843 this._leave(null, this);
16848 this._enter(null, this);
16852 _proto.dispose = function dispose() {
16853 clearTimeout(this._timeout);
16854 $__default['default'].removeData(this.element, this.constructor.DATA_KEY);
16855 $__default['default'](this.element).off(this.constructor.EVENT_KEY);
16856 $__default['default'](this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler);
16859 $__default['default'](this.tip).remove();
16862 this._isEnabled = null;
16863 this._timeout = null;
16864 this._hoverState = null;
16865 this._activeTrigger = null;
16867 if (this._popper) {
16868 this._popper.destroy();
16871 this._popper = null;
16872 this.element = null;
16873 this.config = null;
16877 _proto.show = function show() {
16880 if ($__default['default'](this.element).css('display') === 'none') {
16881 throw new Error('Please use show on visible elements');
16884 var showEvent = $__default['default'].Event(this.constructor.Event.SHOW);
16886 if (this.isWithContent() && this._isEnabled) {
16887 $__default['default'](this.element).trigger(showEvent);
16888 var shadowRoot = Util.findShadowRoot(this.element);
16889 var isInTheDom = $__default['default'].contains(shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, this.element);
16891 if (showEvent.isDefaultPrevented() || !isInTheDom) {
16895 var tip = this.getTipElement();
16896 var tipId = Util.getUID(this.constructor.NAME);
16897 tip.setAttribute('id', tipId);
16898 this.element.setAttribute('aria-describedby', tipId);
16901 if (this.config.animation) {
16902 $__default['default'](tip).addClass(CLASS_NAME_FADE$2);
16905 var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
16907 var attachment = this._getAttachment(placement);
16909 this.addAttachmentClass(attachment);
16911 var container = this._getContainer();
16913 $__default['default'](tip).data(this.constructor.DATA_KEY, this);
16915 if (!$__default['default'].contains(this.element.ownerDocument.documentElement, this.tip)) {
16916 $__default['default'](tip).appendTo(container);
16919 $__default['default'](this.element).trigger(this.constructor.Event.INSERTED);
16920 this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment));
16921 $__default['default'](tip).addClass(CLASS_NAME_SHOW$4);
16922 $__default['default'](tip).addClass(this.config.customClass); // If this is a touch-enabled device we add extra
16923 // empty mouseover listeners to the body's immediate children;
16924 // only needed because of broken event delegation on iOS
16925 // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
16927 if ('ontouchstart' in document.documentElement) {
16928 $__default['default'](document.body).children().on('mouseover', null, $__default['default'].noop);
16931 var complete = function complete() {
16932 if (_this.config.animation) {
16933 _this._fixTransition();
16936 var prevHoverState = _this._hoverState;
16937 _this._hoverState = null;
16938 $__default['default'](_this.element).trigger(_this.constructor.Event.SHOWN);
16940 if (prevHoverState === HOVER_STATE_OUT) {
16941 _this._leave(null, _this);
16945 if ($__default['default'](this.tip).hasClass(CLASS_NAME_FADE$2)) {
16946 var transitionDuration = Util.getTransitionDurationFromElement(this.tip);
16947 $__default['default'](this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
16954 _proto.hide = function hide(callback) {
16957 var tip = this.getTipElement();
16958 var hideEvent = $__default['default'].Event(this.constructor.Event.HIDE);
16960 var complete = function complete() {
16961 if (_this2._hoverState !== HOVER_STATE_SHOW && tip.parentNode) {
16962 tip.parentNode.removeChild(tip);
16965 _this2._cleanTipClass();
16967 _this2.element.removeAttribute('aria-describedby');
16969 $__default['default'](_this2.element).trigger(_this2.constructor.Event.HIDDEN);
16971 if (_this2._popper !== null) {
16972 _this2._popper.destroy();
16980 $__default['default'](this.element).trigger(hideEvent);
16982 if (hideEvent.isDefaultPrevented()) {
16986 $__default['default'](tip).removeClass(CLASS_NAME_SHOW$4); // If this is a touch-enabled device we remove the extra
16987 // empty mouseover listeners we added for iOS support
16989 if ('ontouchstart' in document.documentElement) {
16990 $__default['default'](document.body).children().off('mouseover', null, $__default['default'].noop);
16993 this._activeTrigger[TRIGGER_CLICK] = false;
16994 this._activeTrigger[TRIGGER_FOCUS] = false;
16995 this._activeTrigger[TRIGGER_HOVER] = false;
16997 if ($__default['default'](this.tip).hasClass(CLASS_NAME_FADE$2)) {
16998 var transitionDuration = Util.getTransitionDurationFromElement(tip);
16999 $__default['default'](tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
17004 this._hoverState = '';
17007 _proto.update = function update() {
17008 if (this._popper !== null) {
17009 this._popper.scheduleUpdate();
17014 _proto.isWithContent = function isWithContent() {
17015 return Boolean(this.getTitle());
17018 _proto.addAttachmentClass = function addAttachmentClass(attachment) {
17019 $__default['default'](this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
17022 _proto.getTipElement = function getTipElement() {
17023 this.tip = this.tip || $__default['default'](this.config.template)[0];
17027 _proto.setContent = function setContent() {
17028 var tip = this.getTipElement();
17029 this.setElementContent($__default['default'](tip.querySelectorAll(SELECTOR_TOOLTIP_INNER)), this.getTitle());
17030 $__default['default'](tip).removeClass(CLASS_NAME_FADE$2 + " " + CLASS_NAME_SHOW$4);
17033 _proto.setElementContent = function setElementContent($element, content) {
17034 if (typeof content === 'object' && (content.nodeType || content.jquery)) {
17035 // Content is a DOM node or a jQuery
17036 if (this.config.html) {
17037 if (!$__default['default'](content).parent().is($element)) {
17038 $element.empty().append(content);
17041 $element.text($__default['default'](content).text());
17047 if (this.config.html) {
17048 if (this.config.sanitize) {
17049 content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn);
17052 $element.html(content);
17054 $element.text(content);
17058 _proto.getTitle = function getTitle() {
17059 var title = this.element.getAttribute('data-original-title');
17062 title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
17069 _proto._getPopperConfig = function _getPopperConfig(attachment) {
17072 var defaultBsConfig = {
17073 placement: attachment,
17075 offset: this._getOffset(),
17077 behavior: this.config.fallbackPlacement
17080 element: SELECTOR_ARROW
17083 boundariesElement: this.config.boundary
17086 onCreate: function onCreate(data) {
17087 if (data.originalPlacement !== data.placement) {
17088 _this3._handlePopperPlacementChange(data);
17091 onUpdate: function onUpdate(data) {
17092 return _this3._handlePopperPlacementChange(data);
17095 return _extends({}, defaultBsConfig, this.config.popperConfig);
17098 _proto._getOffset = function _getOffset() {
17103 if (typeof this.config.offset === 'function') {
17104 offset.fn = function (data) {
17105 data.offsets = _extends({}, data.offsets, _this4.config.offset(data.offsets, _this4.element) || {});
17109 offset.offset = this.config.offset;
17115 _proto._getContainer = function _getContainer() {
17116 if (this.config.container === false) {
17117 return document.body;
17120 if (Util.isElement(this.config.container)) {
17121 return $__default['default'](this.config.container);
17124 return $__default['default'](document).find(this.config.container);
17127 _proto._getAttachment = function _getAttachment(placement) {
17128 return AttachmentMap[placement.toUpperCase()];
17131 _proto._setListeners = function _setListeners() {
17134 var triggers = this.config.trigger.split(' ');
17135 triggers.forEach(function (trigger) {
17136 if (trigger === 'click') {
17137 $__default['default'](_this5.element).on(_this5.constructor.Event.CLICK, _this5.config.selector, function (event) {
17138 return _this5.toggle(event);
17140 } else if (trigger !== TRIGGER_MANUAL) {
17141 var eventIn = trigger === TRIGGER_HOVER ? _this5.constructor.Event.MOUSEENTER : _this5.constructor.Event.FOCUSIN;
17142 var eventOut = trigger === TRIGGER_HOVER ? _this5.constructor.Event.MOUSELEAVE : _this5.constructor.Event.FOCUSOUT;
17143 $__default['default'](_this5.element).on(eventIn, _this5.config.selector, function (event) {
17144 return _this5._enter(event);
17145 }).on(eventOut, _this5.config.selector, function (event) {
17146 return _this5._leave(event);
17151 this._hideModalHandler = function () {
17152 if (_this5.element) {
17157 $__default['default'](this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler);
17159 if (this.config.selector) {
17160 this.config = _extends({}, this.config, {
17169 _proto._fixTitle = function _fixTitle() {
17170 var titleType = typeof this.element.getAttribute('data-original-title');
17172 if (this.element.getAttribute('title') || titleType !== 'string') {
17173 this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
17174 this.element.setAttribute('title', '');
17178 _proto._enter = function _enter(event, context) {
17179 var dataKey = this.constructor.DATA_KEY;
17180 context = context || $__default['default'](event.currentTarget).data(dataKey);
17183 context = new this.constructor(event.currentTarget, this._getDelegateConfig());
17184 $__default['default'](event.currentTarget).data(dataKey, context);
17188 context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
17191 if ($__default['default'](context.getTipElement()).hasClass(CLASS_NAME_SHOW$4) || context._hoverState === HOVER_STATE_SHOW) {
17192 context._hoverState = HOVER_STATE_SHOW;
17196 clearTimeout(context._timeout);
17197 context._hoverState = HOVER_STATE_SHOW;
17199 if (!context.config.delay || !context.config.delay.show) {
17204 context._timeout = setTimeout(function () {
17205 if (context._hoverState === HOVER_STATE_SHOW) {
17208 }, context.config.delay.show);
17211 _proto._leave = function _leave(event, context) {
17212 var dataKey = this.constructor.DATA_KEY;
17213 context = context || $__default['default'](event.currentTarget).data(dataKey);
17216 context = new this.constructor(event.currentTarget, this._getDelegateConfig());
17217 $__default['default'](event.currentTarget).data(dataKey, context);
17221 context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = false;
17224 if (context._isWithActiveTrigger()) {
17228 clearTimeout(context._timeout);
17229 context._hoverState = HOVER_STATE_OUT;
17231 if (!context.config.delay || !context.config.delay.hide) {
17236 context._timeout = setTimeout(function () {
17237 if (context._hoverState === HOVER_STATE_OUT) {
17240 }, context.config.delay.hide);
17243 _proto._isWithActiveTrigger = function _isWithActiveTrigger() {
17244 for (var trigger in this._activeTrigger) {
17245 if (this._activeTrigger[trigger]) {
17253 _proto._getConfig = function _getConfig(config) {
17254 var dataAttributes = $__default['default'](this.element).data();
17255 Object.keys(dataAttributes).forEach(function (dataAttr) {
17256 if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) {
17257 delete dataAttributes[dataAttr];
17260 config = _extends({}, this.constructor.Default, dataAttributes, typeof config === 'object' && config ? config : {});
17262 if (typeof config.delay === 'number') {
17264 show: config.delay,
17269 if (typeof config.title === 'number') {
17270 config.title = config.title.toString();
17273 if (typeof config.content === 'number') {
17274 config.content = config.content.toString();
17277 Util.typeCheckConfig(NAME$6, config, this.constructor.DefaultType);
17279 if (config.sanitize) {
17280 config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn);
17286 _proto._getDelegateConfig = function _getDelegateConfig() {
17290 for (var key in this.config) {
17291 if (this.constructor.Default[key] !== this.config[key]) {
17292 config[key] = this.config[key];
17300 _proto._cleanTipClass = function _cleanTipClass() {
17301 var $tip = $__default['default'](this.getTipElement());
17302 var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
17304 if (tabClass !== null && tabClass.length) {
17305 $tip.removeClass(tabClass.join(''));
17309 _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) {
17310 this.tip = popperData.instance.popper;
17312 this._cleanTipClass();
17314 this.addAttachmentClass(this._getAttachment(popperData.placement));
17317 _proto._fixTransition = function _fixTransition() {
17318 var tip = this.getTipElement();
17319 var initConfigAnimation = this.config.animation;
17321 if (tip.getAttribute('x-placement') !== null) {
17325 $__default['default'](tip).removeClass(CLASS_NAME_FADE$2);
17326 this.config.animation = false;
17329 this.config.animation = initConfigAnimation;
17333 Tooltip._jQueryInterface = function _jQueryInterface(config) {
17334 return this.each(function () {
17335 var $element = $__default['default'](this);
17336 var data = $element.data(DATA_KEY$6);
17338 var _config = typeof config === 'object' && config;
17340 if (!data && /dispose|hide/.test(config)) {
17345 data = new Tooltip(this, _config);
17346 $element.data(DATA_KEY$6, data);
17349 if (typeof config === 'string') {
17350 if (typeof data[config] === 'undefined') {
17351 throw new TypeError("No method named \"" + config + "\"");
17359 _createClass(Tooltip, null, [{
17361 get: function get() {
17366 get: function get() {
17371 get: function get() {
17376 get: function get() {
17381 get: function get() {
17386 get: function get() {
17387 return EVENT_KEY$6;
17390 key: "DefaultType",
17391 get: function get() {
17392 return DefaultType$4;
17399 * ------------------------------------------------------------------------
17401 * ------------------------------------------------------------------------
17405 $__default['default'].fn[NAME$6] = Tooltip._jQueryInterface;
17406 $__default['default'].fn[NAME$6].Constructor = Tooltip;
17408 $__default['default'].fn[NAME$6].noConflict = function () {
17409 $__default['default'].fn[NAME$6] = JQUERY_NO_CONFLICT$6;
17410 return Tooltip._jQueryInterface;
17414 * ------------------------------------------------------------------------
17416 * ------------------------------------------------------------------------
17419 var NAME$7 = 'popover';
17420 var VERSION$7 = '4.6.0';
17421 var DATA_KEY$7 = 'bs.popover';
17422 var EVENT_KEY$7 = "." + DATA_KEY$7;
17423 var JQUERY_NO_CONFLICT$7 = $__default['default'].fn[NAME$7];
17424 var CLASS_PREFIX$1 = 'bs-popover';
17425 var BSCLS_PREFIX_REGEX$1 = new RegExp("(^|\\s)" + CLASS_PREFIX$1 + "\\S+", 'g');
17427 var Default$5 = _extends({}, Tooltip.Default, {
17428 placement: 'right',
17431 template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
17434 var DefaultType$5 = _extends({}, Tooltip.DefaultType, {
17435 content: '(string|element|function)'
17438 var CLASS_NAME_FADE$3 = 'fade';
17439 var CLASS_NAME_SHOW$5 = 'show';
17440 var SELECTOR_TITLE = '.popover-header';
17441 var SELECTOR_CONTENT = '.popover-body';
17443 HIDE: "hide" + EVENT_KEY$7,
17444 HIDDEN: "hidden" + EVENT_KEY$7,
17445 SHOW: "show" + EVENT_KEY$7,
17446 SHOWN: "shown" + EVENT_KEY$7,
17447 INSERTED: "inserted" + EVENT_KEY$7,
17448 CLICK: "click" + EVENT_KEY$7,
17449 FOCUSIN: "focusin" + EVENT_KEY$7,
17450 FOCUSOUT: "focusout" + EVENT_KEY$7,
17451 MOUSEENTER: "mouseenter" + EVENT_KEY$7,
17452 MOUSELEAVE: "mouseleave" + EVENT_KEY$7
17455 * ------------------------------------------------------------------------
17457 * ------------------------------------------------------------------------
17460 var Popover = /*#__PURE__*/function (_Tooltip) {
17461 _inheritsLoose(Popover, _Tooltip);
17463 function Popover() {
17464 return _Tooltip.apply(this, arguments) || this;
17467 var _proto = Popover.prototype;
17470 _proto.isWithContent = function isWithContent() {
17471 return this.getTitle() || this._getContent();
17474 _proto.addAttachmentClass = function addAttachmentClass(attachment) {
17475 $__default['default'](this.getTipElement()).addClass(CLASS_PREFIX$1 + "-" + attachment);
17478 _proto.getTipElement = function getTipElement() {
17479 this.tip = this.tip || $__default['default'](this.config.template)[0];
17483 _proto.setContent = function setContent() {
17484 var $tip = $__default['default'](this.getTipElement()); // We use append for html objects to maintain js events
17486 this.setElementContent($tip.find(SELECTOR_TITLE), this.getTitle());
17488 var content = this._getContent();
17490 if (typeof content === 'function') {
17491 content = content.call(this.element);
17494 this.setElementContent($tip.find(SELECTOR_CONTENT), content);
17495 $tip.removeClass(CLASS_NAME_FADE$3 + " " + CLASS_NAME_SHOW$5);
17499 _proto._getContent = function _getContent() {
17500 return this.element.getAttribute('data-content') || this.config.content;
17503 _proto._cleanTipClass = function _cleanTipClass() {
17504 var $tip = $__default['default'](this.getTipElement());
17505 var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX$1);
17507 if (tabClass !== null && tabClass.length > 0) {
17508 $tip.removeClass(tabClass.join(''));
17513 Popover._jQueryInterface = function _jQueryInterface(config) {
17514 return this.each(function () {
17515 var data = $__default['default'](this).data(DATA_KEY$7);
17517 var _config = typeof config === 'object' ? config : null;
17519 if (!data && /dispose|hide/.test(config)) {
17524 data = new Popover(this, _config);
17525 $__default['default'](this).data(DATA_KEY$7, data);
17528 if (typeof config === 'string') {
17529 if (typeof data[config] === 'undefined') {
17530 throw new TypeError("No method named \"" + config + "\"");
17538 _createClass(Popover, null, [{
17541 get: function get() {
17546 get: function get() {
17551 get: function get() {
17556 get: function get() {
17561 get: function get() {
17566 get: function get() {
17567 return EVENT_KEY$7;
17570 key: "DefaultType",
17571 get: function get() {
17572 return DefaultType$5;
17579 * ------------------------------------------------------------------------
17581 * ------------------------------------------------------------------------
17585 $__default['default'].fn[NAME$7] = Popover._jQueryInterface;
17586 $__default['default'].fn[NAME$7].Constructor = Popover;
17588 $__default['default'].fn[NAME$7].noConflict = function () {
17589 $__default['default'].fn[NAME$7] = JQUERY_NO_CONFLICT$7;
17590 return Popover._jQueryInterface;
17594 * ------------------------------------------------------------------------
17596 * ------------------------------------------------------------------------
17599 var NAME$8 = 'scrollspy';
17600 var VERSION$8 = '4.6.0';
17601 var DATA_KEY$8 = 'bs.scrollspy';
17602 var EVENT_KEY$8 = "." + DATA_KEY$8;
17603 var DATA_API_KEY$6 = '.data-api';
17604 var JQUERY_NO_CONFLICT$8 = $__default['default'].fn[NAME$8];
17610 var DefaultType$6 = {
17613 target: '(string|element)'
17615 var EVENT_ACTIVATE = "activate" + EVENT_KEY$8;
17616 var EVENT_SCROLL = "scroll" + EVENT_KEY$8;
17617 var EVENT_LOAD_DATA_API$2 = "load" + EVENT_KEY$8 + DATA_API_KEY$6;
17618 var CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';
17619 var CLASS_NAME_ACTIVE$2 = 'active';
17620 var SELECTOR_DATA_SPY = '[data-spy="scroll"]';
17621 var SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
17622 var SELECTOR_NAV_LINKS = '.nav-link';
17623 var SELECTOR_NAV_ITEMS = '.nav-item';
17624 var SELECTOR_LIST_ITEMS = '.list-group-item';
17625 var SELECTOR_DROPDOWN = '.dropdown';
17626 var SELECTOR_DROPDOWN_ITEMS = '.dropdown-item';
17627 var SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
17628 var METHOD_OFFSET = 'offset';
17629 var METHOD_POSITION = 'position';
17631 * ------------------------------------------------------------------------
17633 * ------------------------------------------------------------------------
17636 var ScrollSpy = /*#__PURE__*/function () {
17637 function ScrollSpy(element, config) {
17640 this._element = element;
17641 this._scrollElement = element.tagName === 'BODY' ? window : element;
17642 this._config = this._getConfig(config);
17643 this._selector = this._config.target + " " + SELECTOR_NAV_LINKS + "," + (this._config.target + " " + SELECTOR_LIST_ITEMS + ",") + (this._config.target + " " + SELECTOR_DROPDOWN_ITEMS);
17644 this._offsets = [];
17645 this._targets = [];
17646 this._activeTarget = null;
17647 this._scrollHeight = 0;
17648 $__default['default'](this._scrollElement).on(EVENT_SCROLL, function (event) {
17649 return _this._process(event);
17657 var _proto = ScrollSpy.prototype;
17660 _proto.refresh = function refresh() {
17663 var autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION;
17664 var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
17665 var offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0;
17666 this._offsets = [];
17667 this._targets = [];
17668 this._scrollHeight = this._getScrollHeight();
17669 var targets = [].slice.call(document.querySelectorAll(this._selector));
17670 targets.map(function (element) {
17672 var targetSelector = Util.getSelectorFromElement(element);
17674 if (targetSelector) {
17675 target = document.querySelector(targetSelector);
17679 var targetBCR = target.getBoundingClientRect();
17681 if (targetBCR.width || targetBCR.height) {
17682 // TODO (fat): remove sketch reliance on jQuery position/offset
17683 return [$__default['default'](target)[offsetMethod]().top + offsetBase, targetSelector];
17688 }).filter(function (item) {
17690 }).sort(function (a, b) {
17691 return a[0] - b[0];
17692 }).forEach(function (item) {
17693 _this2._offsets.push(item[0]);
17695 _this2._targets.push(item[1]);
17699 _proto.dispose = function dispose() {
17700 $__default['default'].removeData(this._element, DATA_KEY$8);
17701 $__default['default'](this._scrollElement).off(EVENT_KEY$8);
17702 this._element = null;
17703 this._scrollElement = null;
17704 this._config = null;
17705 this._selector = null;
17706 this._offsets = null;
17707 this._targets = null;
17708 this._activeTarget = null;
17709 this._scrollHeight = null;
17713 _proto._getConfig = function _getConfig(config) {
17714 config = _extends({}, Default$6, typeof config === 'object' && config ? config : {});
17716 if (typeof config.target !== 'string' && Util.isElement(config.target)) {
17717 var id = $__default['default'](config.target).attr('id');
17720 id = Util.getUID(NAME$8);
17721 $__default['default'](config.target).attr('id', id);
17724 config.target = "#" + id;
17727 Util.typeCheckConfig(NAME$8, config, DefaultType$6);
17731 _proto._getScrollTop = function _getScrollTop() {
17732 return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
17735 _proto._getScrollHeight = function _getScrollHeight() {
17736 return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
17739 _proto._getOffsetHeight = function _getOffsetHeight() {
17740 return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
17743 _proto._process = function _process() {
17744 var scrollTop = this._getScrollTop() + this._config.offset;
17746 var scrollHeight = this._getScrollHeight();
17748 var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
17750 if (this._scrollHeight !== scrollHeight) {
17754 if (scrollTop >= maxScroll) {
17755 var target = this._targets[this._targets.length - 1];
17757 if (this._activeTarget !== target) {
17758 this._activate(target);
17764 if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
17765 this._activeTarget = null;
17772 for (var i = this._offsets.length; i--;) {
17773 var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
17775 if (isActiveTarget) {
17776 this._activate(this._targets[i]);
17781 _proto._activate = function _activate(target) {
17782 this._activeTarget = target;
17786 var queries = this._selector.split(',').map(function (selector) {
17787 return selector + "[data-target=\"" + target + "\"]," + selector + "[href=\"" + target + "\"]";
17790 var $link = $__default['default']([].slice.call(document.querySelectorAll(queries.join(','))));
17792 if ($link.hasClass(CLASS_NAME_DROPDOWN_ITEM)) {
17793 $link.closest(SELECTOR_DROPDOWN).find(SELECTOR_DROPDOWN_TOGGLE).addClass(CLASS_NAME_ACTIVE$2);
17794 $link.addClass(CLASS_NAME_ACTIVE$2);
17796 // Set triggered link as active
17797 $link.addClass(CLASS_NAME_ACTIVE$2); // Set triggered links parents as active
17798 // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
17800 $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_LINKS + ", " + SELECTOR_LIST_ITEMS).addClass(CLASS_NAME_ACTIVE$2); // Handle special case when .nav-link is inside .nav-item
17802 $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_ITEMS).children(SELECTOR_NAV_LINKS).addClass(CLASS_NAME_ACTIVE$2);
17805 $__default['default'](this._scrollElement).trigger(EVENT_ACTIVATE, {
17806 relatedTarget: target
17810 _proto._clear = function _clear() {
17811 [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) {
17812 return node.classList.contains(CLASS_NAME_ACTIVE$2);
17813 }).forEach(function (node) {
17814 return node.classList.remove(CLASS_NAME_ACTIVE$2);
17819 ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
17820 return this.each(function () {
17821 var data = $__default['default'](this).data(DATA_KEY$8);
17823 var _config = typeof config === 'object' && config;
17826 data = new ScrollSpy(this, _config);
17827 $__default['default'](this).data(DATA_KEY$8, data);
17830 if (typeof config === 'string') {
17831 if (typeof data[config] === 'undefined') {
17832 throw new TypeError("No method named \"" + config + "\"");
17840 _createClass(ScrollSpy, null, [{
17842 get: function get() {
17847 get: function get() {
17855 * ------------------------------------------------------------------------
17856 * Data Api implementation
17857 * ------------------------------------------------------------------------
17861 $__default['default'](window).on(EVENT_LOAD_DATA_API$2, function () {
17862 var scrollSpys = [].slice.call(document.querySelectorAll(SELECTOR_DATA_SPY));
17863 var scrollSpysLength = scrollSpys.length;
17865 for (var i = scrollSpysLength; i--;) {
17866 var $spy = $__default['default'](scrollSpys[i]);
17868 ScrollSpy._jQueryInterface.call($spy, $spy.data());
17872 * ------------------------------------------------------------------------
17874 * ------------------------------------------------------------------------
17877 $__default['default'].fn[NAME$8] = ScrollSpy._jQueryInterface;
17878 $__default['default'].fn[NAME$8].Constructor = ScrollSpy;
17880 $__default['default'].fn[NAME$8].noConflict = function () {
17881 $__default['default'].fn[NAME$8] = JQUERY_NO_CONFLICT$8;
17882 return ScrollSpy._jQueryInterface;
17886 * ------------------------------------------------------------------------
17888 * ------------------------------------------------------------------------
17891 var NAME$9 = 'tab';
17892 var VERSION$9 = '4.6.0';
17893 var DATA_KEY$9 = 'bs.tab';
17894 var EVENT_KEY$9 = "." + DATA_KEY$9;
17895 var DATA_API_KEY$7 = '.data-api';
17896 var JQUERY_NO_CONFLICT$9 = $__default['default'].fn[NAME$9];
17897 var EVENT_HIDE$3 = "hide" + EVENT_KEY$9;
17898 var EVENT_HIDDEN$3 = "hidden" + EVENT_KEY$9;
17899 var EVENT_SHOW$3 = "show" + EVENT_KEY$9;
17900 var EVENT_SHOWN$3 = "shown" + EVENT_KEY$9;
17901 var EVENT_CLICK_DATA_API$6 = "click" + EVENT_KEY$9 + DATA_API_KEY$7;
17902 var CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu';
17903 var CLASS_NAME_ACTIVE$3 = 'active';
17904 var CLASS_NAME_DISABLED$1 = 'disabled';
17905 var CLASS_NAME_FADE$4 = 'fade';
17906 var CLASS_NAME_SHOW$6 = 'show';
17907 var SELECTOR_DROPDOWN$1 = '.dropdown';
17908 var SELECTOR_NAV_LIST_GROUP$1 = '.nav, .list-group';
17909 var SELECTOR_ACTIVE$2 = '.active';
17910 var SELECTOR_ACTIVE_UL = '> li > .active';
17911 var SELECTOR_DATA_TOGGLE$4 = '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]';
17912 var SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle';
17913 var SELECTOR_DROPDOWN_ACTIVE_CHILD = '> .dropdown-menu .active';
17915 * ------------------------------------------------------------------------
17917 * ------------------------------------------------------------------------
17920 var Tab = /*#__PURE__*/function () {
17921 function Tab(element) {
17922 this._element = element;
17926 var _proto = Tab.prototype;
17929 _proto.show = function show() {
17932 if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $__default['default'](this._element).hasClass(CLASS_NAME_ACTIVE$3) || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED$1)) {
17938 var listElement = $__default['default'](this._element).closest(SELECTOR_NAV_LIST_GROUP$1)[0];
17939 var selector = Util.getSelectorFromElement(this._element);
17942 var itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE$2;
17943 previous = $__default['default'].makeArray($__default['default'](listElement).find(itemSelector));
17944 previous = previous[previous.length - 1];
17947 var hideEvent = $__default['default'].Event(EVENT_HIDE$3, {
17948 relatedTarget: this._element
17950 var showEvent = $__default['default'].Event(EVENT_SHOW$3, {
17951 relatedTarget: previous
17955 $__default['default'](previous).trigger(hideEvent);
17958 $__default['default'](this._element).trigger(showEvent);
17960 if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
17965 target = document.querySelector(selector);
17968 this._activate(this._element, listElement);
17970 var complete = function complete() {
17971 var hiddenEvent = $__default['default'].Event(EVENT_HIDDEN$3, {
17972 relatedTarget: _this._element
17974 var shownEvent = $__default['default'].Event(EVENT_SHOWN$3, {
17975 relatedTarget: previous
17977 $__default['default'](previous).trigger(hiddenEvent);
17978 $__default['default'](_this._element).trigger(shownEvent);
17982 this._activate(target, target.parentNode, complete);
17988 _proto.dispose = function dispose() {
17989 $__default['default'].removeData(this._element, DATA_KEY$9);
17990 this._element = null;
17994 _proto._activate = function _activate(element, container, callback) {
17997 var activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $__default['default'](container).find(SELECTOR_ACTIVE_UL) : $__default['default'](container).children(SELECTOR_ACTIVE$2);
17998 var active = activeElements[0];
17999 var isTransitioning = callback && active && $__default['default'](active).hasClass(CLASS_NAME_FADE$4);
18001 var complete = function complete() {
18002 return _this2._transitionComplete(element, active, callback);
18005 if (active && isTransitioning) {
18006 var transitionDuration = Util.getTransitionDurationFromElement(active);
18007 $__default['default'](active).removeClass(CLASS_NAME_SHOW$6).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
18013 _proto._transitionComplete = function _transitionComplete(element, active, callback) {
18015 $__default['default'](active).removeClass(CLASS_NAME_ACTIVE$3);
18016 var dropdownChild = $__default['default'](active.parentNode).find(SELECTOR_DROPDOWN_ACTIVE_CHILD)[0];
18018 if (dropdownChild) {
18019 $__default['default'](dropdownChild).removeClass(CLASS_NAME_ACTIVE$3);
18022 if (active.getAttribute('role') === 'tab') {
18023 active.setAttribute('aria-selected', false);
18027 $__default['default'](element).addClass(CLASS_NAME_ACTIVE$3);
18029 if (element.getAttribute('role') === 'tab') {
18030 element.setAttribute('aria-selected', true);
18033 Util.reflow(element);
18035 if (element.classList.contains(CLASS_NAME_FADE$4)) {
18036 element.classList.add(CLASS_NAME_SHOW$6);
18039 if (element.parentNode && $__default['default'](element.parentNode).hasClass(CLASS_NAME_DROPDOWN_MENU)) {
18040 var dropdownElement = $__default['default'](element).closest(SELECTOR_DROPDOWN$1)[0];
18042 if (dropdownElement) {
18043 var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(SELECTOR_DROPDOWN_TOGGLE$1));
18044 $__default['default'](dropdownToggleList).addClass(CLASS_NAME_ACTIVE$3);
18047 element.setAttribute('aria-expanded', true);
18056 Tab._jQueryInterface = function _jQueryInterface(config) {
18057 return this.each(function () {
18058 var $this = $__default['default'](this);
18059 var data = $this.data(DATA_KEY$9);
18062 data = new Tab(this);
18063 $this.data(DATA_KEY$9, data);
18066 if (typeof config === 'string') {
18067 if (typeof data[config] === 'undefined') {
18068 throw new TypeError("No method named \"" + config + "\"");
18076 _createClass(Tab, null, [{
18078 get: function get() {
18086 * ------------------------------------------------------------------------
18087 * Data Api implementation
18088 * ------------------------------------------------------------------------
18092 $__default['default'](document).on(EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$4, function (event) {
18093 event.preventDefault();
18095 Tab._jQueryInterface.call($__default['default'](this), 'show');
18098 * ------------------------------------------------------------------------
18100 * ------------------------------------------------------------------------
18103 $__default['default'].fn[NAME$9] = Tab._jQueryInterface;
18104 $__default['default'].fn[NAME$9].Constructor = Tab;
18106 $__default['default'].fn[NAME$9].noConflict = function () {
18107 $__default['default'].fn[NAME$9] = JQUERY_NO_CONFLICT$9;
18108 return Tab._jQueryInterface;
18112 * ------------------------------------------------------------------------
18114 * ------------------------------------------------------------------------
18117 var NAME$a = 'toast';
18118 var VERSION$a = '4.6.0';
18119 var DATA_KEY$a = 'bs.toast';
18120 var EVENT_KEY$a = "." + DATA_KEY$a;
18121 var JQUERY_NO_CONFLICT$a = $__default['default'].fn[NAME$a];
18122 var EVENT_CLICK_DISMISS$1 = "click.dismiss" + EVENT_KEY$a;
18123 var EVENT_HIDE$4 = "hide" + EVENT_KEY$a;
18124 var EVENT_HIDDEN$4 = "hidden" + EVENT_KEY$a;
18125 var EVENT_SHOW$4 = "show" + EVENT_KEY$a;
18126 var EVENT_SHOWN$4 = "shown" + EVENT_KEY$a;
18127 var CLASS_NAME_FADE$5 = 'fade';
18128 var CLASS_NAME_HIDE = 'hide';
18129 var CLASS_NAME_SHOW$7 = 'show';
18130 var CLASS_NAME_SHOWING = 'showing';
18131 var DefaultType$7 = {
18132 animation: 'boolean',
18133 autohide: 'boolean',
18141 var SELECTOR_DATA_DISMISS$1 = '[data-dismiss="toast"]';
18143 * ------------------------------------------------------------------------
18145 * ------------------------------------------------------------------------
18148 var Toast = /*#__PURE__*/function () {
18149 function Toast(element, config) {
18150 this._element = element;
18151 this._config = this._getConfig(config);
18152 this._timeout = null;
18154 this._setListeners();
18158 var _proto = Toast.prototype;
18161 _proto.show = function show() {
18164 var showEvent = $__default['default'].Event(EVENT_SHOW$4);
18165 $__default['default'](this._element).trigger(showEvent);
18167 if (showEvent.isDefaultPrevented()) {
18171 this._clearTimeout();
18173 if (this._config.animation) {
18174 this._element.classList.add(CLASS_NAME_FADE$5);
18177 var complete = function complete() {
18178 _this._element.classList.remove(CLASS_NAME_SHOWING);
18180 _this._element.classList.add(CLASS_NAME_SHOW$7);
18182 $__default['default'](_this._element).trigger(EVENT_SHOWN$4);
18184 if (_this._config.autohide) {
18185 _this._timeout = setTimeout(function () {
18187 }, _this._config.delay);
18191 this._element.classList.remove(CLASS_NAME_HIDE);
18193 Util.reflow(this._element);
18195 this._element.classList.add(CLASS_NAME_SHOWING);
18197 if (this._config.animation) {
18198 var transitionDuration = Util.getTransitionDurationFromElement(this._element);
18199 $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
18205 _proto.hide = function hide() {
18206 if (!this._element.classList.contains(CLASS_NAME_SHOW$7)) {
18210 var hideEvent = $__default['default'].Event(EVENT_HIDE$4);
18211 $__default['default'](this._element).trigger(hideEvent);
18213 if (hideEvent.isDefaultPrevented()) {
18220 _proto.dispose = function dispose() {
18221 this._clearTimeout();
18223 if (this._element.classList.contains(CLASS_NAME_SHOW$7)) {
18224 this._element.classList.remove(CLASS_NAME_SHOW$7);
18227 $__default['default'](this._element).off(EVENT_CLICK_DISMISS$1);
18228 $__default['default'].removeData(this._element, DATA_KEY$a);
18229 this._element = null;
18230 this._config = null;
18234 _proto._getConfig = function _getConfig(config) {
18235 config = _extends({}, Default$7, $__default['default'](this._element).data(), typeof config === 'object' && config ? config : {});
18236 Util.typeCheckConfig(NAME$a, config, this.constructor.DefaultType);
18240 _proto._setListeners = function _setListeners() {
18243 $__default['default'](this._element).on(EVENT_CLICK_DISMISS$1, SELECTOR_DATA_DISMISS$1, function () {
18244 return _this2.hide();
18248 _proto._close = function _close() {
18251 var complete = function complete() {
18252 _this3._element.classList.add(CLASS_NAME_HIDE);
18254 $__default['default'](_this3._element).trigger(EVENT_HIDDEN$4);
18257 this._element.classList.remove(CLASS_NAME_SHOW$7);
18259 if (this._config.animation) {
18260 var transitionDuration = Util.getTransitionDurationFromElement(this._element);
18261 $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
18267 _proto._clearTimeout = function _clearTimeout() {
18268 clearTimeout(this._timeout);
18269 this._timeout = null;
18273 Toast._jQueryInterface = function _jQueryInterface(config) {
18274 return this.each(function () {
18275 var $element = $__default['default'](this);
18276 var data = $element.data(DATA_KEY$a);
18278 var _config = typeof config === 'object' && config;
18281 data = new Toast(this, _config);
18282 $element.data(DATA_KEY$a, data);
18285 if (typeof config === 'string') {
18286 if (typeof data[config] === 'undefined') {
18287 throw new TypeError("No method named \"" + config + "\"");
18290 data[config](this);
18295 _createClass(Toast, null, [{
18297 get: function get() {
18301 key: "DefaultType",
18302 get: function get() {
18303 return DefaultType$7;
18307 get: function get() {
18315 * ------------------------------------------------------------------------
18317 * ------------------------------------------------------------------------
18321 $__default['default'].fn[NAME$a] = Toast._jQueryInterface;
18322 $__default['default'].fn[NAME$a].Constructor = Toast;
18324 $__default['default'].fn[NAME$a].noConflict = function () {
18325 $__default['default'].fn[NAME$a] = JQUERY_NO_CONFLICT$a;
18326 return Toast._jQueryInterface;
18329 exports.Alert = Alert;
18330 exports.Button = Button;
18331 exports.Carousel = Carousel;
18332 exports.Collapse = Collapse;
18333 exports.Dropdown = Dropdown;
18334 exports.Modal = Modal;
18335 exports.Popover = Popover;
18336 exports.Scrollspy = ScrollSpy;
18338 exports.Toast = Toast;
18339 exports.Tooltip = Tooltip;
18340 exports.Util = Util;
18342 Object.defineProperty(exports, '__esModule', { value: true });
18348 const subscriber_queue = [];
18350 * Create a `Writable` store that allows both updating and reading by subscription.
18351 * @param {*=}value initial value
18352 * @param {StartStopNotifier=}start start and stop notifications for subscriptions
18354 function writable(value, start = noop) {
18356 const subscribers = [];
18357 function set(new_value) {
18358 if (safe_not_equal(value, new_value)) {
18360 if (stop) { // store is ready
18361 const run_queue = !subscriber_queue.length;
18362 for (let i = 0; i < subscribers.length; i += 1) {
18363 const s = subscribers[i];
18365 subscriber_queue.push(s, value);
18368 for (let i = 0; i < subscriber_queue.length; i += 2) {
18369 subscriber_queue[i][0](subscriber_queue[i + 1]);
18371 subscriber_queue.length = 0;
18376 function update(fn) {
18379 function subscribe(run, invalidate = noop) {
18380 const subscriber = [run, invalidate];
18381 subscribers.push(subscriber);
18382 if (subscribers.length === 1) {
18383 stop = start(set) || noop;
18387 const index = subscribers.indexOf(subscriber);
18388 if (index !== -1) {
18389 subscribers.splice(index, 1);
18391 if (subscribers.length === 0) {
18397 return { set, update, subscribe };
18400 const map_store = writable();
18401 const results_store = writable();
18402 const current_result_store = writable();
18403 const current_request_latlon = writable();
18404 const last_updated_store = writable();
18406 /* src/components/Header.svelte generated by Svelte v3.31.2 */
18407 const file = "src/components/Header.svelte";
18409 // (76:8) {#if last_updated}
18410 function create_if_block(ctx) {
18425 let t7_value = /*last_updated*/ ctx[0].date + "";
18429 c: function create() {
18430 div = element("div");
18431 t0 = text("Data from ");
18433 t1 = text("API request");
18435 span0 = element("span");
18438 t4 = text("debug output");
18440 t6 = text("\n Data last updated: ");
18441 span1 = element("span");
18442 t7 = text(t7_value);
18443 attr_dev(a0, "href", a0_href_value = /*last_updated*/ ctx[0].api_request_url);
18444 attr_dev(a0, "class", "svelte-1hjkg8o");
18445 add_location(a0, file, 77, 22, 1413);
18446 attr_dev(a1, "href", a1_href_value = /*last_updated*/ ctx[0].api_request_url_debug);
18447 attr_dev(a1, "class", "svelte-1hjkg8o");
18448 add_location(a1, file, 78, 42, 1512);
18449 attr_dev(span0, "id", "api-request-debug");
18450 add_location(span0, file, 78, 12, 1482);
18451 attr_dev(div, "id", "api-request");
18452 add_location(div, file, 76, 10, 1368);
18453 attr_dev(span1, "id", "data-date");
18454 add_location(span1, file, 80, 29, 1630);
18456 m: function mount(target, anchor) {
18457 insert_dev(target, div, anchor);
18458 append_dev(div, t0);
18459 append_dev(div, a0);
18460 append_dev(a0, t1);
18461 append_dev(div, t2);
18462 append_dev(div, span0);
18463 append_dev(span0, t3);
18464 append_dev(span0, a1);
18465 append_dev(a1, t4);
18466 append_dev(span0, t5);
18467 insert_dev(target, t6, anchor);
18468 insert_dev(target, span1, anchor);
18469 append_dev(span1, t7);
18471 p: function update(ctx, dirty) {
18472 if (dirty & /*last_updated*/ 1 && a0_href_value !== (a0_href_value = /*last_updated*/ ctx[0].api_request_url)) {
18473 attr_dev(a0, "href", a0_href_value);
18476 if (dirty & /*last_updated*/ 1 && a1_href_value !== (a1_href_value = /*last_updated*/ ctx[0].api_request_url_debug)) {
18477 attr_dev(a1, "href", a1_href_value);
18480 if (dirty & /*last_updated*/ 1 && t7_value !== (t7_value = /*last_updated*/ ctx[0].date + "")) set_data_dev(t7, t7_value);
18482 d: function destroy(detaching) {
18483 if (detaching) detach_dev(div);
18484 if (detaching) detach_dev(t6);
18485 if (detaching) detach_dev(span1);
18489 dispatch_dev("SvelteRegisterBlock", {
18491 id: create_if_block.name,
18493 source: "(76:8) {#if last_updated}",
18500 function create_fragment(ctx) {
18534 let if_block = /*last_updated*/ ctx[0] && create_if_block(ctx);
18537 c: function create() {
18538 header = element("header");
18539 div9 = element("div");
18540 div1 = element("div");
18541 div0 = element("div");
18543 img = element("img");
18545 h1 = element("h1");
18546 h1.textContent = "Nominatim";
18548 div4 = element("div");
18549 div3 = element("div");
18550 div2 = element("div");
18551 div2.textContent = "loading...";
18553 if (if_block) if_block.c();
18555 div8 = element("div");
18556 div7 = element("div");
18557 button = element("button");
18558 button.textContent = "About & Help";
18560 div6 = element("div");
18562 a1.textContent = "API Reference";
18565 a2.textContent = "FAQ";
18568 a3.textContent = "OpenStreetMap Help";
18571 a4.textContent = "Nominatim on Github";
18574 a5.textContent = "This frontend on Github";
18576 div5 = element("div");
18579 a6.textContent = "Report problem with results";
18580 attr_dev(img, "alt", "logo");
18581 if (img.src !== (img_src_value = "images/osm_logo.120px.png")) attr_dev(img, "src", img_src_value);
18582 attr_dev(img, "width", "30");
18583 attr_dev(img, "height", "30");
18584 attr_dev(img, "class", "svelte-1hjkg8o");
18585 add_location(img, file, 67, 10, 1075);
18586 attr_dev(h1, "class", "svelte-1hjkg8o");
18587 add_location(h1, file, 68, 10, 1158);
18588 attr_dev(a0, "href", "search.html");
18589 attr_dev(a0, "class", "svelte-1hjkg8o");
18590 add_location(a0, file, 66, 8, 1042);
18591 attr_dev(div0, "class", "brand svelte-1hjkg8o");
18592 add_location(div0, file, 65, 6, 1014);
18593 attr_dev(div1, "class", "col-4");
18594 add_location(div1, file, 64, 4, 988);
18595 attr_dev(div2, "id", "loading");
18596 attr_dev(div2, "class", "svelte-1hjkg8o");
18597 add_location(div2, file, 74, 8, 1296);
18598 attr_dev(div3, "id", "last-updated");
18599 attr_dev(div3, "class", "text-center svelte-1hjkg8o");
18600 add_location(div3, file, 73, 6, 1244);
18601 attr_dev(div4, "class", "col-4");
18602 add_location(div4, file, 72, 4, 1218);
18603 attr_dev(button, "class", "dropdown-toggle btn btn-sm btn-outline-secondary");
18604 attr_dev(button, "data-toggle", "dropdown");
18605 attr_dev(button, "role", "button");
18606 attr_dev(button, "aria-haspopup", "true");
18607 attr_dev(button, "aria-expanded", "false");
18608 add_location(button, file, 86, 8, 1788);
18609 attr_dev(a1, "class", "dropdown-item svelte-1hjkg8o");
18610 attr_dev(a1, "href", "https://nominatim.org/release-docs/develop/api/Overview/");
18611 attr_dev(a1, "target", "_blank");
18612 add_location(a1, file, 90, 10, 2045);
18613 attr_dev(a2, "class", "dropdown-item svelte-1hjkg8o");
18614 attr_dev(a2, "href", "https://nominatim.org/release-docs/develop/api/Faq/");
18615 attr_dev(a2, "target", "_blank");
18616 add_location(a2, file, 91, 10, 2178);
18617 attr_dev(a3, "class", "dropdown-item svelte-1hjkg8o");
18618 attr_dev(a3, "href", "https://help.openstreetmap.org/tags/nominatim/");
18619 add_location(a3, file, 92, 10, 2296);
18620 attr_dev(a4, "class", "dropdown-item svelte-1hjkg8o");
18621 attr_dev(a4, "href", "https://github.com/osm-search/Nominatim");
18622 add_location(a4, file, 93, 10, 2408);
18623 attr_dev(a5, "class", "dropdown-item svelte-1hjkg8o");
18624 attr_dev(a5, "href", "https://github.com/osm-search/nominatim-ui");
18625 add_location(a5, file, 94, 10, 2514);
18626 attr_dev(div5, "class", "dropdown-divider");
18627 add_location(div5, file, 95, 10, 2627);
18628 attr_dev(a6, "class", "dropdown-item svelte-1hjkg8o");
18629 attr_dev(a6, "href", "#");
18630 attr_dev(a6, "data-toggle", "modal");
18631 attr_dev(a6, "data-target", "#report-modal");
18632 add_location(a6, file, 96, 10, 2674);
18633 attr_dev(div6, "class", "dropdown-menu dropdown-menu-right svelte-1hjkg8o");
18634 add_location(div6, file, 89, 8, 1987);
18635 attr_dev(div7, "class", "dropdown");
18636 add_location(div7, file, 85, 6, 1757);
18637 attr_dev(div8, "class", "col-4 text-right");
18638 add_location(div8, file, 84, 4, 1720);
18639 attr_dev(div9, "class", "row");
18640 add_location(div9, file, 63, 2, 966);
18641 attr_dev(header, "class", "container-fluid svelte-1hjkg8o");
18642 add_location(header, file, 62, 0, 931);
18644 l: function claim(nodes) {
18645 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
18647 m: function mount(target, anchor) {
18648 insert_dev(target, header, anchor);
18649 append_dev(header, div9);
18650 append_dev(div9, div1);
18651 append_dev(div1, div0);
18652 append_dev(div0, a0);
18653 append_dev(a0, img);
18654 append_dev(a0, t0);
18655 append_dev(a0, h1);
18656 append_dev(div9, t2);
18657 append_dev(div9, div4);
18658 append_dev(div4, div3);
18659 append_dev(div3, div2);
18660 append_dev(div3, t4);
18661 if (if_block) if_block.m(div3, null);
18662 append_dev(div9, t5);
18663 append_dev(div9, div8);
18664 append_dev(div8, div7);
18665 append_dev(div7, button);
18666 append_dev(div7, t7);
18667 append_dev(div7, div6);
18668 append_dev(div6, a1);
18669 append_dev(div6, t9);
18670 append_dev(div6, a2);
18671 append_dev(div6, t11);
18672 append_dev(div6, a3);
18673 append_dev(div6, t13);
18674 append_dev(div6, a4);
18675 append_dev(div6, t15);
18676 append_dev(div6, a5);
18677 append_dev(div6, t17);
18678 append_dev(div6, div5);
18679 append_dev(div6, t18);
18680 append_dev(div6, a6);
18682 p: function update(ctx, [dirty]) {
18683 if (/*last_updated*/ ctx[0]) {
18685 if_block.p(ctx, dirty);
18687 if_block = create_if_block(ctx);
18689 if_block.m(div3, null);
18691 } else if (if_block) {
18698 d: function destroy(detaching) {
18699 if (detaching) detach_dev(header);
18700 if (if_block) if_block.d();
18704 dispatch_dev("SvelteRegisterBlock", {
18706 id: create_fragment.name,
18715 function instance($$self, $$props, $$invalidate) {
18716 let { $$slots: slots = {}, $$scope } = $$props;
18717 validate_slots("Header", slots, []);
18720 last_updated_store.subscribe(data => {
18725 $$invalidate(0, last_updated = data);
18728 const writable_props = [];
18730 Object.keys($$props).forEach(key => {
18731 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Header> was created with unknown prop '${key}'`);
18734 $$self.$capture_state = () => ({ last_updated_store, last_updated });
18736 $$self.$inject_state = $$props => {
18737 if ("last_updated" in $$props) $$invalidate(0, last_updated = $$props.last_updated);
18740 if ($$props && "$$inject" in $$props) {
18741 $$self.$inject_state($$props.$$inject);
18744 return [last_updated];
18747 class Header extends SvelteComponentDev {
18748 constructor(options) {
18750 init(this, options, instance, create_fragment, safe_not_equal, {});
18752 dispatch_dev("SvelteRegisterComponent", {
18756 id: create_fragment.name
18761 /* src/components/Footer.svelte generated by Svelte v3.31.2 */
18763 const file$1 = "src/components/Footer.svelte";
18765 function create_fragment$1(ctx) {
18775 c: function create() {
18776 footer = element("footer");
18778 p0.textContent = "Addresses and postcodes are approximate";
18783 a.textContent = "OpenStreetMap";
18784 t4 = text(" contributors");
18785 attr_dev(p0, "class", "disclaimer svelte-1f2bd8l");
18786 add_location(p0, file$1, 12, 2, 141);
18787 attr_dev(a, "href", "https://osm.org/copyright");
18788 add_location(a, file$1, 16, 11, 250);
18789 attr_dev(p1, "class", "copyright svelte-1f2bd8l");
18790 add_location(p1, file$1, 15, 2, 217);
18791 attr_dev(footer, "class", "svelte-1f2bd8l");
18792 add_location(footer, file$1, 11, 0, 130);
18794 l: function claim(nodes) {
18795 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
18797 m: function mount(target, anchor) {
18798 insert_dev(target, footer, anchor);
18799 append_dev(footer, p0);
18800 append_dev(footer, t1);
18801 append_dev(footer, p1);
18802 append_dev(p1, t2);
18804 append_dev(p1, t4);
18809 d: function destroy(detaching) {
18810 if (detaching) detach_dev(footer);
18814 dispatch_dev("SvelteRegisterBlock", {
18816 id: create_fragment$1.name,
18825 function instance$1($$self, $$props) {
18826 let { $$slots: slots = {}, $$scope } = $$props;
18827 validate_slots("Footer", slots, []);
18828 const writable_props = [];
18830 Object.keys($$props).forEach(key => {
18831 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Footer> was created with unknown prop '${key}'`);
18837 class Footer extends SvelteComponentDev {
18838 constructor(options) {
18840 init(this, options, instance$1, create_fragment$1, safe_not_equal, {});
18842 dispatch_dev("SvelteRegisterComponent", {
18846 id: create_fragment$1.name
18851 /* src/App.svelte generated by Svelte v3.31.2 */
18852 const file$2 = "src/App.svelte";
18854 function create_fragment$2(ctx) {
18861 header = new Header({ $$inline: true });
18862 footer = new Footer({ $$inline: true });
18865 c: function create() {
18866 create_component(header.$$.fragment);
18868 div = element("div");
18870 create_component(footer.$$.fragment);
18871 attr_dev(div, "id", "main");
18872 add_location(div, file$2, 10, 0, 297);
18874 l: function claim(nodes) {
18875 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
18877 m: function mount(target, anchor) {
18878 mount_component(header, target, anchor);
18879 insert_dev(target, t0, anchor);
18880 insert_dev(target, div, anchor);
18881 insert_dev(target, t1, anchor);
18882 mount_component(footer, target, anchor);
18886 i: function intro(local) {
18887 if (current) return;
18888 transition_in(header.$$.fragment, local);
18889 transition_in(footer.$$.fragment, local);
18892 o: function outro(local) {
18893 transition_out(header.$$.fragment, local);
18894 transition_out(footer.$$.fragment, local);
18897 d: function destroy(detaching) {
18898 destroy_component(header, detaching);
18899 if (detaching) detach_dev(t0);
18900 if (detaching) detach_dev(div);
18901 if (detaching) detach_dev(t1);
18902 destroy_component(footer, detaching);
18906 dispatch_dev("SvelteRegisterBlock", {
18908 id: create_fragment$2.name,
18917 function instance$2($$self, $$props, $$invalidate) {
18918 let { $$slots: slots = {}, $$scope } = $$props;
18919 validate_slots("App", slots, []);
18920 const writable_props = [];
18922 Object.keys($$props).forEach(key => {
18923 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<App> was created with unknown prop '${key}'`);
18926 $$self.$capture_state = () => ({ jquery: jquery$1, Header, Footer });
18930 class App extends SvelteComponentDev {
18931 constructor(options) {
18933 init(this, options, instance$2, create_fragment$2, safe_not_equal, {});
18935 dispatch_dev("SvelteRegisterComponent", {
18939 id: create_fragment$2.name
18944 var get_config_value_1 = get_config_value;
18947 const Nominatim_Config_Defaults = {
18948 Nominatim_API_Endpoint: 'http://localhost/nominatim/',
18949 Images_Base_Url: 'mapicons/',
18950 Search_AreaPolygons: 1,
18951 Reverse_Default_Search_Zoom: 18,
18952 Map_Default_Lat: 20.0,
18953 Map_Default_Lon: 0.0,
18954 Map_Default_Zoom: 2,
18955 Map_Tile_URL: 'https://{s}.tile.osm.org/{z}/{x}/{y}.png',
18956 Map_Tile_Attribution: '<a href="https://osm.org/copyright">OpenStreetMap contributors</a>'
18959 function get_config_value(str, default_val) {
18960 var value = ((typeof Nominatim_Config !== 'undefined')
18961 && (typeof Nominatim_Config[str] !== 'undefined'))
18962 ? Nominatim_Config[str]
18963 : Nominatim_Config_Defaults[str];
18964 return (typeof value !== 'undefined' ? value : default_val);
18967 async function fetch_from_api(endpoint_name, params, callback) {
18968 var api_url = generate_nominatim_api_url(endpoint_name, params);
18970 document.getElementById('loading').style.display = 'block';
18971 await fetch(api_url)
18972 .then(response => response.json())
18975 document.getElementById('loading').style.display = 'none';
18979 fetch(generate_nominatim_api_url('status', {format: 'json'}))
18980 .then(response => response.json())
18982 let last_updated = {
18983 api_request_url: api_url,
18984 api_request_url_debug: api_url + '&debug=1',
18985 date: data.data_updated
18987 last_updated_store.set(last_updated);
18991 function generate_nominatim_api_url(endpoint_name, params) {
18992 return get_config_value_1('Nominatim_API_Endpoint') + endpoint_name + '.php?'
18993 + Object.keys(clean_up_parameters(params)).map( (k) => {
18994 return encodeURIComponent(k) + '=' + encodeURIComponent(params[k])
18999 * Serialize all form data into a SearchParams string
19000 * (c) 2020 Chris Ferdinandi, MIT License, https://gomakethings.com
19001 * @param {Node} form The form to serialize
19002 * @return {String} The serialized form data
19004 function serialize_form(form) {
19006 Array.prototype.slice.call(form.elements).forEach(function (field) {
19007 if (!field.name || field.disabled || ['file', 'reset', 'submit', 'button'].indexOf(field.type) > -1) return;
19008 // if (field.type === 'select-multiple') {
19009 // Array.prototype.slice.call(field.options).forEach(function (option) {
19010 // if (!option.selected) return;
19011 // arr.push(encodeURIComponent(field.name) + '=' + encodeURIComponent(option.value));
19015 if (['checkbox', 'radio'].indexOf(field.type) >-1 && !field.checked) return;
19016 if (typeof(field.value) === 'undefined') return;
19017 arr.push(encodeURIComponent(field.name) + '=' + encodeURIComponent(field.value));
19019 return arr.join('&');
19022 // remove any URL paramters with empty values
19023 // '&empty=&filled=value' => 'filled=value'
19024 function clean_up_url_parameters(url) {
19025 var url_params = new URLSearchParams(url);
19026 var to_delete = []; // deleting inside loop would skip iterations
19027 url_params.forEach(function (value, key) {
19028 if (value === '') to_delete.push(key);
19030 for (var i = 0; i < to_delete.length; i += 1) {
19031 url_params.delete(to_delete[i]);
19033 return url_params.toString();
19036 function clean_up_parameters(params) {
19037 // `&a=&b=&c=1` => '&c=1'
19038 var param_names = Object.keys(params);
19039 for (var i = 0; i < param_names.length; i += 1) {
19040 var val = params[param_names[i]];
19041 if (typeof (val) === 'undefined' || val === '' || val === null) {
19042 delete params[param_names[i]];
19048 function update_html_title(title) {
19049 document.title = [title, 'OpenStreetMap Nominatim']
19050 .filter( (val) => val && val.length > 1 )
19056 * Copyright(c) 2012-2013 TJ Holowaychuk
19057 * Copyright(c) 2015 Andreas Lubbe
19058 * Copyright(c) 2015 Tiancheng "Timothy" Gu
19063 * Module variables.
19067 var matchHtmlRegExp = /["'&<>]/;
19074 var escapeHtml_1 = escapeHtml;
19077 * Escape special characters in the given string of html.
19079 * @param {string} string The string to escape for inserting into HTML
19084 function escapeHtml(string) {
19085 var str = '' + string;
19086 var match = matchHtmlRegExp.exec(str);
19097 for (index = match.index; index < str.length; index++) {
19098 switch (str.charCodeAt(index)) {
19118 if (lastIndex !== index) {
19119 html += str.substring(lastIndex, index);
19122 lastIndex = index + 1;
19126 return lastIndex !== index
19127 ? html + str.substring(lastIndex, index)
19131 var formatOSMType_1 = formatOSMType;
19132 var osmLink_1 = osmLink;
19133 var formatLabel_1 = formatLabel;
19134 var detailsURL_1 = detailsURL;
19135 var wikipediaLink_1 = wikipediaLink;
19136 var coverageType_1 = coverageType;
19137 var isAdminBoundary_1 = isAdminBoundary;
19138 var formatAddressRank_1 = formatAddressRank;
19139 var formatPlaceType_1 = formatPlaceType;
19140 var formatAdminLevel_1 = formatAdminLevel;
19141 var formatDistance_1 = formatDistance;
19142 var formatKeywordToken_1 = formatKeywordToken;
19143 var zoomLevels_1 = zoomLevels;
19147 function formatOSMType(sType, bExcludeExternal) {
19148 if (sType === 'N') return 'node';
19149 if (sType === 'W') return 'way';
19150 if (sType === 'R') return 'relation';
19152 if (!bExcludeExternal) return '';
19154 if (sType === 'T') return 'way';
19155 if (sType === 'I') return 'way';
19160 function formatShortOSMType(sType) {
19161 if (sType === 'node') return 'N';
19162 if (sType === 'way') return 'W';
19163 if (sType === 'relation') return 'R';
19167 function osmLink(aPlace) {
19168 if (!aPlace.osm_type) return '';
19169 var sOSMType = formatOSMType(aPlace.osm_type, false);
19170 if (!sOSMType) return '';
19172 return '<a href="https://www.openstreetmap.org/' + sOSMType + '/' + aPlace.osm_id + '">' + sOSMType + ' ' + aPlace.osm_id + '</a>'
19175 function formatLabel(aPlace) {
19176 if (aPlace.label) return aPlace.label;
19178 function capitalize(s) {
19179 return s && s[0].toUpperCase() + s.slice(1);
19182 if (aPlace.type && aPlace.type === 'yes' && aPlace.class) {
19183 return capitalize(aPlace.class.replace(/_/g, ' '));
19186 return capitalize(aPlace.type.replace(/_/g, ' '));
19191 // 'details.html?osmtype=R&osmid=2181874&class=boundary'
19192 function detailsURL(aFeature) {
19193 if (!aFeature) return '';
19195 var sOSMType = aFeature.osm_type;
19196 if (sOSMType && sOSMType.length !== 1) {
19197 sOSMType = formatShortOSMType(aFeature.osm_type); // node => N
19199 if (!sOSMType) return '';
19201 var sURL = 'details.html?osmtype=' + sOSMType + '&osmid=' + aFeature.osm_id;
19202 if (aFeature.class) {
19203 sURL = sURL + '&class=' + encodeURIComponent(aFeature.class);
19204 } else if (aFeature.category) {
19205 sURL = sURL + '&class=' +encodeURIComponent(aFeature.category);
19210 /* en:London_Borough_of_Redbridge => https://en.wikipedia.org/wiki/London_Borough_of_Redbridge */
19211 function wikipediaLink(aPlace) {
19212 if (!aPlace.calculated_wikipedia) return '';
19214 var parts = aPlace.calculated_wikipedia.split(':', 2);
19216 var sTitle = escapeHtml_1(aPlace.calculated_wikipedia);
19217 var sLanguage = escapeHtml_1(parts[0]);
19218 var sArticle = escapeHtml_1(parts[1]);
19220 return '<a href="https://' + sLanguage + '.wikipedia.org/wiki/' + sArticle + '" target="_blank">' + sTitle + '</a>';
19223 function coverageType(aPlace) {
19224 return (aPlace.isarea ? 'Polygon' : 'Point');
19227 function isAdminBoundary(aPlace) {
19228 return aPlace.category === 'boundary' && aPlace.type === 'administrative';
19231 function formatAddressRank(iRank) {
19232 if (iRank < 4) return 'other';
19233 if (iRank < 6) return 'country';
19234 if (iRank < 8) return 'region';
19235 if (iRank < 10) return 'state';
19236 if (iRank < 12) return 'state district';
19237 if (iRank < 14) return 'county';
19238 if (iRank < 16) return 'municipality';
19239 if (iRank < 18) return 'city / town / village';
19240 if (iRank < 20) return 'city / village district';
19241 if (iRank < 22) return 'suburb / hamlet';
19242 if (iRank < 24) return 'neighbourhood';
19243 if (iRank < 26) return 'city block / square';
19244 if (iRank === 26) return 'major street';
19245 if (iRank === 27) return 'minory street / path';
19246 if (iRank <= 30) return 'house / building';
19250 function formatPlaceType(aPlace) {
19251 var sOut = aPlace.class + ':' + aPlace.type;
19252 if (aPlace.type && aPlace.type === 'administrative' && aPlace.place_type) {
19253 sOut = sOut + ' (' + aPlace.place_type + ')';
19255 return escapeHtml_1(sOut);
19258 // Any over 15 are invalid data in OSM anyway
19259 function formatAdminLevel(iLevel) {
19260 return (iLevel < 15 ? iLevel : '');
19263 function formatDistance(fDistance, bInMeters) {
19265 if (fDistance < 1) return '0';
19266 var sFormatted = (fDistance >= 1000)
19267 ? Math.round(fDistance / 1000, 1) + ' km'
19268 : Math.round(fDistance, 0) + ' m';
19270 return '<abbr class="distance" title="' + fDistance + ' meters">~' + sFormatted + '</abbr>';
19273 // spheric distance, http://postgis.net/docs/ST_Distance_Spheroid.html
19274 if (fDistance === 0) return '0';
19276 return '<abbr class="distance" title="spheric distance ' + fDistance + '">~'
19277 + (Math.round(fDistance * 1000, 4) / 1000)
19281 // mark partial tokens (those starting with a space) with a star for readability
19282 function formatKeywordToken(sToken) {
19283 return (sToken[0] === ' ' ? '*' : '') + escapeHtml_1(sToken);
19286 function zoomLevels() {
19287 const aZoomLevels = [
19288 /* 0 */ 'Continent / Sea',
19300 /* 12 */ 'Town / Village',
19306 /* 18 */ 'Building',
19311 return aZoomLevels;
19315 /* src/components/SearchBar.svelte generated by Svelte v3.31.2 */
19317 const { console: console_1 } = globals;
19318 const file$3 = "src/components/SearchBar.svelte";
19320 function get_each_context(ctx, list, i) {
19321 const child_ctx = ctx.slice();
19322 child_ctx[6] = list[i];
19328 function create_else_block(ctx) {
19346 let input0_value_value;
19352 let input1_value_value;
19355 let input2_value_value;
19358 let input3_value_value;
19361 let input4_value_value;
19364 let input5_value_value;
19367 let input6_value_value;
19370 let input7_value_value;
19375 let input8_value_value;
19378 let input9_value_value;
19381 let input10_value_value;
19384 let input11_value_value;
19387 let input12_value_value;
19390 let input13_value_value;
19396 let input14_value_value;
19399 let input15_value_value;
19402 let input16_value_value;
19405 let input17_value_value;
19408 let input18_value_value;
19411 let input19_value_value;
19414 let input20_value_value;
19423 let input21_checked_value;
19429 let input22_checked_value;
19435 let input23_checked_value;
19444 let input24_value_value;
19450 let input25_value_value;
19457 let input26_value_value;
19463 let input27_value_value;
19468 c: function create() {
19469 div11 = element("div");
19470 ul = element("ul");
19471 li0 = element("li");
19473 a0.textContent = "simple";
19475 li1 = element("li");
19477 a1.textContent = "structured";
19479 div0 = element("div");
19481 a2.textContent = "search by id";
19484 a3.textContent = "reverse search";
19486 div10 = element("div");
19487 div2 = element("div");
19488 form0 = element("form");
19489 input0 = element("input");
19491 div1 = element("div");
19492 button0 = element("button");
19493 button0.textContent = "Search";
19495 input1 = element("input");
19497 input2 = element("input");
19499 input3 = element("input");
19501 input4 = element("input");
19503 input5 = element("input");
19505 input6 = element("input");
19507 input7 = element("input");
19509 div4 = element("div");
19510 form1 = element("form");
19511 input8 = element("input");
19513 input9 = element("input");
19515 input10 = element("input");
19517 input11 = element("input");
19519 input12 = element("input");
19521 input13 = element("input");
19523 div3 = element("div");
19524 button1 = element("button");
19525 button1.textContent = "Search";
19527 input14 = element("input");
19529 input15 = element("input");
19531 input16 = element("input");
19533 input17 = element("input");
19535 input18 = element("input");
19537 input19 = element("input");
19539 input20 = element("input");
19542 a4.textContent = "Advanced options";
19544 div9 = element("div");
19545 div8 = element("div");
19546 div5 = element("div");
19547 span0 = element("span");
19548 input21 = element("input");
19550 label0 = element("label");
19551 label0.textContent = "apply viewbox";
19553 span1 = element("span");
19554 input22 = element("input");
19556 label1 = element("label");
19557 label1.textContent = "bounded to viewbox";
19559 span2 = element("span");
19560 input23 = element("input");
19562 label2 = element("label");
19563 label2.textContent = "deduplicate results";
19565 div6 = element("div");
19566 span3 = element("span");
19567 label3 = element("label");
19568 label3.textContent = "Maximum number of results:";
19570 input24 = element("input");
19572 span4 = element("span");
19573 label4 = element("label");
19574 label4.textContent = "Polygon simplification:";
19576 input25 = element("input");
19578 div7 = element("div");
19579 span5 = element("span");
19580 label5 = element("label");
19581 label5.textContent = "Languages:";
19583 input26 = element("input");
19585 span6 = element("span");
19586 label6 = element("label");
19587 label6.textContent = "Countries:";
19589 input27 = element("input");
19590 attr_dev(a0, "class", "nav-link");
19591 attr_dev(a0, "data-toggle", "tab");
19592 attr_dev(a0, "href", "#simple");
19593 toggle_class(a0, "active", !/*bStructuredSearch*/ ctx[0]);
19594 add_location(a0, file$3, 133, 8, 4140);
19595 attr_dev(li0, "class", "nav-item");
19596 add_location(li0, file$3, 132, 6, 4110);
19597 attr_dev(a1, "class", "nav-link");
19598 attr_dev(a1, "data-toggle", "tab");
19599 attr_dev(a1, "href", "#structured");
19600 toggle_class(a1, "active", /*bStructuredSearch*/ ctx[0]);
19601 add_location(a1, file$3, 136, 8, 4286);
19602 attr_dev(li1, "class", "nav-item");
19603 add_location(li1, file$3, 135, 6, 4256);
19604 attr_dev(a2, "href", "details.html");
19605 attr_dev(a2, "class", "mr-2");
19606 add_location(a2, file$3, 139, 8, 4448);
19607 attr_dev(a3, "id", "switch-to-reverse");
19608 attr_dev(a3, "href", "reverse.html");
19609 add_location(a3, file$3, 140, 8, 4509);
19610 attr_dev(div0, "class", "search-type-link svelte-i44z6l");
19611 add_location(div0, file$3, 138, 6, 4409);
19612 attr_dev(ul, "class", "nav nav-tabs");
19613 add_location(ul, file$3, 131, 4, 4078);
19614 attr_dev(input0, "id", "q");
19615 attr_dev(input0, "name", "q");
19616 attr_dev(input0, "type", "text");
19617 attr_dev(input0, "class", "form-control form-control-sm svelte-i44z6l");
19618 attr_dev(input0, "placeholder", "Search");
19619 input0.value = input0_value_value = /*api_request_params*/ ctx[2].q || "";
19620 add_location(input0, file$3, 146, 10, 4814);
19621 attr_dev(button0, "type", "submit");
19622 attr_dev(button0, "class", "btn btn-primary btn-sm mx-1");
19623 add_location(button0, file$3, 154, 12, 5100);
19624 attr_dev(input1, "type", "hidden");
19625 attr_dev(input1, "name", "viewbox");
19626 input1.value = input1_value_value = /*sViewBox*/ ctx[3] || "";
19627 add_location(input1, file$3, 155, 12, 5186);
19628 attr_dev(input2, "type", "hidden");
19629 attr_dev(input2, "name", "dedupe");
19630 input2.value = input2_value_value = !/*api_request_params*/ ctx[2].dedupe ? "" : 1;
19631 add_location(input2, file$3, 156, 12, 5262);
19632 attr_dev(input3, "type", "hidden");
19633 attr_dev(input3, "name", "bounded");
19634 input3.value = input3_value_value = /*api_request_params*/ ctx[2].bounded ? 1 : "";
19635 add_location(input3, file$3, 157, 12, 5358);
19636 attr_dev(input4, "type", "hidden");
19637 attr_dev(input4, "name", "accept-language");
19638 input4.value = input4_value_value = /*api_request_params*/ ctx[2]["accept-language"] || "";
19639 add_location(input4, file$3, 158, 12, 5455);
19640 attr_dev(input5, "type", "hidden");
19641 attr_dev(input5, "name", "countrycodes");
19642 input5.value = input5_value_value = /*api_request_params*/ ctx[2].countrycodes || "";
19643 add_location(input5, file$3, 159, 12, 5568);
19644 attr_dev(input6, "type", "hidden");
19645 attr_dev(input6, "name", "limit");
19646 input6.value = input6_value_value = /*api_request_params*/ ctx[2].limit || "";
19647 add_location(input6, file$3, 160, 12, 5672);
19648 attr_dev(input7, "type", "hidden");
19649 attr_dev(input7, "name", "polygon_threshold");
19650 input7.value = input7_value_value = /*api_request_params*/ ctx[2].polygon_threshold || "";
19651 add_location(input7, file$3, 161, 12, 5762);
19652 attr_dev(div1, "class", "form-group search-button-group svelte-i44z6l");
19653 add_location(div1, file$3, 153, 10, 5043);
19654 attr_dev(form0, "class", "form-inline svelte-i44z6l");
19655 attr_dev(form0, "role", "search");
19656 attr_dev(form0, "accept-charset", "UTF-8");
19657 attr_dev(form0, "action", "");
19658 add_location(form0, file$3, 145, 8, 4730);
19659 attr_dev(div2, "class", "tab-pane");
19660 attr_dev(div2, "id", "simple");
19661 attr_dev(div2, "role", "tabpanel");
19662 toggle_class(div2, "active", !/*bStructuredSearch*/ ctx[0]);
19663 add_location(div2, file$3, 144, 6, 4637);
19664 attr_dev(input8, "name", "street");
19665 attr_dev(input8, "type", "text");
19666 attr_dev(input8, "class", "form-control form-control-sm mr-1");
19667 attr_dev(input8, "placeholder", "House number/Street");
19668 input8.value = input8_value_value = /*api_request_params*/ ctx[2].street || "";
19669 add_location(input8, file$3, 167, 10, 6096);
19670 attr_dev(input9, "name", "city");
19671 attr_dev(input9, "type", "text");
19672 attr_dev(input9, "class", "form-control form-control-sm mr-1");
19673 attr_dev(input9, "placeholder", "City");
19674 input9.value = input9_value_value = /*api_request_params*/ ctx[2].city || "";
19675 add_location(input9, file$3, 170, 10, 6294);
19676 attr_dev(input10, "id", "county");
19677 attr_dev(input10, "name", "county");
19678 attr_dev(input10, "type", "text");
19679 attr_dev(input10, "class", "form-control form-control-sm mr-1");
19680 attr_dev(input10, "placeholder", "County");
19681 input10.value = input10_value_value = /*api_request_params*/ ctx[2].county || "";
19682 add_location(input10, file$3, 173, 10, 6473);
19683 attr_dev(input11, "name", "state");
19684 attr_dev(input11, "type", "text");
19685 attr_dev(input11, "class", "form-control form-control-sm mr-1");
19686 attr_dev(input11, "placeholder", "State");
19687 input11.value = input11_value_value = /*api_request_params*/ ctx[2].state || "";
19688 add_location(input11, file$3, 176, 10, 6670);
19689 attr_dev(input12, "name", "country");
19690 attr_dev(input12, "type", "text");
19691 attr_dev(input12, "class", "form-control form-control-sm mr-1");
19692 attr_dev(input12, "placeholder", "Country");
19693 input12.value = input12_value_value = /*api_request_params*/ ctx[2].country || "";
19694 add_location(input12, file$3, 179, 10, 6852);
19695 attr_dev(input13, "name", "postalcode");
19696 attr_dev(input13, "type", "text");
19697 attr_dev(input13, "class", "form-control form-control-sm mr-1");
19698 attr_dev(input13, "placeholder", "Postal Code");
19699 input13.value = input13_value_value = /*api_request_params*/ ctx[2].postalcode || "";
19700 add_location(input13, file$3, 182, 10, 7040);
19701 attr_dev(button1, "type", "submit");
19702 attr_dev(button1, "class", "btn btn-primary btn-sm mx-1");
19703 add_location(button1, file$3, 187, 12, 7296);
19704 attr_dev(input14, "type", "hidden");
19705 attr_dev(input14, "name", "viewbox");
19706 input14.value = input14_value_value = /*sViewBox*/ ctx[3] || "";
19707 add_location(input14, file$3, 188, 12, 7382);
19708 attr_dev(input15, "type", "hidden");
19709 attr_dev(input15, "name", "dedupe");
19710 input15.value = input15_value_value = !/*api_request_params*/ ctx[2].dedupe ? "" : 1;
19711 add_location(input15, file$3, 189, 12, 7458);
19712 attr_dev(input16, "type", "hidden");
19713 attr_dev(input16, "name", "bounded");
19714 input16.value = input16_value_value = /*api_request_params*/ ctx[2].bounded ? 1 : "";
19715 add_location(input16, file$3, 190, 12, 7554);
19716 attr_dev(input17, "type", "hidden");
19717 attr_dev(input17, "name", "accept-language");
19718 input17.value = input17_value_value = /*api_request_params*/ ctx[2]["accept-language"] || "";
19719 add_location(input17, file$3, 191, 12, 7651);
19720 attr_dev(input18, "type", "hidden");
19721 attr_dev(input18, "name", "countrycodes");
19722 input18.value = input18_value_value = /*api_request_params*/ ctx[2].countrycodes || "";
19723 add_location(input18, file$3, 192, 12, 7764);
19724 attr_dev(input19, "type", "hidden");
19725 attr_dev(input19, "name", "limit");
19726 input19.value = input19_value_value = /*api_request_params*/ ctx[2].limit || "";
19727 add_location(input19, file$3, 193, 12, 7868);
19728 attr_dev(input20, "type", "hidden");
19729 attr_dev(input20, "name", "polygon_threshold");
19730 input20.value = input20_value_value = /*api_request_params*/ ctx[2].polygon_threshold || "";
19731 add_location(input20, file$3, 194, 12, 7958);
19732 attr_dev(div3, "class", "form-group search-button-group svelte-i44z6l");
19733 add_location(div3, file$3, 186, 10, 7239);
19734 attr_dev(form1, "class", "form-inline");
19735 attr_dev(form1, "role", "search");
19736 attr_dev(form1, "accept-charset", "UTF-8");
19737 attr_dev(form1, "action", "");
19738 add_location(form1, file$3, 166, 8, 6012);
19739 attr_dev(div4, "class", "tab-pane");
19740 attr_dev(div4, "id", "structured");
19741 attr_dev(div4, "role", "tabpanel");
19742 toggle_class(div4, "active", /*bStructuredSearch*/ ctx[0]);
19743 add_location(div4, file$3, 165, 6, 5916);
19744 attr_dev(a4, "href", "#advanced");
19745 attr_dev(a4, "class", "btn btn-outline-secondary btn-sm");
19746 attr_dev(a4, "data-toggle", "collapse");
19747 attr_dev(a4, "data-target", "#searchAdvancedOptions");
19748 attr_dev(a4, "role", "button");
19749 attr_dev(a4, "aria-expanded", "false");
19750 attr_dev(a4, "aria-controls", "collapseAdvancedOptions");
19751 add_location(a4, file$3, 199, 6, 8146);
19752 attr_dev(input21, "type", "checkbox");
19753 attr_dev(input21, "class", "form-check-input api-param-setting");
19754 attr_dev(input21, "id", "use_viewbox");
19755 input21.checked = input21_checked_value = /*api_request_params*/ ctx[2].viewbox;
19756 add_location(input21, file$3, 205, 20, 8559);
19757 attr_dev(label0, "class", "form-check-label svelte-i44z6l");
19758 attr_dev(label0, "for", "use_viewbox");
19759 add_location(label0, file$3, 207, 14, 8741);
19760 attr_dev(span0, "class", "svelte-i44z6l");
19761 add_location(span0, file$3, 205, 14, 8553);
19762 attr_dev(input22, "type", "checkbox");
19763 attr_dev(input22, "class", "form-check-input api-param-setting");
19764 attr_dev(input22, "id", "option_bounded");
19765 input22.checked = input22_checked_value = !!/*api_request_params*/ ctx[2].bounded;
19766 add_location(input22, file$3, 208, 20, 8840);
19767 attr_dev(label1, "class", "form-check-label svelte-i44z6l");
19768 attr_dev(label1, "for", "option_bounded");
19769 add_location(label1, file$3, 210, 14, 9025);
19770 attr_dev(span1, "class", "svelte-i44z6l");
19771 add_location(span1, file$3, 208, 14, 8834);
19772 attr_dev(input23, "type", "checkbox");
19773 attr_dev(input23, "class", "form-check-input api-param-setting");
19774 attr_dev(input23, "id", "option_dedupe");
19775 input23.checked = input23_checked_value = !!/*api_request_params*/ ctx[2].dedupe;
19776 add_location(input23, file$3, 211, 20, 9132);
19777 attr_dev(label2, "class", "form-check-label svelte-i44z6l");
19778 attr_dev(label2, "for", "option_dedupe");
19779 add_location(label2, file$3, 213, 14, 9314);
19780 attr_dev(span2, "class", "svelte-i44z6l");
19781 add_location(span2, file$3, 211, 14, 9126);
19782 attr_dev(div5, "class", "form-check form-check-inline");
19783 add_location(div5, file$3, 204, 12, 8496);
19784 attr_dev(label3, "class", "form-check-label svelte-i44z6l");
19785 attr_dev(label3, "for", "option_limit");
19786 add_location(label3, file$3, 216, 20, 9495);
19787 attr_dev(input24, "type", "number");
19788 attr_dev(input24, "class", "form-check-input api-param-setting");
19789 attr_dev(input24, "data-api-param", "limit");
19790 attr_dev(input24, "id", "option_limit");
19791 attr_dev(input24, "size", "5");
19792 attr_dev(input24, "min", "1");
19793 attr_dev(input24, "max", "50");
19794 input24.value = input24_value_value = /*api_request_params*/ ctx[2].limit || "";
19795 add_location(input24, file$3, 217, 14, 9596);
19796 attr_dev(span3, "class", "svelte-i44z6l");
19797 add_location(span3, file$3, 216, 14, 9489);
19798 attr_dev(label4, "class", "form-check-label svelte-i44z6l");
19799 attr_dev(label4, "for", "option_polygon_threashold");
19800 add_location(label4, file$3, 218, 20, 9822);
19801 attr_dev(input25, "type", "number");
19802 attr_dev(input25, "class", "form-check-input api-param-setting");
19803 attr_dev(input25, "data-api-param", "polygon_threshold");
19804 attr_dev(input25, "id", "option_polygon_threshold");
19805 attr_dev(input25, "size", "5");
19806 attr_dev(input25, "min", "0.0");
19807 attr_dev(input25, "step", "0.01");
19808 input25.value = input25_value_value = /*api_request_params*/ ctx[2].polygon_threshold || "";
19809 add_location(input25, file$3, 219, 14, 9933);
19810 attr_dev(span4, "class", "svelte-i44z6l");
19811 add_location(span4, file$3, 218, 14, 9816);
19812 attr_dev(div6, "class", "form-check form-check-inline");
19813 add_location(div6, file$3, 215, 12, 9432);
19814 attr_dev(label5, "class", "form-check-label svelte-i44z6l");
19815 attr_dev(label5, "for", "accept_lang");
19816 add_location(label5, file$3, 222, 20, 10274);
19817 attr_dev(input26, "type", "text");
19818 attr_dev(input26, "placeholder", "e.g. en,zh-Hant");
19819 attr_dev(input26, "class", "form-check-input api-param-setting");
19820 attr_dev(input26, "data-api-param", "accept-language");
19821 attr_dev(input26, "id", "accept_lang");
19822 attr_dev(input26, "size", "15");
19823 input26.value = input26_value_value = /*api_request_params*/ ctx[2]["accept-language"] || "";
19824 add_location(input26, file$3, 223, 14, 10358);
19825 attr_dev(span5, "class", "svelte-i44z6l");
19826 add_location(span5, file$3, 222, 14, 10268);
19827 attr_dev(label6, "class", "form-check-label svelte-i44z6l");
19828 attr_dev(label6, "for", "option_ccode");
19829 add_location(label6, file$3, 224, 20, 10618);
19830 attr_dev(input27, "type", "text");
19831 attr_dev(input27, "placeholder", "e.g. de,gb");
19832 attr_dev(input27, "class", "form-check-input api-param-setting");
19833 attr_dev(input27, "data-api-param", "countrycodes");
19834 attr_dev(input27, "id", "option_ccode");
19835 attr_dev(input27, "size", "15");
19836 input27.value = input27_value_value = /*api_request_params*/ ctx[2].countrycodes || "";
19837 add_location(input27, file$3, 225, 14, 10703);
19838 attr_dev(span6, "class", "svelte-i44z6l");
19839 add_location(span6, file$3, 224, 14, 10612);
19840 attr_dev(div7, "class", "form-check form-check-inline");
19841 add_location(div7, file$3, 221, 12, 10211);
19842 attr_dev(div8, "id", "searchAdvancedOptionsContent");
19843 attr_dev(div8, "class", "svelte-i44z6l");
19844 add_location(div8, file$3, 203, 8, 8444);
19845 attr_dev(div9, "class", "collapse");
19846 attr_dev(div9, "id", "searchAdvancedOptions");
19847 add_location(div9, file$3, 202, 6, 8386);
19848 attr_dev(div10, "class", "tab-content p-2 svelte-i44z6l");
19849 add_location(div10, file$3, 143, 4, 4601);
19850 attr_dev(div11, "class", "top-bar svelte-i44z6l");
19851 add_location(div11, file$3, 130, 2, 4052);
19853 m: function mount(target, anchor) {
19854 insert_dev(target, div11, anchor);
19855 append_dev(div11, ul);
19856 append_dev(ul, li0);
19857 append_dev(li0, a0);
19858 append_dev(ul, t1);
19859 append_dev(ul, li1);
19860 append_dev(li1, a1);
19861 append_dev(ul, t3);
19862 append_dev(ul, div0);
19863 append_dev(div0, a2);
19864 append_dev(div0, t5);
19865 append_dev(div0, a3);
19866 append_dev(div11, t7);
19867 append_dev(div11, div10);
19868 append_dev(div10, div2);
19869 append_dev(div2, form0);
19870 append_dev(form0, input0);
19871 append_dev(form0, t8);
19872 append_dev(form0, div1);
19873 append_dev(div1, button0);
19874 append_dev(div1, t10);
19875 append_dev(div1, input1);
19876 append_dev(div1, t11);
19877 append_dev(div1, input2);
19878 append_dev(div1, t12);
19879 append_dev(div1, input3);
19880 append_dev(div1, t13);
19881 append_dev(div1, input4);
19882 append_dev(div1, t14);
19883 append_dev(div1, input5);
19884 append_dev(div1, t15);
19885 append_dev(div1, input6);
19886 append_dev(div1, t16);
19887 append_dev(div1, input7);
19888 append_dev(div10, t17);
19889 append_dev(div10, div4);
19890 append_dev(div4, form1);
19891 append_dev(form1, input8);
19892 append_dev(form1, t18);
19893 append_dev(form1, input9);
19894 append_dev(form1, t19);
19895 append_dev(form1, input10);
19896 append_dev(form1, t20);
19897 append_dev(form1, input11);
19898 append_dev(form1, t21);
19899 append_dev(form1, input12);
19900 append_dev(form1, t22);
19901 append_dev(form1, input13);
19902 append_dev(form1, t23);
19903 append_dev(form1, div3);
19904 append_dev(div3, button1);
19905 append_dev(div3, t25);
19906 append_dev(div3, input14);
19907 append_dev(div3, t26);
19908 append_dev(div3, input15);
19909 append_dev(div3, t27);
19910 append_dev(div3, input16);
19911 append_dev(div3, t28);
19912 append_dev(div3, input17);
19913 append_dev(div3, t29);
19914 append_dev(div3, input18);
19915 append_dev(div3, t30);
19916 append_dev(div3, input19);
19917 append_dev(div3, t31);
19918 append_dev(div3, input20);
19919 append_dev(div10, t32);
19920 append_dev(div10, a4);
19921 append_dev(div10, t34);
19922 append_dev(div10, div9);
19923 append_dev(div9, div8);
19924 append_dev(div8, div5);
19925 append_dev(div5, span0);
19926 append_dev(span0, input21);
19927 append_dev(span0, t35);
19928 append_dev(span0, label0);
19929 append_dev(div5, t37);
19930 append_dev(div5, span1);
19931 append_dev(span1, input22);
19932 append_dev(span1, t38);
19933 append_dev(span1, label1);
19934 append_dev(div5, t40);
19935 append_dev(div5, span2);
19936 append_dev(span2, input23);
19937 append_dev(span2, t41);
19938 append_dev(span2, label2);
19939 append_dev(div8, t43);
19940 append_dev(div8, div6);
19941 append_dev(div6, span3);
19942 append_dev(span3, label3);
19943 append_dev(span3, t45);
19944 append_dev(span3, input24);
19945 append_dev(div6, t46);
19946 append_dev(div6, span4);
19947 append_dev(span4, label4);
19948 append_dev(span4, t48);
19949 append_dev(span4, input25);
19950 append_dev(div8, t49);
19951 append_dev(div8, div7);
19952 append_dev(div7, span5);
19953 append_dev(span5, label5);
19954 append_dev(span5, t51);
19955 append_dev(span5, input26);
19956 append_dev(div7, t52);
19957 append_dev(div7, span6);
19958 append_dev(span6, label6);
19959 append_dev(span6, t54);
19960 append_dev(span6, input27);
19964 listen_dev(input21, "change", /*reset_viewbox*/ ctx[4], false, false, false),
19965 listen_dev(input22, "change", set_bounded, false, false, false),
19966 listen_dev(input23, "change", set_dedupe, false, false, false),
19967 listen_dev(input24, "change", set_api_param, false, false, false),
19968 listen_dev(input25, "change", set_api_param, false, false, false),
19969 listen_dev(input26, "change", set_api_param, false, false, false),
19970 listen_dev(input27, "change", set_api_param, false, false, false)
19976 p: function update(ctx, dirty) {
19977 if (dirty & /*bStructuredSearch*/ 1) {
19978 toggle_class(a0, "active", !/*bStructuredSearch*/ ctx[0]);
19981 if (dirty & /*bStructuredSearch*/ 1) {
19982 toggle_class(a1, "active", /*bStructuredSearch*/ ctx[0]);
19985 if (dirty & /*api_request_params*/ 4 && input0_value_value !== (input0_value_value = /*api_request_params*/ ctx[2].q || "") && input0.value !== input0_value_value) {
19986 prop_dev(input0, "value", input0_value_value);
19989 if (dirty & /*sViewBox*/ 8 && input1_value_value !== (input1_value_value = /*sViewBox*/ ctx[3] || "")) {
19990 prop_dev(input1, "value", input1_value_value);
19993 if (dirty & /*api_request_params*/ 4 && input2_value_value !== (input2_value_value = !/*api_request_params*/ ctx[2].dedupe ? "" : 1)) {
19994 prop_dev(input2, "value", input2_value_value);
19997 if (dirty & /*api_request_params*/ 4 && input3_value_value !== (input3_value_value = /*api_request_params*/ ctx[2].bounded ? 1 : "")) {
19998 prop_dev(input3, "value", input3_value_value);
20001 if (dirty & /*api_request_params*/ 4 && input4_value_value !== (input4_value_value = /*api_request_params*/ ctx[2]["accept-language"] || "")) {
20002 prop_dev(input4, "value", input4_value_value);
20005 if (dirty & /*api_request_params*/ 4 && input5_value_value !== (input5_value_value = /*api_request_params*/ ctx[2].countrycodes || "")) {
20006 prop_dev(input5, "value", input5_value_value);
20009 if (dirty & /*api_request_params*/ 4 && input6_value_value !== (input6_value_value = /*api_request_params*/ ctx[2].limit || "")) {
20010 prop_dev(input6, "value", input6_value_value);
20013 if (dirty & /*api_request_params*/ 4 && input7_value_value !== (input7_value_value = /*api_request_params*/ ctx[2].polygon_threshold || "")) {
20014 prop_dev(input7, "value", input7_value_value);
20017 if (dirty & /*bStructuredSearch*/ 1) {
20018 toggle_class(div2, "active", !/*bStructuredSearch*/ ctx[0]);
20021 if (dirty & /*api_request_params*/ 4 && input8_value_value !== (input8_value_value = /*api_request_params*/ ctx[2].street || "") && input8.value !== input8_value_value) {
20022 prop_dev(input8, "value", input8_value_value);
20025 if (dirty & /*api_request_params*/ 4 && input9_value_value !== (input9_value_value = /*api_request_params*/ ctx[2].city || "") && input9.value !== input9_value_value) {
20026 prop_dev(input9, "value", input9_value_value);
20029 if (dirty & /*api_request_params*/ 4 && input10_value_value !== (input10_value_value = /*api_request_params*/ ctx[2].county || "") && input10.value !== input10_value_value) {
20030 prop_dev(input10, "value", input10_value_value);
20033 if (dirty & /*api_request_params*/ 4 && input11_value_value !== (input11_value_value = /*api_request_params*/ ctx[2].state || "") && input11.value !== input11_value_value) {
20034 prop_dev(input11, "value", input11_value_value);
20037 if (dirty & /*api_request_params*/ 4 && input12_value_value !== (input12_value_value = /*api_request_params*/ ctx[2].country || "") && input12.value !== input12_value_value) {
20038 prop_dev(input12, "value", input12_value_value);
20041 if (dirty & /*api_request_params*/ 4 && input13_value_value !== (input13_value_value = /*api_request_params*/ ctx[2].postalcode || "") && input13.value !== input13_value_value) {
20042 prop_dev(input13, "value", input13_value_value);
20045 if (dirty & /*sViewBox*/ 8 && input14_value_value !== (input14_value_value = /*sViewBox*/ ctx[3] || "")) {
20046 prop_dev(input14, "value", input14_value_value);
20049 if (dirty & /*api_request_params*/ 4 && input15_value_value !== (input15_value_value = !/*api_request_params*/ ctx[2].dedupe ? "" : 1)) {
20050 prop_dev(input15, "value", input15_value_value);
20053 if (dirty & /*api_request_params*/ 4 && input16_value_value !== (input16_value_value = /*api_request_params*/ ctx[2].bounded ? 1 : "")) {
20054 prop_dev(input16, "value", input16_value_value);
20057 if (dirty & /*api_request_params*/ 4 && input17_value_value !== (input17_value_value = /*api_request_params*/ ctx[2]["accept-language"] || "")) {
20058 prop_dev(input17, "value", input17_value_value);
20061 if (dirty & /*api_request_params*/ 4 && input18_value_value !== (input18_value_value = /*api_request_params*/ ctx[2].countrycodes || "")) {
20062 prop_dev(input18, "value", input18_value_value);
20065 if (dirty & /*api_request_params*/ 4 && input19_value_value !== (input19_value_value = /*api_request_params*/ ctx[2].limit || "")) {
20066 prop_dev(input19, "value", input19_value_value);
20069 if (dirty & /*api_request_params*/ 4 && input20_value_value !== (input20_value_value = /*api_request_params*/ ctx[2].polygon_threshold || "")) {
20070 prop_dev(input20, "value", input20_value_value);
20073 if (dirty & /*bStructuredSearch*/ 1) {
20074 toggle_class(div4, "active", /*bStructuredSearch*/ ctx[0]);
20077 if (dirty & /*api_request_params*/ 4 && input21_checked_value !== (input21_checked_value = /*api_request_params*/ ctx[2].viewbox)) {
20078 prop_dev(input21, "checked", input21_checked_value);
20081 if (dirty & /*api_request_params*/ 4 && input22_checked_value !== (input22_checked_value = !!/*api_request_params*/ ctx[2].bounded)) {
20082 prop_dev(input22, "checked", input22_checked_value);
20085 if (dirty & /*api_request_params*/ 4 && input23_checked_value !== (input23_checked_value = !!/*api_request_params*/ ctx[2].dedupe)) {
20086 prop_dev(input23, "checked", input23_checked_value);
20089 if (dirty & /*api_request_params*/ 4 && input24_value_value !== (input24_value_value = /*api_request_params*/ ctx[2].limit || "")) {
20090 prop_dev(input24, "value", input24_value_value);
20093 if (dirty & /*api_request_params*/ 4 && input25_value_value !== (input25_value_value = /*api_request_params*/ ctx[2].polygon_threshold || "")) {
20094 prop_dev(input25, "value", input25_value_value);
20097 if (dirty & /*api_request_params*/ 4 && input26_value_value !== (input26_value_value = /*api_request_params*/ ctx[2]["accept-language"] || "") && input26.value !== input26_value_value) {
20098 prop_dev(input26, "value", input26_value_value);
20101 if (dirty & /*api_request_params*/ 4 && input27_value_value !== (input27_value_value = /*api_request_params*/ ctx[2].countrycodes || "") && input27.value !== input27_value_value) {
20102 prop_dev(input27, "value", input27_value_value);
20105 d: function destroy(detaching) {
20106 if (detaching) detach_dev(div11);
20112 dispatch_dev("SvelteRegisterBlock", {
20114 id: create_else_block.name,
20116 source: "(129:0) {:else}",
20123 // (90:0) {#if reverse_search}
20124 function create_if_block$1(ctx) {
20133 let input1_value_value;
20140 let input2_value_value;
20147 let option_selected_value;
20148 let select_value_value;
20158 let each_value = zoomLevels_1();
20159 validate_each_argument(each_value);
20160 let each_blocks = [];
20162 for (let i = 0; i < each_value.length; i += 1) {
20163 each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
20167 c: function create() {
20168 div2 = element("div");
20169 form = element("form");
20170 div0 = element("div");
20171 input0 = element("input");
20173 label0 = element("label");
20174 label0.textContent = "lat";
20176 input1 = element("input");
20179 a0.textContent = "<>";
20181 label1 = element("label");
20182 label1.textContent = "lon";
20184 input2 = element("input");
20186 label2 = element("label");
20187 label2.textContent = "max zoom";
20189 select = element("select");
20190 option = element("option");
20193 for (let i = 0; i < each_blocks.length; i += 1) {
20194 each_blocks[i].c();
20198 button = element("button");
20199 button.textContent = "Search";
20201 div1 = element("div");
20203 a1.textContent = "search by id";
20206 a2.textContent = "forward search";
20207 attr_dev(input0, "name", "format");
20208 attr_dev(input0, "type", "hidden");
20209 input0.value = "html";
20210 add_location(input0, file$3, 93, 8, 2644);
20211 attr_dev(label0, "class", "svelte-i44z6l");
20212 add_location(label0, file$3, 94, 8, 2701);
20213 attr_dev(input1, "name", "lat");
20214 attr_dev(input1, "type", "text");
20215 attr_dev(input1, "class", "form-control form-control-sm");
20216 attr_dev(input1, "placeholder", "latitude");
20217 input1.value = input1_value_value = /*api_request_params*/ ctx[2].lat || "";
20218 add_location(input1, file$3, 95, 8, 2728);
20219 attr_dev(a0, "id", "switch-coords");
20220 attr_dev(a0, "class", "btn btn-outline-secondary btn-sm svelte-i44z6l");
20221 attr_dev(a0, "title", "switch lat and lon");
20222 add_location(a0, file$3, 100, 8, 2928);
20223 attr_dev(label1, "class", "svelte-i44z6l");
20224 add_location(label1, file$3, 104, 8, 3133);
20225 attr_dev(input2, "name", "lon");
20226 attr_dev(input2, "type", "text");
20227 attr_dev(input2, "class", "form-control form-control-sm");
20228 attr_dev(input2, "placeholder", "longitude");
20229 input2.value = input2_value_value = /*api_request_params*/ ctx[2].lon || "";
20230 add_location(input2, file$3, 105, 8, 3160);
20231 attr_dev(label2, "class", "svelte-i44z6l");
20232 add_location(label2, file$3, 110, 8, 3361);
20233 option.__value = "";
20234 option.value = option.__value;
20235 option.selected = option_selected_value = !/*api_request_params*/ ctx[2].zoom;
20236 add_location(option, file$3, 112, 10, 3495);
20237 attr_dev(select, "name", "zoom");
20238 attr_dev(select, "class", "form-control form-control-sm");
20239 add_location(select, file$3, 111, 8, 3393);
20240 attr_dev(button, "type", "submit");
20241 attr_dev(button, "class", "btn btn-primary btn-sm mx-1");
20242 add_location(button, file$3, 117, 8, 3752);
20243 attr_dev(div0, "class", "form-group");
20244 add_location(div0, file$3, 92, 6, 2611);
20245 attr_dev(a1, "href", "details.html");
20246 attr_dev(a1, "class", "mr-2");
20247 add_location(a1, file$3, 122, 8, 3904);
20248 attr_dev(a2, "href", "search.html");
20249 add_location(a2, file$3, 123, 8, 3965);
20250 attr_dev(div1, "class", "search-type-link svelte-i44z6l");
20251 add_location(div1, file$3, 121, 6, 3865);
20252 attr_dev(form, "class", "form-inline svelte-i44z6l");
20253 attr_dev(form, "role", "search");
20254 attr_dev(form, "accept-charset", "UTF-8");
20255 attr_dev(form, "action", "");
20256 add_location(form, file$3, 91, 4, 2531);
20257 attr_dev(div2, "class", "top-bar svelte-i44z6l");
20258 add_location(div2, file$3, 90, 2, 2505);
20260 m: function mount(target, anchor) {
20261 insert_dev(target, div2, anchor);
20262 append_dev(div2, form);
20263 append_dev(form, div0);
20264 append_dev(div0, input0);
20265 append_dev(div0, t0);
20266 append_dev(div0, label0);
20267 append_dev(div0, t2);
20268 append_dev(div0, input1);
20269 append_dev(div0, t3);
20270 append_dev(div0, a0);
20271 append_dev(div0, t5);
20272 append_dev(div0, label1);
20273 append_dev(div0, t7);
20274 append_dev(div0, input2);
20275 append_dev(div0, t8);
20276 append_dev(div0, label2);
20277 append_dev(div0, t10);
20278 append_dev(div0, select);
20279 append_dev(select, option);
20280 append_dev(option, t11);
20282 for (let i = 0; i < each_blocks.length; i += 1) {
20283 each_blocks[i].m(select, null);
20286 select_option(select, /*api_request_params*/ ctx[2].zoom);
20287 append_dev(div0, t12);
20288 append_dev(div0, button);
20289 append_dev(form, t14);
20290 append_dev(form, div1);
20291 append_dev(div1, a1);
20292 append_dev(div1, t16);
20293 append_dev(div1, a2);
20296 dispose = listen_dev(a0, "click", stop_propagation(prevent_default(handleSwitchCoords)), false, true, true);
20300 p: function update(ctx, dirty) {
20301 if (dirty & /*api_request_params*/ 4 && input1_value_value !== (input1_value_value = /*api_request_params*/ ctx[2].lat || "") && input1.value !== input1_value_value) {
20302 prop_dev(input1, "value", input1_value_value);
20305 if (dirty & /*api_request_params*/ 4 && input2_value_value !== (input2_value_value = /*api_request_params*/ ctx[2].lon || "") && input2.value !== input2_value_value) {
20306 prop_dev(input2, "value", input2_value_value);
20309 if (dirty & /*api_request_params*/ 4 && option_selected_value !== (option_selected_value = !/*api_request_params*/ ctx[2].zoom)) {
20310 prop_dev(option, "selected", option_selected_value);
20313 if (dirty & /*api_request_params, zoomLevels*/ 4) {
20314 each_value = zoomLevels_1();
20315 validate_each_argument(each_value);
20318 for (i = 0; i < each_value.length; i += 1) {
20319 const child_ctx = get_each_context(ctx, each_value, i);
20321 if (each_blocks[i]) {
20322 each_blocks[i].p(child_ctx, dirty);
20324 each_blocks[i] = create_each_block(child_ctx);
20325 each_blocks[i].c();
20326 each_blocks[i].m(select, null);
20330 for (; i < each_blocks.length; i += 1) {
20331 each_blocks[i].d(1);
20334 each_blocks.length = each_value.length;
20337 if (dirty & /*api_request_params*/ 4 && select_value_value !== (select_value_value = /*api_request_params*/ ctx[2].zoom)) {
20338 select_option(select, /*api_request_params*/ ctx[2].zoom);
20341 d: function destroy(detaching) {
20342 if (detaching) detach_dev(div2);
20343 destroy_each(each_blocks, detaching);
20349 dispatch_dev("SvelteRegisterBlock", {
20351 id: create_if_block$1.name,
20353 source: "(90:0) {#if reverse_search}",
20360 // (114:10) {#each zoomLevels() as zoomTitle, i}
20361 function create_each_block(ctx) {
20365 let t2_value = /*zoomTitle*/ ctx[6] + "";
20367 let option_selected_value;
20370 c: function create() {
20371 option = element("option");
20372 t0 = text(/*i*/ ctx[8]);
20374 t2 = text(t2_value);
20375 option.__value = /*i*/ ctx[8];
20376 option.value = option.__value;
20377 option.selected = option_selected_value = /*i*/ ctx[8] === /*api_request_params*/ ctx[2].zoom;
20378 add_location(option, file$3, 114, 12, 3620);
20380 m: function mount(target, anchor) {
20381 insert_dev(target, option, anchor);
20382 append_dev(option, t0);
20383 append_dev(option, t1);
20384 append_dev(option, t2);
20386 p: function update(ctx, dirty) {
20387 if (dirty & /*api_request_params*/ 4 && option_selected_value !== (option_selected_value = /*i*/ ctx[8] === /*api_request_params*/ ctx[2].zoom)) {
20388 prop_dev(option, "selected", option_selected_value);
20391 d: function destroy(detaching) {
20392 if (detaching) detach_dev(option);
20396 dispatch_dev("SvelteRegisterBlock", {
20398 id: create_each_block.name,
20400 source: "(114:10) {#each zoomLevels() as zoomTitle, i}",
20407 function create_fragment$3(ctx) {
20408 let if_block_anchor;
20410 function select_block_type(ctx, dirty) {
20411 if (/*reverse_search*/ ctx[1]) return create_if_block$1;
20412 return create_else_block;
20415 let current_block_type = select_block_type(ctx);
20416 let if_block = current_block_type(ctx);
20419 c: function create() {
20421 if_block_anchor = empty();
20423 l: function claim(nodes) {
20424 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
20426 m: function mount(target, anchor) {
20427 if_block.m(target, anchor);
20428 insert_dev(target, if_block_anchor, anchor);
20430 p: function update(ctx, [dirty]) {
20431 if (current_block_type === (current_block_type = select_block_type(ctx)) && if_block) {
20432 if_block.p(ctx, dirty);
20435 if_block = current_block_type(ctx);
20439 if_block.m(if_block_anchor.parentNode, if_block_anchor);
20445 d: function destroy(detaching) {
20446 if_block.d(detaching);
20447 if (detaching) detach_dev(if_block_anchor);
20451 dispatch_dev("SvelteRegisterBlock", {
20453 id: create_fragment$3.name,
20462 function map_viewbox_as_string(map) {
20463 var bounds = map.getBounds();
20464 var west = bounds.getWest();
20465 var east = bounds.getEast();
20467 if (east - west >= 360) {
20468 // covers more than whole planet
20469 west = map.getCenter().lng - 179.999;
20471 east = map.getCenter().lng + 179.999;
20474 east = L.latLng(77, east).wrap().lng;
20475 west = L.latLng(77, west).wrap().lng;
20479 bounds.getNorth().toFixed(5),
20481 bounds.getSouth().toFixed(5)
20482 ].join(","); // left
20488 function update_reverse_link(map) {
20489 let link = document.getElementById("switch-to-reverse");
20492 let center_lat_lng = map.wrapLatLng(map.getCenter());
20493 link.href = "reverse.html?lat=" + center_lat_lng.lat.toFixed(5) + "&lon=" + center_lat_lng.lng.toFixed(5);
20497 function set_bounded(e) {
20498 console.log("setting", e.target);
20499 document.querySelector("input[name=bounded]").value = e.target.checked ? 1 : "";
20502 function set_dedupe(e) {
20503 document.querySelector("input[name=dedupe]").value = e.target.checked ? 1 : "";
20506 function set_api_param(e) {
20507 document.querySelector("input[name=" + e.target.dataset["apiParam"] + "]").value = e.target.value;
20510 function handleSwitchCoords() {
20511 let lat = document.querySelector("input[name=lat]").value;
20512 let lon = document.querySelector("input[name=lon]").value;
20513 document.querySelector("input[name=lat]").value = lon;
20514 document.querySelector("input[name=lon]").value = lat;
20515 document.querySelector("form").submit();
20518 function instance$3($$self, $$props, $$invalidate) {
20519 let { $$slots: slots = {}, $$scope } = $$props;
20520 validate_slots("SearchBar", slots, []);
20521 let { bStructuredSearch = false } = $$props;
20522 let { reverse_search = false } = $$props;
20523 let { api_request_params = {} } = $$props;
20526 function set_viewbox(map) {
20527 let set_viewbox = document.getElementById("use_viewbox");
20529 if (set_viewbox && set_viewbox.checked) {
20530 $$invalidate(3, sViewBox = map_viewbox_as_string(map));
20532 $$invalidate(3, sViewBox = "");
20536 map_store.subscribe(map => {
20541 map.on("move", function () {
20543 update_reverse_link(map);
20546 map.on("load", function () {
20548 update_reverse_link(map);
20552 function reset_viewbox() {
20553 let map = get_store_value(map_store);
20562 const writable_props = ["bStructuredSearch", "reverse_search", "api_request_params"];
20564 Object.keys($$props).forEach(key => {
20565 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console_1.warn(`<SearchBar> was created with unknown prop '${key}'`);
20568 $$self.$$set = $$props => {
20569 if ("bStructuredSearch" in $$props) $$invalidate(0, bStructuredSearch = $$props.bStructuredSearch);
20570 if ("reverse_search" in $$props) $$invalidate(1, reverse_search = $$props.reverse_search);
20571 if ("api_request_params" in $$props) $$invalidate(2, api_request_params = $$props.api_request_params);
20574 $$self.$capture_state = () => ({
20575 zoomLevels: zoomLevels_1,
20577 get: get_store_value,
20580 api_request_params,
20582 map_viewbox_as_string,
20584 update_reverse_link,
20592 $$self.$inject_state = $$props => {
20593 if ("bStructuredSearch" in $$props) $$invalidate(0, bStructuredSearch = $$props.bStructuredSearch);
20594 if ("reverse_search" in $$props) $$invalidate(1, reverse_search = $$props.reverse_search);
20595 if ("api_request_params" in $$props) $$invalidate(2, api_request_params = $$props.api_request_params);
20596 if ("sViewBox" in $$props) $$invalidate(3, sViewBox = $$props.sViewBox);
20599 if ($$props && "$$inject" in $$props) {
20600 $$self.$inject_state($$props.$$inject);
20603 return [bStructuredSearch, reverse_search, api_request_params, sViewBox, reset_viewbox];
20606 class SearchBar extends SvelteComponentDev {
20607 constructor(options) {
20610 init(this, options, instance$3, create_fragment$3, safe_not_equal, {
20611 bStructuredSearch: 0,
20613 api_request_params: 2
20616 dispatch_dev("SvelteRegisterComponent", {
20618 tagName: "SearchBar",
20620 id: create_fragment$3.name
20624 get bStructuredSearch() {
20625 throw new Error("<SearchBar>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20628 set bStructuredSearch(value) {
20629 throw new Error("<SearchBar>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20632 get reverse_search() {
20633 throw new Error("<SearchBar>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20636 set reverse_search(value) {
20637 throw new Error("<SearchBar>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20640 get api_request_params() {
20641 throw new Error("<SearchBar>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20644 set api_request_params(value) {
20645 throw new Error("<SearchBar>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20649 /* src/components/Welcome.svelte generated by Svelte v3.31.2 */
20651 const file$4 = "src/components/Welcome.svelte";
20653 function create_fragment$4(ctx) {
20666 c: function create() {
20667 div = element("div");
20668 h2 = element("h2");
20669 h2.textContent = "Welcome to Nominatim";
20672 t2 = text("Nominatim is a search engine for\n ");
20674 a0.textContent = "OpenStreetMap";
20675 t4 = text(" data. This\n is the debugging interface. You may search for a name or address\n (forward search) or look up data by its geographic coordinate (reverse\n search). Each result comes with a link to a details page where you\n can inspect what data about the object is saved in the database and\n investigate how the address of the object has been computed.");
20676 t5 = text("\n\n For more information visit the\n ");
20678 a1.textContent = "Nominatim home page";
20680 add_location(h2, file$4, 1, 2, 21);
20681 attr_dev(a0, "href", "https://www.openstreetmap.org");
20682 add_location(a0, file$4, 5, 4, 99);
20683 add_location(p, file$4, 3, 2, 54);
20684 attr_dev(a1, "href", "https://nominatim.org");
20685 add_location(a1, file$4, 14, 2, 563);
20686 attr_dev(div, "id", "welcome");
20687 add_location(div, file$4, 0, 0, 0);
20689 l: function claim(nodes) {
20690 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
20692 m: function mount(target, anchor) {
20693 insert_dev(target, div, anchor);
20694 append_dev(div, h2);
20695 append_dev(div, t1);
20696 append_dev(div, p);
20700 append_dev(div, t5);
20701 append_dev(div, a1);
20702 append_dev(div, t7);
20707 d: function destroy(detaching) {
20708 if (detaching) detach_dev(div);
20712 dispatch_dev("SvelteRegisterBlock", {
20714 id: create_fragment$4.name,
20723 function instance$4($$self, $$props) {
20724 let { $$slots: slots = {}, $$scope } = $$props;
20725 validate_slots("Welcome", slots, []);
20726 const writable_props = [];
20728 Object.keys($$props).forEach(key => {
20729 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Welcome> was created with unknown prop '${key}'`);
20735 class Welcome extends SvelteComponentDev {
20736 constructor(options) {
20738 init(this, options, instance$4, create_fragment$4, safe_not_equal, {});
20740 dispatch_dev("SvelteRegisterComponent", {
20742 tagName: "Welcome",
20744 id: create_fragment$4.name
20749 /* src/components/MapIcon.svelte generated by Svelte v3.31.2 */
20750 const file$5 = "src/components/MapIcon.svelte";
20752 // (109:0) {#if sIcon}
20753 function create_if_block$2(ctx) {
20758 c: function create() {
20759 img = element("img");
20760 attr_dev(img, "class", "mapicon svelte-180cawe");
20761 if (img.src !== (img_src_value = /*url*/ ctx[2])) attr_dev(img, "src", img_src_value);
20762 attr_dev(img, "alt", /*title*/ ctx[1]);
20763 add_location(img, file$5, 109, 2, 4543);
20765 m: function mount(target, anchor) {
20766 insert_dev(target, img, anchor);
20769 d: function destroy(detaching) {
20770 if (detaching) detach_dev(img);
20774 dispatch_dev("SvelteRegisterBlock", {
20776 id: create_if_block$2.name,
20778 source: "(109:0) {#if sIcon}",
20785 function create_fragment$5(ctx) {
20786 let if_block_anchor;
20787 let if_block = /*sIcon*/ ctx[0] && create_if_block$2(ctx);
20790 c: function create() {
20791 if (if_block) if_block.c();
20792 if_block_anchor = empty();
20794 l: function claim(nodes) {
20795 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
20797 m: function mount(target, anchor) {
20798 if (if_block) if_block.m(target, anchor);
20799 insert_dev(target, if_block_anchor, anchor);
20801 p: function update(ctx, [dirty]) {
20802 if (/*sIcon*/ ctx[0]) if_block.p(ctx, dirty);
20806 d: function destroy(detaching) {
20807 if (if_block) if_block.d(detaching);
20808 if (detaching) detach_dev(if_block_anchor);
20812 dispatch_dev("SvelteRegisterBlock", {
20814 id: create_fragment$5.name,
20823 function getIcon(aPlace) {
20824 // equivalent to PHP Nominatim::ClassTypes::getIcon
20825 // covers 83 of 214 available icon filenames, e.g. transport_roundabout_anticlockwise
20826 // transport_rental_bicycle or place_of_worship_christian would need more data from
20829 "boundary:administrative": "poi_boundary_administrative",
20830 "place:city": "poi_place_city",
20831 "place:town": "poi_place_town",
20832 "place:village": "poi_place_village",
20833 "place:hamlet": "poi_place_village",
20834 "place:suburb": "poi_place_village",
20835 "place:locality": "poi_place_village",
20836 "place:airport": "transport_airport2",
20837 "aeroway:aerodrome": "transport_airport2",
20838 "railway:station": "transport_train_station2",
20839 "amenity:place_of_worship": "place_of_worship_unknown3",
20840 "amenity:pub": "food_pub",
20841 "amenity:bar": "food_bar",
20842 "amenity:university": "education_university",
20843 "tourism:museum": "tourist_museum",
20844 "amenity:arts_centre": "tourist_art_gallery2",
20845 "tourism:zoo": "tourist_zoo",
20846 "tourism:theme_park": "poi_point_of_interest",
20847 "tourism:attraction": "poi_point_of_interest",
20848 "leisure:golf_course": "sport_golf",
20849 "historic:castle": "tourist_castle",
20850 "amenity:hospital": "health_hospital",
20851 "amenity:school": "education_school",
20852 "amenity:theatre": "tourist_theatre",
20853 "amenity:library": "amenity_library",
20854 "amenity:fire_station": "amenity_firestation3",
20855 "amenity:police": "amenity_police2",
20856 "amenity:bank": "money_bank2",
20857 "amenity:post_office": "amenity_post_office",
20858 "tourism:hotel": "accommodation_hotel2",
20859 "amenity:cinema": "tourist_cinema",
20860 "tourism:artwork": "tourist_art_gallery2",
20861 "historic:archaeological_site": "tourist_archaeological2",
20862 "amenity:doctors": "health_doctors",
20863 "leisure:sports_centre": "sport_leisure_centre",
20864 "leisure:swimming_pool": "sport_swimming_outdoor",
20865 "shop:supermarket": "shopping_supermarket",
20866 "shop:convenience": "shopping_convenience",
20867 "amenity:restaurant": "food_restaurant",
20868 "amenity:fast_food": "food_fastfood",
20869 "amenity:cafe": "food_cafe",
20870 "tourism:guest_house": "accommodation_bed_and_breakfast",
20871 "amenity:pharmacy": "health_pharmacy_dispensing",
20872 "amenity:fuel": "transport_fuel",
20873 "natural:peak": "poi_peak",
20874 "natural:wood": "landuse_coniferous_and_deciduous",
20875 "shop:bicycle": "shopping_bicycle",
20876 "shop:clothes": "shopping_clothes",
20877 "shop:hairdresser": "shopping_hairdresser",
20878 "shop:doityourself": "shopping_diy",
20879 "shop:estate_agent": "shopping_estateagent2",
20880 "shop:car": "shopping_car",
20881 "shop:garden_centre": "shopping_garden_centre",
20882 "shop:car_repair": "shopping_car_repair",
20883 "shop:bakery": "shopping_bakery",
20884 "shop:butcher": "shopping_butcher",
20885 "shop:apparel": "shopping_clothes",
20886 "shop:laundry": "shopping_laundrette",
20887 "shop:beverages": "shopping_alcohol",
20888 "shop:alcohol": "shopping_alcohol",
20889 "shop:optician": "health_opticians",
20890 "shop:chemist": "health_pharmacy",
20891 "shop:gallery": "tourist_art_gallery2",
20892 "shop:jewelry": "shopping_jewelry",
20893 "tourism:information": "amenity_information",
20894 "historic:ruins": "tourist_ruin",
20895 "amenity:college": "education_school",
20896 "historic:monument": "tourist_monument",
20897 "historic:memorial": "tourist_monument",
20898 "historic:mine": "poi_mine",
20899 "tourism:caravan_site": "accommodation_caravan_park",
20900 "amenity:bus_station": "transport_bus_station",
20901 "amenity:atm": "money_atm2",
20902 "tourism:viewpoint": "tourist_view_point",
20903 "tourism:guesthouse": "accommodation_bed_and_breakfast",
20904 "railway:tram": "transport_tram_stop",
20905 "amenity:courthouse": "amenity_court",
20906 "amenity:recycling": "amenity_recycling",
20907 "amenity:dentist": "health_dentist",
20908 "natural:beach": "tourist_beach",
20909 "railway:tram_stop": "transport_tram_stop",
20910 "amenity:prison": "amenity_prison",
20911 "highway:bus_stop": "transport_bus_stop2"
20914 var sCategoryPlace = aPlace.category + ":" + aPlace.type;
20915 return aIcons[sCategoryPlace];
20918 function instance$5($$self, $$props, $$invalidate) {
20919 let { $$slots: slots = {}, $$scope } = $$props;
20920 validate_slots("MapIcon", slots, []);
20921 let { aPlace } = $$props;
20922 let sIcon = getIcon(aPlace);
20923 let title = "icon for " + aPlace.category + " " + aPlace.type;
20924 let url = get_config_value_1("Images_Base_Url") + sIcon + ".p.20.png";
20925 const writable_props = ["aPlace"];
20927 Object.keys($$props).forEach(key => {
20928 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<MapIcon> was created with unknown prop '${key}'`);
20931 $$self.$$set = $$props => {
20932 if ("aPlace" in $$props) $$invalidate(3, aPlace = $$props.aPlace);
20935 $$self.$capture_state = () => ({
20937 get_config_value: get_config_value_1,
20944 $$self.$inject_state = $$props => {
20945 if ("aPlace" in $$props) $$invalidate(3, aPlace = $$props.aPlace);
20946 if ("sIcon" in $$props) $$invalidate(0, sIcon = $$props.sIcon);
20947 if ("title" in $$props) $$invalidate(1, title = $$props.title);
20948 if ("url" in $$props) $$invalidate(2, url = $$props.url);
20951 if ($$props && "$$inject" in $$props) {
20952 $$self.$inject_state($$props.$$inject);
20955 return [sIcon, title, url, aPlace];
20958 class MapIcon extends SvelteComponentDev {
20959 constructor(options) {
20961 init(this, options, instance$5, create_fragment$5, safe_not_equal, { aPlace: 3 });
20963 dispatch_dev("SvelteRegisterComponent", {
20965 tagName: "MapIcon",
20967 id: create_fragment$5.name
20970 const { ctx } = this.$$;
20971 const props = options.props || {};
20973 if (/*aPlace*/ ctx[3] === undefined && !("aPlace" in props)) {
20974 console.warn("<MapIcon> was created without expected prop 'aPlace'");
20979 throw new Error("<MapIcon>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20982 set aPlace(value) {
20983 throw new Error("<MapIcon>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20987 /* src/components/ResultsList.svelte generated by Svelte v3.31.2 */
20988 const file$6 = "src/components/ResultsList.svelte";
20990 function get_each_context$1(ctx, list, i) {
20991 const child_ctx = ctx.slice();
20992 child_ctx[5] = list[i];
20998 function create_else_block_1(ctx) {
21001 welcome = new Welcome({ $$inline: true });
21004 c: function create() {
21005 create_component(welcome.$$.fragment);
21007 m: function mount(target, anchor) {
21008 mount_component(welcome, target, anchor);
21012 i: function intro(local) {
21013 if (current) return;
21014 transition_in(welcome.$$.fragment, local);
21017 o: function outro(local) {
21018 transition_out(welcome.$$.fragment, local);
21021 d: function destroy(detaching) {
21022 destroy_component(welcome, detaching);
21026 dispatch_dev("SvelteRegisterBlock", {
21028 id: create_else_block_1.name,
21030 source: "(83:0) {:else}",
21038 function create_if_block_2(ctx) {
21039 let if_block_anchor;
21041 function select_block_type_1(ctx, dirty) {
21042 if (/*reverse_search*/ ctx[0]) return create_if_block_3;
21043 return create_else_block$1;
21046 let current_block_type = select_block_type_1(ctx);
21047 let if_block = current_block_type(ctx);
21050 c: function create() {
21052 if_block_anchor = empty();
21054 m: function mount(target, anchor) {
21055 if_block.m(target, anchor);
21056 insert_dev(target, if_block_anchor, anchor);
21058 p: function update(ctx, dirty) {
21059 if (current_block_type !== (current_block_type = select_block_type_1(ctx))) {
21061 if_block = current_block_type(ctx);
21065 if_block.m(if_block_anchor.parentNode, if_block_anchor);
21071 d: function destroy(detaching) {
21072 if_block.d(detaching);
21073 if (detaching) detach_dev(if_block_anchor);
21077 dispatch_dev("SvelteRegisterBlock", {
21079 id: create_if_block_2.name,
21081 source: "(77:25) ",
21088 // (53:0) {#if aSearchResults && aSearchResults.length > 0}
21089 function create_if_block$3(ctx) {
21093 let each_value = /*aSearchResults*/ ctx[1];
21094 validate_each_argument(each_value);
21095 let each_blocks = [];
21097 for (let i = 0; i < each_value.length; i += 1) {
21098 each_blocks[i] = create_each_block$1(get_each_context$1(ctx, each_value, i));
21101 const out = i => transition_out(each_blocks[i], 1, 1, () => {
21102 each_blocks[i] = null;
21105 let if_block = /*sMoreURL*/ ctx[3] && !/*reverse_search*/ ctx[0] && create_if_block_1(ctx);
21108 c: function create() {
21109 div = element("div");
21111 for (let i = 0; i < each_blocks.length; i += 1) {
21112 each_blocks[i].c();
21116 if (if_block) if_block.c();
21117 attr_dev(div, "id", "searchresults");
21118 add_location(div, file$6, 53, 2, 1681);
21120 m: function mount(target, anchor) {
21121 insert_dev(target, div, anchor);
21123 for (let i = 0; i < each_blocks.length; i += 1) {
21124 each_blocks[i].m(div, null);
21127 append_dev(div, t);
21128 if (if_block) if_block.m(div, null);
21131 p: function update(ctx, dirty) {
21132 if (dirty & /*iHighlightNum, handleClick, detailsURL, aSearchResults, formatLabel*/ 22) {
21133 each_value = /*aSearchResults*/ ctx[1];
21134 validate_each_argument(each_value);
21137 for (i = 0; i < each_value.length; i += 1) {
21138 const child_ctx = get_each_context$1(ctx, each_value, i);
21140 if (each_blocks[i]) {
21141 each_blocks[i].p(child_ctx, dirty);
21142 transition_in(each_blocks[i], 1);
21144 each_blocks[i] = create_each_block$1(child_ctx);
21145 each_blocks[i].c();
21146 transition_in(each_blocks[i], 1);
21147 each_blocks[i].m(div, t);
21153 for (i = each_value.length; i < each_blocks.length; i += 1) {
21160 if (/*sMoreURL*/ ctx[3] && !/*reverse_search*/ ctx[0]) {
21162 if_block.p(ctx, dirty);
21164 if_block = create_if_block_1(ctx);
21166 if_block.m(div, null);
21168 } else if (if_block) {
21173 i: function intro(local) {
21174 if (current) return;
21176 for (let i = 0; i < each_value.length; i += 1) {
21177 transition_in(each_blocks[i]);
21182 o: function outro(local) {
21183 each_blocks = each_blocks.filter(Boolean);
21185 for (let i = 0; i < each_blocks.length; i += 1) {
21186 transition_out(each_blocks[i]);
21191 d: function destroy(detaching) {
21192 if (detaching) detach_dev(div);
21193 destroy_each(each_blocks, detaching);
21194 if (if_block) if_block.d();
21198 dispatch_dev("SvelteRegisterBlock", {
21200 id: create_if_block$3.name,
21202 source: "(53:0) {#if aSearchResults && aSearchResults.length > 0}",
21210 function create_else_block$1(ctx) {
21214 c: function create() {
21215 div = element("div");
21216 div.textContent = "No search results found";
21217 attr_dev(div, "class", "noresults svelte-d36c6n");
21218 add_location(div, file$6, 80, 4, 2634);
21220 m: function mount(target, anchor) {
21221 insert_dev(target, div, anchor);
21223 d: function destroy(detaching) {
21224 if (detaching) detach_dev(div);
21228 dispatch_dev("SvelteRegisterBlock", {
21230 id: create_else_block$1.name,
21232 source: "(80:2) {:else}",
21239 // (78:2) {#if reverse_search}
21240 function create_if_block_3(ctx) {
21244 c: function create() {
21245 div = element("div");
21246 div.textContent = "Search for coordinates or click anywhere on the map.";
21247 attr_dev(div, "id", "intro");
21248 attr_dev(div, "class", "sidebar");
21249 add_location(div, file$6, 78, 4, 2529);
21251 m: function mount(target, anchor) {
21252 insert_dev(target, div, anchor);
21254 d: function destroy(detaching) {
21255 if (detaching) detach_dev(div);
21259 dispatch_dev("SvelteRegisterBlock", {
21261 id: create_if_block_3.name,
21263 source: "(78:2) {#if reverse_search}",
21270 // (56:4) {#each aSearchResults as aResult, iResNum}
21271 function create_each_block$1(ctx) {
21277 let t1_value = /*aResult*/ ctx[5].display_name + "";
21281 let t3_value = formatLabel_1(/*aResult*/ ctx[5]) + "";
21285 let t5_value = /*aResult*/ ctx[5].lat + "";
21288 let t7_value = /*aResult*/ ctx[5].lon + "";
21298 mapicon = new MapIcon({
21299 props: { aPlace: /*aResult*/ ctx[5] },
21304 c: function create() {
21305 div1 = element("div");
21306 div0 = element("div");
21307 create_component(mapicon.$$.fragment);
21309 span0 = element("span");
21310 t1 = text(t1_value);
21312 span1 = element("span");
21313 t3 = text(t3_value);
21316 t5 = text(t5_value);
21318 t7 = text(t7_value);
21321 t9 = text("details");
21322 set_style(div0, "float", "right");
21323 add_location(div0, file$6, 57, 8, 1898);
21324 attr_dev(span0, "class", "name");
21325 add_location(span0, file$6, 60, 8, 1986);
21326 attr_dev(span1, "class", "type svelte-d36c6n");
21327 add_location(span1, file$6, 61, 8, 2043);
21328 attr_dev(p, "class", "coords svelte-d36c6n");
21329 add_location(p, file$6, 62, 8, 2100);
21330 attr_dev(a, "class", "details btn btn-outline-secondary btn-sm svelte-d36c6n");
21331 attr_dev(a, "href", a_href_value = detailsURL_1(/*aResult*/ ctx[5]));
21332 add_location(a, file$6, 64, 8, 2161);
21333 attr_dev(div1, "class", "result svelte-d36c6n");
21334 attr_dev(div1, "data-position", /*iResNum*/ ctx[7]);
21335 toggle_class(div1, "highlight", /*iResNum*/ ctx[7] === /*iHighlightNum*/ ctx[2]);
21336 add_location(div1, file$6, 56, 6, 1760);
21338 m: function mount(target, anchor) {
21339 insert_dev(target, div1, anchor);
21340 append_dev(div1, div0);
21341 mount_component(mapicon, div0, null);
21342 append_dev(div1, t0);
21343 append_dev(div1, span0);
21344 append_dev(span0, t1);
21345 append_dev(div1, t2);
21346 append_dev(div1, span1);
21347 append_dev(span1, t3);
21348 append_dev(div1, t4);
21349 append_dev(div1, p);
21353 append_dev(div1, t8);
21354 append_dev(div1, a);
21359 dispose = listen_dev(div1, "click", stop_propagation(/*handleClick*/ ctx[4]), false, false, true);
21363 p: function update(ctx, dirty) {
21364 const mapicon_changes = {};
21365 if (dirty & /*aSearchResults*/ 2) mapicon_changes.aPlace = /*aResult*/ ctx[5];
21366 mapicon.$set(mapicon_changes);
21367 if ((!current || dirty & /*aSearchResults*/ 2) && t1_value !== (t1_value = /*aResult*/ ctx[5].display_name + "")) set_data_dev(t1, t1_value);
21368 if ((!current || dirty & /*aSearchResults*/ 2) && t3_value !== (t3_value = formatLabel_1(/*aResult*/ ctx[5]) + "")) set_data_dev(t3, t3_value);
21369 if ((!current || dirty & /*aSearchResults*/ 2) && t5_value !== (t5_value = /*aResult*/ ctx[5].lat + "")) set_data_dev(t5, t5_value);
21370 if ((!current || dirty & /*aSearchResults*/ 2) && t7_value !== (t7_value = /*aResult*/ ctx[5].lon + "")) set_data_dev(t7, t7_value);
21372 if (!current || dirty & /*aSearchResults*/ 2 && a_href_value !== (a_href_value = detailsURL_1(/*aResult*/ ctx[5]))) {
21373 attr_dev(a, "href", a_href_value);
21376 if (dirty & /*iHighlightNum*/ 4) {
21377 toggle_class(div1, "highlight", /*iResNum*/ ctx[7] === /*iHighlightNum*/ ctx[2]);
21380 i: function intro(local) {
21381 if (current) return;
21382 transition_in(mapicon.$$.fragment, local);
21385 o: function outro(local) {
21386 transition_out(mapicon.$$.fragment, local);
21389 d: function destroy(detaching) {
21390 if (detaching) detach_dev(div1);
21391 destroy_component(mapicon);
21397 dispatch_dev("SvelteRegisterBlock", {
21399 id: create_each_block$1.name,
21401 source: "(56:4) {#each aSearchResults as aResult, iResNum}",
21408 // (69:4) {#if sMoreURL && !reverse_search}
21409 function create_if_block_1(ctx) {
21415 c: function create() {
21416 div = element("div");
21418 t = text("Search for more results");
21419 attr_dev(a, "class", "btn btn-primary");
21420 attr_dev(a, "href", /*sMoreURL*/ ctx[3]);
21421 add_location(a, file$6, 70, 8, 2351);
21422 attr_dev(div, "class", "more svelte-d36c6n");
21423 add_location(div, file$6, 69, 6, 2324);
21425 m: function mount(target, anchor) {
21426 insert_dev(target, div, anchor);
21427 append_dev(div, a);
21430 p: function update(ctx, dirty) {
21431 if (dirty & /*sMoreURL*/ 8) {
21432 attr_dev(a, "href", /*sMoreURL*/ ctx[3]);
21435 d: function destroy(detaching) {
21436 if (detaching) detach_dev(div);
21440 dispatch_dev("SvelteRegisterBlock", {
21442 id: create_if_block_1.name,
21444 source: "(69:4) {#if sMoreURL && !reverse_search}",
21451 function create_fragment$6(ctx) {
21452 let current_block_type_index;
21454 let if_block_anchor;
21456 const if_block_creators = [create_if_block$3, create_if_block_2, create_else_block_1];
21457 const if_blocks = [];
21459 function select_block_type(ctx, dirty) {
21460 if (/*aSearchResults*/ ctx[1] && /*aSearchResults*/ ctx[1].length > 0) return 0;
21461 if (/*aSearchResults*/ ctx[1]) return 1;
21465 current_block_type_index = select_block_type(ctx);
21466 if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
21469 c: function create() {
21471 if_block_anchor = empty();
21473 l: function claim(nodes) {
21474 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
21476 m: function mount(target, anchor) {
21477 if_blocks[current_block_type_index].m(target, anchor);
21478 insert_dev(target, if_block_anchor, anchor);
21481 p: function update(ctx, [dirty]) {
21482 let previous_block_index = current_block_type_index;
21483 current_block_type_index = select_block_type(ctx);
21485 if (current_block_type_index === previous_block_index) {
21486 if_blocks[current_block_type_index].p(ctx, dirty);
21490 transition_out(if_blocks[previous_block_index], 1, 1, () => {
21491 if_blocks[previous_block_index] = null;
21495 if_block = if_blocks[current_block_type_index];
21498 if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
21501 if_block.p(ctx, dirty);
21504 transition_in(if_block, 1);
21505 if_block.m(if_block_anchor.parentNode, if_block_anchor);
21508 i: function intro(local) {
21509 if (current) return;
21510 transition_in(if_block);
21513 o: function outro(local) {
21514 transition_out(if_block);
21517 d: function destroy(detaching) {
21518 if_blocks[current_block_type_index].d(detaching);
21519 if (detaching) detach_dev(if_block_anchor);
21523 dispatch_dev("SvelteRegisterBlock", {
21525 id: create_fragment$6.name,
21534 function instance$6($$self, $$props, $$invalidate) {
21535 let { $$slots: slots = {}, $$scope } = $$props;
21536 validate_slots("ResultsList", slots, []);
21537 let { reverse_search = false } = $$props;
21538 let aSearchResults;
21542 results_store.subscribe(data => {
21547 $$invalidate(1, aSearchResults = data);
21548 $$invalidate(2, iHighlightNum = 0);
21549 current_result_store.set(aSearchResults[0]);
21550 let search_params = new URLSearchParams(window.location.search);
21551 let aResults = data;
21553 // lonvia wrote: https://github.com/osm-search/nominatim-ui/issues/24
21554 // I would suggest to remove the guessing and always show the link. Nominatim only returns
21555 // one or two results when it believes the result to be a good enough match.
21556 // if (aResults.length >= 10) {
21557 var aExcludePlaceIds = [];
21559 if (search_params.has("exclude_place_ids")) {
21560 aExcludePlaceIds = search_params.get("exclude_place_ids").split(",");
21563 for (var i = 0; i < aResults.length; i += 1) {
21564 aExcludePlaceIds.push(aResults[i].place_id);
21567 var parsed_url = new URLSearchParams(window.location.search);
21568 parsed_url.set("exclude_place_ids", aExcludePlaceIds.join(","));
21569 $$invalidate(3, sMoreURL = "?" + parsed_url.toString());
21572 function handleClick(e) {
21573 let result_el = e.target;
21575 if (!result_el.className.match("result")) {
21576 result_el = result_el.parentElement;
21579 let pos = Number(result_el.dataset.position);
21580 current_result_store.set(aSearchResults[pos]);
21581 $$invalidate(2, iHighlightNum = pos);
21584 const writable_props = ["reverse_search"];
21586 Object.keys($$props).forEach(key => {
21587 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<ResultsList> was created with unknown prop '${key}'`);
21590 $$self.$$set = $$props => {
21591 if ("reverse_search" in $$props) $$invalidate(0, reverse_search = $$props.reverse_search);
21594 $$self.$capture_state = () => ({
21596 current_result_store,
21597 formatLabel: formatLabel_1,
21598 detailsURL: detailsURL_1,
21608 $$self.$inject_state = $$props => {
21609 if ("reverse_search" in $$props) $$invalidate(0, reverse_search = $$props.reverse_search);
21610 if ("aSearchResults" in $$props) $$invalidate(1, aSearchResults = $$props.aSearchResults);
21611 if ("iHighlightNum" in $$props) $$invalidate(2, iHighlightNum = $$props.iHighlightNum);
21612 if ("sMoreURL" in $$props) $$invalidate(3, sMoreURL = $$props.sMoreURL);
21615 if ($$props && "$$inject" in $$props) {
21616 $$self.$inject_state($$props.$$inject);
21619 return [reverse_search, aSearchResults, iHighlightNum, sMoreURL, handleClick];
21622 class ResultsList extends SvelteComponentDev {
21623 constructor(options) {
21625 init(this, options, instance$6, create_fragment$6, safe_not_equal, { reverse_search: 0 });
21627 dispatch_dev("SvelteRegisterComponent", {
21629 tagName: "ResultsList",
21631 id: create_fragment$6.name
21635 get reverse_search() {
21636 throw new Error("<ResultsList>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
21639 set reverse_search(value) {
21640 throw new Error("<ResultsList>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
21645 * Leaflet 1.7.1, a JS library for interactive maps. http://leafletjs.com
21646 * (c) 2010-2019 Vladimir Agafonkin, (c) 2010-2011 CloudMade
21649 var leafletSrc = createCommonjsModule(function (module, exports) {
21650 (function (global, factory) {
21652 }(commonjsGlobal, (function (exports) {
21653 var version = "1.7.1";
21656 * @namespace Util
\r
21658 * Various utility functions, used by Leaflet internally.
\r
21661 // @function extend(dest: Object, src?: Object): Object
\r
21662 // Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut.
\r
21663 function extend(dest) {
\r
21664 var i, j, len, src;
\r
21666 for (j = 1, len = arguments.length; j < len; j++) {
\r
21667 src = arguments[j];
\r
21669 dest[i] = src[i];
\r
21675 // @function create(proto: Object, properties?: Object): Object
\r
21676 // Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
\r
21677 var create = Object.create || (function () {
\r
21679 return function (proto) {
\r
21680 F.prototype = proto;
\r
21685 // @function bind(fn: Function, …): Function
\r
21686 // Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
\r
21687 // Has a `L.bind()` shortcut.
\r
21688 function bind(fn, obj) {
\r
21689 var slice = Array.prototype.slice;
\r
21692 return fn.bind.apply(fn, slice.call(arguments, 1));
\r
21695 var args = slice.call(arguments, 2);
\r
21697 return function () {
\r
21698 return fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments);
\r
21702 // @property lastId: Number
\r
21703 // Last unique ID used by [`stamp()`](#util-stamp)
\r
21706 // @function stamp(obj: Object): Number
\r
21707 // Returns the unique ID of an object, assigning it one if it doesn't have it.
\r
21708 function stamp(obj) {
\r
21709 /*eslint-disable */
\r
21710 obj._leaflet_id = obj._leaflet_id || ++lastId;
\r
21711 return obj._leaflet_id;
\r
21712 /* eslint-enable */
\r
21715 // @function throttle(fn: Function, time: Number, context: Object): Function
\r
21716 // Returns a function which executes function `fn` with the given scope `context`
\r
21717 // (so that the `this` keyword refers to `context` inside `fn`'s code). The function
\r
21718 // `fn` will be called no more than one time per given amount of `time`. The arguments
\r
21719 // received by the bound function will be any arguments passed when binding the
\r
21720 // function, followed by any arguments passed when invoking the bound function.
\r
21721 // Has an `L.throttle` shortcut.
\r
21722 function throttle(fn, time, context) {
\r
21723 var lock, args, wrapperFn, later;
\r
21725 later = function () {
\r
21726 // reset lock and call if queued
\r
21729 wrapperFn.apply(context, args);
\r
21734 wrapperFn = function () {
\r
21736 // called too soon, queue to call later
\r
21737 args = arguments;
\r
21740 // call and lock until later
\r
21741 fn.apply(context, arguments);
\r
21742 setTimeout(later, time);
\r
21747 return wrapperFn;
\r
21750 // @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number
\r
21751 // Returns the number `num` modulo `range` in such a way so it lies within
\r
21752 // `range[0]` and `range[1]`. The returned value will be always smaller than
\r
21753 // `range[1]` unless `includeMax` is set to `true`.
\r
21754 function wrapNum(x, range, includeMax) {
\r
21755 var max = range[1],
\r
21758 return x === max && includeMax ? x : ((x - min) % d + d) % d + min;
\r
21761 // @function falseFn(): Function
\r
21762 // Returns a function which always returns `false`.
\r
21763 function falseFn() { return false; }
\r
21765 // @function formatNum(num: Number, digits?: Number): Number
\r
21766 // Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default.
\r
21767 function formatNum(num, digits) {
\r
21768 var pow = Math.pow(10, (digits === undefined ? 6 : digits));
\r
21769 return Math.round(num * pow) / pow;
\r
21772 // @function trim(str: String): String
\r
21773 // Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)
\r
21774 function trim(str) {
\r
21775 return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
\r
21778 // @function splitWords(str: String): String[]
\r
21779 // Trims and splits the string on whitespace and returns the array of parts.
\r
21780 function splitWords(str) {
\r
21781 return trim(str).split(/\s+/);
\r
21784 // @function setOptions(obj: Object, options: Object): Object
\r
21785 // Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut.
\r
21786 function setOptions(obj, options) {
\r
21787 if (!Object.prototype.hasOwnProperty.call(obj, 'options')) {
\r
21788 obj.options = obj.options ? create(obj.options) : {};
\r
21790 for (var i in options) {
\r
21791 obj.options[i] = options[i];
\r
21793 return obj.options;
\r
21796 // @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String
\r
21797 // Converts an object into a parameter URL string, e.g. `{a: "foo", b: "bar"}`
\r
21798 // translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will
\r
21799 // be appended at the end. If `uppercase` is `true`, the parameter names will
\r
21800 // be uppercased (e.g. `'?A=foo&B=bar'`)
\r
21801 function getParamString(obj, existingUrl, uppercase) {
\r
21803 for (var i in obj) {
\r
21804 params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));
\r
21806 return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
\r
21809 var templateRe = /\{ *([\w_-]+) *\}/g;
\r
21811 // @function template(str: String, data: Object): String
\r
21812 // Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`
\r
21813 // and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string
\r
21814 // `('Hello foo, bar')`. You can also specify functions instead of strings for
\r
21815 // data values — they will be evaluated passing `data` as an argument.
\r
21816 function template(str, data) {
\r
21817 return str.replace(templateRe, function (str, key) {
\r
21818 var value = data[key];
\r
21820 if (value === undefined) {
\r
21821 throw new Error('No value provided for variable ' + str);
\r
21823 } else if (typeof value === 'function') {
\r
21824 value = value(data);
\r
21830 // @function isArray(obj): Boolean
\r
21831 // Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)
\r
21832 var isArray = Array.isArray || function (obj) {
\r
21833 return (Object.prototype.toString.call(obj) === '[object Array]');
\r
21836 // @function indexOf(array: Array, el: Object): Number
\r
21837 // Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)
\r
21838 function indexOf(array, el) {
\r
21839 for (var i = 0; i < array.length; i++) {
\r
21840 if (array[i] === el) { return i; }
\r
21845 // @property emptyImageUrl: String
\r
21846 // Data URI string containing a base64-encoded empty GIF image.
\r
21847 // Used as a hack to free memory from unused images on WebKit-powered
\r
21848 // mobile devices (by setting image `src` to this string).
\r
21849 var emptyImageUrl = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
\r
21851 // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/
\r
21853 function getPrefixed(name) {
\r
21854 return window['webkit' + name] || window['moz' + name] || window['ms' + name];
\r
21857 var lastTime = 0;
\r
21859 // fallback for IE 7-8
\r
21860 function timeoutDefer(fn) {
\r
21861 var time = +new Date(),
\r
21862 timeToCall = Math.max(0, 16 - (time - lastTime));
\r
21864 lastTime = time + timeToCall;
\r
21865 return window.setTimeout(fn, timeToCall);
\r
21868 var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer;
\r
21869 var cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') ||
\r
21870 getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); };
\r
21872 // @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number
\r
21873 // Schedules `fn` to be executed when the browser repaints. `fn` is bound to
\r
21874 // `context` if given. When `immediate` is set, `fn` is called immediately if
\r
21875 // the browser doesn't have native support for
\r
21876 // [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame),
\r
21877 // otherwise it's delayed. Returns a request ID that can be used to cancel the request.
\r
21878 function requestAnimFrame(fn, context, immediate) {
\r
21879 if (immediate && requestFn === timeoutDefer) {
\r
21880 fn.call(context);
\r
21882 return requestFn.call(window, bind(fn, context));
\r
21886 // @function cancelAnimFrame(id: Number): undefined
\r
21887 // Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame).
\r
21888 function cancelAnimFrame(id) {
\r
21890 cancelFn.call(window, id);
\r
21900 throttle: throttle,
21903 formatNum: formatNum,
21905 splitWords: splitWords,
21906 setOptions: setOptions,
21907 getParamString: getParamString,
21908 template: template,
21911 emptyImageUrl: emptyImageUrl,
21912 requestFn: requestFn,
21913 cancelFn: cancelFn,
21914 requestAnimFrame: requestAnimFrame,
21915 cancelAnimFrame: cancelAnimFrame
21922 // @uninheritable
\r
21924 // Thanks to John Resig and Dean Edwards for inspiration!
\r
21926 function Class() {}
\r
21928 Class.extend = function (props) {
\r
21930 // @function extend(props: Object): Function
\r
21931 // [Extends the current class](#class-inheritance) given the properties to be included.
\r
21932 // Returns a Javascript function that is a class constructor (to be called with `new`).
\r
21933 var NewClass = function () {
\r
21935 // call the constructor
\r
21936 if (this.initialize) {
\r
21937 this.initialize.apply(this, arguments);
\r
21940 // call all constructor hooks
\r
21941 this.callInitHooks();
\r
21944 var parentProto = NewClass.__super__ = this.prototype;
\r
21946 var proto = create(parentProto);
\r
21947 proto.constructor = NewClass;
\r
21949 NewClass.prototype = proto;
\r
21951 // inherit parent's statics
\r
21952 for (var i in this) {
\r
21953 if (Object.prototype.hasOwnProperty.call(this, i) && i !== 'prototype' && i !== '__super__') {
\r
21954 NewClass[i] = this[i];
\r
21958 // mix static properties into the class
\r
21959 if (props.statics) {
\r
21960 extend(NewClass, props.statics);
\r
21961 delete props.statics;
\r
21964 // mix includes into the prototype
\r
21965 if (props.includes) {
\r
21966 checkDeprecatedMixinEvents(props.includes);
\r
21967 extend.apply(null, [proto].concat(props.includes));
\r
21968 delete props.includes;
\r
21972 if (proto.options) {
\r
21973 props.options = extend(create(proto.options), props.options);
\r
21976 // mix given properties into the prototype
\r
21977 extend(proto, props);
\r
21979 proto._initHooks = [];
\r
21981 // add method for calling all hooks
\r
21982 proto.callInitHooks = function () {
\r
21984 if (this._initHooksCalled) { return; }
\r
21986 if (parentProto.callInitHooks) {
\r
21987 parentProto.callInitHooks.call(this);
\r
21990 this._initHooksCalled = true;
\r
21992 for (var i = 0, len = proto._initHooks.length; i < len; i++) {
\r
21993 proto._initHooks[i].call(this);
\r
22001 // @function include(properties: Object): this
\r
22002 // [Includes a mixin](#class-includes) into the current class.
\r
22003 Class.include = function (props) {
\r
22004 extend(this.prototype, props);
\r
22008 // @function mergeOptions(options: Object): this
\r
22009 // [Merges `options`](#class-options) into the defaults of the class.
\r
22010 Class.mergeOptions = function (options) {
\r
22011 extend(this.prototype.options, options);
\r
22015 // @function addInitHook(fn: Function): this
\r
22016 // Adds a [constructor hook](#class-constructor-hooks) to the class.
\r
22017 Class.addInitHook = function (fn) { // (Function) || (String, args...)
\r
22018 var args = Array.prototype.slice.call(arguments, 1);
\r
22020 var init = typeof fn === 'function' ? fn : function () {
\r
22021 this[fn].apply(this, args);
\r
22024 this.prototype._initHooks = this.prototype._initHooks || [];
\r
22025 this.prototype._initHooks.push(init);
\r
22029 function checkDeprecatedMixinEvents(includes) {
\r
22030 if (typeof L === 'undefined' || !L || !L.Mixin) { return; }
\r
22032 includes = isArray(includes) ? includes : [includes];
\r
22034 for (var i = 0; i < includes.length; i++) {
\r
22035 if (includes[i] === L.Mixin.Events) {
\r
22036 console.warn('Deprecated include of L.Mixin.Events: ' +
\r
22037 'this property will be removed in future releases, ' +
\r
22038 'please inherit from L.Evented instead.', new Error().stack);
\r
22046 * @inherits Class
\r
22048 * A set of methods shared between event-powered classes (like `Map` and `Marker`). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire `'click'` event).
\r
22053 * map.on('click', function(e) {
\r
22054 * alert(e.latlng);
\r
22058 * Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:
\r
22061 * function onClick(e) { ... }
\r
22063 * map.on('click', onClick);
\r
22064 * map.off('click', onClick);
\r
22069 /* @method on(type: String, fn: Function, context?: Object): this
\r
22070 * Adds a listener function (`fn`) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. `'click dblclick'`).
\r
22073 * @method on(eventMap: Object): this
\r
22074 * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
\r
22076 on: function (types, fn, context) {
\r
22078 // types can be a map of types/handlers
\r
22079 if (typeof types === 'object') {
\r
22080 for (var type in types) {
\r
22081 // we don't process space-separated events here for performance;
\r
22082 // it's a hot path since Layer uses the on(obj) syntax
\r
22083 this._on(type, types[type], fn);
\r
22087 // types can be a string of space-separated words
\r
22088 types = splitWords(types);
\r
22090 for (var i = 0, len = types.length; i < len; i++) {
\r
22091 this._on(types[i], fn, context);
\r
22098 /* @method off(type: String, fn?: Function, context?: Object): this
\r
22099 * Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to `on`, you must pass the same context to `off` in order to remove the listener.
\r
22102 * @method off(eventMap: Object): this
\r
22103 * Removes a set of type/listener pairs.
\r
22106 * @method off: this
\r
22107 * Removes all listeners to all events on the object. This includes implicitly attached events.
\r
22109 off: function (types, fn, context) {
\r
22112 // clear all listeners if called without arguments
\r
22113 delete this._events;
\r
22115 } else if (typeof types === 'object') {
\r
22116 for (var type in types) {
\r
22117 this._off(type, types[type], fn);
\r
22121 types = splitWords(types);
\r
22123 for (var i = 0, len = types.length; i < len; i++) {
\r
22124 this._off(types[i], fn, context);
\r
22131 // attach listener (without syntactic sugar now)
\r
22132 _on: function (type, fn, context) {
\r
22133 this._events = this._events || {};
\r
22135 /* get/init listeners for type */
\r
22136 var typeListeners = this._events[type];
\r
22137 if (!typeListeners) {
\r
22138 typeListeners = [];
\r
22139 this._events[type] = typeListeners;
\r
22142 if (context === this) {
\r
22143 // Less memory footprint.
\r
22144 context = undefined;
\r
22146 var newListener = {fn: fn, ctx: context},
\r
22147 listeners = typeListeners;
\r
22149 // check if fn already there
\r
22150 for (var i = 0, len = listeners.length; i < len; i++) {
\r
22151 if (listeners[i].fn === fn && listeners[i].ctx === context) {
\r
22156 listeners.push(newListener);
\r
22159 _off: function (type, fn, context) {
\r
22164 if (!this._events) { return; }
\r
22166 listeners = this._events[type];
\r
22168 if (!listeners) {
\r
22173 // Set all removed listeners to noop so they are not called if remove happens in fire
\r
22174 for (i = 0, len = listeners.length; i < len; i++) {
\r
22175 listeners[i].fn = falseFn;
\r
22177 // clear all listeners for a type if function isn't specified
\r
22178 delete this._events[type];
\r
22182 if (context === this) {
\r
22183 context = undefined;
\r
22188 // find fn and remove it
\r
22189 for (i = 0, len = listeners.length; i < len; i++) {
\r
22190 var l = listeners[i];
\r
22191 if (l.ctx !== context) { continue; }
\r
22192 if (l.fn === fn) {
\r
22194 // set the removed listener to noop so that's not called if remove happens in fire
\r
22197 if (this._firingCount) {
\r
22198 /* copy array in case events are being fired */
\r
22199 this._events[type] = listeners = listeners.slice();
\r
22201 listeners.splice(i, 1);
\r
22209 // @method fire(type: String, data?: Object, propagate?: Boolean): this
\r
22210 // Fires an event of the specified type. You can optionally provide an data
\r
22211 // object — the first argument of the listener function will contain its
\r
22212 // properties. The event can optionally be propagated to event parents.
\r
22213 fire: function (type, data, propagate) {
\r
22214 if (!this.listens(type, propagate)) { return this; }
\r
22216 var event = extend({}, data, {
\r
22219 sourceTarget: data && data.sourceTarget || this
\r
22222 if (this._events) {
\r
22223 var listeners = this._events[type];
\r
22226 this._firingCount = (this._firingCount + 1) || 1;
\r
22227 for (var i = 0, len = listeners.length; i < len; i++) {
\r
22228 var l = listeners[i];
\r
22229 l.fn.call(l.ctx || this, event);
\r
22232 this._firingCount--;
\r
22237 // propagate the event to parents (set with addEventParent)
\r
22238 this._propagateEvent(event);
\r
22244 // @method listens(type: String): Boolean
\r
22245 // Returns `true` if a particular event type has any listeners attached to it.
\r
22246 listens: function (type, propagate) {
\r
22247 var listeners = this._events && this._events[type];
\r
22248 if (listeners && listeners.length) { return true; }
\r
22251 // also check parents for listeners if event propagates
\r
22252 for (var id in this._eventParents) {
\r
22253 if (this._eventParents[id].listens(type, propagate)) { return true; }
\r
22259 // @method once(…): this
\r
22260 // Behaves as [`on(…)`](#evented-on), except the listener will only get fired once and then removed.
\r
22261 once: function (types, fn, context) {
\r
22263 if (typeof types === 'object') {
\r
22264 for (var type in types) {
\r
22265 this.once(type, types[type], fn);
\r
22270 var handler = bind(function () {
\r
22272 .off(types, fn, context)
\r
22273 .off(types, handler, context);
\r
22276 // add a listener that's executed once and removed after that
\r
22278 .on(types, fn, context)
\r
22279 .on(types, handler, context);
\r
22282 // @method addEventParent(obj: Evented): this
\r
22283 // Adds an event parent - an `Evented` that will receive propagated events
\r
22284 addEventParent: function (obj) {
\r
22285 this._eventParents = this._eventParents || {};
\r
22286 this._eventParents[stamp(obj)] = obj;
\r
22290 // @method removeEventParent(obj: Evented): this
\r
22291 // Removes an event parent, so it will stop receiving propagated events
\r
22292 removeEventParent: function (obj) {
\r
22293 if (this._eventParents) {
\r
22294 delete this._eventParents[stamp(obj)];
\r
22299 _propagateEvent: function (e) {
\r
22300 for (var id in this._eventParents) {
\r
22301 this._eventParents[id].fire(e.type, extend({
\r
22303 propagatedFrom: e.target
\r
22309 // aliases; we should ditch those eventually
\r
22311 // @method addEventListener(…): this
\r
22312 // Alias to [`on(…)`](#evented-on)
\r
22313 Events.addEventListener = Events.on;
\r
22315 // @method removeEventListener(…): this
\r
22316 // Alias to [`off(…)`](#evented-off)
\r
22318 // @method clearAllEventListeners(…): this
\r
22319 // Alias to [`off()`](#evented-off)
\r
22320 Events.removeEventListener = Events.clearAllEventListeners = Events.off;
\r
22322 // @method addOneTimeEventListener(…): this
\r
22323 // Alias to [`once(…)`](#evented-once)
\r
22324 Events.addOneTimeEventListener = Events.once;
\r
22326 // @method fireEvent(…): this
\r
22327 // Alias to [`fire(…)`](#evented-fire)
\r
22328 Events.fireEvent = Events.fire;
\r
22330 // @method hasEventListeners(…): Boolean
\r
22331 // Alias to [`listens(…)`](#evented-listens)
\r
22332 Events.hasEventListeners = Events.listens;
\r
22334 var Evented = Class.extend(Events);
22340 * Represents a point with `x` and `y` coordinates in pixels.
\r
22345 * var point = L.point(200, 300);
\r
22348 * All Leaflet methods and options that accept `Point` objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:
\r
22351 * map.panBy([200, 300]);
\r
22352 * map.panBy(L.point(200, 300));
\r
22355 * Note that `Point` does not inherit from Leaflet's `Class` object,
\r
22356 * which means new classes can't inherit from it, and new methods
\r
22357 * can't be added to it with the `include` function.
\r
22360 function Point(x, y, round) {
\r
22361 // @property x: Number; The `x` coordinate of the point
\r
22362 this.x = (round ? Math.round(x) : x);
\r
22363 // @property y: Number; The `y` coordinate of the point
\r
22364 this.y = (round ? Math.round(y) : y);
\r
22367 var trunc = Math.trunc || function (v) {
\r
22368 return v > 0 ? Math.floor(v) : Math.ceil(v);
\r
22371 Point.prototype = {
\r
22373 // @method clone(): Point
\r
22374 // Returns a copy of the current point.
\r
22375 clone: function () {
\r
22376 return new Point(this.x, this.y);
\r
22379 // @method add(otherPoint: Point): Point
\r
22380 // Returns the result of addition of the current and the given points.
\r
22381 add: function (point) {
\r
22382 // non-destructive, returns a new point
\r
22383 return this.clone()._add(toPoint(point));
\r
22386 _add: function (point) {
\r
22387 // destructive, used directly for performance in situations where it's safe to modify existing point
\r
22388 this.x += point.x;
\r
22389 this.y += point.y;
\r
22393 // @method subtract(otherPoint: Point): Point
\r
22394 // Returns the result of subtraction of the given point from the current.
\r
22395 subtract: function (point) {
\r
22396 return this.clone()._subtract(toPoint(point));
\r
22399 _subtract: function (point) {
\r
22400 this.x -= point.x;
\r
22401 this.y -= point.y;
\r
22405 // @method divideBy(num: Number): Point
\r
22406 // Returns the result of division of the current point by the given number.
\r
22407 divideBy: function (num) {
\r
22408 return this.clone()._divideBy(num);
\r
22411 _divideBy: function (num) {
\r
22417 // @method multiplyBy(num: Number): Point
\r
22418 // Returns the result of multiplication of the current point by the given number.
\r
22419 multiplyBy: function (num) {
\r
22420 return this.clone()._multiplyBy(num);
\r
22423 _multiplyBy: function (num) {
\r
22429 // @method scaleBy(scale: Point): Point
\r
22430 // Multiply each coordinate of the current point by each coordinate of
\r
22431 // `scale`. In linear algebra terms, multiply the point by the
\r
22432 // [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation)
\r
22433 // defined by `scale`.
\r
22434 scaleBy: function (point) {
\r
22435 return new Point(this.x * point.x, this.y * point.y);
\r
22438 // @method unscaleBy(scale: Point): Point
\r
22439 // Inverse of `scaleBy`. Divide each coordinate of the current point by
\r
22440 // each coordinate of `scale`.
\r
22441 unscaleBy: function (point) {
\r
22442 return new Point(this.x / point.x, this.y / point.y);
\r
22445 // @method round(): Point
\r
22446 // Returns a copy of the current point with rounded coordinates.
\r
22447 round: function () {
\r
22448 return this.clone()._round();
\r
22451 _round: function () {
\r
22452 this.x = Math.round(this.x);
\r
22453 this.y = Math.round(this.y);
\r
22457 // @method floor(): Point
\r
22458 // Returns a copy of the current point with floored coordinates (rounded down).
\r
22459 floor: function () {
\r
22460 return this.clone()._floor();
\r
22463 _floor: function () {
\r
22464 this.x = Math.floor(this.x);
\r
22465 this.y = Math.floor(this.y);
\r
22469 // @method ceil(): Point
\r
22470 // Returns a copy of the current point with ceiled coordinates (rounded up).
\r
22471 ceil: function () {
\r
22472 return this.clone()._ceil();
\r
22475 _ceil: function () {
\r
22476 this.x = Math.ceil(this.x);
\r
22477 this.y = Math.ceil(this.y);
\r
22481 // @method trunc(): Point
\r
22482 // Returns a copy of the current point with truncated coordinates (rounded towards zero).
\r
22483 trunc: function () {
\r
22484 return this.clone()._trunc();
\r
22487 _trunc: function () {
\r
22488 this.x = trunc(this.x);
\r
22489 this.y = trunc(this.y);
\r
22493 // @method distanceTo(otherPoint: Point): Number
\r
22494 // Returns the cartesian distance between the current and the given points.
\r
22495 distanceTo: function (point) {
\r
22496 point = toPoint(point);
\r
22498 var x = point.x - this.x,
\r
22499 y = point.y - this.y;
\r
22501 return Math.sqrt(x * x + y * y);
\r
22504 // @method equals(otherPoint: Point): Boolean
\r
22505 // Returns `true` if the given point has the same coordinates.
\r
22506 equals: function (point) {
\r
22507 point = toPoint(point);
\r
22509 return point.x === this.x &&
\r
22510 point.y === this.y;
\r
22513 // @method contains(otherPoint: Point): Boolean
\r
22514 // Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).
\r
22515 contains: function (point) {
\r
22516 point = toPoint(point);
\r
22518 return Math.abs(point.x) <= Math.abs(this.x) &&
\r
22519 Math.abs(point.y) <= Math.abs(this.y);
\r
22522 // @method toString(): String
\r
22523 // Returns a string representation of the point for debugging purposes.
\r
22524 toString: function () {
\r
22525 return 'Point(' +
\r
22526 formatNum(this.x) + ', ' +
\r
22527 formatNum(this.y) + ')';
\r
22531 // @factory L.point(x: Number, y: Number, round?: Boolean)
\r
22532 // Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values.
\r
22535 // @factory L.point(coords: Number[])
\r
22536 // Expects an array of the form `[x, y]` instead.
\r
22539 // @factory L.point(coords: Object)
\r
22540 // Expects a plain object of the form `{x: Number, y: Number}` instead.
\r
22541 function toPoint(x, y, round) {
\r
22542 if (x instanceof Point) {
\r
22545 if (isArray(x)) {
\r
22546 return new Point(x[0], x[1]);
\r
22548 if (x === undefined || x === null) {
\r
22551 if (typeof x === 'object' && 'x' in x && 'y' in x) {
\r
22552 return new Point(x.x, x.y);
\r
22554 return new Point(x, y, round);
\r
22561 * Represents a rectangular area in pixel coordinates.
\r
22566 * var p1 = L.point(10, 10),
\r
22567 * p2 = L.point(40, 60),
\r
22568 * bounds = L.bounds(p1, p2);
\r
22571 * All Leaflet methods that accept `Bounds` objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:
\r
22574 * otherBounds.intersects([[10, 10], [40, 60]]);
\r
22577 * Note that `Bounds` does not inherit from Leaflet's `Class` object,
\r
22578 * which means new classes can't inherit from it, and new methods
\r
22579 * can't be added to it with the `include` function.
\r
22582 function Bounds(a, b) {
\r
22583 if (!a) { return; }
\r
22585 var points = b ? [a, b] : a;
\r
22587 for (var i = 0, len = points.length; i < len; i++) {
\r
22588 this.extend(points[i]);
\r
22592 Bounds.prototype = {
\r
22593 // @method extend(point: Point): this
\r
22594 // Extends the bounds to contain the given point.
\r
22595 extend: function (point) { // (Point)
\r
22596 point = toPoint(point);
\r
22598 // @property min: Point
\r
22599 // The top left corner of the rectangle.
\r
22600 // @property max: Point
\r
22601 // The bottom right corner of the rectangle.
\r
22602 if (!this.min && !this.max) {
\r
22603 this.min = point.clone();
\r
22604 this.max = point.clone();
\r
22606 this.min.x = Math.min(point.x, this.min.x);
\r
22607 this.max.x = Math.max(point.x, this.max.x);
\r
22608 this.min.y = Math.min(point.y, this.min.y);
\r
22609 this.max.y = Math.max(point.y, this.max.y);
\r
22614 // @method getCenter(round?: Boolean): Point
\r
22615 // Returns the center point of the bounds.
\r
22616 getCenter: function (round) {
\r
22617 return new Point(
\r
22618 (this.min.x + this.max.x) / 2,
\r
22619 (this.min.y + this.max.y) / 2, round);
\r
22622 // @method getBottomLeft(): Point
\r
22623 // Returns the bottom-left point of the bounds.
\r
22624 getBottomLeft: function () {
\r
22625 return new Point(this.min.x, this.max.y);
\r
22628 // @method getTopRight(): Point
\r
22629 // Returns the top-right point of the bounds.
\r
22630 getTopRight: function () { // -> Point
\r
22631 return new Point(this.max.x, this.min.y);
\r
22634 // @method getTopLeft(): Point
\r
22635 // Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)).
\r
22636 getTopLeft: function () {
\r
22637 return this.min; // left, top
\r
22640 // @method getBottomRight(): Point
\r
22641 // Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)).
\r
22642 getBottomRight: function () {
\r
22643 return this.max; // right, bottom
\r
22646 // @method getSize(): Point
\r
22647 // Returns the size of the given bounds
\r
22648 getSize: function () {
\r
22649 return this.max.subtract(this.min);
\r
22652 // @method contains(otherBounds: Bounds): Boolean
\r
22653 // Returns `true` if the rectangle contains the given one.
\r
22655 // @method contains(point: Point): Boolean
\r
22656 // Returns `true` if the rectangle contains the given point.
\r
22657 contains: function (obj) {
\r
22660 if (typeof obj[0] === 'number' || obj instanceof Point) {
\r
22661 obj = toPoint(obj);
\r
22663 obj = toBounds(obj);
\r
22666 if (obj instanceof Bounds) {
\r
22673 return (min.x >= this.min.x) &&
\r
22674 (max.x <= this.max.x) &&
\r
22675 (min.y >= this.min.y) &&
\r
22676 (max.y <= this.max.y);
\r
22679 // @method intersects(otherBounds: Bounds): Boolean
\r
22680 // Returns `true` if the rectangle intersects the given bounds. Two bounds
\r
22681 // intersect if they have at least one point in common.
\r
22682 intersects: function (bounds) { // (Bounds) -> Boolean
\r
22683 bounds = toBounds(bounds);
\r
22685 var min = this.min,
\r
22687 min2 = bounds.min,
\r
22688 max2 = bounds.max,
\r
22689 xIntersects = (max2.x >= min.x) && (min2.x <= max.x),
\r
22690 yIntersects = (max2.y >= min.y) && (min2.y <= max.y);
\r
22692 return xIntersects && yIntersects;
\r
22695 // @method overlaps(otherBounds: Bounds): Boolean
\r
22696 // Returns `true` if the rectangle overlaps the given bounds. Two bounds
\r
22697 // overlap if their intersection is an area.
\r
22698 overlaps: function (bounds) { // (Bounds) -> Boolean
\r
22699 bounds = toBounds(bounds);
\r
22701 var min = this.min,
\r
22703 min2 = bounds.min,
\r
22704 max2 = bounds.max,
\r
22705 xOverlaps = (max2.x > min.x) && (min2.x < max.x),
\r
22706 yOverlaps = (max2.y > min.y) && (min2.y < max.y);
\r
22708 return xOverlaps && yOverlaps;
\r
22711 isValid: function () {
\r
22712 return !!(this.min && this.max);
\r
22717 // @factory L.bounds(corner1: Point, corner2: Point)
\r
22718 // Creates a Bounds object from two corners coordinate pairs.
\r
22720 // @factory L.bounds(points: Point[])
\r
22721 // Creates a Bounds object from the given array of points.
\r
22722 function toBounds(a, b) {
\r
22723 if (!a || a instanceof Bounds) {
\r
22726 return new Bounds(a, b);
\r
22730 * @class LatLngBounds
\r
22731 * @aka L.LatLngBounds
\r
22733 * Represents a rectangular geographical area on a map.
\r
22738 * var corner1 = L.latLng(40.712, -74.227),
\r
22739 * corner2 = L.latLng(40.774, -74.125),
\r
22740 * bounds = L.latLngBounds(corner1, corner2);
\r
22743 * All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:
\r
22746 * map.fitBounds([
\r
22747 * [40.712, -74.227],
\r
22748 * [40.774, -74.125]
\r
22752 * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range.
\r
22754 * Note that `LatLngBounds` does not inherit from Leaflet's `Class` object,
\r
22755 * which means new classes can't inherit from it, and new methods
\r
22756 * can't be added to it with the `include` function.
\r
22759 function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[])
\r
22760 if (!corner1) { return; }
\r
22762 var latlngs = corner2 ? [corner1, corner2] : corner1;
\r
22764 for (var i = 0, len = latlngs.length; i < len; i++) {
\r
22765 this.extend(latlngs[i]);
\r
22769 LatLngBounds.prototype = {
\r
22771 // @method extend(latlng: LatLng): this
\r
22772 // Extend the bounds to contain the given point
\r
22775 // @method extend(otherBounds: LatLngBounds): this
\r
22776 // Extend the bounds to contain the given bounds
\r
22777 extend: function (obj) {
\r
22778 var sw = this._southWest,
\r
22779 ne = this._northEast,
\r
22782 if (obj instanceof LatLng) {
\r
22786 } else if (obj instanceof LatLngBounds) {
\r
22787 sw2 = obj._southWest;
\r
22788 ne2 = obj._northEast;
\r
22790 if (!sw2 || !ne2) { return this; }
\r
22793 return obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this;
\r
22796 if (!sw && !ne) {
\r
22797 this._southWest = new LatLng(sw2.lat, sw2.lng);
\r
22798 this._northEast = new LatLng(ne2.lat, ne2.lng);
\r
22800 sw.lat = Math.min(sw2.lat, sw.lat);
\r
22801 sw.lng = Math.min(sw2.lng, sw.lng);
\r
22802 ne.lat = Math.max(ne2.lat, ne.lat);
\r
22803 ne.lng = Math.max(ne2.lng, ne.lng);
\r
22809 // @method pad(bufferRatio: Number): LatLngBounds
\r
22810 // Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.
\r
22811 // For example, a ratio of 0.5 extends the bounds by 50% in each direction.
\r
22812 // Negative values will retract the bounds.
\r
22813 pad: function (bufferRatio) {
\r
22814 var sw = this._southWest,
\r
22815 ne = this._northEast,
\r
22816 heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio,
\r
22817 widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;
\r
22819 return new LatLngBounds(
\r
22820 new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),
\r
22821 new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer));
\r
22824 // @method getCenter(): LatLng
\r
22825 // Returns the center point of the bounds.
\r
22826 getCenter: function () {
\r
22827 return new LatLng(
\r
22828 (this._southWest.lat + this._northEast.lat) / 2,
\r
22829 (this._southWest.lng + this._northEast.lng) / 2);
\r
22832 // @method getSouthWest(): LatLng
\r
22833 // Returns the south-west point of the bounds.
\r
22834 getSouthWest: function () {
\r
22835 return this._southWest;
\r
22838 // @method getNorthEast(): LatLng
\r
22839 // Returns the north-east point of the bounds.
\r
22840 getNorthEast: function () {
\r
22841 return this._northEast;
\r
22844 // @method getNorthWest(): LatLng
\r
22845 // Returns the north-west point of the bounds.
\r
22846 getNorthWest: function () {
\r
22847 return new LatLng(this.getNorth(), this.getWest());
\r
22850 // @method getSouthEast(): LatLng
\r
22851 // Returns the south-east point of the bounds.
\r
22852 getSouthEast: function () {
\r
22853 return new LatLng(this.getSouth(), this.getEast());
\r
22856 // @method getWest(): Number
\r
22857 // Returns the west longitude of the bounds
\r
22858 getWest: function () {
\r
22859 return this._southWest.lng;
\r
22862 // @method getSouth(): Number
\r
22863 // Returns the south latitude of the bounds
\r
22864 getSouth: function () {
\r
22865 return this._southWest.lat;
\r
22868 // @method getEast(): Number
\r
22869 // Returns the east longitude of the bounds
\r
22870 getEast: function () {
\r
22871 return this._northEast.lng;
\r
22874 // @method getNorth(): Number
\r
22875 // Returns the north latitude of the bounds
\r
22876 getNorth: function () {
\r
22877 return this._northEast.lat;
\r
22880 // @method contains(otherBounds: LatLngBounds): Boolean
\r
22881 // Returns `true` if the rectangle contains the given one.
\r
22884 // @method contains (latlng: LatLng): Boolean
\r
22885 // Returns `true` if the rectangle contains the given point.
\r
22886 contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean
\r
22887 if (typeof obj[0] === 'number' || obj instanceof LatLng || 'lat' in obj) {
\r
22888 obj = toLatLng(obj);
\r
22890 obj = toLatLngBounds(obj);
\r
22893 var sw = this._southWest,
\r
22894 ne = this._northEast,
\r
22897 if (obj instanceof LatLngBounds) {
\r
22898 sw2 = obj.getSouthWest();
\r
22899 ne2 = obj.getNorthEast();
\r
22904 return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) &&
\r
22905 (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng);
\r
22908 // @method intersects(otherBounds: LatLngBounds): Boolean
\r
22909 // Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.
\r
22910 intersects: function (bounds) {
\r
22911 bounds = toLatLngBounds(bounds);
\r
22913 var sw = this._southWest,
\r
22914 ne = this._northEast,
\r
22915 sw2 = bounds.getSouthWest(),
\r
22916 ne2 = bounds.getNorthEast(),
\r
22918 latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat),
\r
22919 lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng);
\r
22921 return latIntersects && lngIntersects;
\r
22924 // @method overlaps(otherBounds: LatLngBounds): Boolean
\r
22925 // Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.
\r
22926 overlaps: function (bounds) {
\r
22927 bounds = toLatLngBounds(bounds);
\r
22929 var sw = this._southWest,
\r
22930 ne = this._northEast,
\r
22931 sw2 = bounds.getSouthWest(),
\r
22932 ne2 = bounds.getNorthEast(),
\r
22934 latOverlaps = (ne2.lat > sw.lat) && (sw2.lat < ne.lat),
\r
22935 lngOverlaps = (ne2.lng > sw.lng) && (sw2.lng < ne.lng);
\r
22937 return latOverlaps && lngOverlaps;
\r
22940 // @method toBBoxString(): String
\r
22941 // Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.
\r
22942 toBBoxString: function () {
\r
22943 return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(',');
\r
22946 // @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean
\r
22947 // Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number.
\r
22948 equals: function (bounds, maxMargin) {
\r
22949 if (!bounds) { return false; }
\r
22951 bounds = toLatLngBounds(bounds);
\r
22953 return this._southWest.equals(bounds.getSouthWest(), maxMargin) &&
\r
22954 this._northEast.equals(bounds.getNorthEast(), maxMargin);
\r
22957 // @method isValid(): Boolean
\r
22958 // Returns `true` if the bounds are properly initialized.
\r
22959 isValid: function () {
\r
22960 return !!(this._southWest && this._northEast);
\r
22964 // TODO International date line?
\r
22966 // @factory L.latLngBounds(corner1: LatLng, corner2: LatLng)
\r
22967 // Creates a `LatLngBounds` object by defining two diagonally opposite corners of the rectangle.
\r
22970 // @factory L.latLngBounds(latlngs: LatLng[])
\r
22971 // Creates a `LatLngBounds` object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with [`fitBounds`](#map-fitbounds).
\r
22972 function toLatLngBounds(a, b) {
\r
22973 if (a instanceof LatLngBounds) {
\r
22976 return new LatLngBounds(a, b);
\r
22982 * Represents a geographical point with a certain latitude and longitude.
\r
22987 * var latlng = L.latLng(50.5, 30.5);
\r
22990 * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:
\r
22993 * map.panTo([50, 30]);
\r
22994 * map.panTo({lon: 30, lat: 50});
\r
22995 * map.panTo({lat: 50, lng: 30});
\r
22996 * map.panTo(L.latLng(50, 30));
\r
22999 * Note that `LatLng` does not inherit from Leaflet's `Class` object,
\r
23000 * which means new classes can't inherit from it, and new methods
\r
23001 * can't be added to it with the `include` function.
\r
23004 function LatLng(lat, lng, alt) {
\r
23005 if (isNaN(lat) || isNaN(lng)) {
\r
23006 throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
\r
23009 // @property lat: Number
\r
23010 // Latitude in degrees
\r
23013 // @property lng: Number
\r
23014 // Longitude in degrees
\r
23017 // @property alt: Number
\r
23018 // Altitude in meters (optional)
\r
23019 if (alt !== undefined) {
\r
23024 LatLng.prototype = {
\r
23025 // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean
\r
23026 // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number.
\r
23027 equals: function (obj, maxMargin) {
\r
23028 if (!obj) { return false; }
\r
23030 obj = toLatLng(obj);
\r
23032 var margin = Math.max(
\r
23033 Math.abs(this.lat - obj.lat),
\r
23034 Math.abs(this.lng - obj.lng));
\r
23036 return margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin);
\r
23039 // @method toString(): String
\r
23040 // Returns a string representation of the point (for debugging purposes).
\r
23041 toString: function (precision) {
\r
23042 return 'LatLng(' +
\r
23043 formatNum(this.lat, precision) + ', ' +
\r
23044 formatNum(this.lng, precision) + ')';
\r
23047 // @method distanceTo(otherLatLng: LatLng): Number
\r
23048 // Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines).
\r
23049 distanceTo: function (other) {
\r
23050 return Earth.distance(this, toLatLng(other));
\r
23053 // @method wrap(): LatLng
\r
23054 // Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees.
\r
23055 wrap: function () {
\r
23056 return Earth.wrapLatLng(this);
\r
23059 // @method toBounds(sizeInMeters: Number): LatLngBounds
\r
23060 // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`.
\r
23061 toBounds: function (sizeInMeters) {
\r
23062 var latAccuracy = 180 * sizeInMeters / 40075017,
\r
23063 lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat);
\r
23065 return toLatLngBounds(
\r
23066 [this.lat - latAccuracy, this.lng - lngAccuracy],
\r
23067 [this.lat + latAccuracy, this.lng + lngAccuracy]);
\r
23070 clone: function () {
\r
23071 return new LatLng(this.lat, this.lng, this.alt);
\r
23077 // @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng
\r
23078 // Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).
\r
23081 // @factory L.latLng(coords: Array): LatLng
\r
23082 // Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead.
\r
23085 // @factory L.latLng(coords: Object): LatLng
\r
23086 // Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead.
\r
23088 function toLatLng(a, b, c) {
\r
23089 if (a instanceof LatLng) {
\r
23092 if (isArray(a) && typeof a[0] !== 'object') {
\r
23093 if (a.length === 3) {
\r
23094 return new LatLng(a[0], a[1], a[2]);
\r
23096 if (a.length === 2) {
\r
23097 return new LatLng(a[0], a[1]);
\r
23101 if (a === undefined || a === null) {
\r
23104 if (typeof a === 'object' && 'lat' in a) {
\r
23105 return new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt);
\r
23107 if (b === undefined) {
\r
23110 return new LatLng(a, b, c);
\r
23115 * @crs L.CRS.Base
\r
23116 * Object that defines coordinate reference systems for projecting
\r
23117 * geographical points into pixel (screen) coordinates and back (and to
\r
23118 * coordinates in other units for [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services). See
\r
23119 * [spatial reference system](http://en.wikipedia.org/wiki/Coordinate_reference_system).
\r
23121 * Leaflet defines the most usual CRSs by default. If you want to use a
\r
23122 * CRS not defined by default, take a look at the
\r
23123 * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin.
\r
23125 * Note that the CRS instances do not inherit from Leaflet's `Class` object,
\r
23126 * and can't be instantiated. Also, new classes can't inherit from them,
\r
23127 * and methods can't be added to them with the `include` function.
\r
23131 // @method latLngToPoint(latlng: LatLng, zoom: Number): Point
\r
23132 // Projects geographical coordinates into pixel coordinates for a given zoom.
\r
23133 latLngToPoint: function (latlng, zoom) {
\r
23134 var projectedPoint = this.projection.project(latlng),
\r
23135 scale = this.scale(zoom);
\r
23137 return this.transformation._transform(projectedPoint, scale);
\r
23140 // @method pointToLatLng(point: Point, zoom: Number): LatLng
\r
23141 // The inverse of `latLngToPoint`. Projects pixel coordinates on a given
\r
23142 // zoom into geographical coordinates.
\r
23143 pointToLatLng: function (point, zoom) {
\r
23144 var scale = this.scale(zoom),
\r
23145 untransformedPoint = this.transformation.untransform(point, scale);
\r
23147 return this.projection.unproject(untransformedPoint);
\r
23150 // @method project(latlng: LatLng): Point
\r
23151 // Projects geographical coordinates into coordinates in units accepted for
\r
23152 // this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).
\r
23153 project: function (latlng) {
\r
23154 return this.projection.project(latlng);
\r
23157 // @method unproject(point: Point): LatLng
\r
23158 // Given a projected coordinate returns the corresponding LatLng.
\r
23159 // The inverse of `project`.
\r
23160 unproject: function (point) {
\r
23161 return this.projection.unproject(point);
\r
23164 // @method scale(zoom: Number): Number
\r
23165 // Returns the scale used when transforming projected coordinates into
\r
23166 // pixel coordinates for a particular zoom. For example, it returns
\r
23167 // `256 * 2^zoom` for Mercator-based CRS.
\r
23168 scale: function (zoom) {
\r
23169 return 256 * Math.pow(2, zoom);
\r
23172 // @method zoom(scale: Number): Number
\r
23173 // Inverse of `scale()`, returns the zoom level corresponding to a scale
\r
23174 // factor of `scale`.
\r
23175 zoom: function (scale) {
\r
23176 return Math.log(scale / 256) / Math.LN2;
\r
23179 // @method getProjectedBounds(zoom: Number): Bounds
\r
23180 // Returns the projection's bounds scaled and transformed for the provided `zoom`.
\r
23181 getProjectedBounds: function (zoom) {
\r
23182 if (this.infinite) { return null; }
\r
23184 var b = this.projection.bounds,
\r
23185 s = this.scale(zoom),
\r
23186 min = this.transformation.transform(b.min, s),
\r
23187 max = this.transformation.transform(b.max, s);
\r
23189 return new Bounds(min, max);
\r
23192 // @method distance(latlng1: LatLng, latlng2: LatLng): Number
\r
23193 // Returns the distance between two geographical coordinates.
\r
23195 // @property code: String
\r
23196 // Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`)
\r
23198 // @property wrapLng: Number[]
\r
23199 // An array of two numbers defining whether the longitude (horizontal) coordinate
\r
23200 // axis wraps around a given range and how. Defaults to `[-180, 180]` in most
\r
23201 // geographical CRSs. If `undefined`, the longitude axis does not wrap around.
\r
23203 // @property wrapLat: Number[]
\r
23204 // Like `wrapLng`, but for the latitude (vertical) axis.
\r
23206 // wrapLng: [min, max],
\r
23207 // wrapLat: [min, max],
\r
23209 // @property infinite: Boolean
\r
23210 // If true, the coordinate space will be unbounded (infinite in both axes)
\r
23213 // @method wrapLatLng(latlng: LatLng): LatLng
\r
23214 // Returns a `LatLng` where lat and lng has been wrapped according to the
\r
23215 // CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds.
\r
23216 wrapLatLng: function (latlng) {
\r
23217 var lng = this.wrapLng ? wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng,
\r
23218 lat = this.wrapLat ? wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat,
\r
23219 alt = latlng.alt;
\r
23221 return new LatLng(lat, lng, alt);
\r
23224 // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
\r
23225 // Returns a `LatLngBounds` with the same size as the given one, ensuring
\r
23226 // that its center is within the CRS's bounds.
\r
23227 // Only accepts actual `L.LatLngBounds` instances, not arrays.
\r
23228 wrapLatLngBounds: function (bounds) {
\r
23229 var center = bounds.getCenter(),
\r
23230 newCenter = this.wrapLatLng(center),
\r
23231 latShift = center.lat - newCenter.lat,
\r
23232 lngShift = center.lng - newCenter.lng;
\r
23234 if (latShift === 0 && lngShift === 0) {
\r
23238 var sw = bounds.getSouthWest(),
\r
23239 ne = bounds.getNorthEast(),
\r
23240 newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift),
\r
23241 newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift);
\r
23243 return new LatLngBounds(newSw, newNe);
\r
23251 * Serves as the base for CRS that are global such that they cover the earth.
23252 * Can only be used as the base for other CRS and cannot be used directly,
23253 * since it does not have a `code`, `projection` or `transformation`. `distance()` returns
23257 var Earth = extend({}, CRS, {
23258 wrapLng: [-180, 180],
23260 // Mean Earth Radius, as recommended for use by
23261 // the International Union of Geodesy and Geophysics,
23262 // see http://rosettacode.org/wiki/Haversine_formula
23265 // distance between two geographical points using spherical law of cosines approximation
23266 distance: function (latlng1, latlng2) {
23267 var rad = Math.PI / 180,
23268 lat1 = latlng1.lat * rad,
23269 lat2 = latlng2.lat * rad,
23270 sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),
23271 sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2),
23272 a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,
23273 c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
23279 * @namespace Projection
\r
23280 * @projection L.Projection.SphericalMercator
\r
23282 * Spherical Mercator projection — the most common projection for online maps,
\r
23283 * used by almost all free and commercial tile providers. Assumes that Earth is
\r
23284 * a sphere. Used by the `EPSG:3857` CRS.
\r
23287 var earthRadius = 6378137;
\r
23289 var SphericalMercator = {
\r
23292 MAX_LATITUDE: 85.0511287798,
\r
23294 project: function (latlng) {
\r
23295 var d = Math.PI / 180,
\r
23296 max = this.MAX_LATITUDE,
\r
23297 lat = Math.max(Math.min(max, latlng.lat), -max),
\r
23298 sin = Math.sin(lat * d);
\r
23300 return new Point(
\r
23301 this.R * latlng.lng * d,
\r
23302 this.R * Math.log((1 + sin) / (1 - sin)) / 2);
\r
23305 unproject: function (point) {
\r
23306 var d = 180 / Math.PI;
\r
23308 return new LatLng(
\r
23309 (2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d,
\r
23310 point.x * d / this.R);
\r
23313 bounds: (function () {
\r
23314 var d = earthRadius * Math.PI;
\r
23315 return new Bounds([-d, -d], [d, d]);
\r
23320 * @class Transformation
\r
23321 * @aka L.Transformation
\r
23323 * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d`
\r
23324 * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing
\r
23325 * the reverse. Used by Leaflet in its projections code.
\r
23330 * var transformation = L.transformation(2, 5, -1, 10),
\r
23331 * p = L.point(1, 2),
\r
23332 * p2 = transformation.transform(p), // L.point(7, 8)
\r
23333 * p3 = transformation.untransform(p2); // L.point(1, 2)
\r
23338 // factory new L.Transformation(a: Number, b: Number, c: Number, d: Number)
\r
23339 // Creates a `Transformation` object with the given coefficients.
\r
23340 function Transformation(a, b, c, d) {
\r
23341 if (isArray(a)) {
\r
23342 // use array properties
\r
23355 Transformation.prototype = {
\r
23356 // @method transform(point: Point, scale?: Number): Point
\r
23357 // Returns a transformed point, optionally multiplied by the given scale.
\r
23358 // Only accepts actual `L.Point` instances, not arrays.
\r
23359 transform: function (point, scale) { // (Point, Number) -> Point
\r
23360 return this._transform(point.clone(), scale);
\r
23363 // destructive transform (faster)
\r
23364 _transform: function (point, scale) {
\r
23365 scale = scale || 1;
\r
23366 point.x = scale * (this._a * point.x + this._b);
\r
23367 point.y = scale * (this._c * point.y + this._d);
\r
23371 // @method untransform(point: Point, scale?: Number): Point
\r
23372 // Returns the reverse transformation of the given point, optionally divided
\r
23373 // by the given scale. Only accepts actual `L.Point` instances, not arrays.
\r
23374 untransform: function (point, scale) {
\r
23375 scale = scale || 1;
\r
23376 return new Point(
\r
23377 (point.x / scale - this._b) / this._a,
\r
23378 (point.y / scale - this._d) / this._c);
\r
23382 // factory L.transformation(a: Number, b: Number, c: Number, d: Number)
\r
23384 // @factory L.transformation(a: Number, b: Number, c: Number, d: Number)
\r
23385 // Instantiates a Transformation object with the given coefficients.
\r
23388 // @factory L.transformation(coefficients: Array): Transformation
\r
23389 // Expects an coefficients array of the form
\r
23390 // `[a: Number, b: Number, c: Number, d: Number]`.
\r
23392 function toTransformation(a, b, c, d) {
\r
23393 return new Transformation(a, b, c, d);
\r
23398 * @crs L.CRS.EPSG3857
\r
23400 * The most common CRS for online maps, used by almost all free and commercial
\r
23401 * tile providers. Uses Spherical Mercator projection. Set in by default in
\r
23402 * Map's `crs` option.
\r
23405 var EPSG3857 = extend({}, Earth, {
\r
23406 code: 'EPSG:3857',
\r
23407 projection: SphericalMercator,
\r
23409 transformation: (function () {
\r
23410 var scale = 0.5 / (Math.PI * SphericalMercator.R);
\r
23411 return toTransformation(scale, 0.5, -scale, 0.5);
\r
23415 var EPSG900913 = extend({}, EPSG3857, {
\r
23416 code: 'EPSG:900913'
\r
23419 // @namespace SVG; @section
23420 // There are several static functions which can be called without instantiating L.SVG:
23422 // @function create(name: String): SVGElement
23423 // Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement),
23424 // corresponding to the class name passed. For example, using 'line' will return
23425 // an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement).
23426 function svgCreate(name) {
23427 return document.createElementNS('http://www.w3.org/2000/svg', name);
23430 // @function pointsToPath(rings: Point[], closed: Boolean): String
23431 // Generates a SVG path string for multiple rings, with each ring turning
23432 // into "M..L..L.." instructions
23433 function pointsToPath(rings, closed) {
23435 i, j, len, len2, points, p;
23437 for (i = 0, len = rings.length; i < len; i++) {
23440 for (j = 0, len2 = points.length; j < len2; j++) {
23442 str += (j ? 'L' : 'M') + p.x + ' ' + p.y;
23445 // closes the ring for polygons; "x" is VML syntax
23446 str += closed ? (svg ? 'z' : 'x') : '';
23449 // SVG complains about empty path strings
23450 return str || 'M0 0';
23454 * @namespace Browser
\r
23457 * A namespace with static properties for browser/feature detection used by Leaflet internally.
\r
23462 * if (L.Browser.ielt9) {
\r
23463 * alert('Upgrade your browser, dude!');
\r
23468 var style$1 = document.documentElement.style;
\r
23470 // @property ie: Boolean; `true` for all Internet Explorer versions (not Edge).
\r
23471 var ie = 'ActiveXObject' in window;
\r
23473 // @property ielt9: Boolean; `true` for Internet Explorer versions less than 9.
\r
23474 var ielt9 = ie && !document.addEventListener;
\r
23476 // @property edge: Boolean; `true` for the Edge web browser.
\r
23477 var edge = 'msLaunchUri' in navigator && !('documentMode' in document);
\r
23479 // @property webkit: Boolean;
\r
23480 // `true` for webkit-based browsers like Chrome and Safari (including mobile versions).
\r
23481 var webkit = userAgentContains('webkit');
\r
23483 // @property android: Boolean
\r
23484 // `true` for any browser running on an Android platform.
\r
23485 var android = userAgentContains('android');
\r
23487 // @property android23: Boolean; `true` for browsers running on Android 2 or Android 3.
\r
23488 var android23 = userAgentContains('android 2') || userAgentContains('android 3');
\r
23490 /* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */
\r
23491 var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit
\r
23492 // @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome)
\r
23493 var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window);
\r
23495 // @property opera: Boolean; `true` for the Opera browser
\r
23496 var opera = !!window.opera;
\r
23498 // @property chrome: Boolean; `true` for the Chrome browser.
\r
23499 var chrome = !edge && userAgentContains('chrome');
\r
23501 // @property gecko: Boolean; `true` for gecko-based browsers like Firefox.
\r
23502 var gecko = userAgentContains('gecko') && !webkit && !opera && !ie;
\r
23504 // @property safari: Boolean; `true` for the Safari browser.
\r
23505 var safari = !chrome && userAgentContains('safari');
\r
23507 var phantom = userAgentContains('phantom');
\r
23509 // @property opera12: Boolean
\r
23510 // `true` for the Opera browser supporting CSS transforms (version 12 or later).
\r
23511 var opera12 = 'OTransition' in style$1;
\r
23513 // @property win: Boolean; `true` when the browser is running in a Windows platform
\r
23514 var win = navigator.platform.indexOf('Win') === 0;
\r
23516 // @property ie3d: Boolean; `true` for all Internet Explorer versions supporting CSS transforms.
\r
23517 var ie3d = ie && ('transition' in style$1);
\r
23519 // @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms.
\r
23520 var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23;
\r
23522 // @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms.
\r
23523 var gecko3d = 'MozPerspective' in style$1;
\r
23525 // @property any3d: Boolean
\r
23526 // `true` for all browsers supporting CSS transforms.
\r
23527 var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom;
\r
23529 // @property mobile: Boolean; `true` for all browsers running in a mobile device.
\r
23530 var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile');
\r
23532 // @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device.
\r
23533 var mobileWebkit = mobile && webkit;
\r
23535 // @property mobileWebkit3d: Boolean
\r
23536 // `true` for all webkit-based browsers in a mobile device supporting CSS transforms.
\r
23537 var mobileWebkit3d = mobile && webkit3d;
\r
23539 // @property msPointer: Boolean
\r
23540 // `true` for browsers implementing the Microsoft touch events model (notably IE10).
\r
23541 var msPointer = !window.PointerEvent && window.MSPointerEvent;
\r
23543 // @property pointer: Boolean
\r
23544 // `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx).
\r
23545 var pointer = !!(window.PointerEvent || msPointer);
\r
23547 // @property touch: Boolean
\r
23548 // `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events).
\r
23549 // This does not necessarily mean that the browser is running in a computer with
\r
23550 // a touchscreen, it only means that the browser is capable of understanding
\r
23552 var touch = !window.L_NO_TOUCH && (pointer || 'ontouchstart' in window ||
\r
23553 (window.DocumentTouch && document instanceof window.DocumentTouch));
\r
23555 // @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device.
\r
23556 var mobileOpera = mobile && opera;
\r
23558 // @property mobileGecko: Boolean
\r
23559 // `true` for gecko-based browsers running in a mobile device.
\r
23560 var mobileGecko = mobile && gecko;
\r
23562 // @property retina: Boolean
\r
23563 // `true` for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%.
\r
23564 var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1;
\r
23566 // @property passiveEvents: Boolean
\r
23567 // `true` for browsers that support passive events.
\r
23568 var passiveEvents = (function () {
\r
23569 var supportsPassiveOption = false;
\r
23571 var opts = Object.defineProperty({}, 'passive', {
\r
23572 get: function () { // eslint-disable-line getter-return
\r
23573 supportsPassiveOption = true;
\r
23576 window.addEventListener('testPassiveEventSupport', falseFn, opts);
\r
23577 window.removeEventListener('testPassiveEventSupport', falseFn, opts);
\r
23579 // Errors can safely be ignored since this is only a browser support test.
\r
23581 return supportsPassiveOption;
\r
23584 // @property canvas: Boolean
\r
23585 // `true` when the browser supports [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).
\r
23586 var canvas = (function () {
\r
23587 return !!document.createElement('canvas').getContext;
\r
23590 // @property svg: Boolean
\r
23591 // `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG).
\r
23592 var svg = !!(document.createElementNS && svgCreate('svg').createSVGRect);
\r
23594 // @property vml: Boolean
\r
23595 // `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language).
\r
23596 var vml = !svg && (function () {
\r
23598 var div = document.createElement('div');
\r
23599 div.innerHTML = '<v:shape adj="1"/>';
\r
23601 var shape = div.firstChild;
\r
23602 shape.style.behavior = 'url(#default#VML)';
\r
23604 return shape && (typeof shape.adj === 'object');
\r
23612 function userAgentContains(str) {
\r
23613 return navigator.userAgent.toLowerCase().indexOf(str) >= 0;
\r
23622 android23: android23,
23623 androidStock: androidStock,
23632 webkit3d: webkit3d,
23636 mobileWebkit: mobileWebkit,
23637 mobileWebkit3d: mobileWebkit3d,
23638 msPointer: msPointer,
23641 mobileOpera: mobileOpera,
23642 mobileGecko: mobileGecko,
23644 passiveEvents: passiveEvents,
23651 * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
23655 var POINTER_DOWN = msPointer ? 'MSPointerDown' : 'pointerdown';
23656 var POINTER_MOVE = msPointer ? 'MSPointerMove' : 'pointermove';
23657 var POINTER_UP = msPointer ? 'MSPointerUp' : 'pointerup';
23658 var POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';
23660 var _pointers = {};
23661 var _pointerDocListener = false;
23663 // Provides a touch events wrapper for (ms)pointer events.
23664 // ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
23666 function addPointerListener(obj, type, handler, id) {
23667 if (type === 'touchstart') {
23668 _addPointerStart(obj, handler, id);
23670 } else if (type === 'touchmove') {
23671 _addPointerMove(obj, handler, id);
23673 } else if (type === 'touchend') {
23674 _addPointerEnd(obj, handler, id);
23680 function removePointerListener(obj, type, id) {
23681 var handler = obj['_leaflet_' + type + id];
23683 if (type === 'touchstart') {
23684 obj.removeEventListener(POINTER_DOWN, handler, false);
23686 } else if (type === 'touchmove') {
23687 obj.removeEventListener(POINTER_MOVE, handler, false);
23689 } else if (type === 'touchend') {
23690 obj.removeEventListener(POINTER_UP, handler, false);
23691 obj.removeEventListener(POINTER_CANCEL, handler, false);
23697 function _addPointerStart(obj, handler, id) {
23698 var onDown = bind(function (e) {
23699 // IE10 specific: MsTouch needs preventDefault. See #2000
23700 if (e.MSPOINTER_TYPE_TOUCH && e.pointerType === e.MSPOINTER_TYPE_TOUCH) {
23704 _handlePointer(e, handler);
23707 obj['_leaflet_touchstart' + id] = onDown;
23708 obj.addEventListener(POINTER_DOWN, onDown, false);
23710 // need to keep track of what pointers and how many are active to provide e.touches emulation
23711 if (!_pointerDocListener) {
23712 // we listen document as any drags that end by moving the touch off the screen get fired there
23713 document.addEventListener(POINTER_DOWN, _globalPointerDown, true);
23714 document.addEventListener(POINTER_MOVE, _globalPointerMove, true);
23715 document.addEventListener(POINTER_UP, _globalPointerUp, true);
23716 document.addEventListener(POINTER_CANCEL, _globalPointerUp, true);
23718 _pointerDocListener = true;
23722 function _globalPointerDown(e) {
23723 _pointers[e.pointerId] = e;
23726 function _globalPointerMove(e) {
23727 if (_pointers[e.pointerId]) {
23728 _pointers[e.pointerId] = e;
23732 function _globalPointerUp(e) {
23733 delete _pointers[e.pointerId];
23736 function _handlePointer(e, handler) {
23738 for (var i in _pointers) {
23739 e.touches.push(_pointers[i]);
23741 e.changedTouches = [e];
23746 function _addPointerMove(obj, handler, id) {
23747 var onMove = function (e) {
23748 // don't fire touch moves when mouse isn't down
23749 if ((e.pointerType === (e.MSPOINTER_TYPE_MOUSE || 'mouse')) && e.buttons === 0) {
23753 _handlePointer(e, handler);
23756 obj['_leaflet_touchmove' + id] = onMove;
23757 obj.addEventListener(POINTER_MOVE, onMove, false);
23760 function _addPointerEnd(obj, handler, id) {
23761 var onUp = function (e) {
23762 _handlePointer(e, handler);
23765 obj['_leaflet_touchend' + id] = onUp;
23766 obj.addEventListener(POINTER_UP, onUp, false);
23767 obj.addEventListener(POINTER_CANCEL, onUp, false);
23771 * Extends the event handling code with double tap support for mobile browsers.
\r
23774 var _touchstart = msPointer ? 'MSPointerDown' : pointer ? 'pointerdown' : 'touchstart';
\r
23775 var _touchend = msPointer ? 'MSPointerUp' : pointer ? 'pointerup' : 'touchend';
\r
23776 var _pre = '_leaflet_';
\r
23778 // inspired by Zepto touch code by Thomas Fuchs
\r
23779 function addDoubleTapListener(obj, handler, id) {
\r
23780 var last, touch$$1,
\r
23781 doubleTap = false,
\r
23784 function onTouchStart(e) {
\r
23787 if (!e.isPrimary) { return; }
\r
23788 if (e.pointerType === 'mouse') { return; } // mouse fires native dblclick
\r
23789 } else if (e.touches.length > 1) {
\r
23793 var now = Date.now(),
\r
23794 delta = now - (last || now);
\r
23796 touch$$1 = e.touches ? e.touches[0] : e;
\r
23797 doubleTap = (delta > 0 && delta <= delay);
\r
23801 function onTouchEnd(e) {
\r
23802 if (doubleTap && !touch$$1.cancelBubble) {
\r
23804 if (e.pointerType === 'mouse') { return; }
\r
23805 // work around .type being readonly with MSPointer* events
\r
23806 var newTouch = {},
\r
23809 for (i in touch$$1) {
\r
23810 prop = touch$$1[i];
\r
23811 newTouch[i] = prop && prop.bind ? prop.bind(touch$$1) : prop;
\r
23813 touch$$1 = newTouch;
\r
23815 touch$$1.type = 'dblclick';
\r
23816 touch$$1.button = 0;
\r
23817 handler(touch$$1);
\r
23822 obj[_pre + _touchstart + id] = onTouchStart;
\r
23823 obj[_pre + _touchend + id] = onTouchEnd;
\r
23824 obj[_pre + 'dblclick' + id] = handler;
\r
23826 obj.addEventListener(_touchstart, onTouchStart, passiveEvents ? {passive: false} : false);
\r
23827 obj.addEventListener(_touchend, onTouchEnd, passiveEvents ? {passive: false} : false);
\r
23829 // On some platforms (notably, chrome<55 on win10 + touchscreen + mouse),
\r
23830 // the browser doesn't fire touchend/pointerup events but does fire
\r
23831 // native dblclicks. See #4127.
\r
23832 // Edge 14 also fires native dblclicks, but only for pointerType mouse, see #5180.
\r
23833 obj.addEventListener('dblclick', handler, false);
\r
23838 function removeDoubleTapListener(obj, id) {
\r
23839 var touchstart = obj[_pre + _touchstart + id],
\r
23840 touchend = obj[_pre + _touchend + id],
\r
23841 dblclick = obj[_pre + 'dblclick' + id];
\r
23843 obj.removeEventListener(_touchstart, touchstart, passiveEvents ? {passive: false} : false);
\r
23844 obj.removeEventListener(_touchend, touchend, passiveEvents ? {passive: false} : false);
\r
23845 obj.removeEventListener('dblclick', dblclick, false);
\r
23851 * @namespace DomUtil
\r
23853 * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)
\r
23854 * tree, used by Leaflet internally.
\r
23856 * Most functions expecting or returning a `HTMLElement` also work for
\r
23857 * SVG elements. The only difference is that classes refer to CSS classes
\r
23858 * in HTML and SVG classes in SVG.
\r
23862 // @property TRANSFORM: String
\r
23863 // Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).
\r
23864 var TRANSFORM = testProp(
\r
23865 ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
\r
23867 // webkitTransition comes first because some browser versions that drop vendor prefix don't do
\r
23868 // the same for the transitionend event, in particular the Android 4.1 stock browser
\r
23870 // @property TRANSITION: String
\r
23871 // Vendor-prefixed transition style name.
\r
23872 var TRANSITION = testProp(
\r
23873 ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
\r
23875 // @property TRANSITION_END: String
\r
23876 // Vendor-prefixed transitionend event name.
\r
23877 var TRANSITION_END =
\r
23878 TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';
\r
23881 // @function get(id: String|HTMLElement): HTMLElement
\r
23882 // Returns an element given its DOM id, or returns the element itself
\r
23883 // if it was passed directly.
\r
23884 function get(id) {
\r
23885 return typeof id === 'string' ? document.getElementById(id) : id;
\r
23888 // @function getStyle(el: HTMLElement, styleAttrib: String): String
\r
23889 // Returns the value for a certain style attribute on an element,
\r
23890 // including computed values or values set through CSS.
\r
23891 function getStyle(el, style) {
\r
23892 var value = el.style[style] || (el.currentStyle && el.currentStyle[style]);
\r
23894 if ((!value || value === 'auto') && document.defaultView) {
\r
23895 var css = document.defaultView.getComputedStyle(el, null);
\r
23896 value = css ? css[style] : null;
\r
23898 return value === 'auto' ? null : value;
\r
23901 // @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement
\r
23902 // Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.
\r
23903 function create$1(tagName, className, container) {
\r
23904 var el = document.createElement(tagName);
\r
23905 el.className = className || '';
\r
23908 container.appendChild(el);
\r
23913 // @function remove(el: HTMLElement)
\r
23914 // Removes `el` from its parent element
\r
23915 function remove(el) {
\r
23916 var parent = el.parentNode;
\r
23918 parent.removeChild(el);
\r
23922 // @function empty(el: HTMLElement)
\r
23923 // Removes all of `el`'s children elements from `el`
\r
23924 function empty(el) {
\r
23925 while (el.firstChild) {
\r
23926 el.removeChild(el.firstChild);
\r
23930 // @function toFront(el: HTMLElement)
\r
23931 // Makes `el` the last child of its parent, so it renders in front of the other children.
\r
23932 function toFront(el) {
\r
23933 var parent = el.parentNode;
\r
23934 if (parent && parent.lastChild !== el) {
\r
23935 parent.appendChild(el);
\r
23939 // @function toBack(el: HTMLElement)
\r
23940 // Makes `el` the first child of its parent, so it renders behind the other children.
\r
23941 function toBack(el) {
\r
23942 var parent = el.parentNode;
\r
23943 if (parent && parent.firstChild !== el) {
\r
23944 parent.insertBefore(el, parent.firstChild);
\r
23948 // @function hasClass(el: HTMLElement, name: String): Boolean
\r
23949 // Returns `true` if the element's class attribute contains `name`.
\r
23950 function hasClass(el, name) {
\r
23951 if (el.classList !== undefined) {
\r
23952 return el.classList.contains(name);
\r
23954 var className = getClass(el);
\r
23955 return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className);
\r
23958 // @function addClass(el: HTMLElement, name: String)
\r
23959 // Adds `name` to the element's class attribute.
\r
23960 function addClass(el, name) {
\r
23961 if (el.classList !== undefined) {
\r
23962 var classes = splitWords(name);
\r
23963 for (var i = 0, len = classes.length; i < len; i++) {
\r
23964 el.classList.add(classes[i]);
\r
23966 } else if (!hasClass(el, name)) {
\r
23967 var className = getClass(el);
\r
23968 setClass(el, (className ? className + ' ' : '') + name);
\r
23972 // @function removeClass(el: HTMLElement, name: String)
\r
23973 // Removes `name` from the element's class attribute.
\r
23974 function removeClass(el, name) {
\r
23975 if (el.classList !== undefined) {
\r
23976 el.classList.remove(name);
\r
23978 setClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
\r
23982 // @function setClass(el: HTMLElement, name: String)
\r
23983 // Sets the element's class.
\r
23984 function setClass(el, name) {
\r
23985 if (el.className.baseVal === undefined) {
\r
23986 el.className = name;
\r
23988 // in case of SVG element
\r
23989 el.className.baseVal = name;
\r
23993 // @function getClass(el: HTMLElement): String
\r
23994 // Returns the element's class.
\r
23995 function getClass(el) {
\r
23996 // Check if the element is an SVGElementInstance and use the correspondingElement instead
\r
23997 // (Required for linked SVG elements in IE11.)
\r
23998 if (el.correspondingElement) {
\r
23999 el = el.correspondingElement;
\r
24001 return el.className.baseVal === undefined ? el.className : el.className.baseVal;
\r
24004 // @function setOpacity(el: HTMLElement, opacity: Number)
\r
24005 // Set the opacity of an element (including old IE support).
\r
24006 // `opacity` must be a number from `0` to `1`.
\r
24007 function setOpacity(el, value) {
\r
24008 if ('opacity' in el.style) {
\r
24009 el.style.opacity = value;
\r
24010 } else if ('filter' in el.style) {
\r
24011 _setOpacityIE(el, value);
\r
24015 function _setOpacityIE(el, value) {
\r
24016 var filter = false,
\r
24017 filterName = 'DXImageTransform.Microsoft.Alpha';
\r
24019 // filters collection throws an error if we try to retrieve a filter that doesn't exist
\r
24021 filter = el.filters.item(filterName);
\r
24023 // don't set opacity to 1 if we haven't already set an opacity,
\r
24024 // it isn't needed and breaks transparent pngs.
\r
24025 if (value === 1) { return; }
\r
24028 value = Math.round(value * 100);
\r
24031 filter.Enabled = (value !== 100);
\r
24032 filter.Opacity = value;
\r
24034 el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
\r
24038 // @function testProp(props: String[]): String|false
\r
24039 // Goes through the array of style names and returns the first name
\r
24040 // that is a valid style name for an element. If no such name is found,
\r
24041 // it returns false. Useful for vendor-prefixed styles like `transform`.
\r
24042 function testProp(props) {
\r
24043 var style = document.documentElement.style;
\r
24045 for (var i = 0; i < props.length; i++) {
\r
24046 if (props[i] in style) {
\r
24053 // @function setTransform(el: HTMLElement, offset: Point, scale?: Number)
\r
24054 // Resets the 3D CSS transform of `el` so it is translated by `offset` pixels
\r
24055 // and optionally scaled by `scale`. Does not have an effect if the
\r
24056 // browser doesn't support 3D CSS transforms.
\r
24057 function setTransform(el, offset, scale) {
\r
24058 var pos = offset || new Point(0, 0);
\r
24060 el.style[TRANSFORM] =
\r
24062 'translate(' + pos.x + 'px,' + pos.y + 'px)' :
\r
24063 'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
\r
24064 (scale ? ' scale(' + scale + ')' : '');
\r
24067 // @function setPosition(el: HTMLElement, position: Point)
\r
24068 // Sets the position of `el` to coordinates specified by `position`,
\r
24069 // using CSS translate or top/left positioning depending on the browser
\r
24070 // (used by Leaflet internally to position its layers).
\r
24071 function setPosition(el, point) {
\r
24073 /*eslint-disable */
\r
24074 el._leaflet_pos = point;
\r
24075 /* eslint-enable */
\r
24078 setTransform(el, point);
\r
24080 el.style.left = point.x + 'px';
\r
24081 el.style.top = point.y + 'px';
\r
24085 // @function getPosition(el: HTMLElement): Point
\r
24086 // Returns the coordinates of an element previously positioned with setPosition.
\r
24087 function getPosition(el) {
\r
24088 // this method is only used for elements previously positioned using setPosition,
\r
24089 // so it's safe to cache the position for performance
\r
24091 return el._leaflet_pos || new Point(0, 0);
\r
24094 // @function disableTextSelection()
\r
24095 // Prevents the user from generating `selectstart` DOM events, usually generated
\r
24096 // when the user drags the mouse through a page with text. Used internally
\r
24097 // by Leaflet to override the behaviour of any click-and-drag interaction on
\r
24098 // the map. Affects drag interactions on the whole document.
\r
24100 // @function enableTextSelection()
\r
24101 // Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).
\r
24102 var disableTextSelection;
\r
24103 var enableTextSelection;
\r
24105 if ('onselectstart' in document) {
\r
24106 disableTextSelection = function () {
\r
24107 on(window, 'selectstart', preventDefault);
\r
24109 enableTextSelection = function () {
\r
24110 off(window, 'selectstart', preventDefault);
\r
24113 var userSelectProperty = testProp(
\r
24114 ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);
\r
24116 disableTextSelection = function () {
\r
24117 if (userSelectProperty) {
\r
24118 var style = document.documentElement.style;
\r
24119 _userSelect = style[userSelectProperty];
\r
24120 style[userSelectProperty] = 'none';
\r
24123 enableTextSelection = function () {
\r
24124 if (userSelectProperty) {
\r
24125 document.documentElement.style[userSelectProperty] = _userSelect;
\r
24126 _userSelect = undefined;
\r
24131 // @function disableImageDrag()
\r
24132 // As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but
\r
24133 // for `dragstart` DOM events, usually generated when the user drags an image.
\r
24134 function disableImageDrag() {
\r
24135 on(window, 'dragstart', preventDefault);
\r
24138 // @function enableImageDrag()
\r
24139 // Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).
\r
24140 function enableImageDrag() {
\r
24141 off(window, 'dragstart', preventDefault);
\r
24144 var _outlineElement, _outlineStyle;
\r
24145 // @function preventOutline(el: HTMLElement)
\r
24146 // Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)
\r
24147 // of the element `el` invisible. Used internally by Leaflet to prevent
\r
24148 // focusable elements from displaying an outline when the user performs a
\r
24149 // drag interaction on them.
\r
24150 function preventOutline(element) {
\r
24151 while (element.tabIndex === -1) {
\r
24152 element = element.parentNode;
\r
24154 if (!element.style) { return; }
\r
24155 restoreOutline();
\r
24156 _outlineElement = element;
\r
24157 _outlineStyle = element.style.outline;
\r
24158 element.style.outline = 'none';
\r
24159 on(window, 'keydown', restoreOutline);
\r
24162 // @function restoreOutline()
\r
24163 // Cancels the effects of a previous [`L.DomUtil.preventOutline`]().
\r
24164 function restoreOutline() {
\r
24165 if (!_outlineElement) { return; }
\r
24166 _outlineElement.style.outline = _outlineStyle;
\r
24167 _outlineElement = undefined;
\r
24168 _outlineStyle = undefined;
\r
24169 off(window, 'keydown', restoreOutline);
\r
24172 // @function getSizedParentNode(el: HTMLElement): HTMLElement
\r
24173 // Finds the closest parent node which size (width and height) is not null.
\r
24174 function getSizedParentNode(element) {
\r
24176 element = element.parentNode;
\r
24177 } while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);
\r
24181 // @function getScale(el: HTMLElement): Object
\r
24182 // Computes the CSS scale currently applied on the element.
\r
24183 // Returns an object with `x` and `y` members as horizontal and vertical scales respectively,
\r
24184 // and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).
\r
24185 function getScale(element) {
\r
24186 var rect = element.getBoundingClientRect(); // Read-only in old browsers.
\r
24189 x: rect.width / element.offsetWidth || 1,
\r
24190 y: rect.height / element.offsetHeight || 1,
\r
24191 boundingClientRect: rect
\r
24196 TRANSFORM: TRANSFORM,
24197 TRANSITION: TRANSITION,
24198 TRANSITION_END: TRANSITION_END,
24200 getStyle: getStyle,
24206 hasClass: hasClass,
24207 addClass: addClass,
24208 removeClass: removeClass,
24209 setClass: setClass,
24210 getClass: getClass,
24211 setOpacity: setOpacity,
24212 testProp: testProp,
24213 setTransform: setTransform,
24214 setPosition: setPosition,
24215 getPosition: getPosition,
24216 disableTextSelection: disableTextSelection,
24217 enableTextSelection: enableTextSelection,
24218 disableImageDrag: disableImageDrag,
24219 enableImageDrag: enableImageDrag,
24220 preventOutline: preventOutline,
24221 restoreOutline: restoreOutline,
24222 getSizedParentNode: getSizedParentNode,
24227 * @namespace DomEvent
\r
24228 * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally.
\r
24231 // Inspired by John Resig, Dean Edwards and YUI addEvent implementations.
\r
24233 // @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this
\r
24234 // Adds a listener function (`fn`) to a particular DOM event type of the
\r
24235 // element `el`. You can optionally specify the context of the listener
\r
24236 // (object the `this` keyword will point to). You can also pass several
\r
24237 // space-separated types (e.g. `'click dblclick'`).
\r
24240 // @function on(el: HTMLElement, eventMap: Object, context?: Object): this
\r
24241 // Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
\r
24242 function on(obj, types, fn, context) {
\r
24244 if (typeof types === 'object') {
\r
24245 for (var type in types) {
\r
24246 addOne(obj, type, types[type], fn);
\r
24249 types = splitWords(types);
\r
24251 for (var i = 0, len = types.length; i < len; i++) {
\r
24252 addOne(obj, types[i], fn, context);
\r
24259 var eventsKey = '_leaflet_events';
\r
24261 // @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this
\r
24262 // Removes a previously added listener function.
\r
24263 // Note that if you passed a custom context to on, you must pass the same
\r
24264 // context to `off` in order to remove the listener.
\r
24267 // @function off(el: HTMLElement, eventMap: Object, context?: Object): this
\r
24268 // Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
\r
24269 function off(obj, types, fn, context) {
\r
24271 if (typeof types === 'object') {
\r
24272 for (var type in types) {
\r
24273 removeOne(obj, type, types[type], fn);
\r
24275 } else if (types) {
\r
24276 types = splitWords(types);
\r
24278 for (var i = 0, len = types.length; i < len; i++) {
\r
24279 removeOne(obj, types[i], fn, context);
\r
24282 for (var j in obj[eventsKey]) {
\r
24283 removeOne(obj, j, obj[eventsKey][j]);
\r
24285 delete obj[eventsKey];
\r
24291 function browserFiresNativeDblClick() {
\r
24292 // See https://github.com/w3c/pointerevents/issues/171
\r
24294 return !(edge || safari);
\r
24298 var mouseSubst = {
\r
24299 mouseenter: 'mouseover',
\r
24300 mouseleave: 'mouseout',
\r
24301 wheel: !('onwheel' in window) && 'mousewheel'
\r
24304 function addOne(obj, type, fn, context) {
\r
24305 var id = type + stamp(fn) + (context ? '_' + stamp(context) : '');
\r
24307 if (obj[eventsKey] && obj[eventsKey][id]) { return this; }
\r
24309 var handler = function (e) {
\r
24310 return fn.call(context || obj, e || window.event);
\r
24313 var originalHandler = handler;
\r
24315 if (pointer && type.indexOf('touch') === 0) {
\r
24316 // Needs DomEvent.Pointer.js
\r
24317 addPointerListener(obj, type, handler, id);
\r
24319 } else if (touch && (type === 'dblclick') && !browserFiresNativeDblClick()) {
\r
24320 addDoubleTapListener(obj, handler, id);
\r
24322 } else if ('addEventListener' in obj) {
\r
24324 if (type === 'touchstart' || type === 'touchmove' || type === 'wheel' || type === 'mousewheel') {
\r
24325 obj.addEventListener(mouseSubst[type] || type, handler, passiveEvents ? {passive: false} : false);
\r
24327 } else if (type === 'mouseenter' || type === 'mouseleave') {
\r
24328 handler = function (e) {
\r
24329 e = e || window.event;
\r
24330 if (isExternalTarget(obj, e)) {
\r
24331 originalHandler(e);
\r
24334 obj.addEventListener(mouseSubst[type], handler, false);
\r
24337 obj.addEventListener(type, originalHandler, false);
\r
24340 } else if ('attachEvent' in obj) {
\r
24341 obj.attachEvent('on' + type, handler);
\r
24344 obj[eventsKey] = obj[eventsKey] || {};
\r
24345 obj[eventsKey][id] = handler;
\r
24348 function removeOne(obj, type, fn, context) {
\r
24350 var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''),
\r
24351 handler = obj[eventsKey] && obj[eventsKey][id];
\r
24353 if (!handler) { return this; }
\r
24355 if (pointer && type.indexOf('touch') === 0) {
\r
24356 removePointerListener(obj, type, id);
\r
24358 } else if (touch && (type === 'dblclick') && !browserFiresNativeDblClick()) {
\r
24359 removeDoubleTapListener(obj, id);
\r
24361 } else if ('removeEventListener' in obj) {
\r
24363 obj.removeEventListener(mouseSubst[type] || type, handler, false);
\r
24365 } else if ('detachEvent' in obj) {
\r
24366 obj.detachEvent('on' + type, handler);
\r
24369 obj[eventsKey][id] = null;
\r
24372 // @function stopPropagation(ev: DOMEvent): this
\r
24373 // Stop the given event from propagation to parent elements. Used inside the listener functions:
\r
24375 // L.DomEvent.on(div, 'click', function (ev) {
\r
24376 // L.DomEvent.stopPropagation(ev);
\r
24379 function stopPropagation(e) {
\r
24381 if (e.stopPropagation) {
\r
24382 e.stopPropagation();
\r
24383 } else if (e.originalEvent) { // In case of Leaflet event.
\r
24384 e.originalEvent._stopped = true;
\r
24386 e.cancelBubble = true;
\r
24393 // @function disableScrollPropagation(el: HTMLElement): this
\r
24394 // Adds `stopPropagation` to the element's `'wheel'` events (plus browser variants).
\r
24395 function disableScrollPropagation(el) {
\r
24396 addOne(el, 'wheel', stopPropagation);
\r
24400 // @function disableClickPropagation(el: HTMLElement): this
\r
24401 // Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`,
\r
24402 // `'mousedown'` and `'touchstart'` events (plus browser variants).
\r
24403 function disableClickPropagation(el) {
\r
24404 on(el, 'mousedown touchstart dblclick', stopPropagation);
\r
24405 addOne(el, 'click', fakeStop);
\r
24409 // @function preventDefault(ev: DOMEvent): this
\r
24410 // Prevents the default action of the DOM Event `ev` from happening (such as
\r
24411 // following a link in the href of the a element, or doing a POST request
\r
24412 // with page reload when a `<form>` is submitted).
\r
24413 // Use it inside listener functions.
\r
24414 function preventDefault(e) {
\r
24415 if (e.preventDefault) {
\r
24416 e.preventDefault();
\r
24418 e.returnValue = false;
\r
24423 // @function stop(ev: DOMEvent): this
\r
24424 // Does `stopPropagation` and `preventDefault` at the same time.
\r
24425 function stop(e) {
\r
24426 preventDefault(e);
\r
24427 stopPropagation(e);
\r
24431 // @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point
\r
24432 // Gets normalized mouse position from a DOM event relative to the
\r
24433 // `container` (border excluded) or to the whole page if not specified.
\r
24434 function getMousePosition(e, container) {
\r
24435 if (!container) {
\r
24436 return new Point(e.clientX, e.clientY);
\r
24439 var scale = getScale(container),
\r
24440 offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y)
\r
24442 return new Point(
\r
24443 // offset.left/top values are in page scale (like clientX/Y),
\r
24444 // whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).
\r
24445 (e.clientX - offset.left) / scale.x - container.clientLeft,
\r
24446 (e.clientY - offset.top) / scale.y - container.clientTop
\r
24450 // Chrome on Win scrolls double the pixels as in other platforms (see #4538),
\r
24451 // and Firefox scrolls device pixels, not CSS pixels
\r
24452 var wheelPxFactor =
\r
24453 (win && chrome) ? 2 * window.devicePixelRatio :
\r
24454 gecko ? window.devicePixelRatio : 1;
\r
24456 // @function getWheelDelta(ev: DOMEvent): Number
\r
24457 // Gets normalized wheel delta from a wheel DOM event, in vertical
\r
24458 // pixels scrolled (negative if scrolling down).
\r
24459 // Events from pointing devices without precise scrolling are mapped to
\r
24460 // a best guess of 60 pixels.
\r
24461 function getWheelDelta(e) {
\r
24462 return (edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta
\r
24463 (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels
\r
24464 (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines
\r
24465 (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages
\r
24466 (e.deltaX || e.deltaZ) ? 0 : // Skip horizontal/depth wheel events
\r
24467 e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels
\r
24468 (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines
\r
24469 e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages
\r
24473 var skipEvents = {};
\r
24475 function fakeStop(e) {
\r
24476 // fakes stopPropagation by setting a special event flag, checked/reset with skipped(e)
\r
24477 skipEvents[e.type] = true;
\r
24480 function skipped(e) {
\r
24481 var events = skipEvents[e.type];
\r
24482 // reset when checking, as it's only used in map container and propagates outside of the map
\r
24483 skipEvents[e.type] = false;
\r
24487 // check if element really left/entered the event target (for mouseenter/mouseleave)
\r
24488 function isExternalTarget(el, e) {
\r
24490 var related = e.relatedTarget;
\r
24492 if (!related) { return true; }
\r
24495 while (related && (related !== el)) {
\r
24496 related = related.parentNode;
\r
24501 return (related !== el);
\r
24507 stopPropagation: stopPropagation,
24508 disableScrollPropagation: disableScrollPropagation,
24509 disableClickPropagation: disableClickPropagation,
24510 preventDefault: preventDefault,
24512 getMousePosition: getMousePosition,
24513 getWheelDelta: getWheelDelta,
24514 fakeStop: fakeStop,
24516 isExternalTarget: isExternalTarget,
24518 removeListener: off
24522 * @class PosAnimation
24523 * @aka L.PosAnimation
24524 * @inherits Evented
24525 * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.
24529 * var fx = new L.PosAnimation();
24530 * fx.run(el, [300, 500], 0.5);
24533 * @constructor L.PosAnimation()
24534 * Creates a `PosAnimation` object.
24538 var PosAnimation = Evented.extend({
24540 // @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)
24541 // Run an animation of a given element to a new position, optionally setting
24542 // duration in seconds (`0.25` by default) and easing linearity factor (3rd
24543 // argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1),
24544 // `0.5` by default).
24545 run: function (el, newPos, duration, easeLinearity) {
24549 this._inProgress = true;
24550 this._duration = duration || 0.25;
24551 this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);
24553 this._startPos = getPosition(el);
24554 this._offset = newPos.subtract(this._startPos);
24555 this._startTime = +new Date();
24557 // @event start: Event
24558 // Fired when the animation starts
24559 this.fire('start');
24565 // Stops the animation (if currently running).
24566 stop: function () {
24567 if (!this._inProgress) { return; }
24573 _animate: function () {
24575 this._animId = requestAnimFrame(this._animate, this);
24579 _step: function (round) {
24580 var elapsed = (+new Date()) - this._startTime,
24581 duration = this._duration * 1000;
24583 if (elapsed < duration) {
24584 this._runFrame(this._easeOut(elapsed / duration), round);
24591 _runFrame: function (progress, round) {
24592 var pos = this._startPos.add(this._offset.multiplyBy(progress));
24596 setPosition(this._el, pos);
24598 // @event step: Event
24599 // Fired continuously during the animation.
24603 _complete: function () {
24604 cancelAnimFrame(this._animId);
24606 this._inProgress = false;
24607 // @event end: Event
24608 // Fired when the animation ends.
24612 _easeOut: function (t) {
24613 return 1 - Math.pow(1 - t, this._easeOutPower);
24620 * @inherits Evented
\r
24622 * The central class of the API — it is used to create a map on a page and manipulate it.
\r
24627 * // initialize the map on the "map" div with a given center and zoom
\r
24628 * var map = L.map('map', {
\r
24629 * center: [51.505, -0.09],
\r
24636 var Map = Evented.extend({
\r
24639 // @section Map State Options
\r
24640 // @option crs: CRS = L.CRS.EPSG3857
\r
24641 // The [Coordinate Reference System](#crs) to use. Don't change this if you're not
\r
24642 // sure what it means.
\r
24645 // @option center: LatLng = undefined
\r
24646 // Initial geographic center of the map
\r
24647 center: undefined,
\r
24649 // @option zoom: Number = undefined
\r
24650 // Initial map zoom level
\r
24653 // @option minZoom: Number = *
\r
24654 // Minimum zoom level of the map.
\r
24655 // If not specified and at least one `GridLayer` or `TileLayer` is in the map,
\r
24656 // the lowest of their `minZoom` options will be used instead.
\r
24657 minZoom: undefined,
\r
24659 // @option maxZoom: Number = *
\r
24660 // Maximum zoom level of the map.
\r
24661 // If not specified and at least one `GridLayer` or `TileLayer` is in the map,
\r
24662 // the highest of their `maxZoom` options will be used instead.
\r
24663 maxZoom: undefined,
\r
24665 // @option layers: Layer[] = []
\r
24666 // Array of layers that will be added to the map initially
\r
24669 // @option maxBounds: LatLngBounds = null
\r
24670 // When this option is set, the map restricts the view to the given
\r
24671 // geographical bounds, bouncing the user back if the user tries to pan
\r
24672 // outside the view. To set the restriction dynamically, use
\r
24673 // [`setMaxBounds`](#map-setmaxbounds) method.
\r
24674 maxBounds: undefined,
\r
24676 // @option renderer: Renderer = *
\r
24677 // The default method for drawing vector layers on the map. `L.SVG`
\r
24678 // or `L.Canvas` by default depending on browser support.
\r
24679 renderer: undefined,
\r
24682 // @section Animation Options
\r
24683 // @option zoomAnimation: Boolean = true
\r
24684 // Whether the map zoom animation is enabled. By default it's enabled
\r
24685 // in all browsers that support CSS3 Transitions except Android.
\r
24686 zoomAnimation: true,
\r
24688 // @option zoomAnimationThreshold: Number = 4
\r
24689 // Won't animate zoom if the zoom difference exceeds this value.
\r
24690 zoomAnimationThreshold: 4,
\r
24692 // @option fadeAnimation: Boolean = true
\r
24693 // Whether the tile fade animation is enabled. By default it's enabled
\r
24694 // in all browsers that support CSS3 Transitions except Android.
\r
24695 fadeAnimation: true,
\r
24697 // @option markerZoomAnimation: Boolean = true
\r
24698 // Whether markers animate their zoom with the zoom animation, if disabled
\r
24699 // they will disappear for the length of the animation. By default it's
\r
24700 // enabled in all browsers that support CSS3 Transitions except Android.
\r
24701 markerZoomAnimation: true,
\r
24703 // @option transform3DLimit: Number = 2^23
\r
24704 // Defines the maximum size of a CSS translation transform. The default
\r
24705 // value should not be changed unless a web browser positions layers in
\r
24706 // the wrong place after doing a large `panBy`.
\r
24707 transform3DLimit: 8388608, // Precision limit of a 32-bit float
\r
24709 // @section Interaction Options
\r
24710 // @option zoomSnap: Number = 1
\r
24711 // Forces the map's zoom level to always be a multiple of this, particularly
\r
24712 // right after a [`fitBounds()`](#map-fitbounds) or a pinch-zoom.
\r
24713 // By default, the zoom level snaps to the nearest integer; lower values
\r
24714 // (e.g. `0.5` or `0.1`) allow for greater granularity. A value of `0`
\r
24715 // means the zoom level will not be snapped after `fitBounds` or a pinch-zoom.
\r
24718 // @option zoomDelta: Number = 1
\r
24719 // Controls how much the map's zoom level will change after a
\r
24720 // [`zoomIn()`](#map-zoomin), [`zoomOut()`](#map-zoomout), pressing `+`
\r
24721 // or `-` on the keyboard, or using the [zoom controls](#control-zoom).
\r
24722 // Values smaller than `1` (e.g. `0.5`) allow for greater granularity.
\r
24725 // @option trackResize: Boolean = true
\r
24726 // Whether the map automatically handles browser window resize to update itself.
\r
24727 trackResize: true
\r
24730 initialize: function (id, options) { // (HTMLElement or String, Object)
\r
24731 options = setOptions(this, options);
\r
24733 // Make sure to assign internal flags at the beginning,
\r
24734 // to avoid inconsistent state in some edge cases.
\r
24735 this._handlers = [];
\r
24736 this._layers = {};
\r
24737 this._zoomBoundLayers = {};
\r
24738 this._sizeChanged = true;
\r
24740 this._initContainer(id);
\r
24741 this._initLayout();
\r
24743 // hack for https://github.com/Leaflet/Leaflet/issues/1980
\r
24744 this._onResize = bind(this._onResize, this);
\r
24746 this._initEvents();
\r
24748 if (options.maxBounds) {
\r
24749 this.setMaxBounds(options.maxBounds);
\r
24752 if (options.zoom !== undefined) {
\r
24753 this._zoom = this._limitZoom(options.zoom);
\r
24756 if (options.center && options.zoom !== undefined) {
\r
24757 this.setView(toLatLng(options.center), options.zoom, {reset: true});
\r
24760 this.callInitHooks();
\r
24762 // don't animate on browsers without hardware-accelerated transitions or old Android/Opera
\r
24763 this._zoomAnimated = TRANSITION && any3d && !mobileOpera &&
\r
24764 this.options.zoomAnimation;
\r
24766 // zoom transitions run with the same duration for all layers, so if one of transitionend events
\r
24767 // happens after starting zoom animation (propagating to the map pane), we know that it ended globally
\r
24768 if (this._zoomAnimated) {
\r
24769 this._createAnimProxy();
\r
24770 on(this._proxy, TRANSITION_END, this._catchTransitionEnd, this);
\r
24773 this._addLayers(this.options.layers);
\r
24777 // @section Methods for modifying map state
\r
24779 // @method setView(center: LatLng, zoom: Number, options?: Zoom/pan options): this
\r
24780 // Sets the view of the map (geographical center and zoom) with the given
\r
24781 // animation options.
\r
24782 setView: function (center, zoom, options) {
\r
24784 zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom);
\r
24785 center = this._limitCenter(toLatLng(center), zoom, this.options.maxBounds);
\r
24786 options = options || {};
\r
24790 if (this._loaded && !options.reset && options !== true) {
\r
24792 if (options.animate !== undefined) {
\r
24793 options.zoom = extend({animate: options.animate}, options.zoom);
\r
24794 options.pan = extend({animate: options.animate, duration: options.duration}, options.pan);
\r
24797 // try animating pan or zoom
\r
24798 var moved = (this._zoom !== zoom) ?
\r
24799 this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) :
\r
24800 this._tryAnimatedPan(center, options.pan);
\r
24803 // prevent resize handler call, the view will refresh after animation anyway
\r
24804 clearTimeout(this._sizeTimer);
\r
24809 // animation didn't start, just reset the map view
\r
24810 this._resetView(center, zoom);
\r
24815 // @method setZoom(zoom: Number, options?: Zoom/pan options): this
\r
24816 // Sets the zoom of the map.
\r
24817 setZoom: function (zoom, options) {
\r
24818 if (!this._loaded) {
\r
24819 this._zoom = zoom;
\r
24822 return this.setView(this.getCenter(), zoom, {zoom: options});
\r
24825 // @method zoomIn(delta?: Number, options?: Zoom options): this
\r
24826 // Increases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).
\r
24827 zoomIn: function (delta, options) {
\r
24828 delta = delta || (any3d ? this.options.zoomDelta : 1);
\r
24829 return this.setZoom(this._zoom + delta, options);
\r
24832 // @method zoomOut(delta?: Number, options?: Zoom options): this
\r
24833 // Decreases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).
\r
24834 zoomOut: function (delta, options) {
\r
24835 delta = delta || (any3d ? this.options.zoomDelta : 1);
\r
24836 return this.setZoom(this._zoom - delta, options);
\r
24839 // @method setZoomAround(latlng: LatLng, zoom: Number, options: Zoom options): this
\r
24840 // Zooms the map while keeping a specified geographical point on the map
\r
24841 // stationary (e.g. used internally for scroll zoom and double-click zoom).
\r
24843 // @method setZoomAround(offset: Point, zoom: Number, options: Zoom options): this
\r
24844 // Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.
\r
24845 setZoomAround: function (latlng, zoom, options) {
\r
24846 var scale = this.getZoomScale(zoom),
\r
24847 viewHalf = this.getSize().divideBy(2),
\r
24848 containerPoint = latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng),
\r
24850 centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale),
\r
24851 newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));
\r
24853 return this.setView(newCenter, zoom, {zoom: options});
\r
24856 _getBoundsCenterZoom: function (bounds, options) {
\r
24858 options = options || {};
\r
24859 bounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds);
\r
24861 var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
\r
24862 paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),
\r
24864 zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
\r
24866 zoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;
\r
24868 if (zoom === Infinity) {
\r
24870 center: bounds.getCenter(),
\r
24875 var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),
\r
24877 swPoint = this.project(bounds.getSouthWest(), zoom),
\r
24878 nePoint = this.project(bounds.getNorthEast(), zoom),
\r
24879 center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);
\r
24887 // @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this
\r
24888 // Sets a map view that contains the given geographical bounds with the
\r
24889 // maximum zoom level possible.
\r
24890 fitBounds: function (bounds, options) {
\r
24892 bounds = toLatLngBounds(bounds);
\r
24894 if (!bounds.isValid()) {
\r
24895 throw new Error('Bounds are not valid.');
\r
24898 var target = this._getBoundsCenterZoom(bounds, options);
\r
24899 return this.setView(target.center, target.zoom, options);
\r
24902 // @method fitWorld(options?: fitBounds options): this
\r
24903 // Sets a map view that mostly contains the whole world with the maximum
\r
24904 // zoom level possible.
\r
24905 fitWorld: function (options) {
\r
24906 return this.fitBounds([[-90, -180], [90, 180]], options);
\r
24909 // @method panTo(latlng: LatLng, options?: Pan options): this
\r
24910 // Pans the map to a given center.
\r
24911 panTo: function (center, options) { // (LatLng)
\r
24912 return this.setView(center, this._zoom, {pan: options});
\r
24915 // @method panBy(offset: Point, options?: Pan options): this
\r
24916 // Pans the map by a given number of pixels (animated).
\r
24917 panBy: function (offset, options) {
\r
24918 offset = toPoint(offset).round();
\r
24919 options = options || {};
\r
24921 if (!offset.x && !offset.y) {
\r
24922 return this.fire('moveend');
\r
24924 // If we pan too far, Chrome gets issues with tiles
\r
24925 // and makes them disappear or appear in the wrong place (slightly offset) #2602
\r
24926 if (options.animate !== true && !this.getSize().contains(offset)) {
\r
24927 this._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom());
\r
24931 if (!this._panAnim) {
\r
24932 this._panAnim = new PosAnimation();
\r
24934 this._panAnim.on({
\r
24935 'step': this._onPanTransitionStep,
\r
24936 'end': this._onPanTransitionEnd
\r
24940 // don't fire movestart if animating inertia
\r
24941 if (!options.noMoveStart) {
\r
24942 this.fire('movestart');
\r
24945 // animate pan unless animate: false specified
\r
24946 if (options.animate !== false) {
\r
24947 addClass(this._mapPane, 'leaflet-pan-anim');
\r
24949 var newPos = this._getMapPanePos().subtract(offset).round();
\r
24950 this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);
\r
24952 this._rawPanBy(offset);
\r
24953 this.fire('move').fire('moveend');
\r
24959 // @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this
\r
24960 // Sets the view of the map (geographical center and zoom) performing a smooth
\r
24961 // pan-zoom animation.
\r
24962 flyTo: function (targetCenter, targetZoom, options) {
\r
24964 options = options || {};
\r
24965 if (options.animate === false || !any3d) {
\r
24966 return this.setView(targetCenter, targetZoom, options);
\r
24971 var from = this.project(this.getCenter()),
\r
24972 to = this.project(targetCenter),
\r
24973 size = this.getSize(),
\r
24974 startZoom = this._zoom;
\r
24976 targetCenter = toLatLng(targetCenter);
\r
24977 targetZoom = targetZoom === undefined ? startZoom : targetZoom;
\r
24979 var w0 = Math.max(size.x, size.y),
\r
24980 w1 = w0 * this.getZoomScale(startZoom, targetZoom),
\r
24981 u1 = (to.distanceTo(from)) || 1,
\r
24983 rho2 = rho * rho;
\r
24986 var s1 = i ? -1 : 1,
\r
24987 s2 = i ? w1 : w0,
\r
24988 t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1,
\r
24989 b1 = 2 * s2 * rho2 * u1,
\r
24991 sq = Math.sqrt(b * b + 1) - b;
\r
24993 // workaround for floating point precision bug when sq = 0, log = -Infinite,
\r
24994 // thus triggering an infinite loop in flyTo
\r
24995 var log = sq < 0.000000001 ? -18 : Math.log(sq);
\r
25000 function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }
\r
25001 function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }
\r
25002 function tanh(n) { return sinh(n) / cosh(n); }
\r
25006 function w(s) { return w0 * (cosh(r0) / cosh(r0 + rho * s)); }
\r
25007 function u(s) { return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2; }
\r
25009 function easeOut(t) { return 1 - Math.pow(1 - t, 1.5); }
\r
25011 var start = Date.now(),
\r
25012 S = (r(1) - r0) / rho,
\r
25013 duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8;
\r
25015 function frame() {
\r
25016 var t = (Date.now() - start) / duration,
\r
25017 s = easeOut(t) * S;
\r
25020 this._flyToFrame = requestAnimFrame(frame, this);
\r
25023 this.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom),
\r
25024 this.getScaleZoom(w0 / w(s), startZoom),
\r
25029 ._move(targetCenter, targetZoom)
\r
25034 this._moveStart(true, options.noMoveStart);
\r
25036 frame.call(this);
\r
25040 // @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this
\r
25041 // Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto),
\r
25042 // but takes a bounds parameter like [`fitBounds`](#map-fitbounds).
\r
25043 flyToBounds: function (bounds, options) {
\r
25044 var target = this._getBoundsCenterZoom(bounds, options);
\r
25045 return this.flyTo(target.center, target.zoom, options);
\r
25048 // @method setMaxBounds(bounds: LatLngBounds): this
\r
25049 // Restricts the map view to the given bounds (see the [maxBounds](#map-maxbounds) option).
\r
25050 setMaxBounds: function (bounds) {
\r
25051 bounds = toLatLngBounds(bounds);
\r
25053 if (!bounds.isValid()) {
\r
25054 this.options.maxBounds = null;
\r
25055 return this.off('moveend', this._panInsideMaxBounds);
\r
25056 } else if (this.options.maxBounds) {
\r
25057 this.off('moveend', this._panInsideMaxBounds);
\r
25060 this.options.maxBounds = bounds;
\r
25062 if (this._loaded) {
\r
25063 this._panInsideMaxBounds();
\r
25066 return this.on('moveend', this._panInsideMaxBounds);
\r
25069 // @method setMinZoom(zoom: Number): this
\r
25070 // Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option).
\r
25071 setMinZoom: function (zoom) {
\r
25072 var oldZoom = this.options.minZoom;
\r
25073 this.options.minZoom = zoom;
\r
25075 if (this._loaded && oldZoom !== zoom) {
\r
25076 this.fire('zoomlevelschange');
\r
25078 if (this.getZoom() < this.options.minZoom) {
\r
25079 return this.setZoom(zoom);
\r
25086 // @method setMaxZoom(zoom: Number): this
\r
25087 // Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option).
\r
25088 setMaxZoom: function (zoom) {
\r
25089 var oldZoom = this.options.maxZoom;
\r
25090 this.options.maxZoom = zoom;
\r
25092 if (this._loaded && oldZoom !== zoom) {
\r
25093 this.fire('zoomlevelschange');
\r
25095 if (this.getZoom() > this.options.maxZoom) {
\r
25096 return this.setZoom(zoom);
\r
25103 // @method panInsideBounds(bounds: LatLngBounds, options?: Pan options): this
\r
25104 // Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.
\r
25105 panInsideBounds: function (bounds, options) {
\r
25106 this._enforcingBounds = true;
\r
25107 var center = this.getCenter(),
\r
25108 newCenter = this._limitCenter(center, this._zoom, toLatLngBounds(bounds));
\r
25110 if (!center.equals(newCenter)) {
\r
25111 this.panTo(newCenter, options);
\r
25114 this._enforcingBounds = false;
\r
25118 // @method panInside(latlng: LatLng, options?: options): this
\r
25119 // Pans the map the minimum amount to make the `latlng` visible. Use
\r
25120 // `padding`, `paddingTopLeft` and `paddingTopRight` options to fit
\r
25121 // the display to more restricted bounds, like [`fitBounds`](#map-fitbounds).
\r
25122 // If `latlng` is already within the (optionally padded) display bounds,
\r
25123 // the map will not be panned.
\r
25124 panInside: function (latlng, options) {
\r
25125 options = options || {};
\r
25127 var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
\r
25128 paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),
\r
25129 center = this.getCenter(),
\r
25130 pixelCenter = this.project(center),
\r
25131 pixelPoint = this.project(latlng),
\r
25132 pixelBounds = this.getPixelBounds(),
\r
25133 halfPixelBounds = pixelBounds.getSize().divideBy(2),
\r
25134 paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]);
\r
25136 if (!paddedBounds.contains(pixelPoint)) {
\r
25137 this._enforcingBounds = true;
\r
25138 var diff = pixelCenter.subtract(pixelPoint),
\r
25139 newCenter = toPoint(pixelPoint.x + diff.x, pixelPoint.y + diff.y);
\r
25141 if (pixelPoint.x < paddedBounds.min.x || pixelPoint.x > paddedBounds.max.x) {
\r
25142 newCenter.x = pixelCenter.x - diff.x;
\r
25143 if (diff.x > 0) {
\r
25144 newCenter.x += halfPixelBounds.x - paddingTL.x;
\r
25146 newCenter.x -= halfPixelBounds.x - paddingBR.x;
\r
25149 if (pixelPoint.y < paddedBounds.min.y || pixelPoint.y > paddedBounds.max.y) {
\r
25150 newCenter.y = pixelCenter.y - diff.y;
\r
25151 if (diff.y > 0) {
\r
25152 newCenter.y += halfPixelBounds.y - paddingTL.y;
\r
25154 newCenter.y -= halfPixelBounds.y - paddingBR.y;
\r
25157 this.panTo(this.unproject(newCenter), options);
\r
25158 this._enforcingBounds = false;
\r
25163 // @method invalidateSize(options: Zoom/pan options): this
\r
25164 // Checks if the map container size changed and updates the map if so —
\r
25165 // call it after you've changed the map size dynamically, also animating
\r
25166 // pan by default. If `options.pan` is `false`, panning will not occur.
\r
25167 // If `options.debounceMoveend` is `true`, it will delay `moveend` event so
\r
25168 // that it doesn't happen often even if the method is called many
\r
25169 // times in a row.
\r
25172 // @method invalidateSize(animate: Boolean): this
\r
25173 // Checks if the map container size changed and updates the map if so —
\r
25174 // call it after you've changed the map size dynamically, also animating
\r
25175 // pan by default.
\r
25176 invalidateSize: function (options) {
\r
25177 if (!this._loaded) { return this; }
\r
25179 options = extend({
\r
25182 }, options === true ? {animate: true} : options);
\r
25184 var oldSize = this.getSize();
\r
25185 this._sizeChanged = true;
\r
25186 this._lastCenter = null;
\r
25188 var newSize = this.getSize(),
\r
25189 oldCenter = oldSize.divideBy(2).round(),
\r
25190 newCenter = newSize.divideBy(2).round(),
\r
25191 offset = oldCenter.subtract(newCenter);
\r
25193 if (!offset.x && !offset.y) { return this; }
\r
25195 if (options.animate && options.pan) {
\r
25196 this.panBy(offset);
\r
25199 if (options.pan) {
\r
25200 this._rawPanBy(offset);
\r
25203 this.fire('move');
\r
25205 if (options.debounceMoveend) {
\r
25206 clearTimeout(this._sizeTimer);
\r
25207 this._sizeTimer = setTimeout(bind(this.fire, this, 'moveend'), 200);
\r
25209 this.fire('moveend');
\r
25213 // @section Map state change events
\r
25214 // @event resize: ResizeEvent
\r
25215 // Fired when the map is resized.
\r
25216 return this.fire('resize', {
\r
25217 oldSize: oldSize,
\r
25222 // @section Methods for modifying map state
\r
25223 // @method stop(): this
\r
25224 // Stops the currently running `panTo` or `flyTo` animation, if any.
\r
25225 stop: function () {
\r
25226 this.setZoom(this._limitZoom(this._zoom));
\r
25227 if (!this.options.zoomSnap) {
\r
25228 this.fire('viewreset');
\r
25230 return this._stop();
\r
25233 // @section Geolocation methods
\r
25234 // @method locate(options?: Locate options): this
\r
25235 // Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound)
\r
25236 // event with location data on success or a [`locationerror`](#map-locationerror) event on failure,
\r
25237 // and optionally sets the map view to the user's location with respect to
\r
25238 // detection accuracy (or to the world view if geolocation failed).
\r
25239 // Note that, if your page doesn't use HTTPS, this method will fail in
\r
25240 // modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins))
\r
25241 // See `Locate options` for more details.
\r
25242 locate: function (options) {
\r
25244 options = this._locateOptions = extend({
\r
25247 // setView: false
\r
25248 // maxZoom: <Number>
\r
25250 // enableHighAccuracy: false
\r
25253 if (!('geolocation' in navigator)) {
\r
25254 this._handleGeolocationError({
\r
25256 message: 'Geolocation not supported.'
\r
25261 var onResponse = bind(this._handleGeolocationResponse, this),
\r
25262 onError = bind(this._handleGeolocationError, this);
\r
25264 if (options.watch) {
\r
25265 this._locationWatchId =
\r
25266 navigator.geolocation.watchPosition(onResponse, onError, options);
\r
25268 navigator.geolocation.getCurrentPosition(onResponse, onError, options);
\r
25273 // @method stopLocate(): this
\r
25274 // Stops watching location previously initiated by `map.locate({watch: true})`
\r
25275 // and aborts resetting the map view if map.locate was called with
\r
25276 // `{setView: true}`.
\r
25277 stopLocate: function () {
\r
25278 if (navigator.geolocation && navigator.geolocation.clearWatch) {
\r
25279 navigator.geolocation.clearWatch(this._locationWatchId);
\r
25281 if (this._locateOptions) {
\r
25282 this._locateOptions.setView = false;
\r
25287 _handleGeolocationError: function (error) {
\r
25288 var c = error.code,
\r
25289 message = error.message ||
\r
25290 (c === 1 ? 'permission denied' :
\r
25291 (c === 2 ? 'position unavailable' : 'timeout'));
\r
25293 if (this._locateOptions.setView && !this._loaded) {
\r
25297 // @section Location events
\r
25298 // @event locationerror: ErrorEvent
\r
25299 // Fired when geolocation (using the [`locate`](#map-locate) method) failed.
\r
25300 this.fire('locationerror', {
\r
25302 message: 'Geolocation error: ' + message + '.'
\r
25306 _handleGeolocationResponse: function (pos) {
\r
25307 var lat = pos.coords.latitude,
\r
25308 lng = pos.coords.longitude,
\r
25309 latlng = new LatLng(lat, lng),
\r
25310 bounds = latlng.toBounds(pos.coords.accuracy * 2),
\r
25311 options = this._locateOptions;
\r
25313 if (options.setView) {
\r
25314 var zoom = this.getBoundsZoom(bounds);
\r
25315 this.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom);
\r
25321 timestamp: pos.timestamp
\r
25324 for (var i in pos.coords) {
\r
25325 if (typeof pos.coords[i] === 'number') {
\r
25326 data[i] = pos.coords[i];
\r
25330 // @event locationfound: LocationEvent
\r
25331 // Fired when geolocation (using the [`locate`](#map-locate) method)
\r
25332 // went successfully.
\r
25333 this.fire('locationfound', data);
\r
25336 // TODO Appropriate docs section?
\r
25337 // @section Other Methods
\r
25338 // @method addHandler(name: String, HandlerClass: Function): this
\r
25339 // Adds a new `Handler` to the map, given its name and constructor function.
\r
25340 addHandler: function (name, HandlerClass) {
\r
25341 if (!HandlerClass) { return this; }
\r
25343 var handler = this[name] = new HandlerClass(this);
\r
25345 this._handlers.push(handler);
\r
25347 if (this.options[name]) {
\r
25348 handler.enable();
\r
25354 // @method remove(): this
\r
25355 // Destroys the map and clears all related event listeners.
\r
25356 remove: function () {
\r
25358 this._initEvents(true);
\r
25359 this.off('moveend', this._panInsideMaxBounds);
\r
25361 if (this._containerId !== this._container._leaflet_id) {
\r
25362 throw new Error('Map container is being reused by another instance');
\r
25366 // throws error in IE6-8
\r
25367 delete this._container._leaflet_id;
\r
25368 delete this._containerId;
\r
25370 /*eslint-disable */
\r
25371 this._container._leaflet_id = undefined;
\r
25372 /* eslint-enable */
\r
25373 this._containerId = undefined;
\r
25376 if (this._locationWatchId !== undefined) {
\r
25377 this.stopLocate();
\r
25382 remove(this._mapPane);
\r
25384 if (this._clearControlPos) {
\r
25385 this._clearControlPos();
\r
25387 if (this._resizeRequest) {
\r
25388 cancelAnimFrame(this._resizeRequest);
\r
25389 this._resizeRequest = null;
\r
25392 this._clearHandlers();
\r
25394 if (this._loaded) {
\r
25395 // @section Map state change events
\r
25396 // @event unload: Event
\r
25397 // Fired when the map is destroyed with [remove](#map-remove) method.
\r
25398 this.fire('unload');
\r
25402 for (i in this._layers) {
\r
25403 this._layers[i].remove();
\r
25405 for (i in this._panes) {
\r
25406 remove(this._panes[i]);
\r
25409 this._layers = [];
\r
25410 this._panes = [];
\r
25411 delete this._mapPane;
\r
25412 delete this._renderer;
\r
25417 // @section Other Methods
\r
25418 // @method createPane(name: String, container?: HTMLElement): HTMLElement
\r
25419 // Creates a new [map pane](#map-pane) with the given name if it doesn't exist already,
\r
25420 // then returns it. The pane is created as a child of `container`, or
\r
25421 // as a child of the main map pane if not set.
\r
25422 createPane: function (name, container) {
\r
25423 var className = 'leaflet-pane' + (name ? ' leaflet-' + name.replace('Pane', '') + '-pane' : ''),
\r
25424 pane = create$1('div', className, container || this._mapPane);
\r
25427 this._panes[name] = pane;
\r
25432 // @section Methods for Getting Map State
\r
25434 // @method getCenter(): LatLng
\r
25435 // Returns the geographical center of the map view
\r
25436 getCenter: function () {
\r
25437 this._checkIfLoaded();
\r
25439 if (this._lastCenter && !this._moved()) {
\r
25440 return this._lastCenter;
\r
25442 return this.layerPointToLatLng(this._getCenterLayerPoint());
\r
25445 // @method getZoom(): Number
\r
25446 // Returns the current zoom level of the map view
\r
25447 getZoom: function () {
\r
25448 return this._zoom;
\r
25451 // @method getBounds(): LatLngBounds
\r
25452 // Returns the geographical bounds visible in the current map view
\r
25453 getBounds: function () {
\r
25454 var bounds = this.getPixelBounds(),
\r
25455 sw = this.unproject(bounds.getBottomLeft()),
\r
25456 ne = this.unproject(bounds.getTopRight());
\r
25458 return new LatLngBounds(sw, ne);
\r
25461 // @method getMinZoom(): Number
\r
25462 // Returns the minimum zoom level of the map (if set in the `minZoom` option of the map or of any layers), or `0` by default.
\r
25463 getMinZoom: function () {
\r
25464 return this.options.minZoom === undefined ? this._layersMinZoom || 0 : this.options.minZoom;
\r
25467 // @method getMaxZoom(): Number
\r
25468 // Returns the maximum zoom level of the map (if set in the `maxZoom` option of the map or of any layers).
\r
25469 getMaxZoom: function () {
\r
25470 return this.options.maxZoom === undefined ?
\r
25471 (this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) :
\r
25472 this.options.maxZoom;
\r
25475 // @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number
\r
25476 // Returns the maximum zoom level on which the given bounds fit to the map
\r
25477 // view in its entirety. If `inside` (optional) is set to `true`, the method
\r
25478 // instead returns the minimum zoom level on which the map view fits into
\r
25479 // the given bounds in its entirety.
\r
25480 getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number
\r
25481 bounds = toLatLngBounds(bounds);
\r
25482 padding = toPoint(padding || [0, 0]);
\r
25484 var zoom = this.getZoom() || 0,
\r
25485 min = this.getMinZoom(),
\r
25486 max = this.getMaxZoom(),
\r
25487 nw = bounds.getNorthWest(),
\r
25488 se = bounds.getSouthEast(),
\r
25489 size = this.getSize().subtract(padding),
\r
25490 boundsSize = toBounds(this.project(se, zoom), this.project(nw, zoom)).getSize(),
\r
25491 snap = any3d ? this.options.zoomSnap : 1,
\r
25492 scalex = size.x / boundsSize.x,
\r
25493 scaley = size.y / boundsSize.y,
\r
25494 scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);
\r
25496 zoom = this.getScaleZoom(scale, zoom);
\r
25499 zoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level
\r
25500 zoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;
\r
25503 return Math.max(min, Math.min(max, zoom));
\r
25506 // @method getSize(): Point
\r
25507 // Returns the current size of the map container (in pixels).
\r
25508 getSize: function () {
\r
25509 if (!this._size || this._sizeChanged) {
\r
25510 this._size = new Point(
\r
25511 this._container.clientWidth || 0,
\r
25512 this._container.clientHeight || 0);
\r
25514 this._sizeChanged = false;
\r
25516 return this._size.clone();
\r
25519 // @method getPixelBounds(): Bounds
\r
25520 // Returns the bounds of the current map view in projected pixel
\r
25521 // coordinates (sometimes useful in layer and overlay implementations).
\r
25522 getPixelBounds: function (center, zoom) {
\r
25523 var topLeftPoint = this._getTopLeftPoint(center, zoom);
\r
25524 return new Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
\r
25527 // TODO: Check semantics - isn't the pixel origin the 0,0 coord relative to
\r
25528 // the map pane? "left point of the map layer" can be confusing, specially
\r
25529 // since there can be negative offsets.
\r
25530 // @method getPixelOrigin(): Point
\r
25531 // Returns the projected pixel coordinates of the top left point of
\r
25532 // the map layer (useful in custom layer and overlay implementations).
\r
25533 getPixelOrigin: function () {
\r
25534 this._checkIfLoaded();
\r
25535 return this._pixelOrigin;
\r
25538 // @method getPixelWorldBounds(zoom?: Number): Bounds
\r
25539 // Returns the world's bounds in pixel coordinates for zoom level `zoom`.
\r
25540 // If `zoom` is omitted, the map's current zoom level is used.
\r
25541 getPixelWorldBounds: function (zoom) {
\r
25542 return this.options.crs.getProjectedBounds(zoom === undefined ? this.getZoom() : zoom);
\r
25545 // @section Other Methods
\r
25547 // @method getPane(pane: String|HTMLElement): HTMLElement
\r
25548 // Returns a [map pane](#map-pane), given its name or its HTML element (its identity).
\r
25549 getPane: function (pane) {
\r
25550 return typeof pane === 'string' ? this._panes[pane] : pane;
\r
25553 // @method getPanes(): Object
\r
25554 // Returns a plain object containing the names of all [panes](#map-pane) as keys and
\r
25555 // the panes as values.
\r
25556 getPanes: function () {
\r
25557 return this._panes;
\r
25560 // @method getContainer: HTMLElement
\r
25561 // Returns the HTML element that contains the map.
\r
25562 getContainer: function () {
\r
25563 return this._container;
\r
25567 // @section Conversion Methods
\r
25569 // @method getZoomScale(toZoom: Number, fromZoom: Number): Number
\r
25570 // Returns the scale factor to be applied to a map transition from zoom level
\r
25571 // `fromZoom` to `toZoom`. Used internally to help with zoom animations.
\r
25572 getZoomScale: function (toZoom, fromZoom) {
\r
25573 // TODO replace with universal implementation after refactoring projections
\r
25574 var crs = this.options.crs;
\r
25575 fromZoom = fromZoom === undefined ? this._zoom : fromZoom;
\r
25576 return crs.scale(toZoom) / crs.scale(fromZoom);
\r
25579 // @method getScaleZoom(scale: Number, fromZoom: Number): Number
\r
25580 // Returns the zoom level that the map would end up at, if it is at `fromZoom`
\r
25581 // level and everything is scaled by a factor of `scale`. Inverse of
\r
25582 // [`getZoomScale`](#map-getZoomScale).
\r
25583 getScaleZoom: function (scale, fromZoom) {
\r
25584 var crs = this.options.crs;
\r
25585 fromZoom = fromZoom === undefined ? this._zoom : fromZoom;
\r
25586 var zoom = crs.zoom(scale * crs.scale(fromZoom));
\r
25587 return isNaN(zoom) ? Infinity : zoom;
\r
25590 // @method project(latlng: LatLng, zoom: Number): Point
\r
25591 // Projects a geographical coordinate `LatLng` according to the projection
\r
25592 // of the map's CRS, then scales it according to `zoom` and the CRS's
\r
25593 // `Transformation`. The result is pixel coordinate relative to
\r
25594 // the CRS origin.
\r
25595 project: function (latlng, zoom) {
\r
25596 zoom = zoom === undefined ? this._zoom : zoom;
\r
25597 return this.options.crs.latLngToPoint(toLatLng(latlng), zoom);
\r
25600 // @method unproject(point: Point, zoom: Number): LatLng
\r
25601 // Inverse of [`project`](#map-project).
\r
25602 unproject: function (point, zoom) {
\r
25603 zoom = zoom === undefined ? this._zoom : zoom;
\r
25604 return this.options.crs.pointToLatLng(toPoint(point), zoom);
\r
25607 // @method layerPointToLatLng(point: Point): LatLng
\r
25608 // Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
\r
25609 // returns the corresponding geographical coordinate (for the current zoom level).
\r
25610 layerPointToLatLng: function (point) {
\r
25611 var projectedPoint = toPoint(point).add(this.getPixelOrigin());
\r
25612 return this.unproject(projectedPoint);
\r
25615 // @method latLngToLayerPoint(latlng: LatLng): Point
\r
25616 // Given a geographical coordinate, returns the corresponding pixel coordinate
\r
25617 // relative to the [origin pixel](#map-getpixelorigin).
\r
25618 latLngToLayerPoint: function (latlng) {
\r
25619 var projectedPoint = this.project(toLatLng(latlng))._round();
\r
25620 return projectedPoint._subtract(this.getPixelOrigin());
\r
25623 // @method wrapLatLng(latlng: LatLng): LatLng
\r
25624 // Returns a `LatLng` where `lat` and `lng` has been wrapped according to the
\r
25625 // map's CRS's `wrapLat` and `wrapLng` properties, if they are outside the
\r
25627 // By default this means longitude is wrapped around the dateline so its
\r
25628 // value is between -180 and +180 degrees.
\r
25629 wrapLatLng: function (latlng) {
\r
25630 return this.options.crs.wrapLatLng(toLatLng(latlng));
\r
25633 // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
\r
25634 // Returns a `LatLngBounds` with the same size as the given one, ensuring that
\r
25635 // its center is within the CRS's bounds.
\r
25636 // By default this means the center longitude is wrapped around the dateline so its
\r
25637 // value is between -180 and +180 degrees, and the majority of the bounds
\r
25638 // overlaps the CRS's bounds.
\r
25639 wrapLatLngBounds: function (latlng) {
\r
25640 return this.options.crs.wrapLatLngBounds(toLatLngBounds(latlng));
\r
25643 // @method distance(latlng1: LatLng, latlng2: LatLng): Number
\r
25644 // Returns the distance between two geographical coordinates according to
\r
25645 // the map's CRS. By default this measures distance in meters.
\r
25646 distance: function (latlng1, latlng2) {
\r
25647 return this.options.crs.distance(toLatLng(latlng1), toLatLng(latlng2));
\r
25650 // @method containerPointToLayerPoint(point: Point): Point
\r
25651 // Given a pixel coordinate relative to the map container, returns the corresponding
\r
25652 // pixel coordinate relative to the [origin pixel](#map-getpixelorigin).
\r
25653 containerPointToLayerPoint: function (point) { // (Point)
\r
25654 return toPoint(point).subtract(this._getMapPanePos());
\r
25657 // @method layerPointToContainerPoint(point: Point): Point
\r
25658 // Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
\r
25659 // returns the corresponding pixel coordinate relative to the map container.
\r
25660 layerPointToContainerPoint: function (point) { // (Point)
\r
25661 return toPoint(point).add(this._getMapPanePos());
\r
25664 // @method containerPointToLatLng(point: Point): LatLng
\r
25665 // Given a pixel coordinate relative to the map container, returns
\r
25666 // the corresponding geographical coordinate (for the current zoom level).
\r
25667 containerPointToLatLng: function (point) {
\r
25668 var layerPoint = this.containerPointToLayerPoint(toPoint(point));
\r
25669 return this.layerPointToLatLng(layerPoint);
\r
25672 // @method latLngToContainerPoint(latlng: LatLng): Point
\r
25673 // Given a geographical coordinate, returns the corresponding pixel coordinate
\r
25674 // relative to the map container.
\r
25675 latLngToContainerPoint: function (latlng) {
\r
25676 return this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng)));
\r
25679 // @method mouseEventToContainerPoint(ev: MouseEvent): Point
\r
25680 // Given a MouseEvent object, returns the pixel coordinate relative to the
\r
25681 // map container where the event took place.
\r
25682 mouseEventToContainerPoint: function (e) {
\r
25683 return getMousePosition(e, this._container);
\r
25686 // @method mouseEventToLayerPoint(ev: MouseEvent): Point
\r
25687 // Given a MouseEvent object, returns the pixel coordinate relative to
\r
25688 // the [origin pixel](#map-getpixelorigin) where the event took place.
\r
25689 mouseEventToLayerPoint: function (e) {
\r
25690 return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));
\r
25693 // @method mouseEventToLatLng(ev: MouseEvent): LatLng
\r
25694 // Given a MouseEvent object, returns geographical coordinate where the
\r
25695 // event took place.
\r
25696 mouseEventToLatLng: function (e) { // (MouseEvent)
\r
25697 return this.layerPointToLatLng(this.mouseEventToLayerPoint(e));
\r
25701 // map initialization methods
\r
25703 _initContainer: function (id) {
\r
25704 var container = this._container = get(id);
\r
25706 if (!container) {
\r
25707 throw new Error('Map container not found.');
\r
25708 } else if (container._leaflet_id) {
\r
25709 throw new Error('Map container is already initialized.');
\r
25712 on(container, 'scroll', this._onScroll, this);
\r
25713 this._containerId = stamp(container);
\r
25716 _initLayout: function () {
\r
25717 var container = this._container;
\r
25719 this._fadeAnimated = this.options.fadeAnimation && any3d;
\r
25721 addClass(container, 'leaflet-container' +
\r
25722 (touch ? ' leaflet-touch' : '') +
\r
25723 (retina ? ' leaflet-retina' : '') +
\r
25724 (ielt9 ? ' leaflet-oldie' : '') +
\r
25725 (safari ? ' leaflet-safari' : '') +
\r
25726 (this._fadeAnimated ? ' leaflet-fade-anim' : ''));
\r
25728 var position = getStyle(container, 'position');
\r
25730 if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') {
\r
25731 container.style.position = 'relative';
\r
25734 this._initPanes();
\r
25736 if (this._initControlPos) {
\r
25737 this._initControlPos();
\r
25741 _initPanes: function () {
\r
25742 var panes = this._panes = {};
\r
25743 this._paneRenderers = {};
\r
25747 // Panes are DOM elements used to control the ordering of layers on the map. You
\r
25748 // can access panes with [`map.getPane`](#map-getpane) or
\r
25749 // [`map.getPanes`](#map-getpanes) methods. New panes can be created with the
\r
25750 // [`map.createPane`](#map-createpane) method.
\r
25752 // Every map has the following default panes that differ only in zIndex.
\r
25754 // @pane mapPane: HTMLElement = 'auto'
\r
25755 // Pane that contains all other map panes
\r
25757 this._mapPane = this.createPane('mapPane', this._container);
\r
25758 setPosition(this._mapPane, new Point(0, 0));
\r
25760 // @pane tilePane: HTMLElement = 200
\r
25761 // Pane for `GridLayer`s and `TileLayer`s
\r
25762 this.createPane('tilePane');
\r
25763 // @pane overlayPane: HTMLElement = 400
\r
25764 // Pane for overlay shadows (e.g. `Marker` shadows)
\r
25765 this.createPane('shadowPane');
\r
25766 // @pane shadowPane: HTMLElement = 500
\r
25767 // Pane for vectors (`Path`s, like `Polyline`s and `Polygon`s), `ImageOverlay`s and `VideoOverlay`s
\r
25768 this.createPane('overlayPane');
\r
25769 // @pane markerPane: HTMLElement = 600
\r
25770 // Pane for `Icon`s of `Marker`s
\r
25771 this.createPane('markerPane');
\r
25772 // @pane tooltipPane: HTMLElement = 650
\r
25773 // Pane for `Tooltip`s.
\r
25774 this.createPane('tooltipPane');
\r
25775 // @pane popupPane: HTMLElement = 700
\r
25776 // Pane for `Popup`s.
\r
25777 this.createPane('popupPane');
\r
25779 if (!this.options.markerZoomAnimation) {
\r
25780 addClass(panes.markerPane, 'leaflet-zoom-hide');
\r
25781 addClass(panes.shadowPane, 'leaflet-zoom-hide');
\r
25786 // private methods that modify map state
\r
25788 // @section Map state change events
\r
25789 _resetView: function (center, zoom) {
\r
25790 setPosition(this._mapPane, new Point(0, 0));
\r
25792 var loading = !this._loaded;
\r
25793 this._loaded = true;
\r
25794 zoom = this._limitZoom(zoom);
\r
25796 this.fire('viewprereset');
\r
25798 var zoomChanged = this._zoom !== zoom;
\r
25800 ._moveStart(zoomChanged, false)
\r
25801 ._move(center, zoom)
\r
25802 ._moveEnd(zoomChanged);
\r
25804 // @event viewreset: Event
\r
25805 // Fired when the map needs to redraw its content (this usually happens
\r
25806 // on map zoom or load). Very useful for creating custom overlays.
\r
25807 this.fire('viewreset');
\r
25809 // @event load: Event
\r
25810 // Fired when the map is initialized (when its center and zoom are set
\r
25811 // for the first time).
\r
25813 this.fire('load');
\r
25817 _moveStart: function (zoomChanged, noMoveStart) {
\r
25818 // @event zoomstart: Event
\r
25819 // Fired when the map zoom is about to change (e.g. before zoom animation).
\r
25820 // @event movestart: Event
\r
25821 // Fired when the view of the map starts changing (e.g. user starts dragging the map).
\r
25822 if (zoomChanged) {
\r
25823 this.fire('zoomstart');
\r
25825 if (!noMoveStart) {
\r
25826 this.fire('movestart');
\r
25831 _move: function (center, zoom, data) {
\r
25832 if (zoom === undefined) {
\r
25833 zoom = this._zoom;
\r
25835 var zoomChanged = this._zoom !== zoom;
\r
25837 this._zoom = zoom;
\r
25838 this._lastCenter = center;
\r
25839 this._pixelOrigin = this._getNewPixelOrigin(center);
\r
25841 // @event zoom: Event
\r
25842 // Fired repeatedly during any change in zoom level, including zoom
\r
25843 // and fly animations.
\r
25844 if (zoomChanged || (data && data.pinch)) { // Always fire 'zoom' if pinching because #3530
\r
25845 this.fire('zoom', data);
\r
25848 // @event move: Event
\r
25849 // Fired repeatedly during any movement of the map, including pan and
\r
25850 // fly animations.
\r
25851 return this.fire('move', data);
\r
25854 _moveEnd: function (zoomChanged) {
\r
25855 // @event zoomend: Event
\r
25856 // Fired when the map has changed, after any animations.
\r
25857 if (zoomChanged) {
\r
25858 this.fire('zoomend');
\r
25861 // @event moveend: Event
\r
25862 // Fired when the center of the map stops changing (e.g. user stopped
\r
25863 // dragging the map).
\r
25864 return this.fire('moveend');
\r
25867 _stop: function () {
\r
25868 cancelAnimFrame(this._flyToFrame);
\r
25869 if (this._panAnim) {
\r
25870 this._panAnim.stop();
\r
25875 _rawPanBy: function (offset) {
\r
25876 setPosition(this._mapPane, this._getMapPanePos().subtract(offset));
\r
25879 _getZoomSpan: function () {
\r
25880 return this.getMaxZoom() - this.getMinZoom();
\r
25883 _panInsideMaxBounds: function () {
\r
25884 if (!this._enforcingBounds) {
\r
25885 this.panInsideBounds(this.options.maxBounds);
\r
25889 _checkIfLoaded: function () {
\r
25890 if (!this._loaded) {
\r
25891 throw new Error('Set map center and zoom first.');
\r
25895 // DOM event handling
\r
25897 // @section Interaction events
\r
25898 _initEvents: function (remove$$1) {
\r
25899 this._targets = {};
\r
25900 this._targets[stamp(this._container)] = this;
\r
25902 var onOff = remove$$1 ? off : on;
\r
25904 // @event click: MouseEvent
\r
25905 // Fired when the user clicks (or taps) the map.
\r
25906 // @event dblclick: MouseEvent
\r
25907 // Fired when the user double-clicks (or double-taps) the map.
\r
25908 // @event mousedown: MouseEvent
\r
25909 // Fired when the user pushes the mouse button on the map.
\r
25910 // @event mouseup: MouseEvent
\r
25911 // Fired when the user releases the mouse button on the map.
\r
25912 // @event mouseover: MouseEvent
\r
25913 // Fired when the mouse enters the map.
\r
25914 // @event mouseout: MouseEvent
\r
25915 // Fired when the mouse leaves the map.
\r
25916 // @event mousemove: MouseEvent
\r
25917 // Fired while the mouse moves over the map.
\r
25918 // @event contextmenu: MouseEvent
\r
25919 // Fired when the user pushes the right mouse button on the map, prevents
\r
25920 // default browser context menu from showing if there are listeners on
\r
25921 // this event. Also fired on mobile when the user holds a single touch
\r
25922 // for a second (also called long press).
\r
25923 // @event keypress: KeyboardEvent
\r
25924 // Fired when the user presses a key from the keyboard that produces a character value while the map is focused.
\r
25925 // @event keydown: KeyboardEvent
\r
25926 // Fired when the user presses a key from the keyboard while the map is focused. Unlike the `keypress` event,
\r
25927 // the `keydown` event is fired for keys that produce a character value and for keys
\r
25928 // that do not produce a character value.
\r
25929 // @event keyup: KeyboardEvent
\r
25930 // Fired when the user releases a key from the keyboard while the map is focused.
\r
25931 onOff(this._container, 'click dblclick mousedown mouseup ' +
\r
25932 'mouseover mouseout mousemove contextmenu keypress keydown keyup', this._handleDOMEvent, this);
\r
25934 if (this.options.trackResize) {
\r
25935 onOff(window, 'resize', this._onResize, this);
\r
25938 if (any3d && this.options.transform3DLimit) {
\r
25939 (remove$$1 ? this.off : this.on).call(this, 'moveend', this._onMoveEnd);
\r
25943 _onResize: function () {
\r
25944 cancelAnimFrame(this._resizeRequest);
\r
25945 this._resizeRequest = requestAnimFrame(
\r
25946 function () { this.invalidateSize({debounceMoveend: true}); }, this);
\r
25949 _onScroll: function () {
\r
25950 this._container.scrollTop = 0;
\r
25951 this._container.scrollLeft = 0;
\r
25954 _onMoveEnd: function () {
\r
25955 var pos = this._getMapPanePos();
\r
25956 if (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) {
\r
25957 // https://bugzilla.mozilla.org/show_bug.cgi?id=1203873 but Webkit also have
\r
25958 // a pixel offset on very high values, see: http://jsfiddle.net/dg6r5hhb/
\r
25959 this._resetView(this.getCenter(), this.getZoom());
\r
25963 _findEventTargets: function (e, type) {
\r
25964 var targets = [],
\r
25966 isHover = type === 'mouseout' || type === 'mouseover',
\r
25967 src = e.target || e.srcElement,
\r
25968 dragging = false;
\r
25971 target = this._targets[stamp(src)];
\r
25972 if (target && (type === 'click' || type === 'preclick') && !e._simulated && this._draggableMoved(target)) {
\r
25973 // Prevent firing click after you just dragged an object.
\r
25977 if (target && target.listens(type, true)) {
\r
25978 if (isHover && !isExternalTarget(src, e)) { break; }
\r
25979 targets.push(target);
\r
25980 if (isHover) { break; }
\r
25982 if (src === this._container) { break; }
\r
25983 src = src.parentNode;
\r
25985 if (!targets.length && !dragging && !isHover && isExternalTarget(src, e)) {
\r
25986 targets = [this];
\r
25991 _handleDOMEvent: function (e) {
\r
25992 if (!this._loaded || skipped(e)) { return; }
\r
25994 var type = e.type;
\r
25996 if (type === 'mousedown' || type === 'keypress' || type === 'keyup' || type === 'keydown') {
\r
25997 // prevents outline when clicking on keyboard-focusable element
\r
25998 preventOutline(e.target || e.srcElement);
\r
26001 this._fireDOMEvent(e, type);
\r
26004 _mouseEvents: ['click', 'dblclick', 'mouseover', 'mouseout', 'contextmenu'],
\r
26006 _fireDOMEvent: function (e, type, targets) {
\r
26008 if (e.type === 'click') {
\r
26009 // Fire a synthetic 'preclick' event which propagates up (mainly for closing popups).
\r
26010 // @event preclick: MouseEvent
\r
26011 // Fired before mouse click on the map (sometimes useful when you
\r
26012 // want something to happen on click before any existing click
\r
26013 // handlers start running).
\r
26014 var synth = extend({}, e);
\r
26015 synth.type = 'preclick';
\r
26016 this._fireDOMEvent(synth, synth.type, targets);
\r
26019 if (e._stopped) { return; }
\r
26021 // Find the layer the event is propagating from and its parents.
\r
26022 targets = (targets || []).concat(this._findEventTargets(e, type));
\r
26024 if (!targets.length) { return; }
\r
26026 var target = targets[0];
\r
26027 if (type === 'contextmenu' && target.listens(type, true)) {
\r
26028 preventDefault(e);
\r
26035 if (e.type !== 'keypress' && e.type !== 'keydown' && e.type !== 'keyup') {
\r
26036 var isMarker = target.getLatLng && (!target._radius || target._radius <= 10);
\r
26037 data.containerPoint = isMarker ?
\r
26038 this.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);
\r
26039 data.layerPoint = this.containerPointToLayerPoint(data.containerPoint);
\r
26040 data.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint);
\r
26043 for (var i = 0; i < targets.length; i++) {
\r
26044 targets[i].fire(type, data, true);
\r
26045 if (data.originalEvent._stopped ||
\r
26046 (targets[i].options.bubblingMouseEvents === false && indexOf(this._mouseEvents, type) !== -1)) { return; }
\r
26050 _draggableMoved: function (obj) {
\r
26051 obj = obj.dragging && obj.dragging.enabled() ? obj : this;
\r
26052 return (obj.dragging && obj.dragging.moved()) || (this.boxZoom && this.boxZoom.moved());
\r
26055 _clearHandlers: function () {
\r
26056 for (var i = 0, len = this._handlers.length; i < len; i++) {
\r
26057 this._handlers[i].disable();
\r
26061 // @section Other Methods
\r
26063 // @method whenReady(fn: Function, context?: Object): this
\r
26064 // Runs the given function `fn` when the map gets initialized with
\r
26065 // a view (center and zoom) and at least one layer, or immediately
\r
26066 // if it's already initialized, optionally passing a function context.
\r
26067 whenReady: function (callback, context) {
\r
26068 if (this._loaded) {
\r
26069 callback.call(context || this, {target: this});
\r
26071 this.on('load', callback, context);
\r
26077 // private methods for getting map state
\r
26079 _getMapPanePos: function () {
\r
26080 return getPosition(this._mapPane) || new Point(0, 0);
\r
26083 _moved: function () {
\r
26084 var pos = this._getMapPanePos();
\r
26085 return pos && !pos.equals([0, 0]);
\r
26088 _getTopLeftPoint: function (center, zoom) {
\r
26089 var pixelOrigin = center && zoom !== undefined ?
\r
26090 this._getNewPixelOrigin(center, zoom) :
\r
26091 this.getPixelOrigin();
\r
26092 return pixelOrigin.subtract(this._getMapPanePos());
\r
26095 _getNewPixelOrigin: function (center, zoom) {
\r
26096 var viewHalf = this.getSize()._divideBy(2);
\r
26097 return this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round();
\r
26100 _latLngToNewLayerPoint: function (latlng, zoom, center) {
\r
26101 var topLeft = this._getNewPixelOrigin(center, zoom);
\r
26102 return this.project(latlng, zoom)._subtract(topLeft);
\r
26105 _latLngBoundsToNewLayerBounds: function (latLngBounds, zoom, center) {
\r
26106 var topLeft = this._getNewPixelOrigin(center, zoom);
\r
26107 return toBounds([
\r
26108 this.project(latLngBounds.getSouthWest(), zoom)._subtract(topLeft),
\r
26109 this.project(latLngBounds.getNorthWest(), zoom)._subtract(topLeft),
\r
26110 this.project(latLngBounds.getSouthEast(), zoom)._subtract(topLeft),
\r
26111 this.project(latLngBounds.getNorthEast(), zoom)._subtract(topLeft)
\r
26115 // layer point of the current center
\r
26116 _getCenterLayerPoint: function () {
\r
26117 return this.containerPointToLayerPoint(this.getSize()._divideBy(2));
\r
26120 // offset of the specified place to the current center in pixels
\r
26121 _getCenterOffset: function (latlng) {
\r
26122 return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint());
\r
26125 // adjust center for view to get inside bounds
\r
26126 _limitCenter: function (center, zoom, bounds) {
\r
26128 if (!bounds) { return center; }
\r
26130 var centerPoint = this.project(center, zoom),
\r
26131 viewHalf = this.getSize().divideBy(2),
\r
26132 viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),
\r
26133 offset = this._getBoundsOffset(viewBounds, bounds, zoom);
\r
26135 // If offset is less than a pixel, ignore.
\r
26136 // This prevents unstable projections from getting into
\r
26137 // an infinite loop of tiny offsets.
\r
26138 if (offset.round().equals([0, 0])) {
\r
26142 return this.unproject(centerPoint.add(offset), zoom);
\r
26145 // adjust offset for view to get inside bounds
\r
26146 _limitOffset: function (offset, bounds) {
\r
26147 if (!bounds) { return offset; }
\r
26149 var viewBounds = this.getPixelBounds(),
\r
26150 newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset));
\r
26152 return offset.add(this._getBoundsOffset(newBounds, bounds));
\r
26155 // returns offset needed for pxBounds to get inside maxBounds at a specified zoom
\r
26156 _getBoundsOffset: function (pxBounds, maxBounds, zoom) {
\r
26157 var projectedMaxBounds = toBounds(
\r
26158 this.project(maxBounds.getNorthEast(), zoom),
\r
26159 this.project(maxBounds.getSouthWest(), zoom)
\r
26161 minOffset = projectedMaxBounds.min.subtract(pxBounds.min),
\r
26162 maxOffset = projectedMaxBounds.max.subtract(pxBounds.max),
\r
26164 dx = this._rebound(minOffset.x, -maxOffset.x),
\r
26165 dy = this._rebound(minOffset.y, -maxOffset.y);
\r
26167 return new Point(dx, dy);
\r
26170 _rebound: function (left, right) {
\r
26171 return left + right > 0 ?
\r
26172 Math.round(left - right) / 2 :
\r
26173 Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right));
\r
26176 _limitZoom: function (zoom) {
\r
26177 var min = this.getMinZoom(),
\r
26178 max = this.getMaxZoom(),
\r
26179 snap = any3d ? this.options.zoomSnap : 1;
\r
26181 zoom = Math.round(zoom / snap) * snap;
\r
26183 return Math.max(min, Math.min(max, zoom));
\r
26186 _onPanTransitionStep: function () {
\r
26187 this.fire('move');
\r
26190 _onPanTransitionEnd: function () {
\r
26191 removeClass(this._mapPane, 'leaflet-pan-anim');
\r
26192 this.fire('moveend');
\r
26195 _tryAnimatedPan: function (center, options) {
\r
26196 // difference between the new and current centers in pixels
\r
26197 var offset = this._getCenterOffset(center)._trunc();
\r
26199 // don't animate too far unless animate: true specified in options
\r
26200 if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }
\r
26202 this.panBy(offset, options);
\r
26207 _createAnimProxy: function () {
\r
26209 var proxy = this._proxy = create$1('div', 'leaflet-proxy leaflet-zoom-animated');
\r
26210 this._panes.mapPane.appendChild(proxy);
\r
26212 this.on('zoomanim', function (e) {
\r
26213 var prop = TRANSFORM,
\r
26214 transform = this._proxy.style[prop];
\r
26216 setTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));
\r
26218 // workaround for case when transform is the same and so transitionend event is not fired
\r
26219 if (transform === this._proxy.style[prop] && this._animatingZoom) {
\r
26220 this._onZoomTransitionEnd();
\r
26224 this.on('load moveend', this._animMoveEnd, this);
\r
26226 this._on('unload', this._destroyAnimProxy, this);
\r
26229 _destroyAnimProxy: function () {
\r
26230 remove(this._proxy);
\r
26231 this.off('load moveend', this._animMoveEnd, this);
\r
26232 delete this._proxy;
\r
26235 _animMoveEnd: function () {
\r
26236 var c = this.getCenter(),
\r
26237 z = this.getZoom();
\r
26238 setTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1));
\r
26241 _catchTransitionEnd: function (e) {
\r
26242 if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) {
\r
26243 this._onZoomTransitionEnd();
\r
26247 _nothingToAnimate: function () {
\r
26248 return !this._container.getElementsByClassName('leaflet-zoom-animated').length;
\r
26251 _tryAnimatedZoom: function (center, zoom, options) {
\r
26253 if (this._animatingZoom) { return true; }
\r
26255 options = options || {};
\r
26257 // don't animate if disabled, not supported or zoom difference is too large
\r
26258 if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() ||
\r
26259 Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; }
\r
26261 // offset is the pixel coords of the zoom origin relative to the current center
\r
26262 var scale = this.getZoomScale(zoom),
\r
26263 offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale);
\r
26265 // don't animate if the zoom origin isn't within one screen from the current center, unless forced
\r
26266 if (options.animate !== true && !this.getSize().contains(offset)) { return false; }
\r
26268 requestAnimFrame(function () {
\r
26270 ._moveStart(true, false)
\r
26271 ._animateZoom(center, zoom, true);
\r
26277 _animateZoom: function (center, zoom, startAnim, noUpdate) {
\r
26278 if (!this._mapPane) { return; }
\r
26281 this._animatingZoom = true;
\r
26283 // remember what center/zoom to set after animation
\r
26284 this._animateToCenter = center;
\r
26285 this._animateToZoom = zoom;
\r
26287 addClass(this._mapPane, 'leaflet-zoom-anim');
\r
26290 // @section Other Events
\r
26291 // @event zoomanim: ZoomAnimEvent
\r
26292 // Fired at least once per zoom animation. For continuous zoom, like pinch zooming, fired once per frame during zoom.
\r
26293 this.fire('zoomanim', {
\r
26296 noUpdate: noUpdate
\r
26299 // Work around webkit not firing 'transitionend', see https://github.com/Leaflet/Leaflet/issues/3689, 2693
\r
26300 setTimeout(bind(this._onZoomTransitionEnd, this), 250);
\r
26303 _onZoomTransitionEnd: function () {
\r
26304 if (!this._animatingZoom) { return; }
\r
26306 if (this._mapPane) {
\r
26307 removeClass(this._mapPane, 'leaflet-zoom-anim');
\r
26310 this._animatingZoom = false;
\r
26312 this._move(this._animateToCenter, this._animateToZoom);
\r
26314 // This anim frame should prevent an obscure iOS webkit tile loading race condition.
\r
26315 requestAnimFrame(function () {
\r
26316 this._moveEnd(true);
\r
26323 // @factory L.map(id: String, options?: Map options)
\r
26324 // Instantiates a map object given the DOM ID of a `<div>` element
\r
26325 // and optionally an object literal with `Map options`.
\r
26328 // @factory L.map(el: HTMLElement, options?: Map options)
\r
26329 // Instantiates a map object given an instance of a `<div>` HTML element
\r
26330 // and optionally an object literal with `Map options`.
\r
26331 function createMap(id, options) {
\r
26332 return new Map(id, options);
\r
26338 * @inherits Class
\r
26340 * L.Control is a base class for implementing map controls. Handles positioning.
\r
26341 * All other controls extend from this class.
\r
26344 var Control = Class.extend({
\r
26346 // @aka Control options
\r
26348 // @option position: String = 'topright'
\r
26349 // The position of the control (one of the map corners). Possible values are `'topleft'`,
\r
26350 // `'topright'`, `'bottomleft'` or `'bottomright'`
\r
26351 position: 'topright'
\r
26354 initialize: function (options) {
\r
26355 setOptions(this, options);
\r
26359 * Classes extending L.Control will inherit the following methods:
\r
26361 * @method getPosition: string
\r
26362 * Returns the position of the control.
\r
26364 getPosition: function () {
\r
26365 return this.options.position;
\r
26368 // @method setPosition(position: string): this
\r
26369 // Sets the position of the control.
\r
26370 setPosition: function (position) {
\r
26371 var map = this._map;
\r
26374 map.removeControl(this);
\r
26377 this.options.position = position;
\r
26380 map.addControl(this);
\r
26386 // @method getContainer: HTMLElement
\r
26387 // Returns the HTMLElement that contains the control.
\r
26388 getContainer: function () {
\r
26389 return this._container;
\r
26392 // @method addTo(map: Map): this
\r
26393 // Adds the control to the given map.
\r
26394 addTo: function (map) {
\r
26398 var container = this._container = this.onAdd(map),
\r
26399 pos = this.getPosition(),
\r
26400 corner = map._controlCorners[pos];
\r
26402 addClass(container, 'leaflet-control');
\r
26404 if (pos.indexOf('bottom') !== -1) {
\r
26405 corner.insertBefore(container, corner.firstChild);
\r
26407 corner.appendChild(container);
\r
26410 this._map.on('unload', this.remove, this);
\r
26415 // @method remove: this
\r
26416 // Removes the control from the map it is currently active on.
\r
26417 remove: function () {
\r
26418 if (!this._map) {
\r
26422 remove(this._container);
\r
26424 if (this.onRemove) {
\r
26425 this.onRemove(this._map);
\r
26428 this._map.off('unload', this.remove, this);
\r
26429 this._map = null;
\r
26434 _refocusOnMap: function (e) {
\r
26435 // if map exists and event is not a keyboard event
\r
26436 if (this._map && e && e.screenX > 0 && e.screenY > 0) {
\r
26437 this._map.getContainer().focus();
\r
26442 var control = function (options) {
\r
26443 return new Control(options);
\r
26446 /* @section Extension methods
\r
26449 * Every control should extend from `L.Control` and (re-)implement the following methods.
\r
26451 * @method onAdd(map: Map): HTMLElement
\r
26452 * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo).
\r
26454 * @method onRemove(map: Map)
\r
26455 * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove).
\r
26458 /* @namespace Map
\r
26459 * @section Methods for Layers and Controls
\r
26462 // @method addControl(control: Control): this
\r
26463 // Adds the given control to the map
\r
26464 addControl: function (control) {
\r
26465 control.addTo(this);
\r
26469 // @method removeControl(control: Control): this
\r
26470 // Removes the given control from the map
\r
26471 removeControl: function (control) {
\r
26472 control.remove();
\r
26476 _initControlPos: function () {
\r
26477 var corners = this._controlCorners = {},
\r
26479 container = this._controlContainer =
\r
26480 create$1('div', l + 'control-container', this._container);
\r
26482 function createCorner(vSide, hSide) {
\r
26483 var className = l + vSide + ' ' + l + hSide;
\r
26485 corners[vSide + hSide] = create$1('div', className, container);
\r
26488 createCorner('top', 'left');
\r
26489 createCorner('top', 'right');
\r
26490 createCorner('bottom', 'left');
\r
26491 createCorner('bottom', 'right');
\r
26494 _clearControlPos: function () {
\r
26495 for (var i in this._controlCorners) {
\r
26496 remove(this._controlCorners[i]);
\r
26498 remove(this._controlContainer);
\r
26499 delete this._controlCorners;
\r
26500 delete this._controlContainer;
\r
26505 * @class Control.Layers
\r
26506 * @aka L.Control.Layers
\r
26507 * @inherits Control
\r
26509 * The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the [detailed example](http://leafletjs.com/examples/layers-control/)). Extends `Control`.
\r
26514 * var baseLayers = {
\r
26515 * "Mapbox": mapbox,
\r
26516 * "OpenStreetMap": osm
\r
26519 * var overlays = {
\r
26520 * "Marker": marker,
\r
26521 * "Roads": roadsLayer
\r
26524 * L.control.layers(baseLayers, overlays).addTo(map);
\r
26527 * The `baseLayers` and `overlays` parameters are object literals with layer names as keys and `Layer` objects as values:
\r
26531 * "<someName1>": layer1,
\r
26532 * "<someName2>": layer2
\r
26536 * The layer names can contain HTML, which allows you to add additional styling to the items:
\r
26539 * {"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>": myLayer}
\r
26543 var Layers = Control.extend({
\r
26545 // @aka Control.Layers options
\r
26547 // @option collapsed: Boolean = true
\r
26548 // If `true`, the control will be collapsed into an icon and expanded on mouse hover or touch.
\r
26550 position: 'topright',
\r
26552 // @option autoZIndex: Boolean = true
\r
26553 // If `true`, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.
\r
26554 autoZIndex: true,
\r
26556 // @option hideSingleBase: Boolean = false
\r
26557 // If `true`, the base layers in the control will be hidden when there is only one.
\r
26558 hideSingleBase: false,
\r
26560 // @option sortLayers: Boolean = false
\r
26561 // Whether to sort the layers. When `false`, layers will keep the order
\r
26562 // in which they were added to the control.
\r
26563 sortLayers: false,
\r
26565 // @option sortFunction: Function = *
\r
26566 // A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
\r
26567 // that will be used for sorting the layers, when `sortLayers` is `true`.
\r
26568 // The function receives both the `L.Layer` instances and their names, as in
\r
26569 // `sortFunction(layerA, layerB, nameA, nameB)`.
\r
26570 // By default, it sorts layers alphabetically by their name.
\r
26571 sortFunction: function (layerA, layerB, nameA, nameB) {
\r
26572 return nameA < nameB ? -1 : (nameB < nameA ? 1 : 0);
\r
26576 initialize: function (baseLayers, overlays, options) {
\r
26577 setOptions(this, options);
\r
26579 this._layerControlInputs = [];
\r
26580 this._layers = [];
\r
26581 this._lastZIndex = 0;
\r
26582 this._handlingClick = false;
\r
26584 for (var i in baseLayers) {
\r
26585 this._addLayer(baseLayers[i], i);
\r
26588 for (i in overlays) {
\r
26589 this._addLayer(overlays[i], i, true);
\r
26593 onAdd: function (map) {
\r
26594 this._initLayout();
\r
26598 map.on('zoomend', this._checkDisabledLayers, this);
\r
26600 for (var i = 0; i < this._layers.length; i++) {
\r
26601 this._layers[i].layer.on('add remove', this._onLayerChange, this);
\r
26604 return this._container;
\r
26607 addTo: function (map) {
\r
26608 Control.prototype.addTo.call(this, map);
\r
26609 // Trigger expand after Layers Control has been inserted into DOM so that is now has an actual height.
\r
26610 return this._expandIfNotCollapsed();
\r
26613 onRemove: function () {
\r
26614 this._map.off('zoomend', this._checkDisabledLayers, this);
\r
26616 for (var i = 0; i < this._layers.length; i++) {
\r
26617 this._layers[i].layer.off('add remove', this._onLayerChange, this);
\r
26621 // @method addBaseLayer(layer: Layer, name: String): this
\r
26622 // Adds a base layer (radio button entry) with the given name to the control.
\r
26623 addBaseLayer: function (layer, name) {
\r
26624 this._addLayer(layer, name);
\r
26625 return (this._map) ? this._update() : this;
\r
26628 // @method addOverlay(layer: Layer, name: String): this
\r
26629 // Adds an overlay (checkbox entry) with the given name to the control.
\r
26630 addOverlay: function (layer, name) {
\r
26631 this._addLayer(layer, name, true);
\r
26632 return (this._map) ? this._update() : this;
\r
26635 // @method removeLayer(layer: Layer): this
\r
26636 // Remove the given layer from the control.
\r
26637 removeLayer: function (layer) {
\r
26638 layer.off('add remove', this._onLayerChange, this);
\r
26640 var obj = this._getLayer(stamp(layer));
\r
26642 this._layers.splice(this._layers.indexOf(obj), 1);
\r
26644 return (this._map) ? this._update() : this;
\r
26647 // @method expand(): this
\r
26648 // Expand the control container if collapsed.
\r
26649 expand: function () {
\r
26650 addClass(this._container, 'leaflet-control-layers-expanded');
\r
26651 this._section.style.height = null;
\r
26652 var acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);
\r
26653 if (acceptableHeight < this._section.clientHeight) {
\r
26654 addClass(this._section, 'leaflet-control-layers-scrollbar');
\r
26655 this._section.style.height = acceptableHeight + 'px';
\r
26657 removeClass(this._section, 'leaflet-control-layers-scrollbar');
\r
26659 this._checkDisabledLayers();
\r
26663 // @method collapse(): this
\r
26664 // Collapse the control container if expanded.
\r
26665 collapse: function () {
\r
26666 removeClass(this._container, 'leaflet-control-layers-expanded');
\r
26670 _initLayout: function () {
\r
26671 var className = 'leaflet-control-layers',
\r
26672 container = this._container = create$1('div', className),
\r
26673 collapsed = this.options.collapsed;
\r
26675 // makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released
\r
26676 container.setAttribute('aria-haspopup', true);
\r
26678 disableClickPropagation(container);
\r
26679 disableScrollPropagation(container);
\r
26681 var section = this._section = create$1('section', className + '-list');
\r
26684 this._map.on('click', this.collapse, this);
\r
26688 mouseenter: this.expand,
\r
26689 mouseleave: this.collapse
\r
26694 var link = this._layersLink = create$1('a', className + '-toggle', container);
\r
26696 link.title = 'Layers';
\r
26699 on(link, 'click', stop);
\r
26700 on(link, 'click', this.expand, this);
\r
26702 on(link, 'focus', this.expand, this);
\r
26705 if (!collapsed) {
\r
26709 this._baseLayersList = create$1('div', className + '-base', section);
\r
26710 this._separator = create$1('div', className + '-separator', section);
\r
26711 this._overlaysList = create$1('div', className + '-overlays', section);
\r
26713 container.appendChild(section);
\r
26716 _getLayer: function (id) {
\r
26717 for (var i = 0; i < this._layers.length; i++) {
\r
26719 if (this._layers[i] && stamp(this._layers[i].layer) === id) {
\r
26720 return this._layers[i];
\r
26725 _addLayer: function (layer, name, overlay) {
\r
26727 layer.on('add remove', this._onLayerChange, this);
\r
26730 this._layers.push({
\r
26736 if (this.options.sortLayers) {
\r
26737 this._layers.sort(bind(function (a, b) {
\r
26738 return this.options.sortFunction(a.layer, b.layer, a.name, b.name);
\r
26742 if (this.options.autoZIndex && layer.setZIndex) {
\r
26743 this._lastZIndex++;
\r
26744 layer.setZIndex(this._lastZIndex);
\r
26747 this._expandIfNotCollapsed();
\r
26750 _update: function () {
\r
26751 if (!this._container) { return this; }
\r
26753 empty(this._baseLayersList);
\r
26754 empty(this._overlaysList);
\r
26756 this._layerControlInputs = [];
\r
26757 var baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0;
\r
26759 for (i = 0; i < this._layers.length; i++) {
\r
26760 obj = this._layers[i];
\r
26761 this._addItem(obj);
\r
26762 overlaysPresent = overlaysPresent || obj.overlay;
\r
26763 baseLayersPresent = baseLayersPresent || !obj.overlay;
\r
26764 baseLayersCount += !obj.overlay ? 1 : 0;
\r
26767 // Hide base layers section if there's only one layer.
\r
26768 if (this.options.hideSingleBase) {
\r
26769 baseLayersPresent = baseLayersPresent && baseLayersCount > 1;
\r
26770 this._baseLayersList.style.display = baseLayersPresent ? '' : 'none';
\r
26773 this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none';
\r
26778 _onLayerChange: function (e) {
\r
26779 if (!this._handlingClick) {
\r
26783 var obj = this._getLayer(stamp(e.target));
\r
26785 // @namespace Map
\r
26786 // @section Layer events
\r
26787 // @event baselayerchange: LayersControlEvent
\r
26788 // Fired when the base layer is changed through the [layers control](#control-layers).
\r
26789 // @event overlayadd: LayersControlEvent
\r
26790 // Fired when an overlay is selected through the [layers control](#control-layers).
\r
26791 // @event overlayremove: LayersControlEvent
\r
26792 // Fired when an overlay is deselected through the [layers control](#control-layers).
\r
26793 // @namespace Control.Layers
\r
26794 var type = obj.overlay ?
\r
26795 (e.type === 'add' ? 'overlayadd' : 'overlayremove') :
\r
26796 (e.type === 'add' ? 'baselayerchange' : null);
\r
26799 this._map.fire(type, obj);
\r
26803 // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe)
\r
26804 _createRadioElement: function (name, checked) {
\r
26806 var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' +
\r
26807 name + '"' + (checked ? ' checked="checked"' : '') + '/>';
\r
26809 var radioFragment = document.createElement('div');
\r
26810 radioFragment.innerHTML = radioHtml;
\r
26812 return radioFragment.firstChild;
\r
26815 _addItem: function (obj) {
\r
26816 var label = document.createElement('label'),
\r
26817 checked = this._map.hasLayer(obj.layer),
\r
26820 if (obj.overlay) {
\r
26821 input = document.createElement('input');
\r
26822 input.type = 'checkbox';
\r
26823 input.className = 'leaflet-control-layers-selector';
\r
26824 input.defaultChecked = checked;
\r
26826 input = this._createRadioElement('leaflet-base-layers_' + stamp(this), checked);
\r
26829 this._layerControlInputs.push(input);
\r
26830 input.layerId = stamp(obj.layer);
\r
26832 on(input, 'click', this._onInputClick, this);
\r
26834 var name = document.createElement('span');
\r
26835 name.innerHTML = ' ' + obj.name;
\r
26837 // Helps from preventing layer control flicker when checkboxes are disabled
\r
26838 // https://github.com/Leaflet/Leaflet/issues/2771
\r
26839 var holder = document.createElement('div');
\r
26841 label.appendChild(holder);
\r
26842 holder.appendChild(input);
\r
26843 holder.appendChild(name);
\r
26845 var container = obj.overlay ? this._overlaysList : this._baseLayersList;
\r
26846 container.appendChild(label);
\r
26848 this._checkDisabledLayers();
\r
26852 _onInputClick: function () {
\r
26853 var inputs = this._layerControlInputs,
\r
26855 var addedLayers = [],
\r
26856 removedLayers = [];
\r
26858 this._handlingClick = true;
\r
26860 for (var i = inputs.length - 1; i >= 0; i--) {
\r
26861 input = inputs[i];
\r
26862 layer = this._getLayer(input.layerId).layer;
\r
26864 if (input.checked) {
\r
26865 addedLayers.push(layer);
\r
26866 } else if (!input.checked) {
\r
26867 removedLayers.push(layer);
\r
26871 // Bugfix issue 2318: Should remove all old layers before readding new ones
\r
26872 for (i = 0; i < removedLayers.length; i++) {
\r
26873 if (this._map.hasLayer(removedLayers[i])) {
\r
26874 this._map.removeLayer(removedLayers[i]);
\r
26877 for (i = 0; i < addedLayers.length; i++) {
\r
26878 if (!this._map.hasLayer(addedLayers[i])) {
\r
26879 this._map.addLayer(addedLayers[i]);
\r
26883 this._handlingClick = false;
\r
26885 this._refocusOnMap();
\r
26888 _checkDisabledLayers: function () {
\r
26889 var inputs = this._layerControlInputs,
\r
26892 zoom = this._map.getZoom();
\r
26894 for (var i = inputs.length - 1; i >= 0; i--) {
\r
26895 input = inputs[i];
\r
26896 layer = this._getLayer(input.layerId).layer;
\r
26897 input.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) ||
\r
26898 (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom);
\r
26903 _expandIfNotCollapsed: function () {
\r
26904 if (this._map && !this.options.collapsed) {
\r
26910 _expand: function () {
\r
26911 // Backward compatibility, remove me in 1.1.
\r
26912 return this.expand();
\r
26915 _collapse: function () {
\r
26916 // Backward compatibility, remove me in 1.1.
\r
26917 return this.collapse();
\r
26923 // @factory L.control.layers(baselayers?: Object, overlays?: Object, options?: Control.Layers options)
\r
26924 // Creates a layers control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.
\r
26925 var layers = function (baseLayers, overlays, options) {
\r
26926 return new Layers(baseLayers, overlays, options);
\r
26930 * @class Control.Zoom
\r
26931 * @aka L.Control.Zoom
\r
26932 * @inherits Control
\r
26934 * A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its [`zoomControl` option](#map-zoomcontrol) to `false`. Extends `Control`.
\r
26937 var Zoom = Control.extend({
\r
26939 // @aka Control.Zoom options
\r
26941 position: 'topleft',
\r
26943 // @option zoomInText: String = '+'
\r
26944 // The text set on the 'zoom in' button.
\r
26947 // @option zoomInTitle: String = 'Zoom in'
\r
26948 // The title set on the 'zoom in' button.
\r
26949 zoomInTitle: 'Zoom in',
\r
26951 // @option zoomOutText: String = '−'
\r
26952 // The text set on the 'zoom out' button.
\r
26953 zoomOutText: '−',
\r
26955 // @option zoomOutTitle: String = 'Zoom out'
\r
26956 // The title set on the 'zoom out' button.
\r
26957 zoomOutTitle: 'Zoom out'
\r
26960 onAdd: function (map) {
\r
26961 var zoomName = 'leaflet-control-zoom',
\r
26962 container = create$1('div', zoomName + ' leaflet-bar'),
\r
26963 options = this.options;
\r
26965 this._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle,
\r
26966 zoomName + '-in', container, this._zoomIn);
\r
26967 this._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle,
\r
26968 zoomName + '-out', container, this._zoomOut);
\r
26970 this._updateDisabled();
\r
26971 map.on('zoomend zoomlevelschange', this._updateDisabled, this);
\r
26973 return container;
\r
26976 onRemove: function (map) {
\r
26977 map.off('zoomend zoomlevelschange', this._updateDisabled, this);
\r
26980 disable: function () {
\r
26981 this._disabled = true;
\r
26982 this._updateDisabled();
\r
26986 enable: function () {
\r
26987 this._disabled = false;
\r
26988 this._updateDisabled();
\r
26992 _zoomIn: function (e) {
\r
26993 if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) {
\r
26994 this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
\r
26998 _zoomOut: function (e) {
\r
26999 if (!this._disabled && this._map._zoom > this._map.getMinZoom()) {
\r
27000 this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
\r
27004 _createButton: function (html, title, className, container, fn) {
\r
27005 var link = create$1('a', className, container);
\r
27006 link.innerHTML = html;
\r
27008 link.title = title;
\r
27011 * Will force screen readers like VoiceOver to read this as "Zoom in - button"
\r
27013 link.setAttribute('role', 'button');
\r
27014 link.setAttribute('aria-label', title);
\r
27016 disableClickPropagation(link);
\r
27017 on(link, 'click', stop);
\r
27018 on(link, 'click', fn, this);
\r
27019 on(link, 'click', this._refocusOnMap, this);
\r
27024 _updateDisabled: function () {
\r
27025 var map = this._map,
\r
27026 className = 'leaflet-disabled';
\r
27028 removeClass(this._zoomInButton, className);
\r
27029 removeClass(this._zoomOutButton, className);
\r
27031 if (this._disabled || map._zoom === map.getMinZoom()) {
\r
27032 addClass(this._zoomOutButton, className);
\r
27034 if (this._disabled || map._zoom === map.getMaxZoom()) {
\r
27035 addClass(this._zoomInButton, className);
\r
27040 // @namespace Map
\r
27041 // @section Control options
\r
27042 // @option zoomControl: Boolean = true
\r
27043 // Whether a [zoom control](#control-zoom) is added to the map by default.
\r
27044 Map.mergeOptions({
\r
27045 zoomControl: true
\r
27048 Map.addInitHook(function () {
\r
27049 if (this.options.zoomControl) {
\r
27050 // @section Controls
\r
27051 // @property zoomControl: Control.Zoom
\r
27052 // The default zoom control (only available if the
\r
27053 // [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map).
\r
27054 this.zoomControl = new Zoom();
\r
27055 this.addControl(this.zoomControl);
\r
27059 // @namespace Control.Zoom
\r
27060 // @factory L.control.zoom(options: Control.Zoom options)
\r
27061 // Creates a zoom control
\r
27062 var zoom = function (options) {
\r
27063 return new Zoom(options);
\r
27067 * @class Control.Scale
27068 * @aka L.Control.Scale
27069 * @inherits Control
27071 * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`.
27076 * L.control.scale().addTo(map);
27080 var Scale = Control.extend({
27082 // @aka Control.Scale options
27084 position: 'bottomleft',
27086 // @option maxWidth: Number = 100
27087 // Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
27090 // @option metric: Boolean = True
27091 // Whether to show the metric scale line (m/km).
27094 // @option imperial: Boolean = True
27095 // Whether to show the imperial scale line (mi/ft).
27098 // @option updateWhenIdle: Boolean = false
27099 // If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)).
27102 onAdd: function (map) {
27103 var className = 'leaflet-control-scale',
27104 container = create$1('div', className),
27105 options = this.options;
27107 this._addScales(options, className + '-line', container);
27109 map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
27110 map.whenReady(this._update, this);
27115 onRemove: function (map) {
27116 map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
27119 _addScales: function (options, className, container) {
27120 if (options.metric) {
27121 this._mScale = create$1('div', className, container);
27123 if (options.imperial) {
27124 this._iScale = create$1('div', className, container);
27128 _update: function () {
27129 var map = this._map,
27130 y = map.getSize().y / 2;
27132 var maxMeters = map.distance(
27133 map.containerPointToLatLng([0, y]),
27134 map.containerPointToLatLng([this.options.maxWidth, y]));
27136 this._updateScales(maxMeters);
27139 _updateScales: function (maxMeters) {
27140 if (this.options.metric && maxMeters) {
27141 this._updateMetric(maxMeters);
27143 if (this.options.imperial && maxMeters) {
27144 this._updateImperial(maxMeters);
27148 _updateMetric: function (maxMeters) {
27149 var meters = this._getRoundNum(maxMeters),
27150 label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';
27152 this._updateScale(this._mScale, label, meters / maxMeters);
27155 _updateImperial: function (maxMeters) {
27156 var maxFeet = maxMeters * 3.2808399,
27157 maxMiles, miles, feet;
27159 if (maxFeet > 5280) {
27160 maxMiles = maxFeet / 5280;
27161 miles = this._getRoundNum(maxMiles);
27162 this._updateScale(this._iScale, miles + ' mi', miles / maxMiles);
27165 feet = this._getRoundNum(maxFeet);
27166 this._updateScale(this._iScale, feet + ' ft', feet / maxFeet);
27170 _updateScale: function (scale, text, ratio) {
27171 scale.style.width = Math.round(this.options.maxWidth * ratio) + 'px';
27172 scale.innerHTML = text;
27175 _getRoundNum: function (num) {
27176 var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
27189 // @factory L.control.scale(options?: Control.Scale options)
27190 // Creates an scale control with the given options.
27191 var scale = function (options) {
27192 return new Scale(options);
27196 * @class Control.Attribution
\r
27197 * @aka L.Control.Attribution
\r
27198 * @inherits Control
\r
27200 * The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its [`attributionControl` option](#map-attributioncontrol) to `false`, and it fetches attribution texts from layers with the [`getAttribution` method](#layer-getattribution) automatically. Extends Control.
\r
27203 var Attribution = Control.extend({
\r
27205 // @aka Control.Attribution options
\r
27207 position: 'bottomright',
\r
27209 // @option prefix: String = 'Leaflet'
\r
27210 // The HTML text shown before the attributions. Pass `false` to disable.
\r
27211 prefix: '<a href="https://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'
\r
27214 initialize: function (options) {
\r
27215 setOptions(this, options);
\r
27217 this._attributions = {};
\r
27220 onAdd: function (map) {
\r
27221 map.attributionControl = this;
\r
27222 this._container = create$1('div', 'leaflet-control-attribution');
\r
27223 disableClickPropagation(this._container);
\r
27225 // TODO ugly, refactor
\r
27226 for (var i in map._layers) {
\r
27227 if (map._layers[i].getAttribution) {
\r
27228 this.addAttribution(map._layers[i].getAttribution());
\r
27234 return this._container;
\r
27237 // @method setPrefix(prefix: String): this
\r
27238 // Sets the text before the attributions.
\r
27239 setPrefix: function (prefix) {
\r
27240 this.options.prefix = prefix;
\r
27245 // @method addAttribution(text: String): this
\r
27246 // Adds an attribution text (e.g. `'Vector data © Mapbox'`).
\r
27247 addAttribution: function (text) {
\r
27248 if (!text) { return this; }
\r
27250 if (!this._attributions[text]) {
\r
27251 this._attributions[text] = 0;
\r
27253 this._attributions[text]++;
\r
27260 // @method removeAttribution(text: String): this
\r
27261 // Removes an attribution text.
\r
27262 removeAttribution: function (text) {
\r
27263 if (!text) { return this; }
\r
27265 if (this._attributions[text]) {
\r
27266 this._attributions[text]--;
\r
27273 _update: function () {
\r
27274 if (!this._map) { return; }
\r
27276 var attribs = [];
\r
27278 for (var i in this._attributions) {
\r
27279 if (this._attributions[i]) {
\r
27284 var prefixAndAttribs = [];
\r
27286 if (this.options.prefix) {
\r
27287 prefixAndAttribs.push(this.options.prefix);
\r
27289 if (attribs.length) {
\r
27290 prefixAndAttribs.push(attribs.join(', '));
\r
27293 this._container.innerHTML = prefixAndAttribs.join(' | ');
\r
27297 // @namespace Map
\r
27298 // @section Control options
\r
27299 // @option attributionControl: Boolean = true
\r
27300 // Whether a [attribution control](#control-attribution) is added to the map by default.
\r
27301 Map.mergeOptions({
\r
27302 attributionControl: true
\r
27305 Map.addInitHook(function () {
\r
27306 if (this.options.attributionControl) {
\r
27307 new Attribution().addTo(this);
\r
27311 // @namespace Control.Attribution
\r
27312 // @factory L.control.attribution(options: Control.Attribution options)
\r
27313 // Creates an attribution control.
\r
27314 var attribution = function (options) {
\r
27315 return new Attribution(options);
\r
27318 Control.Layers = Layers;
27319 Control.Zoom = Zoom;
27320 Control.Scale = Scale;
27321 Control.Attribution = Attribution;
27323 control.layers = layers;
27324 control.zoom = zoom;
27325 control.scale = scale;
27326 control.attribution = attribution;
27329 L.Handler is a base class for handler classes that are used internally to inject
27330 interaction features like dragging to classes like Map and Marker.
27335 // Abstract class for map interaction handlers
27337 var Handler = Class.extend({
27338 initialize: function (map) {
27342 // @method enable(): this
27343 // Enables the handler
27344 enable: function () {
27345 if (this._enabled) { return this; }
27347 this._enabled = true;
27352 // @method disable(): this
27353 // Disables the handler
27354 disable: function () {
27355 if (!this._enabled) { return this; }
27357 this._enabled = false;
27358 this.removeHooks();
27362 // @method enabled(): Boolean
27363 // Returns `true` if the handler is enabled
27364 enabled: function () {
27365 return !!this._enabled;
27368 // @section Extension methods
27369 // Classes inheriting from `Handler` must implement the two following methods:
27370 // @method addHooks()
27371 // Called when the handler is enabled, should add event hooks.
27372 // @method removeHooks()
27373 // Called when the handler is disabled, should remove the event hooks added previously.
27376 // @section There is static function which can be called without instantiating L.Handler:
27377 // @function addTo(map: Map, name: String): this
27378 // Adds a new Handler to the given map with the given name.
27379 Handler.addTo = function (map, name) {
27380 map.addHandler(name, this);
27384 var Mixin = {Events: Events};
27387 * @class Draggable
\r
27388 * @aka L.Draggable
\r
27389 * @inherits Evented
\r
27391 * A class for making DOM elements draggable (including touch support).
\r
27392 * Used internally for map and marker dragging. Only works for elements
\r
27393 * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).
\r
27397 * var draggable = new L.Draggable(elementToDrag);
\r
27398 * draggable.enable();
\r
27402 var START = touch ? 'touchstart mousedown' : 'mousedown';
\r
27404 mousedown: 'mouseup',
\r
27405 touchstart: 'touchend',
\r
27406 pointerdown: 'touchend',
\r
27407 MSPointerDown: 'touchend'
\r
27410 mousedown: 'mousemove',
\r
27411 touchstart: 'touchmove',
\r
27412 pointerdown: 'touchmove',
\r
27413 MSPointerDown: 'touchmove'
\r
27417 var Draggable = Evented.extend({
\r
27421 // @aka Draggable options
\r
27422 // @option clickTolerance: Number = 3
\r
27423 // The max number of pixels a user can shift the mouse pointer during a click
\r
27424 // for it to be considered a valid click (as opposed to a mouse drag).
\r
27425 clickTolerance: 3
\r
27428 // @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options)
\r
27429 // Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default).
\r
27430 initialize: function (element, dragStartTarget, preventOutline$$1, options) {
\r
27431 setOptions(this, options);
\r
27433 this._element = element;
\r
27434 this._dragStartTarget = dragStartTarget || element;
\r
27435 this._preventOutline = preventOutline$$1;
\r
27438 // @method enable()
\r
27439 // Enables the dragging ability
\r
27440 enable: function () {
\r
27441 if (this._enabled) { return; }
\r
27443 on(this._dragStartTarget, START, this._onDown, this);
\r
27445 this._enabled = true;
\r
27448 // @method disable()
\r
27449 // Disables the dragging ability
\r
27450 disable: function () {
\r
27451 if (!this._enabled) { return; }
\r
27453 // If we're currently dragging this draggable,
\r
27454 // disabling it counts as first ending the drag.
\r
27455 if (Draggable._dragging === this) {
\r
27456 this.finishDrag();
\r
27459 off(this._dragStartTarget, START, this._onDown, this);
\r
27461 this._enabled = false;
\r
27462 this._moved = false;
\r
27465 _onDown: function (e) {
\r
27466 // Ignore simulated events, since we handle both touch and
\r
27467 // mouse explicitly; otherwise we risk getting duplicates of
\r
27468 // touch events, see #4315.
\r
27469 // Also ignore the event if disabled; this happens in IE11
\r
27470 // under some circumstances, see #3666.
\r
27471 if (e._simulated || !this._enabled) { return; }
\r
27473 this._moved = false;
\r
27475 if (hasClass(this._element, 'leaflet-zoom-anim')) { return; }
\r
27477 if (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }
\r
27478 Draggable._dragging = this; // Prevent dragging multiple objects at once.
\r
27480 if (this._preventOutline) {
\r
27481 preventOutline(this._element);
\r
27484 disableImageDrag();
\r
27485 disableTextSelection();
\r
27487 if (this._moving) { return; }
\r
27489 // @event down: Event
\r
27490 // Fired when a drag is about to start.
\r
27491 this.fire('down');
\r
27493 var first = e.touches ? e.touches[0] : e,
\r
27494 sizedParent = getSizedParentNode(this._element);
\r
27496 this._startPoint = new Point(first.clientX, first.clientY);
\r
27498 // Cache the scale, so that we can continuously compensate for it during drag (_onMove).
\r
27499 this._parentScale = getScale(sizedParent);
\r
27501 on(document, MOVE[e.type], this._onMove, this);
\r
27502 on(document, END[e.type], this._onUp, this);
\r
27505 _onMove: function (e) {
\r
27506 // Ignore simulated events, since we handle both touch and
\r
27507 // mouse explicitly; otherwise we risk getting duplicates of
\r
27508 // touch events, see #4315.
\r
27509 // Also ignore the event if disabled; this happens in IE11
\r
27510 // under some circumstances, see #3666.
\r
27511 if (e._simulated || !this._enabled) { return; }
\r
27513 if (e.touches && e.touches.length > 1) {
\r
27514 this._moved = true;
\r
27518 var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
\r
27519 offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);
\r
27521 if (!offset.x && !offset.y) { return; }
\r
27522 if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; }
\r
27524 // We assume that the parent container's position, border and scale do not change for the duration of the drag.
\r
27525 // Therefore there is no need to account for the position and border (they are eliminated by the subtraction)
\r
27526 // and we can use the cached value for the scale.
\r
27527 offset.x /= this._parentScale.x;
\r
27528 offset.y /= this._parentScale.y;
\r
27530 preventDefault(e);
\r
27532 if (!this._moved) {
\r
27533 // @event dragstart: Event
\r
27534 // Fired when a drag starts
\r
27535 this.fire('dragstart');
\r
27537 this._moved = true;
\r
27538 this._startPos = getPosition(this._element).subtract(offset);
\r
27540 addClass(document.body, 'leaflet-dragging');
\r
27542 this._lastTarget = e.target || e.srcElement;
\r
27543 // IE and Edge do not give the <use> element, so fetch it
\r
27545 if (window.SVGElementInstance && this._lastTarget instanceof window.SVGElementInstance) {
\r
27546 this._lastTarget = this._lastTarget.correspondingUseElement;
\r
27548 addClass(this._lastTarget, 'leaflet-drag-target');
\r
27551 this._newPos = this._startPos.add(offset);
\r
27552 this._moving = true;
\r
27554 cancelAnimFrame(this._animRequest);
\r
27555 this._lastEvent = e;
\r
27556 this._animRequest = requestAnimFrame(this._updatePosition, this, true);
\r
27559 _updatePosition: function () {
\r
27560 var e = {originalEvent: this._lastEvent};
\r
27562 // @event predrag: Event
\r
27563 // Fired continuously during dragging *before* each corresponding
\r
27564 // update of the element's position.
\r
27565 this.fire('predrag', e);
\r
27566 setPosition(this._element, this._newPos);
\r
27568 // @event drag: Event
\r
27569 // Fired continuously during dragging.
\r
27570 this.fire('drag', e);
\r
27573 _onUp: function (e) {
\r
27574 // Ignore simulated events, since we handle both touch and
\r
27575 // mouse explicitly; otherwise we risk getting duplicates of
\r
27576 // touch events, see #4315.
\r
27577 // Also ignore the event if disabled; this happens in IE11
\r
27578 // under some circumstances, see #3666.
\r
27579 if (e._simulated || !this._enabled) { return; }
\r
27580 this.finishDrag();
\r
27583 finishDrag: function () {
\r
27584 removeClass(document.body, 'leaflet-dragging');
\r
27586 if (this._lastTarget) {
\r
27587 removeClass(this._lastTarget, 'leaflet-drag-target');
\r
27588 this._lastTarget = null;
\r
27591 for (var i in MOVE) {
\r
27592 off(document, MOVE[i], this._onMove, this);
\r
27593 off(document, END[i], this._onUp, this);
\r
27596 enableImageDrag();
\r
27597 enableTextSelection();
\r
27599 if (this._moved && this._moving) {
\r
27600 // ensure drag is not fired after dragend
\r
27601 cancelAnimFrame(this._animRequest);
\r
27603 // @event dragend: DragEndEvent
\r
27604 // Fired when the drag ends.
\r
27605 this.fire('dragend', {
\r
27606 distance: this._newPos.distanceTo(this._startPos)
\r
27610 this._moving = false;
\r
27611 Draggable._dragging = false;
\r
27617 * @namespace LineUtil
\r
27619 * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.
\r
27622 // Simplify polyline with vertex reduction and Douglas-Peucker simplification.
\r
27623 // Improves rendering performance dramatically by lessening the number of points to draw.
\r
27625 // @function simplify(points: Point[], tolerance: Number): Point[]
\r
27626 // Dramatically reduces the number of points in a polyline while retaining
\r
27627 // its shape and returns a new array of simplified points, using the
\r
27628 // [Douglas-Peucker algorithm](http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm).
\r
27629 // Used for a huge performance boost when processing/displaying Leaflet polylines for
\r
27630 // each zoom level and also reducing visual noise. tolerance affects the amount of
\r
27631 // simplification (lesser value means higher quality but slower and with more points).
\r
27632 // Also released as a separated micro-library [Simplify.js](http://mourner.github.com/simplify-js/).
\r
27633 function simplify(points, tolerance) {
\r
27634 if (!tolerance || !points.length) {
\r
27635 return points.slice();
\r
27638 var sqTolerance = tolerance * tolerance;
\r
27640 // stage 1: vertex reduction
\r
27641 points = _reducePoints(points, sqTolerance);
\r
27643 // stage 2: Douglas-Peucker simplification
\r
27644 points = _simplifyDP(points, sqTolerance);
\r
27649 // @function pointToSegmentDistance(p: Point, p1: Point, p2: Point): Number
\r
27650 // Returns the distance between point `p` and segment `p1` to `p2`.
\r
27651 function pointToSegmentDistance(p, p1, p2) {
\r
27652 return Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true));
\r
27655 // @function closestPointOnSegment(p: Point, p1: Point, p2: Point): Number
\r
27656 // Returns the closest point from a point `p` on a segment `p1` to `p2`.
\r
27657 function closestPointOnSegment(p, p1, p2) {
\r
27658 return _sqClosestPointOnSegment(p, p1, p2);
\r
27661 // Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm
\r
27662 function _simplifyDP(points, sqTolerance) {
\r
27664 var len = points.length,
\r
27665 ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array,
\r
27666 markers = new ArrayConstructor(len);
\r
27668 markers[0] = markers[len - 1] = 1;
\r
27670 _simplifyDPStep(points, markers, sqTolerance, 0, len - 1);
\r
27675 for (i = 0; i < len; i++) {
\r
27676 if (markers[i]) {
\r
27677 newPoints.push(points[i]);
\r
27681 return newPoints;
\r
27684 function _simplifyDPStep(points, markers, sqTolerance, first, last) {
\r
27686 var maxSqDist = 0,
\r
27687 index, i, sqDist;
\r
27689 for (i = first + 1; i <= last - 1; i++) {
\r
27690 sqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true);
\r
27692 if (sqDist > maxSqDist) {
\r
27694 maxSqDist = sqDist;
\r
27698 if (maxSqDist > sqTolerance) {
\r
27699 markers[index] = 1;
\r
27701 _simplifyDPStep(points, markers, sqTolerance, first, index);
\r
27702 _simplifyDPStep(points, markers, sqTolerance, index, last);
\r
27706 // reduce points that are too close to each other to a single point
\r
27707 function _reducePoints(points, sqTolerance) {
\r
27708 var reducedPoints = [points[0]];
\r
27710 for (var i = 1, prev = 0, len = points.length; i < len; i++) {
\r
27711 if (_sqDist(points[i], points[prev]) > sqTolerance) {
\r
27712 reducedPoints.push(points[i]);
\r
27716 if (prev < len - 1) {
\r
27717 reducedPoints.push(points[len - 1]);
\r
27719 return reducedPoints;
\r
27724 // @function clipSegment(a: Point, b: Point, bounds: Bounds, useLastCode?: Boolean, round?: Boolean): Point[]|Boolean
\r
27725 // Clips the segment a to b by rectangular bounds with the
\r
27726 // [Cohen-Sutherland algorithm](https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm)
\r
27727 // (modifying the segment points directly!). Used by Leaflet to only show polyline
\r
27728 // points that are on the screen or near, increasing performance.
\r
27729 function clipSegment(a, b, bounds, useLastCode, round) {
\r
27730 var codeA = useLastCode ? _lastCode : _getBitCode(a, bounds),
\r
27731 codeB = _getBitCode(b, bounds),
\r
27733 codeOut, p, newCode;
\r
27735 // save 2nd code to avoid calculating it on the next segment
\r
27736 _lastCode = codeB;
\r
27739 // if a,b is inside the clip window (trivial accept)
\r
27740 if (!(codeA | codeB)) {
\r
27744 // if a,b is outside the clip window (trivial reject)
\r
27745 if (codeA & codeB) {
\r
27750 codeOut = codeA || codeB;
\r
27751 p = _getEdgeIntersection(a, b, codeOut, bounds, round);
\r
27752 newCode = _getBitCode(p, bounds);
\r
27754 if (codeOut === codeA) {
\r
27764 function _getEdgeIntersection(a, b, code, bounds, round) {
\r
27765 var dx = b.x - a.x,
\r
27767 min = bounds.min,
\r
27768 max = bounds.max,
\r
27771 if (code & 8) { // top
\r
27772 x = a.x + dx * (max.y - a.y) / dy;
\r
27775 } else if (code & 4) { // bottom
\r
27776 x = a.x + dx * (min.y - a.y) / dy;
\r
27779 } else if (code & 2) { // right
\r
27781 y = a.y + dy * (max.x - a.x) / dx;
\r
27783 } else if (code & 1) { // left
\r
27785 y = a.y + dy * (min.x - a.x) / dx;
\r
27788 return new Point(x, y, round);
\r
27791 function _getBitCode(p, bounds) {
\r
27794 if (p.x < bounds.min.x) { // left
\r
27796 } else if (p.x > bounds.max.x) { // right
\r
27800 if (p.y < bounds.min.y) { // bottom
\r
27802 } else if (p.y > bounds.max.y) { // top
\r
27809 // square distance (to avoid unnecessary Math.sqrt calls)
\r
27810 function _sqDist(p1, p2) {
\r
27811 var dx = p2.x - p1.x,
\r
27812 dy = p2.y - p1.y;
\r
27813 return dx * dx + dy * dy;
\r
27816 // return closest point on segment or distance to that point
\r
27817 function _sqClosestPointOnSegment(p, p1, p2, sqDist) {
\r
27822 dot = dx * dx + dy * dy,
\r
27826 t = ((p.x - x) * dx + (p.y - y) * dy) / dot;
\r
27831 } else if (t > 0) {
\r
27840 return sqDist ? dx * dx + dy * dy : new Point(x, y);
\r
27844 // @function isFlat(latlngs: LatLng[]): Boolean
\r
27845 // Returns true if `latlngs` is a flat array, false is nested.
\r
27846 function isFlat(latlngs) {
\r
27847 return !isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined');
\r
27850 function _flat(latlngs) {
\r
27851 console.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.');
\r
27852 return isFlat(latlngs);
\r
27856 simplify: simplify,
27857 pointToSegmentDistance: pointToSegmentDistance,
27858 closestPointOnSegment: closestPointOnSegment,
27859 clipSegment: clipSegment,
27860 _getEdgeIntersection: _getEdgeIntersection,
27861 _getBitCode: _getBitCode,
27862 _sqClosestPointOnSegment: _sqClosestPointOnSegment,
27868 * @namespace PolyUtil
\r
27869 * Various utility functions for polygon geometries.
\r
27872 /* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[]
\r
27873 * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)).
\r
27874 * Used by Leaflet to only show polygon points that are on the screen or near, increasing
\r
27875 * performance. Note that polygon points needs different algorithm for clipping
\r
27876 * than polyline, so there's a separate method for it.
\r
27878 function clipPolygon(points, bounds, round) {
\r
27879 var clippedPoints,
\r
27880 edges = [1, 4, 2, 8],
\r
27885 for (i = 0, len = points.length; i < len; i++) {
\r
27886 points[i]._code = _getBitCode(points[i], bounds);
\r
27889 // for each edge (left, bottom, right, top)
\r
27890 for (k = 0; k < 4; k++) {
\r
27892 clippedPoints = [];
\r
27894 for (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
\r
27898 // if a is inside the clip window
\r
27899 if (!(a._code & edge)) {
\r
27900 // if b is outside the clip window (a->b goes out of screen)
\r
27901 if (b._code & edge) {
\r
27902 p = _getEdgeIntersection(b, a, edge, bounds, round);
\r
27903 p._code = _getBitCode(p, bounds);
\r
27904 clippedPoints.push(p);
\r
27906 clippedPoints.push(a);
\r
27908 // else if b is inside the clip window (a->b enters the screen)
\r
27909 } else if (!(b._code & edge)) {
\r
27910 p = _getEdgeIntersection(b, a, edge, bounds, round);
\r
27911 p._code = _getBitCode(p, bounds);
\r
27912 clippedPoints.push(p);
\r
27915 points = clippedPoints;
\r
27922 clipPolygon: clipPolygon
27926 * @namespace Projection
\r
27928 * Leaflet comes with a set of already defined Projections out of the box:
\r
27930 * @projection L.Projection.LonLat
\r
27932 * Equirectangular, or Plate Carree projection — the most simple projection,
\r
27933 * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as
\r
27934 * latitude. Also suitable for flat worlds, e.g. game maps. Used by the
\r
27935 * `EPSG:4326` and `Simple` CRS.
\r
27939 project: function (latlng) {
\r
27940 return new Point(latlng.lng, latlng.lat);
\r
27943 unproject: function (point) {
\r
27944 return new LatLng(point.y, point.x);
\r
27947 bounds: new Bounds([-180, -90], [180, 90])
\r
27951 * @namespace Projection
\r
27952 * @projection L.Projection.Mercator
\r
27954 * Elliptical Mercator projection — more complex than Spherical Mercator. Assumes that Earth is an ellipsoid. Used by the EPSG:3395 CRS.
\r
27959 R_MINOR: 6356752.314245179,
\r
27961 bounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]),
\r
27963 project: function (latlng) {
\r
27964 var d = Math.PI / 180,
\r
27966 y = latlng.lat * d,
\r
27967 tmp = this.R_MINOR / r,
\r
27968 e = Math.sqrt(1 - tmp * tmp),
\r
27969 con = e * Math.sin(y);
\r
27971 var ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2);
\r
27972 y = -r * Math.log(Math.max(ts, 1E-10));
\r
27974 return new Point(latlng.lng * d * r, y);
\r
27977 unproject: function (point) {
\r
27978 var d = 180 / Math.PI,
\r
27980 tmp = this.R_MINOR / r,
\r
27981 e = Math.sqrt(1 - tmp * tmp),
\r
27982 ts = Math.exp(-point.y / r),
\r
27983 phi = Math.PI / 2 - 2 * Math.atan(ts);
\r
27985 for (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) {
\r
27986 con = e * Math.sin(phi);
\r
27987 con = Math.pow((1 - con) / (1 + con), e / 2);
\r
27988 dphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi;
\r
27992 return new LatLng(phi * d, point.x * d / r);
\r
27997 * @class Projection
27999 * An object with methods for projecting geographical coordinates of the world onto
28000 * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection).
28002 * @property bounds: Bounds
28003 * The bounds (specified in CRS units) where the projection is valid
28005 * @method project(latlng: LatLng): Point
28006 * Projects geographical coordinates into a 2D point.
28007 * Only accepts actual `L.LatLng` instances, not arrays.
28009 * @method unproject(point: Point): LatLng
28010 * The inverse of `project`. Projects a 2D point into a geographical location.
28011 * Only accepts actual `L.Point` instances, not arrays.
28013 * Note that the projection instances do not inherit from Leaflet's `Class` object,
28014 * and can't be instantiated. Also, new classes can't inherit from them,
28015 * and methods can't be added to them with the `include` function.
28021 Mercator: Mercator,
28022 SphericalMercator: SphericalMercator
28027 * @crs L.CRS.EPSG3395
\r
28029 * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.
\r
28031 var EPSG3395 = extend({}, Earth, {
\r
28032 code: 'EPSG:3395',
\r
28033 projection: Mercator,
\r
28035 transformation: (function () {
\r
28036 var scale = 0.5 / (Math.PI * Mercator.R);
\r
28037 return toTransformation(scale, 0.5, -scale, 0.5);
\r
28043 * @crs L.CRS.EPSG4326
\r
28045 * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection.
\r
28047 * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic),
\r
28048 * which is a breaking change from 0.7.x behaviour. If you are using a `TileLayer`
\r
28049 * with this CRS, ensure that there are two 256x256 pixel tiles covering the
\r
28050 * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90),
\r
28051 * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set.
\r
28054 var EPSG4326 = extend({}, Earth, {
\r
28055 code: 'EPSG:4326',
\r
28056 projection: LonLat,
\r
28057 transformation: toTransformation(1 / 180, 1, -1 / 180, 0.5)
\r
28062 * @crs L.CRS.Simple
28064 * A simple CRS that maps longitude and latitude into `x` and `y` directly.
28065 * May be used for maps of flat surfaces (e.g. game maps). Note that the `y`
28066 * axis should still be inverted (going from bottom to top). `distance()` returns
28067 * simple euclidean distance.
28070 var Simple = extend({}, CRS, {
28071 projection: LonLat,
28072 transformation: toTransformation(1, 0, -1, 0),
28074 scale: function (zoom) {
28075 return Math.pow(2, zoom);
28078 zoom: function (scale) {
28079 return Math.log(scale) / Math.LN2;
28082 distance: function (latlng1, latlng2) {
28083 var dx = latlng2.lng - latlng1.lng,
28084 dy = latlng2.lat - latlng1.lat;
28086 return Math.sqrt(dx * dx + dy * dy);
28093 CRS.EPSG3395 = EPSG3395;
28094 CRS.EPSG3857 = EPSG3857;
28095 CRS.EPSG900913 = EPSG900913;
28096 CRS.EPSG4326 = EPSG4326;
28097 CRS.Simple = Simple;
28101 * @inherits Evented
28105 * A set of methods from the Layer base class that all Leaflet layers use.
28106 * Inherits all methods, options and events from `L.Evented`.
28111 * var layer = L.marker(latlng).addTo(map);
28112 * layer.addTo(map);
28116 * @event add: Event
28117 * Fired after the layer is added to a map
28119 * @event remove: Event
28120 * Fired after the layer is removed from a map
28124 var Layer = Evented.extend({
28126 // Classes extending `L.Layer` will inherit the following options:
28128 // @option pane: String = 'overlayPane'
28129 // By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default.
28130 pane: 'overlayPane',
28132 // @option attribution: String = null
28133 // String to be shown in the attribution control, e.g. "© OpenStreetMap contributors". It describes the layer data and is often a legal obligation towards copyright holders and tile providers.
28136 bubblingMouseEvents: true
28140 * Classes extending `L.Layer` will inherit the following methods:
28142 * @method addTo(map: Map|LayerGroup): this
28143 * Adds the layer to the given map or layer group.
28145 addTo: function (map) {
28146 map.addLayer(this);
28150 // @method remove: this
28151 // Removes the layer from the map it is currently active on.
28152 remove: function () {
28153 return this.removeFrom(this._map || this._mapToAdd);
28156 // @method removeFrom(map: Map): this
28157 // Removes the layer from the given map
28160 // @method removeFrom(group: LayerGroup): this
28161 // Removes the layer from the given `LayerGroup`
28162 removeFrom: function (obj) {
28164 obj.removeLayer(this);
28169 // @method getPane(name? : String): HTMLElement
28170 // Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer.
28171 getPane: function (name) {
28172 return this._map.getPane(name ? (this.options[name] || name) : this.options.pane);
28175 addInteractiveTarget: function (targetEl) {
28176 this._map._targets[stamp(targetEl)] = this;
28180 removeInteractiveTarget: function (targetEl) {
28181 delete this._map._targets[stamp(targetEl)];
28185 // @method getAttribution: String
28186 // Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution).
28187 getAttribution: function () {
28188 return this.options.attribution;
28191 _layerAdd: function (e) {
28192 var map = e.target;
28194 // check in case layer gets added and then removed before the map is ready
28195 if (!map.hasLayer(this)) { return; }
28198 this._zoomAnimated = map._zoomAnimated;
28200 if (this.getEvents) {
28201 var events = this.getEvents();
28202 map.on(events, this);
28203 this.once('remove', function () {
28204 map.off(events, this);
28210 if (this.getAttribution && map.attributionControl) {
28211 map.attributionControl.addAttribution(this.getAttribution());
28215 map.fire('layeradd', {layer: this});
28219 /* @section Extension methods
28222 * Every layer should extend from `L.Layer` and (re-)implement the following methods.
28224 * @method onAdd(map: Map): this
28225 * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer).
28227 * @method onRemove(map: Map): this
28228 * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer).
28230 * @method getEvents(): Object
28231 * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer.
28233 * @method getAttribution(): String
28234 * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible.
28236 * @method beforeAdd(map: Map): this
28237 * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.
28242 * @section Layer events
28244 * @event layeradd: LayerEvent
28245 * Fired when a new layer is added to the map.
28247 * @event layerremove: LayerEvent
28248 * Fired when some layer is removed from the map
28250 * @section Methods for Layers and Controls
28253 // @method addLayer(layer: Layer): this
28254 // Adds the given layer to the map
28255 addLayer: function (layer) {
28256 if (!layer._layerAdd) {
28257 throw new Error('The provided object is not a Layer.');
28260 var id = stamp(layer);
28261 if (this._layers[id]) { return this; }
28262 this._layers[id] = layer;
28264 layer._mapToAdd = this;
28266 if (layer.beforeAdd) {
28267 layer.beforeAdd(this);
28270 this.whenReady(layer._layerAdd, layer);
28275 // @method removeLayer(layer: Layer): this
28276 // Removes the given layer from the map.
28277 removeLayer: function (layer) {
28278 var id = stamp(layer);
28280 if (!this._layers[id]) { return this; }
28282 if (this._loaded) {
28283 layer.onRemove(this);
28286 if (layer.getAttribution && this.attributionControl) {
28287 this.attributionControl.removeAttribution(layer.getAttribution());
28290 delete this._layers[id];
28292 if (this._loaded) {
28293 this.fire('layerremove', {layer: layer});
28294 layer.fire('remove');
28297 layer._map = layer._mapToAdd = null;
28302 // @method hasLayer(layer: Layer): Boolean
28303 // Returns `true` if the given layer is currently added to the map
28304 hasLayer: function (layer) {
28305 return !!layer && (stamp(layer) in this._layers);
28308 /* @method eachLayer(fn: Function, context?: Object): this
28309 * Iterates over the layers of the map, optionally specifying context of the iterator function.
28311 * map.eachLayer(function(layer){
28312 * layer.bindPopup('Hello');
28316 eachLayer: function (method, context) {
28317 for (var i in this._layers) {
28318 method.call(context, this._layers[i]);
28323 _addLayers: function (layers) {
28324 layers = layers ? (isArray(layers) ? layers : [layers]) : [];
28326 for (var i = 0, len = layers.length; i < len; i++) {
28327 this.addLayer(layers[i]);
28331 _addZoomLimit: function (layer) {
28332 if (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {
28333 this._zoomBoundLayers[stamp(layer)] = layer;
28334 this._updateZoomLevels();
28338 _removeZoomLimit: function (layer) {
28339 var id = stamp(layer);
28341 if (this._zoomBoundLayers[id]) {
28342 delete this._zoomBoundLayers[id];
28343 this._updateZoomLevels();
28347 _updateZoomLevels: function () {
28348 var minZoom = Infinity,
28349 maxZoom = -Infinity,
28350 oldZoomSpan = this._getZoomSpan();
28352 for (var i in this._zoomBoundLayers) {
28353 var options = this._zoomBoundLayers[i].options;
28355 minZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom);
28356 maxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom);
28359 this._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom;
28360 this._layersMinZoom = minZoom === Infinity ? undefined : minZoom;
28362 // @section Map state change events
28363 // @event zoomlevelschange: Event
28364 // Fired when the number of zoomlevels on the map is changed due
28365 // to adding or removing a layer.
28366 if (oldZoomSpan !== this._getZoomSpan()) {
28367 this.fire('zoomlevelschange');
28370 if (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) {
28371 this.setZoom(this._layersMaxZoom);
28373 if (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) {
28374 this.setZoom(this._layersMinZoom);
28380 * @class LayerGroup
\r
28381 * @aka L.LayerGroup
\r
28382 * @inherits Layer
\r
28384 * Used to group several layers and handle them as one. If you add it to the map,
\r
28385 * any layers added or removed from the group will be added/removed on the map as
\r
28386 * well. Extends `Layer`.
\r
28391 * L.layerGroup([marker1, marker2])
\r
28392 * .addLayer(polyline)
\r
28397 var LayerGroup = Layer.extend({
\r
28399 initialize: function (layers, options) {
\r
28400 setOptions(this, options);
\r
28402 this._layers = {};
\r
28407 for (i = 0, len = layers.length; i < len; i++) {
\r
28408 this.addLayer(layers[i]);
\r
28413 // @method addLayer(layer: Layer): this
\r
28414 // Adds the given layer to the group.
\r
28415 addLayer: function (layer) {
\r
28416 var id = this.getLayerId(layer);
\r
28418 this._layers[id] = layer;
\r
28421 this._map.addLayer(layer);
\r
28427 // @method removeLayer(layer: Layer): this
\r
28428 // Removes the given layer from the group.
\r
28430 // @method removeLayer(id: Number): this
\r
28431 // Removes the layer with the given internal ID from the group.
\r
28432 removeLayer: function (layer) {
\r
28433 var id = layer in this._layers ? layer : this.getLayerId(layer);
\r
28435 if (this._map && this._layers[id]) {
\r
28436 this._map.removeLayer(this._layers[id]);
\r
28439 delete this._layers[id];
\r
28444 // @method hasLayer(layer: Layer): Boolean
\r
28445 // Returns `true` if the given layer is currently added to the group.
\r
28447 // @method hasLayer(id: Number): Boolean
\r
28448 // Returns `true` if the given internal ID is currently added to the group.
\r
28449 hasLayer: function (layer) {
\r
28450 if (!layer) { return false; }
\r
28451 var layerId = typeof layer === 'number' ? layer : this.getLayerId(layer);
\r
28452 return layerId in this._layers;
\r
28455 // @method clearLayers(): this
\r
28456 // Removes all the layers from the group.
\r
28457 clearLayers: function () {
\r
28458 return this.eachLayer(this.removeLayer, this);
\r
28461 // @method invoke(methodName: String, …): this
\r
28462 // Calls `methodName` on every layer contained in this group, passing any
\r
28463 // additional parameters. Has no effect if the layers contained do not
\r
28464 // implement `methodName`.
\r
28465 invoke: function (methodName) {
\r
28466 var args = Array.prototype.slice.call(arguments, 1),
\r
28469 for (i in this._layers) {
\r
28470 layer = this._layers[i];
\r
28472 if (layer[methodName]) {
\r
28473 layer[methodName].apply(layer, args);
\r
28480 onAdd: function (map) {
\r
28481 this.eachLayer(map.addLayer, map);
\r
28484 onRemove: function (map) {
\r
28485 this.eachLayer(map.removeLayer, map);
\r
28488 // @method eachLayer(fn: Function, context?: Object): this
\r
28489 // Iterates over the layers of the group, optionally specifying context of the iterator function.
\r
28491 // group.eachLayer(function (layer) {
\r
28492 // layer.bindPopup('Hello');
\r
28495 eachLayer: function (method, context) {
\r
28496 for (var i in this._layers) {
\r
28497 method.call(context, this._layers[i]);
\r
28502 // @method getLayer(id: Number): Layer
\r
28503 // Returns the layer with the given internal ID.
\r
28504 getLayer: function (id) {
\r
28505 return this._layers[id];
\r
28508 // @method getLayers(): Layer[]
\r
28509 // Returns an array of all the layers added to the group.
\r
28510 getLayers: function () {
\r
28512 this.eachLayer(layers.push, layers);
\r
28516 // @method setZIndex(zIndex: Number): this
\r
28517 // Calls `setZIndex` on every layer contained in this group, passing the z-index.
\r
28518 setZIndex: function (zIndex) {
\r
28519 return this.invoke('setZIndex', zIndex);
\r
28522 // @method getLayerId(layer: Layer): Number
\r
28523 // Returns the internal ID for a layer
\r
28524 getLayerId: function (layer) {
\r
28525 return stamp(layer);
\r
28530 // @factory L.layerGroup(layers?: Layer[], options?: Object)
\r
28531 // Create a layer group, optionally given an initial set of layers and an `options` object.
\r
28532 var layerGroup = function (layers, options) {
\r
28533 return new LayerGroup(layers, options);
\r
28537 * @class FeatureGroup
\r
28538 * @aka L.FeatureGroup
\r
28539 * @inherits LayerGroup
\r
28541 * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers:
\r
28542 * * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip))
\r
28543 * * Events are propagated to the `FeatureGroup`, so if the group has an event
\r
28544 * handler, it will handle events from any of the layers. This includes mouse events
\r
28545 * and custom events.
\r
28546 * * Has `layeradd` and `layerremove` events
\r
28551 * L.featureGroup([marker1, marker2, polyline])
\r
28552 * .bindPopup('Hello world!')
\r
28553 * .on('click', function() { alert('Clicked on a member of the group!'); })
\r
28558 var FeatureGroup = LayerGroup.extend({
\r
28560 addLayer: function (layer) {
\r
28561 if (this.hasLayer(layer)) {
\r
28565 layer.addEventParent(this);
\r
28567 LayerGroup.prototype.addLayer.call(this, layer);
\r
28569 // @event layeradd: LayerEvent
\r
28570 // Fired when a layer is added to this `FeatureGroup`
\r
28571 return this.fire('layeradd', {layer: layer});
\r
28574 removeLayer: function (layer) {
\r
28575 if (!this.hasLayer(layer)) {
\r
28578 if (layer in this._layers) {
\r
28579 layer = this._layers[layer];
\r
28582 layer.removeEventParent(this);
\r
28584 LayerGroup.prototype.removeLayer.call(this, layer);
\r
28586 // @event layerremove: LayerEvent
\r
28587 // Fired when a layer is removed from this `FeatureGroup`
\r
28588 return this.fire('layerremove', {layer: layer});
\r
28591 // @method setStyle(style: Path options): this
\r
28592 // Sets the given path options to each layer of the group that has a `setStyle` method.
\r
28593 setStyle: function (style) {
\r
28594 return this.invoke('setStyle', style);
\r
28597 // @method bringToFront(): this
\r
28598 // Brings the layer group to the top of all other layers
\r
28599 bringToFront: function () {
\r
28600 return this.invoke('bringToFront');
\r
28603 // @method bringToBack(): this
\r
28604 // Brings the layer group to the back of all other layers
\r
28605 bringToBack: function () {
\r
28606 return this.invoke('bringToBack');
\r
28609 // @method getBounds(): LatLngBounds
\r
28610 // Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).
\r
28611 getBounds: function () {
\r
28612 var bounds = new LatLngBounds();
\r
28614 for (var id in this._layers) {
\r
28615 var layer = this._layers[id];
\r
28616 bounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng());
\r
28622 // @factory L.featureGroup(layers?: Layer[], options?: Object)
\r
28623 // Create a feature group, optionally given an initial set of layers and an `options` object.
\r
28624 var featureGroup = function (layers, options) {
\r
28625 return new FeatureGroup(layers, options);
\r
28632 * Represents an icon to provide when creating a marker.
\r
28637 * var myIcon = L.icon({
\r
28638 * iconUrl: 'my-icon.png',
\r
28639 * iconRetinaUrl: 'my-icon@2x.png',
\r
28640 * iconSize: [38, 95],
\r
28641 * iconAnchor: [22, 94],
\r
28642 * popupAnchor: [-3, -76],
\r
28643 * shadowUrl: 'my-icon-shadow.png',
\r
28644 * shadowRetinaUrl: 'my-icon-shadow@2x.png',
\r
28645 * shadowSize: [68, 95],
\r
28646 * shadowAnchor: [22, 94]
\r
28649 * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
\r
28652 * `L.Icon.Default` extends `L.Icon` and is the blue icon Leaflet uses for markers by default.
\r
28656 var Icon = Class.extend({
\r
28659 * @aka Icon options
\r
28661 * @option iconUrl: String = null
\r
28662 * **(required)** The URL to the icon image (absolute or relative to your script path).
\r
28664 * @option iconRetinaUrl: String = null
\r
28665 * The URL to a retina sized version of the icon image (absolute or relative to your
\r
28666 * script path). Used for Retina screen devices.
\r
28668 * @option iconSize: Point = null
\r
28669 * Size of the icon image in pixels.
\r
28671 * @option iconAnchor: Point = null
\r
28672 * The coordinates of the "tip" of the icon (relative to its top left corner). The icon
\r
28673 * will be aligned so that this point is at the marker's geographical location. Centered
\r
28674 * by default if size is specified, also can be set in CSS with negative margins.
\r
28676 * @option popupAnchor: Point = [0, 0]
\r
28677 * The coordinates of the point from which popups will "open", relative to the icon anchor.
\r
28679 * @option tooltipAnchor: Point = [0, 0]
\r
28680 * The coordinates of the point from which tooltips will "open", relative to the icon anchor.
\r
28682 * @option shadowUrl: String = null
\r
28683 * The URL to the icon shadow image. If not specified, no shadow image will be created.
\r
28685 * @option shadowRetinaUrl: String = null
\r
28687 * @option shadowSize: Point = null
\r
28688 * Size of the shadow image in pixels.
\r
28690 * @option shadowAnchor: Point = null
\r
28691 * The coordinates of the "tip" of the shadow (relative to its top left corner) (the same
\r
28692 * as iconAnchor if not specified).
\r
28694 * @option className: String = ''
\r
28695 * A custom class name to assign to both icon and shadow images. Empty by default.
\r
28699 popupAnchor: [0, 0],
\r
28700 tooltipAnchor: [0, 0]
\r
28703 initialize: function (options) {
\r
28704 setOptions(this, options);
\r
28707 // @method createIcon(oldIcon?: HTMLElement): HTMLElement
\r
28708 // Called internally when the icon has to be shown, returns a `<img>` HTML element
\r
28709 // styled according to the options.
\r
28710 createIcon: function (oldIcon) {
\r
28711 return this._createIcon('icon', oldIcon);
\r
28714 // @method createShadow(oldIcon?: HTMLElement): HTMLElement
\r
28715 // As `createIcon`, but for the shadow beneath it.
\r
28716 createShadow: function (oldIcon) {
\r
28717 return this._createIcon('shadow', oldIcon);
\r
28720 _createIcon: function (name, oldIcon) {
\r
28721 var src = this._getIconUrl(name);
\r
28724 if (name === 'icon') {
\r
28725 throw new Error('iconUrl not set in Icon options (see the docs).');
\r
28730 var img = this._createImg(src, oldIcon && oldIcon.tagName === 'IMG' ? oldIcon : null);
\r
28731 this._setIconStyles(img, name);
\r
28736 _setIconStyles: function (img, name) {
\r
28737 var options = this.options;
\r
28738 var sizeOption = options[name + 'Size'];
\r
28740 if (typeof sizeOption === 'number') {
\r
28741 sizeOption = [sizeOption, sizeOption];
\r
28744 var size = toPoint(sizeOption),
\r
28745 anchor = toPoint(name === 'shadow' && options.shadowAnchor || options.iconAnchor ||
\r
28746 size && size.divideBy(2, true));
\r
28748 img.className = 'leaflet-marker-' + name + ' ' + (options.className || '');
\r
28751 img.style.marginLeft = (-anchor.x) + 'px';
\r
28752 img.style.marginTop = (-anchor.y) + 'px';
\r
28756 img.style.width = size.x + 'px';
\r
28757 img.style.height = size.y + 'px';
\r
28761 _createImg: function (src, el) {
\r
28762 el = el || document.createElement('img');
\r
28767 _getIconUrl: function (name) {
\r
28768 return retina && this.options[name + 'RetinaUrl'] || this.options[name + 'Url'];
\r
28773 // @factory L.icon(options: Icon options)
\r
28774 // Creates an icon instance with the given options.
\r
28775 function icon(options) {
\r
28776 return new Icon(options);
\r
28780 * @miniclass Icon.Default (Icon)
28781 * @aka L.Icon.Default
28784 * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when
28785 * no icon is specified. Points to the blue marker image distributed with Leaflet
28788 * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options`
28789 * (which is a set of `Icon options`).
28791 * If you want to _completely_ replace the default icon, override the
28792 * `L.Marker.prototype.options.icon` with your own icon instead.
28795 var IconDefault = Icon.extend({
28798 iconUrl: 'marker-icon.png',
28799 iconRetinaUrl: 'marker-icon-2x.png',
28800 shadowUrl: 'marker-shadow.png',
28801 iconSize: [25, 41],
28802 iconAnchor: [12, 41],
28803 popupAnchor: [1, -34],
28804 tooltipAnchor: [16, -28],
28805 shadowSize: [41, 41]
28808 _getIconUrl: function (name) {
28809 if (!IconDefault.imagePath) { // Deprecated, backwards-compatibility only
28810 IconDefault.imagePath = this._detectIconPath();
28813 // @option imagePath: String
28814 // `Icon.Default` will try to auto-detect the location of the
28815 // blue icon images. If you are placing these images in a non-standard
28816 // way, set this option to point to the right path.
28817 return (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);
28820 _detectIconPath: function () {
28821 var el = create$1('div', 'leaflet-default-icon-path', document.body);
28822 var path = getStyle(el, 'background-image') ||
28823 getStyle(el, 'backgroundImage'); // IE8
28825 document.body.removeChild(el);
28827 if (path === null || path.indexOf('url') !== 0) {
28830 path = path.replace(/^url\(["']?/, '').replace(/marker-icon\.png["']?\)$/, '');
28838 * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.
28842 /* @namespace Marker
28843 * @section Interaction handlers
28845 * Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see `Handler` methods). Example:
28848 * marker.dragging.disable();
28851 * @property dragging: Handler
28852 * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)).
28855 var MarkerDrag = Handler.extend({
28856 initialize: function (marker) {
28857 this._marker = marker;
28860 addHooks: function () {
28861 var icon = this._marker._icon;
28863 if (!this._draggable) {
28864 this._draggable = new Draggable(icon, icon, true);
28867 this._draggable.on({
28868 dragstart: this._onDragStart,
28869 predrag: this._onPreDrag,
28870 drag: this._onDrag,
28871 dragend: this._onDragEnd
28874 addClass(icon, 'leaflet-marker-draggable');
28877 removeHooks: function () {
28878 this._draggable.off({
28879 dragstart: this._onDragStart,
28880 predrag: this._onPreDrag,
28881 drag: this._onDrag,
28882 dragend: this._onDragEnd
28883 }, this).disable();
28885 if (this._marker._icon) {
28886 removeClass(this._marker._icon, 'leaflet-marker-draggable');
28890 moved: function () {
28891 return this._draggable && this._draggable._moved;
28894 _adjustPan: function (e) {
28895 var marker = this._marker,
28897 speed = this._marker.options.autoPanSpeed,
28898 padding = this._marker.options.autoPanPadding,
28899 iconPos = getPosition(marker._icon),
28900 bounds = map.getPixelBounds(),
28901 origin = map.getPixelOrigin();
28903 var panBounds = toBounds(
28904 bounds.min._subtract(origin).add(padding),
28905 bounds.max._subtract(origin).subtract(padding)
28908 if (!panBounds.contains(iconPos)) {
28909 // Compute incremental movement
28910 var movement = toPoint(
28911 (Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) -
28912 (Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),
28914 (Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) -
28915 (Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)
28916 ).multiplyBy(speed);
28918 map.panBy(movement, {animate: false});
28920 this._draggable._newPos._add(movement);
28921 this._draggable._startPos._add(movement);
28923 setPosition(marker._icon, this._draggable._newPos);
28926 this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
28930 _onDragStart: function () {
28931 // @section Dragging events
28932 // @event dragstart: Event
28933 // Fired when the user starts dragging the marker.
28935 // @event movestart: Event
28936 // Fired when the marker starts moving (because of dragging).
28938 this._oldLatLng = this._marker.getLatLng();
28940 // When using ES6 imports it could not be set when `Popup` was not imported as well
28941 this._marker.closePopup && this._marker.closePopup();
28945 .fire('dragstart');
28948 _onPreDrag: function (e) {
28949 if (this._marker.options.autoPan) {
28950 cancelAnimFrame(this._panRequest);
28951 this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
28955 _onDrag: function (e) {
28956 var marker = this._marker,
28957 shadow = marker._shadow,
28958 iconPos = getPosition(marker._icon),
28959 latlng = marker._map.layerPointToLatLng(iconPos);
28961 // update shadow position
28963 setPosition(shadow, iconPos);
28966 marker._latlng = latlng;
28968 e.oldLatLng = this._oldLatLng;
28970 // @event drag: Event
28971 // Fired repeatedly while the user drags the marker.
28977 _onDragEnd: function (e) {
28978 // @event dragend: DragEndEvent
28979 // Fired when the user stops dragging the marker.
28981 cancelAnimFrame(this._panRequest);
28983 // @event moveend: Event
28984 // Fired when the marker stops moving (because of dragging).
28985 delete this._oldLatLng;
28988 .fire('dragend', e);
28994 * @inherits Interactive layer
\r
28996 * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`.
\r
29001 * L.marker([50.5, 30.5]).addTo(map);
\r
29005 var Marker = Layer.extend({
\r
29008 // @aka Marker options
\r
29010 // @option icon: Icon = *
\r
29011 // Icon instance to use for rendering the marker.
\r
29012 // See [Icon documentation](#L.Icon) for details on how to customize the marker icon.
\r
29013 // If not specified, a common instance of `L.Icon.Default` is used.
\r
29014 icon: new IconDefault(),
\r
29016 // Option inherited from "Interactive layer" abstract class
\r
29017 interactive: true,
\r
29019 // @option keyboard: Boolean = true
\r
29020 // Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
\r
29023 // @option title: String = ''
\r
29024 // Text for the browser tooltip that appear on marker hover (no tooltip by default).
\r
29027 // @option alt: String = ''
\r
29028 // Text for the `alt` attribute of the icon image (useful for accessibility).
\r
29031 // @option zIndexOffset: Number = 0
\r
29032 // By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively).
\r
29035 // @option opacity: Number = 1.0
\r
29036 // The opacity of the marker.
\r
29039 // @option riseOnHover: Boolean = false
\r
29040 // If `true`, the marker will get on top of others when you hover the mouse over it.
\r
29041 riseOnHover: false,
\r
29043 // @option riseOffset: Number = 250
\r
29044 // The z-index offset used for the `riseOnHover` feature.
\r
29047 // @option pane: String = 'markerPane'
\r
29048 // `Map pane` where the markers icon will be added.
\r
29049 pane: 'markerPane',
\r
29051 // @option shadowPane: String = 'shadowPane'
\r
29052 // `Map pane` where the markers shadow will be added.
\r
29053 shadowPane: 'shadowPane',
\r
29055 // @option bubblingMouseEvents: Boolean = false
\r
29056 // When `true`, a mouse event on this marker will trigger the same event on the map
\r
29057 // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
\r
29058 bubblingMouseEvents: false,
\r
29060 // @section Draggable marker options
\r
29061 // @option draggable: Boolean = false
\r
29062 // Whether the marker is draggable with mouse/touch or not.
\r
29063 draggable: false,
\r
29065 // @option autoPan: Boolean = false
\r
29066 // Whether to pan the map when dragging this marker near its edge or not.
\r
29069 // @option autoPanPadding: Point = Point(50, 50)
\r
29070 // Distance (in pixels to the left/right and to the top/bottom) of the
\r
29071 // map edge to start panning the map.
\r
29072 autoPanPadding: [50, 50],
\r
29074 // @option autoPanSpeed: Number = 10
\r
29075 // Number of pixels the map should pan by.
\r
29081 * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods:
\r
29084 initialize: function (latlng, options) {
\r
29085 setOptions(this, options);
\r
29086 this._latlng = toLatLng(latlng);
\r
29089 onAdd: function (map) {
\r
29090 this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;
\r
29092 if (this._zoomAnimated) {
\r
29093 map.on('zoomanim', this._animateZoom, this);
\r
29096 this._initIcon();
\r
29100 onRemove: function (map) {
\r
29101 if (this.dragging && this.dragging.enabled()) {
\r
29102 this.options.draggable = true;
\r
29103 this.dragging.removeHooks();
\r
29105 delete this.dragging;
\r
29107 if (this._zoomAnimated) {
\r
29108 map.off('zoomanim', this._animateZoom, this);
\r
29111 this._removeIcon();
\r
29112 this._removeShadow();
\r
29115 getEvents: function () {
\r
29117 zoom: this.update,
\r
29118 viewreset: this.update
\r
29122 // @method getLatLng: LatLng
\r
29123 // Returns the current geographical position of the marker.
\r
29124 getLatLng: function () {
\r
29125 return this._latlng;
\r
29128 // @method setLatLng(latlng: LatLng): this
\r
29129 // Changes the marker position to the given point.
\r
29130 setLatLng: function (latlng) {
\r
29131 var oldLatLng = this._latlng;
\r
29132 this._latlng = toLatLng(latlng);
\r
29135 // @event move: Event
\r
29136 // Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
\r
29137 return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
\r
29140 // @method setZIndexOffset(offset: Number): this
\r
29141 // Changes the [zIndex offset](#marker-zindexoffset) of the marker.
\r
29142 setZIndexOffset: function (offset) {
\r
29143 this.options.zIndexOffset = offset;
\r
29144 return this.update();
\r
29147 // @method getIcon: Icon
\r
29148 // Returns the current icon used by the marker
\r
29149 getIcon: function () {
\r
29150 return this.options.icon;
\r
29153 // @method setIcon(icon: Icon): this
\r
29154 // Changes the marker icon.
\r
29155 setIcon: function (icon) {
\r
29157 this.options.icon = icon;
\r
29160 this._initIcon();
\r
29164 if (this._popup) {
\r
29165 this.bindPopup(this._popup, this._popup.options);
\r
29171 getElement: function () {
\r
29172 return this._icon;
\r
29175 update: function () {
\r
29177 if (this._icon && this._map) {
\r
29178 var pos = this._map.latLngToLayerPoint(this._latlng).round();
\r
29179 this._setPos(pos);
\r
29185 _initIcon: function () {
\r
29186 var options = this.options,
\r
29187 classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');
\r
29189 var icon = options.icon.createIcon(this._icon),
\r
29192 // if we're not reusing the icon, remove the old one and init new one
\r
29193 if (icon !== this._icon) {
\r
29194 if (this._icon) {
\r
29195 this._removeIcon();
\r
29199 if (options.title) {
\r
29200 icon.title = options.title;
\r
29203 if (icon.tagName === 'IMG') {
\r
29204 icon.alt = options.alt || '';
\r
29208 addClass(icon, classToAdd);
\r
29210 if (options.keyboard) {
\r
29211 icon.tabIndex = '0';
\r
29214 this._icon = icon;
\r
29216 if (options.riseOnHover) {
\r
29218 mouseover: this._bringToFront,
\r
29219 mouseout: this._resetZIndex
\r
29223 var newShadow = options.icon.createShadow(this._shadow),
\r
29224 addShadow = false;
\r
29226 if (newShadow !== this._shadow) {
\r
29227 this._removeShadow();
\r
29228 addShadow = true;
\r
29232 addClass(newShadow, classToAdd);
\r
29233 newShadow.alt = '';
\r
29235 this._shadow = newShadow;
\r
29238 if (options.opacity < 1) {
\r
29239 this._updateOpacity();
\r
29244 this.getPane().appendChild(this._icon);
\r
29246 this._initInteraction();
\r
29247 if (newShadow && addShadow) {
\r
29248 this.getPane(options.shadowPane).appendChild(this._shadow);
\r
29252 _removeIcon: function () {
\r
29253 if (this.options.riseOnHover) {
\r
29255 mouseover: this._bringToFront,
\r
29256 mouseout: this._resetZIndex
\r
29260 remove(this._icon);
\r
29261 this.removeInteractiveTarget(this._icon);
\r
29263 this._icon = null;
\r
29266 _removeShadow: function () {
\r
29267 if (this._shadow) {
\r
29268 remove(this._shadow);
\r
29270 this._shadow = null;
\r
29273 _setPos: function (pos) {
\r
29275 if (this._icon) {
\r
29276 setPosition(this._icon, pos);
\r
29279 if (this._shadow) {
\r
29280 setPosition(this._shadow, pos);
\r
29283 this._zIndex = pos.y + this.options.zIndexOffset;
\r
29285 this._resetZIndex();
\r
29288 _updateZIndex: function (offset) {
\r
29289 if (this._icon) {
\r
29290 this._icon.style.zIndex = this._zIndex + offset;
\r
29294 _animateZoom: function (opt) {
\r
29295 var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
\r
29297 this._setPos(pos);
\r
29300 _initInteraction: function () {
\r
29302 if (!this.options.interactive) { return; }
\r
29304 addClass(this._icon, 'leaflet-interactive');
\r
29306 this.addInteractiveTarget(this._icon);
\r
29308 if (MarkerDrag) {
\r
29309 var draggable = this.options.draggable;
\r
29310 if (this.dragging) {
\r
29311 draggable = this.dragging.enabled();
\r
29312 this.dragging.disable();
\r
29315 this.dragging = new MarkerDrag(this);
\r
29318 this.dragging.enable();
\r
29323 // @method setOpacity(opacity: Number): this
\r
29324 // Changes the opacity of the marker.
\r
29325 setOpacity: function (opacity) {
\r
29326 this.options.opacity = opacity;
\r
29328 this._updateOpacity();
\r
29334 _updateOpacity: function () {
\r
29335 var opacity = this.options.opacity;
\r
29337 if (this._icon) {
\r
29338 setOpacity(this._icon, opacity);
\r
29341 if (this._shadow) {
\r
29342 setOpacity(this._shadow, opacity);
\r
29346 _bringToFront: function () {
\r
29347 this._updateZIndex(this.options.riseOffset);
\r
29350 _resetZIndex: function () {
\r
29351 this._updateZIndex(0);
\r
29354 _getPopupAnchor: function () {
\r
29355 return this.options.icon.options.popupAnchor;
\r
29358 _getTooltipAnchor: function () {
\r
29359 return this.options.icon.options.tooltipAnchor;
\r
29364 // factory L.marker(latlng: LatLng, options? : Marker options)
\r
29366 // @factory L.marker(latlng: LatLng, options? : Marker options)
\r
29367 // Instantiates a Marker object given a geographical point and optionally an options object.
\r
29368 function marker(latlng, options) {
\r
29369 return new Marker(latlng, options);
\r
29375 * @inherits Interactive layer
29377 * An abstract class that contains options and constants shared between vector
29378 * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.
29381 var Path = Layer.extend({
29384 // @aka Path options
29386 // @option stroke: Boolean = true
29387 // Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.
29390 // @option color: String = '#3388ff'
29394 // @option weight: Number = 3
29395 // Stroke width in pixels
29398 // @option opacity: Number = 1.0
29402 // @option lineCap: String= 'round'
29403 // A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.
29406 // @option lineJoin: String = 'round'
29407 // A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.
29410 // @option dashArray: String = null
29411 // A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
29414 // @option dashOffset: String = null
29415 // A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
29418 // @option fill: Boolean = depends
29419 // Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.
29422 // @option fillColor: String = *
29423 // Fill color. Defaults to the value of the [`color`](#path-color) option
29426 // @option fillOpacity: Number = 0.2
29430 // @option fillRule: String = 'evenodd'
29431 // A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.
29432 fillRule: 'evenodd',
29436 // Option inherited from "Interactive layer" abstract class
29439 // @option bubblingMouseEvents: Boolean = true
29440 // When `true`, a mouse event on this path will trigger the same event on the map
29441 // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
29442 bubblingMouseEvents: true
29445 beforeAdd: function (map) {
29446 // Renderer is set here because we need to call renderer.getEvents
29447 // before this.getEvents.
29448 this._renderer = map.getRenderer(this);
29451 onAdd: function () {
29452 this._renderer._initPath(this);
29454 this._renderer._addPath(this);
29457 onRemove: function () {
29458 this._renderer._removePath(this);
29461 // @method redraw(): this
29462 // Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.
29463 redraw: function () {
29465 this._renderer._updatePath(this);
29470 // @method setStyle(style: Path options): this
29471 // Changes the appearance of a Path based on the options in the `Path options` object.
29472 setStyle: function (style) {
29473 setOptions(this, style);
29474 if (this._renderer) {
29475 this._renderer._updateStyle(this);
29476 if (this.options.stroke && style && Object.prototype.hasOwnProperty.call(style, 'weight')) {
29477 this._updateBounds();
29483 // @method bringToFront(): this
29484 // Brings the layer to the top of all path layers.
29485 bringToFront: function () {
29486 if (this._renderer) {
29487 this._renderer._bringToFront(this);
29492 // @method bringToBack(): this
29493 // Brings the layer to the bottom of all path layers.
29494 bringToBack: function () {
29495 if (this._renderer) {
29496 this._renderer._bringToBack(this);
29501 getElement: function () {
29505 _reset: function () {
29506 // defined in child classes
29511 _clickTolerance: function () {
29512 // used when doing hit detection for Canvas layers
29513 return (this.options.stroke ? this.options.weight / 2 : 0) + this._renderer.options.tolerance;
29518 * @class CircleMarker
29519 * @aka L.CircleMarker
29522 * A circle of a fixed size with radius specified in pixels. Extends `Path`.
29525 var CircleMarker = Path.extend({
29528 // @aka CircleMarker options
29532 // @option radius: Number = 10
29533 // Radius of the circle marker, in pixels
29537 initialize: function (latlng, options) {
29538 setOptions(this, options);
29539 this._latlng = toLatLng(latlng);
29540 this._radius = this.options.radius;
29543 // @method setLatLng(latLng: LatLng): this
29544 // Sets the position of a circle marker to a new location.
29545 setLatLng: function (latlng) {
29546 var oldLatLng = this._latlng;
29547 this._latlng = toLatLng(latlng);
29550 // @event move: Event
29551 // Fired when the marker is moved via [`setLatLng`](#circlemarker-setlatlng). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
29552 return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
29555 // @method getLatLng(): LatLng
29556 // Returns the current geographical position of the circle marker
29557 getLatLng: function () {
29558 return this._latlng;
29561 // @method setRadius(radius: Number): this
29562 // Sets the radius of a circle marker. Units are in pixels.
29563 setRadius: function (radius) {
29564 this.options.radius = this._radius = radius;
29565 return this.redraw();
29568 // @method getRadius(): Number
29569 // Returns the current radius of the circle
29570 getRadius: function () {
29571 return this._radius;
29574 setStyle : function (options) {
29575 var radius = options && options.radius || this._radius;
29576 Path.prototype.setStyle.call(this, options);
29577 this.setRadius(radius);
29581 _project: function () {
29582 this._point = this._map.latLngToLayerPoint(this._latlng);
29583 this._updateBounds();
29586 _updateBounds: function () {
29587 var r = this._radius,
29588 r2 = this._radiusY || r,
29589 w = this._clickTolerance(),
29590 p = [r + w, r2 + w];
29591 this._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));
29594 _update: function () {
29596 this._updatePath();
29600 _updatePath: function () {
29601 this._renderer._updateCircle(this);
29604 _empty: function () {
29605 return this._radius && !this._renderer._bounds.intersects(this._pxBounds);
29608 // Needed by the `Canvas` renderer for interactivity
29609 _containsPoint: function (p) {
29610 return p.distanceTo(this._point) <= this._radius + this._clickTolerance();
29615 // @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)
29616 // Instantiates a circle marker object given a geographical point, and an optional options object.
29617 function circleMarker(latlng, options) {
29618 return new CircleMarker(latlng, options);
29624 * @inherits CircleMarker
29626 * A class for drawing circle overlays on a map. Extends `CircleMarker`.
29628 * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).
29633 * L.circle([50.5, 30.5], {radius: 200}).addTo(map);
29637 var Circle = CircleMarker.extend({
29639 initialize: function (latlng, options, legacyOptions) {
29640 if (typeof options === 'number') {
29641 // Backwards compatibility with 0.7.x factory (latlng, radius, options?)
29642 options = extend({}, legacyOptions, {radius: options});
29644 setOptions(this, options);
29645 this._latlng = toLatLng(latlng);
29647 if (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }
29650 // @aka Circle options
29651 // @option radius: Number; Radius of the circle, in meters.
29652 this._mRadius = this.options.radius;
29655 // @method setRadius(radius: Number): this
29656 // Sets the radius of a circle. Units are in meters.
29657 setRadius: function (radius) {
29658 this._mRadius = radius;
29659 return this.redraw();
29662 // @method getRadius(): Number
29663 // Returns the current radius of a circle. Units are in meters.
29664 getRadius: function () {
29665 return this._mRadius;
29668 // @method getBounds(): LatLngBounds
29669 // Returns the `LatLngBounds` of the path.
29670 getBounds: function () {
29671 var half = [this._radius, this._radiusY || this._radius];
29673 return new LatLngBounds(
29674 this._map.layerPointToLatLng(this._point.subtract(half)),
29675 this._map.layerPointToLatLng(this._point.add(half)));
29678 setStyle: Path.prototype.setStyle,
29680 _project: function () {
29682 var lng = this._latlng.lng,
29683 lat = this._latlng.lat,
29685 crs = map.options.crs;
29687 if (crs.distance === Earth.distance) {
29688 var d = Math.PI / 180,
29689 latR = (this._mRadius / Earth.R) / d,
29690 top = map.project([lat + latR, lng]),
29691 bottom = map.project([lat - latR, lng]),
29692 p = top.add(bottom).divideBy(2),
29693 lat2 = map.unproject(p).lat,
29694 lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /
29695 (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;
29697 if (isNaN(lngR) || lngR === 0) {
29698 lngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425
29701 this._point = p.subtract(map.getPixelOrigin());
29702 this._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
29703 this._radiusY = p.y - top.y;
29706 var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));
29708 this._point = map.latLngToLayerPoint(this._latlng);
29709 this._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;
29712 this._updateBounds();
29716 // @factory L.circle(latlng: LatLng, options?: Circle options)
29717 // Instantiates a circle object given a geographical point, and an options object
29718 // which contains the circle radius.
29720 // @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)
29721 // Obsolete way of instantiating a circle, for compatibility with 0.7.x code.
29722 // Do not use in new applications or plugins.
29723 function circle(latlng, options, legacyOptions) {
29724 return new Circle(latlng, options, legacyOptions);
29732 * A class for drawing polyline overlays on a map. Extends `Path`.
29737 * // create a red polyline from an array of LatLng points
29739 * [45.51, -122.68],
29740 * [37.77, -122.43],
29744 * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
29746 * // zoom the map to the polyline
29747 * map.fitBounds(polyline.getBounds());
29750 * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:
29753 * // create a red polyline from an array of arrays of LatLng points
29755 * [[45.51, -122.68],
29756 * [37.77, -122.43],
29757 * [34.04, -118.2]],
29758 * [[40.78, -73.91],
29766 var Polyline = Path.extend({
29769 // @aka Polyline options
29771 // @option smoothFactor: Number = 1.0
29772 // How much to simplify the polyline on each zoom level. More means
29773 // better performance and smoother look, and less means more accurate representation.
29776 // @option noClip: Boolean = false
29777 // Disable polyline clipping.
29781 initialize: function (latlngs, options) {
29782 setOptions(this, options);
29783 this._setLatLngs(latlngs);
29786 // @method getLatLngs(): LatLng[]
29787 // Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.
29788 getLatLngs: function () {
29789 return this._latlngs;
29792 // @method setLatLngs(latlngs: LatLng[]): this
29793 // Replaces all the points in the polyline with the given array of geographical points.
29794 setLatLngs: function (latlngs) {
29795 this._setLatLngs(latlngs);
29796 return this.redraw();
29799 // @method isEmpty(): Boolean
29800 // Returns `true` if the Polyline has no LatLngs.
29801 isEmpty: function () {
29802 return !this._latlngs.length;
29805 // @method closestLayerPoint(p: Point): Point
29806 // Returns the point closest to `p` on the Polyline.
29807 closestLayerPoint: function (p) {
29808 var minDistance = Infinity,
29810 closest = _sqClosestPointOnSegment,
29813 for (var j = 0, jLen = this._parts.length; j < jLen; j++) {
29814 var points = this._parts[j];
29816 for (var i = 1, len = points.length; i < len; i++) {
29817 p1 = points[i - 1];
29820 var sqDist = closest(p, p1, p2, true);
29822 if (sqDist < minDistance) {
29823 minDistance = sqDist;
29824 minPoint = closest(p, p1, p2);
29829 minPoint.distance = Math.sqrt(minDistance);
29834 // @method getCenter(): LatLng
29835 // Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline.
29836 getCenter: function () {
29837 // throws error when not yet added to map as this center calculation requires projected coordinates
29839 throw new Error('Must add layer to map before using getCenter()');
29842 var i, halfDist, segDist, dist, p1, p2, ratio,
29843 points = this._rings[0],
29844 len = points.length;
29846 if (!len) { return null; }
29848 // polyline centroid algorithm; only uses the first ring if there are multiple
29850 for (i = 0, halfDist = 0; i < len - 1; i++) {
29851 halfDist += points[i].distanceTo(points[i + 1]) / 2;
29854 // The line is so small in the current view that all points are on the same pixel.
29855 if (halfDist === 0) {
29856 return this._map.layerPointToLatLng(points[0]);
29859 for (i = 0, dist = 0; i < len - 1; i++) {
29861 p2 = points[i + 1];
29862 segDist = p1.distanceTo(p2);
29865 if (dist > halfDist) {
29866 ratio = (dist - halfDist) / segDist;
29867 return this._map.layerPointToLatLng([
29868 p2.x - ratio * (p2.x - p1.x),
29869 p2.y - ratio * (p2.y - p1.y)
29875 // @method getBounds(): LatLngBounds
29876 // Returns the `LatLngBounds` of the path.
29877 getBounds: function () {
29878 return this._bounds;
29881 // @method addLatLng(latlng: LatLng, latlngs?: LatLng[]): this
29882 // Adds a given point to the polyline. By default, adds to the first ring of
29883 // the polyline in case of a multi-polyline, but can be overridden by passing
29884 // a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).
29885 addLatLng: function (latlng, latlngs) {
29886 latlngs = latlngs || this._defaultShape();
29887 latlng = toLatLng(latlng);
29888 latlngs.push(latlng);
29889 this._bounds.extend(latlng);
29890 return this.redraw();
29893 _setLatLngs: function (latlngs) {
29894 this._bounds = new LatLngBounds();
29895 this._latlngs = this._convertLatLngs(latlngs);
29898 _defaultShape: function () {
29899 return isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];
29902 // recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
29903 _convertLatLngs: function (latlngs) {
29905 flat = isFlat(latlngs);
29907 for (var i = 0, len = latlngs.length; i < len; i++) {
29909 result[i] = toLatLng(latlngs[i]);
29910 this._bounds.extend(result[i]);
29912 result[i] = this._convertLatLngs(latlngs[i]);
29919 _project: function () {
29920 var pxBounds = new Bounds();
29922 this._projectLatlngs(this._latlngs, this._rings, pxBounds);
29924 if (this._bounds.isValid() && pxBounds.isValid()) {
29925 this._rawPxBounds = pxBounds;
29926 this._updateBounds();
29930 _updateBounds: function () {
29931 var w = this._clickTolerance(),
29932 p = new Point(w, w);
29933 this._pxBounds = new Bounds([
29934 this._rawPxBounds.min.subtract(p),
29935 this._rawPxBounds.max.add(p)
29939 // recursively turns latlngs into a set of rings with projected coordinates
29940 _projectLatlngs: function (latlngs, result, projectedBounds) {
29941 var flat = latlngs[0] instanceof LatLng,
29942 len = latlngs.length,
29947 for (i = 0; i < len; i++) {
29948 ring[i] = this._map.latLngToLayerPoint(latlngs[i]);
29949 projectedBounds.extend(ring[i]);
29953 for (i = 0; i < len; i++) {
29954 this._projectLatlngs(latlngs[i], result, projectedBounds);
29959 // clip polyline by renderer bounds so that we have less to render for performance
29960 _clipPoints: function () {
29961 var bounds = this._renderer._bounds;
29964 if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
29968 if (this.options.noClip) {
29969 this._parts = this._rings;
29973 var parts = this._parts,
29974 i, j, k, len, len2, segment, points;
29976 for (i = 0, k = 0, len = this._rings.length; i < len; i++) {
29977 points = this._rings[i];
29979 for (j = 0, len2 = points.length; j < len2 - 1; j++) {
29980 segment = clipSegment(points[j], points[j + 1], bounds, j, true);
29982 if (!segment) { continue; }
29984 parts[k] = parts[k] || [];
29985 parts[k].push(segment[0]);
29987 // if segment goes out of screen, or it's the last one, it's the end of the line part
29988 if ((segment[1] !== points[j + 1]) || (j === len2 - 2)) {
29989 parts[k].push(segment[1]);
29996 // simplify each clipped part of the polyline for performance
29997 _simplifyPoints: function () {
29998 var parts = this._parts,
29999 tolerance = this.options.smoothFactor;
30001 for (var i = 0, len = parts.length; i < len; i++) {
30002 parts[i] = simplify(parts[i], tolerance);
30006 _update: function () {
30007 if (!this._map) { return; }
30009 this._clipPoints();
30010 this._simplifyPoints();
30011 this._updatePath();
30014 _updatePath: function () {
30015 this._renderer._updatePoly(this);
30018 // Needed by the `Canvas` renderer for interactivity
30019 _containsPoint: function (p, closed) {
30020 var i, j, k, len, len2, part,
30021 w = this._clickTolerance();
30023 if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }
30025 // hit detection for polylines
30026 for (i = 0, len = this._parts.length; i < len; i++) {
30027 part = this._parts[i];
30029 for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
30030 if (!closed && (j === 0)) { continue; }
30032 if (pointToSegmentDistance(p, part[k], part[j]) <= w) {
30041 // @factory L.polyline(latlngs: LatLng[], options?: Polyline options)
30042 // Instantiates a polyline object given an array of geographical points and
30043 // optionally an options object. You can create a `Polyline` object with
30044 // multiple separate lines (`MultiPolyline`) by passing an array of arrays
30045 // of geographic points.
30046 function polyline(latlngs, options) {
30047 return new Polyline(latlngs, options);
30050 // Retrocompat. Allow plugins to support Leaflet versions before and after 1.1.
30051 Polyline._flat = _flat;
30056 * @inherits Polyline
30058 * A class for drawing polygon overlays on a map. Extends `Polyline`.
30060 * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.
30066 * // create a red polygon from an array of LatLng points
30067 * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
30069 * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
30071 * // zoom the map to the polygon
30072 * map.fitBounds(polygon.getBounds());
30075 * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:
30079 * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
30080 * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
30084 * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.
30088 * [ // first polygon
30089 * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
30090 * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
30092 * [ // second polygon
30093 * [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
30099 var Polygon = Polyline.extend({
30105 isEmpty: function () {
30106 return !this._latlngs.length || !this._latlngs[0].length;
30109 getCenter: function () {
30110 // throws error when not yet added to map as this center calculation requires projected coordinates
30112 throw new Error('Must add layer to map before using getCenter()');
30115 var i, j, p1, p2, f, area, x, y, center,
30116 points = this._rings[0],
30117 len = points.length;
30119 if (!len) { return null; }
30121 // polygon centroid algorithm; only uses the first ring if there are multiple
30125 for (i = 0, j = len - 1; i < len; j = i++) {
30129 f = p1.y * p2.x - p2.y * p1.x;
30130 x += (p1.x + p2.x) * f;
30131 y += (p1.y + p2.y) * f;
30136 // Polygon is so small that all points are on same pixel.
30137 center = points[0];
30139 center = [x / area, y / area];
30141 return this._map.layerPointToLatLng(center);
30144 _convertLatLngs: function (latlngs) {
30145 var result = Polyline.prototype._convertLatLngs.call(this, latlngs),
30146 len = result.length;
30148 // remove last point if it equals first one
30149 if (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) {
30155 _setLatLngs: function (latlngs) {
30156 Polyline.prototype._setLatLngs.call(this, latlngs);
30157 if (isFlat(this._latlngs)) {
30158 this._latlngs = [this._latlngs];
30162 _defaultShape: function () {
30163 return isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];
30166 _clipPoints: function () {
30167 // polygons need a different clipping algorithm so we redefine that
30169 var bounds = this._renderer._bounds,
30170 w = this.options.weight,
30171 p = new Point(w, w);
30173 // increase clip padding by stroke width to avoid stroke on clip edges
30174 bounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));
30177 if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
30181 if (this.options.noClip) {
30182 this._parts = this._rings;
30186 for (var i = 0, len = this._rings.length, clipped; i < len; i++) {
30187 clipped = clipPolygon(this._rings[i], bounds, true);
30188 if (clipped.length) {
30189 this._parts.push(clipped);
30194 _updatePath: function () {
30195 this._renderer._updatePoly(this, true);
30198 // Needed by the `Canvas` renderer for interactivity
30199 _containsPoint: function (p) {
30200 var inside = false,
30201 part, p1, p2, i, j, k, len, len2;
30203 if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }
30205 // ray casting algorithm for detecting if point is in polygon
30206 for (i = 0, len = this._parts.length; i < len; i++) {
30207 part = this._parts[i];
30209 for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
30213 if (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
30219 // also check if it's on polygon stroke
30220 return inside || Polyline.prototype._containsPoint.call(this, p, true);
30226 // @factory L.polygon(latlngs: LatLng[], options?: Polyline options)
30227 function polygon(latlngs, options) {
30228 return new Polygon(latlngs, options);
30234 * @inherits FeatureGroup
\r
30236 * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse
\r
30237 * GeoJSON data and display it on the map. Extends `FeatureGroup`.
\r
30242 * L.geoJSON(data, {
\r
30243 * style: function (feature) {
\r
30244 * return {color: feature.properties.color};
\r
30246 * }).bindPopup(function (layer) {
\r
30247 * return layer.feature.properties.description;
\r
30252 var GeoJSON = FeatureGroup.extend({
\r
30255 * @aka GeoJSON options
\r
30257 * @option pointToLayer: Function = *
\r
30258 * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally
\r
30259 * called when data is added, passing the GeoJSON point feature and its `LatLng`.
\r
30260 * The default is to spawn a default `Marker`:
\r
30262 * function(geoJsonPoint, latlng) {
\r
30263 * return L.marker(latlng);
\r
30267 * @option style: Function = *
\r
30268 * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,
\r
30269 * called internally when data is added.
\r
30270 * The default value is to not override any defaults:
\r
30272 * function (geoJsonFeature) {
\r
30277 * @option onEachFeature: Function = *
\r
30278 * A `Function` that will be called once for each created `Feature`, after it has
\r
30279 * been created and styled. Useful for attaching events and popups to features.
\r
30280 * The default is to do nothing with the newly created layers:
\r
30282 * function (feature, layer) {}
\r
30285 * @option filter: Function = *
\r
30286 * A `Function` that will be used to decide whether to include a feature or not.
\r
30287 * The default is to include all features:
\r
30289 * function (geoJsonFeature) {
\r
30293 * Note: dynamically changing the `filter` option will have effect only on newly
\r
30294 * added data. It will _not_ re-evaluate already included features.
\r
30296 * @option coordsToLatLng: Function = *
\r
30297 * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s.
\r
30298 * The default is the `coordsToLatLng` static method.
\r
30300 * @option markersInheritOptions: Boolean = false
\r
30301 * Whether default Markers for "Point" type Features inherit from group options.
\r
30304 initialize: function (geojson, options) {
\r
30305 setOptions(this, options);
\r
30307 this._layers = {};
\r
30310 this.addData(geojson);
\r
30314 // @method addData( <GeoJSON> data ): this
\r
30315 // Adds a GeoJSON object to the layer.
\r
30316 addData: function (geojson) {
\r
30317 var features = isArray(geojson) ? geojson : geojson.features,
\r
30321 for (i = 0, len = features.length; i < len; i++) {
\r
30322 // only add this if geometry or geometries are set and not null
\r
30323 feature = features[i];
\r
30324 if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
\r
30325 this.addData(feature);
\r
30331 var options = this.options;
\r
30333 if (options.filter && !options.filter(geojson)) { return this; }
\r
30335 var layer = geometryToLayer(geojson, options);
\r
30339 layer.feature = asFeature(geojson);
\r
30341 layer.defaultOptions = layer.options;
\r
30342 this.resetStyle(layer);
\r
30344 if (options.onEachFeature) {
\r
30345 options.onEachFeature(geojson, layer);
\r
30348 return this.addLayer(layer);
\r
30351 // @method resetStyle( <Path> layer? ): this
\r
30352 // Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.
\r
30353 // If `layer` is omitted, the style of all features in the current layer is reset.
\r
30354 resetStyle: function (layer) {
\r
30355 if (layer === undefined) {
\r
30356 return this.eachLayer(this.resetStyle, this);
\r
30358 // reset any custom styles
\r
30359 layer.options = extend({}, layer.defaultOptions);
\r
30360 this._setLayerStyle(layer, this.options.style);
\r
30364 // @method setStyle( <Function> style ): this
\r
30365 // Changes styles of GeoJSON vector layers with the given style function.
\r
30366 setStyle: function (style) {
\r
30367 return this.eachLayer(function (layer) {
\r
30368 this._setLayerStyle(layer, style);
\r
30372 _setLayerStyle: function (layer, style) {
\r
30373 if (layer.setStyle) {
\r
30374 if (typeof style === 'function') {
\r
30375 style = style(layer.feature);
\r
30377 layer.setStyle(style);
\r
30383 // There are several static functions which can be called without instantiating L.GeoJSON:
\r
30385 // @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer
\r
30386 // Creates a `Layer` from a given GeoJSON feature. Can use a custom
\r
30387 // [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng)
\r
30388 // functions if provided as options.
\r
30389 function geometryToLayer(geojson, options) {
\r
30391 var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
\r
30392 coords = geometry ? geometry.coordinates : null,
\r
30394 pointToLayer = options && options.pointToLayer,
\r
30395 _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng,
\r
30396 latlng, latlngs, i, len;
\r
30398 if (!coords && !geometry) {
\r
30402 switch (geometry.type) {
\r
30404 latlng = _coordsToLatLng(coords);
\r
30405 return _pointToLayer(pointToLayer, geojson, latlng, options);
\r
30407 case 'MultiPoint':
\r
30408 for (i = 0, len = coords.length; i < len; i++) {
\r
30409 latlng = _coordsToLatLng(coords[i]);
\r
30410 layers.push(_pointToLayer(pointToLayer, geojson, latlng, options));
\r
30412 return new FeatureGroup(layers);
\r
30414 case 'LineString':
\r
30415 case 'MultiLineString':
\r
30416 latlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng);
\r
30417 return new Polyline(latlngs, options);
\r
30420 case 'MultiPolygon':
\r
30421 latlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng);
\r
30422 return new Polygon(latlngs, options);
\r
30424 case 'GeometryCollection':
\r
30425 for (i = 0, len = geometry.geometries.length; i < len; i++) {
\r
30426 var layer = geometryToLayer({
\r
30427 geometry: geometry.geometries[i],
\r
30429 properties: geojson.properties
\r
30433 layers.push(layer);
\r
30436 return new FeatureGroup(layers);
\r
30439 throw new Error('Invalid GeoJSON object.');
\r
30443 function _pointToLayer(pointToLayerFn, geojson, latlng, options) {
\r
30444 return pointToLayerFn ?
\r
30445 pointToLayerFn(geojson, latlng) :
\r
30446 new Marker(latlng, options && options.markersInheritOptions && options);
\r
30449 // @function coordsToLatLng(coords: Array): LatLng
\r
30450 // Creates a `LatLng` object from an array of 2 numbers (longitude, latitude)
\r
30451 // or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
\r
30452 function coordsToLatLng(coords) {
\r
30453 return new LatLng(coords[1], coords[0], coords[2]);
\r
30456 // @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array
\r
30457 // Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array.
\r
30458 // `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default).
\r
30459 // Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function.
\r
30460 function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
\r
30461 var latlngs = [];
\r
30463 for (var i = 0, len = coords.length, latlng; i < len; i++) {
\r
30464 latlng = levelsDeep ?
\r
30465 coordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) :
\r
30466 (_coordsToLatLng || coordsToLatLng)(coords[i]);
\r
30468 latlngs.push(latlng);
\r
30474 // @function latLngToCoords(latlng: LatLng, precision?: Number): Array
\r
30475 // Reverse of [`coordsToLatLng`](#geojson-coordstolatlng)
\r
30476 function latLngToCoords(latlng, precision) {
\r
30477 precision = typeof precision === 'number' ? precision : 6;
\r
30478 return latlng.alt !== undefined ?
\r
30479 [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] :
\r
30480 [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];
\r
30483 // @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array
\r
30484 // Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs)
\r
30485 // `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default.
\r
30486 function latLngsToCoords(latlngs, levelsDeep, closed, precision) {
\r
30489 for (var i = 0, len = latlngs.length; i < len; i++) {
\r
30490 coords.push(levelsDeep ?
\r
30491 latLngsToCoords(latlngs[i], levelsDeep - 1, closed, precision) :
\r
30492 latLngToCoords(latlngs[i], precision));
\r
30495 if (!levelsDeep && closed) {
\r
30496 coords.push(coords[0]);
\r
30502 function getFeature(layer, newGeometry) {
\r
30503 return layer.feature ?
\r
30504 extend({}, layer.feature, {geometry: newGeometry}) :
\r
30505 asFeature(newGeometry);
\r
30508 // @function asFeature(geojson: Object): Object
\r
30509 // Normalize GeoJSON geometries/features into GeoJSON features.
\r
30510 function asFeature(geojson) {
\r
30511 if (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') {
\r
30518 geometry: geojson
\r
30522 var PointToGeoJSON = {
\r
30523 toGeoJSON: function (precision) {
\r
30524 return getFeature(this, {
\r
30526 coordinates: latLngToCoords(this.getLatLng(), precision)
\r
30531 // @namespace Marker
\r
30532 // @section Other methods
\r
30533 // @method toGeoJSON(precision?: Number): Object
\r
30534 // `precision` is the number of decimal places for coordinates.
\r
30535 // The default value is 6 places.
\r
30536 // Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature).
\r
30537 Marker.include(PointToGeoJSON);
\r
30539 // @namespace CircleMarker
\r
30540 // @method toGeoJSON(precision?: Number): Object
\r
30541 // `precision` is the number of decimal places for coordinates.
\r
30542 // The default value is 6 places.
\r
30543 // Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature).
\r
30544 Circle.include(PointToGeoJSON);
\r
30545 CircleMarker.include(PointToGeoJSON);
\r
30548 // @namespace Polyline
\r
30549 // @method toGeoJSON(precision?: Number): Object
\r
30550 // `precision` is the number of decimal places for coordinates.
\r
30551 // The default value is 6 places.
\r
30552 // Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature).
\r
30553 Polyline.include({
\r
30554 toGeoJSON: function (precision) {
\r
30555 var multi = !isFlat(this._latlngs);
\r
30557 var coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);
\r
30559 return getFeature(this, {
\r
30560 type: (multi ? 'Multi' : '') + 'LineString',
\r
30561 coordinates: coords
\r
30566 // @namespace Polygon
\r
30567 // @method toGeoJSON(precision?: Number): Object
\r
30568 // `precision` is the number of decimal places for coordinates.
\r
30569 // The default value is 6 places.
\r
30570 // Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature).
\r
30571 Polygon.include({
\r
30572 toGeoJSON: function (precision) {
\r
30573 var holes = !isFlat(this._latlngs),
\r
30574 multi = holes && !isFlat(this._latlngs[0]);
\r
30576 var coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);
\r
30579 coords = [coords];
\r
30582 return getFeature(this, {
\r
30583 type: (multi ? 'Multi' : '') + 'Polygon',
\r
30584 coordinates: coords
\r
30590 // @namespace LayerGroup
\r
30591 LayerGroup.include({
\r
30592 toMultiPoint: function (precision) {
\r
30595 this.eachLayer(function (layer) {
\r
30596 coords.push(layer.toGeoJSON(precision).geometry.coordinates);
\r
30599 return getFeature(this, {
\r
30600 type: 'MultiPoint',
\r
30601 coordinates: coords
\r
30605 // @method toGeoJSON(precision?: Number): Object
\r
30606 // `precision` is the number of decimal places for coordinates.
\r
30607 // The default value is 6 places.
\r
30608 // Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`).
\r
30609 toGeoJSON: function (precision) {
\r
30611 var type = this.feature && this.feature.geometry && this.feature.geometry.type;
\r
30613 if (type === 'MultiPoint') {
\r
30614 return this.toMultiPoint(precision);
\r
30617 var isGeometryCollection = type === 'GeometryCollection',
\r
30620 this.eachLayer(function (layer) {
\r
30621 if (layer.toGeoJSON) {
\r
30622 var json = layer.toGeoJSON(precision);
\r
30623 if (isGeometryCollection) {
\r
30624 jsons.push(json.geometry);
\r
30626 var feature = asFeature(json);
\r
30627 // Squash nested feature collections
\r
30628 if (feature.type === 'FeatureCollection') {
\r
30629 jsons.push.apply(jsons, feature.features);
\r
30631 jsons.push(feature);
\r
30637 if (isGeometryCollection) {
\r
30638 return getFeature(this, {
\r
30639 geometries: jsons,
\r
30640 type: 'GeometryCollection'
\r
30645 type: 'FeatureCollection',
\r
30651 // @namespace GeoJSON
\r
30652 // @factory L.geoJSON(geojson?: Object, options?: GeoJSON options)
\r
30653 // Creates a GeoJSON layer. Optionally accepts an object in
\r
30654 // [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map
\r
30655 // (you can alternatively add it later with `addData` method) and an `options` object.
\r
30656 function geoJSON(geojson, options) {
\r
30657 return new GeoJSON(geojson, options);
\r
30660 // Backward compatibility.
\r
30661 var geoJson = geoJSON;
30664 * @class ImageOverlay
\r
30665 * @aka L.ImageOverlay
\r
30666 * @inherits Interactive layer
\r
30668 * Used to load and display a single image over specific bounds of the map. Extends `Layer`.
\r
30673 * var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
\r
30674 * imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
\r
30675 * L.imageOverlay(imageUrl, imageBounds).addTo(map);
\r
30679 var ImageOverlay = Layer.extend({
\r
30682 // @aka ImageOverlay options
\r
30684 // @option opacity: Number = 1.0
\r
30685 // The opacity of the image overlay.
\r
30688 // @option alt: String = ''
\r
30689 // Text for the `alt` attribute of the image (useful for accessibility).
\r
30692 // @option interactive: Boolean = false
\r
30693 // If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered.
\r
30694 interactive: false,
\r
30696 // @option crossOrigin: Boolean|String = false
\r
30697 // Whether the crossOrigin attribute will be added to the image.
\r
30698 // If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data.
\r
30699 // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
\r
30700 crossOrigin: false,
\r
30702 // @option errorOverlayUrl: String = ''
\r
30703 // URL to the overlay image to show in place of the overlay that failed to load.
\r
30704 errorOverlayUrl: '',
\r
30706 // @option zIndex: Number = 1
\r
30707 // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer.
\r
30710 // @option className: String = ''
\r
30711 // A custom class name to assign to the image. Empty by default.
\r
30715 initialize: function (url, bounds, options) { // (String, LatLngBounds, Object)
\r
30717 this._bounds = toLatLngBounds(bounds);
\r
30719 setOptions(this, options);
\r
30722 onAdd: function () {
\r
30723 if (!this._image) {
\r
30724 this._initImage();
\r
30726 if (this.options.opacity < 1) {
\r
30727 this._updateOpacity();
\r
30731 if (this.options.interactive) {
\r
30732 addClass(this._image, 'leaflet-interactive');
\r
30733 this.addInteractiveTarget(this._image);
\r
30736 this.getPane().appendChild(this._image);
\r
30740 onRemove: function () {
\r
30741 remove(this._image);
\r
30742 if (this.options.interactive) {
\r
30743 this.removeInteractiveTarget(this._image);
\r
30747 // @method setOpacity(opacity: Number): this
\r
30748 // Sets the opacity of the overlay.
\r
30749 setOpacity: function (opacity) {
\r
30750 this.options.opacity = opacity;
\r
30752 if (this._image) {
\r
30753 this._updateOpacity();
\r
30758 setStyle: function (styleOpts) {
\r
30759 if (styleOpts.opacity) {
\r
30760 this.setOpacity(styleOpts.opacity);
\r
30765 // @method bringToFront(): this
\r
30766 // Brings the layer to the top of all overlays.
\r
30767 bringToFront: function () {
\r
30769 toFront(this._image);
\r
30774 // @method bringToBack(): this
\r
30775 // Brings the layer to the bottom of all overlays.
\r
30776 bringToBack: function () {
\r
30778 toBack(this._image);
\r
30783 // @method setUrl(url: String): this
\r
30784 // Changes the URL of the image.
\r
30785 setUrl: function (url) {
\r
30788 if (this._image) {
\r
30789 this._image.src = url;
\r
30794 // @method setBounds(bounds: LatLngBounds): this
\r
30795 // Update the bounds that this ImageOverlay covers
\r
30796 setBounds: function (bounds) {
\r
30797 this._bounds = toLatLngBounds(bounds);
\r
30805 getEvents: function () {
\r
30807 zoom: this._reset,
\r
30808 viewreset: this._reset
\r
30811 if (this._zoomAnimated) {
\r
30812 events.zoomanim = this._animateZoom;
\r
30818 // @method setZIndex(value: Number): this
\r
30819 // Changes the [zIndex](#imageoverlay-zindex) of the image overlay.
\r
30820 setZIndex: function (value) {
\r
30821 this.options.zIndex = value;
\r
30822 this._updateZIndex();
\r
30826 // @method getBounds(): LatLngBounds
\r
30827 // Get the bounds that this ImageOverlay covers
\r
30828 getBounds: function () {
\r
30829 return this._bounds;
\r
30832 // @method getElement(): HTMLElement
\r
30833 // Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement)
\r
30834 // used by this overlay.
\r
30835 getElement: function () {
\r
30836 return this._image;
\r
30839 _initImage: function () {
\r
30840 var wasElementSupplied = this._url.tagName === 'IMG';
\r
30841 var img = this._image = wasElementSupplied ? this._url : create$1('img');
\r
30843 addClass(img, 'leaflet-image-layer');
\r
30844 if (this._zoomAnimated) { addClass(img, 'leaflet-zoom-animated'); }
\r
30845 if (this.options.className) { addClass(img, this.options.className); }
\r
30847 img.onselectstart = falseFn;
\r
30848 img.onmousemove = falseFn;
\r
30850 // @event load: Event
\r
30851 // Fired when the ImageOverlay layer has loaded its image
\r
30852 img.onload = bind(this.fire, this, 'load');
\r
30853 img.onerror = bind(this._overlayOnError, this, 'error');
\r
30855 if (this.options.crossOrigin || this.options.crossOrigin === '') {
\r
30856 img.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
\r
30859 if (this.options.zIndex) {
\r
30860 this._updateZIndex();
\r
30863 if (wasElementSupplied) {
\r
30864 this._url = img.src;
\r
30868 img.src = this._url;
\r
30869 img.alt = this.options.alt;
\r
30872 _animateZoom: function (e) {
\r
30873 var scale = this._map.getZoomScale(e.zoom),
\r
30874 offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min;
\r
30876 setTransform(this._image, offset, scale);
\r
30879 _reset: function () {
\r
30880 var image = this._image,
\r
30881 bounds = new Bounds(
\r
30882 this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
\r
30883 this._map.latLngToLayerPoint(this._bounds.getSouthEast())),
\r
30884 size = bounds.getSize();
\r
30886 setPosition(image, bounds.min);
\r
30888 image.style.width = size.x + 'px';
\r
30889 image.style.height = size.y + 'px';
\r
30892 _updateOpacity: function () {
\r
30893 setOpacity(this._image, this.options.opacity);
\r
30896 _updateZIndex: function () {
\r
30897 if (this._image && this.options.zIndex !== undefined && this.options.zIndex !== null) {
\r
30898 this._image.style.zIndex = this.options.zIndex;
\r
30902 _overlayOnError: function () {
\r
30903 // @event error: Event
\r
30904 // Fired when the ImageOverlay layer fails to load its image
\r
30905 this.fire('error');
\r
30907 var errorUrl = this.options.errorOverlayUrl;
\r
30908 if (errorUrl && this._url !== errorUrl) {
\r
30909 this._url = errorUrl;
\r
30910 this._image.src = errorUrl;
\r
30915 // @factory L.imageOverlay(imageUrl: String, bounds: LatLngBounds, options?: ImageOverlay options)
\r
30916 // Instantiates an image overlay object given the URL of the image and the
\r
30917 // geographical bounds it is tied to.
\r
30918 var imageOverlay = function (url, bounds, options) {
\r
30919 return new ImageOverlay(url, bounds, options);
\r
30923 * @class VideoOverlay
\r
30924 * @aka L.VideoOverlay
\r
30925 * @inherits ImageOverlay
\r
30927 * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`.
\r
30929 * A video overlay uses the [`<video>`](https://developer.mozilla.org/docs/Web/HTML/Element/video)
\r
30935 * var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
\r
30936 * videoBounds = [[ 32, -130], [ 13, -100]];
\r
30937 * L.videoOverlay(videoUrl, videoBounds ).addTo(map);
\r
30941 var VideoOverlay = ImageOverlay.extend({
\r
30944 // @aka VideoOverlay options
\r
30946 // @option autoplay: Boolean = true
\r
30947 // Whether the video starts playing automatically when loaded.
\r
30950 // @option loop: Boolean = true
\r
30951 // Whether the video will loop back to the beginning when played.
\r
30954 // @option keepAspectRatio: Boolean = true
\r
30955 // Whether the video will save aspect ratio after the projection.
\r
30956 // Relevant for supported browsers. Browser compatibility- https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
\r
30957 keepAspectRatio: true,
\r
30959 // @option muted: Boolean = false
\r
30960 // Whether the video starts on mute when loaded.
\r
30964 _initImage: function () {
\r
30965 var wasElementSupplied = this._url.tagName === 'VIDEO';
\r
30966 var vid = this._image = wasElementSupplied ? this._url : create$1('video');
\r
30968 addClass(vid, 'leaflet-image-layer');
\r
30969 if (this._zoomAnimated) { addClass(vid, 'leaflet-zoom-animated'); }
\r
30970 if (this.options.className) { addClass(vid, this.options.className); }
\r
30972 vid.onselectstart = falseFn;
\r
30973 vid.onmousemove = falseFn;
\r
30975 // @event load: Event
\r
30976 // Fired when the video has finished loading the first frame
\r
30977 vid.onloadeddata = bind(this.fire, this, 'load');
\r
30979 if (wasElementSupplied) {
\r
30980 var sourceElements = vid.getElementsByTagName('source');
\r
30981 var sources = [];
\r
30982 for (var j = 0; j < sourceElements.length; j++) {
\r
30983 sources.push(sourceElements[j].src);
\r
30986 this._url = (sourceElements.length > 0) ? sources : [vid.src];
\r
30990 if (!isArray(this._url)) { this._url = [this._url]; }
\r
30992 if (!this.options.keepAspectRatio && Object.prototype.hasOwnProperty.call(vid.style, 'objectFit')) {
\r
30993 vid.style['objectFit'] = 'fill';
\r
30995 vid.autoplay = !!this.options.autoplay;
\r
30996 vid.loop = !!this.options.loop;
\r
30997 vid.muted = !!this.options.muted;
\r
30998 for (var i = 0; i < this._url.length; i++) {
\r
30999 var source = create$1('source');
\r
31000 source.src = this._url[i];
\r
31001 vid.appendChild(source);
\r
31005 // @method getElement(): HTMLVideoElement
\r
31006 // Returns the instance of [`HTMLVideoElement`](https://developer.mozilla.org/docs/Web/API/HTMLVideoElement)
\r
31007 // used by this overlay.
\r
31011 // @factory L.videoOverlay(video: String|Array|HTMLVideoElement, bounds: LatLngBounds, options?: VideoOverlay options)
\r
31012 // Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the
\r
31013 // geographical bounds it is tied to.
\r
31015 function videoOverlay(video, bounds, options) {
\r
31016 return new VideoOverlay(video, bounds, options);
\r
31020 * @class SVGOverlay
31021 * @aka L.SVGOverlay
31022 * @inherits ImageOverlay
31024 * Used to load, display and provide DOM access to an SVG file over specific bounds of the map. Extends `ImageOverlay`.
31026 * An SVG overlay uses the [`<svg>`](https://developer.mozilla.org/docs/Web/SVG/Element/svg) element.
31031 * var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
31032 * svgElement.setAttribute('xmlns', "http://www.w3.org/2000/svg");
31033 * svgElement.setAttribute('viewBox', "0 0 200 200");
31034 * svgElement.innerHTML = '<rect width="200" height="200"/><rect x="75" y="23" width="50" height="50" style="fill:red"/><rect x="75" y="123" width="50" height="50" style="fill:#0013ff"/>';
31035 * var svgElementBounds = [ [ 32, -130 ], [ 13, -100 ] ];
31036 * L.svgOverlay(svgElement, svgElementBounds).addTo(map);
31040 var SVGOverlay = ImageOverlay.extend({
31041 _initImage: function () {
31042 var el = this._image = this._url;
31044 addClass(el, 'leaflet-image-layer');
31045 if (this._zoomAnimated) { addClass(el, 'leaflet-zoom-animated'); }
31046 if (this.options.className) { addClass(el, this.options.className); }
31048 el.onselectstart = falseFn;
31049 el.onmousemove = falseFn;
31052 // @method getElement(): SVGElement
31053 // Returns the instance of [`SVGElement`](https://developer.mozilla.org/docs/Web/API/SVGElement)
31054 // used by this overlay.
31058 // @factory L.svgOverlay(svg: String|SVGElement, bounds: LatLngBounds, options?: SVGOverlay options)
31059 // Instantiates an image overlay object given an SVG element and the geographical bounds it is tied to.
31060 // A viewBox attribute is required on the SVG element to zoom in and out properly.
31062 function svgOverlay(el, bounds, options) {
31063 return new SVGOverlay(el, bounds, options);
31067 * @class DivOverlay
\r
31068 * @inherits Layer
\r
31069 * @aka L.DivOverlay
\r
31070 * Base model for L.Popup and L.Tooltip. Inherit from it for custom popup like plugins.
\r
31073 // @namespace DivOverlay
\r
31074 var DivOverlay = Layer.extend({
\r
31077 // @aka DivOverlay options
\r
31079 // @option offset: Point = Point(0, 7)
\r
31080 // The offset of the popup position. Useful to control the anchor
\r
31081 // of the popup when opening it on some overlays.
\r
31084 // @option className: String = ''
\r
31085 // A custom CSS class name to assign to the popup.
\r
31088 // @option pane: String = 'popupPane'
\r
31089 // `Map pane` where the popup will be added.
\r
31090 pane: 'popupPane'
\r
31093 initialize: function (options, source) {
\r
31094 setOptions(this, options);
\r
31096 this._source = source;
\r
31099 onAdd: function (map) {
\r
31100 this._zoomAnimated = map._zoomAnimated;
\r
31102 if (!this._container) {
\r
31103 this._initLayout();
\r
31106 if (map._fadeAnimated) {
\r
31107 setOpacity(this._container, 0);
\r
31110 clearTimeout(this._removeTimeout);
\r
31111 this.getPane().appendChild(this._container);
\r
31114 if (map._fadeAnimated) {
\r
31115 setOpacity(this._container, 1);
\r
31118 this.bringToFront();
\r
31121 onRemove: function (map) {
\r
31122 if (map._fadeAnimated) {
\r
31123 setOpacity(this._container, 0);
\r
31124 this._removeTimeout = setTimeout(bind(remove, undefined, this._container), 200);
\r
31126 remove(this._container);
\r
31130 // @namespace Popup
\r
31131 // @method getLatLng: LatLng
\r
31132 // Returns the geographical point of popup.
\r
31133 getLatLng: function () {
\r
31134 return this._latlng;
\r
31137 // @method setLatLng(latlng: LatLng): this
\r
31138 // Sets the geographical point where the popup will open.
\r
31139 setLatLng: function (latlng) {
\r
31140 this._latlng = toLatLng(latlng);
\r
31142 this._updatePosition();
\r
31143 this._adjustPan();
\r
31148 // @method getContent: String|HTMLElement
\r
31149 // Returns the content of the popup.
\r
31150 getContent: function () {
\r
31151 return this._content;
\r
31154 // @method setContent(htmlContent: String|HTMLElement|Function): this
\r
31155 // Sets the HTML content of the popup. If a function is passed the source layer will be passed to the function. The function should return a `String` or `HTMLElement` to be used in the popup.
\r
31156 setContent: function (content) {
\r
31157 this._content = content;
\r
31162 // @method getElement: String|HTMLElement
\r
31163 // Returns the HTML container of the popup.
\r
31164 getElement: function () {
\r
31165 return this._container;
\r
31168 // @method update: null
\r
31169 // Updates the popup content, layout and position. Useful for updating the popup after something inside changed, e.g. image loaded.
\r
31170 update: function () {
\r
31171 if (!this._map) { return; }
\r
31173 this._container.style.visibility = 'hidden';
\r
31175 this._updateContent();
\r
31176 this._updateLayout();
\r
31177 this._updatePosition();
\r
31179 this._container.style.visibility = '';
\r
31181 this._adjustPan();
\r
31184 getEvents: function () {
\r
31186 zoom: this._updatePosition,
\r
31187 viewreset: this._updatePosition
\r
31190 if (this._zoomAnimated) {
\r
31191 events.zoomanim = this._animateZoom;
\r
31196 // @method isOpen: Boolean
\r
31197 // Returns `true` when the popup is visible on the map.
\r
31198 isOpen: function () {
\r
31199 return !!this._map && this._map.hasLayer(this);
\r
31202 // @method bringToFront: this
\r
31203 // Brings this popup in front of other popups (in the same map pane).
\r
31204 bringToFront: function () {
\r
31206 toFront(this._container);
\r
31211 // @method bringToBack: this
\r
31212 // Brings this popup to the back of other popups (in the same map pane).
\r
31213 bringToBack: function () {
\r
31215 toBack(this._container);
\r
31220 _prepareOpen: function (parent, layer, latlng) {
\r
31221 if (!(layer instanceof Layer)) {
\r
31226 if (layer instanceof FeatureGroup) {
\r
31227 for (var id in parent._layers) {
\r
31228 layer = parent._layers[id];
\r
31234 if (layer.getCenter) {
\r
31235 latlng = layer.getCenter();
\r
31236 } else if (layer.getLatLng) {
\r
31237 latlng = layer.getLatLng();
\r
31239 throw new Error('Unable to get source layer LatLng.');
\r
31243 // set overlay source to this layer
\r
31244 this._source = layer;
\r
31246 // update the overlay (content, layout, ect...)
\r
31252 _updateContent: function () {
\r
31253 if (!this._content) { return; }
\r
31255 var node = this._contentNode;
\r
31256 var content = (typeof this._content === 'function') ? this._content(this._source || this) : this._content;
\r
31258 if (typeof content === 'string') {
\r
31259 node.innerHTML = content;
\r
31261 while (node.hasChildNodes()) {
\r
31262 node.removeChild(node.firstChild);
\r
31264 node.appendChild(content);
\r
31266 this.fire('contentupdate');
\r
31269 _updatePosition: function () {
\r
31270 if (!this._map) { return; }
\r
31272 var pos = this._map.latLngToLayerPoint(this._latlng),
\r
31273 offset = toPoint(this.options.offset),
\r
31274 anchor = this._getAnchor();
\r
31276 if (this._zoomAnimated) {
\r
31277 setPosition(this._container, pos.add(anchor));
\r
31279 offset = offset.add(pos).add(anchor);
\r
31282 var bottom = this._containerBottom = -offset.y,
\r
31283 left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x;
\r
31285 // bottom position the popup in case the height of the popup changes (images loading etc)
\r
31286 this._container.style.bottom = bottom + 'px';
\r
31287 this._container.style.left = left + 'px';
\r
31290 _getAnchor: function () {
\r
31298 * @inherits DivOverlay
\r
31300 * Used to open popups in certain places of the map. Use [Map.openPopup](#map-openpopup) to
\r
31301 * open popups while making sure that only one popup is open at one time
\r
31302 * (recommended for usability), or use [Map.addLayer](#map-addlayer) to open as many as you want.
\r
31306 * If you want to just bind a popup to marker click and then open it, it's really easy:
\r
31309 * marker.bindPopup(popupContent).openPopup();
\r
31311 * Path overlays like polylines also have a `bindPopup` method.
\r
31312 * Here's a more complicated way to open a popup on a map:
\r
31315 * var popup = L.popup()
\r
31316 * .setLatLng(latlng)
\r
31317 * .setContent('<p>Hello world!<br />This is a nice popup.</p>')
\r
31323 // @namespace Popup
\r
31324 var Popup = DivOverlay.extend({
\r
31327 // @aka Popup options
\r
31329 // @option maxWidth: Number = 300
\r
31330 // Max width of the popup, in pixels.
\r
31333 // @option minWidth: Number = 50
\r
31334 // Min width of the popup, in pixels.
\r
31337 // @option maxHeight: Number = null
\r
31338 // If set, creates a scrollable container of the given height
\r
31339 // inside a popup if its content exceeds it.
\r
31342 // @option autoPan: Boolean = true
\r
31343 // Set it to `false` if you don't want the map to do panning animation
\r
31344 // to fit the opened popup.
\r
31347 // @option autoPanPaddingTopLeft: Point = null
\r
31348 // The margin between the popup and the top left corner of the map
\r
31349 // view after autopanning was performed.
\r
31350 autoPanPaddingTopLeft: null,
\r
31352 // @option autoPanPaddingBottomRight: Point = null
\r
31353 // The margin between the popup and the bottom right corner of the map
\r
31354 // view after autopanning was performed.
\r
31355 autoPanPaddingBottomRight: null,
\r
31357 // @option autoPanPadding: Point = Point(5, 5)
\r
31358 // Equivalent of setting both top left and bottom right autopan padding to the same value.
\r
31359 autoPanPadding: [5, 5],
\r
31361 // @option keepInView: Boolean = false
\r
31362 // Set it to `true` if you want to prevent users from panning the popup
\r
31363 // off of the screen while it is open.
\r
31364 keepInView: false,
\r
31366 // @option closeButton: Boolean = true
\r
31367 // Controls the presence of a close button in the popup.
\r
31368 closeButton: true,
\r
31370 // @option autoClose: Boolean = true
\r
31371 // Set it to `false` if you want to override the default behavior of
\r
31372 // the popup closing when another popup is opened.
\r
31375 // @option closeOnEscapeKey: Boolean = true
\r
31376 // Set it to `false` if you want to override the default behavior of
\r
31377 // the ESC key for closing of the popup.
\r
31378 closeOnEscapeKey: true,
\r
31380 // @option closeOnClick: Boolean = *
\r
31381 // Set it if you want to override the default behavior of the popup closing when user clicks
\r
31382 // on the map. Defaults to the map's [`closePopupOnClick`](#map-closepopuponclick) option.
\r
31384 // @option className: String = ''
\r
31385 // A custom CSS class name to assign to the popup.
\r
31389 // @namespace Popup
\r
31390 // @method openOn(map: Map): this
\r
31391 // Adds the popup to the map and closes the previous one. The same as `map.openPopup(popup)`.
\r
31392 openOn: function (map) {
\r
31393 map.openPopup(this);
\r
31397 onAdd: function (map) {
\r
31398 DivOverlay.prototype.onAdd.call(this, map);
\r
31400 // @namespace Map
\r
31401 // @section Popup events
\r
31402 // @event popupopen: PopupEvent
\r
31403 // Fired when a popup is opened in the map
\r
31404 map.fire('popupopen', {popup: this});
\r
31406 if (this._source) {
\r
31407 // @namespace Layer
\r
31408 // @section Popup events
\r
31409 // @event popupopen: PopupEvent
\r
31410 // Fired when a popup bound to this layer is opened
\r
31411 this._source.fire('popupopen', {popup: this}, true);
\r
31412 // For non-path layers, we toggle the popup when clicking
\r
31413 // again the layer, so prevent the map to reopen it.
\r
31414 if (!(this._source instanceof Path)) {
\r
31415 this._source.on('preclick', stopPropagation);
\r
31420 onRemove: function (map) {
\r
31421 DivOverlay.prototype.onRemove.call(this, map);
\r
31423 // @namespace Map
\r
31424 // @section Popup events
\r
31425 // @event popupclose: PopupEvent
\r
31426 // Fired when a popup in the map is closed
\r
31427 map.fire('popupclose', {popup: this});
\r
31429 if (this._source) {
\r
31430 // @namespace Layer
\r
31431 // @section Popup events
\r
31432 // @event popupclose: PopupEvent
\r
31433 // Fired when a popup bound to this layer is closed
\r
31434 this._source.fire('popupclose', {popup: this}, true);
\r
31435 if (!(this._source instanceof Path)) {
\r
31436 this._source.off('preclick', stopPropagation);
\r
31441 getEvents: function () {
\r
31442 var events = DivOverlay.prototype.getEvents.call(this);
\r
31444 if (this.options.closeOnClick !== undefined ? this.options.closeOnClick : this._map.options.closePopupOnClick) {
\r
31445 events.preclick = this._close;
\r
31448 if (this.options.keepInView) {
\r
31449 events.moveend = this._adjustPan;
\r
31455 _close: function () {
\r
31457 this._map.closePopup(this);
\r
31461 _initLayout: function () {
\r
31462 var prefix = 'leaflet-popup',
\r
31463 container = this._container = create$1('div',
\r
31464 prefix + ' ' + (this.options.className || '') +
\r
31465 ' leaflet-zoom-animated');
\r
31467 var wrapper = this._wrapper = create$1('div', prefix + '-content-wrapper', container);
\r
31468 this._contentNode = create$1('div', prefix + '-content', wrapper);
\r
31470 disableClickPropagation(container);
\r
31471 disableScrollPropagation(this._contentNode);
\r
31472 on(container, 'contextmenu', stopPropagation);
\r
31474 this._tipContainer = create$1('div', prefix + '-tip-container', container);
\r
31475 this._tip = create$1('div', prefix + '-tip', this._tipContainer);
\r
31477 if (this.options.closeButton) {
\r
31478 var closeButton = this._closeButton = create$1('a', prefix + '-close-button', container);
\r
31479 closeButton.href = '#close';
\r
31480 closeButton.innerHTML = '×';
\r
31482 on(closeButton, 'click', this._onCloseButtonClick, this);
\r
31486 _updateLayout: function () {
\r
31487 var container = this._contentNode,
\r
31488 style = container.style;
\r
31490 style.width = '';
\r
31491 style.whiteSpace = 'nowrap';
\r
31493 var width = container.offsetWidth;
\r
31494 width = Math.min(width, this.options.maxWidth);
\r
31495 width = Math.max(width, this.options.minWidth);
\r
31497 style.width = (width + 1) + 'px';
\r
31498 style.whiteSpace = '';
\r
31500 style.height = '';
\r
31502 var height = container.offsetHeight,
\r
31503 maxHeight = this.options.maxHeight,
\r
31504 scrolledClass = 'leaflet-popup-scrolled';
\r
31506 if (maxHeight && height > maxHeight) {
\r
31507 style.height = maxHeight + 'px';
\r
31508 addClass(container, scrolledClass);
\r
31510 removeClass(container, scrolledClass);
\r
31513 this._containerWidth = this._container.offsetWidth;
\r
31516 _animateZoom: function (e) {
\r
31517 var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center),
\r
31518 anchor = this._getAnchor();
\r
31519 setPosition(this._container, pos.add(anchor));
\r
31522 _adjustPan: function () {
\r
31523 if (!this.options.autoPan) { return; }
\r
31524 if (this._map._panAnim) { this._map._panAnim.stop(); }
\r
31526 var map = this._map,
\r
31527 marginBottom = parseInt(getStyle(this._container, 'marginBottom'), 10) || 0,
\r
31528 containerHeight = this._container.offsetHeight + marginBottom,
\r
31529 containerWidth = this._containerWidth,
\r
31530 layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom);
\r
31532 layerPos._add(getPosition(this._container));
\r
31534 var containerPos = map.layerPointToContainerPoint(layerPos),
\r
31535 padding = toPoint(this.options.autoPanPadding),
\r
31536 paddingTL = toPoint(this.options.autoPanPaddingTopLeft || padding),
\r
31537 paddingBR = toPoint(this.options.autoPanPaddingBottomRight || padding),
\r
31538 size = map.getSize(),
\r
31542 if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right
\r
31543 dx = containerPos.x + containerWidth - size.x + paddingBR.x;
\r
31545 if (containerPos.x - dx - paddingTL.x < 0) { // left
\r
31546 dx = containerPos.x - paddingTL.x;
\r
31548 if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom
\r
31549 dy = containerPos.y + containerHeight - size.y + paddingBR.y;
\r
31551 if (containerPos.y - dy - paddingTL.y < 0) { // top
\r
31552 dy = containerPos.y - paddingTL.y;
\r
31555 // @namespace Map
\r
31556 // @section Popup events
\r
31557 // @event autopanstart: Event
\r
31558 // Fired when the map starts autopanning when opening a popup.
\r
31561 .fire('autopanstart')
\r
31562 .panBy([dx, dy]);
\r
31566 _onCloseButtonClick: function (e) {
\r
31571 _getAnchor: function () {
\r
31572 // Where should we anchor the popup on the source layer?
\r
31573 return toPoint(this._source && this._source._getPopupAnchor ? this._source._getPopupAnchor() : [0, 0]);
\r
31578 // @namespace Popup
\r
31579 // @factory L.popup(options?: Popup options, source?: Layer)
\r
31580 // Instantiates a `Popup` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the popup with a reference to the Layer to which it refers.
\r
31581 var popup = function (options, source) {
\r
31582 return new Popup(options, source);
\r
31586 /* @namespace Map
\r
31587 * @section Interaction Options
\r
31588 * @option closePopupOnClick: Boolean = true
\r
31589 * Set it to `false` if you don't want popups to close when user clicks the map.
\r
31591 Map.mergeOptions({
\r
31592 closePopupOnClick: true
\r
31596 // @namespace Map
\r
31597 // @section Methods for Layers and Controls
\r
31599 // @method openPopup(popup: Popup): this
\r
31600 // Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).
\r
31602 // @method openPopup(content: String|HTMLElement, latlng: LatLng, options?: Popup options): this
\r
31603 // Creates a popup with the specified content and options and opens it in the given point on a map.
\r
31604 openPopup: function (popup, latlng, options) {
\r
31605 if (!(popup instanceof Popup)) {
\r
31606 popup = new Popup(options).setContent(popup);
\r
31610 popup.setLatLng(latlng);
\r
31613 if (this.hasLayer(popup)) {
\r
31617 if (this._popup && this._popup.options.autoClose) {
\r
31618 this.closePopup();
\r
31621 this._popup = popup;
\r
31622 return this.addLayer(popup);
\r
31625 // @method closePopup(popup?: Popup): this
\r
31626 // Closes the popup previously opened with [openPopup](#map-openpopup) (or the given one).
\r
31627 closePopup: function (popup) {
\r
31628 if (!popup || popup === this._popup) {
\r
31629 popup = this._popup;
\r
31630 this._popup = null;
\r
31633 this.removeLayer(popup);
\r
31640 * @namespace Layer
\r
31641 * @section Popup methods example
\r
31643 * All layers share a set of methods convenient for binding popups to it.
\r
31646 * var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
\r
31647 * layer.openPopup();
\r
31648 * layer.closePopup();
\r
31651 * Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.
\r
31654 // @section Popup methods
\r
31657 // @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this
\r
31658 // Binds a popup to the layer with the passed `content` and sets up the
\r
31659 // necessary event listeners. If a `Function` is passed it will receive
\r
31660 // the layer as the first argument and should return a `String` or `HTMLElement`.
\r
31661 bindPopup: function (content, options) {
\r
31663 if (content instanceof Popup) {
\r
31664 setOptions(content, options);
\r
31665 this._popup = content;
\r
31666 content._source = this;
\r
31668 if (!this._popup || options) {
\r
31669 this._popup = new Popup(options, this);
\r
31671 this._popup.setContent(content);
\r
31674 if (!this._popupHandlersAdded) {
\r
31676 click: this._openPopup,
\r
31677 keypress: this._onKeyPress,
\r
31678 remove: this.closePopup,
\r
31679 move: this._movePopup
\r
31681 this._popupHandlersAdded = true;
\r
31687 // @method unbindPopup(): this
\r
31688 // Removes the popup previously bound with `bindPopup`.
\r
31689 unbindPopup: function () {
\r
31690 if (this._popup) {
\r
31692 click: this._openPopup,
\r
31693 keypress: this._onKeyPress,
\r
31694 remove: this.closePopup,
\r
31695 move: this._movePopup
\r
31697 this._popupHandlersAdded = false;
\r
31698 this._popup = null;
\r
31703 // @method openPopup(latlng?: LatLng): this
\r
31704 // Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed.
\r
31705 openPopup: function (layer, latlng) {
\r
31706 if (this._popup && this._map) {
\r
31707 latlng = this._popup._prepareOpen(this, layer, latlng);
\r
31709 // open the popup on the map
\r
31710 this._map.openPopup(this._popup, latlng);
\r
31716 // @method closePopup(): this
\r
31717 // Closes the popup bound to this layer if it is open.
\r
31718 closePopup: function () {
\r
31719 if (this._popup) {
\r
31720 this._popup._close();
\r
31725 // @method togglePopup(): this
\r
31726 // Opens or closes the popup bound to this layer depending on its current state.
\r
31727 togglePopup: function (target) {
\r
31728 if (this._popup) {
\r
31729 if (this._popup._map) {
\r
31730 this.closePopup();
\r
31732 this.openPopup(target);
\r
31738 // @method isPopupOpen(): boolean
\r
31739 // Returns `true` if the popup bound to this layer is currently open.
\r
31740 isPopupOpen: function () {
\r
31741 return (this._popup ? this._popup.isOpen() : false);
\r
31744 // @method setPopupContent(content: String|HTMLElement|Popup): this
\r
31745 // Sets the content of the popup bound to this layer.
\r
31746 setPopupContent: function (content) {
\r
31747 if (this._popup) {
\r
31748 this._popup.setContent(content);
\r
31753 // @method getPopup(): Popup
\r
31754 // Returns the popup bound to this layer.
\r
31755 getPopup: function () {
\r
31756 return this._popup;
\r
31759 _openPopup: function (e) {
\r
31760 var layer = e.layer || e.target;
\r
31762 if (!this._popup) {
\r
31766 if (!this._map) {
\r
31770 // prevent map click
\r
31773 // if this inherits from Path its a vector and we can just
\r
31774 // open the popup at the new location
\r
31775 if (layer instanceof Path) {
\r
31776 this.openPopup(e.layer || e.target, e.latlng);
\r
31780 // otherwise treat it like a marker and figure out
\r
31781 // if we should toggle it open/closed
\r
31782 if (this._map.hasLayer(this._popup) && this._popup._source === layer) {
\r
31783 this.closePopup();
\r
31785 this.openPopup(layer, e.latlng);
\r
31789 _movePopup: function (e) {
\r
31790 this._popup.setLatLng(e.latlng);
\r
31793 _onKeyPress: function (e) {
\r
31794 if (e.originalEvent.keyCode === 13) {
\r
31795 this._openPopup(e);
\r
31802 * @inherits DivOverlay
31804 * Used to display small texts on top of map layers.
31809 * marker.bindTooltip("my tooltip text").openTooltip();
31811 * Note about tooltip offset. Leaflet takes two options in consideration
31812 * for computing tooltip offsetting:
31813 * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.
31814 * Add a positive x offset to move the tooltip to the right, and a positive y offset to
31815 * move it to the bottom. Negatives will move to the left and top.
31816 * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You
31817 * should adapt this value if you use a custom icon.
31821 // @namespace Tooltip
31822 var Tooltip = DivOverlay.extend({
31825 // @aka Tooltip options
31827 // @option pane: String = 'tooltipPane'
31828 // `Map pane` where the tooltip will be added.
31829 pane: 'tooltipPane',
31831 // @option offset: Point = Point(0, 0)
31832 // Optional offset of the tooltip position.
31835 // @option direction: String = 'auto'
31836 // Direction where to open the tooltip. Possible values are: `right`, `left`,
31837 // `top`, `bottom`, `center`, `auto`.
31838 // `auto` will dynamically switch between `right` and `left` according to the tooltip
31839 // position on the map.
31842 // @option permanent: Boolean = false
31843 // Whether to open the tooltip permanently or only on mouseover.
31846 // @option sticky: Boolean = false
31847 // If true, the tooltip will follow the mouse instead of being fixed at the feature center.
31850 // @option interactive: Boolean = false
31851 // If true, the tooltip will listen to the feature events.
31852 interactive: false,
31854 // @option opacity: Number = 0.9
31855 // Tooltip container opacity.
31859 onAdd: function (map) {
31860 DivOverlay.prototype.onAdd.call(this, map);
31861 this.setOpacity(this.options.opacity);
31864 // @section Tooltip events
31865 // @event tooltipopen: TooltipEvent
31866 // Fired when a tooltip is opened in the map.
31867 map.fire('tooltipopen', {tooltip: this});
31869 if (this._source) {
31870 // @namespace Layer
31871 // @section Tooltip events
31872 // @event tooltipopen: TooltipEvent
31873 // Fired when a tooltip bound to this layer is opened.
31874 this._source.fire('tooltipopen', {tooltip: this}, true);
31878 onRemove: function (map) {
31879 DivOverlay.prototype.onRemove.call(this, map);
31882 // @section Tooltip events
31883 // @event tooltipclose: TooltipEvent
31884 // Fired when a tooltip in the map is closed.
31885 map.fire('tooltipclose', {tooltip: this});
31887 if (this._source) {
31888 // @namespace Layer
31889 // @section Tooltip events
31890 // @event tooltipclose: TooltipEvent
31891 // Fired when a tooltip bound to this layer is closed.
31892 this._source.fire('tooltipclose', {tooltip: this}, true);
31896 getEvents: function () {
31897 var events = DivOverlay.prototype.getEvents.call(this);
31899 if (touch && !this.options.permanent) {
31900 events.preclick = this._close;
31906 _close: function () {
31908 this._map.closeTooltip(this);
31912 _initLayout: function () {
31913 var prefix = 'leaflet-tooltip',
31914 className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');
31916 this._contentNode = this._container = create$1('div', className);
31919 _updateLayout: function () {},
31921 _adjustPan: function () {},
31923 _setPosition: function (pos) {
31926 container = this._container,
31927 centerPoint = map.latLngToContainerPoint(map.getCenter()),
31928 tooltipPoint = map.layerPointToContainerPoint(pos),
31929 direction = this.options.direction,
31930 tooltipWidth = container.offsetWidth,
31931 tooltipHeight = container.offsetHeight,
31932 offset = toPoint(this.options.offset),
31933 anchor = this._getAnchor();
31935 if (direction === 'top') {
31936 subX = tooltipWidth / 2;
31937 subY = tooltipHeight;
31938 } else if (direction === 'bottom') {
31939 subX = tooltipWidth / 2;
31941 } else if (direction === 'center') {
31942 subX = tooltipWidth / 2;
31943 subY = tooltipHeight / 2;
31944 } else if (direction === 'right') {
31946 subY = tooltipHeight / 2;
31947 } else if (direction === 'left') {
31948 subX = tooltipWidth;
31949 subY = tooltipHeight / 2;
31950 } else if (tooltipPoint.x < centerPoint.x) {
31951 direction = 'right';
31953 subY = tooltipHeight / 2;
31955 direction = 'left';
31956 subX = tooltipWidth + (offset.x + anchor.x) * 2;
31957 subY = tooltipHeight / 2;
31960 pos = pos.subtract(toPoint(subX, subY, true)).add(offset).add(anchor);
31962 removeClass(container, 'leaflet-tooltip-right');
31963 removeClass(container, 'leaflet-tooltip-left');
31964 removeClass(container, 'leaflet-tooltip-top');
31965 removeClass(container, 'leaflet-tooltip-bottom');
31966 addClass(container, 'leaflet-tooltip-' + direction);
31967 setPosition(container, pos);
31970 _updatePosition: function () {
31971 var pos = this._map.latLngToLayerPoint(this._latlng);
31972 this._setPosition(pos);
31975 setOpacity: function (opacity) {
31976 this.options.opacity = opacity;
31978 if (this._container) {
31979 setOpacity(this._container, opacity);
31983 _animateZoom: function (e) {
31984 var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
31985 this._setPosition(pos);
31988 _getAnchor: function () {
31989 // Where should we anchor the tooltip on the source layer?
31990 return toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
31995 // @namespace Tooltip
31996 // @factory L.tooltip(options?: Tooltip options, source?: Layer)
31997 // Instantiates a Tooltip object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers.
31998 var tooltip = function (options, source) {
31999 return new Tooltip(options, source);
32003 // @section Methods for Layers and Controls
32006 // @method openTooltip(tooltip: Tooltip): this
32007 // Opens the specified tooltip.
32009 // @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this
32010 // Creates a tooltip with the specified content and options and open it.
32011 openTooltip: function (tooltip, latlng, options) {
32012 if (!(tooltip instanceof Tooltip)) {
32013 tooltip = new Tooltip(options).setContent(tooltip);
32017 tooltip.setLatLng(latlng);
32020 if (this.hasLayer(tooltip)) {
32024 return this.addLayer(tooltip);
32027 // @method closeTooltip(tooltip?: Tooltip): this
32028 // Closes the tooltip given as parameter.
32029 closeTooltip: function (tooltip) {
32031 this.removeLayer(tooltip);
32040 * @section Tooltip methods example
32042 * All layers share a set of methods convenient for binding tooltips to it.
32045 * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
32046 * layer.openTooltip();
32047 * layer.closeTooltip();
32051 // @section Tooltip methods
32054 // @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this
32055 // Binds a tooltip to the layer with the passed `content` and sets up the
32056 // necessary event listeners. If a `Function` is passed it will receive
32057 // the layer as the first argument and should return a `String` or `HTMLElement`.
32058 bindTooltip: function (content, options) {
32060 if (content instanceof Tooltip) {
32061 setOptions(content, options);
32062 this._tooltip = content;
32063 content._source = this;
32065 if (!this._tooltip || options) {
32066 this._tooltip = new Tooltip(options, this);
32068 this._tooltip.setContent(content);
32072 this._initTooltipInteractions();
32074 if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) {
32075 this.openTooltip();
32081 // @method unbindTooltip(): this
32082 // Removes the tooltip previously bound with `bindTooltip`.
32083 unbindTooltip: function () {
32084 if (this._tooltip) {
32085 this._initTooltipInteractions(true);
32086 this.closeTooltip();
32087 this._tooltip = null;
32092 _initTooltipInteractions: function (remove$$1) {
32093 if (!remove$$1 && this._tooltipHandlersAdded) { return; }
32094 var onOff = remove$$1 ? 'off' : 'on',
32096 remove: this.closeTooltip,
32097 move: this._moveTooltip
32099 if (!this._tooltip.options.permanent) {
32100 events.mouseover = this._openTooltip;
32101 events.mouseout = this.closeTooltip;
32102 if (this._tooltip.options.sticky) {
32103 events.mousemove = this._moveTooltip;
32106 events.click = this._openTooltip;
32109 events.add = this._openTooltip;
32111 this[onOff](events);
32112 this._tooltipHandlersAdded = !remove$$1;
32115 // @method openTooltip(latlng?: LatLng): this
32116 // Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed.
32117 openTooltip: function (layer, latlng) {
32118 if (this._tooltip && this._map) {
32119 latlng = this._tooltip._prepareOpen(this, layer, latlng);
32121 // open the tooltip on the map
32122 this._map.openTooltip(this._tooltip, latlng);
32124 // Tooltip container may not be defined if not permanent and never
32126 if (this._tooltip.options.interactive && this._tooltip._container) {
32127 addClass(this._tooltip._container, 'leaflet-clickable');
32128 this.addInteractiveTarget(this._tooltip._container);
32135 // @method closeTooltip(): this
32136 // Closes the tooltip bound to this layer if it is open.
32137 closeTooltip: function () {
32138 if (this._tooltip) {
32139 this._tooltip._close();
32140 if (this._tooltip.options.interactive && this._tooltip._container) {
32141 removeClass(this._tooltip._container, 'leaflet-clickable');
32142 this.removeInteractiveTarget(this._tooltip._container);
32148 // @method toggleTooltip(): this
32149 // Opens or closes the tooltip bound to this layer depending on its current state.
32150 toggleTooltip: function (target) {
32151 if (this._tooltip) {
32152 if (this._tooltip._map) {
32153 this.closeTooltip();
32155 this.openTooltip(target);
32161 // @method isTooltipOpen(): boolean
32162 // Returns `true` if the tooltip bound to this layer is currently open.
32163 isTooltipOpen: function () {
32164 return this._tooltip.isOpen();
32167 // @method setTooltipContent(content: String|HTMLElement|Tooltip): this
32168 // Sets the content of the tooltip bound to this layer.
32169 setTooltipContent: function (content) {
32170 if (this._tooltip) {
32171 this._tooltip.setContent(content);
32176 // @method getTooltip(): Tooltip
32177 // Returns the tooltip bound to this layer.
32178 getTooltip: function () {
32179 return this._tooltip;
32182 _openTooltip: function (e) {
32183 var layer = e.layer || e.target;
32185 if (!this._tooltip || !this._map) {
32188 this.openTooltip(layer, this._tooltip.options.sticky ? e.latlng : undefined);
32191 _moveTooltip: function (e) {
32192 var latlng = e.latlng, containerPoint, layerPoint;
32193 if (this._tooltip.options.sticky && e.originalEvent) {
32194 containerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);
32195 layerPoint = this._map.containerPointToLayerPoint(containerPoint);
32196 latlng = this._map.layerPointToLatLng(layerPoint);
32198 this._tooltip.setLatLng(latlng);
32207 * Represents a lightweight icon for markers that uses a simple `<div>`
32208 * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options.
32212 * var myIcon = L.divIcon({className: 'my-div-icon'});
32213 * // you can set .my-div-icon styles in CSS
32215 * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
32218 * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.
32221 var DivIcon = Icon.extend({
32224 // @aka DivIcon options
32225 iconSize: [12, 12], // also can be set through CSS
32227 // iconAnchor: (Point),
32228 // popupAnchor: (Point),
32230 // @option html: String|HTMLElement = ''
32231 // Custom HTML code to put inside the div element, empty by default. Alternatively,
32232 // an instance of `HTMLElement`.
32235 // @option bgPos: Point = [0, 0]
32236 // Optional relative position of the background, in pixels
32239 className: 'leaflet-div-icon'
32242 createIcon: function (oldIcon) {
32243 var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),
32244 options = this.options;
32246 if (options.html instanceof Element) {
32248 div.appendChild(options.html);
32250 div.innerHTML = options.html !== false ? options.html : '';
32253 if (options.bgPos) {
32254 var bgPos = toPoint(options.bgPos);
32255 div.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px';
32257 this._setIconStyles(div, 'icon');
32262 createShadow: function () {
32267 // @factory L.divIcon(options: DivIcon options)
32268 // Creates a `DivIcon` instance with the given options.
32269 function divIcon(options) {
32270 return new DivIcon(options);
32273 Icon.Default = IconDefault;
32280 * Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces `TileLayer.Canvas`.
32281 * GridLayer can be extended to create a tiled grid of HTML elements like `<canvas>`, `<img>` or `<div>`. GridLayer will handle creating and animating these DOM elements for you.
32284 * @section Synchronous usage
32287 * To create a custom layer, extend GridLayer and implement the `createTile()` method, which will be passed a `Point` object with the `x`, `y`, and `z` (zoom level) coordinates to draw your tile.
32290 * var CanvasLayer = L.GridLayer.extend({
32291 * createTile: function(coords){
32292 * // create a <canvas> element for drawing
32293 * var tile = L.DomUtil.create('canvas', 'leaflet-tile');
32295 * // setup tile width and height according to the options
32296 * var size = this.getTileSize();
32297 * tile.width = size.x;
32298 * tile.height = size.y;
32300 * // get a canvas context and draw something on it using coords.x, coords.y and coords.z
32301 * var ctx = tile.getContext('2d');
32303 * // return the tile so it can be rendered on screen
32309 * @section Asynchronous usage
32312 * Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the `done()` callback.
32315 * var CanvasLayer = L.GridLayer.extend({
32316 * createTile: function(coords, done){
32319 * // create a <canvas> element for drawing
32320 * var tile = L.DomUtil.create('canvas', 'leaflet-tile');
32322 * // setup tile width and height according to the options
32323 * var size = this.getTileSize();
32324 * tile.width = size.x;
32325 * tile.height = size.y;
32327 * // draw something asynchronously and pass the tile to the done() callback
32328 * setTimeout(function() {
32329 * done(error, tile);
32341 var GridLayer = Layer.extend({
32344 // @aka GridLayer options
32346 // @option tileSize: Number|Point = 256
32347 // Width and height of tiles in the grid. Use a number if width and height are equal, or `L.point(width, height)` otherwise.
32350 // @option opacity: Number = 1.0
32351 // Opacity of the tiles. Can be used in the `createTile()` function.
32354 // @option updateWhenIdle: Boolean = (depends)
32355 // Load new tiles only when panning ends.
32356 // `true` by default on mobile browsers, in order to avoid too many requests and keep smooth navigation.
32357 // `false` otherwise in order to display new tiles _during_ panning, since it is easy to pan outside the
32358 // [`keepBuffer`](#gridlayer-keepbuffer) option in desktop browsers.
32359 updateWhenIdle: mobile,
32361 // @option updateWhenZooming: Boolean = true
32362 // By default, a smooth zoom animation (during a [touch zoom](#map-touchzoom) or a [`flyTo()`](#map-flyto)) will update grid layers every integer zoom level. Setting this option to `false` will update the grid layer only when the smooth animation ends.
32363 updateWhenZooming: true,
32365 // @option updateInterval: Number = 200
32366 // Tiles will not update more than once every `updateInterval` milliseconds when panning.
32367 updateInterval: 200,
32369 // @option zIndex: Number = 1
32370 // The explicit zIndex of the tile layer.
32373 // @option bounds: LatLngBounds = undefined
32374 // If set, tiles will only be loaded inside the set `LatLngBounds`.
32377 // @option minZoom: Number = 0
32378 // The minimum zoom level down to which this layer will be displayed (inclusive).
32381 // @option maxZoom: Number = undefined
32382 // The maximum zoom level up to which this layer will be displayed (inclusive).
32383 maxZoom: undefined,
32385 // @option maxNativeZoom: Number = undefined
32386 // Maximum zoom number the tile source has available. If it is specified,
32387 // the tiles on all zoom levels higher than `maxNativeZoom` will be loaded
32388 // from `maxNativeZoom` level and auto-scaled.
32389 maxNativeZoom: undefined,
32391 // @option minNativeZoom: Number = undefined
32392 // Minimum zoom number the tile source has available. If it is specified,
32393 // the tiles on all zoom levels lower than `minNativeZoom` will be loaded
32394 // from `minNativeZoom` level and auto-scaled.
32395 minNativeZoom: undefined,
32397 // @option noWrap: Boolean = false
32398 // Whether the layer is wrapped around the antimeridian. If `true`, the
32399 // GridLayer will only be displayed once at low zoom levels. Has no
32400 // effect when the [map CRS](#map-crs) doesn't wrap around. Can be used
32401 // in combination with [`bounds`](#gridlayer-bounds) to prevent requesting
32402 // tiles outside the CRS limits.
32405 // @option pane: String = 'tilePane'
32406 // `Map pane` where the grid layer will be added.
32409 // @option className: String = ''
32410 // A custom class name to assign to the tile layer. Empty by default.
32413 // @option keepBuffer: Number = 2
32414 // When panning the map, keep this many rows and columns of tiles before unloading them.
32418 initialize: function (options) {
32419 setOptions(this, options);
32422 onAdd: function () {
32423 this._initContainer();
32432 beforeAdd: function (map) {
32433 map._addZoomLimit(this);
32436 onRemove: function (map) {
32437 this._removeAllTiles();
32438 remove(this._container);
32439 map._removeZoomLimit(this);
32440 this._container = null;
32441 this._tileZoom = undefined;
32444 // @method bringToFront: this
32445 // Brings the tile layer to the top of all tile layers.
32446 bringToFront: function () {
32448 toFront(this._container);
32449 this._setAutoZIndex(Math.max);
32454 // @method bringToBack: this
32455 // Brings the tile layer to the bottom of all tile layers.
32456 bringToBack: function () {
32458 toBack(this._container);
32459 this._setAutoZIndex(Math.min);
32464 // @method getContainer: HTMLElement
32465 // Returns the HTML element that contains the tiles for this layer.
32466 getContainer: function () {
32467 return this._container;
32470 // @method setOpacity(opacity: Number): this
32471 // Changes the [opacity](#gridlayer-opacity) of the grid layer.
32472 setOpacity: function (opacity) {
32473 this.options.opacity = opacity;
32474 this._updateOpacity();
32478 // @method setZIndex(zIndex: Number): this
32479 // Changes the [zIndex](#gridlayer-zindex) of the grid layer.
32480 setZIndex: function (zIndex) {
32481 this.options.zIndex = zIndex;
32482 this._updateZIndex();
32487 // @method isLoading: Boolean
32488 // Returns `true` if any tile in the grid layer has not finished loading.
32489 isLoading: function () {
32490 return this._loading;
32493 // @method redraw: this
32494 // Causes the layer to clear all the tiles and request them again.
32495 redraw: function () {
32497 this._removeAllTiles();
32503 getEvents: function () {
32505 viewprereset: this._invalidateAll,
32506 viewreset: this._resetView,
32507 zoom: this._resetView,
32508 moveend: this._onMoveEnd
32511 if (!this.options.updateWhenIdle) {
32512 // update tiles on move, but not more often than once per given interval
32513 if (!this._onMove) {
32514 this._onMove = throttle(this._onMoveEnd, this.options.updateInterval, this);
32517 events.move = this._onMove;
32520 if (this._zoomAnimated) {
32521 events.zoomanim = this._animateZoom;
32527 // @section Extension methods
32528 // Layers extending `GridLayer` shall reimplement the following method.
32529 // @method createTile(coords: Object, done?: Function): HTMLElement
32530 // Called only internally, must be overridden by classes extending `GridLayer`.
32531 // Returns the `HTMLElement` corresponding to the given `coords`. If the `done` callback
32532 // is specified, it must be called when the tile has finished loading and drawing.
32533 createTile: function () {
32534 return document.createElement('div');
32538 // @method getTileSize: Point
32539 // Normalizes the [tileSize option](#gridlayer-tilesize) into a point. Used by the `createTile()` method.
32540 getTileSize: function () {
32541 var s = this.options.tileSize;
32542 return s instanceof Point ? s : new Point(s, s);
32545 _updateZIndex: function () {
32546 if (this._container && this.options.zIndex !== undefined && this.options.zIndex !== null) {
32547 this._container.style.zIndex = this.options.zIndex;
32551 _setAutoZIndex: function (compare) {
32552 // go through all other layers of the same pane, set zIndex to max + 1 (front) or min - 1 (back)
32554 var layers = this.getPane().children,
32555 edgeZIndex = -compare(-Infinity, Infinity); // -Infinity for max, Infinity for min
32557 for (var i = 0, len = layers.length, zIndex; i < len; i++) {
32559 zIndex = layers[i].style.zIndex;
32561 if (layers[i] !== this._container && zIndex) {
32562 edgeZIndex = compare(edgeZIndex, +zIndex);
32566 if (isFinite(edgeZIndex)) {
32567 this.options.zIndex = edgeZIndex + compare(-1, 1);
32568 this._updateZIndex();
32572 _updateOpacity: function () {
32573 if (!this._map) { return; }
32575 // IE doesn't inherit filter opacity properly, so we're forced to set it on tiles
32576 if (ielt9) { return; }
32578 setOpacity(this._container, this.options.opacity);
32580 var now = +new Date(),
32584 for (var key in this._tiles) {
32585 var tile = this._tiles[key];
32586 if (!tile.current || !tile.loaded) { continue; }
32588 var fade = Math.min(1, (now - tile.loaded) / 200);
32590 setOpacity(tile.el, fade);
32597 this._onOpaqueTile(tile);
32599 tile.active = true;
32603 if (willPrune && !this._noPrune) { this._pruneTiles(); }
32606 cancelAnimFrame(this._fadeFrame);
32607 this._fadeFrame = requestAnimFrame(this._updateOpacity, this);
32611 _onOpaqueTile: falseFn,
32613 _initContainer: function () {
32614 if (this._container) { return; }
32616 this._container = create$1('div', 'leaflet-layer ' + (this.options.className || ''));
32617 this._updateZIndex();
32619 if (this.options.opacity < 1) {
32620 this._updateOpacity();
32623 this.getPane().appendChild(this._container);
32626 _updateLevels: function () {
32628 var zoom = this._tileZoom,
32629 maxZoom = this.options.maxZoom;
32631 if (zoom === undefined) { return undefined; }
32633 for (var z in this._levels) {
32635 if (this._levels[z].el.children.length || z === zoom) {
32636 this._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom - z);
32637 this._onUpdateLevel(z);
32639 remove(this._levels[z].el);
32640 this._removeTilesAtZoom(z);
32641 this._onRemoveLevel(z);
32642 delete this._levels[z];
32646 var level = this._levels[zoom],
32650 level = this._levels[zoom] = {};
32652 level.el = create$1('div', 'leaflet-tile-container leaflet-zoom-animated', this._container);
32653 level.el.style.zIndex = maxZoom;
32655 level.origin = map.project(map.unproject(map.getPixelOrigin()), zoom).round();
32658 this._setZoomTransform(level, map.getCenter(), map.getZoom());
32660 // force the browser to consider the newly added element for transition
32661 falseFn(level.el.offsetWidth);
32663 this._onCreateLevel(level);
32666 this._level = level;
32671 _onUpdateLevel: falseFn,
32673 _onRemoveLevel: falseFn,
32675 _onCreateLevel: falseFn,
32677 _pruneTiles: function () {
32684 var zoom = this._map.getZoom();
32685 if (zoom > this.options.maxZoom ||
32686 zoom < this.options.minZoom) {
32687 this._removeAllTiles();
32691 for (key in this._tiles) {
32692 tile = this._tiles[key];
32693 tile.retain = tile.current;
32696 for (key in this._tiles) {
32697 tile = this._tiles[key];
32698 if (tile.current && !tile.active) {
32699 var coords = tile.coords;
32700 if (!this._retainParent(coords.x, coords.y, coords.z, coords.z - 5)) {
32701 this._retainChildren(coords.x, coords.y, coords.z, coords.z + 2);
32706 for (key in this._tiles) {
32707 if (!this._tiles[key].retain) {
32708 this._removeTile(key);
32713 _removeTilesAtZoom: function (zoom) {
32714 for (var key in this._tiles) {
32715 if (this._tiles[key].coords.z !== zoom) {
32718 this._removeTile(key);
32722 _removeAllTiles: function () {
32723 for (var key in this._tiles) {
32724 this._removeTile(key);
32728 _invalidateAll: function () {
32729 for (var z in this._levels) {
32730 remove(this._levels[z].el);
32731 this._onRemoveLevel(Number(z));
32732 delete this._levels[z];
32734 this._removeAllTiles();
32736 this._tileZoom = undefined;
32739 _retainParent: function (x, y, z, minZoom) {
32740 var x2 = Math.floor(x / 2),
32741 y2 = Math.floor(y / 2),
32743 coords2 = new Point(+x2, +y2);
32746 var key = this._tileCoordsToKey(coords2),
32747 tile = this._tiles[key];
32749 if (tile && tile.active) {
32750 tile.retain = true;
32753 } else if (tile && tile.loaded) {
32754 tile.retain = true;
32757 if (z2 > minZoom) {
32758 return this._retainParent(x2, y2, z2, minZoom);
32764 _retainChildren: function (x, y, z, maxZoom) {
32766 for (var i = 2 * x; i < 2 * x + 2; i++) {
32767 for (var j = 2 * y; j < 2 * y + 2; j++) {
32769 var coords = new Point(i, j);
32772 var key = this._tileCoordsToKey(coords),
32773 tile = this._tiles[key];
32775 if (tile && tile.active) {
32776 tile.retain = true;
32779 } else if (tile && tile.loaded) {
32780 tile.retain = true;
32783 if (z + 1 < maxZoom) {
32784 this._retainChildren(i, j, z + 1, maxZoom);
32790 _resetView: function (e) {
32791 var animating = e && (e.pinch || e.flyTo);
32792 this._setView(this._map.getCenter(), this._map.getZoom(), animating, animating);
32795 _animateZoom: function (e) {
32796 this._setView(e.center, e.zoom, true, e.noUpdate);
32799 _clampZoom: function (zoom) {
32800 var options = this.options;
32802 if (undefined !== options.minNativeZoom && zoom < options.minNativeZoom) {
32803 return options.minNativeZoom;
32806 if (undefined !== options.maxNativeZoom && options.maxNativeZoom < zoom) {
32807 return options.maxNativeZoom;
32813 _setView: function (center, zoom, noPrune, noUpdate) {
32814 var tileZoom = Math.round(zoom);
32815 if ((this.options.maxZoom !== undefined && tileZoom > this.options.maxZoom) ||
32816 (this.options.minZoom !== undefined && tileZoom < this.options.minZoom)) {
32817 tileZoom = undefined;
32819 tileZoom = this._clampZoom(tileZoom);
32822 var tileZoomChanged = this.options.updateWhenZooming && (tileZoom !== this._tileZoom);
32824 if (!noUpdate || tileZoomChanged) {
32826 this._tileZoom = tileZoom;
32828 if (this._abortLoading) {
32829 this._abortLoading();
32832 this._updateLevels();
32835 if (tileZoom !== undefined) {
32836 this._update(center);
32840 this._pruneTiles();
32843 // Flag to prevent _updateOpacity from pruning tiles during
32844 // a zoom anim or a pinch gesture
32845 this._noPrune = !!noPrune;
32848 this._setZoomTransforms(center, zoom);
32851 _setZoomTransforms: function (center, zoom) {
32852 for (var i in this._levels) {
32853 this._setZoomTransform(this._levels[i], center, zoom);
32857 _setZoomTransform: function (level, center, zoom) {
32858 var scale = this._map.getZoomScale(zoom, level.zoom),
32859 translate = level.origin.multiplyBy(scale)
32860 .subtract(this._map._getNewPixelOrigin(center, zoom)).round();
32863 setTransform(level.el, translate, scale);
32865 setPosition(level.el, translate);
32869 _resetGrid: function () {
32870 var map = this._map,
32871 crs = map.options.crs,
32872 tileSize = this._tileSize = this.getTileSize(),
32873 tileZoom = this._tileZoom;
32875 var bounds = this._map.getPixelWorldBounds(this._tileZoom);
32877 this._globalTileRange = this._pxBoundsToTileRange(bounds);
32880 this._wrapX = crs.wrapLng && !this.options.noWrap && [
32881 Math.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x),
32882 Math.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y)
32884 this._wrapY = crs.wrapLat && !this.options.noWrap && [
32885 Math.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x),
32886 Math.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y)
32890 _onMoveEnd: function () {
32891 if (!this._map || this._map._animatingZoom) { return; }
32896 _getTiledPixelBounds: function (center) {
32897 var map = this._map,
32898 mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(),
32899 scale = map.getZoomScale(mapZoom, this._tileZoom),
32900 pixelCenter = map.project(center, this._tileZoom).floor(),
32901 halfSize = map.getSize().divideBy(scale * 2);
32903 return new Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
32906 // Private method to load tiles in the grid's active zoom level according to map bounds
32907 _update: function (center) {
32908 var map = this._map;
32909 if (!map) { return; }
32910 var zoom = this._clampZoom(map.getZoom());
32912 if (center === undefined) { center = map.getCenter(); }
32913 if (this._tileZoom === undefined) { return; } // if out of minzoom/maxzoom
32915 var pixelBounds = this._getTiledPixelBounds(center),
32916 tileRange = this._pxBoundsToTileRange(pixelBounds),
32917 tileCenter = tileRange.getCenter(),
32919 margin = this.options.keepBuffer,
32920 noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([margin, -margin]),
32921 tileRange.getTopRight().add([margin, -margin]));
32923 // Sanity check: panic if the tile range contains Infinity somewhere.
32924 if (!(isFinite(tileRange.min.x) &&
32925 isFinite(tileRange.min.y) &&
32926 isFinite(tileRange.max.x) &&
32927 isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); }
32929 for (var key in this._tiles) {
32930 var c = this._tiles[key].coords;
32931 if (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) {
32932 this._tiles[key].current = false;
32936 // _update just loads more tiles. If the tile zoom level differs too much
32937 // from the map's, let _setView reset levels and prune old tiles.
32938 if (Math.abs(zoom - this._tileZoom) > 1) { this._setView(center, zoom); return; }
32940 // create a queue of coordinates to load tiles from
32941 for (var j = tileRange.min.y; j <= tileRange.max.y; j++) {
32942 for (var i = tileRange.min.x; i <= tileRange.max.x; i++) {
32943 var coords = new Point(i, j);
32944 coords.z = this._tileZoom;
32946 if (!this._isValidTile(coords)) { continue; }
32948 var tile = this._tiles[this._tileCoordsToKey(coords)];
32950 tile.current = true;
32952 queue.push(coords);
32957 // sort tile queue to load tiles in order of their distance to center
32958 queue.sort(function (a, b) {
32959 return a.distanceTo(tileCenter) - b.distanceTo(tileCenter);
32962 if (queue.length !== 0) {
32963 // if it's the first batch of tiles to load
32964 if (!this._loading) {
32965 this._loading = true;
32966 // @event loading: Event
32967 // Fired when the grid layer starts loading tiles.
32968 this.fire('loading');
32971 // create DOM fragment to append tiles in one batch
32972 var fragment = document.createDocumentFragment();
32974 for (i = 0; i < queue.length; i++) {
32975 this._addTile(queue[i], fragment);
32978 this._level.el.appendChild(fragment);
32982 _isValidTile: function (coords) {
32983 var crs = this._map.options.crs;
32985 if (!crs.infinite) {
32986 // don't load tile if it's out of bounds and not wrapped
32987 var bounds = this._globalTileRange;
32988 if ((!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x)) ||
32989 (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))) { return false; }
32992 if (!this.options.bounds) { return true; }
32994 // don't load tile if it doesn't intersect the bounds in options
32995 var tileBounds = this._tileCoordsToBounds(coords);
32996 return toLatLngBounds(this.options.bounds).overlaps(tileBounds);
32999 _keyToBounds: function (key) {
33000 return this._tileCoordsToBounds(this._keyToTileCoords(key));
33003 _tileCoordsToNwSe: function (coords) {
33004 var map = this._map,
33005 tileSize = this.getTileSize(),
33006 nwPoint = coords.scaleBy(tileSize),
33007 sePoint = nwPoint.add(tileSize),
33008 nw = map.unproject(nwPoint, coords.z),
33009 se = map.unproject(sePoint, coords.z);
33013 // converts tile coordinates to its geographical bounds
33014 _tileCoordsToBounds: function (coords) {
33015 var bp = this._tileCoordsToNwSe(coords),
33016 bounds = new LatLngBounds(bp[0], bp[1]);
33018 if (!this.options.noWrap) {
33019 bounds = this._map.wrapLatLngBounds(bounds);
33023 // converts tile coordinates to key for the tile cache
33024 _tileCoordsToKey: function (coords) {
33025 return coords.x + ':' + coords.y + ':' + coords.z;
33028 // converts tile cache key to coordinates
33029 _keyToTileCoords: function (key) {
33030 var k = key.split(':'),
33031 coords = new Point(+k[0], +k[1]);
33036 _removeTile: function (key) {
33037 var tile = this._tiles[key];
33038 if (!tile) { return; }
33042 delete this._tiles[key];
33044 // @event tileunload: TileEvent
33045 // Fired when a tile is removed (e.g. when a tile goes off the screen).
33046 this.fire('tileunload', {
33048 coords: this._keyToTileCoords(key)
33052 _initTile: function (tile) {
33053 addClass(tile, 'leaflet-tile');
33055 var tileSize = this.getTileSize();
33056 tile.style.width = tileSize.x + 'px';
33057 tile.style.height = tileSize.y + 'px';
33059 tile.onselectstart = falseFn;
33060 tile.onmousemove = falseFn;
33062 // update opacity on tiles in IE7-8 because of filter inheritance problems
33063 if (ielt9 && this.options.opacity < 1) {
33064 setOpacity(tile, this.options.opacity);
33067 // without this hack, tiles disappear after zoom on Chrome for Android
33068 // https://github.com/Leaflet/Leaflet/issues/2078
33069 if (android && !android23) {
33070 tile.style.WebkitBackfaceVisibility = 'hidden';
33074 _addTile: function (coords, container) {
33075 var tilePos = this._getTilePos(coords),
33076 key = this._tileCoordsToKey(coords);
33078 var tile = this.createTile(this._wrapCoords(coords), bind(this._tileReady, this, coords));
33080 this._initTile(tile);
33082 // if createTile is defined with a second argument ("done" callback),
33083 // we know that tile is async and will be ready later; otherwise
33084 if (this.createTile.length < 2) {
33085 // mark tile as ready, but delay one frame for opacity animation to happen
33086 requestAnimFrame(bind(this._tileReady, this, coords, null, tile));
33089 setPosition(tile, tilePos);
33091 // save tile in cache
33092 this._tiles[key] = {
33098 container.appendChild(tile);
33099 // @event tileloadstart: TileEvent
33100 // Fired when a tile is requested and starts loading.
33101 this.fire('tileloadstart', {
33107 _tileReady: function (coords, err, tile) {
33109 // @event tileerror: TileErrorEvent
33110 // Fired when there is an error loading a tile.
33111 this.fire('tileerror', {
33118 var key = this._tileCoordsToKey(coords);
33120 tile = this._tiles[key];
33121 if (!tile) { return; }
33123 tile.loaded = +new Date();
33124 if (this._map._fadeAnimated) {
33125 setOpacity(tile.el, 0);
33126 cancelAnimFrame(this._fadeFrame);
33127 this._fadeFrame = requestAnimFrame(this._updateOpacity, this);
33129 tile.active = true;
33130 this._pruneTiles();
33134 addClass(tile.el, 'leaflet-tile-loaded');
33136 // @event tileload: TileEvent
33137 // Fired when a tile loads.
33138 this.fire('tileload', {
33144 if (this._noTilesToLoad()) {
33145 this._loading = false;
33146 // @event load: Event
33147 // Fired when the grid layer loaded all visible tiles.
33150 if (ielt9 || !this._map._fadeAnimated) {
33151 requestAnimFrame(this._pruneTiles, this);
33153 // Wait a bit more than 0.2 secs (the duration of the tile fade-in)
33154 // to trigger a pruning.
33155 setTimeout(bind(this._pruneTiles, this), 250);
33160 _getTilePos: function (coords) {
33161 return coords.scaleBy(this.getTileSize()).subtract(this._level.origin);
33164 _wrapCoords: function (coords) {
33165 var newCoords = new Point(
33166 this._wrapX ? wrapNum(coords.x, this._wrapX) : coords.x,
33167 this._wrapY ? wrapNum(coords.y, this._wrapY) : coords.y);
33168 newCoords.z = coords.z;
33172 _pxBoundsToTileRange: function (bounds) {
33173 var tileSize = this.getTileSize();
33175 bounds.min.unscaleBy(tileSize).floor(),
33176 bounds.max.unscaleBy(tileSize).ceil().subtract([1, 1]));
33179 _noTilesToLoad: function () {
33180 for (var key in this._tiles) {
33181 if (!this._tiles[key].loaded) { return false; }
33187 // @factory L.gridLayer(options?: GridLayer options)
33188 // Creates a new instance of GridLayer with the supplied options.
33189 function gridLayer(options) {
33190 return new GridLayer(options);
33194 * @class TileLayer
\r
33195 * @inherits GridLayer
\r
33196 * @aka L.TileLayer
\r
33197 * Used to load and display tile layers on the map. Note that most tile servers require attribution, which you can set under `Layer`. Extends `GridLayer`.
\r
33202 * L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar', attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'}).addTo(map);
\r
33205 * @section URL template
\r
33208 * A string of the following form:
\r
33211 * 'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
\r
33214 * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add "@2x" to the URL to load retina tiles.
\r
33216 * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this:
\r
33219 * L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
\r
33224 var TileLayer = GridLayer.extend({
\r
33227 // @aka TileLayer options
\r
33229 // @option minZoom: Number = 0
\r
33230 // The minimum zoom level down to which this layer will be displayed (inclusive).
\r
33233 // @option maxZoom: Number = 18
\r
33234 // The maximum zoom level up to which this layer will be displayed (inclusive).
\r
33237 // @option subdomains: String|String[] = 'abc'
\r
33238 // Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
\r
33239 subdomains: 'abc',
\r
33241 // @option errorTileUrl: String = ''
\r
33242 // URL to the tile image to show in place of the tile that failed to load.
\r
33243 errorTileUrl: '',
\r
33245 // @option zoomOffset: Number = 0
\r
33246 // The zoom number used in tile URLs will be offset with this value.
\r
33249 // @option tms: Boolean = false
\r
33250 // If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).
\r
33253 // @option zoomReverse: Boolean = false
\r
33254 // If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)
\r
33255 zoomReverse: false,
\r
33257 // @option detectRetina: Boolean = false
\r
33258 // If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
\r
33259 detectRetina: false,
\r
33261 // @option crossOrigin: Boolean|String = false
\r
33262 // Whether the crossOrigin attribute will be added to the tiles.
\r
33263 // If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.
\r
33264 // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
\r
33265 crossOrigin: false
\r
33268 initialize: function (url, options) {
\r
33272 options = setOptions(this, options);
\r
33274 // detecting retina displays, adjusting tileSize and zoom levels
\r
33275 if (options.detectRetina && retina && options.maxZoom > 0) {
\r
33277 options.tileSize = Math.floor(options.tileSize / 2);
\r
33279 if (!options.zoomReverse) {
\r
33280 options.zoomOffset++;
\r
33281 options.maxZoom--;
\r
33283 options.zoomOffset--;
\r
33284 options.minZoom++;
\r
33287 options.minZoom = Math.max(0, options.minZoom);
\r
33290 if (typeof options.subdomains === 'string') {
\r
33291 options.subdomains = options.subdomains.split('');
\r
33294 // for https://github.com/Leaflet/Leaflet/issues/137
\r
33296 this.on('tileunload', this._onTileRemove);
\r
33300 // @method setUrl(url: String, noRedraw?: Boolean): this
\r
33301 // Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
\r
33302 // If the URL does not change, the layer will not be redrawn unless
\r
33303 // the noRedraw parameter is set to false.
\r
33304 setUrl: function (url, noRedraw) {
\r
33305 if (this._url === url && noRedraw === undefined) {
\r
33317 // @method createTile(coords: Object, done?: Function): HTMLElement
\r
33318 // Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
\r
33319 // to return an `<img>` HTML element with the appropriate image URL given `coords`. The `done`
\r
33320 // callback is called when the tile has been loaded.
\r
33321 createTile: function (coords, done) {
\r
33322 var tile = document.createElement('img');
\r
33324 on(tile, 'load', bind(this._tileOnLoad, this, done, tile));
\r
33325 on(tile, 'error', bind(this._tileOnError, this, done, tile));
\r
33327 if (this.options.crossOrigin || this.options.crossOrigin === '') {
\r
33328 tile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
\r
33332 Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons
\r
33333 http://www.w3.org/TR/WCAG20-TECHS/H67
\r
33338 Set role="presentation" to force screen readers to ignore this
\r
33339 https://www.w3.org/TR/wai-aria/roles#textalternativecomputation
\r
33341 tile.setAttribute('role', 'presentation');
\r
33343 tile.src = this.getTileUrl(coords);
\r
33348 // @section Extension methods
\r
33349 // @uninheritable
\r
33350 // Layers extending `TileLayer` might reimplement the following method.
\r
33351 // @method getTileUrl(coords: Object): String
\r
33352 // Called only internally, returns the URL for a tile given its coordinates.
\r
33353 // Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.
\r
33354 getTileUrl: function (coords) {
\r
33356 r: retina ? '@2x' : '',
\r
33357 s: this._getSubdomain(coords),
\r
33360 z: this._getZoomForUrl()
\r
33362 if (this._map && !this._map.options.crs.infinite) {
\r
33363 var invertedY = this._globalTileRange.max.y - coords.y;
\r
33364 if (this.options.tms) {
\r
33365 data['y'] = invertedY;
\r
33367 data['-y'] = invertedY;
\r
33370 return template(this._url, extend(data, this.options));
\r
33373 _tileOnLoad: function (done, tile) {
\r
33374 // For https://github.com/Leaflet/Leaflet/issues/3332
\r
33376 setTimeout(bind(done, this, null, tile), 0);
\r
33378 done(null, tile);
\r
33382 _tileOnError: function (done, tile, e) {
\r
33383 var errorUrl = this.options.errorTileUrl;
\r
33384 if (errorUrl && tile.getAttribute('src') !== errorUrl) {
\r
33385 tile.src = errorUrl;
\r
33390 _onTileRemove: function (e) {
\r
33391 e.tile.onload = null;
\r
33394 _getZoomForUrl: function () {
\r
33395 var zoom = this._tileZoom,
\r
33396 maxZoom = this.options.maxZoom,
\r
33397 zoomReverse = this.options.zoomReverse,
\r
33398 zoomOffset = this.options.zoomOffset;
\r
33400 if (zoomReverse) {
\r
33401 zoom = maxZoom - zoom;
\r
33404 return zoom + zoomOffset;
\r
33407 _getSubdomain: function (tilePoint) {
\r
33408 var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;
\r
33409 return this.options.subdomains[index];
\r
33412 // stops loading all tiles in the background layer
\r
33413 _abortLoading: function () {
\r
33415 for (i in this._tiles) {
\r
33416 if (this._tiles[i].coords.z !== this._tileZoom) {
\r
33417 tile = this._tiles[i].el;
\r
33419 tile.onload = falseFn;
\r
33420 tile.onerror = falseFn;
\r
33422 if (!tile.complete) {
\r
33423 tile.src = emptyImageUrl;
\r
33425 delete this._tiles[i];
\r
33431 _removeTile: function (key) {
\r
33432 var tile = this._tiles[key];
\r
33433 if (!tile) { return; }
\r
33435 // Cancels any pending http requests associated with the tile
\r
33436 // unless we're on Android's stock browser,
\r
33437 // see https://github.com/Leaflet/Leaflet/issues/137
\r
33438 if (!androidStock) {
\r
33439 tile.el.setAttribute('src', emptyImageUrl);
\r
33442 return GridLayer.prototype._removeTile.call(this, key);
\r
33445 _tileReady: function (coords, err, tile) {
\r
33446 if (!this._map || (tile && tile.getAttribute('src') === emptyImageUrl)) {
\r
33450 return GridLayer.prototype._tileReady.call(this, coords, err, tile);
\r
33455 // @factory L.tilelayer(urlTemplate: String, options?: TileLayer options)
\r
33456 // Instantiates a tile layer object given a `URL template` and optionally an options object.
\r
33458 function tileLayer(url, options) {
\r
33459 return new TileLayer(url, options);
\r
33463 * @class TileLayer.WMS
\r
33464 * @inherits TileLayer
\r
33465 * @aka L.TileLayer.WMS
\r
33466 * Used to display [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services as tile layers on the map. Extends `TileLayer`.
\r
33471 * var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
\r
33472 * layers: 'nexrad-n0r-900913',
\r
33473 * format: 'image/png',
\r
33474 * transparent: true,
\r
33475 * attribution: "Weather data © 2012 IEM Nexrad"
\r
33480 var TileLayerWMS = TileLayer.extend({
\r
33483 // @aka TileLayer.WMS options
\r
33484 // If any custom options not documented here are used, they will be sent to the
\r
33485 // WMS server as extra parameters in each request URL. This can be useful for
\r
33486 // [non-standard vendor WMS parameters](http://docs.geoserver.org/stable/en/user/services/wms/vendor.html).
\r
33487 defaultWmsParams: {
\r
33489 request: 'GetMap',
\r
33491 // @option layers: String = ''
\r
33492 // **(required)** Comma-separated list of WMS layers to show.
\r
33495 // @option styles: String = ''
\r
33496 // Comma-separated list of WMS styles.
\r
33499 // @option format: String = 'image/jpeg'
\r
33500 // WMS image format (use `'image/png'` for layers with transparency).
\r
33501 format: 'image/jpeg',
\r
33503 // @option transparent: Boolean = false
\r
33504 // If `true`, the WMS service will return images with transparency.
\r
33505 transparent: false,
\r
33507 // @option version: String = '1.1.1'
\r
33508 // Version of the WMS service to use
\r
33513 // @option crs: CRS = null
\r
33514 // Coordinate Reference System to use for the WMS requests, defaults to
\r
33515 // map CRS. Don't change this if you're not sure what it means.
\r
33518 // @option uppercase: Boolean = false
\r
33519 // If `true`, WMS request parameter keys will be uppercase.
\r
33523 initialize: function (url, options) {
\r
33527 var wmsParams = extend({}, this.defaultWmsParams);
\r
33529 // all keys that are not TileLayer options go to WMS params
\r
33530 for (var i in options) {
\r
33531 if (!(i in this.options)) {
\r
33532 wmsParams[i] = options[i];
\r
33536 options = setOptions(this, options);
\r
33538 var realRetina = options.detectRetina && retina ? 2 : 1;
\r
33539 var tileSize = this.getTileSize();
\r
33540 wmsParams.width = tileSize.x * realRetina;
\r
33541 wmsParams.height = tileSize.y * realRetina;
\r
33543 this.wmsParams = wmsParams;
\r
33546 onAdd: function (map) {
\r
33548 this._crs = this.options.crs || map.options.crs;
\r
33549 this._wmsVersion = parseFloat(this.wmsParams.version);
\r
33551 var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs';
\r
33552 this.wmsParams[projectionKey] = this._crs.code;
\r
33554 TileLayer.prototype.onAdd.call(this, map);
\r
33557 getTileUrl: function (coords) {
\r
33559 var tileBounds = this._tileCoordsToNwSe(coords),
\r
33561 bounds = toBounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])),
\r
33562 min = bounds.min,
\r
33563 max = bounds.max,
\r
33564 bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ?
\r
33565 [min.y, min.x, max.y, max.x] :
\r
33566 [min.x, min.y, max.x, max.y]).join(','),
\r
33567 url = TileLayer.prototype.getTileUrl.call(this, coords);
\r
33569 getParamString(this.wmsParams, url, this.options.uppercase) +
\r
33570 (this.options.uppercase ? '&BBOX=' : '&bbox=') + bbox;
\r
33573 // @method setParams(params: Object, noRedraw?: Boolean): this
\r
33574 // Merges an object with the new parameters and re-requests tiles on the current screen (unless `noRedraw` was set to true).
\r
33575 setParams: function (params, noRedraw) {
\r
33577 extend(this.wmsParams, params);
\r
33588 // @factory L.tileLayer.wms(baseUrl: String, options: TileLayer.WMS options)
\r
33589 // Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object.
\r
33590 function tileLayerWMS(url, options) {
\r
33591 return new TileLayerWMS(url, options);
\r
33594 TileLayer.WMS = TileLayerWMS;
33595 tileLayer.wms = tileLayerWMS;
33602 * Base class for vector renderer implementations (`SVG`, `Canvas`). Handles the
33603 * DOM container of the renderer, its bounds, and its zoom animation.
33605 * A `Renderer` works as an implicit layer group for all `Path`s - the renderer
33606 * itself can be added or removed to the map. All paths use a renderer, which can
33607 * be implicit (the map will decide the type of renderer and use it automatically)
33608 * or explicit (using the [`renderer`](#path-renderer) option of the path).
33610 * Do not use this class directly, use `SVG` and `Canvas` instead.
33612 * @event update: Event
33613 * Fired when the renderer updates its bounds, center and zoom, for example when
33614 * its map has moved
33617 var Renderer = Layer.extend({
33620 // @aka Renderer options
33622 // @option padding: Number = 0.1
33623 // How much to extend the clip area around the map view (relative to its size)
33624 // e.g. 0.1 would be 10% of map view in each direction
33627 // @option tolerance: Number = 0
33628 // How much to extend click tolerance round a path/object on the map
33632 initialize: function (options) {
33633 setOptions(this, options);
33635 this._layers = this._layers || {};
33638 onAdd: function () {
33639 if (!this._container) {
33640 this._initContainer(); // defined by renderer implementations
33642 if (this._zoomAnimated) {
33643 addClass(this._container, 'leaflet-zoom-animated');
33647 this.getPane().appendChild(this._container);
33649 this.on('update', this._updatePaths, this);
33652 onRemove: function () {
33653 this.off('update', this._updatePaths, this);
33654 this._destroyContainer();
33657 getEvents: function () {
33659 viewreset: this._reset,
33660 zoom: this._onZoom,
33661 moveend: this._update,
33662 zoomend: this._onZoomEnd
33664 if (this._zoomAnimated) {
33665 events.zoomanim = this._onAnimZoom;
33670 _onAnimZoom: function (ev) {
33671 this._updateTransform(ev.center, ev.zoom);
33674 _onZoom: function () {
33675 this._updateTransform(this._map.getCenter(), this._map.getZoom());
33678 _updateTransform: function (center, zoom) {
33679 var scale = this._map.getZoomScale(zoom, this._zoom),
33680 position = getPosition(this._container),
33681 viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding),
33682 currentCenterPoint = this._map.project(this._center, zoom),
33683 destCenterPoint = this._map.project(center, zoom),
33684 centerOffset = destCenterPoint.subtract(currentCenterPoint),
33686 topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(viewHalf).subtract(centerOffset);
33689 setTransform(this._container, topLeftOffset, scale);
33691 setPosition(this._container, topLeftOffset);
33695 _reset: function () {
33697 this._updateTransform(this._center, this._zoom);
33699 for (var id in this._layers) {
33700 this._layers[id]._reset();
33704 _onZoomEnd: function () {
33705 for (var id in this._layers) {
33706 this._layers[id]._project();
33710 _updatePaths: function () {
33711 for (var id in this._layers) {
33712 this._layers[id]._update();
33716 _update: function () {
33717 // Update pixel bounds of renderer container (for positioning/sizing/clipping later)
33718 // Subclasses are responsible of firing the 'update' event.
33719 var p = this.options.padding,
33720 size = this._map.getSize(),
33721 min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();
33723 this._bounds = new Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round());
33725 this._center = this._map.getCenter();
33726 this._zoom = this._map.getZoom();
33732 * @inherits Renderer
33735 * Allows vector layers to be displayed with [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).
33736 * Inherits `Renderer`.
33738 * Due to [technical limitations](http://caniuse.com/#search=canvas), Canvas is not
33739 * available in all web browsers, notably IE8, and overlapping geometries might
33740 * not display properly in some edge cases.
33744 * Use Canvas by default for all paths in the map:
33747 * var map = L.map('map', {
33748 * renderer: L.canvas()
33752 * Use a Canvas renderer with extra padding for specific vector geometries:
33755 * var map = L.map('map');
33756 * var myRenderer = L.canvas({ padding: 0.5 });
33757 * var line = L.polyline( coordinates, { renderer: myRenderer } );
33758 * var circle = L.circle( center, { renderer: myRenderer } );
33762 var Canvas = Renderer.extend({
33763 getEvents: function () {
33764 var events = Renderer.prototype.getEvents.call(this);
33765 events.viewprereset = this._onViewPreReset;
33769 _onViewPreReset: function () {
33770 // Set a flag so that a viewprereset+moveend+viewreset only updates&redraws once
33771 this._postponeUpdatePaths = true;
33774 onAdd: function () {
33775 Renderer.prototype.onAdd.call(this);
33777 // Redraw vectors since canvas is cleared upon removal,
33778 // in case of removing the renderer itself from the map.
33782 _initContainer: function () {
33783 var container = this._container = document.createElement('canvas');
33785 on(container, 'mousemove', this._onMouseMove, this);
33786 on(container, 'click dblclick mousedown mouseup contextmenu', this._onClick, this);
33787 on(container, 'mouseout', this._handleMouseOut, this);
33789 this._ctx = container.getContext('2d');
33792 _destroyContainer: function () {
33793 cancelAnimFrame(this._redrawRequest);
33795 remove(this._container);
33796 off(this._container);
33797 delete this._container;
33800 _updatePaths: function () {
33801 if (this._postponeUpdatePaths) { return; }
33804 this._redrawBounds = null;
33805 for (var id in this._layers) {
33806 layer = this._layers[id];
33812 _update: function () {
33813 if (this._map._animatingZoom && this._bounds) { return; }
33815 Renderer.prototype._update.call(this);
33817 var b = this._bounds,
33818 container = this._container,
33819 size = b.getSize(),
33820 m = retina ? 2 : 1;
33822 setPosition(container, b.min);
33824 // set canvas size (also clearing it); use double size on retina
33825 container.width = m * size.x;
33826 container.height = m * size.y;
33827 container.style.width = size.x + 'px';
33828 container.style.height = size.y + 'px';
33831 this._ctx.scale(2, 2);
33834 // translate so we use the same path coordinates after canvas element moves
33835 this._ctx.translate(-b.min.x, -b.min.y);
33837 // Tell paths to redraw themselves
33838 this.fire('update');
33841 _reset: function () {
33842 Renderer.prototype._reset.call(this);
33844 if (this._postponeUpdatePaths) {
33845 this._postponeUpdatePaths = false;
33846 this._updatePaths();
33850 _initPath: function (layer) {
33851 this._updateDashArray(layer);
33852 this._layers[stamp(layer)] = layer;
33854 var order = layer._order = {
33856 prev: this._drawLast,
33859 if (this._drawLast) { this._drawLast.next = order; }
33860 this._drawLast = order;
33861 this._drawFirst = this._drawFirst || this._drawLast;
33864 _addPath: function (layer) {
33865 this._requestRedraw(layer);
33868 _removePath: function (layer) {
33869 var order = layer._order;
33870 var next = order.next;
33871 var prev = order.prev;
33876 this._drawLast = prev;
33881 this._drawFirst = next;
33884 delete layer._order;
33886 delete this._layers[stamp(layer)];
33888 this._requestRedraw(layer);
33891 _updatePath: function (layer) {
33892 // Redraw the union of the layer's old pixel
33893 // bounds and the new pixel bounds.
33894 this._extendRedrawBounds(layer);
33897 // The redraw will extend the redraw bounds
33898 // with the new pixel bounds.
33899 this._requestRedraw(layer);
33902 _updateStyle: function (layer) {
33903 this._updateDashArray(layer);
33904 this._requestRedraw(layer);
33907 _updateDashArray: function (layer) {
33908 if (typeof layer.options.dashArray === 'string') {
33909 var parts = layer.options.dashArray.split(/[, ]+/),
33913 for (i = 0; i < parts.length; i++) {
33914 dashValue = Number(parts[i]);
33915 // Ignore dash array containing invalid lengths
33916 if (isNaN(dashValue)) { return; }
33917 dashArray.push(dashValue);
33919 layer.options._dashArray = dashArray;
33921 layer.options._dashArray = layer.options.dashArray;
33925 _requestRedraw: function (layer) {
33926 if (!this._map) { return; }
33928 this._extendRedrawBounds(layer);
33929 this._redrawRequest = this._redrawRequest || requestAnimFrame(this._redraw, this);
33932 _extendRedrawBounds: function (layer) {
33933 if (layer._pxBounds) {
33934 var padding = (layer.options.weight || 0) + 1;
33935 this._redrawBounds = this._redrawBounds || new Bounds();
33936 this._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding]));
33937 this._redrawBounds.extend(layer._pxBounds.max.add([padding, padding]));
33941 _redraw: function () {
33942 this._redrawRequest = null;
33944 if (this._redrawBounds) {
33945 this._redrawBounds.min._floor();
33946 this._redrawBounds.max._ceil();
33949 this._clear(); // clear layers in redraw bounds
33950 this._draw(); // draw layers
33952 this._redrawBounds = null;
33955 _clear: function () {
33956 var bounds = this._redrawBounds;
33958 var size = bounds.getSize();
33959 this._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y);
33962 this._ctx.setTransform(1, 0, 0, 1, 0, 0);
33963 this._ctx.clearRect(0, 0, this._container.width, this._container.height);
33964 this._ctx.restore();
33968 _draw: function () {
33969 var layer, bounds = this._redrawBounds;
33972 var size = bounds.getSize();
33973 this._ctx.beginPath();
33974 this._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y);
33978 this._drawing = true;
33980 for (var order = this._drawFirst; order; order = order.next) {
33981 layer = order.layer;
33982 if (!bounds || (layer._pxBounds && layer._pxBounds.intersects(bounds))) {
33983 layer._updatePath();
33987 this._drawing = false;
33989 this._ctx.restore(); // Restore state before clipping.
33992 _updatePoly: function (layer, closed) {
33993 if (!this._drawing) { return; }
33996 parts = layer._parts,
33997 len = parts.length,
34000 if (!len) { return; }
34004 for (i = 0; i < len; i++) {
34005 for (j = 0, len2 = parts[i].length; j < len2; j++) {
34007 ctx[j ? 'lineTo' : 'moveTo'](p.x, p.y);
34014 this._fillStroke(ctx, layer);
34016 // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
34019 _updateCircle: function (layer) {
34021 if (!this._drawing || layer._empty()) { return; }
34023 var p = layer._point,
34025 r = Math.max(Math.round(layer._radius), 1),
34026 s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;
34034 ctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false);
34040 this._fillStroke(ctx, layer);
34043 _fillStroke: function (ctx, layer) {
34044 var options = layer.options;
34046 if (options.fill) {
34047 ctx.globalAlpha = options.fillOpacity;
34048 ctx.fillStyle = options.fillColor || options.color;
34049 ctx.fill(options.fillRule || 'evenodd');
34052 if (options.stroke && options.weight !== 0) {
34053 if (ctx.setLineDash) {
34054 ctx.setLineDash(layer.options && layer.options._dashArray || []);
34056 ctx.globalAlpha = options.opacity;
34057 ctx.lineWidth = options.weight;
34058 ctx.strokeStyle = options.color;
34059 ctx.lineCap = options.lineCap;
34060 ctx.lineJoin = options.lineJoin;
34065 // Canvas obviously doesn't have mouse events for individual drawn objects,
34066 // so we emulate that by calculating what's under the mouse on mousemove/click manually
34068 _onClick: function (e) {
34069 var point = this._map.mouseEventToLayerPoint(e), layer, clickedLayer;
34071 for (var order = this._drawFirst; order; order = order.next) {
34072 layer = order.layer;
34073 if (layer.options.interactive && layer._containsPoint(point)) {
34074 if (!(e.type === 'click' || e.type !== 'preclick') || !this._map._draggableMoved(layer)) {
34075 clickedLayer = layer;
34079 if (clickedLayer) {
34081 this._fireEvent([clickedLayer], e);
34085 _onMouseMove: function (e) {
34086 if (!this._map || this._map.dragging.moving() || this._map._animatingZoom) { return; }
34088 var point = this._map.mouseEventToLayerPoint(e);
34089 this._handleMouseHover(e, point);
34093 _handleMouseOut: function (e) {
34094 var layer = this._hoveredLayer;
34096 // if we're leaving the layer, fire mouseout
34097 removeClass(this._container, 'leaflet-interactive');
34098 this._fireEvent([layer], e, 'mouseout');
34099 this._hoveredLayer = null;
34100 this._mouseHoverThrottled = false;
34104 _handleMouseHover: function (e, point) {
34105 if (this._mouseHoverThrottled) {
34109 var layer, candidateHoveredLayer;
34111 for (var order = this._drawFirst; order; order = order.next) {
34112 layer = order.layer;
34113 if (layer.options.interactive && layer._containsPoint(point)) {
34114 candidateHoveredLayer = layer;
34118 if (candidateHoveredLayer !== this._hoveredLayer) {
34119 this._handleMouseOut(e);
34121 if (candidateHoveredLayer) {
34122 addClass(this._container, 'leaflet-interactive'); // change cursor
34123 this._fireEvent([candidateHoveredLayer], e, 'mouseover');
34124 this._hoveredLayer = candidateHoveredLayer;
34128 if (this._hoveredLayer) {
34129 this._fireEvent([this._hoveredLayer], e);
34132 this._mouseHoverThrottled = true;
34133 setTimeout(bind(function () {
34134 this._mouseHoverThrottled = false;
34138 _fireEvent: function (layers, e, type) {
34139 this._map._fireDOMEvent(e, type || e.type, layers);
34142 _bringToFront: function (layer) {
34143 var order = layer._order;
34145 if (!order) { return; }
34147 var next = order.next;
34148 var prev = order.prev;
34159 // Update first entry unless this is the
34161 this._drawFirst = next;
34164 order.prev = this._drawLast;
34165 this._drawLast.next = order;
34168 this._drawLast = order;
34170 this._requestRedraw(layer);
34173 _bringToBack: function (layer) {
34174 var order = layer._order;
34176 if (!order) { return; }
34178 var next = order.next;
34179 var prev = order.prev;
34190 // Update last entry unless this is the
34192 this._drawLast = prev;
34197 order.next = this._drawFirst;
34198 this._drawFirst.prev = order;
34199 this._drawFirst = order;
34201 this._requestRedraw(layer);
34205 // @factory L.canvas(options?: Renderer options)
34206 // Creates a Canvas renderer with the given options.
34207 function canvas$1(options) {
34208 return canvas ? new Canvas(options) : null;
34212 * Thanks to Dmitry Baranovsky and his Raphael library for inspiration!
34216 var vmlCreate = (function () {
34218 document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml');
34219 return function (name) {
34220 return document.createElement('<lvml:' + name + ' class="lvml">');
34223 return function (name) {
34224 return document.createElement('<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">');
34234 * VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility
34235 * with old versions of Internet Explorer.
34238 // mixin to redefine some SVG methods to handle VML syntax which is similar but with some differences
34241 _initContainer: function () {
34242 this._container = create$1('div', 'leaflet-vml-container');
34245 _update: function () {
34246 if (this._map._animatingZoom) { return; }
34247 Renderer.prototype._update.call(this);
34248 this.fire('update');
34251 _initPath: function (layer) {
34252 var container = layer._container = vmlCreate('shape');
34254 addClass(container, 'leaflet-vml-shape ' + (this.options.className || ''));
34256 container.coordsize = '1 1';
34258 layer._path = vmlCreate('path');
34259 container.appendChild(layer._path);
34261 this._updateStyle(layer);
34262 this._layers[stamp(layer)] = layer;
34265 _addPath: function (layer) {
34266 var container = layer._container;
34267 this._container.appendChild(container);
34269 if (layer.options.interactive) {
34270 layer.addInteractiveTarget(container);
34274 _removePath: function (layer) {
34275 var container = layer._container;
34277 layer.removeInteractiveTarget(container);
34278 delete this._layers[stamp(layer)];
34281 _updateStyle: function (layer) {
34282 var stroke = layer._stroke,
34283 fill = layer._fill,
34284 options = layer.options,
34285 container = layer._container;
34287 container.stroked = !!options.stroke;
34288 container.filled = !!options.fill;
34290 if (options.stroke) {
34292 stroke = layer._stroke = vmlCreate('stroke');
34294 container.appendChild(stroke);
34295 stroke.weight = options.weight + 'px';
34296 stroke.color = options.color;
34297 stroke.opacity = options.opacity;
34299 if (options.dashArray) {
34300 stroke.dashStyle = isArray(options.dashArray) ?
34301 options.dashArray.join(' ') :
34302 options.dashArray.replace(/( *, *)/g, ' ');
34304 stroke.dashStyle = '';
34306 stroke.endcap = options.lineCap.replace('butt', 'flat');
34307 stroke.joinstyle = options.lineJoin;
34309 } else if (stroke) {
34310 container.removeChild(stroke);
34311 layer._stroke = null;
34314 if (options.fill) {
34316 fill = layer._fill = vmlCreate('fill');
34318 container.appendChild(fill);
34319 fill.color = options.fillColor || options.color;
34320 fill.opacity = options.fillOpacity;
34323 container.removeChild(fill);
34324 layer._fill = null;
34328 _updateCircle: function (layer) {
34329 var p = layer._point.round(),
34330 r = Math.round(layer._radius),
34331 r2 = Math.round(layer._radiusY || r);
34333 this._setPath(layer, layer._empty() ? 'M0 0' :
34334 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360));
34337 _setPath: function (layer, path) {
34338 layer._path.v = path;
34341 _bringToFront: function (layer) {
34342 toFront(layer._container);
34345 _bringToBack: function (layer) {
34346 toBack(layer._container);
34350 var create$2 = vml ? vmlCreate : svgCreate;
34354 * @inherits Renderer
34357 * Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG).
34358 * Inherits `Renderer`.
34360 * Due to [technical limitations](http://caniuse.com/#search=svg), SVG is not
34361 * available in all web browsers, notably Android 2.x and 3.x.
34363 * Although SVG is not available on IE7 and IE8, these browsers support
34364 * [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language)
34365 * (a now deprecated technology), and the SVG renderer will fall back to VML in
34370 * Use SVG by default for all paths in the map:
34373 * var map = L.map('map', {
34374 * renderer: L.svg()
34378 * Use a SVG renderer with extra padding for specific vector geometries:
34381 * var map = L.map('map');
34382 * var myRenderer = L.svg({ padding: 0.5 });
34383 * var line = L.polyline( coordinates, { renderer: myRenderer } );
34384 * var circle = L.circle( center, { renderer: myRenderer } );
34388 var SVG = Renderer.extend({
34390 getEvents: function () {
34391 var events = Renderer.prototype.getEvents.call(this);
34392 events.zoomstart = this._onZoomStart;
34396 _initContainer: function () {
34397 this._container = create$2('svg');
34399 // makes it possible to click through svg root; we'll reset it back in individual paths
34400 this._container.setAttribute('pointer-events', 'none');
34402 this._rootGroup = create$2('g');
34403 this._container.appendChild(this._rootGroup);
34406 _destroyContainer: function () {
34407 remove(this._container);
34408 off(this._container);
34409 delete this._container;
34410 delete this._rootGroup;
34411 delete this._svgSize;
34414 _onZoomStart: function () {
34415 // Drag-then-pinch interactions might mess up the center and zoom.
34416 // In this case, the easiest way to prevent this is re-do the renderer
34417 // bounds and padding when the zooming starts.
34421 _update: function () {
34422 if (this._map._animatingZoom && this._bounds) { return; }
34424 Renderer.prototype._update.call(this);
34426 var b = this._bounds,
34427 size = b.getSize(),
34428 container = this._container;
34430 // set size of svg-container if changed
34431 if (!this._svgSize || !this._svgSize.equals(size)) {
34432 this._svgSize = size;
34433 container.setAttribute('width', size.x);
34434 container.setAttribute('height', size.y);
34437 // movement: update container viewBox so that we don't have to change coordinates of individual layers
34438 setPosition(container, b.min);
34439 container.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));
34441 this.fire('update');
34444 // methods below are called by vector layers implementations
34446 _initPath: function (layer) {
34447 var path = layer._path = create$2('path');
34450 // @option className: String = null
34451 // Custom class name set on an element. Only for SVG renderer.
34452 if (layer.options.className) {
34453 addClass(path, layer.options.className);
34456 if (layer.options.interactive) {
34457 addClass(path, 'leaflet-interactive');
34460 this._updateStyle(layer);
34461 this._layers[stamp(layer)] = layer;
34464 _addPath: function (layer) {
34465 if (!this._rootGroup) { this._initContainer(); }
34466 this._rootGroup.appendChild(layer._path);
34467 layer.addInteractiveTarget(layer._path);
34470 _removePath: function (layer) {
34471 remove(layer._path);
34472 layer.removeInteractiveTarget(layer._path);
34473 delete this._layers[stamp(layer)];
34476 _updatePath: function (layer) {
34481 _updateStyle: function (layer) {
34482 var path = layer._path,
34483 options = layer.options;
34485 if (!path) { return; }
34487 if (options.stroke) {
34488 path.setAttribute('stroke', options.color);
34489 path.setAttribute('stroke-opacity', options.opacity);
34490 path.setAttribute('stroke-width', options.weight);
34491 path.setAttribute('stroke-linecap', options.lineCap);
34492 path.setAttribute('stroke-linejoin', options.lineJoin);
34494 if (options.dashArray) {
34495 path.setAttribute('stroke-dasharray', options.dashArray);
34497 path.removeAttribute('stroke-dasharray');
34500 if (options.dashOffset) {
34501 path.setAttribute('stroke-dashoffset', options.dashOffset);
34503 path.removeAttribute('stroke-dashoffset');
34506 path.setAttribute('stroke', 'none');
34509 if (options.fill) {
34510 path.setAttribute('fill', options.fillColor || options.color);
34511 path.setAttribute('fill-opacity', options.fillOpacity);
34512 path.setAttribute('fill-rule', options.fillRule || 'evenodd');
34514 path.setAttribute('fill', 'none');
34518 _updatePoly: function (layer, closed) {
34519 this._setPath(layer, pointsToPath(layer._parts, closed));
34522 _updateCircle: function (layer) {
34523 var p = layer._point,
34524 r = Math.max(Math.round(layer._radius), 1),
34525 r2 = Math.max(Math.round(layer._radiusY), 1) || r,
34526 arc = 'a' + r + ',' + r2 + ' 0 1,0 ';
34528 // drawing a circle with two half-arcs
34529 var d = layer._empty() ? 'M0 0' :
34530 'M' + (p.x - r) + ',' + p.y +
34531 arc + (r * 2) + ',0 ' +
34532 arc + (-r * 2) + ',0 ';
34534 this._setPath(layer, d);
34537 _setPath: function (layer, path) {
34538 layer._path.setAttribute('d', path);
34541 // SVG does not have the concept of zIndex so we resort to changing the DOM order of elements
34542 _bringToFront: function (layer) {
34543 toFront(layer._path);
34546 _bringToBack: function (layer) {
34547 toBack(layer._path);
34552 SVG.include(vmlMixin);
34556 // @factory L.svg(options?: Renderer options)
34557 // Creates a SVG renderer with the given options.
34558 function svg$1(options) {
34559 return svg || vml ? new SVG(options) : null;
34563 // @namespace Map; @method getRenderer(layer: Path): Renderer
34564 // Returns the instance of `Renderer` that should be used to render the given
34565 // `Path`. It will ensure that the `renderer` options of the map and paths
34566 // are respected, and that the renderers do exist on the map.
34567 getRenderer: function (layer) {
34568 // @namespace Path; @option renderer: Renderer
34569 // Use this specific instance of `Renderer` for this path. Takes
34570 // precedence over the map's [default renderer](#map-renderer).
34571 var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;
34574 renderer = this._renderer = this._createRenderer();
34577 if (!this.hasLayer(renderer)) {
34578 this.addLayer(renderer);
34583 _getPaneRenderer: function (name) {
34584 if (name === 'overlayPane' || name === undefined) {
34588 var renderer = this._paneRenderers[name];
34589 if (renderer === undefined) {
34590 renderer = this._createRenderer({pane: name});
34591 this._paneRenderers[name] = renderer;
34596 _createRenderer: function (options) {
34597 // @namespace Map; @option preferCanvas: Boolean = false
34598 // Whether `Path`s should be rendered on a `Canvas` renderer.
34599 // By default, all `Path`s are rendered in a `SVG` renderer.
34600 return (this.options.preferCanvas && canvas$1(options)) || svg$1(options);
34605 * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object.
34611 * @inherits Polygon
34613 * A class for drawing rectangle overlays on a map. Extends `Polygon`.
34618 * // define rectangle geographical bounds
34619 * var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
34621 * // create an orange rectangle
34622 * L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
34624 * // zoom the map to the rectangle bounds
34625 * map.fitBounds(bounds);
34631 var Rectangle = Polygon.extend({
34632 initialize: function (latLngBounds, options) {
34633 Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options);
34636 // @method setBounds(latLngBounds: LatLngBounds): this
34637 // Redraws the rectangle with the passed bounds.
34638 setBounds: function (latLngBounds) {
34639 return this.setLatLngs(this._boundsToLatLngs(latLngBounds));
34642 _boundsToLatLngs: function (latLngBounds) {
34643 latLngBounds = toLatLngBounds(latLngBounds);
34645 latLngBounds.getSouthWest(),
34646 latLngBounds.getNorthWest(),
34647 latLngBounds.getNorthEast(),
34648 latLngBounds.getSouthEast()
34654 // @factory L.rectangle(latLngBounds: LatLngBounds, options?: Polyline options)
34655 function rectangle(latLngBounds, options) {
34656 return new Rectangle(latLngBounds, options);
34659 SVG.create = create$2;
34660 SVG.pointsToPath = pointsToPath;
34662 GeoJSON.geometryToLayer = geometryToLayer;
34663 GeoJSON.coordsToLatLng = coordsToLatLng;
34664 GeoJSON.coordsToLatLngs = coordsToLatLngs;
34665 GeoJSON.latLngToCoords = latLngToCoords;
34666 GeoJSON.latLngsToCoords = latLngsToCoords;
34667 GeoJSON.getFeature = getFeature;
34668 GeoJSON.asFeature = asFeature;
34671 * L.Handler.BoxZoom is used to add shift-drag zoom interaction to the map
34672 * (zoom to a selected bounding box), enabled by default.
34676 // @section Interaction Options
34678 // @option boxZoom: Boolean = true
34679 // Whether the map can be zoomed to a rectangular area specified by
34680 // dragging the mouse while pressing the shift key.
34684 var BoxZoom = Handler.extend({
34685 initialize: function (map) {
34687 this._container = map._container;
34688 this._pane = map._panes.overlayPane;
34689 this._resetStateTimeout = 0;
34690 map.on('unload', this._destroy, this);
34693 addHooks: function () {
34694 on(this._container, 'mousedown', this._onMouseDown, this);
34697 removeHooks: function () {
34698 off(this._container, 'mousedown', this._onMouseDown, this);
34701 moved: function () {
34702 return this._moved;
34705 _destroy: function () {
34706 remove(this._pane);
34710 _resetState: function () {
34711 this._resetStateTimeout = 0;
34712 this._moved = false;
34715 _clearDeferredResetState: function () {
34716 if (this._resetStateTimeout !== 0) {
34717 clearTimeout(this._resetStateTimeout);
34718 this._resetStateTimeout = 0;
34722 _onMouseDown: function (e) {
34723 if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }
34725 // Clear the deferred resetState if it hasn't executed yet, otherwise it
34726 // will interrupt the interaction and orphan a box element in the container.
34727 this._clearDeferredResetState();
34728 this._resetState();
34730 disableTextSelection();
34731 disableImageDrag();
34733 this._startPoint = this._map.mouseEventToContainerPoint(e);
34737 mousemove: this._onMouseMove,
34738 mouseup: this._onMouseUp,
34739 keydown: this._onKeyDown
34743 _onMouseMove: function (e) {
34744 if (!this._moved) {
34745 this._moved = true;
34747 this._box = create$1('div', 'leaflet-zoom-box', this._container);
34748 addClass(this._container, 'leaflet-crosshair');
34750 this._map.fire('boxzoomstart');
34753 this._point = this._map.mouseEventToContainerPoint(e);
34755 var bounds = new Bounds(this._point, this._startPoint),
34756 size = bounds.getSize();
34758 setPosition(this._box, bounds.min);
34760 this._box.style.width = size.x + 'px';
34761 this._box.style.height = size.y + 'px';
34764 _finish: function () {
34767 removeClass(this._container, 'leaflet-crosshair');
34770 enableTextSelection();
34775 mousemove: this._onMouseMove,
34776 mouseup: this._onMouseUp,
34777 keydown: this._onKeyDown
34781 _onMouseUp: function (e) {
34782 if ((e.which !== 1) && (e.button !== 1)) { return; }
34786 if (!this._moved) { return; }
34787 // Postpone to next JS tick so internal click event handling
34788 // still see it as "moved".
34789 this._clearDeferredResetState();
34790 this._resetStateTimeout = setTimeout(bind(this._resetState, this), 0);
34792 var bounds = new LatLngBounds(
34793 this._map.containerPointToLatLng(this._startPoint),
34794 this._map.containerPointToLatLng(this._point));
34798 .fire('boxzoomend', {boxZoomBounds: bounds});
34801 _onKeyDown: function (e) {
34802 if (e.keyCode === 27) {
34808 // @section Handlers
34809 // @property boxZoom: Handler
34810 // Box (shift-drag with mouse) zoom handler.
34811 Map.addInitHook('addHandler', 'boxZoom', BoxZoom);
34814 * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default.
34818 // @section Interaction Options
34821 // @option doubleClickZoom: Boolean|String = true
34822 // Whether the map can be zoomed in by double clicking on it and
34823 // zoomed out by double clicking while holding shift. If passed
34824 // `'center'`, double-click zoom will zoom to the center of the
34825 // view regardless of where the mouse was.
34826 doubleClickZoom: true
34829 var DoubleClickZoom = Handler.extend({
34830 addHooks: function () {
34831 this._map.on('dblclick', this._onDoubleClick, this);
34834 removeHooks: function () {
34835 this._map.off('dblclick', this._onDoubleClick, this);
34838 _onDoubleClick: function (e) {
34839 var map = this._map,
34840 oldZoom = map.getZoom(),
34841 delta = map.options.zoomDelta,
34842 zoom = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta;
34844 if (map.options.doubleClickZoom === 'center') {
34847 map.setZoomAround(e.containerPoint, zoom);
34852 // @section Handlers
34854 // Map properties include interaction handlers that allow you to control
34855 // interaction behavior in runtime, enabling or disabling certain features such
34856 // as dragging or touch zoom (see `Handler` methods). For example:
34859 // map.doubleClickZoom.disable();
34862 // @property doubleClickZoom: Handler
34863 // Double click zoom handler.
34864 Map.addInitHook('addHandler', 'doubleClickZoom', DoubleClickZoom);
34867 * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default.
34871 // @section Interaction Options
34873 // @option dragging: Boolean = true
34874 // Whether the map be draggable with mouse/touch or not.
34877 // @section Panning Inertia Options
34878 // @option inertia: Boolean = *
34879 // If enabled, panning of the map will have an inertia effect where
34880 // the map builds momentum while dragging and continues moving in
34881 // the same direction for some time. Feels especially nice on touch
34882 // devices. Enabled by default unless running on old Android devices.
34883 inertia: !android23,
34885 // @option inertiaDeceleration: Number = 3000
34886 // The rate with which the inertial movement slows down, in pixels/second².
34887 inertiaDeceleration: 3400, // px/s^2
34889 // @option inertiaMaxSpeed: Number = Infinity
34890 // Max speed of the inertial movement, in pixels/second.
34891 inertiaMaxSpeed: Infinity, // px/s
34893 // @option easeLinearity: Number = 0.2
34894 easeLinearity: 0.2,
34896 // TODO refactor, move to CRS
34897 // @option worldCopyJump: Boolean = false
34898 // With this option enabled, the map tracks when you pan to another "copy"
34899 // of the world and seamlessly jumps to the original one so that all overlays
34900 // like markers and vector layers are still visible.
34901 worldCopyJump: false,
34903 // @option maxBoundsViscosity: Number = 0.0
34904 // If `maxBounds` is set, this option will control how solid the bounds
34905 // are when dragging the map around. The default value of `0.0` allows the
34906 // user to drag outside the bounds at normal speed, higher values will
34907 // slow down map dragging outside bounds, and `1.0` makes the bounds fully
34908 // solid, preventing the user from dragging outside the bounds.
34909 maxBoundsViscosity: 0.0
34912 var Drag = Handler.extend({
34913 addHooks: function () {
34914 if (!this._draggable) {
34915 var map = this._map;
34917 this._draggable = new Draggable(map._mapPane, map._container);
34919 this._draggable.on({
34920 dragstart: this._onDragStart,
34921 drag: this._onDrag,
34922 dragend: this._onDragEnd
34925 this._draggable.on('predrag', this._onPreDragLimit, this);
34926 if (map.options.worldCopyJump) {
34927 this._draggable.on('predrag', this._onPreDragWrap, this);
34928 map.on('zoomend', this._onZoomEnd, this);
34930 map.whenReady(this._onZoomEnd, this);
34933 addClass(this._map._container, 'leaflet-grab leaflet-touch-drag');
34934 this._draggable.enable();
34935 this._positions = [];
34939 removeHooks: function () {
34940 removeClass(this._map._container, 'leaflet-grab');
34941 removeClass(this._map._container, 'leaflet-touch-drag');
34942 this._draggable.disable();
34945 moved: function () {
34946 return this._draggable && this._draggable._moved;
34949 moving: function () {
34950 return this._draggable && this._draggable._moving;
34953 _onDragStart: function () {
34954 var map = this._map;
34957 if (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) {
34958 var bounds = toLatLngBounds(this._map.options.maxBounds);
34960 this._offsetLimit = toBounds(
34961 this._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1),
34962 this._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1)
34963 .add(this._map.getSize()));
34965 this._viscosity = Math.min(1.0, Math.max(0.0, this._map.options.maxBoundsViscosity));
34967 this._offsetLimit = null;
34972 .fire('dragstart');
34974 if (map.options.inertia) {
34975 this._positions = [];
34980 _onDrag: function (e) {
34981 if (this._map.options.inertia) {
34982 var time = this._lastTime = +new Date(),
34983 pos = this._lastPos = this._draggable._absPos || this._draggable._newPos;
34985 this._positions.push(pos);
34986 this._times.push(time);
34988 this._prunePositions(time);
34996 _prunePositions: function (time) {
34997 while (this._positions.length > 1 && time - this._times[0] > 50) {
34998 this._positions.shift();
34999 this._times.shift();
35003 _onZoomEnd: function () {
35004 var pxCenter = this._map.getSize().divideBy(2),
35005 pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);
35007 this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;
35008 this._worldWidth = this._map.getPixelWorldBounds().getSize().x;
35011 _viscousLimit: function (value, threshold) {
35012 return value - (value - threshold) * this._viscosity;
35015 _onPreDragLimit: function () {
35016 if (!this._viscosity || !this._offsetLimit) { return; }
35018 var offset = this._draggable._newPos.subtract(this._draggable._startPos);
35020 var limit = this._offsetLimit;
35021 if (offset.x < limit.min.x) { offset.x = this._viscousLimit(offset.x, limit.min.x); }
35022 if (offset.y < limit.min.y) { offset.y = this._viscousLimit(offset.y, limit.min.y); }
35023 if (offset.x > limit.max.x) { offset.x = this._viscousLimit(offset.x, limit.max.x); }
35024 if (offset.y > limit.max.y) { offset.y = this._viscousLimit(offset.y, limit.max.y); }
35026 this._draggable._newPos = this._draggable._startPos.add(offset);
35029 _onPreDragWrap: function () {
35030 // TODO refactor to be able to adjust map pane position after zoom
35031 var worldWidth = this._worldWidth,
35032 halfWidth = Math.round(worldWidth / 2),
35033 dx = this._initialWorldOffset,
35034 x = this._draggable._newPos.x,
35035 newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx,
35036 newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx,
35037 newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;
35039 this._draggable._absPos = this._draggable._newPos.clone();
35040 this._draggable._newPos.x = newX;
35043 _onDragEnd: function (e) {
35044 var map = this._map,
35045 options = map.options,
35047 noInertia = !options.inertia || this._times.length < 2;
35049 map.fire('dragend', e);
35052 map.fire('moveend');
35055 this._prunePositions(+new Date());
35057 var direction = this._lastPos.subtract(this._positions[0]),
35058 duration = (this._lastTime - this._times[0]) / 1000,
35059 ease = options.easeLinearity,
35061 speedVector = direction.multiplyBy(ease / duration),
35062 speed = speedVector.distanceTo([0, 0]),
35064 limitedSpeed = Math.min(options.inertiaMaxSpeed, speed),
35065 limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed),
35067 decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease),
35068 offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();
35070 if (!offset.x && !offset.y) {
35071 map.fire('moveend');
35074 offset = map._limitOffset(offset, map.options.maxBounds);
35076 requestAnimFrame(function () {
35077 map.panBy(offset, {
35078 duration: decelerationDuration,
35079 easeLinearity: ease,
35089 // @section Handlers
35090 // @property dragging: Handler
35091 // Map dragging handler (by both mouse and touch).
35092 Map.addInitHook('addHandler', 'dragging', Drag);
35095 * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default.
35099 // @section Keyboard Navigation Options
35101 // @option keyboard: Boolean = true
35102 // Makes the map focusable and allows users to navigate the map with keyboard
35103 // arrows and `+`/`-` keys.
35106 // @option keyboardPanDelta: Number = 80
35107 // Amount of pixels to pan when pressing an arrow key.
35108 keyboardPanDelta: 80
35111 var Keyboard = Handler.extend({
35118 zoomIn: [187, 107, 61, 171],
35119 zoomOut: [189, 109, 54, 173]
35122 initialize: function (map) {
35125 this._setPanDelta(map.options.keyboardPanDelta);
35126 this._setZoomDelta(map.options.zoomDelta);
35129 addHooks: function () {
35130 var container = this._map._container;
35132 // make the container focusable by tabbing
35133 if (container.tabIndex <= 0) {
35134 container.tabIndex = '0';
35138 focus: this._onFocus,
35139 blur: this._onBlur,
35140 mousedown: this._onMouseDown
35144 focus: this._addHooks,
35145 blur: this._removeHooks
35149 removeHooks: function () {
35150 this._removeHooks();
35152 off(this._map._container, {
35153 focus: this._onFocus,
35154 blur: this._onBlur,
35155 mousedown: this._onMouseDown
35159 focus: this._addHooks,
35160 blur: this._removeHooks
35164 _onMouseDown: function () {
35165 if (this._focused) { return; }
35167 var body = document.body,
35168 docEl = document.documentElement,
35169 top = body.scrollTop || docEl.scrollTop,
35170 left = body.scrollLeft || docEl.scrollLeft;
35172 this._map._container.focus();
35174 window.scrollTo(left, top);
35177 _onFocus: function () {
35178 this._focused = true;
35179 this._map.fire('focus');
35182 _onBlur: function () {
35183 this._focused = false;
35184 this._map.fire('blur');
35187 _setPanDelta: function (panDelta) {
35188 var keys = this._panKeys = {},
35189 codes = this.keyCodes,
35192 for (i = 0, len = codes.left.length; i < len; i++) {
35193 keys[codes.left[i]] = [-1 * panDelta, 0];
35195 for (i = 0, len = codes.right.length; i < len; i++) {
35196 keys[codes.right[i]] = [panDelta, 0];
35198 for (i = 0, len = codes.down.length; i < len; i++) {
35199 keys[codes.down[i]] = [0, panDelta];
35201 for (i = 0, len = codes.up.length; i < len; i++) {
35202 keys[codes.up[i]] = [0, -1 * panDelta];
35206 _setZoomDelta: function (zoomDelta) {
35207 var keys = this._zoomKeys = {},
35208 codes = this.keyCodes,
35211 for (i = 0, len = codes.zoomIn.length; i < len; i++) {
35212 keys[codes.zoomIn[i]] = zoomDelta;
35214 for (i = 0, len = codes.zoomOut.length; i < len; i++) {
35215 keys[codes.zoomOut[i]] = -zoomDelta;
35219 _addHooks: function () {
35220 on(document, 'keydown', this._onKeyDown, this);
35223 _removeHooks: function () {
35224 off(document, 'keydown', this._onKeyDown, this);
35227 _onKeyDown: function (e) {
35228 if (e.altKey || e.ctrlKey || e.metaKey) { return; }
35230 var key = e.keyCode,
35234 if (key in this._panKeys) {
35235 if (!map._panAnim || !map._panAnim._inProgress) {
35236 offset = this._panKeys[key];
35238 offset = toPoint(offset).multiplyBy(3);
35243 if (map.options.maxBounds) {
35244 map.panInsideBounds(map.options.maxBounds);
35247 } else if (key in this._zoomKeys) {
35248 map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);
35250 } else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) {
35261 // @section Handlers
35262 // @section Handlers
35263 // @property keyboard: Handler
35264 // Keyboard navigation handler.
35265 Map.addInitHook('addHandler', 'keyboard', Keyboard);
35268 * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map.
35272 // @section Interaction Options
35274 // @section Mouse wheel options
35275 // @option scrollWheelZoom: Boolean|String = true
35276 // Whether the map can be zoomed by using the mouse wheel. If passed `'center'`,
35277 // it will zoom to the center of the view regardless of where the mouse was.
35278 scrollWheelZoom: true,
35280 // @option wheelDebounceTime: Number = 40
35281 // Limits the rate at which a wheel can fire (in milliseconds). By default
35282 // user can't zoom via wheel more often than once per 40 ms.
35283 wheelDebounceTime: 40,
35285 // @option wheelPxPerZoomLevel: Number = 60
35286 // How many scroll pixels (as reported by [L.DomEvent.getWheelDelta](#domevent-getwheeldelta))
35287 // mean a change of one full zoom level. Smaller values will make wheel-zooming
35288 // faster (and vice versa).
35289 wheelPxPerZoomLevel: 60
35292 var ScrollWheelZoom = Handler.extend({
35293 addHooks: function () {
35294 on(this._map._container, 'wheel', this._onWheelScroll, this);
35299 removeHooks: function () {
35300 off(this._map._container, 'wheel', this._onWheelScroll, this);
35303 _onWheelScroll: function (e) {
35304 var delta = getWheelDelta(e);
35306 var debounce = this._map.options.wheelDebounceTime;
35308 this._delta += delta;
35309 this._lastMousePos = this._map.mouseEventToContainerPoint(e);
35311 if (!this._startTime) {
35312 this._startTime = +new Date();
35315 var left = Math.max(debounce - (+new Date() - this._startTime), 0);
35317 clearTimeout(this._timer);
35318 this._timer = setTimeout(bind(this._performZoom, this), left);
35323 _performZoom: function () {
35324 var map = this._map,
35325 zoom = map.getZoom(),
35326 snap = this._map.options.zoomSnap || 0;
35328 map._stop(); // stop panning and fly animations if any
35330 // map the delta with a sigmoid function to -4..4 range leaning on -1..1
35331 var d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4),
35332 d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2,
35333 d4 = snap ? Math.ceil(d3 / snap) * snap : d3,
35334 delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom;
35337 this._startTime = null;
35339 if (!delta) { return; }
35341 if (map.options.scrollWheelZoom === 'center') {
35342 map.setZoom(zoom + delta);
35344 map.setZoomAround(this._lastMousePos, zoom + delta);
35349 // @section Handlers
35350 // @property scrollWheelZoom: Handler
35351 // Scroll wheel zoom handler.
35352 Map.addInitHook('addHandler', 'scrollWheelZoom', ScrollWheelZoom);
35355 * L.Map.Tap is used to enable mobile hacks like quick taps and long hold.
35359 // @section Interaction Options
35361 // @section Touch interaction options
35362 // @option tap: Boolean = true
35363 // Enables mobile hacks for supporting instant taps (fixing 200ms click
35364 // delay on iOS/Android) and touch holds (fired as `contextmenu` events).
35367 // @option tapTolerance: Number = 15
35368 // The max number of pixels a user can shift his finger during touch
35369 // for it to be considered a valid tap.
35373 var Tap = Handler.extend({
35374 addHooks: function () {
35375 on(this._map._container, 'touchstart', this._onDown, this);
35378 removeHooks: function () {
35379 off(this._map._container, 'touchstart', this._onDown, this);
35382 _onDown: function (e) {
35383 if (!e.touches) { return; }
35387 this._fireClick = true;
35389 // don't simulate click or track longpress if more than 1 touch
35390 if (e.touches.length > 1) {
35391 this._fireClick = false;
35392 clearTimeout(this._holdTimeout);
35396 var first = e.touches[0],
35399 this._startPos = this._newPos = new Point(first.clientX, first.clientY);
35401 // if touching a link, highlight it
35402 if (el.tagName && el.tagName.toLowerCase() === 'a') {
35403 addClass(el, 'leaflet-active');
35406 // simulate long hold but setting a timeout
35407 this._holdTimeout = setTimeout(bind(function () {
35408 if (this._isTapValid()) {
35409 this._fireClick = false;
35411 this._simulateEvent('contextmenu', first);
35415 this._simulateEvent('mousedown', first);
35418 touchmove: this._onMove,
35419 touchend: this._onUp
35423 _onUp: function (e) {
35424 clearTimeout(this._holdTimeout);
35427 touchmove: this._onMove,
35428 touchend: this._onUp
35431 if (this._fireClick && e && e.changedTouches) {
35433 var first = e.changedTouches[0],
35436 if (el && el.tagName && el.tagName.toLowerCase() === 'a') {
35437 removeClass(el, 'leaflet-active');
35440 this._simulateEvent('mouseup', first);
35442 // simulate click if the touch didn't move too much
35443 if (this._isTapValid()) {
35444 this._simulateEvent('click', first);
35449 _isTapValid: function () {
35450 return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance;
35453 _onMove: function (e) {
35454 var first = e.touches[0];
35455 this._newPos = new Point(first.clientX, first.clientY);
35456 this._simulateEvent('mousemove', first);
35459 _simulateEvent: function (type, e) {
35460 var simulatedEvent = document.createEvent('MouseEvents');
35462 simulatedEvent._simulated = true;
35463 e.target._simulatedClick = true;
35465 simulatedEvent.initMouseEvent(
35466 type, true, true, window, 1,
35467 e.screenX, e.screenY,
35468 e.clientX, e.clientY,
35469 false, false, false, false, 0, null);
35471 e.target.dispatchEvent(simulatedEvent);
35475 // @section Handlers
35476 // @property tap: Handler
35477 // Mobile touch hacks (quick tap and touch hold) handler.
35478 if (touch && (!pointer || safari)) {
35479 Map.addInitHook('addHandler', 'tap', Tap);
35483 * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers.
35487 // @section Interaction Options
35489 // @section Touch interaction options
35490 // @option touchZoom: Boolean|String = *
35491 // Whether the map can be zoomed by touch-dragging with two fingers. If
35492 // passed `'center'`, it will zoom to the center of the view regardless of
35493 // where the touch events (fingers) were. Enabled for touch-capable web
35494 // browsers except for old Androids.
35495 touchZoom: touch && !android23,
35497 // @option bounceAtZoomLimits: Boolean = true
35498 // Set it to false if you don't want the map to zoom beyond min/max zoom
35499 // and then bounce back when pinch-zooming.
35500 bounceAtZoomLimits: true
35503 var TouchZoom = Handler.extend({
35504 addHooks: function () {
35505 addClass(this._map._container, 'leaflet-touch-zoom');
35506 on(this._map._container, 'touchstart', this._onTouchStart, this);
35509 removeHooks: function () {
35510 removeClass(this._map._container, 'leaflet-touch-zoom');
35511 off(this._map._container, 'touchstart', this._onTouchStart, this);
35514 _onTouchStart: function (e) {
35515 var map = this._map;
35516 if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; }
35518 var p1 = map.mouseEventToContainerPoint(e.touches[0]),
35519 p2 = map.mouseEventToContainerPoint(e.touches[1]);
35521 this._centerPoint = map.getSize()._divideBy(2);
35522 this._startLatLng = map.containerPointToLatLng(this._centerPoint);
35523 if (map.options.touchZoom !== 'center') {
35524 this._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2));
35527 this._startDist = p1.distanceTo(p2);
35528 this._startZoom = map.getZoom();
35530 this._moved = false;
35531 this._zooming = true;
35535 on(document, 'touchmove', this._onTouchMove, this);
35536 on(document, 'touchend', this._onTouchEnd, this);
35541 _onTouchMove: function (e) {
35542 if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; }
35544 var map = this._map,
35545 p1 = map.mouseEventToContainerPoint(e.touches[0]),
35546 p2 = map.mouseEventToContainerPoint(e.touches[1]),
35547 scale = p1.distanceTo(p2) / this._startDist;
35549 this._zoom = map.getScaleZoom(scale, this._startZoom);
35551 if (!map.options.bounceAtZoomLimits && (
35552 (this._zoom < map.getMinZoom() && scale < 1) ||
35553 (this._zoom > map.getMaxZoom() && scale > 1))) {
35554 this._zoom = map._limitZoom(this._zoom);
35557 if (map.options.touchZoom === 'center') {
35558 this._center = this._startLatLng;
35559 if (scale === 1) { return; }
35561 // Get delta from pinch to center, so centerLatLng is delta applied to initial pinchLatLng
35562 var delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint);
35563 if (scale === 1 && delta.x === 0 && delta.y === 0) { return; }
35564 this._center = map.unproject(map.project(this._pinchStartLatLng, this._zoom).subtract(delta), this._zoom);
35567 if (!this._moved) {
35568 map._moveStart(true, false);
35569 this._moved = true;
35572 cancelAnimFrame(this._animRequest);
35574 var moveFn = bind(map._move, map, this._center, this._zoom, {pinch: true, round: false});
35575 this._animRequest = requestAnimFrame(moveFn, this, true);
35580 _onTouchEnd: function () {
35581 if (!this._moved || !this._zooming) {
35582 this._zooming = false;
35586 this._zooming = false;
35587 cancelAnimFrame(this._animRequest);
35589 off(document, 'touchmove', this._onTouchMove, this);
35590 off(document, 'touchend', this._onTouchEnd, this);
35592 // Pinch updates GridLayers' levels only when zoomSnap is off, so zoomSnap becomes noUpdate.
35593 if (this._map.options.zoomAnimation) {
35594 this._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap);
35596 this._map._resetView(this._center, this._map._limitZoom(this._zoom));
35601 // @section Handlers
35602 // @property touchZoom: Handler
35603 // Touch zoom handler.
35604 Map.addInitHook('addHandler', 'touchZoom', TouchZoom);
35606 Map.BoxZoom = BoxZoom;
35607 Map.DoubleClickZoom = DoubleClickZoom;
35609 Map.Keyboard = Keyboard;
35610 Map.ScrollWheelZoom = ScrollWheelZoom;
35612 Map.TouchZoom = TouchZoom;
35614 exports.version = version;
35615 exports.Control = Control;
35616 exports.control = control;
35617 exports.Browser = Browser;
35618 exports.Evented = Evented;
35619 exports.Mixin = Mixin;
35620 exports.Util = Util;
35621 exports.Class = Class;
35622 exports.Handler = Handler;
35623 exports.extend = extend;
35624 exports.bind = bind;
35625 exports.stamp = stamp;
35626 exports.setOptions = setOptions;
35627 exports.DomEvent = DomEvent;
35628 exports.DomUtil = DomUtil;
35629 exports.PosAnimation = PosAnimation;
35630 exports.Draggable = Draggable;
35631 exports.LineUtil = LineUtil;
35632 exports.PolyUtil = PolyUtil;
35633 exports.Point = Point;
35634 exports.point = toPoint;
35635 exports.Bounds = Bounds;
35636 exports.bounds = toBounds;
35637 exports.Transformation = Transformation;
35638 exports.transformation = toTransformation;
35639 exports.Projection = index;
35640 exports.LatLng = LatLng;
35641 exports.latLng = toLatLng;
35642 exports.LatLngBounds = LatLngBounds;
35643 exports.latLngBounds = toLatLngBounds;
35645 exports.GeoJSON = GeoJSON;
35646 exports.geoJSON = geoJSON;
35647 exports.geoJson = geoJson;
35648 exports.Layer = Layer;
35649 exports.LayerGroup = LayerGroup;
35650 exports.layerGroup = layerGroup;
35651 exports.FeatureGroup = FeatureGroup;
35652 exports.featureGroup = featureGroup;
35653 exports.ImageOverlay = ImageOverlay;
35654 exports.imageOverlay = imageOverlay;
35655 exports.VideoOverlay = VideoOverlay;
35656 exports.videoOverlay = videoOverlay;
35657 exports.SVGOverlay = SVGOverlay;
35658 exports.svgOverlay = svgOverlay;
35659 exports.DivOverlay = DivOverlay;
35660 exports.Popup = Popup;
35661 exports.popup = popup;
35662 exports.Tooltip = Tooltip;
35663 exports.tooltip = tooltip;
35664 exports.Icon = Icon;
35665 exports.icon = icon;
35666 exports.DivIcon = DivIcon;
35667 exports.divIcon = divIcon;
35668 exports.Marker = Marker;
35669 exports.marker = marker;
35670 exports.TileLayer = TileLayer;
35671 exports.tileLayer = tileLayer;
35672 exports.GridLayer = GridLayer;
35673 exports.gridLayer = gridLayer;
35675 exports.svg = svg$1;
35676 exports.Renderer = Renderer;
35677 exports.Canvas = Canvas;
35678 exports.canvas = canvas$1;
35679 exports.Path = Path;
35680 exports.CircleMarker = CircleMarker;
35681 exports.circleMarker = circleMarker;
35682 exports.Circle = Circle;
35683 exports.circle = circle;
35684 exports.Polyline = Polyline;
35685 exports.polyline = polyline;
35686 exports.Polygon = Polygon;
35687 exports.polygon = polygon;
35688 exports.Rectangle = Rectangle;
35689 exports.rectangle = rectangle;
35691 exports.map = createMap;
35693 var oldL = window.L;
35694 exports.noConflict = function() {
35699 // Always export us to window global (see #2364)
35700 window.L = exports;
35706 var L$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), leafletSrc, {
35707 'default': leafletSrc
35710 var Control_MiniMap_min = createCommonjsModule(function (module, exports) {
35711 (function(factory,window){{module.exports=factory(leafletSrc);}if(typeof window!=="undefined"&&window.L){window.L.Control.MiniMap=factory(L);window.L.control.minimap=function(layer,options){return new window.L.Control.MiniMap(layer,options)};}})(function(L){var MiniMap=L.Control.extend({includes:L.Evented?L.Evented.prototype:L.Mixin.Events,options:{position:"bottomright",toggleDisplay:false,zoomLevelOffset:-5,zoomLevelFixed:false,centerFixed:false,zoomAnimation:false,autoToggleDisplay:false,minimized:false,width:150,height:150,collapsedWidth:19,collapsedHeight:19,aimingRectOptions:{color:"#ff7800",weight:1,clickable:false},shadowRectOptions:{color:"#000000",weight:1,clickable:false,opacity:0,fillOpacity:0},strings:{hideText:"Hide MiniMap",showText:"Show MiniMap"},mapOptions:{}},initialize:function(layer,options){L.Util.setOptions(this,options);this.options.aimingRectOptions.clickable=false;this.options.shadowRectOptions.clickable=false;this._layer=layer;},onAdd:function(map){this._mainMap=map;this._container=L.DomUtil.create("div","leaflet-control-minimap");this._container.style.width=this.options.width+"px";this._container.style.height=this.options.height+"px";L.DomEvent.disableClickPropagation(this._container);L.DomEvent.on(this._container,"mousewheel",L.DomEvent.stopPropagation);var mapOptions={attributionControl:false,dragging:!this.options.centerFixed,zoomControl:false,zoomAnimation:this.options.zoomAnimation,autoToggleDisplay:this.options.autoToggleDisplay,touchZoom:this.options.centerFixed?"center":!this._isZoomLevelFixed(),scrollWheelZoom:this.options.centerFixed?"center":!this._isZoomLevelFixed(),doubleClickZoom:this.options.centerFixed?"center":!this._isZoomLevelFixed(),boxZoom:!this._isZoomLevelFixed(),crs:map.options.crs};mapOptions=L.Util.extend(this.options.mapOptions,mapOptions);this._miniMap=new L.Map(this._container,mapOptions);this._miniMap.addLayer(this._layer);this._mainMapMoving=false;this._miniMapMoving=false;this._userToggledDisplay=false;this._minimized=false;if(this.options.toggleDisplay){this._addToggleButton();}this._miniMap.whenReady(L.Util.bind(function(){this._aimingRect=L.rectangle(this._mainMap.getBounds(),this.options.aimingRectOptions).addTo(this._miniMap);this._shadowRect=L.rectangle(this._mainMap.getBounds(),this.options.shadowRectOptions).addTo(this._miniMap);this._mainMap.on("moveend",this._onMainMapMoved,this);this._mainMap.on("move",this._onMainMapMoving,this);this._miniMap.on("movestart",this._onMiniMapMoveStarted,this);this._miniMap.on("move",this._onMiniMapMoving,this);this._miniMap.on("moveend",this._onMiniMapMoved,this);},this));return this._container},addTo:function(map){L.Control.prototype.addTo.call(this,map);var center=this.options.centerFixed||this._mainMap.getCenter();this._miniMap.setView(center,this._decideZoom(true));this._setDisplay(this.options.minimized);return this},onRemove:function(map){this._mainMap.off("moveend",this._onMainMapMoved,this);this._mainMap.off("move",this._onMainMapMoving,this);this._miniMap.off("moveend",this._onMiniMapMoved,this);this._miniMap.removeLayer(this._layer);},changeLayer:function(layer){this._miniMap.removeLayer(this._layer);this._layer=layer;this._miniMap.addLayer(this._layer);},_addToggleButton:function(){this._toggleDisplayButton=this.options.toggleDisplay?this._createButton("",this._toggleButtonInitialTitleText(),"leaflet-control-minimap-toggle-display leaflet-control-minimap-toggle-display-"+this.options.position,this._container,this._toggleDisplayButtonClicked,this):undefined;this._toggleDisplayButton.style.width=this.options.collapsedWidth+"px";this._toggleDisplayButton.style.height=this.options.collapsedHeight+"px";},_toggleButtonInitialTitleText:function(){if(this.options.minimized){return this.options.strings.showText}else {return this.options.strings.hideText}},_createButton:function(html,title,className,container,fn,context){var link=L.DomUtil.create("a",className,container);link.innerHTML=html;link.href="#";link.title=title;var stop=L.DomEvent.stopPropagation;L.DomEvent.on(link,"click",stop).on(link,"mousedown",stop).on(link,"dblclick",stop).on(link,"click",L.DomEvent.preventDefault).on(link,"click",fn,context);return link},_toggleDisplayButtonClicked:function(){this._userToggledDisplay=true;if(!this._minimized){this._minimize();}else {this._restore();}},_setDisplay:function(minimize){if(minimize!==this._minimized){if(!this._minimized){this._minimize();}else {this._restore();}}},_minimize:function(){if(this.options.toggleDisplay){this._container.style.width=this.options.collapsedWidth+"px";this._container.style.height=this.options.collapsedHeight+"px";this._toggleDisplayButton.className+=" minimized-"+this.options.position;this._toggleDisplayButton.title=this.options.strings.showText;}else {this._container.style.display="none";}this._minimized=true;this._onToggle();},_restore:function(){if(this.options.toggleDisplay){this._container.style.width=this.options.width+"px";this._container.style.height=this.options.height+"px";this._toggleDisplayButton.className=this._toggleDisplayButton.className.replace("minimized-"+this.options.position,"");this._toggleDisplayButton.title=this.options.strings.hideText;}else {this._container.style.display="block";}this._minimized=false;this._onToggle();},_onMainMapMoved:function(e){if(!this._miniMapMoving){var center=this.options.centerFixed||this._mainMap.getCenter();this._mainMapMoving=true;this._miniMap.setView(center,this._decideZoom(true));this._setDisplay(this._decideMinimized());}else {this._miniMapMoving=false;}this._aimingRect.setBounds(this._mainMap.getBounds());},_onMainMapMoving:function(e){this._aimingRect.setBounds(this._mainMap.getBounds());},_onMiniMapMoveStarted:function(e){if(!this.options.centerFixed){var lastAimingRect=this._aimingRect.getBounds();var sw=this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest());var ne=this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast());this._lastAimingRectPosition={sw:sw,ne:ne};}},_onMiniMapMoving:function(e){if(!this.options.centerFixed){if(!this._mainMapMoving&&this._lastAimingRectPosition){this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw),this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne)));this._shadowRect.setStyle({opacity:1,fillOpacity:.3});}}},_onMiniMapMoved:function(e){if(!this._mainMapMoving){this._miniMapMoving=true;this._mainMap.setView(this._miniMap.getCenter(),this._decideZoom(false));this._shadowRect.setStyle({opacity:0,fillOpacity:0});}else {this._mainMapMoving=false;}},_isZoomLevelFixed:function(){var zoomLevelFixed=this.options.zoomLevelFixed;return this._isDefined(zoomLevelFixed)&&this._isInteger(zoomLevelFixed)},_decideZoom:function(fromMaintoMini){if(!this._isZoomLevelFixed()){if(fromMaintoMini){return this._mainMap.getZoom()+this.options.zoomLevelOffset}else {var currentDiff=this._miniMap.getZoom()-this._mainMap.getZoom();var proposedZoom=this._miniMap.getZoom()-this.options.zoomLevelOffset;var toRet;if(currentDiff>this.options.zoomLevelOffset&&this._mainMap.getZoom()<this._miniMap.getMinZoom()-this.options.zoomLevelOffset){if(this._miniMap.getZoom()>this._lastMiniMapZoom){toRet=this._mainMap.getZoom()+1;this._miniMap.setZoom(this._miniMap.getZoom()-1);}else {toRet=this._mainMap.getZoom();}}else {toRet=proposedZoom;}this._lastMiniMapZoom=this._miniMap.getZoom();return toRet}}else {if(fromMaintoMini){return this.options.zoomLevelFixed}else {return this._mainMap.getZoom()}}},_decideMinimized:function(){if(this._userToggledDisplay){return this._minimized}if(this.options.autoToggleDisplay){if(this._mainMap.getBounds().contains(this._miniMap.getBounds())){return true}return false}return this._minimized},_isInteger:function(value){return typeof value==="number"},_isDefined:function(value){return typeof value!=="undefined"},_onToggle:function(){L.Util.requestAnimFrame(function(){L.DomEvent.on(this._container,"transitionend",this._fireToggleEvents,this);if(!L.Browser.any3d){L.Util.requestAnimFrame(this._fireToggleEvents,this);}},this);},_fireToggleEvents:function(){L.DomEvent.off(this._container,"transitionend",this._fireToggleEvents,this);var data={minimized:this._minimized};this.fire(this._minimized?"minimize":"restore",data);this.fire("toggle",data);}});L.Map.mergeOptions({miniMapControl:false});L.Map.addInitHook(function(){if(this.options.miniMapControl){this.miniMapControl=(new MiniMap).addTo(this);}});return MiniMap},window);
35714 var LMM = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), Control_MiniMap_min, {
35715 'default': Control_MiniMap_min
35718 /* src/components/MapPosition.svelte generated by Svelte v3.31.2 */
35719 const file$7 = "src/components/MapPosition.svelte";
35721 function create_fragment$7(ctx) {
35752 c: function create() {
35753 div2 = element("div");
35754 div0 = element("div");
35755 t0 = text("map center: ");
35756 t1 = text(/*map_center*/ ctx[0]);
35759 t3 = text("view on osm.org");
35761 br0 = element("br");
35762 t5 = text("\n map zoom: ");
35763 t6 = text(/*map_zoom*/ ctx[1]);
35765 br1 = element("br");
35766 t8 = text("\n viewbox: ");
35767 t9 = text(/*map_viewbox*/ ctx[2]);
35769 br2 = element("br");
35770 t11 = text("\n last click: ");
35771 t12 = text(/*last_click*/ ctx[4]);
35773 br3 = element("br");
35774 t14 = text("\n mouse position: ");
35775 t15 = text(/*mouse_position*/ ctx[5]);
35777 div1 = element("div");
35779 a1.textContent = "hide";
35780 attr_dev(a0, "target", "_blank");
35781 attr_dev(a0, "href", /*view_on_osm_link*/ ctx[3]);
35782 add_location(a0, file$7, 86, 4, 2297);
35783 add_location(br0, file$7, 87, 4, 2366);
35784 add_location(br1, file$7, 89, 4, 2400);
35785 add_location(br2, file$7, 91, 4, 2436);
35786 add_location(br3, file$7, 93, 4, 2474);
35787 attr_dev(div0, "id", "map-position-inner");
35788 add_location(div0, file$7, 84, 2, 2234);
35789 attr_dev(a1, "href", "#");
35790 add_location(a1, file$7, 96, 31, 2556);
35791 attr_dev(div1, "id", "map-position-close");
35792 attr_dev(div1, "class", "svelte-1b30dq3");
35793 add_location(div1, file$7, 96, 2, 2527);
35794 attr_dev(div2, "id", "map-position");
35795 attr_dev(div2, "class", "svelte-1b30dq3");
35796 add_location(div2, file$7, 83, 0, 2208);
35798 l: function claim(nodes) {
35799 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
35801 m: function mount(target, anchor) {
35802 insert_dev(target, div2, anchor);
35803 append_dev(div2, div0);
35804 append_dev(div0, t0);
35805 append_dev(div0, t1);
35806 append_dev(div0, t2);
35807 append_dev(div0, a0);
35808 append_dev(a0, t3);
35809 append_dev(div0, t4);
35810 append_dev(div0, br0);
35811 append_dev(div0, t5);
35812 append_dev(div0, t6);
35813 append_dev(div0, t7);
35814 append_dev(div0, br1);
35815 append_dev(div0, t8);
35816 append_dev(div0, t9);
35817 append_dev(div0, t10);
35818 append_dev(div0, br2);
35819 append_dev(div0, t11);
35820 append_dev(div0, t12);
35821 append_dev(div0, t13);
35822 append_dev(div0, br3);
35823 append_dev(div0, t14);
35824 append_dev(div0, t15);
35825 append_dev(div2, t16);
35826 append_dev(div2, div1);
35827 append_dev(div1, a1);
35830 dispose = listen_dev(a1, "click", handleHideClick, false, false, false);
35834 p: function update(ctx, [dirty]) {
35835 if (dirty & /*map_center*/ 1) set_data_dev(t1, /*map_center*/ ctx[0]);
35837 if (dirty & /*view_on_osm_link*/ 8) {
35838 attr_dev(a0, "href", /*view_on_osm_link*/ ctx[3]);
35841 if (dirty & /*map_zoom*/ 2) set_data_dev(t6, /*map_zoom*/ ctx[1]);
35842 if (dirty & /*map_viewbox*/ 4) set_data_dev(t9, /*map_viewbox*/ ctx[2]);
35843 if (dirty & /*last_click*/ 16) set_data_dev(t12, /*last_click*/ ctx[4]);
35844 if (dirty & /*mouse_position*/ 32) set_data_dev(t15, /*mouse_position*/ ctx[5]);
35848 d: function destroy(detaching) {
35849 if (detaching) detach_dev(div2);
35855 dispatch_dev("SvelteRegisterBlock", {
35857 id: create_fragment$7.name,
35866 function map_link_to_osm(map) {
35867 var zoom = map.getZoom();
35868 var lat = map.getCenter().lat.toFixed(5);
35869 var lng = map.getCenter().lng.toFixed(5);
35870 return "https://openstreetmap.org/#map=" + zoom + "/" + lat + "/" + lng;
35873 function map_viewbox_as_string$1(map) {
35874 var bounds = map.getBounds();
35875 var west = bounds.getWest();
35876 var east = bounds.getEast();
35878 if (east - west >= 360) {
35879 // covers more than whole planet
35880 west = map.getCenter().lng - 179.999;
35882 east = map.getCenter().lng + 179.999;
35885 east = L.latLng(77, east).wrap().lng;
35886 west = L.latLng(77, west).wrap().lng;
35890 bounds.getNorth().toFixed(5),
35892 bounds.getSouth().toFixed(5)
35893 ].join(","); // left
35899 function handleHideClick(e) {
35900 document.getElementById("map-position").style.display = "none";
35901 document.getElementById("show-map-position").style.display = "block";
35904 function instance$7($$self, $$props, $$invalidate) {
35905 let { $$slots: slots = {}, $$scope } = $$props;
35906 validate_slots("MapPosition", slots, []);
35907 let last_click_latlng;
35911 let view_on_osm_link;
35913 let mouse_position;
35915 function display_map_position(map, mouse_lat_lng) {
35916 $$invalidate(0, map_center = map.getCenter().lat.toFixed(5) + "," + map.getCenter().lng.toFixed(5));
35917 $$invalidate(3, view_on_osm_link = map_link_to_osm(map));
35918 $$invalidate(1, map_zoom = map.getZoom());
35919 $$invalidate(2, map_viewbox = map_viewbox_as_string$1(map));
35920 $$invalidate(5, mouse_position = "-");
35922 if (mouse_lat_lng) {
35923 $$invalidate(5, mouse_position = [mouse_lat_lng.lat.toFixed(5), mouse_lat_lng.lng.toFixed(5)].join(","));
35926 if (last_click_latlng) {
35927 $$invalidate(4, last_click = [last_click_latlng.lat.toFixed(5), last_click_latlng.lng.toFixed(5)].join(","));
35931 map_store.subscribe(map => {
35936 map.on("move", function () {
35937 display_map_position(map);
35938 }); // update_viewbox_field();
35940 map.on("mousemove", function (e) {
35941 display_map_position(map, e.latlng);
35944 map.on("click", function (e) {
35945 last_click_latlng = e.latlng;
35946 display_map_position(map);
35949 map.on("load", function () {
35950 display_map_position(map);
35954 const writable_props = [];
35956 Object.keys($$props).forEach(key => {
35957 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<MapPosition> was created with unknown prop '${key}'`);
35960 $$self.$capture_state = () => ({
35970 map_viewbox_as_string: map_viewbox_as_string$1,
35971 display_map_position,
35975 $$self.$inject_state = $$props => {
35976 if ("last_click_latlng" in $$props) last_click_latlng = $$props.last_click_latlng;
35977 if ("map_center" in $$props) $$invalidate(0, map_center = $$props.map_center);
35978 if ("map_zoom" in $$props) $$invalidate(1, map_zoom = $$props.map_zoom);
35979 if ("map_viewbox" in $$props) $$invalidate(2, map_viewbox = $$props.map_viewbox);
35980 if ("view_on_osm_link" in $$props) $$invalidate(3, view_on_osm_link = $$props.view_on_osm_link);
35981 if ("last_click" in $$props) $$invalidate(4, last_click = $$props.last_click);
35982 if ("mouse_position" in $$props) $$invalidate(5, mouse_position = $$props.mouse_position);
35985 if ($$props && "$$inject" in $$props) {
35986 $$self.$inject_state($$props.$$inject);
35999 class MapPosition extends SvelteComponentDev {
36000 constructor(options) {
36002 init(this, options, instance$7, create_fragment$7, safe_not_equal, {});
36004 dispatch_dev("SvelteRegisterComponent", {
36006 tagName: "MapPosition",
36008 id: create_fragment$7.name
36013 /* src/components/Map.svelte generated by Svelte v3.31.2 */
36014 const file$8 = "src/components/Map.svelte";
36016 function create_fragment$8(ctx) {
36025 mapposition = new MapPosition({ $$inline: true });
36028 c: function create() {
36029 create_component(mapposition.$$.fragment);
36031 div0 = element("div");
36033 div1 = element("div");
36034 div1.textContent = "show map bounds";
36035 attr_dev(div0, "id", "map");
36036 attr_dev(div0, "class", "svelte-1vbvdrk");
36037 add_location(div0, file$8, 173, 0, 4682);
36038 attr_dev(div1, "id", "show-map-position");
36039 attr_dev(div1, "class", "leaflet-bar btn btn-sm btn-outline-secondary svelte-1vbvdrk");
36040 add_location(div1, file$8, 174, 0, 4713);
36042 l: function claim(nodes) {
36043 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
36045 m: function mount(target, anchor) {
36046 mount_component(mapposition, target, anchor);
36047 insert_dev(target, t0, anchor);
36048 insert_dev(target, div0, anchor);
36049 insert_dev(target, t1, anchor);
36050 insert_dev(target, div1, anchor);
36055 action_destroyer(/*mapAction*/ ctx[0].call(null, div0)),
36056 listen_dev(div1, "click", stop_propagation(show_map_position_click), false, false, true)
36063 i: function intro(local) {
36064 if (current) return;
36065 transition_in(mapposition.$$.fragment, local);
36068 o: function outro(local) {
36069 transition_out(mapposition.$$.fragment, local);
36072 d: function destroy(detaching) {
36073 destroy_component(mapposition, detaching);
36074 if (detaching) detach_dev(t0);
36075 if (detaching) detach_dev(div0);
36076 if (detaching) detach_dev(t1);
36077 if (detaching) detach_dev(div1);
36083 dispatch_dev("SvelteRegisterBlock", {
36085 id: create_fragment$8.name,
36094 function parse_and_normalize_geojson_string(part) {
36095 // normalize places the geometry into a featurecollection, similar to
36096 // https://github.com/mapbox/geojson-normalize
36097 var parsed_geojson = {
36098 type: "FeatureCollection",
36108 return parsed_geojson;
36111 function show_map_position_click(e) {
36112 e.target.style.display = "none";
36113 document.getElementById("map-position").style.display = "block";
36116 function instance$8($$self, $$props, $$invalidate) {
36117 let { $$slots: slots = {}, $$scope } = $$props;
36118 validate_slots("Map", slots, []);
36119 let { display_minimap = false } = $$props;
36120 let dataLayers = [];
36122 function createMap(container) {
36123 const attribution = get_config_value_1("Map_Tile_Attribution") || null;
36125 let map = new leafletSrc.map(container,
36127 attributionControl: attribution && attribution.length,
36128 scrollWheelZoom: true, // !L.Browser.touch,
36130 center: [get_config_value_1("Map_Default_Lat"), get_config_value_1("Map_Default_Lon")],
36131 zoom: get_config_value_1("Map_Default_Zoom")
36134 leafletSrc.tileLayer(get_config_value_1("Map_Tile_URL"), { attribution }).addTo(map);
36136 if (display_minimap) {
36137 let osm2 = new leafletSrc.TileLayer(get_config_value_1("Map_Tile_URL"), { minZoom: 0, maxZoom: 13, attribution });
36138 new leafletSrc.Control.MiniMap(osm2, { toggleDisplay: true }).addTo(map);
36141 const MapPositionControl = leafletSrc.Control.extend({
36142 options: { position: "topright" },
36144 return document.getElementById("show-map-position");
36148 map.addControl(new MapPositionControl());
36152 function mapAction(container) {
36153 let map = createMap(container);
36154 map_store.set(map);
36155 setMapData(get_store_value(current_result_store));
36164 function resetMapData() {
36165 let map = get_store_value(map_store);
36171 dataLayers.forEach(function (layer) {
36172 map.removeLayer(layer);
36176 function setMapData(aFeature) {
36177 let map = get_store_value(map_store);
36184 let request_latlon = get_store_value(current_request_latlon);
36186 if (request_latlon) {
36187 // We don't need a marker, but an L.circle instance changes radius once you zoom in/out
36188 let cm = leafletSrc.circleMarker(request_latlon, {
36191 fillColor: "#ff7800",
36199 dataLayers.push(cm);
36202 var search_params = new URLSearchParams(window.location.search);
36203 var viewbox = search_params.get("viewbox");
36206 let coords = viewbox.split(","); // <x1>,<y1>,<x2>,<y2>
36207 let bounds = leafletSrc.latLngBounds([coords[1], coords[0]], [coords[3], coords[2]]);
36209 leafletSrc.rectangle(bounds, {
36223 let lat = aFeature.centroid
36224 ? aFeature.centroid.coordinates[1]
36227 let lon = aFeature.centroid
36228 ? aFeature.centroid.coordinates[0]
36231 let geojson = aFeature.geometry || aFeature.geojson;
36234 let circle = leafletSrc.circleMarker([lat, lon], {
36237 fillColor: "#ff7800",
36242 map.addLayer(circle);
36243 dataLayers.push(circle);
36247 var geojson_layer = leafletSrc.geoJson(
36248 // https://leafletjs.com/reference-1.0.3.html#path-option
36249 parse_and_normalize_geojson_string(geojson),
36252 return { interactive: false, color: "blue" };
36257 map.addLayer(geojson_layer);
36258 dataLayers.push(geojson_layer);
36259 map.fitBounds(geojson_layer.getBounds());
36260 } else if (lat && lon) {
36261 map.setView([lat, lon], 10);
36267 current_result_store.subscribe(aFeature => {
36268 setMapData(aFeature);
36271 const writable_props = ["display_minimap"];
36273 Object.keys($$props).forEach(key => {
36274 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Map> was created with unknown prop '${key}'`);
36277 $$self.$$set = $$props => {
36278 if ("display_minimap" in $$props) $$invalidate(1, display_minimap = $$props.display_minimap);
36281 $$self.$capture_state = () => ({
36284 get: get_store_value,
36285 get_config_value: get_config_value_1,
36287 current_result_store,
36288 current_request_latlon,
36294 parse_and_normalize_geojson_string,
36297 show_map_position_click
36300 $$self.$inject_state = $$props => {
36301 if ("display_minimap" in $$props) $$invalidate(1, display_minimap = $$props.display_minimap);
36302 if ("dataLayers" in $$props) dataLayers = $$props.dataLayers;
36305 if ($$props && "$$inject" in $$props) {
36306 $$self.$inject_state($$props.$$inject);
36309 return [mapAction, display_minimap];
36312 class Map$1 extends SvelteComponentDev {
36313 constructor(options) {
36315 init(this, options, instance$8, create_fragment$8, safe_not_equal, { display_minimap: 1 });
36317 dispatch_dev("SvelteRegisterComponent", {
36321 id: create_fragment$8.name
36325 get display_minimap() {
36326 throw new Error("<Map>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
36329 set display_minimap(value) {
36330 throw new Error("<Map>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
36334 /* src/pages/SearchPage.svelte generated by Svelte v3.31.2 */
36335 const file$9 = "src/pages/SearchPage.svelte";
36337 function create_fragment$9(ctx) {
36348 searchbar = new SearchBar({
36350 reverse_search: /*reverse_search*/ ctx[0],
36351 api_request_params: /*api_request_params*/ ctx[1],
36352 bStructuredSearch: /*bStructuredSearch*/ ctx[2]
36357 resultslist = new ResultsList({
36359 reverse_search: /*reverse_search*/ ctx[0]
36365 props: { display_minimap: true },
36370 c: function create() {
36371 create_component(searchbar.$$.fragment);
36373 div2 = element("div");
36374 div0 = element("div");
36375 create_component(resultslist.$$.fragment);
36377 div1 = element("div");
36378 create_component(map.$$.fragment);
36379 attr_dev(div0, "class", "sidebar svelte-1wb4w3");
36380 add_location(div0, file$9, 93, 2, 3393);
36381 attr_dev(div1, "id", "map-wrapper");
36382 attr_dev(div1, "class", "svelte-1wb4w3");
36383 add_location(div1, file$9, 96, 2, 3478);
36384 attr_dev(div2, "id", "content");
36385 attr_dev(div2, "class", "svelte-1wb4w3");
36386 add_location(div2, file$9, 92, 0, 3372);
36388 l: function claim(nodes) {
36389 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
36391 m: function mount(target, anchor) {
36392 mount_component(searchbar, target, anchor);
36393 insert_dev(target, t0, anchor);
36394 insert_dev(target, div2, anchor);
36395 append_dev(div2, div0);
36396 mount_component(resultslist, div0, null);
36397 append_dev(div2, t1);
36398 append_dev(div2, div1);
36399 mount_component(map, div1, null);
36402 p: function update(ctx, [dirty]) {
36403 const searchbar_changes = {};
36404 if (dirty & /*reverse_search*/ 1) searchbar_changes.reverse_search = /*reverse_search*/ ctx[0];
36405 if (dirty & /*api_request_params*/ 2) searchbar_changes.api_request_params = /*api_request_params*/ ctx[1];
36406 searchbar.$set(searchbar_changes);
36407 const resultslist_changes = {};
36408 if (dirty & /*reverse_search*/ 1) resultslist_changes.reverse_search = /*reverse_search*/ ctx[0];
36409 resultslist.$set(resultslist_changes);
36411 i: function intro(local) {
36412 if (current) return;
36413 transition_in(searchbar.$$.fragment, local);
36414 transition_in(resultslist.$$.fragment, local);
36415 transition_in(map.$$.fragment, local);
36418 o: function outro(local) {
36419 transition_out(searchbar.$$.fragment, local);
36420 transition_out(resultslist.$$.fragment, local);
36421 transition_out(map.$$.fragment, local);
36424 d: function destroy(detaching) {
36425 destroy_component(searchbar, detaching);
36426 if (detaching) detach_dev(t0);
36427 if (detaching) detach_dev(div2);
36428 destroy_component(resultslist);
36429 destroy_component(map);
36433 dispatch_dev("SvelteRegisterBlock", {
36435 id: create_fragment$9.name,
36444 function instance$9($$self, $$props, $$invalidate) {
36445 let { $$slots: slots = {}, $$scope } = $$props;
36446 validate_slots("SearchPage", slots, []);
36447 let { reverse_search = false } = $$props;
36448 let api_request_params;
36449 let bStructuredSearch;
36451 function loaddata() {
36452 let search_params = new URLSearchParams(window.location.search);
36453 update_html_title();
36455 if (reverse_search) {
36456 $$invalidate(1, api_request_params = {
36457 lat: search_params.get("lat"),
36458 lon: search_params.get("lon"),
36459 zoom: search_params.get("zoom") > 1
36460 ? Number(search_params.get("zoom"))
36461 : Number(get_config_value_1("Reverse_Default_Search_Zoom")),
36465 if (api_request_params.lat || api_request_params.lat) {
36466 fetch_from_api("reverse", api_request_params, function (data) {
36467 if (data && !data.error) {
36468 current_request_latlon.set([api_request_params.lat, api_request_params.lon]);
36469 results_store.set([data]);
36471 results_store.set([]);
36474 update_html_title("Reverse result for " + api_request_params.lat + "," + api_request_params.lon);
36475 document.querySelector("input[name=lat]").focus();
36479 $$invalidate(1, api_request_params = {
36480 q: search_params.get("q"),
36481 street: search_params.get("street"),
36482 city: search_params.get("city"),
36483 county: search_params.get("county"),
36484 state: search_params.get("state"),
36485 country: search_params.get("country"),
36486 postalcode: search_params.get("postalcode"),
36487 polygon_geojson: get_config_value_1("Search_AreaPolygons", false) ? 1 : 0,
36488 viewbox: search_params.get("viewbox"),
36489 bounded: search_params.get("bounded"),
36490 dedupe: search_params.get("dedupe"),
36491 "accept-language": search_params.get("accept-language"),
36492 countrycodes: search_params.get("countrycodes"),
36493 limit: search_params.get("limit"),
36494 polygon_threshold: search_params.get("polygon_threshold"),
36495 exclude_place_ids: search_params.get("exclude_place_ids"),
36499 let bStructuredSearch = api_request_params.street || api_request_params.city || api_request_params.county || api_request_params.state || api_request_params.country || api_request_params.postalcode;
36501 if (api_request_params.q || bStructuredSearch) {
36502 fetch_from_api("search", api_request_params, function (data) {
36503 results_store.set(data);
36504 update_html_title("Result for " + api_request_params.q);
36505 document.querySelector("input[name=q]").focus();
36512 const writable_props = ["reverse_search"];
36514 Object.keys($$props).forEach(key => {
36515 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<SearchPage> was created with unknown prop '${key}'`);
36518 $$self.$$set = $$props => {
36519 if ("reverse_search" in $$props) $$invalidate(0, reverse_search = $$props.reverse_search);
36522 $$self.$capture_state = () => ({
36525 current_result_store,
36526 current_request_latlon,
36527 get_config_value: get_config_value_1,
36534 api_request_params,
36539 $$self.$inject_state = $$props => {
36540 if ("reverse_search" in $$props) $$invalidate(0, reverse_search = $$props.reverse_search);
36541 if ("api_request_params" in $$props) $$invalidate(1, api_request_params = $$props.api_request_params);
36542 if ("bStructuredSearch" in $$props) $$invalidate(2, bStructuredSearch = $$props.bStructuredSearch);
36545 if ($$props && "$$inject" in $$props) {
36546 $$self.$inject_state($$props.$$inject);
36549 return [reverse_search, api_request_params, bStructuredSearch];
36552 class SearchPage extends SvelteComponentDev {
36553 constructor(options) {
36555 init(this, options, instance$9, create_fragment$9, safe_not_equal, { reverse_search: 0 });
36557 dispatch_dev("SvelteRegisterComponent", {
36559 tagName: "SearchPage",
36561 id: create_fragment$9.name
36565 get reverse_search() {
36566 throw new Error("<SearchPage>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
36569 set reverse_search(value) {
36570 throw new Error("<SearchPage>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
36574 /* src/components/DetailsIndex.svelte generated by Svelte v3.31.2 */
36576 const file$a = "src/components/DetailsIndex.svelte";
36578 function create_fragment$a(ctx) {
36619 c: function create() {
36620 div5 = element("div");
36621 div4 = element("div");
36622 div3 = element("div");
36623 h1 = element("h1");
36624 h1.textContent = "Show details for place";
36626 div0 = element("div");
36627 h40 = element("h4");
36628 h40.textContent = "Search by place id";
36630 form0 = element("form");
36631 input0 = element("input");
36633 input1 = element("input");
36635 div1 = element("div");
36636 h41 = element("h4");
36637 h41.textContent = "Search by OSM type and OSM id";
36639 form1 = element("form");
36640 input2 = element("input");
36642 input3 = element("input");
36644 input4 = element("input");
36646 input5 = element("input");
36648 div2 = element("div");
36649 h42 = element("h4");
36650 h42.textContent = "Search by openstreetmap.org URL";
36652 form2 = element("form");
36653 input6 = element("input");
36655 input7 = element("input");
36657 input8 = element("input");
36659 input9 = element("input");
36660 add_location(h1, file$a, 25, 6, 687);
36661 attr_dev(h40, "class", "svelte-k5v90i");
36662 add_location(h40, file$a, 28, 8, 760);
36663 attr_dev(input0, "type", "edit");
36664 attr_dev(input0, "class", "form-control form-control-sm svelte-k5v90i");
36665 attr_dev(input0, "pattern", "^[0-9]+$");
36666 attr_dev(input0, "name", "place_id");
36667 attr_dev(input0, "placeholder", "12345");
36668 add_location(input0, file$a, 31, 10, 856);
36669 attr_dev(input1, "type", "submit");
36670 attr_dev(input1, "class", "btn btn-primary btn-sm");
36671 input1.value = "Show";
36672 add_location(input1, file$a, 36, 10, 1048);
36673 attr_dev(form0, "class", "form-inline");
36674 attr_dev(form0, "action", "details.html");
36675 add_location(form0, file$a, 30, 8, 797);
36676 attr_dev(div0, "class", "search-form svelte-k5v90i");
36677 add_location(div0, file$a, 27, 6, 726);
36678 attr_dev(h41, "class", "svelte-k5v90i");
36679 add_location(h41, file$a, 43, 8, 1220);
36680 attr_dev(input2, "type", "edit");
36681 attr_dev(input2, "class", "form-control form-control-sm svelte-k5v90i");
36682 attr_dev(input2, "pattern", "^[NWR][0-9]+$");
36683 attr_dev(input2, "placeholder", "N123 or W123 or R123");
36684 add_location(input2, file$a, 49, 10, 1438);
36685 attr_dev(input3, "type", "hidden");
36686 attr_dev(input3, "name", "osmtype");
36687 add_location(input3, file$a, 53, 10, 1617);
36688 attr_dev(input4, "type", "hidden");
36689 attr_dev(input4, "name", "osmid");
36690 add_location(input4, file$a, 54, 10, 1666);
36691 attr_dev(input5, "type", "submit");
36692 attr_dev(input5, "class", "btn btn-primary btn-sm");
36693 input5.value = "Show";
36694 add_location(input5, file$a, 55, 10, 1713);
36695 attr_dev(form1, "id", "form-by-type-and-id");
36696 attr_dev(form1, "class", "form-inline");
36697 attr_dev(form1, "action", "details.html");
36698 add_location(form1, file$a, 45, 8, 1268);
36699 attr_dev(div1, "class", "search-form svelte-k5v90i");
36700 add_location(div1, file$a, 42, 6, 1186);
36701 attr_dev(h42, "class", "svelte-k5v90i");
36702 add_location(h42, file$a, 60, 8, 1851);
36703 attr_dev(input6, "type", "edit");
36704 attr_dev(input6, "class", "form-control form-control-sm svelte-k5v90i");
36705 attr_dev(input6, "pattern", ".*openstreetmap.*");
36706 attr_dev(input6, "placeholder", "https://www.openstreetmap.org/relation/123");
36707 add_location(input6, file$a, 66, 10, 2067);
36708 attr_dev(input7, "type", "hidden");
36709 attr_dev(input7, "name", "osmtype");
36710 add_location(input7, file$a, 70, 10, 2272);
36711 attr_dev(input8, "type", "hidden");
36712 attr_dev(input8, "name", "osmid");
36713 add_location(input8, file$a, 71, 10, 2321);
36714 attr_dev(input9, "type", "submit");
36715 attr_dev(input9, "class", "btn btn-primary btn-sm");
36716 input9.value = "Show";
36717 add_location(input9, file$a, 72, 10, 2368);
36718 attr_dev(form2, "id", "form-by-osm-url");
36719 attr_dev(form2, "class", "form-inline");
36720 attr_dev(form2, "action", "details.html");
36721 add_location(form2, file$a, 62, 8, 1901);
36722 attr_dev(div2, "class", "search-form svelte-k5v90i");
36723 add_location(div2, file$a, 59, 6, 1817);
36724 attr_dev(div3, "class", "col-md-12");
36725 add_location(div3, file$a, 23, 4, 656);
36726 attr_dev(div4, "class", "row");
36727 add_location(div4, file$a, 22, 2, 634);
36728 attr_dev(div5, "class", "container");
36729 attr_dev(div5, "id", "details-index-page");
36730 add_location(div5, file$a, 21, 0, 584);
36732 l: function claim(nodes) {
36733 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
36735 m: function mount(target, anchor) {
36736 insert_dev(target, div5, anchor);
36737 append_dev(div5, div4);
36738 append_dev(div4, div3);
36739 append_dev(div3, h1);
36740 append_dev(div3, t1);
36741 append_dev(div3, div0);
36742 append_dev(div0, h40);
36743 append_dev(div0, t3);
36744 append_dev(div0, form0);
36745 append_dev(form0, input0);
36746 append_dev(form0, t4);
36747 append_dev(form0, input1);
36748 append_dev(div3, t5);
36749 append_dev(div3, div1);
36750 append_dev(div1, h41);
36751 append_dev(div1, t7);
36752 append_dev(div1, form1);
36753 append_dev(form1, input2);
36754 append_dev(form1, t8);
36755 append_dev(form1, input3);
36756 append_dev(form1, t9);
36757 append_dev(form1, input4);
36758 append_dev(form1, t10);
36759 append_dev(form1, input5);
36760 append_dev(div3, t11);
36761 append_dev(div3, div2);
36762 append_dev(div2, h42);
36763 append_dev(div2, t13);
36764 append_dev(div2, form2);
36765 append_dev(form2, input6);
36766 append_dev(form2, t14);
36767 append_dev(form2, input7);
36768 append_dev(form2, t15);
36769 append_dev(form2, input8);
36770 append_dev(form2, t16);
36771 append_dev(form2, input9);
36775 listen_dev(form1, "submit", prevent_default(handleFormSubmit), false, true, false),
36776 listen_dev(form2, "submit", prevent_default(handleFormSubmit), false, true, false)
36785 d: function destroy(detaching) {
36786 if (detaching) detach_dev(div5);
36792 dispatch_dev("SvelteRegisterBlock", {
36794 id: create_fragment$a.name,
36803 function handleFormSubmit(event) {
36804 let form_el = event.target;
36805 let val = form_el.querySelector("input[type=edit]").value;
36806 let matches = val.match(/^\s*([NWR])(\d+)\s*$/i);
36809 matches = val.match(/\/(relation|way|node)\/(\d+)\s*$/);
36813 alert("invalid input");
36817 form_el.querySelector("input[name=osmtype]").setAttribute("value", matches[1].charAt(0).toUpperCase());
36818 form_el.querySelector("input[name=osmid]").setAttribute("value", matches[2]);
36822 function instance$a($$self, $$props, $$invalidate) {
36823 let { $$slots: slots = {}, $$scope } = $$props;
36824 validate_slots("DetailsIndex", slots, []);
36825 const writable_props = [];
36827 Object.keys($$props).forEach(key => {
36828 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<DetailsIndex> was created with unknown prop '${key}'`);
36831 $$self.$capture_state = () => ({ handleFormSubmit });
36835 class DetailsIndex extends SvelteComponentDev {
36836 constructor(options) {
36838 init(this, options, instance$a, create_fragment$a, safe_not_equal, {});
36840 dispatch_dev("SvelteRegisterComponent", {
36842 tagName: "DetailsIndex",
36844 id: create_fragment$a.name
36849 /* src/components/DetailsOneRow.svelte generated by Svelte v3.31.2 */
36851 const file$b = "src/components/DetailsOneRow.svelte";
36854 function create_else_block$2(ctx) {
36858 c: function create() {
36859 span = element("span");
36860 span.textContent = "No Name";
36861 attr_dev(span, "class", "noname svelte-rtfpp8");
36862 add_location(span, file$b, 16, 6, 377);
36864 m: function mount(target, anchor) {
36865 insert_dev(target, span, anchor);
36868 d: function destroy(detaching) {
36869 if (detaching) detach_dev(span);
36873 dispatch_dev("SvelteRegisterBlock", {
36875 id: create_else_block$2.name,
36877 source: "(16:4) {:else}",
36884 // (14:4) {#if addressLine.localname}
36885 function create_if_block_1$1(ctx) {
36886 let t_value = /*addressLine*/ ctx[0].localname + "";
36890 c: function create() {
36893 m: function mount(target, anchor) {
36894 insert_dev(target, t, anchor);
36896 p: function update(ctx, dirty) {
36897 if (dirty & /*addressLine*/ 1 && t_value !== (t_value = /*addressLine*/ ctx[0].localname + "")) set_data_dev(t, t_value);
36899 d: function destroy(detaching) {
36900 if (detaching) detach_dev(t);
36904 dispatch_dev("SvelteRegisterBlock", {
36906 id: create_if_block_1$1.name,
36908 source: "(14:4) {#if addressLine.localname}",
36915 // (25:6) {#if addressLine.osm_id}
36916 function create_if_block$4(ctx) {
36922 c: function create() {
36924 t = text("details");
36925 attr_dev(a, "href", a_href_value = detailsURL_1(/*addressLine*/ ctx[0]));
36926 add_location(a, file$b, 24, 30, 711);
36928 m: function mount(target, anchor) {
36929 insert_dev(target, a, anchor);
36932 p: function update(ctx, dirty) {
36933 if (dirty & /*addressLine*/ 1 && a_href_value !== (a_href_value = detailsURL_1(/*addressLine*/ ctx[0]))) {
36934 attr_dev(a, "href", a_href_value);
36937 d: function destroy(detaching) {
36938 if (detaching) detach_dev(a);
36942 dispatch_dev("SvelteRegisterBlock", {
36944 id: create_if_block$4.name,
36946 source: "(25:6) {#if addressLine.osm_id}",
36953 function create_fragment$b(ctx) {
36958 let t1_value = formatPlaceType_1(/*addressLine*/ ctx[0]) + "";
36962 let raw0_value = osmLink_1(/*addressLine*/ ctx[0]) + "";
36965 let t4_value = /*addressLine*/ ctx[0].rank_address + "";
36969 let t6_value = formatAdminLevel_1(/*addressLine*/ ctx[0].admin_level) + "";
36973 let raw1_value = formatDistance_1(/*addressLine*/ ctx[0].distance, /*bDistanceInMeters*/ ctx[1]) + "";
36977 function select_block_type(ctx, dirty) {
36978 if (/*addressLine*/ ctx[0].localname) return create_if_block_1$1;
36979 return create_else_block$2;
36982 let current_block_type = select_block_type(ctx);
36983 let if_block0 = current_block_type(ctx);
36984 let if_block1 = /*addressLine*/ ctx[0].osm_id && create_if_block$4(ctx);
36987 c: function create() {
36988 tr = element("tr");
36989 td0 = element("td");
36992 td1 = element("td");
36993 t1 = text(t1_value);
36995 td2 = element("td");
36997 td3 = element("td");
36998 t4 = text(t4_value);
37000 td4 = element("td");
37001 t6 = text(t6_value);
37003 td5 = element("td");
37005 td6 = element("td");
37006 if (if_block1) if_block1.c();
37007 attr_dev(td0, "class", "name svelte-rtfpp8");
37008 add_location(td0, file$b, 12, 2, 279);
37009 add_location(td1, file$b, 19, 2, 433);
37010 add_location(td2, file$b, 20, 2, 475);
37011 add_location(td3, file$b, 21, 2, 515);
37012 add_location(td4, file$b, 22, 2, 553);
37013 add_location(td5, file$b, 23, 2, 608);
37014 add_location(td6, file$b, 24, 2, 683);
37015 attr_dev(tr, "class", "svelte-rtfpp8");
37016 toggle_class(tr, "notused", !/*bAddressLineUsed*/ ctx[2]);
37017 add_location(tr, file$b, 11, 0, 238);
37019 l: function claim(nodes) {
37020 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
37022 m: function mount(target, anchor) {
37023 insert_dev(target, tr, anchor);
37024 append_dev(tr, td0);
37025 if_block0.m(td0, null);
37026 append_dev(tr, t0);
37027 append_dev(tr, td1);
37028 append_dev(td1, t1);
37029 append_dev(tr, t2);
37030 append_dev(tr, td2);
37031 td2.innerHTML = raw0_value;
37032 append_dev(tr, t3);
37033 append_dev(tr, td3);
37034 append_dev(td3, t4);
37035 append_dev(tr, t5);
37036 append_dev(tr, td4);
37037 append_dev(td4, t6);
37038 append_dev(tr, t7);
37039 append_dev(tr, td5);
37040 td5.innerHTML = raw1_value;
37041 append_dev(tr, t8);
37042 append_dev(tr, td6);
37043 if (if_block1) if_block1.m(td6, null);
37045 p: function update(ctx, [dirty]) {
37046 if (current_block_type === (current_block_type = select_block_type(ctx)) && if_block0) {
37047 if_block0.p(ctx, dirty);
37050 if_block0 = current_block_type(ctx);
37054 if_block0.m(td0, null);
37058 if (dirty & /*addressLine*/ 1 && t1_value !== (t1_value = formatPlaceType_1(/*addressLine*/ ctx[0]) + "")) set_data_dev(t1, t1_value);
37059 if (dirty & /*addressLine*/ 1 && raw0_value !== (raw0_value = osmLink_1(/*addressLine*/ ctx[0]) + "")) td2.innerHTML = raw0_value; if (dirty & /*addressLine*/ 1 && t4_value !== (t4_value = /*addressLine*/ ctx[0].rank_address + "")) set_data_dev(t4, t4_value);
37060 if (dirty & /*addressLine*/ 1 && t6_value !== (t6_value = formatAdminLevel_1(/*addressLine*/ ctx[0].admin_level) + "")) set_data_dev(t6, t6_value);
37061 if (dirty & /*addressLine, bDistanceInMeters*/ 3 && raw1_value !== (raw1_value = formatDistance_1(/*addressLine*/ ctx[0].distance, /*bDistanceInMeters*/ ctx[1]) + "")) td5.innerHTML = raw1_value;
37062 if (/*addressLine*/ ctx[0].osm_id) {
37064 if_block1.p(ctx, dirty);
37066 if_block1 = create_if_block$4(ctx);
37068 if_block1.m(td6, null);
37070 } else if (if_block1) {
37075 if (dirty & /*bAddressLineUsed*/ 4) {
37076 toggle_class(tr, "notused", !/*bAddressLineUsed*/ ctx[2]);
37081 d: function destroy(detaching) {
37082 if (detaching) detach_dev(tr);
37084 if (if_block1) if_block1.d();
37088 dispatch_dev("SvelteRegisterBlock", {
37090 id: create_fragment$b.name,
37099 function instance$b($$self, $$props, $$invalidate) {
37100 let bAddressLineUsed;
37101 let { $$slots: slots = {}, $$scope } = $$props;
37102 validate_slots("DetailsOneRow", slots, []);
37103 let { addressLine } = $$props;
37104 let { bDistanceInMeters } = $$props;
37105 const writable_props = ["addressLine", "bDistanceInMeters"];
37107 Object.keys($$props).forEach(key => {
37108 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<DetailsOneRow> was created with unknown prop '${key}'`);
37111 $$self.$$set = $$props => {
37112 if ("addressLine" in $$props) $$invalidate(0, addressLine = $$props.addressLine);
37113 if ("bDistanceInMeters" in $$props) $$invalidate(1, bDistanceInMeters = $$props.bDistanceInMeters);
37116 $$self.$capture_state = () => ({
37119 formatPlaceType: formatPlaceType_1,
37120 osmLink: osmLink_1,
37121 formatAdminLevel: formatAdminLevel_1,
37122 formatDistance: formatDistance_1,
37123 detailsURL: detailsURL_1,
37127 $$self.$inject_state = $$props => {
37128 if ("addressLine" in $$props) $$invalidate(0, addressLine = $$props.addressLine);
37129 if ("bDistanceInMeters" in $$props) $$invalidate(1, bDistanceInMeters = $$props.bDistanceInMeters);
37130 if ("bAddressLineUsed" in $$props) $$invalidate(2, bAddressLineUsed = $$props.bAddressLineUsed);
37133 if ($$props && "$$inject" in $$props) {
37134 $$self.$inject_state($$props.$$inject);
37137 $$self.$$.update = () => {
37138 if ($$self.$$.dirty & /*addressLine*/ 1) {
37139 $$invalidate(2, bAddressLineUsed = addressLine.isaddress);
37143 return [addressLine, bDistanceInMeters, bAddressLineUsed];
37146 class DetailsOneRow extends SvelteComponentDev {
37147 constructor(options) {
37149 init(this, options, instance$b, create_fragment$b, safe_not_equal, { addressLine: 0, bDistanceInMeters: 1 });
37151 dispatch_dev("SvelteRegisterComponent", {
37153 tagName: "DetailsOneRow",
37155 id: create_fragment$b.name
37158 const { ctx } = this.$$;
37159 const props = options.props || {};
37161 if (/*addressLine*/ ctx[0] === undefined && !("addressLine" in props)) {
37162 console.warn("<DetailsOneRow> was created without expected prop 'addressLine'");
37165 if (/*bDistanceInMeters*/ ctx[1] === undefined && !("bDistanceInMeters" in props)) {
37166 console.warn("<DetailsOneRow> was created without expected prop 'bDistanceInMeters'");
37170 get addressLine() {
37171 throw new Error("<DetailsOneRow>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
37174 set addressLine(value) {
37175 throw new Error("<DetailsOneRow>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
37178 get bDistanceInMeters() {
37179 throw new Error("<DetailsOneRow>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
37182 set bDistanceInMeters(value) {
37183 throw new Error("<DetailsOneRow>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
37187 /* src/pages/DetailsPage.svelte generated by Svelte v3.31.2 */
37189 const { Object: Object_1 } = globals;
37190 const file$c = "src/pages/DetailsPage.svelte";
37192 function get_each_context$2(ctx, list, i) {
37193 const child_ctx = ctx.slice();
37194 child_ctx[3] = list[i];
37198 function get_each_context_1(ctx, list, i) {
37199 const child_ctx = ctx.slice();
37200 child_ctx[6] = list[i];
37204 function get_each_context_2(ctx, list, i) {
37205 const child_ctx = ctx.slice();
37206 child_ctx[9] = list[i];
37210 function get_each_context_3(ctx, list, i) {
37211 const child_ctx = ctx.slice();
37212 child_ctx[9] = list[i];
37216 function get_each_context_4(ctx, list, i) {
37217 const child_ctx = ctx.slice();
37218 child_ctx[14] = list[i];
37222 function get_each_context_5(ctx, list, i) {
37223 const child_ctx = ctx.slice();
37224 child_ctx[14] = list[i];
37228 function get_each_context_6(ctx, list, i) {
37229 const child_ctx = ctx.slice();
37230 child_ctx[19] = list[i];
37234 function get_each_context_7(ctx, list, i) {
37235 const child_ctx = ctx.slice();
37236 child_ctx[19] = list[i];
37240 function get_each_context_8(ctx, list, i) {
37241 const child_ctx = ctx.slice();
37242 child_ctx[19] = list[i];
37247 function create_else_block_2(ctx) {
37251 c: function create() {
37252 t = text("No such place found.");
37254 m: function mount(target, anchor) {
37255 insert_dev(target, t, anchor);
37260 d: function destroy(detaching) {
37261 if (detaching) detach_dev(t);
37265 dispatch_dev("SvelteRegisterBlock", {
37267 id: create_else_block_2.name,
37269 source: "(258:0) {:else}",
37277 function create_if_block_12(ctx) {
37280 detailsindex = new DetailsIndex({ $$inline: true });
37283 c: function create() {
37284 create_component(detailsindex.$$.fragment);
37286 m: function mount(target, anchor) {
37287 mount_component(detailsindex, target, anchor);
37291 i: function intro(local) {
37292 if (current) return;
37293 transition_in(detailsindex.$$.fragment, local);
37296 o: function outro(local) {
37297 transition_out(detailsindex.$$.fragment, local);
37300 d: function destroy(detaching) {
37301 destroy_component(detailsindex, detaching);
37305 dispatch_dev("SvelteRegisterBlock", {
37307 id: create_if_block_12.name,
37309 source: "(256:35) ",
37316 // (53:0) {#if aPlace}
37317 function create_if_block$5(ctx) {
37322 let t0_value = /*aPlace*/ ctx[0].localname + "";
37346 let t10_value = /*aPlace*/ ctx[0].category + "";
37349 let t12_value = /*aPlace*/ ctx[0].type + "";
37356 let t16_value = /*aPlace*/ ctx[0].indexed_date + "";
37359 let show_if = isAdminBoundary_1(/*aPlace*/ ctx[0]);
37365 let t21_value = /*aPlace*/ ctx[0].rank_search + "";
37372 let t25_value = /*aPlace*/ ctx[0].rank_address + "";
37375 let t27_value = formatAddressRank_1(/*aPlace*/ ctx[0].rank_address) + "";
37384 let t33_value = coverageType_1(/*aPlace*/ ctx[0]) + "";
37391 let t37_value = /*aPlace*/ ctx[0].centroid.coordinates[1] + "";
37394 let t39_value = /*aPlace*/ ctx[0].centroid.coordinates[0] + "";
37401 let raw_value = osmLink_1(/*aPlace*/ ctx[0]) + "";
37410 let t48_value = /*aPlace*/ ctx[0].place_id + "";
37418 let t53_value = /*aPlace*/ ctx[0].calculated_postcode + "";
37468 let current_block_type_index;
37472 mapicon = new MapIcon({
37473 props: { aPlace: /*aPlace*/ ctx[0] },
37477 let each_value_8 = Object.keys(/*aPlace*/ ctx[0].names);
37478 validate_each_argument(each_value_8);
37479 let each_blocks_2 = [];
37481 for (let i = 0; i < each_value_8.length; i += 1) {
37482 each_blocks_2[i] = create_each_block_8(get_each_context_8(ctx, each_value_8, i));
37485 let if_block0 = show_if && create_if_block_11(ctx);
37486 let if_block1 = /*aPlace*/ ctx[0].calculated_importance && create_if_block_9(ctx);
37487 let if_block2 = /*aPlace*/ ctx[0].calculated_wikipedia && create_if_block_8(ctx);
37488 let each_value_7 = Object.keys(/*aPlace*/ ctx[0].addresstags);
37489 validate_each_argument(each_value_7);
37490 let each_blocks_1 = [];
37492 for (let i = 0; i < each_value_7.length; i += 1) {
37493 each_blocks_1[i] = create_each_block_7(get_each_context_7(ctx, each_value_7, i));
37496 let each_value_6 = Object.keys(/*aPlace*/ ctx[0].extratags);
37497 validate_each_argument(each_value_6);
37498 let each_blocks = [];
37500 for (let i = 0; i < each_value_6.length; i += 1) {
37501 each_blocks[i] = create_each_block_6(get_each_context_6(ctx, each_value_6, i));
37504 map = new Map$1({ $$inline: true });
37505 let if_block3 = /*aPlace*/ ctx[0].address && create_if_block_7(ctx);
37506 let if_block4 = /*aPlace*/ ctx[0].linked_places && create_if_block_6(ctx);
37508 function select_block_type_1(ctx, dirty) {
37509 if (/*aPlace*/ ctx[0].keywords) return create_if_block_3$1;
37510 return create_else_block_1$1;
37513 let current_block_type = select_block_type_1(ctx);
37514 let if_block5 = current_block_type(ctx);
37515 const if_block_creators = [create_if_block_1$2, create_else_block$3];
37516 const if_blocks = [];
37518 function select_block_type_2(ctx, dirty) {
37519 if (/*aPlace*/ ctx[0].hierarchy) return 0;
37523 current_block_type_index = select_block_type_2(ctx);
37524 if_block6 = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
37527 c: function create() {
37528 div9 = element("div");
37529 div2 = element("div");
37530 div0 = element("div");
37531 h1 = element("h1");
37532 t0 = text(t0_value);
37534 small = element("small");
37536 t2 = text("link to this page");
37538 div1 = element("div");
37539 create_component(mapicon.$$.fragment);
37541 div6 = element("div");
37542 div3 = element("div");
37543 table0 = element("table");
37544 tbody0 = element("tbody");
37545 tr0 = element("tr");
37546 td0 = element("td");
37547 td0.textContent = "Name";
37549 td1 = element("td");
37551 for (let i = 0; i < each_blocks_2.length; i += 1) {
37552 each_blocks_2[i].c();
37556 tr1 = element("tr");
37557 td2 = element("td");
37558 td2.textContent = "Type";
37560 td3 = element("td");
37561 t10 = text(t10_value);
37563 t12 = text(t12_value);
37565 tr2 = element("tr");
37566 td4 = element("td");
37567 td4.textContent = "Last Updated";
37569 td5 = element("td");
37570 t16 = text(t16_value);
37572 if (if_block0) if_block0.c();
37574 tr3 = element("tr");
37575 td6 = element("td");
37576 td6.textContent = "Search Rank";
37578 td7 = element("td");
37579 t21 = text(t21_value);
37581 tr4 = element("tr");
37582 td8 = element("td");
37583 td8.textContent = "Address Rank";
37585 td9 = element("td");
37586 t25 = text(t25_value);
37588 t27 = text(t27_value);
37591 if (if_block1) if_block1.c();
37593 tr5 = element("tr");
37594 td10 = element("td");
37595 td10.textContent = "Coverage";
37597 td11 = element("td");
37598 t33 = text(t33_value);
37600 tr6 = element("tr");
37601 td12 = element("td");
37602 td12.textContent = "Centre Point (lat,lon)";
37604 td13 = element("td");
37605 t37 = text(t37_value);
37607 t39 = text(t39_value);
37609 tr7 = element("tr");
37610 td14 = element("td");
37611 td14.textContent = "OSM";
37613 td15 = element("td");
37615 tr8 = element("tr");
37616 td16 = element("td");
37617 t44 = text("Place Id\n (");
37619 a1.textContent = "on this server";
37622 td17 = element("td");
37623 t48 = text(t48_value);
37625 if (if_block2) if_block2.c();
37627 tr9 = element("tr");
37628 td18 = element("td");
37629 td18.textContent = "Computed Postcode";
37631 td19 = element("td");
37632 t53 = text(t53_value);
37634 tr10 = element("tr");
37635 td20 = element("td");
37636 td20.textContent = "Address Tags";
37638 td21 = element("td");
37640 for (let i = 0; i < each_blocks_1.length; i += 1) {
37641 each_blocks_1[i].c();
37645 tr11 = element("tr");
37646 td22 = element("td");
37647 td22.textContent = "Extra Tags";
37649 td23 = element("td");
37651 for (let i = 0; i < each_blocks.length; i += 1) {
37652 each_blocks[i].c();
37656 div5 = element("div");
37657 div4 = element("div");
37658 create_component(map.$$.fragment);
37660 div8 = element("div");
37661 div7 = element("div");
37662 h20 = element("h2");
37663 h20.textContent = "Address";
37665 table1 = element("table");
37666 thead = element("thead");
37667 tr12 = element("tr");
37668 th0 = element("th");
37669 th0.textContent = "Local name";
37671 th1 = element("th");
37672 th1.textContent = "Type";
37674 th2 = element("th");
37675 th2.textContent = "OSM";
37677 th3 = element("th");
37678 th3.textContent = "Address rank";
37680 th4 = element("th");
37681 th4.textContent = "Admin level";
37683 th5 = element("th");
37684 th5.textContent = "Distance";
37686 th6 = element("th");
37688 tbody1 = element("tbody");
37689 if (if_block3) if_block3.c();
37691 if (if_block4) if_block4.c();
37693 tr13 = element("tr");
37694 td24 = element("td");
37695 h21 = element("h2");
37696 h21.textContent = "Keywords";
37700 tr14 = element("tr");
37701 td25 = element("td");
37702 h22 = element("h2");
37703 h22.textContent = "Parent Of";
37706 attr_dev(a0, "href", a0_href_value = detailsURL_1(/*aPlace*/ ctx[0]));
37707 attr_dev(a0, "class", "svelte-j6zgmy");
37708 add_location(a0, file$c, 58, 17, 1869);
37709 add_location(small, file$c, 58, 10, 1862);
37710 attr_dev(h1, "class", "svelte-j6zgmy");
37711 add_location(h1, file$c, 56, 8, 1818);
37712 attr_dev(div0, "class", "col-sm-10");
37713 add_location(div0, file$c, 55, 6, 1786);
37714 attr_dev(div1, "class", "col-sm-2 text-right");
37715 add_location(div1, file$c, 61, 6, 1963);
37716 attr_dev(div2, "class", "row");
37717 add_location(div2, file$c, 54, 4, 1762);
37718 attr_dev(td0, "class", "svelte-j6zgmy");
37719 add_location(td0, file$c, 70, 14, 2222);
37720 attr_dev(td1, "class", "svelte-j6zgmy");
37721 add_location(td1, file$c, 71, 14, 2250);
37722 attr_dev(tr0, "class", "svelte-j6zgmy");
37723 add_location(tr0, file$c, 69, 12, 2203);
37724 attr_dev(td2, "class", "svelte-j6zgmy");
37725 add_location(td2, file$c, 80, 14, 2544);
37726 attr_dev(td3, "class", "svelte-j6zgmy");
37727 add_location(td3, file$c, 81, 14, 2572);
37728 attr_dev(tr1, "class", "svelte-j6zgmy");
37729 add_location(tr1, file$c, 79, 12, 2525);
37730 attr_dev(td4, "class", "svelte-j6zgmy");
37731 add_location(td4, file$c, 84, 14, 2662);
37732 attr_dev(td5, "class", "svelte-j6zgmy");
37733 add_location(td5, file$c, 85, 14, 2698);
37734 attr_dev(tr2, "class", "svelte-j6zgmy");
37735 add_location(tr2, file$c, 83, 12, 2643);
37736 attr_dev(td6, "class", "svelte-j6zgmy");
37737 add_location(td6, file$c, 94, 14, 2955);
37738 attr_dev(td7, "class", "svelte-j6zgmy");
37739 add_location(td7, file$c, 95, 14, 2990);
37740 attr_dev(tr3, "class", "svelte-j6zgmy");
37741 add_location(tr3, file$c, 93, 12, 2936);
37742 attr_dev(td8, "class", "svelte-j6zgmy");
37743 add_location(td8, file$c, 98, 14, 3069);
37744 attr_dev(td9, "class", "svelte-j6zgmy");
37745 add_location(td9, file$c, 99, 14, 3105);
37746 attr_dev(tr4, "class", "svelte-j6zgmy");
37747 add_location(tr4, file$c, 97, 12, 3050);
37748 attr_dev(td10, "class", "svelte-j6zgmy");
37749 add_location(td10, file$c, 111, 14, 3520);
37750 attr_dev(td11, "class", "svelte-j6zgmy");
37751 add_location(td11, file$c, 112, 14, 3552);
37752 attr_dev(tr5, "class", "svelte-j6zgmy");
37753 add_location(tr5, file$c, 110, 12, 3501);
37754 attr_dev(td12, "class", "svelte-j6zgmy");
37755 add_location(td12, file$c, 115, 14, 3633);
37756 attr_dev(td13, "class", "svelte-j6zgmy");
37757 add_location(td13, file$c, 116, 14, 3679);
37758 attr_dev(tr6, "class", "svelte-j6zgmy");
37759 add_location(tr6, file$c, 114, 12, 3614);
37760 attr_dev(td14, "class", "svelte-j6zgmy");
37761 add_location(td14, file$c, 121, 14, 3835);
37762 attr_dev(td15, "class", "svelte-j6zgmy");
37763 add_location(td15, file$c, 122, 14, 3862);
37764 attr_dev(tr7, "class", "svelte-j6zgmy");
37765 add_location(tr7, file$c, 120, 12, 3816);
37766 attr_dev(a1, "href", "https://nominatim.org/release-docs/develop/api/Output/#place_id-is-not-a-persistent-id");
37767 add_location(a1, file$c, 127, 17, 3986);
37768 attr_dev(td16, "class", "svelte-j6zgmy");
37769 add_location(td16, file$c, 125, 14, 3939);
37770 attr_dev(td17, "class", "svelte-j6zgmy");
37771 add_location(td17, file$c, 129, 14, 4137);
37772 attr_dev(tr8, "class", "svelte-j6zgmy");
37773 add_location(tr8, file$c, 124, 12, 3920);
37774 attr_dev(td18, "class", "svelte-j6zgmy");
37775 add_location(td18, file$c, 138, 14, 4417);
37776 attr_dev(td19, "class", "svelte-j6zgmy");
37777 add_location(td19, file$c, 139, 14, 4458);
37778 attr_dev(tr9, "class", "svelte-j6zgmy");
37779 add_location(tr9, file$c, 137, 12, 4398);
37780 attr_dev(td20, "class", "svelte-j6zgmy");
37781 add_location(td20, file$c, 142, 14, 4545);
37782 attr_dev(td21, "class", "svelte-j6zgmy");
37783 add_location(td21, file$c, 143, 14, 4581);
37784 attr_dev(tr10, "class", "svelte-j6zgmy");
37785 add_location(tr10, file$c, 141, 12, 4526);
37786 attr_dev(td22, "class", "svelte-j6zgmy");
37787 add_location(td22, file$c, 152, 14, 4887);
37788 attr_dev(td23, "class", "svelte-j6zgmy");
37789 add_location(td23, file$c, 153, 14, 4921);
37790 attr_dev(tr11, "class", "svelte-j6zgmy");
37791 add_location(tr11, file$c, 151, 12, 4868);
37792 attr_dev(tbody0, "class", "svelte-j6zgmy");
37793 add_location(tbody0, file$c, 68, 10, 2183);
37794 attr_dev(table0, "id", "locationdetails");
37795 attr_dev(table0, "class", "table table-striped svelte-j6zgmy");
37796 add_location(table0, file$c, 67, 8, 2116);
37797 attr_dev(div3, "class", "col-md-6");
37798 add_location(div3, file$c, 66, 6, 2085);
37799 attr_dev(div4, "id", "map-wrapper");
37800 attr_dev(div4, "class", "svelte-j6zgmy");
37801 add_location(div4, file$c, 165, 8, 5278);
37802 attr_dev(div5, "class", "col-md-6");
37803 add_location(div5, file$c, 164, 6, 5247);
37804 attr_dev(div6, "class", "row");
37805 add_location(div6, file$c, 65, 4, 2061);
37806 attr_dev(h20, "class", "svelte-j6zgmy");
37807 add_location(h20, file$c, 172, 8, 5417);
37808 attr_dev(th0, "class", "svelte-j6zgmy");
37809 add_location(th0, file$c, 176, 14, 5553);
37810 attr_dev(th1, "class", "svelte-j6zgmy");
37811 add_location(th1, file$c, 177, 14, 5587);
37812 attr_dev(th2, "class", "svelte-j6zgmy");
37813 add_location(th2, file$c, 178, 14, 5615);
37814 attr_dev(th3, "class", "svelte-j6zgmy");
37815 add_location(th3, file$c, 179, 14, 5642);
37816 attr_dev(th4, "class", "svelte-j6zgmy");
37817 add_location(th4, file$c, 180, 14, 5678);
37818 attr_dev(th5, "class", "svelte-j6zgmy");
37819 add_location(th5, file$c, 181, 14, 5713);
37820 attr_dev(th6, "class", "svelte-j6zgmy");
37821 add_location(th6, file$c, 182, 14, 5745);
37822 attr_dev(tr12, "class", "svelte-j6zgmy");
37823 add_location(tr12, file$c, 175, 12, 5534);
37824 attr_dev(thead, "class", "svelte-j6zgmy");
37825 add_location(thead, file$c, 174, 10, 5514);
37826 attr_dev(h21, "class", "svelte-j6zgmy");
37827 add_location(h21, file$c, 199, 52, 6380);
37828 attr_dev(td24, "colspan", "6");
37829 attr_dev(td24, "class", "svelte-j6zgmy");
37830 add_location(td24, file$c, 199, 36, 6364);
37831 attr_dev(tr13, "class", "all-columns svelte-j6zgmy");
37832 add_location(tr13, file$c, 199, 12, 6340);
37833 attr_dev(h22, "class", "svelte-j6zgmy");
37834 add_location(h22, file$c, 229, 52, 7511);
37835 attr_dev(td25, "colspan", "6");
37836 attr_dev(td25, "class", "svelte-j6zgmy");
37837 add_location(td25, file$c, 229, 36, 7495);
37838 attr_dev(tr14, "class", "all-columns svelte-j6zgmy");
37839 add_location(tr14, file$c, 229, 12, 7471);
37840 attr_dev(tbody1, "class", "svelte-j6zgmy");
37841 add_location(tbody1, file$c, 185, 10, 5802);
37842 attr_dev(table1, "id", "address");
37843 attr_dev(table1, "class", "table table-striped table-small svelte-j6zgmy");
37844 add_location(table1, file$c, 173, 9, 5443);
37845 attr_dev(div7, "class", "col-md-12");
37846 add_location(div7, file$c, 171, 6, 5385);
37847 attr_dev(div8, "class", "row");
37848 add_location(div8, file$c, 170, 4, 5361);
37849 attr_dev(div9, "class", "container");
37850 add_location(div9, file$c, 53, 2, 1734);
37852 m: function mount(target, anchor) {
37853 insert_dev(target, div9, anchor);
37854 append_dev(div9, div2);
37855 append_dev(div2, div0);
37856 append_dev(div0, h1);
37857 append_dev(h1, t0);
37858 append_dev(h1, t1);
37859 append_dev(h1, small);
37860 append_dev(small, a0);
37861 append_dev(a0, t2);
37862 append_dev(div2, t3);
37863 append_dev(div2, div1);
37864 mount_component(mapicon, div1, null);
37865 append_dev(div9, t4);
37866 append_dev(div9, div6);
37867 append_dev(div6, div3);
37868 append_dev(div3, table0);
37869 append_dev(table0, tbody0);
37870 append_dev(tbody0, tr0);
37871 append_dev(tr0, td0);
37872 append_dev(tr0, t6);
37873 append_dev(tr0, td1);
37875 for (let i = 0; i < each_blocks_2.length; i += 1) {
37876 each_blocks_2[i].m(td1, null);
37879 append_dev(tbody0, t7);
37880 append_dev(tbody0, tr1);
37881 append_dev(tr1, td2);
37882 append_dev(tr1, t9);
37883 append_dev(tr1, td3);
37884 append_dev(td3, t10);
37885 append_dev(td3, t11);
37886 append_dev(td3, t12);
37887 append_dev(tbody0, t13);
37888 append_dev(tbody0, tr2);
37889 append_dev(tr2, td4);
37890 append_dev(tr2, t15);
37891 append_dev(tr2, td5);
37892 append_dev(td5, t16);
37893 append_dev(tbody0, t17);
37894 if (if_block0) if_block0.m(tbody0, null);
37895 append_dev(tbody0, t18);
37896 append_dev(tbody0, tr3);
37897 append_dev(tr3, td6);
37898 append_dev(tr3, t20);
37899 append_dev(tr3, td7);
37900 append_dev(td7, t21);
37901 append_dev(tbody0, t22);
37902 append_dev(tbody0, tr4);
37903 append_dev(tr4, td8);
37904 append_dev(tr4, t24);
37905 append_dev(tr4, td9);
37906 append_dev(td9, t25);
37907 append_dev(td9, t26);
37908 append_dev(td9, t27);
37909 append_dev(td9, t28);
37910 append_dev(tbody0, t29);
37911 if (if_block1) if_block1.m(tbody0, null);
37912 append_dev(tbody0, t30);
37913 append_dev(tbody0, tr5);
37914 append_dev(tr5, td10);
37915 append_dev(tr5, t32);
37916 append_dev(tr5, td11);
37917 append_dev(td11, t33);
37918 append_dev(tbody0, t34);
37919 append_dev(tbody0, tr6);
37920 append_dev(tr6, td12);
37921 append_dev(tr6, t36);
37922 append_dev(tr6, td13);
37923 append_dev(td13, t37);
37924 append_dev(td13, t38);
37925 append_dev(td13, t39);
37926 append_dev(tbody0, t40);
37927 append_dev(tbody0, tr7);
37928 append_dev(tr7, td14);
37929 append_dev(tr7, t42);
37930 append_dev(tr7, td15);
37931 td15.innerHTML = raw_value;
37932 append_dev(tbody0, t43);
37933 append_dev(tbody0, tr8);
37934 append_dev(tr8, td16);
37935 append_dev(td16, t44);
37936 append_dev(td16, a1);
37937 append_dev(td16, t46);
37938 append_dev(tr8, t47);
37939 append_dev(tr8, td17);
37940 append_dev(td17, t48);
37941 append_dev(tbody0, t49);
37942 if (if_block2) if_block2.m(tbody0, null);
37943 append_dev(tbody0, t50);
37944 append_dev(tbody0, tr9);
37945 append_dev(tr9, td18);
37946 append_dev(tr9, t52);
37947 append_dev(tr9, td19);
37948 append_dev(td19, t53);
37949 append_dev(tbody0, t54);
37950 append_dev(tbody0, tr10);
37951 append_dev(tr10, td20);
37952 append_dev(tr10, t56);
37953 append_dev(tr10, td21);
37955 for (let i = 0; i < each_blocks_1.length; i += 1) {
37956 each_blocks_1[i].m(td21, null);
37959 append_dev(tbody0, t57);
37960 append_dev(tbody0, tr11);
37961 append_dev(tr11, td22);
37962 append_dev(tr11, t59);
37963 append_dev(tr11, td23);
37965 for (let i = 0; i < each_blocks.length; i += 1) {
37966 each_blocks[i].m(td23, null);
37969 append_dev(div6, t60);
37970 append_dev(div6, div5);
37971 append_dev(div5, div4);
37972 mount_component(map, div4, null);
37973 append_dev(div9, t61);
37974 append_dev(div9, div8);
37975 append_dev(div8, div7);
37976 append_dev(div7, h20);
37977 append_dev(div7, t63);
37978 append_dev(div7, table1);
37979 append_dev(table1, thead);
37980 append_dev(thead, tr12);
37981 append_dev(tr12, th0);
37982 append_dev(tr12, t65);
37983 append_dev(tr12, th1);
37984 append_dev(tr12, t67);
37985 append_dev(tr12, th2);
37986 append_dev(tr12, t69);
37987 append_dev(tr12, th3);
37988 append_dev(tr12, t71);
37989 append_dev(tr12, th4);
37990 append_dev(tr12, t73);
37991 append_dev(tr12, th5);
37992 append_dev(tr12, t75);
37993 append_dev(tr12, th6);
37994 append_dev(table1, t76);
37995 append_dev(table1, tbody1);
37996 if (if_block3) if_block3.m(tbody1, null);
37997 append_dev(tbody1, t77);
37998 if (if_block4) if_block4.m(tbody1, null);
37999 append_dev(tbody1, t78);
38000 append_dev(tbody1, tr13);
38001 append_dev(tr13, td24);
38002 append_dev(td24, h21);
38003 append_dev(tbody1, t80);
38004 if_block5.m(tbody1, null);
38005 append_dev(tbody1, t81);
38006 append_dev(tbody1, tr14);
38007 append_dev(tr14, td25);
38008 append_dev(td25, h22);
38009 append_dev(tbody1, t83);
38010 if_blocks[current_block_type_index].m(tbody1, null);
38013 p: function update(ctx, dirty) {
38014 if ((!current || dirty & /*aPlace*/ 1) && t0_value !== (t0_value = /*aPlace*/ ctx[0].localname + "")) set_data_dev(t0, t0_value);
38016 if (!current || dirty & /*aPlace*/ 1 && a0_href_value !== (a0_href_value = detailsURL_1(/*aPlace*/ ctx[0]))) {
38017 attr_dev(a0, "href", a0_href_value);
38020 const mapicon_changes = {};
38021 if (dirty & /*aPlace*/ 1) mapicon_changes.aPlace = /*aPlace*/ ctx[0];
38022 mapicon.$set(mapicon_changes);
38024 if (dirty & /*Object, aPlace*/ 1) {
38025 each_value_8 = Object.keys(/*aPlace*/ ctx[0].names);
38026 validate_each_argument(each_value_8);
38029 for (i = 0; i < each_value_8.length; i += 1) {
38030 const child_ctx = get_each_context_8(ctx, each_value_8, i);
38032 if (each_blocks_2[i]) {
38033 each_blocks_2[i].p(child_ctx, dirty);
38035 each_blocks_2[i] = create_each_block_8(child_ctx);
38036 each_blocks_2[i].c();
38037 each_blocks_2[i].m(td1, null);
38041 for (; i < each_blocks_2.length; i += 1) {
38042 each_blocks_2[i].d(1);
38045 each_blocks_2.length = each_value_8.length;
38048 if ((!current || dirty & /*aPlace*/ 1) && t10_value !== (t10_value = /*aPlace*/ ctx[0].category + "")) set_data_dev(t10, t10_value);
38049 if ((!current || dirty & /*aPlace*/ 1) && t12_value !== (t12_value = /*aPlace*/ ctx[0].type + "")) set_data_dev(t12, t12_value);
38050 if ((!current || dirty & /*aPlace*/ 1) && t16_value !== (t16_value = /*aPlace*/ ctx[0].indexed_date + "")) set_data_dev(t16, t16_value);
38051 if (dirty & /*aPlace*/ 1) show_if = isAdminBoundary_1(/*aPlace*/ ctx[0]);
38055 if_block0.p(ctx, dirty);
38057 if_block0 = create_if_block_11(ctx);
38059 if_block0.m(tbody0, t18);
38061 } else if (if_block0) {
38066 if ((!current || dirty & /*aPlace*/ 1) && t21_value !== (t21_value = /*aPlace*/ ctx[0].rank_search + "")) set_data_dev(t21, t21_value);
38067 if ((!current || dirty & /*aPlace*/ 1) && t25_value !== (t25_value = /*aPlace*/ ctx[0].rank_address + "")) set_data_dev(t25, t25_value);
38068 if ((!current || dirty & /*aPlace*/ 1) && t27_value !== (t27_value = formatAddressRank_1(/*aPlace*/ ctx[0].rank_address) + "")) set_data_dev(t27, t27_value);
38070 if (/*aPlace*/ ctx[0].calculated_importance) {
38072 if_block1.p(ctx, dirty);
38074 if_block1 = create_if_block_9(ctx);
38076 if_block1.m(tbody0, t30);
38078 } else if (if_block1) {
38083 if ((!current || dirty & /*aPlace*/ 1) && t33_value !== (t33_value = coverageType_1(/*aPlace*/ ctx[0]) + "")) set_data_dev(t33, t33_value);
38084 if ((!current || dirty & /*aPlace*/ 1) && t37_value !== (t37_value = /*aPlace*/ ctx[0].centroid.coordinates[1] + "")) set_data_dev(t37, t37_value);
38085 if ((!current || dirty & /*aPlace*/ 1) && t39_value !== (t39_value = /*aPlace*/ ctx[0].centroid.coordinates[0] + "")) set_data_dev(t39, t39_value);
38086 if ((!current || dirty & /*aPlace*/ 1) && raw_value !== (raw_value = osmLink_1(/*aPlace*/ ctx[0]) + "")) td15.innerHTML = raw_value; if ((!current || dirty & /*aPlace*/ 1) && t48_value !== (t48_value = /*aPlace*/ ctx[0].place_id + "")) set_data_dev(t48, t48_value);
38088 if (/*aPlace*/ ctx[0].calculated_wikipedia) {
38090 if_block2.p(ctx, dirty);
38092 if_block2 = create_if_block_8(ctx);
38094 if_block2.m(tbody0, t50);
38096 } else if (if_block2) {
38101 if ((!current || dirty & /*aPlace*/ 1) && t53_value !== (t53_value = /*aPlace*/ ctx[0].calculated_postcode + "")) set_data_dev(t53, t53_value);
38103 if (dirty & /*Object, aPlace*/ 1) {
38104 each_value_7 = Object.keys(/*aPlace*/ ctx[0].addresstags);
38105 validate_each_argument(each_value_7);
38108 for (i = 0; i < each_value_7.length; i += 1) {
38109 const child_ctx = get_each_context_7(ctx, each_value_7, i);
38111 if (each_blocks_1[i]) {
38112 each_blocks_1[i].p(child_ctx, dirty);
38114 each_blocks_1[i] = create_each_block_7(child_ctx);
38115 each_blocks_1[i].c();
38116 each_blocks_1[i].m(td21, null);
38120 for (; i < each_blocks_1.length; i += 1) {
38121 each_blocks_1[i].d(1);
38124 each_blocks_1.length = each_value_7.length;
38127 if (dirty & /*Object, aPlace*/ 1) {
38128 each_value_6 = Object.keys(/*aPlace*/ ctx[0].extratags);
38129 validate_each_argument(each_value_6);
38132 for (i = 0; i < each_value_6.length; i += 1) {
38133 const child_ctx = get_each_context_6(ctx, each_value_6, i);
38135 if (each_blocks[i]) {
38136 each_blocks[i].p(child_ctx, dirty);
38138 each_blocks[i] = create_each_block_6(child_ctx);
38139 each_blocks[i].c();
38140 each_blocks[i].m(td23, null);
38144 for (; i < each_blocks.length; i += 1) {
38145 each_blocks[i].d(1);
38148 each_blocks.length = each_value_6.length;
38151 if (/*aPlace*/ ctx[0].address) {
38153 if_block3.p(ctx, dirty);
38155 if (dirty & /*aPlace*/ 1) {
38156 transition_in(if_block3, 1);
38159 if_block3 = create_if_block_7(ctx);
38161 transition_in(if_block3, 1);
38162 if_block3.m(tbody1, t77);
38164 } else if (if_block3) {
38167 transition_out(if_block3, 1, 1, () => {
38174 if (/*aPlace*/ ctx[0].linked_places) {
38176 if_block4.p(ctx, dirty);
38178 if (dirty & /*aPlace*/ 1) {
38179 transition_in(if_block4, 1);
38182 if_block4 = create_if_block_6(ctx);
38184 transition_in(if_block4, 1);
38185 if_block4.m(tbody1, t78);
38187 } else if (if_block4) {
38190 transition_out(if_block4, 1, 1, () => {
38197 if (current_block_type === (current_block_type = select_block_type_1(ctx)) && if_block5) {
38198 if_block5.p(ctx, dirty);
38201 if_block5 = current_block_type(ctx);
38205 if_block5.m(tbody1, t81);
38209 let previous_block_index = current_block_type_index;
38210 current_block_type_index = select_block_type_2(ctx);
38212 if (current_block_type_index === previous_block_index) {
38213 if_blocks[current_block_type_index].p(ctx, dirty);
38217 transition_out(if_blocks[previous_block_index], 1, 1, () => {
38218 if_blocks[previous_block_index] = null;
38222 if_block6 = if_blocks[current_block_type_index];
38225 if_block6 = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
38228 if_block6.p(ctx, dirty);
38231 transition_in(if_block6, 1);
38232 if_block6.m(tbody1, null);
38235 i: function intro(local) {
38236 if (current) return;
38237 transition_in(mapicon.$$.fragment, local);
38238 transition_in(map.$$.fragment, local);
38239 transition_in(if_block3);
38240 transition_in(if_block4);
38241 transition_in(if_block6);
38244 o: function outro(local) {
38245 transition_out(mapicon.$$.fragment, local);
38246 transition_out(map.$$.fragment, local);
38247 transition_out(if_block3);
38248 transition_out(if_block4);
38249 transition_out(if_block6);
38252 d: function destroy(detaching) {
38253 if (detaching) detach_dev(div9);
38254 destroy_component(mapicon);
38255 destroy_each(each_blocks_2, detaching);
38256 if (if_block0) if_block0.d();
38257 if (if_block1) if_block1.d();
38258 if (if_block2) if_block2.d();
38259 destroy_each(each_blocks_1, detaching);
38260 destroy_each(each_blocks, detaching);
38261 destroy_component(map);
38262 if (if_block3) if_block3.d();
38263 if (if_block4) if_block4.d();
38265 if_blocks[current_block_type_index].d();
38269 dispatch_dev("SvelteRegisterBlock", {
38271 id: create_if_block$5.name,
38273 source: "(53:0) {#if aPlace}",
38280 // (73:16) {#each Object.keys(aPlace.names) as name}
38281 function create_each_block_8(ctx) {
38284 let t0_value = /*aPlace*/ ctx[0].names[/*name*/ ctx[19]] + "";
38287 let t2_value = /*name*/ ctx[19] + "";
38292 c: function create() {
38293 div = element("div");
38294 span = element("span");
38295 t0 = text(t0_value);
38297 t2 = text(t2_value);
38299 attr_dev(span, "class", "name svelte-j6zgmy");
38300 add_location(span, file$c, 74, 20, 2370);
38301 attr_dev(div, "class", "line");
38302 add_location(div, file$c, 73, 18, 2331);
38304 m: function mount(target, anchor) {
38305 insert_dev(target, div, anchor);
38306 append_dev(div, span);
38307 append_dev(span, t0);
38308 append_dev(div, t1);
38309 append_dev(div, t2);
38310 append_dev(div, t3);
38312 p: function update(ctx, dirty) {
38313 if (dirty & /*aPlace*/ 1 && t0_value !== (t0_value = /*aPlace*/ ctx[0].names[/*name*/ ctx[19]] + "")) set_data_dev(t0, t0_value);
38314 if (dirty & /*aPlace*/ 1 && t2_value !== (t2_value = /*name*/ ctx[19] + "")) set_data_dev(t2, t2_value);
38316 d: function destroy(detaching) {
38317 if (detaching) detach_dev(div);
38321 dispatch_dev("SvelteRegisterBlock", {
38323 id: create_each_block_8.name,
38325 source: "(73:16) {#each Object.keys(aPlace.names) as name}",
38332 // (88:12) {#if (isAdminBoundary(aPlace)) }
38333 function create_if_block_11(ctx) {
38338 let t2_value = /*aPlace*/ ctx[0].admin_level + "";
38342 c: function create() {
38343 tr = element("tr");
38344 td0 = element("td");
38345 td0.textContent = "Admin Level";
38347 td1 = element("td");
38348 t2 = text(t2_value);
38349 attr_dev(td0, "class", "svelte-j6zgmy");
38350 add_location(td0, file$c, 89, 14, 2823);
38351 attr_dev(td1, "class", "svelte-j6zgmy");
38352 add_location(td1, file$c, 90, 14, 2858);
38353 attr_dev(tr, "class", "svelte-j6zgmy");
38354 add_location(tr, file$c, 88, 12, 2804);
38356 m: function mount(target, anchor) {
38357 insert_dev(target, tr, anchor);
38358 append_dev(tr, td0);
38359 append_dev(tr, t1);
38360 append_dev(tr, td1);
38361 append_dev(td1, t2);
38363 p: function update(ctx, dirty) {
38364 if (dirty & /*aPlace*/ 1 && t2_value !== (t2_value = /*aPlace*/ ctx[0].admin_level + "")) set_data_dev(t2, t2_value);
38366 d: function destroy(detaching) {
38367 if (detaching) detach_dev(tr);
38371 dispatch_dev("SvelteRegisterBlock", {
38373 id: create_if_block_11.name,
38375 source: "(88:12) {#if (isAdminBoundary(aPlace)) }",
38382 // (102:12) {#if aPlace.calculated_importance}
38383 function create_if_block_9(ctx) {
38388 let t2_value = /*aPlace*/ ctx[0].calculated_importance + "";
38391 let if_block = !/*aPlace*/ ctx[0].importance && create_if_block_10(ctx);
38394 c: function create() {
38395 tr = element("tr");
38396 td0 = element("td");
38397 td0.textContent = "Importance";
38399 td1 = element("td");
38400 t2 = text(t2_value);
38402 if (if_block) if_block.c();
38403 attr_dev(td0, "class", "svelte-j6zgmy");
38404 add_location(td0, file$c, 103, 16, 3279);
38405 attr_dev(td1, "class", "svelte-j6zgmy");
38406 add_location(td1, file$c, 104, 16, 3315);
38407 attr_dev(tr, "class", "svelte-j6zgmy");
38408 add_location(tr, file$c, 102, 14, 3258);
38410 m: function mount(target, anchor) {
38411 insert_dev(target, tr, anchor);
38412 append_dev(tr, td0);
38413 append_dev(tr, t1);
38414 append_dev(tr, td1);
38415 append_dev(td1, t2);
38416 append_dev(td1, t3);
38417 if (if_block) if_block.m(td1, null);
38419 p: function update(ctx, dirty) {
38420 if (dirty & /*aPlace*/ 1 && t2_value !== (t2_value = /*aPlace*/ ctx[0].calculated_importance + "")) set_data_dev(t2, t2_value);
38422 if (!/*aPlace*/ ctx[0].importance) {
38423 if (if_block) ; else {
38424 if_block = create_if_block_10(ctx);
38426 if_block.m(td1, null);
38428 } else if (if_block) {
38433 d: function destroy(detaching) {
38434 if (detaching) detach_dev(tr);
38435 if (if_block) if_block.d();
38439 dispatch_dev("SvelteRegisterBlock", {
38441 id: create_if_block_9.name,
38443 source: "(102:12) {#if aPlace.calculated_importance}",
38450 // (107:18) {#if !aPlace.importance}
38451 function create_if_block_10(ctx) {
38455 c: function create() {
38456 t = text("(estimated)");
38458 m: function mount(target, anchor) {
38459 insert_dev(target, t, anchor);
38461 d: function destroy(detaching) {
38462 if (detaching) detach_dev(t);
38466 dispatch_dev("SvelteRegisterBlock", {
38468 id: create_if_block_10.name,
38470 source: "(107:18) {#if !aPlace.importance}",
38477 // (132:12) {#if aPlace.calculated_wikipedia}
38478 function create_if_block_8(ctx) {
38483 let raw_value = wikipediaLink_1(/*aPlace*/ ctx[0]) + "";
38486 c: function create() {
38487 tr = element("tr");
38488 td0 = element("td");
38489 td0.textContent = "Wikipedia Calculated";
38491 td1 = element("td");
38492 attr_dev(td0, "class", "svelte-j6zgmy");
38493 add_location(td0, file$c, 133, 16, 4263);
38494 attr_dev(td1, "class", "svelte-j6zgmy");
38495 add_location(td1, file$c, 134, 16, 4309);
38496 attr_dev(tr, "class", "svelte-j6zgmy");
38497 add_location(tr, file$c, 132, 14, 4242);
38499 m: function mount(target, anchor) {
38500 insert_dev(target, tr, anchor);
38501 append_dev(tr, td0);
38502 append_dev(tr, t1);
38503 append_dev(tr, td1);
38504 td1.innerHTML = raw_value;
38506 p: function update(ctx, dirty) {
38507 if (dirty & /*aPlace*/ 1 && raw_value !== (raw_value = wikipediaLink_1(/*aPlace*/ ctx[0]) + "")) td1.innerHTML = raw_value; },
38508 d: function destroy(detaching) {
38509 if (detaching) detach_dev(tr);
38513 dispatch_dev("SvelteRegisterBlock", {
38515 id: create_if_block_8.name,
38517 source: "(132:12) {#if aPlace.calculated_wikipedia}",
38524 // (145:16) {#each Object.keys(aPlace.addresstags) as name}
38525 function create_each_block_7(ctx) {
38528 let t0_value = /*aPlace*/ ctx[0].addresstags[/*name*/ ctx[19]] + "";
38531 let t2_value = /*name*/ ctx[19] + "";
38536 c: function create() {
38537 div = element("div");
38538 span = element("span");
38539 t0 = text(t0_value);
38541 t2 = text(t2_value);
38543 attr_dev(span, "class", "name svelte-j6zgmy");
38544 add_location(span, file$c, 146, 20, 4707);
38545 attr_dev(div, "class", "line");
38546 add_location(div, file$c, 145, 18, 4668);
38548 m: function mount(target, anchor) {
38549 insert_dev(target, div, anchor);
38550 append_dev(div, span);
38551 append_dev(span, t0);
38552 append_dev(div, t1);
38553 append_dev(div, t2);
38554 append_dev(div, t3);
38556 p: function update(ctx, dirty) {
38557 if (dirty & /*aPlace*/ 1 && t0_value !== (t0_value = /*aPlace*/ ctx[0].addresstags[/*name*/ ctx[19]] + "")) set_data_dev(t0, t0_value);
38558 if (dirty & /*aPlace*/ 1 && t2_value !== (t2_value = /*name*/ ctx[19] + "")) set_data_dev(t2, t2_value);
38560 d: function destroy(detaching) {
38561 if (detaching) detach_dev(div);
38565 dispatch_dev("SvelteRegisterBlock", {
38567 id: create_each_block_7.name,
38569 source: "(145:16) {#each Object.keys(aPlace.addresstags) as name}",
38576 // (155:16) {#each Object.keys(aPlace.extratags) as name}
38577 function create_each_block_6(ctx) {
38580 let t0_value = /*aPlace*/ ctx[0].extratags[/*name*/ ctx[19]] + "";
38583 let t2_value = /*name*/ ctx[19] + "";
38588 c: function create() {
38589 div = element("div");
38590 span = element("span");
38591 t0 = text(t0_value);
38593 t2 = text(t2_value);
38595 attr_dev(span, "class", "name svelte-j6zgmy");
38596 add_location(span, file$c, 156, 20, 5045);
38597 attr_dev(div, "class", "line");
38598 add_location(div, file$c, 155, 18, 5006);
38600 m: function mount(target, anchor) {
38601 insert_dev(target, div, anchor);
38602 append_dev(div, span);
38603 append_dev(span, t0);
38604 append_dev(div, t1);
38605 append_dev(div, t2);
38606 append_dev(div, t3);
38608 p: function update(ctx, dirty) {
38609 if (dirty & /*aPlace*/ 1 && t0_value !== (t0_value = /*aPlace*/ ctx[0].extratags[/*name*/ ctx[19]] + "")) set_data_dev(t0, t0_value);
38610 if (dirty & /*aPlace*/ 1 && t2_value !== (t2_value = /*name*/ ctx[19] + "")) set_data_dev(t2, t2_value);
38612 d: function destroy(detaching) {
38613 if (detaching) detach_dev(div);
38617 dispatch_dev("SvelteRegisterBlock", {
38619 id: create_each_block_6.name,
38621 source: "(155:16) {#each Object.keys(aPlace.extratags) as name}",
38628 // (187:12) {#if aPlace.address}
38629 function create_if_block_7(ctx) {
38632 let each_value_5 = /*aPlace*/ ctx[0].address;
38633 validate_each_argument(each_value_5);
38634 let each_blocks = [];
38636 for (let i = 0; i < each_value_5.length; i += 1) {
38637 each_blocks[i] = create_each_block_5(get_each_context_5(ctx, each_value_5, i));
38640 const out = i => transition_out(each_blocks[i], 1, 1, () => {
38641 each_blocks[i] = null;
38645 c: function create() {
38646 for (let i = 0; i < each_blocks.length; i += 1) {
38647 each_blocks[i].c();
38650 each_1_anchor = empty();
38652 m: function mount(target, anchor) {
38653 for (let i = 0; i < each_blocks.length; i += 1) {
38654 each_blocks[i].m(target, anchor);
38657 insert_dev(target, each_1_anchor, anchor);
38660 p: function update(ctx, dirty) {
38661 if (dirty & /*aPlace*/ 1) {
38662 each_value_5 = /*aPlace*/ ctx[0].address;
38663 validate_each_argument(each_value_5);
38666 for (i = 0; i < each_value_5.length; i += 1) {
38667 const child_ctx = get_each_context_5(ctx, each_value_5, i);
38669 if (each_blocks[i]) {
38670 each_blocks[i].p(child_ctx, dirty);
38671 transition_in(each_blocks[i], 1);
38673 each_blocks[i] = create_each_block_5(child_ctx);
38674 each_blocks[i].c();
38675 transition_in(each_blocks[i], 1);
38676 each_blocks[i].m(each_1_anchor.parentNode, each_1_anchor);
38682 for (i = each_value_5.length; i < each_blocks.length; i += 1) {
38689 i: function intro(local) {
38690 if (current) return;
38692 for (let i = 0; i < each_value_5.length; i += 1) {
38693 transition_in(each_blocks[i]);
38698 o: function outro(local) {
38699 each_blocks = each_blocks.filter(Boolean);
38701 for (let i = 0; i < each_blocks.length; i += 1) {
38702 transition_out(each_blocks[i]);
38707 d: function destroy(detaching) {
38708 destroy_each(each_blocks, detaching);
38709 if (detaching) detach_dev(each_1_anchor);
38713 dispatch_dev("SvelteRegisterBlock", {
38715 id: create_if_block_7.name,
38717 source: "(187:12) {#if aPlace.address}",
38724 // (188:14) {#each aPlace.address as addressLine}
38725 function create_each_block_5(ctx) {
38729 detailsonerow = new DetailsOneRow({
38731 addressLine: /*addressLine*/ ctx[14],
38732 bDistanceInMeters: "false"
38738 c: function create() {
38739 create_component(detailsonerow.$$.fragment);
38741 m: function mount(target, anchor) {
38742 mount_component(detailsonerow, target, anchor);
38745 p: function update(ctx, dirty) {
38746 const detailsonerow_changes = {};
38747 if (dirty & /*aPlace*/ 1) detailsonerow_changes.addressLine = /*addressLine*/ ctx[14];
38748 detailsonerow.$set(detailsonerow_changes);
38750 i: function intro(local) {
38751 if (current) return;
38752 transition_in(detailsonerow.$$.fragment, local);
38755 o: function outro(local) {
38756 transition_out(detailsonerow.$$.fragment, local);
38759 d: function destroy(detaching) {
38760 destroy_component(detailsonerow, detaching);
38764 dispatch_dev("SvelteRegisterBlock", {
38766 id: create_each_block_5.name,
38768 source: "(188:14) {#each aPlace.address as addressLine}",
38775 // (193:12) {#if aPlace.linked_places}
38776 function create_if_block_6(ctx) {
38783 let each_value_4 = /*aPlace*/ ctx[0].linked_places;
38784 validate_each_argument(each_value_4);
38785 let each_blocks = [];
38787 for (let i = 0; i < each_value_4.length; i += 1) {
38788 each_blocks[i] = create_each_block_4(get_each_context_4(ctx, each_value_4, i));
38791 const out = i => transition_out(each_blocks[i], 1, 1, () => {
38792 each_blocks[i] = null;
38796 c: function create() {
38797 tr = element("tr");
38798 td = element("td");
38799 h2 = element("h2");
38800 h2.textContent = "Linked Places";
38803 for (let i = 0; i < each_blocks.length; i += 1) {
38804 each_blocks[i].c();
38807 each_1_anchor = empty();
38808 attr_dev(h2, "class", "svelte-j6zgmy");
38809 add_location(h2, file$c, 193, 54, 6113);
38810 attr_dev(td, "colspan", "6");
38811 attr_dev(td, "class", "svelte-j6zgmy");
38812 add_location(td, file$c, 193, 38, 6097);
38813 attr_dev(tr, "class", "all-columns svelte-j6zgmy");
38814 add_location(tr, file$c, 193, 14, 6073);
38816 m: function mount(target, anchor) {
38817 insert_dev(target, tr, anchor);
38818 append_dev(tr, td);
38819 append_dev(td, h2);
38820 insert_dev(target, t1, anchor);
38822 for (let i = 0; i < each_blocks.length; i += 1) {
38823 each_blocks[i].m(target, anchor);
38826 insert_dev(target, each_1_anchor, anchor);
38829 p: function update(ctx, dirty) {
38830 if (dirty & /*aPlace*/ 1) {
38831 each_value_4 = /*aPlace*/ ctx[0].linked_places;
38832 validate_each_argument(each_value_4);
38835 for (i = 0; i < each_value_4.length; i += 1) {
38836 const child_ctx = get_each_context_4(ctx, each_value_4, i);
38838 if (each_blocks[i]) {
38839 each_blocks[i].p(child_ctx, dirty);
38840 transition_in(each_blocks[i], 1);
38842 each_blocks[i] = create_each_block_4(child_ctx);
38843 each_blocks[i].c();
38844 transition_in(each_blocks[i], 1);
38845 each_blocks[i].m(each_1_anchor.parentNode, each_1_anchor);
38851 for (i = each_value_4.length; i < each_blocks.length; i += 1) {
38858 i: function intro(local) {
38859 if (current) return;
38861 for (let i = 0; i < each_value_4.length; i += 1) {
38862 transition_in(each_blocks[i]);
38867 o: function outro(local) {
38868 each_blocks = each_blocks.filter(Boolean);
38870 for (let i = 0; i < each_blocks.length; i += 1) {
38871 transition_out(each_blocks[i]);
38876 d: function destroy(detaching) {
38877 if (detaching) detach_dev(tr);
38878 if (detaching) detach_dev(t1);
38879 destroy_each(each_blocks, detaching);
38880 if (detaching) detach_dev(each_1_anchor);
38884 dispatch_dev("SvelteRegisterBlock", {
38886 id: create_if_block_6.name,
38888 source: "(193:12) {#if aPlace.linked_places}",
38895 // (195:14) {#each aPlace.linked_places as addressLine}
38896 function create_each_block_4(ctx) {
38900 detailsonerow = new DetailsOneRow({
38902 addressLine: /*addressLine*/ ctx[14],
38903 bDistanceInMeters: "true"
38909 c: function create() {
38910 create_component(detailsonerow.$$.fragment);
38912 m: function mount(target, anchor) {
38913 mount_component(detailsonerow, target, anchor);
38916 p: function update(ctx, dirty) {
38917 const detailsonerow_changes = {};
38918 if (dirty & /*aPlace*/ 1) detailsonerow_changes.addressLine = /*addressLine*/ ctx[14];
38919 detailsonerow.$set(detailsonerow_changes);
38921 i: function intro(local) {
38922 if (current) return;
38923 transition_in(detailsonerow.$$.fragment, local);
38926 o: function outro(local) {
38927 transition_out(detailsonerow.$$.fragment, local);
38930 d: function destroy(detaching) {
38931 destroy_component(detailsonerow, detaching);
38935 dispatch_dev("SvelteRegisterBlock", {
38937 id: create_each_block_4.name,
38939 source: "(195:14) {#each aPlace.linked_places as addressLine}",
38946 // (221:12) {:else}
38947 function create_else_block_1$1(ctx) {
38954 c: function create() {
38955 tr = element("tr");
38956 td = element("td");
38958 t = text("display keywords");
38959 attr_dev(a, "class", "btn btn-outline-secondary btn-sm");
38960 attr_dev(a, "href", "" + (/*base_url*/ ctx[1] + "&keywords=1"));
38961 add_location(a, file$c, 223, 19, 7284);
38962 attr_dev(td, "class", "svelte-j6zgmy");
38963 add_location(td, file$c, 222, 16, 7260);
38964 attr_dev(tr, "class", "svelte-j6zgmy");
38965 add_location(tr, file$c, 221, 14, 7239);
38967 m: function mount(target, anchor) {
38968 insert_dev(target, tr, anchor);
38969 append_dev(tr, td);
38974 d: function destroy(detaching) {
38975 if (detaching) detach_dev(tr);
38979 dispatch_dev("SvelteRegisterBlock", {
38981 id: create_else_block_1$1.name,
38983 source: "(221:12) {:else}",
38990 // (201:12) {#if aPlace.keywords}
38991 function create_if_block_3$1(ctx) {
39002 let each_value_3 = /*aPlace*/ ctx[0].keywords.name;
39003 validate_each_argument(each_value_3);
39004 let each_blocks_1 = [];
39006 for (let i = 0; i < each_value_3.length; i += 1) {
39007 each_blocks_1[i] = create_each_block_3(get_each_context_3(ctx, each_value_3, i));
39010 let each_value_2 = /*aPlace*/ ctx[0].keywords.address;
39011 validate_each_argument(each_value_2);
39012 let each_blocks = [];
39014 for (let i = 0; i < each_value_2.length; i += 1) {
39015 each_blocks[i] = create_each_block_2(get_each_context_2(ctx, each_value_2, i));
39019 c: function create() {
39020 tr0 = element("tr");
39021 td0 = element("td");
39022 h30 = element("h3");
39023 h30.textContent = "Name Keywords";
39026 for (let i = 0; i < each_blocks_1.length; i += 1) {
39027 each_blocks_1[i].c();
39031 tr1 = element("tr");
39032 td1 = element("td");
39033 h31 = element("h3");
39034 h31.textContent = "Address Keywords";
39037 for (let i = 0; i < each_blocks.length; i += 1) {
39038 each_blocks[i].c();
39041 each1_anchor = empty();
39042 attr_dev(h30, "class", "svelte-j6zgmy");
39043 add_location(h30, file$c, 201, 54, 6496);
39044 attr_dev(td0, "colspan", "6");
39045 attr_dev(td0, "class", "svelte-j6zgmy");
39046 add_location(td0, file$c, 201, 38, 6480);
39047 attr_dev(tr0, "class", "all-columns svelte-j6zgmy");
39048 add_location(tr0, file$c, 201, 14, 6456);
39049 attr_dev(h31, "class", "svelte-j6zgmy");
39050 add_location(h31, file$c, 211, 54, 6876);
39051 attr_dev(td1, "colspan", "6");
39052 attr_dev(td1, "class", "svelte-j6zgmy");
39053 add_location(td1, file$c, 211, 38, 6860);
39054 attr_dev(tr1, "class", "all-columns svelte-j6zgmy");
39055 add_location(tr1, file$c, 211, 14, 6836);
39057 m: function mount(target, anchor) {
39058 insert_dev(target, tr0, anchor);
39059 append_dev(tr0, td0);
39060 append_dev(td0, h30);
39061 insert_dev(target, t1, anchor);
39063 for (let i = 0; i < each_blocks_1.length; i += 1) {
39064 each_blocks_1[i].m(target, anchor);
39067 insert_dev(target, t2, anchor);
39068 insert_dev(target, tr1, anchor);
39069 append_dev(tr1, td1);
39070 append_dev(td1, h31);
39071 insert_dev(target, t4, anchor);
39073 for (let i = 0; i < each_blocks.length; i += 1) {
39074 each_blocks[i].m(target, anchor);
39077 insert_dev(target, each1_anchor, anchor);
39079 p: function update(ctx, dirty) {
39080 if (dirty & /*aPlace, formatKeywordToken*/ 1) {
39081 each_value_3 = /*aPlace*/ ctx[0].keywords.name;
39082 validate_each_argument(each_value_3);
39085 for (i = 0; i < each_value_3.length; i += 1) {
39086 const child_ctx = get_each_context_3(ctx, each_value_3, i);
39088 if (each_blocks_1[i]) {
39089 each_blocks_1[i].p(child_ctx, dirty);
39091 each_blocks_1[i] = create_each_block_3(child_ctx);
39092 each_blocks_1[i].c();
39093 each_blocks_1[i].m(t2.parentNode, t2);
39097 for (; i < each_blocks_1.length; i += 1) {
39098 each_blocks_1[i].d(1);
39101 each_blocks_1.length = each_value_3.length;
39104 if (dirty & /*aPlace, formatKeywordToken*/ 1) {
39105 each_value_2 = /*aPlace*/ ctx[0].keywords.address;
39106 validate_each_argument(each_value_2);
39109 for (i = 0; i < each_value_2.length; i += 1) {
39110 const child_ctx = get_each_context_2(ctx, each_value_2, i);
39112 if (each_blocks[i]) {
39113 each_blocks[i].p(child_ctx, dirty);
39115 each_blocks[i] = create_each_block_2(child_ctx);
39116 each_blocks[i].c();
39117 each_blocks[i].m(each1_anchor.parentNode, each1_anchor);
39121 for (; i < each_blocks.length; i += 1) {
39122 each_blocks[i].d(1);
39125 each_blocks.length = each_value_2.length;
39128 d: function destroy(detaching) {
39129 if (detaching) detach_dev(tr0);
39130 if (detaching) detach_dev(t1);
39131 destroy_each(each_blocks_1, detaching);
39132 if (detaching) detach_dev(t2);
39133 if (detaching) detach_dev(tr1);
39134 if (detaching) detach_dev(t4);
39135 destroy_each(each_blocks, detaching);
39136 if (detaching) detach_dev(each1_anchor);
39140 dispatch_dev("SvelteRegisterBlock", {
39142 id: create_if_block_3$1.name,
39144 source: "(201:12) {#if aPlace.keywords}",
39151 // (206:18) {#if keyword.id}
39152 function create_if_block_5(ctx) {
39155 let t1_value = /*keyword*/ ctx[9].id + "";
39159 c: function create() {
39160 td = element("td");
39161 t0 = text("word id: ");
39162 t1 = text(t1_value);
39163 attr_dev(td, "class", "svelte-j6zgmy");
39164 add_location(td, file$c, 206, 20, 6722);
39166 m: function mount(target, anchor) {
39167 insert_dev(target, td, anchor);
39168 append_dev(td, t0);
39169 append_dev(td, t1);
39171 p: function update(ctx, dirty) {
39172 if (dirty & /*aPlace*/ 1 && t1_value !== (t1_value = /*keyword*/ ctx[9].id + "")) set_data_dev(t1, t1_value);
39174 d: function destroy(detaching) {
39175 if (detaching) detach_dev(td);
39179 dispatch_dev("SvelteRegisterBlock", {
39181 id: create_if_block_5.name,
39183 source: "(206:18) {#if keyword.id}",
39190 // (203:14) {#each aPlace.keywords.name as keyword}
39191 function create_each_block_3(ctx) {
39194 let t0_value = formatKeywordToken_1(/*keyword*/ ctx[9].token) + "";
39197 let if_block = /*keyword*/ ctx[9].id && create_if_block_5(ctx);
39200 c: function create() {
39201 tr = element("tr");
39202 td = element("td");
39203 t0 = text(t0_value);
39205 if (if_block) if_block.c();
39206 attr_dev(td, "class", "svelte-j6zgmy");
39207 add_location(td, file$c, 204, 18, 6622);
39208 attr_dev(tr, "class", "svelte-j6zgmy");
39209 add_location(tr, file$c, 203, 16, 6599);
39211 m: function mount(target, anchor) {
39212 insert_dev(target, tr, anchor);
39213 append_dev(tr, td);
39214 append_dev(td, t0);
39215 append_dev(tr, t1);
39216 if (if_block) if_block.m(tr, null);
39218 p: function update(ctx, dirty) {
39219 if (dirty & /*aPlace*/ 1 && t0_value !== (t0_value = formatKeywordToken_1(/*keyword*/ ctx[9].token) + "")) set_data_dev(t0, t0_value);
39221 if (/*keyword*/ ctx[9].id) {
39223 if_block.p(ctx, dirty);
39225 if_block = create_if_block_5(ctx);
39227 if_block.m(tr, null);
39229 } else if (if_block) {
39234 d: function destroy(detaching) {
39235 if (detaching) detach_dev(tr);
39236 if (if_block) if_block.d();
39240 dispatch_dev("SvelteRegisterBlock", {
39242 id: create_each_block_3.name,
39244 source: "(203:14) {#each aPlace.keywords.name as keyword}",
39251 // (216:18) {#if keyword.id}
39252 function create_if_block_4(ctx) {
39255 let t1_value = /*keyword*/ ctx[9].id + "";
39259 c: function create() {
39260 td = element("td");
39261 t0 = text("word id: ");
39262 t1 = text(t1_value);
39263 attr_dev(td, "class", "svelte-j6zgmy");
39264 add_location(td, file$c, 216, 20, 7108);
39266 m: function mount(target, anchor) {
39267 insert_dev(target, td, anchor);
39268 append_dev(td, t0);
39269 append_dev(td, t1);
39271 p: function update(ctx, dirty) {
39272 if (dirty & /*aPlace*/ 1 && t1_value !== (t1_value = /*keyword*/ ctx[9].id + "")) set_data_dev(t1, t1_value);
39274 d: function destroy(detaching) {
39275 if (detaching) detach_dev(td);
39279 dispatch_dev("SvelteRegisterBlock", {
39281 id: create_if_block_4.name,
39283 source: "(216:18) {#if keyword.id}",
39290 // (213:14) {#each aPlace.keywords.address as keyword}
39291 function create_each_block_2(ctx) {
39294 let t0_value = formatKeywordToken_1(/*keyword*/ ctx[9].token) + "";
39298 let if_block = /*keyword*/ ctx[9].id && create_if_block_4(ctx);
39301 c: function create() {
39302 tr = element("tr");
39303 td = element("td");
39304 t0 = text(t0_value);
39306 if (if_block) if_block.c();
39308 attr_dev(td, "class", "svelte-j6zgmy");
39309 add_location(td, file$c, 214, 18, 7008);
39310 attr_dev(tr, "class", "svelte-j6zgmy");
39311 add_location(tr, file$c, 213, 16, 6985);
39313 m: function mount(target, anchor) {
39314 insert_dev(target, tr, anchor);
39315 append_dev(tr, td);
39316 append_dev(td, t0);
39317 append_dev(tr, t1);
39318 if (if_block) if_block.m(tr, null);
39319 append_dev(tr, t2);
39321 p: function update(ctx, dirty) {
39322 if (dirty & /*aPlace*/ 1 && t0_value !== (t0_value = formatKeywordToken_1(/*keyword*/ ctx[9].token) + "")) set_data_dev(t0, t0_value);
39324 if (/*keyword*/ ctx[9].id) {
39326 if_block.p(ctx, dirty);
39328 if_block = create_if_block_4(ctx);
39330 if_block.m(tr, t2);
39332 } else if (if_block) {
39337 d: function destroy(detaching) {
39338 if (detaching) detach_dev(tr);
39339 if (if_block) if_block.d();
39343 dispatch_dev("SvelteRegisterBlock", {
39345 id: create_each_block_2.name,
39347 source: "(213:14) {#each aPlace.keywords.address as keyword}",
39354 // (243:12) {:else}
39355 function create_else_block$3(ctx) {
39362 c: function create() {
39363 tr = element("tr");
39364 td = element("td");
39366 t = text("display child places");
39367 attr_dev(a, "class", "btn btn-outline-secondary btn-sm");
39368 attr_dev(a, "href", "" + (/*base_url*/ ctx[1] + "&hierarchy=1"));
39369 add_location(a, file$c, 245, 19, 8125);
39370 attr_dev(td, "class", "svelte-j6zgmy");
39371 add_location(td, file$c, 244, 16, 8101);
39372 attr_dev(tr, "class", "svelte-j6zgmy");
39373 add_location(tr, file$c, 243, 14, 8080);
39375 m: function mount(target, anchor) {
39376 insert_dev(target, tr, anchor);
39377 append_dev(tr, td);
39384 d: function destroy(detaching) {
39385 if (detaching) detach_dev(tr);
39389 dispatch_dev("SvelteRegisterBlock", {
39391 id: create_else_block$3.name,
39393 source: "(243:12) {:else}",
39400 // (231:12) {#if aPlace.hierarchy}
39401 function create_if_block_1$2(ctx) {
39403 let show_if = Object.keys(/*aPlace*/ ctx[0].hierarchy) > 500;
39404 let if_block_anchor;
39406 let each_value = Object.keys(/*aPlace*/ ctx[0].hierarchy);
39407 validate_each_argument(each_value);
39408 let each_blocks = [];
39410 for (let i = 0; i < each_value.length; i += 1) {
39411 each_blocks[i] = create_each_block$2(get_each_context$2(ctx, each_value, i));
39414 const out = i => transition_out(each_blocks[i], 1, 1, () => {
39415 each_blocks[i] = null;
39418 let if_block = show_if && create_if_block_2$1(ctx);
39421 c: function create() {
39422 for (let i = 0; i < each_blocks.length; i += 1) {
39423 each_blocks[i].c();
39427 if (if_block) if_block.c();
39428 if_block_anchor = empty();
39430 m: function mount(target, anchor) {
39431 for (let i = 0; i < each_blocks.length; i += 1) {
39432 each_blocks[i].m(target, anchor);
39435 insert_dev(target, t, anchor);
39436 if (if_block) if_block.m(target, anchor);
39437 insert_dev(target, if_block_anchor, anchor);
39440 p: function update(ctx, dirty) {
39441 if (dirty & /*aPlace, Object*/ 1) {
39442 each_value = Object.keys(/*aPlace*/ ctx[0].hierarchy);
39443 validate_each_argument(each_value);
39446 for (i = 0; i < each_value.length; i += 1) {
39447 const child_ctx = get_each_context$2(ctx, each_value, i);
39449 if (each_blocks[i]) {
39450 each_blocks[i].p(child_ctx, dirty);
39451 transition_in(each_blocks[i], 1);
39453 each_blocks[i] = create_each_block$2(child_ctx);
39454 each_blocks[i].c();
39455 transition_in(each_blocks[i], 1);
39456 each_blocks[i].m(t.parentNode, t);
39462 for (i = each_value.length; i < each_blocks.length; i += 1) {
39469 if (dirty & /*aPlace*/ 1) show_if = Object.keys(/*aPlace*/ ctx[0].hierarchy) > 500;
39472 if (if_block) ; else {
39473 if_block = create_if_block_2$1(ctx);
39475 if_block.m(if_block_anchor.parentNode, if_block_anchor);
39477 } else if (if_block) {
39482 i: function intro(local) {
39483 if (current) return;
39485 for (let i = 0; i < each_value.length; i += 1) {
39486 transition_in(each_blocks[i]);
39491 o: function outro(local) {
39492 each_blocks = each_blocks.filter(Boolean);
39494 for (let i = 0; i < each_blocks.length; i += 1) {
39495 transition_out(each_blocks[i]);
39500 d: function destroy(detaching) {
39501 destroy_each(each_blocks, detaching);
39502 if (detaching) detach_dev(t);
39503 if (if_block) if_block.d(detaching);
39504 if (detaching) detach_dev(if_block_anchor);
39508 dispatch_dev("SvelteRegisterBlock", {
39510 id: create_if_block_1$2.name,
39512 source: "(231:12) {#if aPlace.hierarchy}",
39519 // (235:16) {#each aPlace.hierarchy[type] as line}
39520 function create_each_block_1(ctx) {
39524 detailsonerow = new DetailsOneRow({
39526 addressLine: /*line*/ ctx[6],
39527 bDistanceInMeters: "true"
39533 c: function create() {
39534 create_component(detailsonerow.$$.fragment);
39536 m: function mount(target, anchor) {
39537 mount_component(detailsonerow, target, anchor);
39540 p: function update(ctx, dirty) {
39541 const detailsonerow_changes = {};
39542 if (dirty & /*aPlace*/ 1) detailsonerow_changes.addressLine = /*line*/ ctx[6];
39543 detailsonerow.$set(detailsonerow_changes);
39545 i: function intro(local) {
39546 if (current) return;
39547 transition_in(detailsonerow.$$.fragment, local);
39550 o: function outro(local) {
39551 transition_out(detailsonerow.$$.fragment, local);
39554 d: function destroy(detaching) {
39555 destroy_component(detailsonerow, detaching);
39559 dispatch_dev("SvelteRegisterBlock", {
39561 id: create_each_block_1.name,
39563 source: "(235:16) {#each aPlace.hierarchy[type] as line}",
39570 // (233:14) {#each Object.keys(aPlace.hierarchy) as type}
39571 function create_each_block$2(ctx) {
39575 let t0_value = /*type*/ ctx[3] + "";
39580 let each_value_1 = /*aPlace*/ ctx[0].hierarchy[/*type*/ ctx[3]];
39581 validate_each_argument(each_value_1);
39582 let each_blocks = [];
39584 for (let i = 0; i < each_value_1.length; i += 1) {
39585 each_blocks[i] = create_each_block_1(get_each_context_1(ctx, each_value_1, i));
39588 const out = i => transition_out(each_blocks[i], 1, 1, () => {
39589 each_blocks[i] = null;
39593 c: function create() {
39594 tr = element("tr");
39595 td = element("td");
39596 h3 = element("h3");
39597 t0 = text(t0_value);
39600 for (let i = 0; i < each_blocks.length; i += 1) {
39601 each_blocks[i].c();
39604 each_1_anchor = empty();
39605 attr_dev(h3, "class", "svelte-j6zgmy");
39606 add_location(h3, file$c, 233, 56, 7692);
39607 attr_dev(td, "colspan", "6");
39608 attr_dev(td, "class", "svelte-j6zgmy");
39609 add_location(td, file$c, 233, 40, 7676);
39610 attr_dev(tr, "class", "all-columns svelte-j6zgmy");
39611 add_location(tr, file$c, 233, 16, 7652);
39613 m: function mount(target, anchor) {
39614 insert_dev(target, tr, anchor);
39615 append_dev(tr, td);
39616 append_dev(td, h3);
39617 append_dev(h3, t0);
39618 insert_dev(target, t1, anchor);
39620 for (let i = 0; i < each_blocks.length; i += 1) {
39621 each_blocks[i].m(target, anchor);
39624 insert_dev(target, each_1_anchor, anchor);
39627 p: function update(ctx, dirty) {
39628 if ((!current || dirty & /*aPlace*/ 1) && t0_value !== (t0_value = /*type*/ ctx[3] + "")) set_data_dev(t0, t0_value);
39630 if (dirty & /*aPlace, Object*/ 1) {
39631 each_value_1 = /*aPlace*/ ctx[0].hierarchy[/*type*/ ctx[3]];
39632 validate_each_argument(each_value_1);
39635 for (i = 0; i < each_value_1.length; i += 1) {
39636 const child_ctx = get_each_context_1(ctx, each_value_1, i);
39638 if (each_blocks[i]) {
39639 each_blocks[i].p(child_ctx, dirty);
39640 transition_in(each_blocks[i], 1);
39642 each_blocks[i] = create_each_block_1(child_ctx);
39643 each_blocks[i].c();
39644 transition_in(each_blocks[i], 1);
39645 each_blocks[i].m(each_1_anchor.parentNode, each_1_anchor);
39651 for (i = each_value_1.length; i < each_blocks.length; i += 1) {
39658 i: function intro(local) {
39659 if (current) return;
39661 for (let i = 0; i < each_value_1.length; i += 1) {
39662 transition_in(each_blocks[i]);
39667 o: function outro(local) {
39668 each_blocks = each_blocks.filter(Boolean);
39670 for (let i = 0; i < each_blocks.length; i += 1) {
39671 transition_out(each_blocks[i]);
39676 d: function destroy(detaching) {
39677 if (detaching) detach_dev(tr);
39678 if (detaching) detach_dev(t1);
39679 destroy_each(each_blocks, detaching);
39680 if (detaching) detach_dev(each_1_anchor);
39684 dispatch_dev("SvelteRegisterBlock", {
39686 id: create_each_block$2.name,
39688 source: "(233:14) {#each Object.keys(aPlace.hierarchy) as type}",
39695 // (240:14) {#if Object.keys(aPlace.hierarchy) > 500}
39696 function create_if_block_2$1(ctx) {
39700 c: function create() {
39702 p.textContent = "There are more child objects which are not shown.";
39703 add_location(p, file$c, 240, 16, 7969);
39705 m: function mount(target, anchor) {
39706 insert_dev(target, p, anchor);
39708 d: function destroy(detaching) {
39709 if (detaching) detach_dev(p);
39713 dispatch_dev("SvelteRegisterBlock", {
39715 id: create_if_block_2$1.name,
39717 source: "(240:14) {#if Object.keys(aPlace.hierarchy) > 500}",
39724 function create_fragment$c(ctx) {
39725 let current_block_type_index;
39727 let if_block_anchor;
39729 const if_block_creators = [create_if_block$5, create_if_block_12, create_else_block_2];
39730 const if_blocks = [];
39732 function select_block_type(ctx, dirty) {
39733 if (/*aPlace*/ ctx[0]) return 0;
39734 if (location.search === "") return 1;
39738 current_block_type_index = select_block_type(ctx);
39739 if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
39742 c: function create() {
39744 if_block_anchor = empty();
39746 l: function claim(nodes) {
39747 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
39749 m: function mount(target, anchor) {
39750 if_blocks[current_block_type_index].m(target, anchor);
39751 insert_dev(target, if_block_anchor, anchor);
39754 p: function update(ctx, [dirty]) {
39755 let previous_block_index = current_block_type_index;
39756 current_block_type_index = select_block_type(ctx);
39758 if (current_block_type_index === previous_block_index) {
39759 if_blocks[current_block_type_index].p(ctx, dirty);
39763 transition_out(if_blocks[previous_block_index], 1, 1, () => {
39764 if_blocks[previous_block_index] = null;
39768 if_block = if_blocks[current_block_type_index];
39771 if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
39774 if_block.p(ctx, dirty);
39777 transition_in(if_block, 1);
39778 if_block.m(if_block_anchor.parentNode, if_block_anchor);
39781 i: function intro(local) {
39782 if (current) return;
39783 transition_in(if_block);
39786 o: function outro(local) {
39787 transition_out(if_block);
39790 d: function destroy(detaching) {
39791 if_blocks[current_block_type_index].d(detaching);
39792 if (detaching) detach_dev(if_block_anchor);
39796 dispatch_dev("SvelteRegisterBlock", {
39798 id: create_fragment$c.name,
39807 function instance$c($$self, $$props, $$invalidate) {
39808 let { $$slots: slots = {}, $$scope } = $$props;
39809 validate_slots("DetailsPage", slots, []);
39811 let base_url = window.location.search;
39813 function loaddata() {
39814 var search_params = new URLSearchParams(window.location.search);
39816 var api_request_params = {
39817 place_id: search_params.get("place_id"),
39818 osmtype: search_params.get("osmtype"),
39819 osmid: search_params.get("osmid"),
39820 class: search_params.get("class"),
39821 keywords: search_params.get("keywords"),
39823 hierarchy: search_params.get("hierarchy") === "1" ? 1 : 0,
39824 group_hierarchy: 1,
39825 polygon_geojson: 1,
39829 if (api_request_params.place_id || api_request_params.osmtype && api_request_params.osmid) {
39830 if (api_request_params.place_id) {
39831 update_html_title("Details for " + api_request_params.place_id);
39833 update_html_title("Details for " + api_request_params.osmtype + api_request_params.osmid);
39836 fetch_from_api("details", api_request_params, function (data) {
39837 $$invalidate(0, aPlace = data);
39838 current_result_store.set(data);
39841 $$invalidate(0, aPlace = undefined);
39846 const writable_props = [];
39848 Object_1.keys($$props).forEach(key => {
39849 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<DetailsPage> was created with unknown prop '${key}'`);
39852 $$self.$capture_state = () => ({
39856 current_result_store,
39857 osmLink: osmLink_1,
39858 detailsURL: detailsURL_1,
39859 wikipediaLink: wikipediaLink_1,
39860 coverageType: coverageType_1,
39861 isAdminBoundary: isAdminBoundary_1,
39862 formatAddressRank: formatAddressRank_1,
39863 formatKeywordToken: formatKeywordToken_1,
39873 $$self.$inject_state = $$props => {
39874 if ("aPlace" in $$props) $$invalidate(0, aPlace = $$props.aPlace);
39875 if ("base_url" in $$props) $$invalidate(1, base_url = $$props.base_url);
39878 if ($$props && "$$inject" in $$props) {
39879 $$self.$inject_state($$props.$$inject);
39882 return [aPlace, base_url];
39885 class DetailsPage extends SvelteComponentDev {
39886 constructor(options) {
39888 init(this, options, instance$c, create_fragment$c, safe_not_equal, {});
39890 dispatch_dev("SvelteRegisterComponent", {
39892 tagName: "DetailsPage",
39894 id: create_fragment$c.name
39899 /* src/pages/PolygonsPage.svelte generated by Svelte v3.31.2 */
39900 const file$d = "src/pages/PolygonsPage.svelte";
39902 function get_each_context$3(ctx, list, i) {
39903 const child_ctx = ctx.slice();
39904 child_ctx[2] = list[i];
39908 // (40:10) {#each aPolygons as polygon}
39909 function create_each_block$3(ctx) {
39912 let t0_value = /*polygon*/ ctx[2].osm_type + "";
39916 let raw_value = osmLink_1(/*polygon*/ ctx[2]) + "";
39919 let t3_value = /*polygon*/ ctx[2].class + "";
39923 let t5_value = /*polygon*/ ctx[2].type + "";
39927 let t7_value = /*polygon*/ ctx[2].name + "";
39931 let t9_value = (/*polygon*/ ctx[2].country_code || "") + "";
39935 let t11_value = /*polygon*/ ctx[2].errormessage + "";
39939 let t13_value = /*polygon*/ ctx[2].updated + "";
39949 c: function create() {
39950 tr = element("tr");
39951 td0 = element("td");
39952 t0 = text(t0_value);
39954 td1 = element("td");
39956 td2 = element("td");
39957 t3 = text(t3_value);
39959 td3 = element("td");
39960 t5 = text(t5_value);
39962 td4 = element("td");
39963 t7 = text(t7_value);
39965 td5 = element("td");
39966 t9 = text(t9_value);
39968 td6 = element("td");
39969 t11 = text(t11_value);
39971 td7 = element("td");
39972 t13 = text(t13_value);
39974 td8 = element("td");
39976 t15 = text("josm");
39978 add_location(td0, file$d, 41, 14, 1005);
39979 add_location(td1, file$d, 42, 14, 1047);
39980 add_location(td2, file$d, 43, 14, 1095);
39981 add_location(td3, file$d, 44, 14, 1134);
39982 add_location(td4, file$d, 45, 14, 1172);
39983 add_location(td5, file$d, 46, 14, 1210);
39984 add_location(td6, file$d, 47, 14, 1262);
39985 add_location(td7, file$d, 48, 14, 1308);
39986 attr_dev(a, "href", a_href_value = "http://localhost:8111/import?url=https://www.openstreetmap.org/api/0.6/" + formatOSMType_1(/*polygon*/ ctx[2].osm_type) + "/" + /*polygon*/ ctx[2].osm_id + "/full");
39987 attr_dev(a, "target", "josm");
39988 add_location(a, file$d, 50, 16, 1370);
39989 add_location(td8, file$d, 49, 14, 1349);
39990 add_location(tr, file$d, 40, 12, 986);
39992 m: function mount(target, anchor) {
39993 insert_dev(target, tr, anchor);
39994 append_dev(tr, td0);
39995 append_dev(td0, t0);
39996 append_dev(tr, t1);
39997 append_dev(tr, td1);
39998 td1.innerHTML = raw_value;
39999 append_dev(tr, t2);
40000 append_dev(tr, td2);
40001 append_dev(td2, t3);
40002 append_dev(tr, t4);
40003 append_dev(tr, td3);
40004 append_dev(td3, t5);
40005 append_dev(tr, t6);
40006 append_dev(tr, td4);
40007 append_dev(td4, t7);
40008 append_dev(tr, t8);
40009 append_dev(tr, td5);
40010 append_dev(td5, t9);
40011 append_dev(tr, t10);
40012 append_dev(tr, td6);
40013 append_dev(td6, t11);
40014 append_dev(tr, t12);
40015 append_dev(tr, td7);
40016 append_dev(td7, t13);
40017 append_dev(tr, t14);
40018 append_dev(tr, td8);
40019 append_dev(td8, a);
40020 append_dev(a, t15);
40021 append_dev(tr, t16);
40023 p: function update(ctx, dirty) {
40024 if (dirty & /*aPolygons*/ 1 && t0_value !== (t0_value = /*polygon*/ ctx[2].osm_type + "")) set_data_dev(t0, t0_value);
40025 if (dirty & /*aPolygons*/ 1 && raw_value !== (raw_value = osmLink_1(/*polygon*/ ctx[2]) + "")) td1.innerHTML = raw_value; if (dirty & /*aPolygons*/ 1 && t3_value !== (t3_value = /*polygon*/ ctx[2].class + "")) set_data_dev(t3, t3_value);
40026 if (dirty & /*aPolygons*/ 1 && t5_value !== (t5_value = /*polygon*/ ctx[2].type + "")) set_data_dev(t5, t5_value);
40027 if (dirty & /*aPolygons*/ 1 && t7_value !== (t7_value = /*polygon*/ ctx[2].name + "")) set_data_dev(t7, t7_value);
40028 if (dirty & /*aPolygons*/ 1 && t9_value !== (t9_value = (/*polygon*/ ctx[2].country_code || "") + "")) set_data_dev(t9, t9_value);
40029 if (dirty & /*aPolygons*/ 1 && t11_value !== (t11_value = /*polygon*/ ctx[2].errormessage + "")) set_data_dev(t11, t11_value);
40030 if (dirty & /*aPolygons*/ 1 && t13_value !== (t13_value = /*polygon*/ ctx[2].updated + "")) set_data_dev(t13, t13_value);
40032 if (dirty & /*aPolygons*/ 1 && a_href_value !== (a_href_value = "http://localhost:8111/import?url=https://www.openstreetmap.org/api/0.6/" + formatOSMType_1(/*polygon*/ ctx[2].osm_type) + "/" + /*polygon*/ ctx[2].osm_id + "/full")) {
40033 attr_dev(a, "href", a_href_value);
40036 d: function destroy(detaching) {
40037 if (detaching) detach_dev(tr);
40041 dispatch_dev("SvelteRegisterBlock", {
40043 id: create_each_block$3.name,
40045 source: "(40:10) {#each aPolygons as polygon}",
40052 function create_fragment$d(ctx) {
40060 let t3_value = /*aPolygons*/ ctx[0].length + "";
40085 let each_value = /*aPolygons*/ ctx[0];
40086 validate_each_argument(each_value);
40087 let each_blocks = [];
40089 for (let i = 0; i < each_value.length; i += 1) {
40090 each_blocks[i] = create_each_block$3(get_each_context$3(ctx, each_value, i));
40094 c: function create() {
40095 div2 = element("div");
40096 div1 = element("div");
40097 div0 = element("div");
40098 h1 = element("h1");
40099 h1.textContent = "Broken polygons";
40102 t2 = text("Total number of broken polygons: ");
40103 t3 = text(t3_value);
40106 table = element("table");
40107 thead = element("thead");
40108 th0 = element("th");
40109 th0.textContent = "OSM type";
40111 th1 = element("th");
40112 th1.textContent = "OSM id";
40114 th2 = element("th");
40115 th2.textContent = "Class";
40117 th3 = element("th");
40118 th3.textContent = "Type";
40120 th4 = element("th");
40121 th4.textContent = "Name";
40123 th5 = element("th");
40124 th5.textContent = "Country Code";
40126 th6 = element("th");
40127 th6.textContent = "Error message";
40129 th7 = element("th");
40130 th7.textContent = "Updated";
40132 th8 = element("th");
40134 tbody = element("tbody");
40136 for (let i = 0; i < each_blocks.length; i += 1) {
40137 each_blocks[i].c();
40140 add_location(h1, file$d, 20, 6, 484);
40141 add_location(p, file$d, 22, 6, 516);
40142 add_location(th0, file$d, 28, 10, 673);
40143 add_location(th1, file$d, 29, 10, 701);
40144 add_location(th2, file$d, 30, 10, 727);
40145 add_location(th3, file$d, 31, 10, 752);
40146 add_location(th4, file$d, 32, 10, 776);
40147 add_location(th5, file$d, 33, 10, 800);
40148 add_location(th6, file$d, 34, 10, 832);
40149 add_location(th7, file$d, 35, 10, 865);
40150 add_location(th8, file$d, 36, 10, 892);
40151 add_location(thead, file$d, 27, 8, 655);
40152 add_location(tbody, file$d, 38, 8, 927);
40153 attr_dev(table, "class", "table table-striped table-hover");
40154 add_location(table, file$d, 26, 6, 599);
40155 attr_dev(div0, "class", "col-sm-12");
40156 add_location(div0, file$d, 19, 4, 454);
40157 attr_dev(div1, "class", "row");
40158 add_location(div1, file$d, 18, 2, 432);
40159 attr_dev(div2, "class", "container");
40160 add_location(div2, file$d, 17, 0, 406);
40162 l: function claim(nodes) {
40163 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
40165 m: function mount(target, anchor) {
40166 insert_dev(target, div2, anchor);
40167 append_dev(div2, div1);
40168 append_dev(div1, div0);
40169 append_dev(div0, h1);
40170 append_dev(div0, t1);
40171 append_dev(div0, p);
40175 append_dev(div0, t5);
40176 append_dev(div0, table);
40177 append_dev(table, thead);
40178 append_dev(thead, th0);
40179 append_dev(thead, t7);
40180 append_dev(thead, th1);
40181 append_dev(thead, t9);
40182 append_dev(thead, th2);
40183 append_dev(thead, t11);
40184 append_dev(thead, th3);
40185 append_dev(thead, t13);
40186 append_dev(thead, th4);
40187 append_dev(thead, t15);
40188 append_dev(thead, th5);
40189 append_dev(thead, t17);
40190 append_dev(thead, th6);
40191 append_dev(thead, t19);
40192 append_dev(thead, th7);
40193 append_dev(thead, t21);
40194 append_dev(thead, th8);
40195 append_dev(table, t22);
40196 append_dev(table, tbody);
40198 for (let i = 0; i < each_blocks.length; i += 1) {
40199 each_blocks[i].m(tbody, null);
40202 p: function update(ctx, [dirty]) {
40203 if (dirty & /*aPolygons*/ 1 && t3_value !== (t3_value = /*aPolygons*/ ctx[0].length + "")) set_data_dev(t3, t3_value);
40205 if (dirty & /*formatOSMType, aPolygons, osmLink*/ 1) {
40206 each_value = /*aPolygons*/ ctx[0];
40207 validate_each_argument(each_value);
40210 for (i = 0; i < each_value.length; i += 1) {
40211 const child_ctx = get_each_context$3(ctx, each_value, i);
40213 if (each_blocks[i]) {
40214 each_blocks[i].p(child_ctx, dirty);
40216 each_blocks[i] = create_each_block$3(child_ctx);
40217 each_blocks[i].c();
40218 each_blocks[i].m(tbody, null);
40222 for (; i < each_blocks.length; i += 1) {
40223 each_blocks[i].d(1);
40226 each_blocks.length = each_value.length;
40231 d: function destroy(detaching) {
40232 if (detaching) detach_dev(div2);
40233 destroy_each(each_blocks, detaching);
40237 dispatch_dev("SvelteRegisterBlock", {
40239 id: create_fragment$d.name,
40248 function instance$d($$self, $$props, $$invalidate) {
40249 let { $$slots: slots = {}, $$scope } = $$props;
40250 validate_slots("PolygonsPage", slots, []);
40251 let aPolygons = [];
40253 function loaddata() {
40254 fetch_from_api("polygons", { format: "json" }, function (data) {
40255 $$invalidate(0, aPolygons = data);
40258 update_html_title("Broken polygons");
40262 const writable_props = [];
40264 Object.keys($$props).forEach(key => {
40265 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<PolygonsPage> was created with unknown prop '${key}'`);
40268 $$self.$capture_state = () => ({
40272 formatOSMType: formatOSMType_1,
40273 osmLink: osmLink_1,
40278 $$self.$inject_state = $$props => {
40279 if ("aPolygons" in $$props) $$invalidate(0, aPolygons = $$props.aPolygons);
40282 if ($$props && "$$inject" in $$props) {
40283 $$self.$inject_state($$props.$$inject);
40286 return [aPolygons];
40289 class PolygonsPage extends SvelteComponentDev {
40290 constructor(options) {
40292 init(this, options, instance$d, create_fragment$d, safe_not_equal, {});
40294 dispatch_dev("SvelteRegisterComponent", {
40296 tagName: "PolygonsPage",
40298 id: create_fragment$d.name
40303 /* src/pages/DeletablePage.svelte generated by Svelte v3.31.2 */
40304 const file$e = "src/pages/DeletablePage.svelte";
40306 function get_each_context$4(ctx, list, i) {
40307 const child_ctx = ctx.slice();
40308 child_ctx[2] = list[i];
40312 // (37:10) {#each aPolygons as polygon}
40313 function create_each_block$4(ctx) {
40317 let t0_value = /*polygon*/ ctx[2].place_id + "";
40322 let t2_value = /*polygon*/ ctx[2].country_code + "";
40326 let t4_value = /*polygon*/ ctx[2].name + "";
40330 let raw_value = osmLink_1(/*polygon*/ ctx[2]) + "";
40333 let t7_value = /*polygon*/ ctx[2].osm_type + "";
40337 let t9_value = /*polygon*/ ctx[2].class + "";
40341 let t11_value = /*polygon*/ ctx[2].type + "";
40346 c: function create() {
40347 tr = element("tr");
40348 td0 = element("td");
40350 t0 = text(t0_value);
40352 td1 = element("td");
40353 t2 = text(t2_value);
40355 td2 = element("td");
40356 t4 = text(t4_value);
40358 td3 = element("td");
40360 td4 = element("td");
40361 t7 = text(t7_value);
40363 td5 = element("td");
40364 t9 = text(t9_value);
40366 td6 = element("td");
40367 t11 = text(t11_value);
40369 attr_dev(a, "href", a_href_value = detailsURL_1(/*polygon*/ ctx[2]));
40370 add_location(a, file$e, 38, 16, 988);
40371 add_location(td0, file$e, 38, 12, 984);
40372 add_location(td1, file$e, 39, 12, 1060);
40373 add_location(td2, file$e, 40, 12, 1104);
40374 add_location(td3, file$e, 41, 12, 1140);
40375 add_location(td4, file$e, 42, 12, 1186);
40376 add_location(td5, file$e, 43, 12, 1226);
40377 add_location(td6, file$e, 44, 12, 1263);
40378 add_location(tr, file$e, 37, 10, 967);
40380 m: function mount(target, anchor) {
40381 insert_dev(target, tr, anchor);
40382 append_dev(tr, td0);
40383 append_dev(td0, a);
40385 append_dev(tr, t1);
40386 append_dev(tr, td1);
40387 append_dev(td1, t2);
40388 append_dev(tr, t3);
40389 append_dev(tr, td2);
40390 append_dev(td2, t4);
40391 append_dev(tr, t5);
40392 append_dev(tr, td3);
40393 td3.innerHTML = raw_value;
40394 append_dev(tr, t6);
40395 append_dev(tr, td4);
40396 append_dev(td4, t7);
40397 append_dev(tr, t8);
40398 append_dev(tr, td5);
40399 append_dev(td5, t9);
40400 append_dev(tr, t10);
40401 append_dev(tr, td6);
40402 append_dev(td6, t11);
40403 append_dev(tr, t12);
40405 p: function update(ctx, dirty) {
40406 if (dirty & /*aPolygons*/ 1 && t0_value !== (t0_value = /*polygon*/ ctx[2].place_id + "")) set_data_dev(t0, t0_value);
40408 if (dirty & /*aPolygons*/ 1 && a_href_value !== (a_href_value = detailsURL_1(/*polygon*/ ctx[2]))) {
40409 attr_dev(a, "href", a_href_value);
40412 if (dirty & /*aPolygons*/ 1 && t2_value !== (t2_value = /*polygon*/ ctx[2].country_code + "")) set_data_dev(t2, t2_value);
40413 if (dirty & /*aPolygons*/ 1 && t4_value !== (t4_value = /*polygon*/ ctx[2].name + "")) set_data_dev(t4, t4_value);
40414 if (dirty & /*aPolygons*/ 1 && raw_value !== (raw_value = osmLink_1(/*polygon*/ ctx[2]) + "")) td3.innerHTML = raw_value; if (dirty & /*aPolygons*/ 1 && t7_value !== (t7_value = /*polygon*/ ctx[2].osm_type + "")) set_data_dev(t7, t7_value);
40415 if (dirty & /*aPolygons*/ 1 && t9_value !== (t9_value = /*polygon*/ ctx[2].class + "")) set_data_dev(t9, t9_value);
40416 if (dirty & /*aPolygons*/ 1 && t11_value !== (t11_value = /*polygon*/ ctx[2].type + "")) set_data_dev(t11, t11_value);
40418 d: function destroy(detaching) {
40419 if (detaching) detach_dev(tr);
40423 dispatch_dev("SvelteRegisterBlock", {
40425 id: create_each_block$4.name,
40427 source: "(37:10) {#each aPolygons as polygon}",
40434 function create_fragment$e(ctx) {
40441 let t2_value = /*aPolygons*/ ctx[0].length + "";
40462 let each_value = /*aPolygons*/ ctx[0];
40463 validate_each_argument(each_value);
40464 let each_blocks = [];
40466 for (let i = 0; i < each_value.length; i += 1) {
40467 each_blocks[i] = create_each_block$4(get_each_context$4(ctx, each_value, i));
40471 c: function create() {
40472 div2 = element("div");
40473 div1 = element("div");
40474 div0 = element("div");
40475 h1 = element("h1");
40476 h1.textContent = "Deletable";
40479 t2 = text(t2_value);
40480 t3 = text(" objects have been deleted in OSM but are still in the Nominatim database.");
40482 table = element("table");
40483 thead = element("thead");
40484 th0 = element("th");
40485 th0.textContent = "Place id";
40487 th1 = element("th");
40488 th1.textContent = "Country Code";
40490 th2 = element("th");
40491 th2.textContent = "Name";
40493 th3 = element("th");
40494 th3.textContent = "OSM id";
40496 th4 = element("th");
40497 th4.textContent = "OSM type";
40499 th5 = element("th");
40500 th5.textContent = "Class";
40502 th6 = element("th");
40503 th6.textContent = "Type";
40505 tbody = element("tbody");
40507 for (let i = 0; i < each_blocks.length; i += 1) {
40508 each_blocks[i].c();
40511 add_location(h1, file$e, 19, 6, 483);
40512 add_location(p, file$e, 21, 6, 509);
40513 add_location(th0, file$e, 27, 10, 708);
40514 add_location(th1, file$e, 28, 10, 736);
40515 add_location(th2, file$e, 29, 10, 768);
40516 add_location(th3, file$e, 30, 10, 792);
40517 add_location(th4, file$e, 31, 10, 818);
40518 add_location(th5, file$e, 32, 10, 846);
40519 add_location(th6, file$e, 33, 10, 871);
40520 add_location(thead, file$e, 26, 8, 690);
40521 add_location(tbody, file$e, 35, 8, 910);
40522 attr_dev(table, "class", "table table-striped table-hover");
40523 add_location(table, file$e, 25, 6, 634);
40524 attr_dev(div0, "class", "col-sm-12");
40525 add_location(div0, file$e, 18, 4, 453);
40526 attr_dev(div1, "class", "row");
40527 add_location(div1, file$e, 17, 2, 431);
40528 attr_dev(div2, "class", "container");
40529 add_location(div2, file$e, 16, 0, 405);
40531 l: function claim(nodes) {
40532 throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
40534 m: function mount(target, anchor) {
40535 insert_dev(target, div2, anchor);
40536 append_dev(div2, div1);
40537 append_dev(div1, div0);
40538 append_dev(div0, h1);
40539 append_dev(div0, t1);
40540 append_dev(div0, p);
40543 append_dev(div0, t4);
40544 append_dev(div0, table);
40545 append_dev(table, thead);
40546 append_dev(thead, th0);
40547 append_dev(thead, t6);
40548 append_dev(thead, th1);
40549 append_dev(thead, t8);
40550 append_dev(thead, th2);
40551 append_dev(thead, t10);
40552 append_dev(thead, th3);
40553 append_dev(thead, t12);
40554 append_dev(thead, th4);
40555 append_dev(thead, t14);
40556 append_dev(thead, th5);
40557 append_dev(thead, t16);
40558 append_dev(thead, th6);
40559 append_dev(table, t18);
40560 append_dev(table, tbody);
40562 for (let i = 0; i < each_blocks.length; i += 1) {
40563 each_blocks[i].m(tbody, null);
40566 p: function update(ctx, [dirty]) {
40567 if (dirty & /*aPolygons*/ 1 && t2_value !== (t2_value = /*aPolygons*/ ctx[0].length + "")) set_data_dev(t2, t2_value);
40569 if (dirty & /*aPolygons, osmLink, detailsURL*/ 1) {
40570 each_value = /*aPolygons*/ ctx[0];
40571 validate_each_argument(each_value);
40574 for (i = 0; i < each_value.length; i += 1) {
40575 const child_ctx = get_each_context$4(ctx, each_value, i);
40577 if (each_blocks[i]) {
40578 each_blocks[i].p(child_ctx, dirty);
40580 each_blocks[i] = create_each_block$4(child_ctx);
40581 each_blocks[i].c();
40582 each_blocks[i].m(tbody, null);
40586 for (; i < each_blocks.length; i += 1) {
40587 each_blocks[i].d(1);
40590 each_blocks.length = each_value.length;
40595 d: function destroy(detaching) {
40596 if (detaching) detach_dev(div2);
40597 destroy_each(each_blocks, detaching);
40601 dispatch_dev("SvelteRegisterBlock", {
40603 id: create_fragment$e.name,
40612 function instance$e($$self, $$props, $$invalidate) {
40613 let { $$slots: slots = {}, $$scope } = $$props;
40614 validate_slots("DeletablePage", slots, []);
40615 let aPolygons = [];
40617 function loaddata() {
40618 fetch_from_api("deletable", { format: "json" }, function (data) {
40619 $$invalidate(0, aPolygons = data);
40622 update_html_title("Deletable objects");
40626 const writable_props = [];
40628 Object.keys($$props).forEach(key => {
40629 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<DeletablePage> was created with unknown prop '${key}'`);
40632 $$self.$capture_state = () => ({
40636 detailsURL: detailsURL_1,
40637 osmLink: osmLink_1,
40642 $$self.$inject_state = $$props => {
40643 if ("aPolygons" in $$props) $$invalidate(0, aPolygons = $$props.aPolygons);
40646 if ($$props && "$$inject" in $$props) {
40647 $$self.$inject_state($$props.$$inject);
40650 return [aPolygons];
40653 class DeletablePage extends SvelteComponentDev {
40654 constructor(options) {
40656 init(this, options, instance$e, create_fragment$e, safe_not_equal, {});
40658 dispatch_dev("SvelteRegisterComponent", {
40660 tagName: "DeletablePage",
40662 id: create_fragment$e.name
40667 let myhistory = [];
40670 target: document.body
40676 // inspects window.location
40677 function identify_current_page() {
40678 var pagename = window.location.pathname.replace('.html', '').replace(/^.*\//, '');
40680 if (pagename === '') { return 'search' }
40682 if (['search', 'reverse', 'details', 'deletable', 'polygons'].indexOf(pagename) != '-1') {
40689 function parse_url_and_load_page() {
40690 let pagename = identify_current_page();
40692 document.getElementById('main').replaceChildren();
40694 if (pagename === 'search' || pagename === 'reverse') {
40696 target: document.getElementById('main'),
40698 reverse_search: (pagename === 'reverse')
40701 } else if (pagename === 'details') {
40703 target: document.getElementById('main')
40705 } else if (pagename === 'deletable') {
40706 new DeletablePage({
40707 target: document.getElementById('main')
40709 } else if (pagename === 'polygons') {
40711 target: document.getElementById('main')
40718 function is_relative_url(url) {
40719 if (!url) return false;
40720 if (url.indexOf('?') === 0) return true;
40721 if (url.indexOf('/') === 0) return true;
40722 if (url.indexOf('#') === 0) return false;
40723 if (url.match(/^http/)) return false;
40724 if (!url.match(/\.html/)) return true;
40730 parse_url_and_load_page();
40732 // load page after form submit
40733 document.addEventListener('submit', function (e) {
40735 // loop parent nodes from the target to the delegation node
40736 for (var target = e.target; target && target != this; target = target.parentNode) {
40737 if (target.matches('form')) {
40738 e.preventDefault();
40740 var target_url = serialize_form(target);
40741 target_url = clean_up_url_parameters(target_url);
40743 window.history.pushState(myhistory, '', '?' + target_url);
40745 parse_url_and_load_page();
40752 // load page after click on relative URL
40753 document.addEventListener('click', function (e) {
40755 // loop parent nodes from the target to the delegation node
40756 for (var target = e.target; target && target != this; target = target.parentNode) {
40757 if (target.matches('a')) {
40759 var target_url = target.href;
40761 if (!is_relative_url(target_url)) return;
40763 e.preventDefault();
40764 e.stopPropagation();
40766 window.history.pushState(myhistory, '', target_url);
40768 parse_url_and_load_page();
40774 // deal with back-button and other user action
40775 window.onpopstate = function () {
40776 parse_url_and_load_page();
40780 //# sourceMappingURL=bundle.js.map