vendor: 4,491 bytes, lines 1-2
1/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */ 2!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*ne
vendor: 3,069 bytes, line 2
2w Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}
vendor: 9,959 bytes, line 2
2function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)}
vendor: 79,644 bytes, lines 2-5
2,input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; 3}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&U.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var Y=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)Y(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?"<table>"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ma.test(f)?this.mouseHooks:la.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d="on"+b;a.detachEvent&&("undefined"==typeof a[d]&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?pa:qa):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?n.prop(b,"form"):void 0;c&&!n._data(c,"submit")&&(n.event.add(c,"submit._submit",function(a){a._submitBubble=!0}),n._data(c,"submit",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?("checkbox"!==this.type&&"radio"!==this.type||(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,"click._change",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate("change",this,a)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,"change")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a)}),n._data(b,"change",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!ka.test(this.nodeName)}}),l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=qa),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ta=/ jQuery\d+="(?:null|\d+)"/g,ua=new RegExp("<(?:"+ba+")[\\s/>]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/<script|<style|<link/i,xa=/checked\s*(?:[^=]|=\s*.checked.)/i,ya=/^true\/(.*)/,za=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Pa=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement("div"),j=d.createElement("div");if(j.style){j.style.cssText="float:left;opacity:.5",l.opacity="0.5"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip="content-box",j.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===j.style.backgroundClip,i=d.createElement("div"),i.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",j.innerHTML="",i.appendChild(j),l.boxSizing=""===j.style.boxSizing||""===j.style.MozBoxSizing||""===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b="1%"!==(l||{}).top,h="2px"===(l||{}).marginLeft,e="4px"===(l||{width:"4px"}).width,j.style.marginRight="50%",c="4px"===(l||{marginRight:"4px"}).marginRight,k=j.appendChild(d.createElement("div")),k.style.cssText=j.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",k.style.marginRight=k.style.width="0",j.style.width="1px",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display="none",f=0===j.getClientRects().length,f&&(j.style.display="",j.innerHTML="<table><tr><td></td><td>t</td></tr></table>",j.childNodes[0].style.borderCollapse="separate",k=j.getElementsByTagName("td"),k[0].style.cssText="margin:0;border:0;padding:0;display:none",f=0===k[0].offsetHeight,f&&(k[0].style.display="",k[1].style.display="none",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Oa.test(g)&&Na.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0===g?g:g+""}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\([^)]*\)/i,Wa=/opacity\s*=\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp("^("+T+")(.*)$","i"),Za={position:"absolute",visibility:"hidden",display:"block"},$a={letterSpacing:"0",fontWeight:"400"},_a=["Webkit","O","Moz","ms"],ab=d.createElement("div").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&W(d)&&(f[g]=n._data(d,"olddisplay",Ma(d.nodeName)))):(e=W(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function eb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+V[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+V[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+V[f]+"Width",!0,e))):(g+=n.css(a,"padding"+V[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+V[f]+"Width",!0,e)));return g}function fb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ra(a),g=l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Sa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Oa.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+eb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=U.exec(c))&&e[1]&&(c=X(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),"normal"===f&&b in $a&&(f=$a[b]),""===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,"display"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Va,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+" "+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:"inline-block"},Sa,[a,"marginRight"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Sa(a,"marginLeft"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{ 4marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},gb.propHooks.scrollTop=gb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:hb||lb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,nb,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(qb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(W).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=qb(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(mb(b,!0),a,d,e)}}),n.each({slideDown:mb("show"),slideUp:mb("hide"),slideToggle:mb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a,b=d.createElement("input"),c=d.createElement("div"),e=d.createElement("select"),f=e.appendChild(d.createElement("option"));c=d.createElement("div"),c.setAttribute("className","t"),c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],b.setAttribute("type","checkbox"),c.appendChild(b),a=c.getElementsByTagName("a")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==c.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement("form").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value}();var rb=/\r/g,sb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(sb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>-1)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var tb,ub,vb=n.expr.attrHandle,wb=/^(?:checked|selected)$/i,xb=l.getSetAttribute,yb=l.input;n.fn.extend({attr:function(a,b){return Y(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ub:tb)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?yb&&xb||!wb.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(xb?c:d)}}),ub={set:function(a,b,c){return b===!1?n.removeAttr(a,c):yb&&xb||!wb.test(c)?a.setAttribute(!xb&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=vb[b]||n.find.attr;yb&&xb||!wb.test(b)?vb[b]=function(a,b,d){var e,f;return d||(f=vb[b],vb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,vb[b]=f),e}:vb[b]=function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),yb&&xb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):tb&&tb.set(a,b,c)}}),xb||(tb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},vb.id=vb.name=vb.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:tb.set},n.attrHooks.contenteditable={set:function(a,b,c){tb.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var zb=/^(?:input|select|textarea|button|object)$/i,Ab=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):zb.test(a.nodeName)||Ab.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var Bb=/[\t\r\n\f]/g;function Cb(a){return n.attr(a,"class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,Cb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,Cb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,Cb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=Cb(this),b&&n._data(this,"__className__",b),n.attr(this,"class",b||a===!1?"":n._data(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+Cb(c)+" ").replace(Bb," ").indexOf(b)>-1)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Db=a.location,Eb=n.now(),Fb=/\?/,Gb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(Gb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,"text/xml")):(c=new a.ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var Hb=/#.*$/,Ib=/([?&])_=[^&]*/,Jb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Kb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Lb=/^(?:GET|HEAD)$/,Mb=/^\/\//,Nb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ob={},Pb={},Qb="*/".concat("*"),Rb=Db.href,Sb=Nb.exec(Rb.toLowerCase())||[];function Tb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Ub(a,b,c,d){var e={},f=a===Pb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Vb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Wb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Xb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Rb,type:"GET",isLocal:Kb.test(Sb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Qb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Vb(Vb(a,n.ajaxSettings),b):Vb(n.ajaxSettings,a)},ajaxPrefilter:Tb(Ob),ajaxTransport:Tb(Pb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks("once memory"),r=l.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Jb.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Rb)+"").replace(Hb,"").replace(Mb,Sb[1]+"//"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||"*").toLowerCase().match(G)||[""],null==l.crossDomain&&(d=Nb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Sb[1]&&d[2]===Sb[2]&&(d[3]||("http:"===d[1]?"80":"443"))===(Sb[3]||("http:"===Sb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Ub(Ob,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!Lb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Fb.test(f)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=Ib.test(f)?f.replace(Ib,"$1_="+Eb++):f+(Fb.test(f)?"&":"?")+"_="+Eb++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&w.setRequestHeader("If-None-Match",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",l.contentType),w.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+Qb+"; q=0.01":""):l.accepts["*"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v="abort";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Ub(Pb,l,c,w)){if(w.readyState=1,i&&o.trigger("ajaxSend",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort("timeout")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,"No Transport");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||"",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Wb(l,w,d)),v=Xb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(n.lastModified[f]=x),x=w.getResponseHeader("etag"),x&&(n.etag[f]=x)),204===b||"HEAD"===l.type?y="nocontent":304===b?y="notmodified":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+"",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?"ajaxSuccess":"ajaxError",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger("ajaxComplete",[w,l]),--n.active||n.event.trigger("ajaxStop")))}return w},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}});function Yb(a){return a.style&&a.style.display||n.css(a,"display")}function Zb(a){if(!n.contains(a.ownerDocument||d,a))return!0;while(a&&1===a.nodeType){if("none"===Yb(a)||"hidden"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Zb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var $b=/%20/g,_b=/\[\]$/,ac=/\r?\n/g,bc=/^(?:submit|button|image|reset|file)$/i,cc=/^(?:input|select|textarea|keygen)/i;function dc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||_b.test(a)?d(a,e):dc(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)dc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)dc(c,a[c],b,e);return d.join("&").replace($b,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&cc.test(this.nodeName)&&!bc.test(a)&&(this.checked||!Z.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(ac,"\r\n")}}):{name:b.name,value:c.replace(ac,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?ic():d.documentMode>8?hc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&hc()||ic()}:hc;var ec=0,fc={},gc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in fc)fc[a](void 0,!0)}),l.cors=!!gc&&"withCredentials"in gc,gc=l.ajax=!!gc,gc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++ec;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+"");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete fc[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,"string"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=""}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=fc[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function hc(){try{return new a.XMLHttpRequest}catch(b){}}function ic(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=d.head||n("head")[0]||d.documentElement;return{send:function(e,f){b=d.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var jc=[],kc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=jc.pop()||n.expando+"_"+Eb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(kc.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&kc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(kc,"$1"+e):b.jsonp!==!1&&(b.url+=(Fb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,jc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var lc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&lc)return lc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h,a.length)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function mc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?("undefined"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=mc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=mc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){return c?(c=Sa(a,b),Oa.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({ 5padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return Y(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n});
vendor: 1,034 bytes, lines 6-28
6 7;(function(root, factory) { 8 if (typeof define === 'function' && define.amd) { 9 define(['jquery'], factory); 10 } else if (typeof exports === 'object') { 11 module.exports = factory(require('jquery')); 12 } else { 13 root.jquery_mmenu_js = factory(root.jQuery); 14 } 15}(this, function(jQuery) { 16/* 17 * jQuery mmenu v6.1.8 18 * @requires jQuery 1.7.0 or later 19 * 20 * mmenu.frebsite.nl 21 * 22 * Copyright (c) Fred Heusschen 23 * www.frebsite.nl 24 * 25 * License: CC-BY-NC-4.0 26 * http://creativecommons.org/licenses/by-nc/4.0/ 27 */ 28!function(t){function e(){t[n].glbl||(o={$wndw:t(window),$docu:t(document),$html:t("html"),$body:t("body")},s={},a={},r={},t.each([s,a,r],function(t,e){e.add=function(t){t=t.split(" ");for(var n=0,i=t.length;n<i;n++)e[t[n]]=e.mm(t[n])}}),s.mm=function(t){return"mm-"+t},s.add("wrapper menu panels panel nopanel highest opened subopened navbar hasnavbar title btn prev next listview nolistview inset vertical selected divider spacer hidden fullsubopen noanimation"),s.umm=function(t){return"mm-"==t.slice(0,3)&&(t=t.
28slice(3)),t},a.mm=function(t){return"mm-"+t},a.add("parent child"),r.mm=function(t){return t+".mm"},r.add("transitionend webkitTransitionEnd click scroll resize keydown mousedown mouseup touchstart touchmove touchend orientationchange"),t[n]._c=s,t[n]._d=a,t[n]._e=r,t[n].glbl=o)}var n="mmenu",i="6.1.8";if(!(t[n]&&t[n].version>i)){t[n]=function(t,e,n){return this.$menu=t,this._api=["bind","getInstance","initPanels","openPanel","closePanel","closeAllPanels","setSelected"],this.opts=e,this.conf=n,this.vars={},this.cbck={},this.mtch={},"function"==typeof this.___deprecated&&this.___deprecated(),this._initAddons(),this._initExtensions(),this._initMenu(),this._initPanels(),this._initOpened(),this._initAnchors(),this._initMatchMedia(),"function"==typeof this.___debug&&this.___debug(),this},t[n].version=i,t[n].addons={},t[n].uniqueId=0,t[n].defaults={extensions:[],initMenu:function(){},initPanels:function(){},navbar:{add:!0,title:"Menu",titleLink:"parent"},onClick:{setSelected:!0},slidingSubmenus:!0},t[n].configuration={classNames:{divider:"Divider",inset:"Inset",nolistview:"NoListview",nopanel:"NoPanel",panel:"Panel",selected:"Selected",spacer:"Spacer",vertical:"Vertical"},clone:!1,openingInterval:25,panelNodetype:"ul, ol, div",transitionDuration:400},t[n].prototype={getInstance:function(){return this},initPanels:function(t){this._initPanels(t)},openPanel:function(e,i){if(this.trigger("openPanel:before",e),e&&e.length&&(e.is("."+s.panel)||(e=e.closest("."+s.panel)),e.is("."+s.panel))){var r=this;if("boolean"!=typeof i&&(i=!0),e.hasClass(s.vertical))e.add(e.parents("."+s.vertical)).removeClass(s.hidden).parent("li").addClass(s.opened),this.openPanel(e.parents("."+s.panel).not("."+s.vertical).first()),this.trigger("openPanel:start",e),this.trigger("openPanel:finish",e);else{if(e.hasClass(s.opened))return;var o=this.$pnls.children("."+s.panel),l=o.filter("."+s.opened);if(!t[n].support.csstransitions)return l.addClass(s.hidden).removeClass(s.opened),e.removeClass(s.hidden).addClass(s.opened),this.trigger("openPanel:start",e),void this.trigger("openPanel:finish",e);o.not(e).removeClass(s.subopened);for(var d=e.data(a.parent);d;)d=d.closest("."+s.panel),d.is("."+s.vertical)||d.addClass(s.subopened),d=d.data(a.parent);o.removeClass(s.highest).not(l).not(e).addClass(s.hidden),e.removeClass(s.hidden),this.openPanelStart=function(){l.removeClass(s.opened),e.addClass(s.opened),e.hasClass(s.subopened)?(l.addClass(s.highest),e.removeClass(s.subopened)):(l.addClass(s.subopened),e.addClass(s.highest)),this.trigger("openPanel:start",e)},this.openPanelFinish=function(){l.removeClass(s.highest).addClass(s.hidden),e.removeClass(s.highest),this.trigger("openPanel:finish",e)},i&&!e.hasClass(s.noanimation)?setTimeout(function(){r.__transitionend(e,function(){r.openPanelFinish.call(r)},r.conf.transitionDuration),r.openPanelStart.call(r)},r.conf.openingInterval):(this.openPanelStart.call(this),this.openPanelFinish.call(this))}this.trigger("openPanel:after",e)}},closePanel:function(t){this.trigger("closePanel:before",t);var e=t.parent();e.hasClass(s.vertical)&&(e.removeClass(s.opened),this.trigger("closePanel",t)),this.trigger("closePanel:after",t)},closeAllPanels:function(t){this.trigger("closeAllPanels:before"),this.$pnls.find("."+s.listview).children().removeClass(s.selected).filter("."+s.vertical).removeClass(s.opened);var e=this.$pnls.children("."+s.panel),n=t&&t.length?t:e.first();this.$pnls.children("."+s.panel).not(n).removeClass(s.subopened).removeClass(s.opened).removeClass(s.highest).addClass(s.hidden),this.openPanel(n,!1),this.trigger("closeAllPanels:after")},togglePanel:function(t){var e=t.parent();e.hasClass(s.vertical)&&this[e.hasClass(s.opened)?"closePanel":"openPanel"](t)},setSelected:function(t){this.trigger("setSelected:before",t),this.$menu.find("."+s.listview).children("."+s.selected).removeClass(s.selected),t.addClass(s.selected),this.trigger("setSelected:after",t)},bind:function(t,e){this.cbck[t]=this.cbck[t]||[],this.cbck[t].push(e)},trigger:function(){var t=this,e=Array.prototype.slice.call(arguments),n=e.shift();if(this.cbck[n])for(var i=0,s=this.cbck[n].length;i<s;i++)this.cbck[n][i].apply(t,e)},matchMedia:function(t,e,n){var i={yes:e,no:n};this.mtch[t]=this.mtch[t]||[],this.mtch[t].push(i)},_initAddons:function(){this.trigger("initAddons:before");var e;
28for(e in t[n].addons)t[n].addons[e].add.call(this),t[n].addons[e].add=function(){};for(e in t[n].addons)t[n].addons[e].setup.call(this);this.trigger("initAddons:after")},_initExtensions:function(){this.trigger("initExtensions:before");var t=this;this.opts.extensions.constructor===Array&&(this.opts.extensions={all:this.opts.extensions});for(var e in this.opts.extensions)this.opts.extensions[e]=this.opts.extensions[e].length?"mm-"+this.opts.extensions[e].join(" mm-"):"",this.opts.extensions[e]&&!function(e){t.matchMedia(e,function(){this.$menu.addClass(this.opts.extensions[e])},function(){this.$menu.removeClass(this.opts.extensions[e])})}(e);this.trigger("initExtensions:after")},_initMenu:function(){this.trigger("initMenu:before");this.conf.clone&&(this.$orig=this.$menu,this.$menu=this.$orig.clone(),this.$menu.add(this.$menu.find("[id]")).filter("[id]").each(function(){t(this).attr("id",s.mm(t(this).attr("id")))})),this.opts.initMenu.call(this,this.$menu,this.$orig),this.$menu.attr("id",this.$menu.attr("id")||this.__getUniqueId()),this.$pnls=t('<div class="'+s.panels+'" />').append(this.$menu.children(this.conf.panelNodetype)).prependTo(this.$menu);var e=[s.menu];this.opts.slidingSubmenus||e.push(s.vertical),this.$menu.addClass(e.join(" ")).parent().addClass(s.wrapper),this.trigger("initMenu:after")},_initPanels:function(e){this.trigger("initPanels:before",e),e=e||this.$pnls.children(this.conf.panelNodetype);var n=t(),i=this,a=function(e){e.filter(this.conf.panelNodetype).each(function(){var e=i._initPanel(t(this));if(e){i._initNavbar(e),i._initListview(e),n=n.add(e);var r=e.children("."+s.listview).children("li").children(i.conf.panelNodeType).add(e.children("."+i.conf.classNames.panel));r.length&&a.call(i,r)}})};a.call(this,e),this.opts.initPanels.call(this,n),this.trigger("initPanels:after",n)},_initPanel:function(t){this.trigger("initPanel:before",t);if(t.hasClass(s.panel))return t;if(this.__refactorClass(t,this.conf.classNames.panel,"panel"),this.__refactorClass(t,this.conf.classNames.nopanel,"nopanel"),this.__refactorClass(t,this.conf.classNames.vertical,"vertical"),this.__refactorClass(t,this.conf.classNames.inset,"inset"),t.filter("."+s.inset).addClass(s.nopanel),t.hasClass(s.nopanel))return!1;var e=t.hasClass(s.vertical)||!this.opts.slidingSubmenus;t.removeClass(s.vertical);var n=t.attr("id")||this.__getUniqueId();t.removeAttr("id"),t.is("ul, ol")&&(t.wrap("<div />"),t=t.parent()),t.addClass(s.panel+" "+s.hidden).attr("id",n);var i=t.parent("li");return e?t.add(i).addClass(s.vertical):t.appendTo(this.$pnls),i.length&&(i.data(a.child,t),t.data(a.parent,i)),this.trigger("initPanel:after",t),t},_initNavbar:function(e){if(this.trigger("initNavbar:before",e),!e.children("."+s.navbar).length){var i=e.data(a.parent),r=t('<div class="'+s.navbar+'" />'),o=t[n].i18n(this.opts.navbar.title),l="";if(i&&i.length){if(i.hasClass(s.vertical))return;if(i.parent().is("."+s.listview))var d=i.children("a, span").not("."+s.next);else var d=i.closest("."+s.panel).find('a[href="#'+e.attr("id")+'"]');d=d.first(),i=d.closest("."+s.panel);var c=i.attr("id");switch(o=d.text(),this.opts.navbar.titleLink){case"anchor":l=d.attr("href");break;case"parent":l="#"+c}r.append('<a class="'+s.btn+" "+s.prev+'" href="#'+c+'" />')}else if(!this.opts.navbar.title)return;this.opts.navbar.add&&e.addClass(s.hasnavbar),r.append('<a class="'+s.title+'"'+(l.length?' href="'+l+'"':"")+">"+o+"</a>").prependTo(e),this.trigger("initNavbar:after",e)}},_initListview:function(e){this.trigger("initListview:before",e);var n=this.__childAddBack(e,"ul, ol");this.__refactorClass(n,this.conf.classNames.nolistview,"nolistview"),n.filter("."+this.conf.classNames.inset).addClass(s.nolistview);var i=n.not("."+s.nolistview).addClass(s.listview).children();this.__refactorClass(i,this.conf.classNames.selected,"selected"),this.__refactorClass(i,this.conf.classNames.divider,"divider"),this.__refactorClass(i,this.conf.classNames.spacer,"spacer");var r=e.data(a.parent);if(r&&r.parent().is("."+s.listview)&&!r.children("."+s.next).length){var o=r.children("a, span").first(),l=t('<a class="'+s.next+'" href="#'+e.attr("id")+'" />').insertBefore(o);o.is("span")&&l.addClass(s.fullsubopen)}this.trigger("initListview:after",e)},_initOpened:function(){this.trigger("initOpened:before");var t=this.$pnls.find("."+s.listview).children("."+s.selected).removeClass(s.selected).last(
28).addClass(s.selected),e=t.length?t.closest("."+s.panel):this.$pnls.children("."+s.panel).first();this.openPanel(e,!1),this.trigger("initOpened:after")},_initAnchors:function(){var e=this;o.$body.on(r.click+"-oncanvas","a[href]",function(i){var a=t(this),r=!1,o=e.$menu.find(a).length;for(var l in t[n].addons)if(t[n].addons[l].clickAnchor.call(e,a,o)){r=!0;break}var d=a.attr("href");if(!r&&o&&d.length>1&&"#"==d.slice(0,1))try{var c=t(d,e.$menu);c.is("."+s.panel)&&(r=!0,e[a.parent().hasClass(s.vertical)?"togglePanel":"openPanel"](c))}catch(h){}if(r&&i.preventDefault(),!r&&o&&a.is("."+s.listview+" > li > a")&&!a.is('[rel="external"]')&&!a.is('[target="_blank"]')){e.__valueOrFn(e.opts.onClick.setSelected,a)&&e.setSelected(t(i.target).parent());var f=e.__valueOrFn(e.opts.onClick.preventDefault,a,"#"==d.slice(0,1));f&&i.preventDefault(),e.__valueOrFn(e.opts.onClick.close,a,f)&&e.opts.offCanvas&&"function"==typeof e.close&&e.close()}})},_initMatchMedia:function(){var t=this;this._fireMatchMedia(),o.$wndw.on(r.resize,function(e){t._fireMatchMedia()})},_fireMatchMedia:function(){for(var t in this.mtch)for(var e=window.matchMedia&&window.matchMedia(t).matches?"yes":"no",n=0;n<this.mtch[t].length;n++)this.mtch[t][n][e].call(this)},_getOriginalMenuId:function(){var t=this.$menu.attr("id");return this.conf.clone&&t&&t.length&&(t=s.umm(t)),t},__api:function(){var e=this,n={};return t.each(this._api,function(t){var i=this;n[i]=function(){var t=e[i].apply(e,arguments);return"undefined"==typeof t?n:t}}),n},__valueOrFn:function(t,e,n){return"function"==typeof t?t.call(e[0]):"undefined"==typeof t&&"undefined"!=typeof n?n:t},__refactorClass:function(t,e,n){return t.filter("."+e).removeClass(e).addClass(s[n])},__findAddBack:function(t,e){return t.find(e).add(t.filter(e))},__childAddBack:function(t,e){return t.children(e).add(t.filter(e))},__filterListItems:function(t){return t.not("."+s.divider).not("."+s.hidden)},__filterListItemAnchors:function(t){return this.__filterListItems(t).children("a").not("."+s.next)},__transitionend:function(t,e,n){var i=!1,s=function(n){"undefined"!=typeof n&&n.target!=t[0]||(i||(t.off(r.transitionend),t.off(r.webkitTransitionEnd),e.call(t[0])),i=!0)};t.on(r.transitionend,s),t.on(r.webkitTransitionEnd,s),setTimeout(s,1.1*n)},__getUniqueId:function(){return s.mm(t[n].uniqueId++)}},t.fn[n]=function(i,s){e(),i=t.extend(!0,{},t[n].defaults,i),s=t.extend(!0,{}
28,t[n].configuration,s);var a=t();return this.each(function(){var e=t(this);if(!e.data(n)){var r=new t[n](e,i,s);r.$menu.data(n,r.__api()),a=a.add(r.$menu)}}),a},t[n].i18n=function(){var e={};return function(n){switch(typeof n){case"object":return t.extend(e,n),e;case"string":return e[n]||n;case"undefined":default:return e}}}(),t[n].support={touch:"ontouchstart"in window||navigator.msMaxTouchPoints||!1,csstransitions:function(){return"undefined"==typeof Modernizr||"undefined"==typeof Modernizr.csstransitions||Modernizr.csstransitions}(),csstransforms:function(){return"undefined"==typeof Modernizr||"undefined"==typeof Modernizr.csstransforms||Modernizr.csstransforms}(),csstransforms3d:function(){return"undefined"==typeof Modernizr||"undefined"==typeof Modernizr.csstransforms3d||Modernizr.csstransforms3d}()};var s,a,r,o}}(jQuery),/* 29 * jQuery mmenu offCanvas add-on 30 * mmenu.frebsite.nl 31 * 32 * Copyright (c) Fred Heusschen 33 */ 34function(t){var e="mmenu",n="offCanvas";t[e].addons[n]={setup:function(){if(this.opts[n]){var s=this,a=this.opts[n],o=this.conf[n];r=t[e].glbl,this._api=t.merge(this._api,["open","close","setPage"]),"object"!=typeof a&&(a={}),"top"!=a.position&&"bottom"!=a.position||(a.zposition="front"),a=this.opts[n]=t.extend(!0,{},t[e].defaults[n],a),"string"!=typeof o.pageSelector&&(o.pageSelector="> "+o.pageNodetype),this.vars.opened=!1;var l=[i.offcanvas];"left"!=a.position&&l.push(i.mm(a.position)),"back"!=a.zposition&&l.push(i.mm(a.zposition)),t[e].support.csstransforms||l.push(i["no-csstransforms"]),t[e].support.csstransforms3d||l.push(i["no-csstransforms3d"]),this.bind("initMenu:after",function(){var t=this;this.setPage(r.$page),this._initBlocker(),this["_initWindow_"+n](),this.$menu.addClass(l.join(" ")).parent("."+i.wrapper).removeClass(i.wrapper),this.$menu[o.menuInsertMethod](o.menuInsertSelector);var e=window.location.hash;if(e){var s=this._getOriginalMenuId();s&&s==e.slice(1)&&setTimeout(function(){t.open()},1e3)}}),this.bind("initExtensions:after",function(){for(var t=[i.mm("widescreen"),i.mm("iconbar")],e=0;e<t.length;e++)for(var n in this.opts.extensions)if(this.opts.extensions[n].indexOf(t[e])>-1){!function(e,n){s.matchMedia(e,function(){r.$html.addClass(t[n])},function(){r.$html.removeClass(t[n])})}(n,e);break}}),this.bind("open:start:sr-aria",function(){this.__sr_aria(this.$menu,"hidden",!1)}),this.bind("close:finish:sr-aria",function(){this.__sr_aria(this.$menu,"hidden",!0)}),this.bind("initMenu:after:sr-aria",function(){this.__sr_aria(this.$menu,"hidden",!0)})}},add:function(){i=t[e]._c,s=t[e]._d,a=t[e]._e,i.add("offcanvas slideout blocking modal background opening blocker page no-csstransforms3d"),s.add("style")},clickAnchor:function(t,e){var s=this;if(this.opts[n]){var a=this._getOriginalMenuId();if(a&&t.is('[href="#'+a+'"]')){if(e)return!0;var o=t.closest("."+i.menu);if(o.length){var l=o.data("mmenu");if(l&&l.close)return l.close(),s.__transitionend(o,function(){s.open()},s.conf.transitionDuration),!0}return this.open(),!0}if(r.$page)return a=r.$page.first().attr("id"),a&&t.is('[href="#'+a+'"]')?(this.close(),!0):void 0}}},t[e].defaults[n]={position:"left",zposition:"back",blockUI:!0,moveBackground:!0},t[e].configuration[n]={pageNodetype:"div",pageSelector:null,noPageSelector:[],wrapPageIfNeeded:!0,menuInsertMethod:"prependTo",menuInsertSelector:"body"},t[e].prototype.open=function(){if(this.trigger("open:before"),!this.vars.opened){var t=this;this._openSetup(),setTimeout(function(){t._openFinish()},this.conf.openingInterval),this.trigger("open:after")}},t[e].prototype._openSetup=function(){var e=this,o=this.opts[n];this.closeAllOthers(),r.$page.each(function(){t(this).data(s.style,t(this).attr("style")||"")}),r.$wndw.trigger(a.resize+"-"+n,[!0]);var l=[i.opened];o.blockUI&&l.push(i.blocking),"modal"==o.blockUI&&l.push(i.modal),o.moveBackground&&l.push(i.background),"left"!=o.position&&l.push(i.mm(this.opts[n].position)),"back"!=o.zposition&&l.push(i.mm(this.opts[n].zposition)),r.$html.addClass(l.join(" ")),setTimeout(function(){e.vars.opened=!0},this.conf.openingInterval),this.$menu.addClass(i.opened)},t[e].prototype._openFinish=function(){var t=this;this.__transitionend(r.$page.first(),function(){t.trigger("open:finish")},this.conf.transitionDuration),this.trigger("open:start"),r.$html.addClass(i.opening)},t[e].prototype.close=function(){if(this.trigger("close:before"),this.vars.opened){var e=this;this.__transitionend(r.$page.first(),function(){e.$menu.removeClass(i.opened);var a=[i.opened,i.blocking,i.modal,i.background,i.mm(e.opts[n].position),i.mm(e.opts[n].zposition)];r.$html.removeClass(a.join(" ")),r.$page.each(function(){t(this).attr("style",t(this).data(s.style))}),e.vars.opened=!1,e.trigger("close:finish")},this.conf.transitionDuration),this.trigger("close:start"),r.$html.removeClass(i.opening),this.trigger("close:after")}},t[e].prototype.closeAllOthers=function(){r.$body.find("."+i.menu+"."+i.offcanvas).not(this.$menu).each(function(){var n=t(this).data(e);n&&n.close&&n.close()})},t[e].prototype.setPage=function(e){this.trigger("setPage:before",e);var s=this,a=this.conf[n];e&&e.length||(e=r.$body.find(a.pageSelector),a.noPageSelector.length&&(e=e.not(a.noPageSelector.join(", "))),e.length>1&&a.wrapPageIfNeeded&&(e=e.wrapAll("<"+this.conf[n].pageNodetype+" />").parent())),e.each(function(){t(this).attr("id",t(this).attr("id")||s.__getUniqueId())}),e.addClass(i.page+" "+i.slideout),r.$page=e,this.trigger("setPage:after",e)},t[e].prototype["_initWindow_"+n]=function(){r.$wndw.off(a.keydown+"-"+n).on(a.keydown+"-"+n,function(t){if(r.$html.hasClass(i.opened)&&9==t.keyCode)return t.preventDefault(),!1});var t=0;r.$wndw.off(a.resize+"-"+n).on(a.resize+"-"+n,function(e,n){if(1==r.$page.length&&(n||r.$html.hasClass(i.opened))){var s=r.$wndw.height();(n||s!=t)&&(t=s,r.$page.css("minHeight",s))}})},t[e].prototype._initBlocker=function(){var e=this;this.opts[n].blockUI&&(r.$blck||(r.$blck=t('<div id="'+i.blocker+'" class="'+i.slideout+'" />')),r.$blck.appendTo(r.$body).off(a.touchstart+"-"+n+" "+a.touchmove+"-"+n).on(a.touchstart+"-"+n+" "+a.touchmove+"-"+n,function(t){t.preventDefault(),t.stopPropagation(),r.$blck.trigger(a.mousedown+"-"+n)}).off(a.mousedown+"-"+n).on(a.mousedown+"-"+n,function(t){t.preventDefault(),r.$html.hasClass(i.modal)||(e.closeAllOthers(),e.close())}))};var i,s,a,r}(jQuery),/* 35 * jQuery mmenu scrollBugFix add-on 36 * mmenu.frebsite.nl 37 * 38 * Copyright (c) Fred Heusschen 39 */ 40function(t){var e="mmenu",n="scrollBugFix";t[e].addons[n]={setup:function(){var s=this.opts[n];this.conf[n];r=t[e].glbl,t[e].support.touch&&this.opts.offCanvas&&this.opts.offCanvas.blockUI&&("boolean"==typeof s&&(s={fix:s}),"object"!=typeof s&&(s={}),s=this.opts[n]=t.extend(!0,{},t[e].defaults[n],s),s.fix&&(this.bind("open:start",function(){this.$pnls.children("."+i.opened).scrollTop(0)}),this.bind("initMenu:after",function(){this["_initWindow_"+n]()})))},add:function(){i=t[e]._c,s=t[e]._d,a=t[e]._e},clickAnchor:function(t,e){}},t[e].defaults[n]={fix:!0},t[e].prototype["_initWindow_"+n]=function(){var e=this;r.$docu.off(a.touchmove+"-"+n).on(a.touchmove+"-"+n,function(t){r.$html.hasClass(i.opened)&&t.preventDefault()});var s=!1;r.$body.off(a.touchstart+"-"+n).on(a.touchstart+"-"+n,"."+i.panels+"> ."+i.panel,function(t){r.$html.hasClass(i.opened)&&(s||(s=!0,0===t.currentTarget.scrollTop?t.currentTarget.scrollTop=1:t.currentTarget.scrollHeight===t.currentTarget.scrollTop+t.currentTarget.offsetHeight&&(t.currentTarget.scrollTop-=1),s=!1))}).off(a.touchmove+"-"+n).on(a.touchmove+"-"+n,"."+i.panels+"> ."+i.panel,function(e){r.$html.hasClass(i.opened)&&t(this)[0].scrollHeight>t(this).innerHeight()&&e.stopPropagation()}),r.$wndw.off(a.orientationchange+"-"+n).on(a.orientationchange+"-"+n,function(){e.$pnls.children("."+i.opened).scrollTop(0).css({"-webkit-overflow-scrolling":"auto"}).css({"-webkit-overflow-scrolling":"touch"})})};var i,s,a,r}(jQuery),/* 41 * jQuery mmenu screenReader add-on 42 * mmenu.frebsite.nl 43 * 44 * Copyright (c) Fred Heusschen 45 */ 46function(t){var e="mmenu",n="screenReader";t[e].addons[n]={setup:function(){var a=this,o=this.opts[n],l=this.conf[n];r=t[e].glbl,"boolean"==typeof o&&(o={aria:o,text:o}),"object"!=typeof o&&(o={}),o=this.opts[n]=t.extend(!0,{},t[e].defaults[n],o),o.aria&&(this.bind("initAddons:after",function(){this.bind("initMenu:after",function(){this.trigger("initMenu:after:sr-aria")}),this.bind("initNavbar:after",function(){this.trigger("initNavbar:after:sr-aria",arguments[0])}),this.bind("openPanel:start",function(){this.trigger("openPanel:start:sr-aria",arguments[0])}),this.bind("close:start",function(){this.trigger("close:start:sr-aria")}),this.bind("close:finish",function(){this.trigger("close:finish:sr-aria")}),this.bind("open:start",function(){this.trigger("open:start:sr-aria")}),this.bind("open:finish",function(){this.trigger("open:finish:sr-aria")})}),this.bind("updateListview",function(){this.$pnls.find("."+i.listview).children().each(function(){a.__sr_aria(t(this),"hidden",t(this).is("."+i.hidden))})}),this.bind("openPanel:start",function(t){var e=this.$menu.find("."+i.panel).not(t).not(t.parents("."+i.panel)),n=t.add(t.find("."+i.vertical+"."+i.opened).children("."+i.panel));this.__sr_aria(e,"hidden",!0),this.__sr_aria(n,"hidden",!1)}),this.bind("closePanel",function(t){this.__sr_aria(t,"hidden",!0)}),this.bind("initPanels:after",function(e){var n=e.find("."+i.prev+", ."+i.next).each(function(){a.__sr_aria(t(this),"owns",t(this).attr("href").replace("#",""))});this.__sr_aria(n,"haspopup",!0)}),this.bind("initNavbar:after",function(t){var e=t.children("."+i.navbar);this.__sr_aria(e,"hidden",!t.hasClass(i.hasnavbar))}),o.text&&(this.bind("initlistview:after",function(t){var e=t.find("."+i.listview).find("."+i.fullsubopen).parent().children("span");this.__sr_aria(e,"hidden",!0)}),"parent"==this.opts.navbar.titleLink&&this.bind("initNavbar:after",function(t){var e=t.children("."+i.navbar),n=!!e.children("."+i.prev).length;this.__sr_aria(e.children("."+i.title),"hidden",n)}
46))),o.text&&(this.bind("initAddons:after",function(){this.bind("setPage:after",function(){this.trigger("setPage:after:sr-text",arguments[0])})}),this.bind("initNavbar:after",function(n){var s=n.children("."+i.navbar),a=s.children("."+i.title).text(),r=t[e].i18n(l.text.closeSubmenu);a&&(r+=" ("+a+")"),s.children("."+i.prev).html(this.__sr_text(r))}),this.bind("initListview:after",function(n){var r=n.data(s.parent);if(r&&r.length){var o=r.children("."+i.next),d=o.nextAll("span, a").first().text(),c=t[e].i18n(l.text[o.parent().is("."+i.vertical)?"toggleSubmenu":"openSubmenu"]);d&&(c+=" ("+d+")"),o.html(a.__sr_text(c))}}))},add:function(){i=t[e]._c,s=t[e]._d,a=t[e]._e,i.add("sronly")},clickAnchor:function(t,e){}},t[e].defaults[n]={aria:!0,text:!0},t[e].configuration[n]={text:{closeMenu:"Close menu",closeSubmenu:"Close submenu",openSubmenu:"Open submenu",toggleSubmenu:"Toggle submenu"}},t[e].prototype.__sr_aria=function(t,e,n){t.prop("aria-"+e,n)[n?"attr":"removeAttr"]("aria-"+e,n)},t[e].prototype.__sr_text=function(t){return'<span class="'+i.sronly+'">'+t+"</span>"};var i,s,a,r}(jQuery); 47return true; 48})); 49 50/* 51 * jQuery mmenu navbar add-on 52 * mmenu.frebsite.nl 53 * 54 * Copyright (c) Fred Heusschen 55 */ 56!function(a){var n="mmenu",t="navbars";a[n].addons[t]={setup:function(){var r=this,s=this.opts[t],o=this.conf[t];if(i=a[n].glbl,"undefined"!=typeof s){s instanceof Array||(s=[s]);var d={},c={};s.length&&(a.each(s,function(i){var h=s[i];"boolean"==typeof h&&h&&(h={}),"object"!=typeof h&&(h={}),"undefined"==typeof h.content&&(h.content=["prev","title"]),h.content instanceof Array||(h.content=[h.content]),h=a.extend(!0,{},r.opts.navbar,h);var l=a('<div class="'+e.navbar+'" />'),f=h.height;"number"!=typeof f&&(f=1),f=Math.min(4,Math.max(1,f)),l.addClass(e.navbar+"-size-"+f);var v=h.position;"bottom"!=v&&(v="top"),d[v]||(d[v]=0),d[v]+=f,c[v]||(c[v]=a('<div class="'+e.navbars+"-"+v+'" />')),c[v].append(l);for(var b=0,p=0,u=h.content.length;p<u;p++){var m=a[n].addons[t][h.content[p]]||!1;m?b+=m.call(r,l,h,o):(m=h.content[p],m instanceof a||(m=a(h.content[p])),l.append(m))}b+=Math.ceil(l.children().not("."+e.btn).length/f),b>1&&l.addClass(e.navbar+"-content-"+b),l.children("."+e.btn).length&&l.addClass(e.hasbtns)}),this.bind("initMenu:after",function(){for(var a in d)this.$menu.addClass(e.hasnavbar+"-"+a+"-"+d[a]),this.$menu["bottom"==a?"append":"prepend"](c[a])}))}},add:function(){e=a[n]._c,r=a[n]._d,s=a[n]._e,e.add("navbars close hasbtns")},clickAnchor:function(a,n){}},a[n].configuration[t]={breadcrumbSeparator:"/"},a[n].configuration.classNames[t]={};var e,r,s,i}(jQuery),/* 57 * jQuery mmenu navbar add-on breadcrumbs content 58 * mmenu.frebsite.nl 59 * 60 * Copyright (c) Fred Heusschen 61 */ 62function(a){var n="mmenu",t="navbars",e="breadcrumbs";a[n].addons[t][e]=function(t,e,r){var s=this,i=a[n]._c,o=a[n]._d;i.add("breadcrumbs separator");var d=a('<span class="'+i.breadcrumbs+'" />').appendTo(t);return this.bind("initNavbar:after",function(n){n.removeClass(i.hasnavbar);for(var t=[],e=a('<span class="'+i.breadcrumbs+'"></span>'),s=n,d=!0;s&&s.length;){if(s.is("."+i.panel)||(s=s.closest("."+i.panel)),!s.hasClass(i.vertical)){var c=s.children("."+i.navbar).children("."+i.title).text();t.unshift(d?"<span>"+c+"</span>":'<a href="#'+s.attr("id")+'">'+c+"</a>"),d=!1}s=s.data(o.parent)}e.append(t.join('<span class="'+i.separator+'">'+r.breadcrumbSeparator+"</span>")).appendTo(n.children("."+i.navbar))}),this.bind("openPanel:start",function(a){d.html(a.children("."+i.navbar).children("."+i.breadcrumbs).html()||"")}),this.bind("initNavbar:after:sr-aria",function(n){n.children("."+i.navbar).children("."+i.breadcrumbs).children("a").each(function(){s.__sr_aria(a(this),"owns",a(this).attr("href").slice(1))})}),0}}(jQuery),/* 63 * jQuery mmenu navbar add-on close content 64 * mmenu.frebsite.nl 65 * 66 * Copyright (c) Fred Heusschen 67 */ 68function(a){var n="mmenu",t="navbars",e="close";a[n].addons[t][e]=function(t,e){var r=a[n]._c,s=(a[n].glbl,a('<a class="'+r.close+" "+r.btn+'" href="#" />').appendTo(t));return this.bind("setPage:after",function(a){s.attr("href","#"+a.attr("id"))}),this.bind("setPage:after:sr-text",function(t){s.html(this.__sr_text(a[n].i18n(this.conf.screenReader.text.closeMenu))),this.__sr_aria(s,"owns",s.attr("href").slice(1))}),-1}}(jQuery),/* 69 * jQuery mmenu navbar add-on next content 70 * mmenu.frebsite.nl 71 * 72 * Copyright (c) Fred Heusschen 73 */ 74function(a){var n="mmenu",t="navbars",e="next";a[n].addons[t][e]=function(e,r){var s,i,o,d=a[n]._c,c=a('<a class="'+d.next+" "+d.btn+'" href="#" />').appendTo(e);return this.bind("openPanel:start",function(a){s=a.find("."+this.conf.classNames[t].panelNext),i=s.attr("href"),o=s.html(),i?c.attr("href",i):c.removeAttr("href"),c[i||o?"removeClass":"addClass"](d.hidden),c.html(o)}),this.bind("openPanel:start:sr-aria",function(a){this.__sr_aria(c,"hidden",c.hasClass(d.hidden)),this.__sr_aria(c,"owns",(c.attr("href")||"").slice(1))}),-1},a[n].configuration.classNames[t].panelNext="Next"}(jQuery),/* 75 * jQuery mmenu navbar add-on prev content 76 * mmenu.frebsite.nl 77 * 78 * Copyright (c) Fred Heusschen 79 */ 80function(a){var n="mmenu",t="navbars",e="prev";a[n].addons[t][e]=function(e,r){var s=a[n]._c,i=a('<a class="'+s.prev+" "+s.btn+'" href="#" />').appendTo(e);this.bind("initNavbar:after",function(a){a.removeClass(s.hasnavbar)});var o,d,c;return this.bind("openPanel:start",function(a){a.hasClass(s.vertical)||(o=a.find("."+this.conf.classNames[t].panelPrev),o.length||(o=a.children("."+s.navbar).children("."+s.prev)),d=o.attr("href"),c=o.html(),d?i.attr("href",d):i.removeAttr("href"),i[d||c?"removeClass":"addClass"](s.hidden),i.html(c))}),this.bind("initNavbar:after:sr-aria",function(a){var n=a.children("."+s.navbar);this.__sr_aria(n,"hidden",!0)}),this.bind("openPanel:start:sr-aria",function(a){this.__sr_aria(i,"hidden",i.hasClass(s.hidden)),this.__sr_aria(i,"owns",(i.attr("href")||"").slice(1))}),-1},a[n].configuration.classNames[t].panelPrev="Prev"}(jQuery),/* 81 * jQuery mmenu navbar add-on searchfield content 82 * mmenu.frebsite.nl 83 * 84 * Copyright (c) Fred Heusschen 85 */ 86function(a){var n="mmenu",t="navbars",e="searchfield";a[n].addons[t][e]=function(t,e){var r=a[n]._c,s=a('<div class="'+r.search+'" />').appendTo(t);return"object"!=typeof this.opts.searchfield&&(this.opts.searchfield={}),this.opts.searchfield.add=!0,this.opts.searchfield.addTo=s,0}}(jQuery),/* 87 * jQuery mmenu navbar add-on title content 88 * mmenu.frebsite.nl 89 * 90 * Copyright (c) Fred Heusschen 91 */ 92function(a){var n="mmenu",t="navbars",e="title";a[n].addons[t][e]=function(e,r){var s,i,o,d=a[n]._c,c=a('<a class="'+d.title+'" />').appendTo(e);this.bind("openPanel:start",function(a){a.hasClass(d.vertical)||(o=a.find("."+this.conf.classNames[t].panelTitle),o.length||(o=a.children("."+d.navbar).children("."+d.title)),s=o.attr("href"),i=o.html()||r.title,s?c.attr("href",s):c.removeAttr("href"),c[s||i?"removeClass":"addClass"](d.hidden),c.html(i))});var h;
92return this.bind("openPanel:start:sr-aria",function(a){if(this.opts.screenReader.text&&(h||(h=this.$menu.children("."+d.navbars+"-top, ."+d.navbars+"-bottom").children("."+d.navbar).children("."+d.prev)),h.length)){var n=!0;"parent"==this.opts.navbar.titleLink&&(n=!h.hasClass(d.hidden)),this.__sr_aria(c,"hidden",n)}}),0},a[n].configuration.classNames[t].panelTitle="Title"}(jQuery); 93/*! SmartMenus jQuery Plugin - v1.0.1 - November 1, 2016 94 * http://www.smartmenus.org/ 95 * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).unbind(e),mouseDetectionEnabled=!1);else{var i=!0,s=null;$(document).bind(getEventsNS([["mousemove",function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}],[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut",function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)}]],e)),mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};return $.each(t,function(t,s){i[s[0].split(" ").join(e+" ")+e]=s[1]}),i}var menuTrees=[],IE=!!window.createPopup,mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)};return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend($.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).bind(getEventsNS([["mouseover focusin",$.proxy(this.rootOver,this)],["mouseout focusout",$.proxy(this.rootOut,this)],["keydown",$.proxy(this.rootKeyDown,this)]],i)).delegate("a",getEventsNS([["mouseenter",$.proxy(this.itemEnter,this)],["mouseleave",$.proxy(this.itemLeave,this)],["mousedown",$.proxy(this.itemDown,this)],["focus",$.proxy(this.itemFocus,this)],["blur",$.proxy(this.itemBlur,this)],["click",$.proxy(this.itemClick,this)]],i)),i+=this.rootId,this.opts.hideOnClick&&$(document).bind(getEventsNS([["touchstart",$.proxy(this.docTouchStart,this)],["touchmove",$.proxy(this.docTouchMove,this)],["touchend",$.proxy(this.docTouchEnd,this)],["click",$.proxy(this.docClick,this)]],i)),$(window).bind(getEventsNS([["resize orientationchange",$.proxy(this.winResize,this)]],i)),this.opts.subIndicators&&(this.$subArrow=$("<span/>").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").unbind(e).undelegate(e),e+=this.rootId,$(document).unbind(e),$(window).unbind(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("ie-shim").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('<div class="sm-jquery-disable-overlay"/>
95').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?(this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).is("a"))&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for(var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"block"==this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if((!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is("span.sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1;if(s&&!s.is(":visible")){if(this.opts.showOnClick&&o&&(this.clickActivated=!0),this.itemActivate(e),s.is(":visible"))return this.focusActivated=!0,!1}else if(this.isCollapsible()&&i)return this.itemActivate(e),this.menuHide(s),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}}
95,itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("ie-shim")&&t.dataSM("ie-shim").remove().css({"-webkit-transform":"",transform:""}),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).unbind(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(this.$root.stop(!0,!0),this.$root.is(":visible")&&(this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration),this.$root.dataSM("ie-shim")&&this.$root.dataSM("ie-shim").remove())),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuIframeShim:function(t){IE&&this.opts.overlapControlsInIE&&!t.dataSM("ie-shim")&&t.dataSM("ie-shim",$("<iframe/>").attr({src:"javascript:0",tabindex:-9}).css({position:"absolute",top:"auto",left:"0",opacity:0,border:"0"}))},menuInit:function(t){if(!t.dataSM("in-mega")){t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),S=this.getViewportWidth(),b=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]")||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenu
95SubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+S&&(e=g?f+S-r-y+e:w-r),g||(b>h&&I+h>v+b?i+=v+b-h-I:(h>=b||v>I)&&(i+=v-I)),g&&(I+h>v+b+.49||v>I)||!g&&h>b+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0],$('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]).bind({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){t.preventDefault()}}).insertAfter(t));var C=".smartmenus_scroll";t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).bind(getEventsNS([["mouseover",function(e){x.menuScrollOver(t,e)}],["mouseout",function(e){x.menuScrollOut(t,e)}],["mousewheel DOMMouseScroll",function(e){x.menuScrollMousewheel(t,e)}]],C)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()&&t.css({"touch-action":"none","-ms-touch-action":"none"}).bind(getEventsNS([[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp",function(e){x.menuScrollTouch(t,e)}]],C))}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m}),this.menuIframeShim(t),t.dataSM("ie-shim")&&t.dataSM("ie-shim").css({zIndex:t.css("z-index"),width:r,height:h,marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"),a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.add(t.dataSM("ie-shim")).css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y<o.upEnd)&&a.eq(o.up?1:0).show(),o.y==n)mouse&&a.eq(o.up?0:1).hide(),this.menuScrollStop(t);else if(!e){this.opts.scrollAccelerate&&o.step<this.opts.scrollStep&&(o.step+=.2);var h=this;this.scrollTimeout=requestAnimationFrame(function(){h.menuScroll(t)})}},menuScrollMousewheel:function(t,e){if(this.getClosestMenu(e.target)==t[0]){e=e.originalEvent;var i=(e.wheelDelta||-e.detail)>0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i,downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");
95if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2))&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0).stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a");if((this.opts.keepHighlighted||this.isCollapsible())&&e.addClass("highlighted"),this.isCollapsible())t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var i=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),i>this.getWidth(t)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t),t.dataSM("ie-shim")&&t.dataSM("ie-shim").insertBefore(t)}var s=function(){t.css("overflow","")};this.isCollapsible()?this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,s):t.show(this.opts.collapsibleShowDuration,s):this.opts.showFunction?this.opts.showFunction.call(this,t,s):t.show(this.opts.showDuration,s),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0).stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e}),this.menuIframeShim(this.$root),this.$root.dataSM("ie-shim")&&this.$root.dataSM("ie-shim").css({zIndex:this.$root.css("z-index"),width:this.getWidth(this.$root),height:this.getHeight(this.$root),left:t,top:e}).insertBefore(this.$root);var i=this,s=function(){i.$root.css("overflow","")};this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();
95this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})}var dataOpts=this.data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}return this.each(function(){new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"prepend",subIndicatorsText:"+",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1,bottomToTopSubMenus:!1,overlapControlsInIE:!0},$}); 96// SmartMenus init 97$(function() { 98 $('#main-menu').smartmenus({ 99 mainMenuSubOffsetX: -1, 100 mainMenuSubOffsetY: 4, 101 subMenusSubOffsetX: 6, 102 subMenusSubOffsetY: -6, 103 subMenusMinWidth: '14em' 104 }); 105}); 106/* @preserve 107 * Leaflet 1.3.4+Detached: 0e566b2ad5e696ba9f79a9d48a7e51c8f4892441.0e566b2, a JS library for interactive maps. http://leafletjs.com 108 * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade 109 */ 110 111(function (global, factory) { 112 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 113 typeof define === 'function' && define.amd ? define(['exports'], factory) : 114 (factory((global.L = {}))); 115}(this, (function (exports) { 'use strict'; 116 117var version = "1.3.4+HEAD.0e566b2"; 118 119/* 120 * @namespace Util 121 * 122 * Various utility functions, used by Leaflet internally. 123 */ 124 125var freeze = Object.freeze; 126Object.freeze = function (obj) { return obj; }; 127 128// @function extend(dest: Object, src?: Object): Object 129// Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut. 130function extend(dest) { 131 var i, j, len, src; 132 133 for (j = 1, len = arguments.length; j < len; j++) { 134 src = arguments[j]; 135 for (i in src) { 136 dest[i] = src[i]; 137 } 138 } 139 return dest; 140} 141 142// @function create(proto: Object, properties?: Object): Object 143// Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create) 144var create = Object.create || (function () { 145 function F() {} 146 return function (proto) { 147 F.prototype = proto; 148 return new F(); 149 }; 150})(); 151 152// @function bind(fn: Function, â¦): Function 153// 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). 154// Has a `L.bind()` shortcut. 155function bind(fn, obj) { 156 var slice = Array.prototype.slice; 157 158 if (fn.bind) { 159 return fn.bind.apply(fn, slice.call(arguments, 1)); 160 } 161 162 var args = slice.call(arguments, 2); 163 164 return function () { 165 return fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments); 166 }; 167} 168 169// @property lastId: Number 170// Last unique ID used by [`stamp()`](#util-stamp) 171var lastId = 0; 172 173// @function stamp(obj: Object): Number 174// Returns the unique ID of an object, assigning it one if it doesn't have it. 175function stamp(obj) { 176 /*eslint-disable */ 177 obj._leaflet_id = obj._leaflet_id || ++lastId; 178 return obj._leaflet_id; 179 /* eslint-enable */ 180} 181
vendor: 5,772 bytes, lines 182-338
182// @function throttle(fn: Function, time: Number, context: Object): Function 183// Returns a function which executes function `fn` with the given scope `context` 184// (so that the `this` keyword refers to `context` inside `fn`'s code). The function 185// `fn` will be called no more than one time per given amount of `time`. The arguments 186// received by the bound function will be any arguments passed when binding the 187// function, followed by any arguments passed when invoking the bound function. 188// Has an `L.throttle` shortcut. 189function throttle(fn, time, context) { 190 var lock, args, wrapperFn, later; 191 192 later = function () { 193 // reset lock and call if queued 194 lock = false; 195 if (args) { 196 wrapperFn.apply(context, args); 197 args = false; 198 } 199 }; 200 201 wrapperFn = function () { 202 if (lock) { 203 // called too soon, queue to call later 204 args = arguments; 205 206 } else { 207 // call and lock until later 208 fn.apply(context, arguments); 209 setTimeout(later, time); 210 lock = true; 211 } 212 }; 213 214 return wrapperFn; 215} 216 217// @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number 218// Returns the number `num` modulo `range` in such a way so it lies within 219// `range[0]` and `range[1]`. The returned value will be always smaller than 220// `range[1]` unless `includeMax` is set to `true`. 221function wrapNum(x, range, includeMax) { 222 var max = range[1], 223 min = range[0], 224 d = max - min; 225 return x === max && includeMax ? x : ((x - min) % d + d) % d + min; 226} 227 228// @function falseFn(): Function 229// Returns a function which always returns `false`. 230function falseFn() { return false; } 231 232// @function formatNum(num: Number, digits?: Number): Number 233// Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default. 234function formatNum(num, digits) { 235 var pow = Math.pow(10, (digits === undefined ? 6 : digits)); 236 return Math.round(num * pow) / pow; 237} 238 239// @function trim(str: String): String 240// Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) 241function trim(str) { 242 return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); 243} 244 245// @function splitWords(str: String): String[] 246// Trims and splits the string on whitespace and returns the array of parts. 247function splitWords(str) { 248 return trim(str).split(/\s+/); 249} 250 251// @function setOptions(obj: Object, options: Object): Object 252// Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut. 253function setOptions(obj, options) { 254 if (!obj.hasOwnProperty('options')) { 255 obj.options = obj.options ? create(obj.options) : {}; 256 } 257 for (var i in options) { 258 obj.options[i] = options[i]; 259 } 260 return obj.options; 261} 262 263// @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String 264// Converts an object into a parameter URL string, e.g. `{a: "foo", b: "bar"}` 265// translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will 266// be appended at the end. If `uppercase` is `true`, the parameter names will 267// be uppercased (e.g. `'?A=foo&B=bar'`) 268function getParamString(obj, existingUrl, uppercase) { 269 var params = []; 270 for (var i in obj) { 271 params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); 272 } 273 return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); 274} 275 276var templateRe = /\{ *([\w_-]+) *\}/g; 277 278// @function template(str: String, data: Object): String 279// Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'` 280// and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string 281// `('Hello foo, bar')`. You can also specify functions instead of strings for 282// data values â they will be evaluated passing `data` as an argument. 283function template(str, data) { 284 return str.replace(templateRe, function (str, key) { 285 var value = data[key]; 286 287 if (value === undefined) { 288 throw new Error('No value provided for variable ' + str); 289 290 } else if (typeof value === 'function') { 291 value = value(data); 292 } 293 return value; 294 }); 295} 296 297// @function isArray(obj): Boolean 298// Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray) 299var isArray = Array.isArray || function (obj) { 300 return (Object.prototype.toString.call(obj) === '[object Array]'); 301}; 302 303// @function indexOf(array: Array, el: Object): Number 304// Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) 305function indexOf(array, el) { 306 for (var i = 0; i < array.length; i++) { 307 if (array[i] === el) { return i; } 308 } 309 return -1; 310} 311 312// @property emptyImageUrl: String 313// Data URI string containing a base64-encoded empty GIF image. 314// Used as a hack to free memory from unused images on WebKit-powered 315// mobile devices (by setting image `src` to this string). 316var emptyImageUrl = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; 317 318// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 319 320function getPrefixed(name) { 321 return window['webkit' + name] || window['moz' + name] || window['ms' + name]; 322} 323 324var lastTime = 0; 325 326// fallback for IE 7-8 327function timeoutDefer(fn) { 328 var time = +new Date(), 329 timeToCall = Math.max(0, 16 - (time - lastTime)); 330 331 lastTime = time + timeToCall; 332 return window.setTimeout(fn, timeToCall); 333} 334 335var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer; 336var cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') || 337 getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); }; 338
339// @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number 340// Schedules `fn` to be executed when the browser repaints. `fn` is bound to 341// `context` if given. When `immediate` is set, `fn` is called immediately if 342// the browser doesn't have native support for 343// [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame), 344// otherwise it's delayed. Returns a request ID that can be used to cancel the request. 345function requestAnimFrame(fn, context, immediate) { 346 if (immediate && requestFn === timeoutDefer) { 347 fn.call(context); 348 } else { 349 return requestFn.call(window, bind(fn, context)); 350 } 351} 352 353// @function cancelAnimFrame(id: Number): undefined 354// Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame). 355function cancelAnimFrame(id) { 356 if (id) { 357 cancelFn.call(window, id); 358 } 359} 360 361 362var Util = (Object.freeze || Object)({ 363 freeze: freeze, 364 extend: extend, 365 create: create, 366 bind: bind, 367 lastId: lastId, 368 stamp: stamp, 369 throttle: throttle, 370 wrapNum: wrapNum, 371 falseFn: falseFn, 372 formatNum: formatNum, 373 trim: trim, 374 splitWords: splitWords, 375 setOptions: setOptions, 376 getParamString: getParamString, 377 template: template, 378 isArray: isArray, 379 indexOf: indexOf, 380 emptyImageUrl: emptyImageUrl, 381 requestFn: requestFn, 382 cancelFn: cancelFn, 383 requestAnimFrame: requestAnimFrame, 384 cancelAnimFrame: cancelAnimFrame 385}); 386 387// @class Class 388// @aka L.Class 389 390// @section 391// @uninheritable 392 393// Thanks to John Resig and Dean Edwards for inspiration! 394 395function Class() {} 396 397Class.extend = function (props) { 398 399 // @function extend(props: Object): Function 400 // [Extends the current class](#class-inheritance) given the properties to be included. 401 // Returns a Javascript function that is a class constructor (to be called with `new`). 402 var NewClass = function () { 403 404 // call the constructor 405 if (this.initialize) { 406 this.initialize.apply(this, arguments); 407 } 408 409 // call all constructor hooks 410 this.callInitHooks(); 411 }; 412 413 var parentProto = NewClass.__super__ = this.prototype; 414 415 var proto = create(parentProto); 416 proto.constructor = NewClass; 417 418 NewClass.prototype = proto; 419 420 // inherit parent's statics 421 for (var i in this) { 422 if (this.hasOwnProperty(i) && i !== 'prototype' && i !== '__super__') { 423 NewClass[i] = this[i]; 424 } 425 } 426 427 // mix static properties into the class 428 if (props.statics) { 429 extend(NewClass, props.statics); 430 delete props.statics; 431 } 432 433 // mix includes into the prototype 434 if (props.includes) { 435 checkDeprecatedMixinEvents(props.includes); 436 extend.apply(null, [proto].concat(props.includes)); 437 delete props.includes; 438 } 439 440 // merge options 441 if (proto.options) { 442 props.options = extend(create(proto.options), props.options); 443 } 444 445 // mix given properties into the prototype 446 extend(proto, props); 447 448 proto._initHooks = []; 449 450 // add method for calling all hooks 451 proto.callInitHooks = function () { 452 453 if (this._initHooksCalled) { return; } 454 455 if (parentProto.callInitHooks) { 456 parentProto.callInitHooks.call(this); 457 } 458 459 this._initHooksCalled = true; 460 461 for (var i = 0, len = proto._initHooks.length; i < len; i++) { 462 proto._initHooks[i].call(this); 463 } 464 }; 465 466 return NewClass; 467}; 468 469 470// @function include(properties: Object): this 471// [Includes a mixin](#class-includes) into the current class. 472Class.include = function (props) { 473 extend(this.prototype, props); 474 return this; 475}; 476 477// @function mergeOptions(options: Object): this 478// [Merges `options`](#class-options) into the defaults of the class. 479Class.mergeOptions = function (options) { 480 extend(this.prototype.options, options); 481 return this; 482}; 483 484// @function addInitHook(fn: Function): this 485// Adds a [constructor hook](#class-constructor-hooks) to the class. 486Class.addInitHook = function (fn) { // (Function) || (String, args...) 487 var args = Array.prototype.slice.call(arguments, 1); 488 489 var init = typeof fn === 'function' ? fn : function () { 490 this[fn].apply(this, args); 491 }; 492 493 this.prototype._initHooks = this.prototype._initHooks || []; 494 this.prototype._initHooks.push(init); 495 return this; 496}; 497 498function checkDeprecatedMixinEvents(includes) { 499 if (typeof L === 'undefined' || !L || !L.Mixin) { return; } 500 501 includes = isArray(includes) ? includes : [includes]; 502 503 for (var i = 0; i < includes.length; i++) { 504 if (includes[i] === L.Mixin.Events) {
505 console.warn('Deprecated include of L.Mixin.Events: ' + 506 'this property will be removed in future releases, ' + 507 'please inherit from L.Evented instead.', new Error().stack); 508 } 509 } 510} 511 512/* 513 * @class Evented 514 * @aka L.Evented 515 * @inherits Class 516 * 517 * 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). 518 * 519 * @example 520 * 521 * ```js 522 * map.on('click', function(e) { 523 * alert(e.latlng); 524 * } ); 525 * ``` 526 * 527 * Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function: 528 * 529 * ```js 530 * function onClick(e) { ... } 531 * 532 * map.on('click', onClick); 533 * map.off('click', onClick); 534 * ``` 535 */ 536 537var Events = { 538 /* @method on(type: String, fn: Function, context?: Object): this 539 * 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'`). 540 * 541 * @alternative 542 * @method on(eventMap: Object): this 543 * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` 544 */ 545 on: function (types, fn, context) { 546 547 // types can be a map of types/handlers 548 if (typeof types === 'object') { 549 for (var type in types) { 550 // we don't process space-separated events here for performance; 551 // it's a hot path since Layer uses the on(obj) syntax 552 this._on(type, types[type], fn); 553 } 554 555 } else { 556 // types can be a string of space-separated words 557 types = splitWords(types); 558 559 for (var i = 0, len = types.length; i < len; i++) { 560 this._on(types[i], fn, context); 561 } 562 } 563 564 return this; 565 }, 566 567 /* @method off(type: String, fn?: Function, context?: Object): this 568 * 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. 569 * 570 * @alternative 571 * @method off(eventMap: Object): this 572 * Removes a set of type/listener pairs. 573 * 574 * @alternative 575 * @method off: this 576 * Removes all listeners to all events on the object. 577 */ 578 off: function (types, fn, context) { 579 580 if (!types) { 581 // clear all listeners if called without arguments 582 delete this._events; 583 584 } else if (typeof types === 'object') { 585 for (var type in types) { 586 this._off(type, types[type], fn); 587 } 588 589 } else { 590 types = splitWords(types); 591 592 for (var i = 0, len = types.length; i < len; i++) { 593 this._off(types[i], fn, context); 594 } 595 } 596 597 return this; 598 }, 599 600 // attach listener (without syntactic sugar now) 601 _on: function (type, fn, context) { 602 this._events = this._events || {}; 603 604 /* get/init listeners for type */ 605 var typeListeners = this._events[type]; 606 if (!typeListeners) { 607 typeListeners = []; 608 this._events[type] = typeListeners; 609 } 610 611 if (context === this) { 612 // Less memory footprint. 613 context = undefined; 614 } 615 var newListener = {fn: fn, ctx: context}, 616 listeners = typeListeners; 617 618 // check if fn already there 619 for (var i = 0, len = listeners.length; i < len; i++) { 620 if (listeners[i].fn === fn && listeners[i].ctx === context) { 621 return; 622 } 623 } 624 625 listeners.push(newListener); 626 }, 627 628 _off: function (type, fn, context) { 629 var listeners, 630 i, 631 len; 632 633 if (!this._events) { return; } 634 635 listeners = this._events[type]; 636 637 if (!listeners) { 638 return; 639 } 640 641 if (!fn) { 642 // Set all removed listeners to noop so they are not called if remove happens in fire 643 for (i = 0, len = listeners.length; i < len; i++) { 644 listeners[i].fn = falseFn; 645 } 646 // clear all listeners for a type if function isn't specified 647 delete this._events[type]; 648 return; 649 } 650 651 if (context === this) { 652 context = undefined; 653 } 654 655 if (listeners) { 656 657 // find fn and remove it 658 for (i = 0, len = listeners.length; i < len; i++) { 659 var l = listeners[i]; 660 if (l.ctx !== context) { continue; } 661 if (l.fn === fn) { 662 663 // set the removed listener to noop so that's not called if remove happens in fire 664 l.fn = falseFn; 665 666 if (this._firingCount) { 667 /* copy array in case events are being fired */ 668 this._events[type] = listeners = listeners.slice(); 669 } 670 listeners.splice(i, 1); 671 672 return; 673 } 674 } 675 } 676 }, 677 678 // @method fire(type: String, data?: Object, propagate?: Boolean): this 679 // Fires an event of the specified type. You can optionally provide an data 680 // object â the first argument of the listener function will contain its 681 // properties. The event can optionally be propagated to event parents. 682 fire: function (type, data, propagate) {
vendor: 16,671 bytes, lines 683-1300
683 if (!this.listens(type, propagate)) { return this; } 684 685 var event = extend({}, data, { 686 type: type, 687 target: this, 688 sourceTarget: data && data.sourceTarget || this 689 }); 690 691 if (this._events) { 692 var listeners = this._events[type]; 693 694 if (listeners) { 695 this._firingCount = (this._firingCount + 1) || 1; 696 for (var i = 0, len = listeners.length; i < len; i++) { 697 var l = listeners[i]; 698 l.fn.call(l.ctx || this, event); 699 } 700 701 this._firingCount--; 702 } 703 } 704 705 if (propagate) { 706 // propagate the event to parents (set with addEventParent) 707 this._propagateEvent(event); 708 } 709 710 return this; 711 }, 712 713 // @method listens(type: String): Boolean 714 // Returns `true` if a particular event type has any listeners attached to it. 715 listens: function (type, propagate) { 716 var listeners = this._events && this._events[type]; 717 if (listeners && listeners.length) { return true; } 718 719 if (propagate) { 720 // also check parents for listeners if event propagates 721 for (var id in this._eventParents) { 722 if (this._eventParents[id].listens(type, propagate)) { return true; } 723 } 724 } 725 return false; 726 }, 727 728 // @method once(â¦): this 729 // Behaves as [`on(â¦)`](#evented-on), except the listener will only get fired once and then removed. 730 once: function (types, fn, context) { 731 732 if (typeof types === 'object') { 733 for (var type in types) { 734 this.once(type, types[type], fn); 735 } 736 return this; 737 } 738 739 var handler = bind(function () { 740 this 741 .off(types, fn, context) 742 .off(types, handler, context); 743 }, this); 744 745 // add a listener that's executed once and removed after that 746 return this 747 .on(types, fn, context) 748 .on(types, handler, context); 749 }, 750 751 // @method addEventParent(obj: Evented): this 752 // Adds an event parent - an `Evented` that will receive propagated events 753 addEventParent: function (obj) { 754 this._eventParents = this._eventParents || {}; 755 this._eventParents[stamp(obj)] = obj; 756 return this; 757 }, 758 759 // @method removeEventParent(obj: Evented): this 760 // Removes an event parent, so it will stop receiving propagated events 761 removeEventParent: function (obj) { 762 if (this._eventParents) { 763 delete this._eventParents[stamp(obj)]; 764 } 765 return this; 766 }, 767 768 _propagateEvent: function (e) { 769 for (var id in this._eventParents) { 770 this._eventParents[id].fire(e.type, extend({ 771 layer: e.target, 772 propagatedFrom: e.target 773 }, e), true); 774 } 775 } 776}; 777 778// aliases; we should ditch those eventually 779 780// @method addEventListener(â¦): this 781// Alias to [`on(â¦)`](#evented-on) 782Events.addEventListener = Events.on; 783 784// @method removeEventListener(â¦): this 785// Alias to [`off(â¦)`](#evented-off) 786 787// @method clearAllEventListeners(â¦): this 788// Alias to [`off()`](#evented-off) 789Events.removeEventListener = Events.clearAllEventListeners = Events.off; 790 791// @method addOneTimeEventListener(â¦): this 792// Alias to [`once(â¦)`](#evented-once) 793Events.addOneTimeEventListener = Events.once; 794 795// @method fireEvent(â¦): this 796// Alias to [`fire(â¦)`](#evented-fire) 797Events.fireEvent = Events.fire; 798 799// @method hasEventListeners(â¦): Boolean 800// Alias to [`listens(â¦)`](#evented-listens) 801Events.hasEventListeners = Events.listens; 802 803var Evented = Class.extend(Events); 804 805/* 806 * @class Point 807 * @aka L.Point 808 * 809 * Represents a point with `x` and `y` coordinates in pixels. 810 * 811 * @example 812 * 813 * ```js 814 * var point = L.point(200, 300); 815 * ``` 816 * 817 * 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: 818 * 819 * ```js 820 * map.panBy([200, 300]); 821 * map.panBy(L.point(200, 300)); 822 * ``` 823 * 824 * Note that `Point` does not inherit from Leafet's `Class` object, 825 * which means new classes can't inherit from it, and new methods 826 * can't be added to it with the `include` function. 827 */ 828 829function Point(x, y, round) { 830 // @property x: Number; The `x` coordinate of the point 831 this.x = (round ? Math.round(x) : x); 832 // @property y: Number; The `y` coordinate of the point 833 this.y = (round ? Math.round(y) : y); 834} 835 836var trunc = Math.trunc || function (v) { 837 return v > 0 ? Math.floor(v) : Math.ceil(v); 838}; 839 840Point.prototype = { 841 842 // @method clone(): Point 843 // Returns a copy of the current point. 844 clone: function () { 845 return new Point(this.x, this.y); 846 }, 847 848 // @method add(otherPoint: Point): Point 849 // Returns the result of addition of the current and the given points. 850 add: function (point) { 851 // non-destructive, returns a new point 852 return this.clone()._add(toPoint(point)); 853 }, 854 855 _add: function (point) { 856 // destructive, used directly for performance in situations where it's safe to modify existing point 857 this.x += point.x; 858 this.y += point.y; 859 return this; 860 }, 861 862 // @method subtract(otherPoint: Point): Point 863 // Returns the result of subtraction of the given point from the current. 864 subtract: function (point) { 865 return this.clone()._subtract(toPoint(point)); 866 }, 867 868 _subtract: function (point) { 869 this.x -= point.x; 870 this.y -= point.y; 871 return this; 872 }, 873 874 // @method divideBy(num: Number): Point 875 // Returns the result of division of the current point by the given number. 876 divideBy: function (num) { 877 return this.clone()._divideBy(num); 878 }, 879 880 _divideBy: function (num) { 881 this.x /= num; 882 this.y /= num; 883 return this; 884 }, 885 886 // @method multiplyBy(num: Number): Point 887 // Returns the result of multiplication of the current point by the given number. 888 multiplyBy: function (num) { 889 return this.clone()._multiplyBy(num); 890 }, 891 892 _multiplyBy: function (num) { 893 this.x *= num; 894 this.y *= num; 895 return this; 896 }, 897 898 // @method scaleBy(scale: Point): Point 899 // Multiply each coordinate of the current point by each coordinate of 900 // `scale`. In linear algebra terms, multiply the point by the 901 // [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation) 902 // defined by `scale`. 903 scaleBy: function (point) { 904 return new Point(this.x * point.x, this.y * point.y); 905 }, 906 907 // @method unscaleBy(scale: Point): Point 908 // Inverse of `scaleBy`. Divide each coordinate of the current point by 909 // each coordinate of `scale`. 910 unscaleBy: function (point) { 911 return new Point(this.x / point.x, this.y / point.y); 912 }, 913 914 // @method round(): Point 915 // Returns a copy of the current point with rounded coordinates. 916 round: function () { 917 return this.clone()._round(); 918 }, 919 920 _round: function () { 921 this.x = Math.round(this.x); 922 this.y = Math.round(this.y); 923 return this; 924 }, 925 926 // @method floor(): Point 927 // Returns a copy of the current point with floored coordinates (rounded down). 928 floor: function () { 929 return this.clone()._floor(); 930 }, 931 932 _floor: function () { 933 this.x = Math.floor(this.x); 934 this.y = Math.floor(this.y); 935 return this; 936 }, 937 938 // @method ceil(): Point 939 // Returns a copy of the current point with ceiled coordinates (rounded up). 940 ceil: function () { 941 return this.clone()._ceil(); 942 }, 943 944 _ceil: function () { 945 this.x = Math.ceil(this.x); 946 this.y = Math.ceil(this.y); 947 return this; 948 }, 949 950 // @method trunc(): Point 951 // Returns a copy of the current point with truncated coordinates (rounded towards zero). 952 trunc: function () { 953 return this.clone()._trunc(); 954 }, 955 956 _trunc: function () { 957 this.x = trunc(this.x); 958 this.y = trunc(this.y); 959 return this; 960 }, 961 962 // @method distanceTo(otherPoint: Point): Number 963 // Returns the cartesian distance between the current and the given points. 964 distanceTo: function (point) { 965 point = toPoint(point); 966 967 var x = point.x - this.x, 968 y = point.y - this.y; 969 970 return Math.sqrt(x * x + y * y); 971 }, 972 973 // @method equals(otherPoint: Point): Boolean 974 // Returns `true` if the given point has the same coordinates. 975 equals: function (point) { 976 point = toPoint(point); 977 978 return point.x === this.x && 979 point.y === this.y; 980 }, 981 982 // @method contains(otherPoint: Point): Boolean 983 // Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values). 984 contains: function (point) { 985 point = toPoint(point); 986 987 return Math.abs(point.x) <= Math.abs(this.x) && 988 Math.abs(point.y) <= Math.abs(this.y); 989 }, 990 991 // @method toString(): String 992 // Returns a string representation of the point for debugging purposes. 993 toString: function () { 994 return 'Point(' + 995 formatNum(this.x) + ', ' + 996 formatNum(this.y) + ')'; 997 } 998}; 999 1000// @factory L.point(x: Number, y: Number, round?: Boolean) 1001// Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values. 1002 1003// @alternative 1004// @factory L.point(coords: Number[]) 1005// Expects an array of the form `[x, y]` instead. 1006 1007// @alternative 1008// @factory L.point(coords: Object) 1009// Expects a plain object of the form `{x: Number, y: Number}` instead. 1010function toPoint(x, y, round) { 1011 if (x instanceof Point) { 1012 return x; 1013 } 1014 if (isArray(x)) { 1015 return new Point(x[0], x[1]); 1016 } 1017 if (x === undefined || x === null) { 1018 return x; 1019 } 1020 if (typeof x === 'object' && 'x' in x && 'y' in x) { 1021 return new Point(x.x, x.y); 1022 } 1023 return new Point(x, y, round); 1024} 1025 1026/* 1027 * @class Bounds 1028 * @aka L.Bounds 1029 * 1030 * Represents a rectangular area in pixel coordinates. 1031 * 1032 * @example 1033 * 1034 * ```js 1035 * var p1 = L.point(10, 10), 1036 * p2 = L.point(40, 60), 1037 * bounds = L.bounds(p1, p2); 1038 * ``` 1039 * 1040 * 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: 1041 * 1042 * ```js 1043 * otherBounds.intersects([[10, 10], [40, 60]]); 1044 * ``` 1045 * 1046 * Note that `Bounds` does not inherit from Leafet's `Class` object, 1047 * which means new classes can't inherit from it, and new methods 1048 * can't be added to it with the `include` function. 1049 */ 1050 1051function Bounds(a, b) { 1052 if (!a) { return; } 1053 1054 var points = b ? [a, b] : a; 1055 1056 for (var i = 0, len = points.length; i < len; i++) { 1057 this.extend(points[i]); 1058 } 1059} 1060 1061Bounds.prototype = { 1062 // @method extend(point: Point): this 1063 // Extends the bounds to contain the given point. 1064 extend: function (point) { // (Point) 1065 point = toPoint(point); 1066 1067 // @property min: Point 1068 // The top left corner of the rectangle. 1069 // @property max: Point 1070 // The bottom right corner of the rectangle. 1071 if (!this.min && !this.max) { 1072 this.min = point.clone(); 1073 this.max = point.clone(); 1074 } else { 1075 this.min.x = Math.min(point.x, this.min.x); 1076 this.max.x = Math.max(point.x, this.max.x); 1077 this.min.y = Math.min(point.y, this.min.y); 1078 this.max.y = Math.max(point.y, this.max.y); 1079 } 1080 return this; 1081 }, 1082 1083 // @method getCenter(round?: Boolean): Point 1084 // Returns the center point of the bounds. 1085 getCenter: function (round) { 1086 return new Point( 1087 (this.min.x + this.max.x) / 2, 1088 (this.min.y + this.max.y) / 2, round); 1089 }, 1090 1091 // @method getBottomLeft(): Point 1092 // Returns the bottom-left point of the bounds. 1093 getBottomLeft: function () { 1094 return new Point(this.min.x, this.max.y); 1095 }, 1096 1097 // @method getTopRight(): Point 1098 // Returns the top-right point of the bounds. 1099 getTopRight: function () { // -> Point 1100 return new Point(this.max.x, this.min.y); 1101 }, 1102 1103 // @method getTopLeft(): Point 1104 // Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)). 1105 getTopLeft: function () { 1106 return this.min; // left, top 1107 }, 1108 1109 // @method getBottomRight(): Point 1110 // Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)). 1111 getBottomRight: function () { 1112 return this.max; // right, bottom 1113 }, 1114 1115 // @method getSize(): Point 1116 // Returns the size of the given bounds 1117 getSize: function () { 1118 return this.max.subtract(this.min); 1119 }, 1120 1121 // @method contains(otherBounds: Bounds): Boolean 1122 // Returns `true` if the rectangle contains the given one. 1123 // @alternative 1124 // @method contains(point: Point): Boolean 1125 // Returns `true` if the rectangle contains the given point. 1126 contains: function (obj) { 1127 var min, max; 1128 1129 if (typeof obj[0] === 'number' || obj instanceof Point) { 1130 obj = toPoint(obj); 1131 } else { 1132 obj = toBounds(obj); 1133 } 1134 1135 if (obj instanceof Bounds) { 1136 min = obj.min; 1137 max = obj.max; 1138 } else { 1139 min = max = obj; 1140 } 1141 1142 return (min.x >= this.min.x) && 1143 (max.x <= this.max.x) && 1144 (min.y >= this.min.y) && 1145 (max.y <= this.max.y); 1146 }, 1147 1148 // @method intersects(otherBounds: Bounds): Boolean 1149 // Returns `true` if the rectangle intersects the given bounds. Two bounds 1150 // intersect if they have at least one point in common. 1151 intersects: function (bounds) { // (Bounds) -> Boolean 1152 bounds = toBounds(bounds); 1153 1154 var min = this.min, 1155 max = this.max, 1156 min2 = bounds.min, 1157 max2 = bounds.max, 1158 xIntersects = (max2.x >= min.x) && (min2.x <= max.x), 1159 yIntersects = (max2.y >= min.y) && (min2.y <= max.y); 1160 1161 return xIntersects && yIntersects; 1162 }, 1163 1164 // @method overlaps(otherBounds: Bounds): Boolean 1165 // Returns `true` if the rectangle overlaps the given bounds. Two bounds 1166 // overlap if their intersection is an area. 1167 overlaps: function (bounds) { // (Bounds) -> Boolean 1168 bounds = toBounds(bounds); 1169 1170 var min = this.min, 1171 max = this.max, 1172 min2 = bounds.min, 1173 max2 = bounds.max, 1174 xOverlaps = (max2.x > min.x) && (min2.x < max.x), 1175 yOverlaps = (max2.y > min.y) && (min2.y < max.y); 1176 1177 return xOverlaps && yOverlaps; 1178 }, 1179 1180 isValid: function () { 1181 return !!(this.min && this.max); 1182 } 1183}; 1184 1185 1186// @factory L.bounds(corner1: Point, corner2: Point) 1187// Creates a Bounds object from two corners coordinate pairs. 1188// @alternative 1189// @factory L.bounds(points: Point[]) 1190// Creates a Bounds object from the given array of points. 1191function toBounds(a, b) { 1192 if (!a || a instanceof Bounds) { 1193 return a; 1194 } 1195 return new Bounds(a, b); 1196} 1197 1198/* 1199 * @class LatLngBounds 1200 * @aka L.LatLngBounds 1201 * 1202 * Represents a rectangular geographical area on a map. 1203 * 1204 * @example 1205 * 1206 * ```js 1207 * var corner1 = L.latLng(40.712, -74.227), 1208 * corner2 = L.latLng(40.774, -74.125), 1209 * bounds = L.latLngBounds(corner1, corner2); 1210 * ``` 1211 * 1212 * 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: 1213 * 1214 * ```js 1215 * map.fitBounds([ 1216 * [40.712, -74.227], 1217 * [40.774, -74.125] 1218 * ]); 1219 * ``` 1220 * 1221 * 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. 1222 * 1223 * Note that `LatLngBounds` does not inherit from Leafet's `Class` object, 1224 * which means new classes can't inherit from it, and new methods 1225 * can't be added to it with the `include` function. 1226 */ 1227 1228function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[]) 1229 if (!corner1) { return; } 1230 1231 var latlngs = corner2 ? [corner1, corner2] : corner1; 1232 1233 for (var i = 0, len = latlngs.length; i < len; i++) { 1234 this.extend(latlngs[i]); 1235 } 1236} 1237 1238LatLngBounds.prototype = { 1239 1240 // @method extend(latlng: LatLng): this 1241 // Extend the bounds to contain the given point 1242 1243 // @alternative 1244 // @method extend(otherBounds: LatLngBounds): this 1245 // Extend the bounds to contain the given bounds 1246 extend: function (obj) { 1247 var sw = this._southWest, 1248 ne = this._northEast, 1249 sw2, ne2; 1250 1251 if (obj instanceof LatLng) { 1252 sw2 = obj; 1253 ne2 = obj; 1254 1255 } else if (obj instanceof LatLngBounds) { 1256 sw2 = obj._southWest; 1257 ne2 = obj._northEast; 1258 1259 if (!sw2 || !ne2) { return this; } 1260 1261 } else { 1262 return obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this; 1263 } 1264 1265 if (!sw && !ne) { 1266 this._southWest = new LatLng(sw2.lat, sw2.lng); 1267 this._northEast = new LatLng(ne2.lat, ne2.lng); 1268 } else { 1269 sw.lat = Math.min(sw2.lat, sw.lat); 1270 sw.lng = Math.min(sw2.lng, sw.lng); 1271 ne.lat = Math.max(ne2.lat, ne.lat); 1272 ne.lng = Math.max(ne2.lng, ne.lng); 1273 } 1274 1275 return this; 1276 }, 1277 1278 // @method pad(bufferRatio: Number): LatLngBounds 1279 // Returns bounds created by extending or retracting the current bounds by a given ratio in each direction. 1280 // For example, a ratio of 0.5 extends the bounds by 50% in each direction. 1281 // Negative values will retract the bounds. 1282 pad: function (bufferRatio) { 1283 var sw = this._southWest, 1284 ne = this._northEast, 1285 heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, 1286 widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio; 1287 1288 return new LatLngBounds( 1289 new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), 1290 new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)); 1291 }, 1292 1293 // @method getCenter(): LatLng 1294 // Returns the center point of the bounds. 1295 getCenter: function () { 1296 return new LatLng( 1297 (this._southWest.lat + this._northEast.lat) / 2, 1298 (this._southWest.lng + this._northEast.lng) / 2); 1299 }, 1300
1301 // @method getSouthWest(): LatLng 1302 // Returns the south-west point of the bounds. 1303 getSouthWest: function () { 1304 return this._southWest; 1305 }, 1306 1307 // @method getNorthEast(): LatLng 1308 // Returns the north-east point of the bounds. 1309 getNorthEast: function () { 1310 return this._northEast; 1311 }, 1312 1313 // @method getNorthWest(): LatLng 1314 // Returns the north-west point of the bounds. 1315 getNorthWest: function () { 1316 return new LatLng(this.getNorth(), this.getWest()); 1317 }, 1318 1319 // @method getSouthEast(): LatLng 1320 // Returns the south-east point of the bounds. 1321 getSouthEast: function () { 1322 return new LatLng(this.getSouth(), this.getEast()); 1323 }, 1324 1325 // @method getWest(): Number 1326 // Returns the west longitude of the bounds 1327 getWest: function () { 1328 return this._southWest.lng; 1329 }, 1330 1331 // @method getSouth(): Number 1332 // Returns the south latitude of the bounds 1333 getSouth: function () { 1334 return this._southWest.lat; 1335 }, 1336 1337 // @method getEast(): Number 1338 // Returns the east longitude of the bounds 1339 getEast: function () { 1340 return this._northEast.lng; 1341 }, 1342 1343 // @method getNorth(): Number 1344 // Returns the north latitude of the bounds 1345 getNorth: function () { 1346 return this._northEast.lat; 1347 }, 1348 1349 // @method contains(otherBounds: LatLngBounds): Boolean 1350 // Returns `true` if the rectangle contains the given one. 1351 1352 // @alternative 1353 // @method contains (latlng: LatLng): Boolean 1354 // Returns `true` if the rectangle contains the given point. 1355 contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean 1356 if (typeof obj[0] === 'number' || obj instanceof LatLng || 'lat' in obj) { 1357 obj = toLatLng(obj); 1358 } else { 1359 obj = toLatLngBounds(obj); 1360 } 1361 1362 var sw = this._southWest, 1363 ne = this._northEast, 1364 sw2, ne2; 1365 1366 if (obj instanceof LatLngBounds) {
vendor: 7,059 bytes, lines 1367-1586
1367 sw2 = obj.getSouthWest(); 1368 ne2 = obj.getNorthEast(); 1369 } else { 1370 sw2 = ne2 = obj; 1371 } 1372 1373 return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) && 1374 (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng); 1375 }, 1376 1377 // @method intersects(otherBounds: LatLngBounds): Boolean 1378 // Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common. 1379 intersects: function (bounds) { 1380 bounds = toLatLngBounds(bounds); 1381 1382 var sw = this._southWest, 1383 ne = this._northEast, 1384 sw2 = bounds.getSouthWest(), 1385 ne2 = bounds.getNorthEast(), 1386 1387 latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat), 1388 lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng); 1389 1390 return latIntersects && lngIntersects; 1391 }, 1392 1393 // @method overlaps(otherBounds: Bounds): Boolean 1394 // Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area. 1395 overlaps: function (bounds) { 1396 bounds = toLatLngBounds(bounds); 1397 1398 var sw = this._southWest, 1399 ne = this._northEast, 1400 sw2 = bounds.getSouthWest(), 1401 ne2 = bounds.getNorthEast(), 1402 1403 latOverlaps = (ne2.lat > sw.lat) && (sw2.lat < ne.lat), 1404 lngOverlaps = (ne2.lng > sw.lng) && (sw2.lng < ne.lng); 1405 1406 return latOverlaps && lngOverlaps; 1407 }, 1408 1409 // @method toBBoxString(): String 1410 // 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. 1411 toBBoxString: function () { 1412 return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(','); 1413 }, 1414 1415 // @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean 1416 // 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. 1417 equals: function (bounds, maxMargin) { 1418 if (!bounds) { return false; } 1419 1420 bounds = toLatLngBounds(bounds); 1421 1422 return this._southWest.equals(bounds.getSouthWest(), maxMargin) && 1423 this._northEast.equals(bounds.getNorthEast(), maxMargin); 1424 }, 1425 1426 // @method isValid(): Boolean 1427 // Returns `true` if the bounds are properly initialized. 1428 isValid: function () { 1429 return !!(this._southWest && this._northEast); 1430 } 1431}; 1432 1433// TODO International date line? 1434 1435// @factory L.latLngBounds(corner1: LatLng, corner2: LatLng) 1436// Creates a `LatLngBounds` object by defining two diagonally opposite corners of the rectangle. 1437 1438// @alternative 1439// @factory L.latLngBounds(latlngs: LatLng[]) 1440// 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). 1441function toLatLngBounds(a, b) { 1442 if (a instanceof LatLngBounds) { 1443 return a; 1444 } 1445 return new LatLngBounds(a, b); 1446} 1447 1448/* @class LatLng 1449 * @aka L.LatLng 1450 * 1451 * Represents a geographical point with a certain latitude and longitude. 1452 * 1453 * @example 1454 * 1455 * ``` 1456 * var latlng = L.latLng(50.5, 30.5); 1457 * ``` 1458 * 1459 * 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: 1460 * 1461 * ``` 1462 * map.panTo([50, 30]); 1463 * map.panTo({lon: 30, lat: 50}); 1464 * map.panTo({lat: 50, lng: 30}); 1465 * map.panTo(L.latLng(50, 30)); 1466 * ``` 1467 * 1468 * Note that `LatLng` does not inherit from Leaflet's `Class` object, 1469 * which means new classes can't inherit from it, and new methods 1470 * can't be added to it with the `include` function. 1471 */ 1472 1473function LatLng(lat, lng, alt) { 1474 if (isNaN(lat) || isNaN(lng)) { 1475 throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); 1476 } 1477 1478 // @property lat: Number 1479 // Latitude in degrees 1480 this.lat = +lat; 1481 1482 // @property lng: Number 1483 // Longitude in degrees 1484 this.lng = +lng; 1485 1486 // @property alt: Number 1487 // Altitude in meters (optional) 1488 if (alt !== undefined) { 1489 this.alt = +alt; 1490 } 1491} 1492 1493LatLng.prototype = { 1494 // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean 1495 // 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. 1496 equals: function (obj, maxMargin) { 1497 if (!obj) { return false; } 1498 1499 obj = toLatLng(obj); 1500 1501 var margin = Math.max( 1502 Math.abs(this.lat - obj.lat), 1503 Math.abs(this.lng - obj.lng)); 1504 1505 return margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin); 1506 }, 1507 1508 // @method toString(): String 1509 // Returns a string representation of the point (for debugging purposes). 1510 toString: function (precision) { 1511 return 'LatLng(' + 1512 formatNum(this.lat, precision) + ', ' + 1513 formatNum(this.lng, precision) + ')'; 1514 }, 1515 1516 // @method distanceTo(otherLatLng: LatLng): Number 1517 // 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). 1518 distanceTo: function (other) { 1519 return Earth.distance(this, toLatLng(other)); 1520 }, 1521 1522 // @method wrap(): LatLng 1523 // Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees. 1524 wrap: function () { 1525 return Earth.wrapLatLng(this); 1526 }, 1527 1528 // @method toBounds(sizeInMeters: Number): LatLngBounds 1529 // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`. 1530 toBounds: function (sizeInMeters) { 1531 var latAccuracy = 180 * sizeInMeters / 40075017, 1532 lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat); 1533 1534 return toLatLngBounds( 1535 [this.lat - latAccuracy, this.lng - lngAccuracy], 1536 [this.lat + latAccuracy, this.lng + lngAccuracy]); 1537 }, 1538 1539 clone: function () { 1540 return new LatLng(this.lat, this.lng, this.alt); 1541 } 1542}; 1543 1544 1545 1546// @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng 1547// Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude). 1548 1549// @alternative 1550// @factory L.latLng(coords: Array): LatLng 1551// Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead. 1552 1553// @alternative 1554// @factory L.latLng(coords: Object): LatLng 1555// Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead. 1556 1557function toLatLng(a, b, c) { 1558 if (a instanceof LatLng) { 1559 return a; 1560 } 1561 if (isArray(a) && typeof a[0] !== 'object') { 1562 if (a.length === 3) { 1563 return new LatLng(a[0], a[1], a[2]); 1564 } 1565 if (a.length === 2) { 1566 return new LatLng(a[0], a[1]); 1567 } 1568 return null; 1569 } 1570 if (a === undefined || a === null) { 1571 return a; 1572 } 1573 if (typeof a === 'object' && 'lat' in a) { 1574 return new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt); 1575 } 1576 if (b === undefined) { 1577 return null; 1578 } 1579 return new LatLng(a, b, c); 1580} 1581 1582/* 1583 * @namespace CRS 1584 * @crs L.CRS.Base 1585 * Object that defines coordinate reference systems for projecting 1586 * geographical points into pixel (screen) coordinates and back (and to
1587 * coordinates in other units for [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services). See 1588 * [spatial reference system](http://en.wikipedia.org/wiki/Coordinate_reference_system). 1589 * 1590 * Leaflet defines the most usual CRSs by default. If you want to use a 1591 * CRS not defined by default, take a look at the 1592 * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin. 1593 * 1594 * Note that the CRS instances do not inherit from Leafet's `Class` object, 1595 * and can't be instantiated. Also, new classes can't inherit from them, 1596 * and methods can't be added to them with the `include` function. 1597 */ 1598 1599var CRS = { 1600 // @method latLngToPoint(latlng: LatLng, zoom: Number): Point 1601 // Projects geographical coordinates into pixel coordinates for a given zoom. 1602 latLngToPoint: function (latlng, zoom) { 1603 var projectedPoint = this.projection.project(latlng), 1604 scale = this.scale(zoom); 1605 1606 return this.transformation._transform(projectedPoint, scale); 1607 }, 1608 1609 // @method pointToLatLng(point: Point, zoom: Number): LatLng 1610 // The inverse of `latLngToPoint`. Projects pixel coordinates on a given 1611 // zoom into geographical coordinates. 1612 pointToLatLng: function (point, zoom) { 1613 var scale = this.scale(zoom), 1614 untransformedPoint = this.transformation.untransform(point, scale); 1615 1616 return this.projection.unproject(untransformedPoint); 1617 }, 1618 1619 // @method project(latlng: LatLng): Point 1620 // Projects geographical coordinates into coordinates in units accepted for 1621 // this CRS (e.g. meters for EPSG:3857, for passing it to WMS services). 1622 project: function (latlng) { 1623 return this.projection.project(latlng); 1624 }, 1625 1626 // @method unproject(point: Point): LatLng 1627 // Given a projected coordinate returns the corresponding LatLng. 1628 // The inverse of `project`. 1629 unproject: function (point) { 1630 return this.projection.unproject(point); 1631 }, 1632 1633 // @method scale(zoom: Number): Number 1634 // Returns the scale used when transforming projected coordinates into 1635 // pixel coordinates for a particular zoom. For example, it returns 1636 // `256 * 2^zoom` for Mercator-based CRS. 1637 scale: function (zoom) { 1638 return 256 * Math.pow(2, zoom); 1639 }, 1640 1641 // @method zoom(scale: Number): Number 1642 // Inverse of `scale()`, returns the zoom level corresponding to a scale 1643 // factor of `scale`. 1644 zoom: function (scale) { 1645 return Math.log(scale / 256) / Math.LN2; 1646 }, 1647 1648 // @method getProjectedBounds(zoom: Number): Bounds 1649 // Returns the projection's bounds scaled and transformed for the provided `zoom`. 1650 getProjectedBounds: function (zoom) { 1651 if (this.infinite) { return null; } 1652 1653 var b = this.projection.bounds, 1654 s = this.scale(zoom), 1655 min = this.transformation.transform(b.min, s), 1656 max = this.transformation.transform(b.max, s); 1657 1658 return new Bounds(min, max); 1659 }, 1660 1661 // @method distance(latlng1: LatLng, latlng2: LatLng): Number 1662 // Returns the distance between two geographical coordinates. 1663 1664 // @property code: String 1665 // Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`) 1666 // 1667 // @property wrapLng: Number[] 1668 // An array of two numbers defining whether the longitude (horizontal) coordinate 1669 // axis wraps around a given range and how. Defaults to `[-180, 180]` in most 1670 // geographical CRSs. If `undefined`, the longitude axis does not wrap around. 1671 // 1672 // @property wrapLat: Number[] 1673 // Like `wrapLng`, but for the latitude (vertical) axis. 1674 1675 // wrapLng: [min, max], 1676 // wrapLat: [min, max], 1677 1678 // @property infinite: Boolean 1679 // If true, the coordinate space will be unbounded (infinite in both axes) 1680 infinite: false, 1681 1682 // @method wrapLatLng(latlng: LatLng): LatLng 1683 // Returns a `LatLng` where lat and lng has been wrapped according to the 1684 // CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds. 1685 wrapLatLng: function (latlng) { 1686 var lng = this.wrapLng ? wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng, 1687 lat = this.wrapLat ? wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat, 1688 alt = latlng.alt; 1689 1690 return new LatLng(lat, lng, alt); 1691 }, 1692 1693 // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds 1694 // Returns a `LatLngBounds` with the same size as the given one, ensuring 1695 // that its center is within the CRS's bounds. 1696 // Only accepts actual `L.LatLngBounds` instances, not arrays. 1697 wrapLatLngBounds: function (bounds) { 1698 var center = bounds.getCenter(), 1699 newCenter = this.wrapLatLng(center), 1700 latShift = center.lat - newCenter.lat, 1701 lngShift = center.lng - newCenter.lng; 1702 1703 if (latShift === 0 && lngShift === 0) { 1704 return bounds; 1705 } 1706
vendor: 8,558 bytes, lines 1707-1983
1707 var sw = bounds.getSouthWest(), 1708 ne = bounds.getNorthEast(), 1709 newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift), 1710 newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift); 1711 1712 return new LatLngBounds(newSw, newNe); 1713 } 1714}; 1715 1716/* 1717 * @namespace CRS 1718 * @crs L.CRS.Earth 1719 * 1720 * Serves as the base for CRS that are global such that they cover the earth. 1721 * Can only be used as the base for other CRS and cannot be used directly, 1722 * since it does not have a `code`, `projection` or `transformation`. `distance()` returns 1723 * meters. 1724 */ 1725 1726var Earth = extend({}, CRS, { 1727 wrapLng: [-180, 180], 1728 1729 // Mean Earth Radius, as recommended for use by 1730 // the International Union of Geodesy and Geophysics, 1731 // see http://rosettacode.org/wiki/Haversine_formula 1732 R: 6371000, 1733 1734 // distance between two geographical points using spherical law of cosines approximation 1735 distance: function (latlng1, latlng2) { 1736 var rad = Math.PI / 180, 1737 lat1 = latlng1.lat * rad, 1738 lat2 = latlng2.lat * rad, 1739 sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2), 1740 sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2), 1741 a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon, 1742 c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 1743 return this.R * c; 1744 } 1745}); 1746 1747/* 1748 * @namespace Projection 1749 * @projection L.Projection.SphericalMercator 1750 * 1751 * Spherical Mercator projection â the most common projection for online maps, 1752 * used by almost all free and commercial tile providers. Assumes that Earth is 1753 * a sphere. Used by the `EPSG:3857` CRS. 1754 */ 1755 1756var SphericalMercator = { 1757 1758 R: 6378137, 1759 MAX_LATITUDE: 85.0511287798, 1760 1761 project: function (latlng) { 1762 var d = Math.PI / 180, 1763 max = this.MAX_LATITUDE, 1764 lat = Math.max(Math.min(max, latlng.lat), -max), 1765 sin = Math.sin(lat * d); 1766 1767 return new Point( 1768 this.R * latlng.lng * d, 1769 this.R * Math.log((1 + sin) / (1 - sin)) / 2); 1770 }, 1771 1772 unproject: function (point) { 1773 var d = 180 / Math.PI; 1774 1775 return new LatLng( 1776 (2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d, 1777 point.x * d / this.R); 1778 }, 1779 1780 bounds: (function () { 1781 var d = 6378137 * Math.PI; 1782 return new Bounds([-d, -d], [d, d]); 1783 })() 1784}; 1785 1786/* 1787 * @class Transformation 1788 * @aka L.Transformation 1789 * 1790 * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d` 1791 * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing 1792 * the reverse. Used by Leaflet in its projections code. 1793 * 1794 * @example 1795 * 1796 * ```js 1797 * var transformation = L.transformation(2, 5, -1, 10), 1798 * p = L.point(1, 2), 1799 * p2 = transformation.transform(p), // L.point(7, 8) 1800 * p3 = transformation.untransform(p2); // L.point(1, 2) 1801 * ``` 1802 */ 1803 1804 1805// factory new L.Transformation(a: Number, b: Number, c: Number, d: Number) 1806// Creates a `Transformation` object with the given coefficients. 1807function Transformation(a, b, c, d) { 1808 if (isArray(a)) { 1809 // use array properties 1810 this._a = a[0]; 1811 this._b = a[1]; 1812 this._c = a[2]; 1813 this._d = a[3]; 1814 return; 1815 } 1816 this._a = a; 1817 this._b = b; 1818 this._c = c; 1819 this._d = d; 1820} 1821 1822Transformation.prototype = { 1823 // @method transform(point: Point, scale?: Number): Point 1824 // Returns a transformed point, optionally multiplied by the given scale. 1825 // Only accepts actual `L.Point` instances, not arrays. 1826 transform: function (point, scale) { // (Point, Number) -> Point 1827 return this._transform(point.clone(), scale); 1828 }, 1829 1830 // destructive transform (faster) 1831 _transform: function (point, scale) { 1832 scale = scale || 1; 1833 point.x = scale * (this._a * point.x + this._b); 1834 point.y = scale * (this._c * point.y + this._d); 1835 return point; 1836 }, 1837 1838 // @method untransform(point: Point, scale?: Number): Point 1839 // Returns the reverse transformation of the given point, optionally divided 1840 // by the given scale. Only accepts actual `L.Point` instances, not arrays. 1841 untransform: function (point, scale) { 1842 scale = scale || 1; 1843 return new Point( 1844 (point.x / scale - this._b) / this._a, 1845 (point.y / scale - this._d) / this._c); 1846 } 1847}; 1848 1849// factory L.transformation(a: Number, b: Number, c: Number, d: Number) 1850 1851// @factory L.transformation(a: Number, b: Number, c: Number, d: Number) 1852// Instantiates a Transformation object with the given coefficients. 1853 1854// @alternative 1855// @factory L.transformation(coefficients: Array): Transformation 1856// Expects an coefficients array of the form 1857// `[a: Number, b: Number, c: Number, d: Number]`. 1858 1859function toTransformation(a, b, c, d) { 1860 return new Transformation(a, b, c, d); 1861} 1862 1863/* 1864 * @namespace CRS 1865 * @crs L.CRS.EPSG3857 1866 * 1867 * The most common CRS for online maps, used by almost all free and commercial 1868 * tile providers. Uses Spherical Mercator projection. Set in by default in 1869 * Map's `crs` option. 1870 */ 1871 1872var EPSG3857 = extend({}, Earth, { 1873 code: 'EPSG:3857', 1874 projection: SphericalMercator, 1875 1876 transformation: (function () { 1877 var scale = 0.5 / (Math.PI * SphericalMercator.R); 1878 return toTransformation(scale, 0.5, -scale, 0.5); 1879 }()) 1880}); 1881 1882var EPSG900913 = extend({}, EPSG3857, { 1883 code: 'EPSG:900913' 1884}); 1885 1886// @namespace SVG; @section 1887// There are several static functions which can be called without instantiating L.SVG: 1888 1889// @function create(name: String): SVGElement 1890// Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement), 1891// corresponding to the class name passed. For example, using 'line' will return 1892// an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement). 1893function svgCreate(name) { 1894 return document.createElementNS('http://www.w3.org/2000/svg', name); 1895} 1896 1897// @function pointsToPath(rings: Point[], closed: Boolean): String 1898// Generates a SVG path string for multiple rings, with each ring turning 1899// into "M..L..L.." instructions 1900function pointsToPath(rings, closed) { 1901 var str = '', 1902 i, j, len, len2, points, p; 1903 1904 for (i = 0, len = rings.length; i < len; i++) { 1905 points = rings[i]; 1906 1907 for (j = 0, len2 = points.length; j < len2; j++) { 1908 p = points[j]; 1909 str += (j ? 'L' : 'M') + p.x + ' ' + p.y; 1910 } 1911 1912 // closes the ring for polygons; "x" is VML syntax 1913 str += closed ? (svg ? 'z' : 'x') : ''; 1914 } 1915 1916 // SVG complains about empty path strings 1917 return str || 'M0 0'; 1918} 1919 1920/* 1921 * @namespace Browser 1922 * @aka L.Browser 1923 * 1924 * A namespace with static properties for browser/feature detection used by Leaflet internally. 1925 * 1926 * @example 1927 * 1928 * ```js 1929 * if (L.Browser.ielt9) { 1930 * alert('Upgrade your browser, dude!'); 1931 * } 1932 * ``` 1933 */ 1934 1935var style$1 = document.documentElement.style; 1936 1937// @property ie: Boolean; `true` for all Internet Explorer versions (not Edge). 1938var ie = 'ActiveXObject' in window; 1939 1940// @property ielt9: Boolean; `true` for Internet Explorer versions less than 9. 1941var ielt9 = ie && !document.addEventListener; 1942 1943// @property edge: Boolean; `true` for the Edge web browser. 1944var edge = 'msLaunchUri' in navigator && !('documentMode' in document); 1945 1946// @property webkit: Boolean; 1947// `true` for webkit-based browsers like Chrome and Safari (including mobile versions). 1948var webkit = userAgentContains('webkit'); 1949 1950// @property android: Boolean 1951// `true` for any browser running on an Android platform. 1952var android = userAgentContains('android'); 1953 1954// @property android23: Boolean; `true` for browsers running on Android 2 or Android 3. 1955var android23 = userAgentContains('android 2') || userAgentContains('android 3'); 1956 1957/* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */ 1958var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit 1959// @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome) 1960var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window); 1961 1962// @property opera: Boolean; `true` for the Opera browser 1963var opera = !!window.opera; 1964 1965// @property chrome: Boolean; `true` for the Chrome browser. 1966var chrome = userAgentContains('chrome'); 1967 1968// @property gecko: Boolean; `true` for gecko-based browsers like Firefox. 1969var gecko = userAgentContains('gecko') && !webkit && !opera && !ie; 1970 1971// @property safari: Boolean; `true` for the Safari browser. 1972var safari = !chrome && userAgentContains('safari'); 1973 1974var phantom = userAgentContains('phantom'); 1975 1976// @property opera12: Boolean 1977// `true` for the Opera browser supporting CSS transforms (version 12 or later). 1978var opera12 = 'OTransition' in style$1; 1979 1980// @property win: Boolean; `true` when the browser is running in a Windows platform 1981var win = navigator.platform.indexOf('Win') === 0; 1982 1983// @property ie3d: Boolean;
1983 `true` for all Internet Explorer versions supporting CSS transforms. 1984var ie3d = ie && ('transition' in style$1); 1985 1986// @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms. 1987var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23; 1988 1989// @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms. 1990var gecko3d = 'MozPerspective' in style$1; 1991 1992// @property any3d: Boolean 1993// `true` for all browsers supporting CSS transforms. 1994var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom; 1995 1996// @property mobile: Boolean; `true` for all browsers running in a mobile device. 1997var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile'); 1998 1999// @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device. 2000var mobileWebkit = mobile && webkit; 2001 2002// @property mobileWebkit3d: Boolean 2003// `true` for all webkit-based browsers in a mobile device supporting CSS transforms. 2004var mobileWebkit3d = mobile && webkit3d; 2005 2006// @property msPointer: Boolean 2007// `true` for browsers implementing the Microsoft touch events model (notably IE10). 2008var msPointer = !window.PointerEvent && window.MSPointerEvent; 2009 2010// @property pointer: Boolean 2011// `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx). 2012var pointer = !!(window.PointerEvent || msPointer); 2013 2014// @property touch: Boolean 2015// `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events). 2016// This does not necessarily mean that the browser is running in a computer with 2017// a touchscreen, it only means that the browser is capable of understanding 2018// touch events. 2019var touch = !window.L_NO_TOUCH && (pointer || 'ontouchstart' in window || 2020 (window.DocumentTouch && document instanceof window.DocumentTouch)); 2021 2022// @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device. 2023var mobileOpera = mobile && opera; 2024 2025// @property mobileGecko: Boolean 2026// `true` for gecko-based browsers running in a mobile device. 2027var mobileGecko = mobile && gecko; 2028 2029// @property retina: Boolean 2030// `true` for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%. 2031var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1; 2032 2033 2034// @property canvas: Boolean 2035// `true` when the browser supports [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API). 2036var canvas = (function () { 2037 return !!document.createElement('canvas').getContext; 2038}()); 2039 2040// @property svg: Boolean 2041// `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG). 2042var svg = !!(document.createElementNS && svgCreate('svg').createSVGRect); 2043 2044// @property vml: Boolean 2045// `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language). 2046var vml = !svg && (function () { 2047 try { 2048 var div = document.createElement('div'); 2049 div.innerHTML = '<v:shape adj="1"/>'; 2050 2051 var shape = div.firstChild; 2052 shape.style.behavior = 'url(#default#VML)'; 2053 2054 return shape && (typeof shape.adj === 'object'); 2055 2056 } catch (e) { 2057 return false; 2058 } 2059}()); 2060 2061 2062function userAgentContains(str) { 2063 return navigator.userAgent.toLowerCase().indexOf(str) >= 0; 2064} 2065 2066 2067var Browser = (Object.freeze || Object)({ 2068 ie: ie, 2069 ielt9: ielt9, 2070 edge: edge, 2071 webkit: webkit, 2072 android: android, 2073 android23: android23, 2074 androidStock: androidStock, 2075 opera: opera, 2076 chrome: chrome, 2077 gecko: gecko, 2078 safari: safari, 2079 phantom: phantom, 2080 opera12: opera12, 2081 win: win, 2082 ie3d: ie3d, 2083 webkit3d: webkit3d, 2084 gecko3d: gecko3d, 2085 any3d: any3d, 2086 mobile: mobile, 2087 mobileWebkit: mobileWebkit, 2088 mobileWebkit3d: mobileWebkit3d, 2089 msPointer: msPointer, 2090 pointer: pointer, 2091 touch: touch, 2092 mobileOpera: mobileOpera, 2093 mobileGecko: mobileGecko, 2094 retina: retina, 2095 canvas: canvas, 2096 svg: svg, 2097 vml: vml 2098}); 2099 2100/* 2101 * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. 2102 */ 2103 2104 2105var POINTER_DOWN = msPointer ? 'MSPointerDown' : 'pointerdown';
2106var POINTER_MOVE = msPointer ? 'MSPointerMove' : 'pointermove'; 2107var POINTER_UP = msPointer ? 'MSPointerUp' : 'pointerup'; 2108var POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel'; 2109var TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION']; 2110 2111var _pointers = {}; 2112var _pointerDocListener = false; 2113 2114// DomEvent.DoubleTap needs to know about this 2115var _pointersCount = 0; 2116 2117// Provides a touch events wrapper for (ms)pointer events. 2118// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 2119 2120function addPointerListener(obj, type, handler, id) { 2121 if (type === 'touchstart') { 2122 _addPointerStart(obj, handler, id); 2123 2124 } else if (type === 'touchmove') { 2125 _addPointerMove(obj, handler, id); 2126 2127 } else if (type === 'touchend') { 2128 _addPointerEnd(obj, handler, id); 2129 } 2130 2131 return this; 2132} 2133 2134function removePointerListener(obj, type, id) { 2135 var handler = obj['_leaflet_' + type + id]; 2136 2137 if (type === 'touchstart') { 2138 obj.removeEventListener(POINTER_DOWN, handler, false); 2139 2140 } else if (type === 'touchmove') { 2141 obj.removeEventListener(POINTER_MOVE, handler, false); 2142 2143 } else if (type === 'touchend') { 2144 obj.removeEventListener(POINTER_UP, handler, false); 2145 obj.removeEventListener(POINTER_CANCEL, handler, false); 2146 } 2147 2148 return this; 2149} 2150 2151function _addPointerStart(obj, handler, id) { 2152 var onDown = bind(function (e) { 2153 if (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { 2154 // In IE11, some touch events needs to fire for form controls, or 2155 // the controls will stop working. We keep a whitelist of tag names that 2156 // need these events. For other target tags, we prevent default on the event. 2157 if (TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) { 2158 preventDefault(e); 2159 } else { 2160 return; 2161 } 2162 } 2163 2164 _handlePointer(e, handler); 2165 }); 2166 2167 obj['_leaflet_touchstart' + id] = onDown; 2168 obj.addEventListener(POINTER_DOWN, onDown, false); 2169 2170 // need to keep track of what pointers and how many are active to provide e.touches emulation 2171 if (!_pointerDocListener) { 2172 // we listen documentElement as any drags that end by moving the touch off the screen get fired there 2173 document.documentElement.addEventListener(POINTER_DOWN, _globalPointerDown, true); 2174 document.documentElement.addEventListener(POINTER_MOVE, _globalPointerMove, true); 2175 document.documentElement.addEventListener(POINTER_UP, _globalPointerUp, true); 2176 document.documentElement.addEventListener(POINTER_CANCEL, _globalPointerUp, true); 2177 2178 _pointerDocListener = true; 2179 } 2180} 2181 2182function _globalPointerDown(e) { 2183 _pointers[e.pointerId] = e; 2184 _pointersCount++; 2185} 2186 2187function _globalPointerMove(e) { 2188 if (_pointers[e.pointerId]) { 2189 _pointers[e.pointerId] = e; 2190 } 2191} 2192 2193function _globalPointerUp(e) { 2194 delete _pointers[e.pointerId]; 2195 _pointersCount--; 2196} 2197 2198function _handlePointer(e, handler) { 2199 e.touches = []; 2200 for (var i in _pointers) { 2201 e.touches.push(_pointers[i]); 2202 } 2203 e.changedTouches = [e]; 2204 2205 handler(e); 2206} 2207 2208function _addPointerMove(obj, handler, id) { 2209 var onMove = function (e) { 2210 // don't fire touch moves when mouse isn't down 2211 if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } 2212 2213 _handlePointer(e, handler); 2214 }; 2215 2216 obj['_leaflet_touchmove' + id] = onMove; 2217 obj.addEventListener(POINTER_MOVE, onMove, false); 2218} 2219 2220function _addPointerEnd(obj, handler, id) { 2221 var onUp = function (e) { 2222 _handlePointer(e, handler); 2223 }; 2224 2225 obj['_leaflet_touchend' + id] = onUp; 2226 obj.addEventListener(POINTER_UP, onUp, false); 2227 obj.addEventListener(POINTER_CANCEL, onUp, false); 2228} 2229 2230/* 2231 * Extends the event handling code with double tap support for mobile browsers. 2232 */ 2233 2234var _touchstart = msPointer ? 'MSPointerDown' : pointer ? 'pointerdown' : 'touchstart'; 2235var _touchend = msPointer ? 'MSPointerUp' : pointer ? 'pointerup' : 'touchend'; 2236var _pre = '_leaflet_'; 2237 2238// inspired by Zepto touch code by Thomas Fuchs 2239function addDoubleTapListener(obj, handler, id) { 2240 var last, touch$$1, 2241 doubleTap = false, 2242 delay = 250; 2243 2244 function onTouchStart(e) { 2245 var count; 2246 2247 if (pointer) { 2248 if ((!edge) || e.pointerType === 'mouse') { return; } 2249 count = _pointersCount; 2250 } else {
2251 count = e.touches.length; 2252 } 2253 2254 if (count > 1) { return; } 2255 2256 var now = Date.now(), 2257 delta = now - (last || now); 2258 2259 touch$$1 = e.touches ? e.touches[0] : e; 2260 doubleTap = (delta > 0 && delta <= delay); 2261 last = now; 2262 } 2263 2264 function onTouchEnd(e) { 2265 if (doubleTap && !touch$$1.cancelBubble) { 2266 if (pointer) { 2267 if ((!edge) || e.pointerType === 'mouse') { return; } 2268 // work around .type being readonly with MSPointer* events 2269 var newTouch = {}, 2270 prop, i; 2271 2272 for (i in touch$$1) { 2273 prop = touch$$1[i]; 2274 newTouch[i] = prop && prop.bind ? prop.bind(touch$$1) : prop; 2275 } 2276 touch$$1 = newTouch; 2277 } 2278 touch$$1.type = 'dblclick'; 2279 handler(touch$$1); 2280 last = null; 2281 } 2282 } 2283 2284 obj[_pre + _touchstart + id] = onTouchStart; 2285 obj[_pre + _touchend + id] = onTouchEnd; 2286 obj[_pre + 'dblclick' + id] = handler; 2287 2288 obj.addEventListener(_touchstart, onTouchStart, false); 2289 obj.addEventListener(_touchend, onTouchEnd, false); 2290 2291 // On some platforms (notably, chrome<55 on win10 + touchscreen + mouse), 2292 // the browser doesn't fire touchend/pointerup events but does fire 2293 // native dblclicks. See #4127. 2294 // Edge 14 also fires native dblclicks, but only for pointerType mouse, see #5180. 2295 obj.addEventListener('dblclick', handler, false); 2296 2297 return this; 2298} 2299 2300function removeDoubleTapListener(obj, id) { 2301 var touchstart = obj[_pre + _touchstart + id], 2302 touchend = obj[_pre + _touchend + id], 2303 dblclick = obj[_pre + 'dblclick' + id]; 2304 2305 obj.removeEventListener(_touchstart, touchstart, false); 2306 obj.removeEventListener(_touchend, touchend, false); 2307 if (!edge) { 2308 obj.removeEventListener('dblclick', dblclick, false); 2309 } 2310 2311 return this; 2312} 2313 2314/* 2315 * @namespace DomUtil 2316 * 2317 * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) 2318 * tree, used by Leaflet internally. 2319 * 2320 * Most functions expecting or returning a `HTMLElement` also work for 2321 * SVG elements. The only difference is that classes refer to CSS classes 2322 * in HTML and SVG classes in SVG. 2323 */ 2324 2325 2326// @property TRANSFORM: String 2327// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit). 2328var TRANSFORM = testProp( 2329 ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']); 2330 2331// webkitTransition comes first because some browser versions that drop vendor prefix don't do 2332// the same for the transitionend event, in particular the Android 4.1 stock browser 2333 2334// @property TRANSITION: String 2335// Vendor-prefixed transition style name. 2336var TRANSITION = testProp( 2337 ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); 2338 2339// @property TRANSITION_END: String 2340// Vendor-prefixed transitionend event name. 2341var TRANSITION_END = 2342 TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend'; 2343 2344 2345// @function get(id: String|HTMLElement): HTMLElement 2346// Returns an element given its DOM id, or returns the element itself 2347// if it was passed directly. 2348function get(id) { 2349 return typeof id === 'string' ? document.getElementById(id) : id; 2350} 2351 2352// @function getStyle(el: HTMLElement, styleAttrib: String): String 2353// Returns the value for a certain style attribute on an element, 2354// including computed values or values set through CSS. 2355function getStyle(el, style) { 2356 var value = el.style[style] || (el.currentStyle && el.currentStyle[style]); 2357 2358 if ((!value || value === 'auto') && document.defaultView) { 2359 var css = document.defaultView.getComputedStyle(el, null); 2360 value = css ? css[style] : null; 2361 } 2362 return value === 'auto' ? null : value; 2363} 2364 2365// @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement 2366// Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element. 2367function create$1(tagName, className, container) { 2368 var el = document.createElement(tagName); 2369 el.className = className || ''; 2370 2371 if (container) { 2372 container.appendChild(el); 2373 } 2374 return el; 2375} 2376 2377// @function remove(el: HTMLElement) 2378// Removes `el` from its parent element 2379function remove(el) { 2380 var parent = el.parentNode; 2381 if (parent) { 2382 parent.removeChild(el); 2383 } 2384} 2385 2386// @function empty(el: HTMLElement) 2387// Removes all of `el`'s children elements from `el` 2388function empty(el) { 2389 while (el.firstChild) { 2390 el.removeChild(el.firstChild); 2391 } 2392} 2393 2394// @function toFront(el: HTMLElement)
vendor: 9,278 bytes, lines 2395-2691
2395// Makes `el` the last child of its parent, so it renders in front of the other children. 2396function toFront(el) { 2397 var parent = el.parentNode; 2398 if (parent.lastChild !== el) { 2399 parent.appendChild(el); 2400 } 2401} 2402 2403// @function toBack(el: HTMLElement) 2404// Makes `el` the first child of its parent, so it renders behind the other children. 2405function toBack(el) { 2406 var parent = el.parentNode; 2407 if (parent.firstChild !== el) { 2408 parent.insertBefore(el, parent.firstChild); 2409 } 2410} 2411 2412// @function hasClass(el: HTMLElement, name: String): Boolean 2413// Returns `true` if the element's class attribute contains `name`. 2414function hasClass(el, name) { 2415 if (el.classList !== undefined) { 2416 return el.classList.contains(name); 2417 } 2418 var className = getClass(el); 2419 return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); 2420} 2421 2422// @function addClass(el: HTMLElement, name: String) 2423// Adds `name` to the element's class attribute. 2424function addClass(el, name) { 2425 if (el.classList !== undefined) { 2426 var classes = splitWords(name); 2427 for (var i = 0, len = classes.length; i < len; i++) { 2428 el.classList.add(classes[i]); 2429 } 2430 } else if (!hasClass(el, name)) { 2431 var className = getClass(el); 2432 setClass(el, (className ? className + ' ' : '') + name); 2433 } 2434} 2435 2436// @function removeClass(el: HTMLElement, name: String) 2437// Removes `name` from the element's class attribute. 2438function removeClass(el, name) { 2439 if (el.classList !== undefined) { 2440 el.classList.remove(name); 2441 } else { 2442 setClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' '))); 2443 } 2444} 2445 2446// @function setClass(el: HTMLElement, name: String) 2447// Sets the element's class. 2448function setClass(el, name) { 2449 if (el.className.baseVal === undefined) { 2450 el.className = name; 2451 } else { 2452 // in case of SVG element 2453 el.className.baseVal = name; 2454 } 2455} 2456 2457// @function getClass(el: HTMLElement): String 2458// Returns the element's class. 2459function getClass(el) { 2460 return el.className.baseVal === undefined ? el.className : el.className.baseVal; 2461} 2462 2463// @function setOpacity(el: HTMLElement, opacity: Number) 2464// Set the opacity of an element (including old IE support). 2465// `opacity` must be a number from `0` to `1`. 2466function setOpacity(el, value) { 2467 if ('opacity' in el.style) { 2468 el.style.opacity = value; 2469 } else if ('filter' in el.style) { 2470 _setOpacityIE(el, value); 2471 } 2472} 2473 2474function _setOpacityIE(el, value) { 2475 var filter = false, 2476 filterName = 'DXImageTransform.Microsoft.Alpha'; 2477 2478 // filters collection throws an error if we try to retrieve a filter that doesn't exist 2479 try { 2480 filter = el.filters.item(filterName); 2481 } catch (e) { 2482 // don't set opacity to 1 if we haven't already set an opacity, 2483 // it isn't needed and breaks transparent pngs. 2484 if (value === 1) { return; } 2485 } 2486 2487 value = Math.round(value * 100); 2488 2489 if (filter) { 2490 filter.Enabled = (value !== 100); 2491 filter.Opacity = value; 2492 } else { 2493 el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; 2494 } 2495} 2496 2497// @function testProp(props: String[]): String|false 2498// Goes through the array of style names and returns the first name 2499// that is a valid style name for an element. If no such name is found, 2500// it returns false. Useful for vendor-prefixed styles like `transform`. 2501function testProp(props) { 2502 var style = document.documentElement.style; 2503 2504 for (var i = 0; i < props.length; i++) { 2505 if (props[i] in style) { 2506 return props[i]; 2507 } 2508 } 2509 return false; 2510} 2511 2512// @function setTransform(el: HTMLElement, offset: Point, scale?: Number) 2513// Resets the 3D CSS transform of `el` so it is translated by `offset` pixels 2514// and optionally scaled by `scale`. Does not have an effect if the 2515// browser doesn't support 3D CSS transforms. 2516function setTransform(el, offset, scale) { 2517 var pos = offset || new Point(0, 0); 2518 2519 el.style[TRANSFORM] = 2520 (ie3d ? 2521 'translate(' + pos.x + 'px,' + pos.y + 'px)' : 2522 'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') + 2523 (scale ? ' scale(' + scale + ')' : ''); 2524} 2525 2526// @function setPosition(el: HTMLElement, position: Point) 2527// Sets the position of `el` to coordinates specified by `position`, 2528// using CSS translate or top/left positioning depending on the browser 2529// (used by Leaflet internally to position its layers). 2530function setPosition(el, point) { 2531 2532 /*eslint-disable */ 2533 el._leaflet_pos = point; 2534 /* eslint-enable */ 2535 2536 if (any3d) { 2537 setTransform(el, point); 2538 } else { 2539 el.style.left = point.x + 'px'; 2540 el.style.top = point.y + 'px'; 2541 } 2542} 2543 2544// @function getPosition(el: HTMLElement): Point 2545// Returns the coordinates of an element previously positioned with setPosition. 2546function getPosition(el) { 2547 // this method is only used for elements previously positioned using setPosition, 2548 // so it's safe to cache the position for performance 2549 2550 return el._leaflet_pos || new Point(0, 0); 2551} 2552 2553// @function disableTextSelection() 2554// Prevents the user from generating `selectstart` DOM events, usually generated 2555// when the user drags the mouse through a page with text. Used internally 2556// by Leaflet to override the behaviour of any click-and-drag interaction on 2557// the map. Affects drag interactions on the whole document. 2558 2559// @function enableTextSelection() 2560// Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection). 2561var disableTextSelection; 2562var enableTextSelection; 2563var _userSelect; 2564if ('onselectstart' in document) { 2565 disableTextSelection = function () { 2566 on(window, 'selectstart', preventDefault); 2567 }; 2568 enableTextSelection = function () { 2569 off(window, 'selectstart', preventDefault); 2570 }; 2571} else { 2572 var userSelectProperty = testProp( 2573 ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); 2574 2575 disableTextSelection = function () { 2576 if (userSelectProperty) { 2577 var style = document.documentElement.style; 2578 _userSelect = style[userSelectProperty]; 2579 style[userSelectProperty] = 'none'; 2580 } 2581 }; 2582 enableTextSelection = function () { 2583 if (userSelectProperty) { 2584 document.documentElement.style[userSelectProperty] = _userSelect; 2585 _userSelect = undefined; 2586 } 2587 }; 2588} 2589 2590// @function disableImageDrag() 2591// As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but 2592// for `dragstart` DOM events, usually generated when the user drags an image. 2593function disableImageDrag() { 2594 on(window, 'dragstart', preventDefault); 2595} 2596 2597// @function enableImageDrag() 2598// Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection). 2599function enableImageDrag() { 2600 off(window, 'dragstart', preventDefault); 2601} 2602 2603var _outlineElement; 2604var _outlineStyle; 2605// @function preventOutline(el: HTMLElement) 2606// Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline) 2607// of the element `el` invisible. Used internally by Leaflet to prevent 2608// focusable elements from displaying an outline when the user performs a 2609// drag interaction on them. 2610function preventOutline(element) { 2611 while (element.tabIndex === -1) { 2612 element = element.parentNode; 2613 } 2614 if (!element.style) { return; } 2615 restoreOutline(); 2616 _outlineElement = element; 2617 _outlineStyle = element.style.outline; 2618 element.style.outline = 'none'; 2619 on(window, 'keydown', restoreOutline); 2620} 2621 2622// @function restoreOutline() 2623// Cancels the effects of a previous [`L.DomUtil.preventOutline`](). 2624function restoreOutline() { 2625 if (!_outlineElement) { return; } 2626 _outlineElement.style.outline = _outlineStyle; 2627 _outlineElement = undefined; 2628 _outlineStyle = undefined; 2629 off(window, 'keydown', restoreOutline); 2630} 2631 2632// @function getSizedParentNode(el: HTMLElement): HTMLElement 2633// Finds the closest parent node which size (width and height) is not null. 2634function getSizedParentNode(element) { 2635 do { 2636 element = element.parentNode; 2637 } while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body); 2638 return element; 2639} 2640 2641// @function getScale(el: HTMLElement): Object 2642// Computes the CSS scale currently applied on the element. 2643// Returns an object with `x` and `y` members as horizontal and vertical scales respectively, 2644// and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect). 2645function getScale(element) { 2646 var rect = element.getBoundingClientRect(); // Read-only in old browsers. 2647 2648 return { 2649 x: rect.width / element.offsetWidth || 1, 2650 y: rect.height / element.offsetHeight || 1, 2651 boundingClientRect: rect 2652 }; 2653} 2654 2655 2656var DomUtil = (Object.freeze || Object)({ 2657 TRANSFORM: TRANSFORM, 2658 TRANSITION: TRANSITION, 2659 TRANSITION_END: TRANSITION_END, 2660 get: get, 2661 getStyle: getStyle, 2662 create: create$1, 2663 remove: remove, 2664 empty: empty, 2665 toFront: toFront, 2666 toBack: toBack, 2667 hasClass: hasClass, 2668 addClass: addClass, 2669 removeClass: removeClass, 2670 setClass: setClass, 2671 getClass: getClass, 2672 setOpacity: setOpacity, 2673 testProp: testProp, 2674 setTransform: setTransform, 2675 setPosition: setPosition, 2676 getPosition: getPosition, 2677 disableTextSelection: disableTextSelection, 2678 enableTextSelection: enableTextSelection, 2679 disableImageDrag: disableImageDrag, 2680 enableImageDrag: enableImageDrag, 2681 preventOutline: preventOutline, 2682 restoreOutline: restoreOutline, 2683 getSizedParentNode: getSizedParentNode, 2684 getScale: getScale 2685}); 2686 2687/* 2688 * @namespace DomEvent 2689 * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally. 2690 */ 2691
2692// Inspired by John Resig, Dean Edwards and YUI addEvent implementations. 2693 2694// @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this 2695// Adds a listener function (`fn`) to a particular DOM event type of the 2696// element `el`. You can optionally specify the context of the listener 2697// (object the `this` keyword will point to). You can also pass several 2698// space-separated types (e.g. `'click dblclick'`). 2699 2700// @alternative 2701// @function on(el: HTMLElement, eventMap: Object, context?: Object): this 2702// Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` 2703function on(obj, types, fn, context) { 2704 2705 if (typeof types === 'object') { 2706 for (var type in types) { 2707 addOne(obj, type, types[type], fn); 2708 } 2709 } else { 2710 types = splitWords(types); 2711 2712 for (var i = 0, len = types.length; i < len; i++) { 2713 addOne(obj, types[i], fn, context); 2714 } 2715 } 2716 2717 return this; 2718} 2719 2720var eventsKey = '_leaflet_events'; 2721 2722// @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this 2723// Removes a previously added listener function. 2724// Note that if you passed a custom context to on, you must pass the same 2725// context to `off` in order to remove the listener. 2726 2727// @alternative 2728// @function off(el: HTMLElement, eventMap: Object, context?: Object): this 2729// Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` 2730function off(obj, types, fn, context) { 2731 2732 if (typeof types === 'object') { 2733 for (var type in types) { 2734 removeOne(obj, type, types[type], fn); 2735 } 2736 } else if (types) { 2737 types = splitWords(types); 2738 2739 for (var i = 0, len = types.length; i < len; i++) { 2740 removeOne(obj, types[i], fn, context); 2741 } 2742 } else { 2743 for (var j in obj[eventsKey]) { 2744 removeOne(obj, j, obj[eventsKey][j]); 2745 } 2746 delete obj[eventsKey]; 2747 } 2748 2749 return this; 2750} 2751 2752function addOne(obj, type, fn, context) { 2753 var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''); 2754 2755 if (obj[eventsKey] && obj[eventsKey][id]) { return this; } 2756 2757 var handler = function (e) { 2758 return fn.call(context || obj, e || window.event); 2759 }; 2760 2761 var originalHandler = handler; 2762 2763 if (pointer && type.indexOf('touch') === 0) { 2764 // Needs DomEvent.Pointer.js 2765 addPointerListener(obj, type, handler, id); 2766 2767 } else if (touch && (type === 'dblclick') && addDoubleTapListener && 2768 !(pointer && chrome)) { 2769 // Chrome >55 does not need the synthetic dblclicks from addDoubleTapListener 2770 // See #5180 2771 addDoubleTapListener(obj, handler, id); 2772 2773 } else if ('addEventListener' in obj) { 2774 2775 if (type === 'mousewheel') { 2776 obj.addEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false); 2777 2778 } else if ((type === 'mouseenter') || (type === 'mouseleave')) { 2779 handler = function (e) { 2780 e = e || window.event; 2781 if (isExternalTarget(obj, e)) { 2782 originalHandler(e); 2783 } 2784 }; 2785 obj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false); 2786 2787 } else { 2788 if (type === 'click' && android) { 2789 handler = function (e) { 2790 filterClick(e, originalHandler); 2791 }; 2792 } 2793 obj.addEventListener(type, handler, false); 2794 } 2795 2796 } else if ('attachEvent' in obj) { 2797 obj.attachEvent('on' + type, handler); 2798 } 2799 2800 obj[eventsKey] = obj[eventsKey] || {}; 2801 obj[eventsKey][id] = handler; 2802} 2803 2804function removeOne(obj, type, fn, context) { 2805 2806 var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''), 2807 handler = obj[eventsKey] && obj[eventsKey][id]; 2808 2809 if (!handler) { return this; } 2810 2811 if (pointer && type.indexOf('touch') === 0) { 2812 removePointerListener(obj, type, id); 2813 2814 } else if (touch && (type === 'dblclick') && removeDoubleTapListener && 2815 !(pointer && chrome)) { 2816 removeDoubleTapListener(obj, id); 2817 2818 } else if ('removeEventListener' in obj) { 2819 2820 if (type === 'mousewheel') { 2821 obj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false); 2822 2823 } else { 2824 obj.removeEventListener( 2825 type === 'mouseenter' ? 'mouseover' : 2826 type === 'mouseleave' ? 'mouseout' : type, handler, false); 2827 } 2828 2829 } else if ('detachEvent' in obj) { 2830 obj.detachEvent('on' + type, handler); 2831 } 2832 2833 obj[eventsKey][id] = null; 2834} 2835 2836// @function stopPropagation(ev: DOMEvent): this 2837// Stop the given event from propagation to parent elements. Used inside the listener functions: 2838// ```js 2839// L.DomEvent.on(div, 'click', function (ev) { 2840// L.DomEvent.stopPropagation(ev); 2841// }); 2842// ``` 2843function stopPropagation(e) { 2844 2845 if (e.stopPropagation) { 2846 e.stopPropagation(); 2847 } else if (e.originalEvent) { // In case of Leaflet event. 2848 e.originalEvent._stopped = true; 2849 } else { 2850 e.cancelBubble = true; 2851 } 2852 skipped(e); 2853 2854 return this; 2855} 2856 2857// @function disableScrollPropagation(el: HTMLElement): this 2858// Adds `stopPropagation` to the element's `'mousewheel'` events (plus browser variants). 2859function disableScrollPropagation(el) { 2860 addOne(el, 'mousewheel', stopPropagation); 2861 return this; 2862} 2863 2864// @function disableClickPropagation(el: HTMLElement): this 2865// Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`, 2866// `'mousedown'` and `'touchstart'` events (plus browser variants). 2867function disableClickPropagation(el) { 2868 on(el, 'mousedown touchstart dblclick', stopPropagation); 2869 addOne(el, 'click', fakeStop); 2870 return this; 2871} 2872 2873// @function preventDefault(ev: DOMEvent): this 2874// Prevents the default action of the DOM Event `ev` from happening (such as 2875// following a link in the href of the a element, or doing a POST request 2876// with page reload when a `<form>` is submitted). 2877// Use it inside listener functions. 2878function preventDefault(e) { 2879 if (e.preventDefault) { 2880 e.preventDefault(); 2881 } else { 2882 e.returnValue = false;
2883 } 2884 return this; 2885} 2886 2887// @function stop(ev: DOMEvent): this 2888// Does `stopPropagation` and `preventDefault` at the same time. 2889function stop(e) { 2890 preventDefault(e); 2891 stopPropagation(e); 2892 return this; 2893} 2894 2895// @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point 2896// Gets normalized mouse position from a DOM event relative to the 2897// `container` (border excluded) or to the whole page if not specified. 2898function getMousePosition(e, container) { 2899 if (!container) { 2900 return new Point(e.clientX, e.clientY); 2901 } 2902 2903 var scale = getScale(container), 2904 offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y) 2905 2906 return new Point( 2907 // offset.left/top values are in page scale (like clientX/Y), 2908 // whereas clientLeft/Top (border width) values are the original values (before CSS scale applies). 2909 (e.clientX - offset.left) / scale.x - container.clientLeft, 2910 (e.clientY - offset.top) / scale.y - container.clientTop 2911 ); 2912} 2913 2914// Chrome on Win scrolls double the pixels as in other platforms (see #4538), 2915// and Firefox scrolls device pixels, not CSS pixels 2916var wheelPxFactor = 2917 (win && chrome) ? 2 * window.devicePixelRatio : 2918 gecko ? window.devicePixelRatio : 1; 2919 2920// @function getWheelDelta(ev: DOMEvent): Number 2921// Gets normalized wheel delta from a mousewheel DOM event, in vertical 2922// pixels scrolled (negative if scrolling down). 2923// Events from pointing devices without precise scrolling are mapped to 2924// a best guess of 60 pixels. 2925function getWheelDelta(e) { 2926 return (edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta 2927 (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels 2928 (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines 2929 (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages 2930 (e.deltaX || e.deltaZ) ? 0 : // Skip horizontal/depth wheel events
2931 e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels 2932 (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines 2933 e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages 2934 0; 2935} 2936 2937var skipEvents = {}; 2938 2939function fakeStop(e) { 2940 // fakes stopPropagation by setting a special event flag, checked/reset with skipped(e) 2941 skipEvents[e.type] = true; 2942} 2943 2944function skipped(e) { 2945 var events = skipEvents[e.type]; 2946 // reset when checking, as it's only used in map container and propagates outside of the map 2947 skipEvents[e.type] = false; 2948 return events; 2949} 2950 2951// check if element really left/entered the event target (for mouseenter/mouseleave) 2952function isExternalTarget(el, e) { 2953 2954 var related = e.relatedTarget; 2955 2956 if (!related) { return true; } 2957 2958 try { 2959 while (related && (related !== el)) { 2960 related = related.parentNode; 2961 } 2962 } catch (err) { 2963 return false; 2964 } 2965 return (related !== el); 2966} 2967 2968var lastClick; 2969 2970// this is a horrible workaround for a bug in Android where a single touch triggers two click events 2971function filterClick(e, handler) { 2972 var timeStamp = (e.timeStamp || (e.originalEvent && e.originalEvent.timeStamp)), 2973 elapsed = lastClick && (timeStamp - lastClick); 2974 2975 // are they closer together than 500ms yet more than 100ms? 2976 // Android typically triggers them ~300ms apart while multiple listeners 2977 // on the same event should be triggered far faster; 2978 // or check if click is simulated on the element, and if it is, reject any non-simulated events 2979 2980 if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) { 2981 stop(e); 2982 return; 2983 } 2984 lastClick = timeStamp; 2985 2986 handler(e); 2987} 2988 2989 2990 2991 2992var DomEvent = (Object.freeze || Object)({ 2993 on: on, 2994 off: off, 2995 stopPropagation: stopPropagation, 2996 disableScrollPropagation: disableScrollPropagation, 2997 disableClickPropagation: disableClickPropagation, 2998 preventDefault: preventDefault, 2999 stop: stop, 3000 getMousePosition: getMousePosition, 3001 getWheelDelta: getWheelDelta, 3002 fakeStop: fakeStop, 3003 skipped: skipped, 3004 isExternalTarget: isExternalTarget, 3005 addListener: on, 3006 removeListener: off 3007}); 3008 3009/* 3010 * @class PosAnimation 3011 * @aka L.PosAnimation 3012 * @inherits Evented 3013 * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9. 3014 * 3015 * @example 3016 * ```js 3017 * var fx = new L.PosAnimation(); 3018 * fx.run(el, [300, 500], 0.5); 3019 * ``` 3020 * 3021 * @constructor L.PosAnimation() 3022 * Creates a `PosAnimation` object. 3023 * 3024 */ 3025 3026var PosAnimation = Evented.extend({ 3027 3028 // @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number) 3029 // Run an animation of a given element to a new position, optionally setting 3030 // duration in seconds (`0.25` by default) and easing linearity factor (3rd 3031 // argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1), 3032 // `0.5` by default). 3033 run: function (el, newPos, duration, easeLinearity) { 3034 this.stop(); 3035 3036 this._el = el; 3037 this._inProgress = true; 3038 this._duration = duration || 0.25; 3039 this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2); 3040 3041 this._startPos = getPosition(el); 3042 this._offset = newPos.subtract(this._startPos); 3043 this._startTime = +new Date(); 3044 3045 // @event start: Event 3046 // Fired when the animation starts 3047 this.fire('start'); 3048 3049 this._animate(); 3050 }, 3051 3052 // @method stop() 3053 // Stops the animation (if currently running). 3054 stop: function () { 3055 if (!this._inProgress) { return; } 3056 3057 this._step(true); 3058 this._complete(); 3059 }, 3060 3061 _animate: function () { 3062 // animation loop 3063 this._animId = requestAnimFrame(this._animate, this); 3064 this._step(); 3065 }, 3066 3067 _step: function (round) { 3068 var elapsed = (+new Date()) - this._startTime, 3069 duration = this._duration * 1000; 3070 3071 if (elapsed < duration) { 3072 this._runFrame(this._easeOut(elapsed / duration), round); 3073 } else { 3074 this._runFrame(1); 3075 this._complete(); 3076 } 3077 }, 3078 3079 _runFrame: function (progress, round) { 3080 var pos = this._startPos.add(this._offset.multiplyBy(progress)); 3081 if (round) { 3082 pos._round(); 3083 } 3084 setPosition(this._el, pos); 3085 3086 // @event step: Event 3087 // Fired continuously during the animation. 3088 this.fire('step'); 3089 }, 3090 3091 _complete: function () {
vendor: 18,113 bytes, lines 3092-3664
3092 cancelAnimFrame(this._animId); 3093 3094 this._inProgress = false; 3095 // @event end: Event 3096 // Fired when the animation ends. 3097 this.fire('end'); 3098 }, 3099 3100 _easeOut: function (t) { 3101 return 1 - Math.pow(1 - t, this._easeOutPower); 3102 } 3103}); 3104 3105/* 3106 * @class Map 3107 * @aka L.Map 3108 * @inherits Evented 3109 * 3110 * The central class of the API â it is used to create a map on a page and manipulate it. 3111 * 3112 * @example 3113 * 3114 * ```js 3115 * // initialize the map on the "map" div with a given center and zoom 3116 * var map = L.map('map', { 3117 * center: [51.505, -0.09], 3118 * zoom: 13 3119 * }); 3120 * ``` 3121 * 3122 */ 3123 3124var Map = Evented.extend({ 3125 3126 options: { 3127 // @section Map State Options 3128 // @option crs: CRS = L.CRS.EPSG3857 3129 // The [Coordinate Reference System](#crs) to use. Don't change this if you're not 3130 // sure what it means. 3131 crs: EPSG3857, 3132 3133 // @option center: LatLng = undefined 3134 // Initial geographic center of the map 3135 center: undefined, 3136 3137 // @option zoom: Number = undefined 3138 // Initial map zoom level 3139 zoom: undefined, 3140 3141 // @option minZoom: Number = * 3142 // Minimum zoom level of the map. 3143 // If not specified and at least one `GridLayer` or `TileLayer` is in the map, 3144 // the lowest of their `minZoom` options will be used instead. 3145 minZoom: undefined, 3146 3147 // @option maxZoom: Number = * 3148 // Maximum zoom level of the map. 3149 // If not specified and at least one `GridLayer` or `TileLayer` is in the map, 3150 // the highest of their `maxZoom` options will be used instead. 3151 maxZoom: undefined, 3152 3153 // @option layers: Layer[] = [] 3154 // Array of layers that will be added to the map initially 3155 layers: [], 3156 3157 // @option maxBounds: LatLngBounds = null 3158 // When this option is set, the map restricts the view to the given 3159 // geographical bounds, bouncing the user back if the user tries to pan 3160 // outside the view. To set the restriction dynamically, use 3161 // [`setMaxBounds`](#map-setmaxbounds) method. 3162 maxBounds: undefined, 3163 3164 // @option renderer: Renderer = * 3165 // The default method for drawing vector layers on the map. `L.SVG` 3166 // or `L.Canvas` by default depending on browser support. 3167 renderer: undefined, 3168 3169 3170 // @section Animation Options 3171 // @option zoomAnimation: Boolean = true 3172 // Whether the map zoom animation is enabled. By default it's enabled 3173 // in all browsers that support CSS3 Transitions except Android. 3174 zoomAnimation: true, 3175 3176 // @option zoomAnimationThreshold: Number = 4 3177 // Won't animate zoom if the zoom difference exceeds this value. 3178 zoomAnimationThreshold: 4, 3179 3180 // @option fadeAnimation: Boolean = true 3181 // Whether the tile fade animation is enabled. By default it's enabled 3182 // in all browsers that support CSS3 Transitions except Android. 3183 fadeAnimation: true, 3184 3185 // @option markerZoomAnimation: Boolean = true 3186 // Whether markers animate their zoom with the zoom animation, if disabled 3187 // they will disappear for the length of the animation. By default it's 3188 // enabled in all browsers that support CSS3 Transitions except Android. 3189 markerZoomAnimation: true, 3190 3191 // @option transform3DLimit: Number = 2^23 3192 // Defines the maximum size of a CSS translation transform. The default 3193 // value should not be changed unless a web browser positions layers in 3194 // the wrong place after doing a large `panBy`. 3195 transform3DLimit: 8388608, // Precision limit of a 32-bit float 3196 3197 // @section Interaction Options 3198 // @option zoomSnap: Number = 1 3199 // Forces the map's zoom level to always be a multiple of this, particularly 3200 // right after a [`fitBounds()`](#map-fitbounds) or a pinch-zoom. 3201 // By default, the zoom level snaps to the nearest integer; lower values 3202 // (e.g. `0.5` or `0.1`) allow for greater granularity. A value of `0` 3203 // means the zoom level will not be snapped after `fitBounds` or a pinch-zoom. 3204 zoomSnap: 1, 3205 3206 // @option zoomDelta: Number = 1 3207 // Controls how much the map's zoom level will change after a 3208 // [`zoomIn()`](#map-zoomin), [`zoomOut()`](#map-zoomout), pressing `+` 3209 // or `-` on the keyboard, or using the [zoom controls](#control-zoom). 3210 // Values smaller than `1` (e.g. `0.5`) allow for greater granularity. 3211 zoomDelta: 1, 3212 3213 // @option trackResize: Boolean = true 3214 // Whether the map automatically handles browser window resize to update itself. 3215 trackResize: true 3216 }, 3217 3218 initialize: function (id, options) { // (HTMLElement or String, Object) 3219 options = setOptions(this, options); 3220 3221 this._initContainer(id); 3222 this._initLayout(); 3223 3224 // hack for https://github.com/Leaflet/Leaflet/issues/1980 3225 this._onResize = bind(this._onResize, this); 3226 3227 this._initEvents(); 3228 3229 if (options.maxBounds) { 3230 this.setMaxBounds(options.maxBounds); 3231 } 3232 3233 if (options.zoom !== undefined) { 3234 this._zoom = this._limitZoom(options.zoom); 3235 } 3236 3237 if (options.center && options.zoom !== undefined) { 3238 this.setView(toLatLng(options.center), options.zoom, {reset: true}); 3239 } 3240 3241 this._handlers = []; 3242 this._layers = {}; 3243 this._zoomBoundLayers = {}; 3244 this._sizeChanged = true; 3245 3246 this.callInitHooks(); 3247 3248 // don't animate on browsers without hardware-accelerated transitions or old Android/Opera 3249 this._zoomAnimated = TRANSITION && any3d && !mobileOpera && 3250 this.options.zoomAnimation; 3251 3252 // zoom transitions run with the same duration for all layers, so if one of transitionend events 3253 // happens after starting zoom animation (propagating to the map pane), we know that it ended globally 3254 if (this._zoomAnimated) { 3255 this._createAnimProxy(); 3256 on(this._proxy, TRANSITION_END, this._catchTransitionEnd, this); 3257 } 3258 3259 this._addLayers(this.options.layers); 3260 }, 3261 3262 3263 // @section Methods for modifying map state 3264 3265 // @method setView(center: LatLng, zoom: Number, options?: Zoom/pan options): this 3266 // Sets the view of the map (geographical center and zoom) with the given 3267 // animation options. 3268 setView: function (center, zoom, options) { 3269 3270 zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom); 3271 center = this._limitCenter(toLatLng(center), zoom, this.options.maxBounds); 3272 options = options || {}; 3273 3274 this._stop(); 3275 3276 if (this._loaded && !options.reset && options !== true) { 3277 3278 if (options.animate !== undefined) { 3279 options.zoom = extend({animate: options.animate}, options.zoom); 3280 options.pan = extend({animate: options.animate, duration: options.duration}, options.pan); 3281 } 3282 3283 // try animating pan or zoom 3284 var moved = (this._zoom !== zoom) ? 3285 this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) : 3286 this._tryAnimatedPan(center, options.pan); 3287 3288 if (moved) { 3289 // prevent resize handler call, the view will refresh after animation anyway 3290 clearTimeout(this._sizeTimer); 3291 return this; 3292 } 3293 } 3294 3295 // animation didn't start, just reset the map view 3296 this._resetView(center, zoom); 3297 3298 return this; 3299 }, 3300 3301 // @method setZoom(zoom: Number, options?: Zoom/pan options): this 3302 // Sets the zoom of the map. 3303 setZoom: function (zoom, options) { 3304 if (!this._loaded) { 3305 this._zoom = zoom; 3306 return this; 3307 } 3308 return this.setView(this.getCenter(), zoom, {zoom: options}); 3309 }, 3310 3311 // @method zoomIn(delta?: Number, options?: Zoom options): this 3312 // Increases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default). 3313 zoomIn: function (delta, options) { 3314 delta = delta || (any3d ? this.options.zoomDelta : 1); 3315 return this.setZoom(this._zoom + delta, options); 3316 }, 3317 3318 // @method zoomOut(delta?: Number, options?: Zoom options): this 3319 // Decreases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default). 3320 zoomOut: function (delta, options) { 3321 delta = delta || (any3d ? this.options.zoomDelta : 1); 3322 return this.setZoom(this._zoom - delta, options); 3323 }, 3324 3325 // @method setZoomAround(latlng: LatLng, zoom: Number, options: Zoom options): this 3326 // Zooms the map while keeping a specified geographical point on the map 3327 // stationary (e.g. used internally for scroll zoom and double-click zoom). 3328 // @alternative 3329 // @method setZoomAround(offset: Point, zoom: Number, options: Zoom options): this 3330 // Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary. 3331 setZoomAround: function (latlng, zoom, options) { 3332 var scale = this.getZoomScale(zoom), 3333 viewHalf = this.getSize().divideBy(2), 3334 containerPoint = latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng), 3335 3336 centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale), 3337 newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset)); 3338 3339 return this.setView(newCenter, zoom, {zoom: options}); 3340 }, 3341 3342 _getBoundsCenterZoom: function (bounds, options) { 3343 3344 options = options || {}; 3345 bounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds); 3346 3347 var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]), 3348 paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]), 3349 3350 zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR)); 3351 3352 zoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom; 3353 3354 if (zoom === Infinity) { 3355 return { 3356 center: bounds.getCenter(), 3357 zoom: zoom 3358 }; 3359 } 3360 3361 var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), 3362 3363 swPoint = this.project(bounds.getSouthWest(), zoom), 3364 nePoint = this.project(bounds.getNorthEast(), zoom), 3365 center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom); 3366 3367 return { 3368 center: center, 3369 zoom: zoom 3370 }; 3371 }, 3372 3373 // @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this 3374 // Sets a map view that contains the given geographical bounds with the 3375 // maximum zoom level possible. 3376 fitBounds: function (bounds, options) { 3377 3378 bounds = toLatLngBounds(bounds); 3379 3380 if (!bounds.isValid()) { 3381 throw new Error('Bounds are not valid.'); 3382 } 3383 3384 var target = this._getBoundsCenterZoom(bounds, options); 3385 return this.setView(target.center, target.zoom, options); 3386 }, 3387 3388 // @method fitWorld(options?: fitBounds options): this 3389 // Sets a map view that mostly contains the whole world with the maximum 3390 // zoom level possible. 3391 fitWorld: function (options) { 3392 return this.fitBounds([[-90, -180], [90, 180]], options); 3393 }, 3394 3395 // @method panTo(latlng: LatLng, options?: Pan options): this 3396 // Pans the map to a given center. 3397 panTo: function (center, options) { // (LatLng) 3398 return this.setView(center, this._zoom, {pan: options}); 3399 }, 3400 3401 // @method panBy(offset: Point, options?: Pan options): this 3402 // Pans the map by a given number of pixels (animated). 3403 panBy: function (offset, options) { 3404 offset = toPoint(offset).round(); 3405 options = options || {}; 3406 3407 if (!offset.x && !offset.y) { 3408 return this.fire('moveend'); 3409 } 3410 // If we pan too far, Chrome gets issues with tiles 3411 // and makes them disappear or appear in the wrong place (slightly offset) #2602 3412 if (options.animate !== true && !this.getSize().contains(offset)) { 3413 this._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom()); 3414 return this; 3415 } 3416 3417 if (!this._panAnim) { 3418 this._panAnim = new PosAnimation(); 3419 3420 this._panAnim.on({ 3421 'step': this._onPanTransitionStep, 3422 'end': this._onPanTransitionEnd 3423 }, this); 3424 } 3425 3426 // don't fire movestart if animating inertia 3427 if (!options.noMoveStart) { 3428 this.fire('movestart'); 3429 } 3430 3431 // animate pan unless animate: false specified 3432 if (options.animate !== false) { 3433 addClass(this._mapPane, 'leaflet-pan-anim'); 3434 3435 var newPos = this._getMapPanePos().subtract(offset).round(); 3436 this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity); 3437 } else { 3438 this._rawPanBy(offset); 3439 this.fire('move').fire('moveend'); 3440 } 3441 3442 return this; 3443 }, 3444 3445 // @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this 3446 // Sets the view of the map (geographical center and zoom) performing a smooth 3447 // pan-zoom animation. 3448 flyTo: function (targetCenter, targetZoom, options) { 3449 3450 options = options || {}; 3451 if (options.animate === false || !any3d) { 3452 return this.setView(targetCenter, targetZoom, options); 3453 } 3454 3455 this._stop(); 3456 3457 var from = this.project(this.getCenter()), 3458 to = this.project(targetCenter), 3459 size = this.getSize(), 3460 startZoom = this._zoom; 3461 3462 targetCenter = toLatLng(targetCenter); 3463 targetZoom = targetZoom === undefined ? startZoom : targetZoom; 3464 3465 var w0 = Math.max(size.x, size.y), 3466 w1 = w0 * this.getZoomScale(startZoom, targetZoom), 3467 u1 = (to.distanceTo(from)) || 1, 3468 rho = 1.42, 3469 rho2 = rho * rho; 3470 3471 function r(i) { 3472 var s1 = i ? -1 : 1, 3473 s2 = i ? w1 : w0, 3474 t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1, 3475 b1 = 2 * s2 * rho2 * u1, 3476 b = t1 / b1, 3477 sq = Math.sqrt(b * b + 1) - b; 3478 3479 // workaround for floating point precision bug when sq = 0, log = -Infinite, 3480 // thus triggering an infinite loop in flyTo 3481 var log = sq < 0.000000001 ? -18 : Math.log(sq); 3482 3483 return log; 3484 } 3485 3486 function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; } 3487 function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; } 3488 function tanh(n) { return sinh(n) / cosh(n); } 3489 3490 var r0 = r(0); 3491 3492 function w(s) { return w0 * (cosh(r0) / cosh(r0 + rho * s)); } 3493 function u(s) { return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2; } 3494 3495 function easeOut(t) { return 1 - Math.pow(1 - t, 1.5); } 3496 3497 var start = Date.now(), 3498 S = (r(1) - r0) / rho, 3499 duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8; 3500 3501 function frame() { 3502 var t = (Date.now() - start) / duration, 3503 s = easeOut(t) * S; 3504 3505 if (t <= 1) { 3506 this._flyToFrame = requestAnimFrame(frame, this); 3507 3508 this._move( 3509 this.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom), 3510 this.getScaleZoom(w0 / w(s), startZoom), 3511 {flyTo: true}); 3512 3513 } else { 3514 this 3515 ._move(targetCenter, targetZoom) 3516 ._moveEnd(true); 3517 } 3518 } 3519 3520 this._moveStart(true, options.noMoveStart); 3521 3522 frame.call(this); 3523 return this; 3524 }, 3525 3526 // @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this 3527 // Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto), 3528 // but takes a bounds parameter like [`fitBounds`](#map-fitbounds). 3529 flyToBounds: function (bounds, options) { 3530 var target = this._getBoundsCenterZoom(bounds, options); 3531 return this.flyTo(target.center, target.zoom, options); 3532 }, 3533 3534 // @method setMaxBounds(bounds: Bounds): this 3535 // Restricts the map view to the given bounds (see the [maxBounds](#map-maxbounds) option). 3536 setMaxBounds: function (bounds) { 3537 bounds = toLatLngBounds(bounds); 3538 3539 if (!bounds.isValid()) { 3540 this.options.maxBounds = null; 3541 return this.off('moveend', this._panInsideMaxBounds); 3542 } else if (this.options.maxBounds) { 3543 this.off('moveend', this._panInsideMaxBounds); 3544 } 3545 3546 this.options.maxBounds = bounds; 3547 3548 if (this._loaded) { 3549 this._panInsideMaxBounds(); 3550 } 3551 3552 return this.on('moveend', this._panInsideMaxBounds); 3553 }, 3554 3555 // @method setMinZoom(zoom: Number): this 3556 // Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option). 3557 setMinZoom: function (zoom) { 3558 var oldZoom = this.options.minZoom; 3559 this.options.minZoom = zoom; 3560 3561 if (this._loaded && oldZoom !== zoom) { 3562 this.fire('zoomlevelschange'); 3563 3564 if (this.getZoom() < this.options.minZoom) { 3565 return this.setZoom(zoom); 3566 } 3567 } 3568 3569 return this; 3570 }, 3571 3572 // @method setMaxZoom(zoom: Number): this 3573 // Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option). 3574 setMaxZoom: function (zoom) { 3575 var oldZoom = this.options.maxZoom; 3576 this.options.maxZoom = zoom; 3577 3578 if (this._loaded && oldZoom !== zoom) { 3579 this.fire('zoomlevelschange'); 3580 3581 if (this.getZoom() > this.options.maxZoom) { 3582 return this.setZoom(zoom); 3583 } 3584 } 3585 3586 return this; 3587 }, 3588 3589 // @method panInsideBounds(bounds: LatLngBounds, options?: Pan options): this 3590 // 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. 3591 panInsideBounds: function (bounds, options) { 3592 this._enforcingBounds = true; 3593 var center = this.getCenter(), 3594 newCenter = this._limitCenter(center, this._zoom, toLatLngBounds(bounds)); 3595 3596 if (!center.equals(newCenter)) { 3597 this.panTo(newCenter, options); 3598 } 3599 3600 this._enforcingBounds = false; 3601 return this; 3602 }, 3603 3604 // @method invalidateSize(options: Zoom/pan options): this 3605 // Checks if the map container size changed and updates the map if so â 3606 // call it after you've changed the map size dynamically, also animating 3607 // pan by default. If `options.pan` is `false`, panning will not occur. 3608 // If `options.debounceMoveend` is `true`, it will delay `moveend` event so 3609 // that it doesn't happen often even if the method is called many 3610 // times in a row. 3611 3612 // @alternative 3613 // @method invalidateSize(animate: Boolean): this 3614 // Checks if the map container size changed and updates the map if so â 3615 // call it after you've changed the map size dynamically, also animating 3616 // pan by default. 3617 invalidateSize: function (options) { 3618 if (!this._loaded) { return this; } 3619 3620 options = extend({ 3621 animate: false, 3622 pan: true 3623 }, options === true ? {animate: true} : options); 3624 3625 var oldSize = this.getSize(); 3626 this._sizeChanged = true; 3627 this._lastCenter = null; 3628 3629 var newSize = this.getSize(), 3630 oldCenter = oldSize.divideBy(2).round(), 3631 newCenter = newSize.divideBy(2).round(), 3632 offset = oldCenter.subtract(newCenter); 3633 3634 if (!offset.x && !offset.y) { return this; } 3635 3636 if (options.animate && options.pan) { 3637 this.panBy(offset); 3638 3639 } else { 3640 if (options.pan) { 3641 this._rawPanBy(offset); 3642 } 3643 3644 this.fire('move'); 3645 3646 if (options.debounceMoveend) { 3647 clearTimeout(this._sizeTimer); 3648 this._sizeTimer = setTimeout(bind(this.fire, this, 'moveend'), 200); 3649 } else { 3650 this.fire('moveend'); 3651 } 3652 } 3653 3654 // @section Map state change events 3655 // @event resize: ResizeEvent 3656 // Fired when the map is resized. 3657 return this.fire('resize', { 3658 oldSize: oldSize, 3659 newSize: newSize 3660 }); 3661 }, 3662 3663 // @section Methods for modifying map state 3664 // @method stop(): this
3665 // Stops the currently running `panTo` or `flyTo` animation, if any. 3666 stop: function () { 3667 this.setZoom(this._limitZoom(this._zoom)); 3668 if (!this.options.zoomSnap) { 3669 this.fire('viewreset'); 3670 } 3671 return this._stop(); 3672 }, 3673 3674 // @section Geolocation methods 3675 // @method locate(options?: Locate options): this 3676 // Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound) 3677 // event with location data on success or a [`locationerror`](#map-locationerror) event on failure, 3678 // and optionally sets the map view to the user's location with respect to 3679 // detection accuracy (or to the world view if geolocation failed). 3680 // Note that, if your page doesn't use HTTPS, this method will fail in 3681 // modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins)) 3682 // See `Locate options` for more details. 3683 locate: function (options) { 3684 3685 options = this._locateOptions = extend({ 3686 timeout: 10000, 3687 watch: false 3688 // setView: false 3689 // maxZoom: <Number> 3690 // maximumAge: 0
vendor: 21,622 bytes, lines 3691-4360
3691 // enableHighAccuracy: false 3692 }, options); 3693 3694 if (!('geolocation' in navigator)) { 3695 this._handleGeolocationError({ 3696 code: 0, 3697 message: 'Geolocation not supported.' 3698 }); 3699 return this; 3700 } 3701 3702 var onResponse = bind(this._handleGeolocationResponse, this), 3703 onError = bind(this._handleGeolocationError, this); 3704 3705 if (options.watch) { 3706 this._locationWatchId = 3707 navigator.geolocation.watchPosition(onResponse, onError, options); 3708 } else { 3709 navigator.geolocation.getCurrentPosition(onResponse, onError, options); 3710 } 3711 return this; 3712 }, 3713 3714 // @method stopLocate(): this 3715 // Stops watching location previously initiated by `map.locate({watch: true})` 3716 // and aborts resetting the map view if map.locate was called with 3717 // `{setView: true}`. 3718 stopLocate: function () { 3719 if (navigator.geolocation && navigator.geolocation.clearWatch) { 3720 navigator.geolocation.clearWatch(this._locationWatchId); 3721 } 3722 if (this._locateOptions) { 3723 this._locateOptions.setView = false; 3724 } 3725 return this; 3726 }, 3727 3728 _handleGeolocationError: function (error) { 3729 var c = error.code, 3730 message = error.message || 3731 (c === 1 ? 'permission denied' : 3732 (c === 2 ? 'position unavailable' : 'timeout')); 3733 3734 if (this._locateOptions.setView && !this._loaded) { 3735 this.fitWorld(); 3736 } 3737 3738 // @section Location events 3739 // @event locationerror: ErrorEvent 3740 // Fired when geolocation (using the [`locate`](#map-locate) method) failed. 3741 this.fire('locationerror', { 3742 code: c, 3743 message: 'Geolocation error: ' + message + '.' 3744 }); 3745 }, 3746 3747 _handleGeolocationResponse: function (pos) { 3748 var lat = pos.coords.latitude, 3749 lng = pos.coords.longitude, 3750 latlng = new LatLng(lat, lng), 3751 bounds = latlng.toBounds(pos.coords.accuracy * 2), 3752 options = this._locateOptions; 3753 3754 if (options.setView) { 3755 var zoom = this.getBoundsZoom(bounds); 3756 this.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom); 3757 } 3758 3759 var data = { 3760 latlng: latlng, 3761 bounds: bounds, 3762 timestamp: pos.timestamp 3763 }; 3764 3765 for (var i in pos.coords) { 3766 if (typeof pos.coords[i] === 'number') { 3767 data[i] = pos.coords[i]; 3768 } 3769 } 3770 3771 // @event locationfound: LocationEvent 3772 // Fired when geolocation (using the [`locate`](#map-locate) method) 3773 // went successfully. 3774 this.fire('locationfound', data); 3775 }, 3776 3777 // TODO Appropriate docs section? 3778 // @section Other Methods 3779 // @method addHandler(name: String, HandlerClass: Function): this 3780 // Adds a new `Handler` to the map, given its name and constructor function. 3781 addHandler: function (name, HandlerClass) { 3782 if (!HandlerClass) { return this; } 3783 3784 var handler = this[name] = new HandlerClass(this); 3785 3786 this._handlers.push(handler); 3787 3788 if (this.options[name]) { 3789 handler.enable(); 3790 } 3791 3792 return this; 3793 }, 3794 3795 // @method remove(): this 3796 // Destroys the map and clears all related event listeners. 3797 remove: function () { 3798 3799 this._initEvents(true); 3800 3801 if (this._containerId !== this._container._leaflet_id) { 3802 throw new Error('Map container is being reused by another instance'); 3803 } 3804 3805 try { 3806 // throws error in IE6-8 3807 delete this._container._leaflet_id; 3808 delete this._containerId; 3809 } catch (e) { 3810 /*eslint-disable */ 3811 this._container._leaflet_id = undefined; 3812 /* eslint-enable */ 3813 this._containerId = undefined; 3814 } 3815 3816 if (this._locationWatchId !== undefined) { 3817 this.stopLocate(); 3818 } 3819 3820 this._stop(); 3821 3822 remove(this._mapPane); 3823 3824 if (this._clearControlPos) { 3825 this._clearControlPos(); 3826 } 3827 if (this._resizeRequest) { 3828 cancelAnimFrame(this._resizeRequest); 3829 this._resizeRequest = null; 3830 } 3831 3832 this._clearHandlers(); 3833 3834 if (this._loaded) { 3835 // @section Map state change events 3836 // @event unload: Event 3837 // Fired when the map is destroyed with [remove](#map-remove) method. 3838 this.fire('unload'); 3839 } 3840 3841 var i; 3842 for (i in this._layers) { 3843 this._layers[i].remove(); 3844 } 3845 for (i in this._panes) { 3846 remove(this._panes[i]); 3847 } 3848 3849 this._layers = []; 3850 this._panes = []; 3851 delete this._mapPane; 3852 delete this._renderer; 3853 3854 return this; 3855 }, 3856 3857 // @section Other Methods 3858 // @method createPane(name: String, container?: HTMLElement): HTMLElement 3859 // Creates a new [map pane](#map-pane) with the given name if it doesn't exist already, 3860 // then returns it. The pane is created as a child of `container`, or 3861 // as a child of the main map pane if not set. 3862 createPane: function (name, container) { 3863 var className = 'leaflet-pane' + (name ? ' leaflet-' + name.replace('Pane', '') + '-pane' : ''), 3864 pane = create$1('div', className, container || this._mapPane); 3865 3866 if (name) { 3867 this._panes[name] = pane; 3868 } 3869 return pane; 3870 }, 3871 3872 // @section Methods for Getting Map State 3873 3874 // @method getCenter(): LatLng 3875 // Returns the geographical center of the map view 3876 getCenter: function () { 3877 this._checkIfLoaded(); 3878 3879 if (this._lastCenter && !this._moved()) { 3880 return this._lastCenter; 3881 } 3882 return this.layerPointToLatLng(this._getCenterLayerPoint()); 3883 }, 3884 3885 // @method getZoom(): Number 3886 // Returns the current zoom level of the map view 3887 getZoom: function () { 3888 return this._zoom; 3889 }, 3890 3891 // @method getBounds(): LatLngBounds 3892 // Returns the geographical bounds visible in the current map view 3893 getBounds: function () { 3894 var bounds = this.getPixelBounds(), 3895 sw = this.unproject(bounds.getBottomLeft()), 3896 ne = this.unproject(bounds.getTopRight()); 3897 3898 return new LatLngBounds(sw, ne); 3899 }, 3900 3901 // @method getMinZoom(): Number 3902 // 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. 3903 getMinZoom: function () { 3904 return this.options.minZoom === undefined ? this._layersMinZoom || 0 : this.options.minZoom; 3905 }, 3906 3907 // @method getMaxZoom(): Number 3908 // Returns the maximum zoom level of the map (if set in the `maxZoom` option of the map or of any layers). 3909 getMaxZoom: function () { 3910 return this.options.maxZoom === undefined ? 3911 (this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) : 3912 this.options.maxZoom; 3913 }, 3914 3915 // @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number 3916 // Returns the maximum zoom level on which the given bounds fit to the map 3917 // view in its entirety. If `inside` (optional) is set to `true`, the method 3918 // instead returns the minimum zoom level on which the map view fits into 3919 // the given bounds in its entirety. 3920 getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number 3921 bounds = toLatLngBounds(bounds); 3922 padding = toPoint(padding || [0, 0]); 3923 3924 var zoom = this.getZoom() || 0, 3925 min = this.getMinZoom(), 3926 max = this.getMaxZoom(), 3927 nw = bounds.getNorthWest(), 3928 se = bounds.getSouthEast(), 3929 size = this.getSize().subtract(padding), 3930 boundsSize = toBounds(this.project(se, zoom), this.project(nw, zoom)).getSize(), 3931 snap = any3d ? this.options.zoomSnap : 1, 3932 scalex = size.x / boundsSize.x, 3933 scaley = size.y / boundsSize.y, 3934 scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley); 3935 3936 zoom = this.getScaleZoom(scale, zoom); 3937 3938 if (snap) { 3939 zoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level 3940 zoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap; 3941 } 3942 3943 return Math.max(min, Math.min(max, zoom)); 3944 }, 3945 3946 // @method getSize(): Point 3947 // Returns the current size of the map container (in pixels). 3948 getSize: function () { 3949 if (!this._size || this._sizeChanged) { 3950 this._size = new Point( 3951 this._container.clientWidth || 0, 3952 this._container.clientHeight || 0); 3953 3954 this._sizeChanged = false; 3955 } 3956 return this._size.clone(); 3957 }, 3958 3959 // @method getPixelBounds(): Bounds 3960 // Returns the bounds of the current map view in projected pixel 3961 // coordinates (sometimes useful in layer and overlay implementations). 3962 getPixelBounds: function (center, zoom) { 3963 var topLeftPoint = this._getTopLeftPoint(center, zoom); 3964 return new Bounds(topLeftPoint, topLeftPoint.add(this.getSize())); 3965 }, 3966 3967 // TODO: Check semantics - isn't the pixel origin the 0,0 coord relative to 3968 // the map pane? "left point of the map layer" can be confusing, specially 3969 // since there can be negative offsets. 3970 // @method getPixelOrigin(): Point 3971 // Returns the projected pixel coordinates of the top left point of 3972 // the map layer (useful in custom layer and overlay implementations). 3973 getPixelOrigin: function () { 3974 this._checkIfLoaded(); 3975 return this._pixelOrigin; 3976 }, 3977 3978 // @method getPixelWorldBounds(zoom?: Number): Bounds 3979 // Returns the world's bounds in pixel coordinates for zoom level `zoom`. 3980 // If `zoom` is omitted, the map's current zoom level is used. 3981 getPixelWorldBounds: function (zoom) { 3982 return this.options.crs.getProjectedBounds(zoom === undefined ? this.getZoom() : zoom); 3983 }, 3984 3985 // @section Other Methods 3986 3987 // @method getPane(pane: String|HTMLElement): HTMLElement 3988 // Returns a [map pane](#map-pane), given its name or its HTML element (its identity). 3989 getPane: function (pane) { 3990 return typeof pane === 'string' ? this._panes[pane] : pane; 3991 }, 3992 3993 // @method getPanes(): Object 3994 // Returns a plain object containing the names of all [panes](#map-pane) as keys and 3995 // the panes as values. 3996 getPanes: function () { 3997 return this._panes; 3998 }, 3999 4000 // @method getContainer: HTMLElement 4001 // Returns the HTML element that contains the map. 4002 getContainer: function () { 4003 return this._container; 4004 }, 4005 4006 4007 // @section Conversion Methods 4008 4009 // @method getZoomScale(toZoom: Number, fromZoom: Number): Number 4010 // Returns the scale factor to be applied to a map transition from zoom level 4011 // `fromZoom` to `toZoom`. Used internally to help with zoom animations. 4012 getZoomScale: function (toZoom, fromZoom) { 4013 // TODO replace with universal implementation after refactoring projections 4014 var crs = this.options.crs; 4015 fromZoom = fromZoom === undefined ? this._zoom : fromZoom; 4016 return crs.scale(toZoom) / crs.scale(fromZoom); 4017 }, 4018 4019 // @method getScaleZoom(scale: Number, fromZoom: Number): Number 4020 // Returns the zoom level that the map would end up at, if it is at `fromZoom` 4021 // level and everything is scaled by a factor of `scale`. Inverse of 4022 // [`getZoomScale`](#map-getZoomScale). 4023 getScaleZoom: function (scale, fromZoom) { 4024 var crs = this.options.crs; 4025 fromZoom = fromZoom === undefined ? this._zoom : fromZoom; 4026 var zoom = crs.zoom(scale * crs.scale(fromZoom)); 4027 return isNaN(zoom) ? Infinity : zoom; 4028 }, 4029 4030 // @method project(latlng: LatLng, zoom: Number): Point 4031 // Projects a geographical coordinate `LatLng` according to the projection 4032 // of the map's CRS, then scales it according to `zoom` and the CRS's 4033 // `Transformation`. The result is pixel coordinate relative to 4034 // the CRS origin. 4035 project: function (latlng, zoom) { 4036 zoom = zoom === undefined ? this._zoom : zoom; 4037 return this.options.crs.latLngToPoint(toLatLng(latlng), zoom); 4038 }, 4039 4040 // @method unproject(point: Point, zoom: Number): LatLng 4041 // Inverse of [`project`](#map-project). 4042 unproject: function (point, zoom) { 4043 zoom = zoom === undefined ? this._zoom : zoom; 4044 return this.options.crs.pointToLatLng(toPoint(point), zoom); 4045 }, 4046 4047 // @method layerPointToLatLng(point: Point): LatLng 4048 // Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin), 4049 // returns the corresponding geographical coordinate (for the current zoom level). 4050 layerPointToLatLng: function (point) { 4051 var projectedPoint = toPoint(point).add(this.getPixelOrigin()); 4052 return this.unproject(projectedPoint); 4053 }, 4054 4055 // @method latLngToLayerPoint(latlng: LatLng): Point 4056 // Given a geographical coordinate, returns the corresponding pixel coordinate 4057 // relative to the [origin pixel](#map-getpixelorigin). 4058 latLngToLayerPoint: function (latlng) { 4059 var projectedPoint = this.project(toLatLng(latlng))._round(); 4060 return projectedPoint._subtract(this.getPixelOrigin()); 4061 }, 4062 4063 // @method wrapLatLng(latlng: LatLng): LatLng 4064 // Returns a `LatLng` where `lat` and `lng` has been wrapped according to the 4065 // map's CRS's `wrapLat` and `wrapLng` properties, if they are outside the 4066 // CRS's bounds. 4067 // By default this means longitude is wrapped around the dateline so its 4068 // value is between -180 and +180 degrees. 4069 wrapLatLng: function (latlng) { 4070 return this.options.crs.wrapLatLng(toLatLng(latlng)); 4071 }, 4072 4073 // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds 4074 // Returns a `LatLngBounds` with the same size as the given one, ensuring that 4075 // its center is within the CRS's bounds. 4076 // By default this means the center longitude is wrapped around the dateline so its 4077 // value is between -180 and +180 degrees, and the majority of the bounds 4078 // overlaps the CRS's bounds. 4079 wrapLatLngBounds: function (latlng) { 4080 return this.options.crs.wrapLatLngBounds(toLatLngBounds(latlng)); 4081 }, 4082 4083 // @method distance(latlng1: LatLng, latlng2: LatLng): Number 4084 // Returns the distance between two geographical coordinates according to 4085 // the map's CRS. By default this measures distance in meters. 4086 distance: function (latlng1, latlng2) { 4087 return this.options.crs.distance(toLatLng(latlng1), toLatLng(latlng2)); 4088 }, 4089 4090 // @method containerPointToLayerPoint(point: Point): Point 4091 // Given a pixel coordinate relative to the map container, returns the corresponding 4092 // pixel coordinate relative to the [origin pixel](#map-getpixelorigin). 4093 containerPointToLayerPoint: function (point) { // (Point) 4094 return toPoint(point).subtract(this._getMapPanePos()); 4095 }, 4096 4097 // @method layerPointToContainerPoint(point: Point): Point 4098 // Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin), 4099 // returns the corresponding pixel coordinate relative to the map container. 4100 layerPointToContainerPoint: function (point) { // (Point) 4101 return toPoint(point).add(this._getMapPanePos()); 4102 }, 4103 4104 // @method containerPointToLatLng(point: Point): LatLng 4105 // Given a pixel coordinate relative to the map container, returns 4106 // the corresponding geographical coordinate (for the current zoom level). 4107 containerPointToLatLng: function (point) { 4108 var layerPoint = this.containerPointToLayerPoint(toPoint(point)); 4109 return this.layerPointToLatLng(layerPoint); 4110 }, 4111 4112 // @method latLngToContainerPoint(latlng: LatLng): Point 4113 // Given a geographical coordinate, returns the corresponding pixel coordinate 4114 // relative to the map container. 4115 latLngToContainerPoint: function (latlng) { 4116 return this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng))); 4117 }, 4118 4119 // @method mouseEventToContainerPoint(ev: MouseEvent): Point 4120 // Given a MouseEvent object, returns the pixel coordinate relative to the 4121 // map container where the event took place. 4122 mouseEventToContainerPoint: function (e) { 4123 return getMousePosition(e, this._container); 4124 }, 4125 4126 // @method mouseEventToLayerPoint(ev: MouseEvent): Point 4127 // Given a MouseEvent object, returns the pixel coordinate relative to 4128 // the [origin pixel](#map-getpixelorigin) where the event took place. 4129 mouseEventToLayerPoint: function (e) { 4130 return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e)); 4131 }, 4132 4133 // @method mouseEventToLatLng(ev: MouseEvent): LatLng 4134 // Given a MouseEvent object, returns geographical coordinate where the 4135 // event took place. 4136 mouseEventToLatLng: function (e) { // (MouseEvent) 4137 return this.layerPointToLatLng(this.mouseEventToLayerPoint(e)); 4138 }, 4139 4140 4141 // map initialization methods 4142 4143 _initContainer: function (id) { 4144 var container = this._container = get(id); 4145 4146 if (!container) { 4147 throw new Error('Map container not found.'); 4148 } else if (container._leaflet_id) { 4149 throw new Error('Map container is already initialized.'); 4150 } 4151 4152 on(container, 'scroll', this._onScroll, this); 4153 this._containerId = stamp(container); 4154 }, 4155 4156 _initLayout: function () { 4157 var container = this._container; 4158 4159 this._fadeAnimated = this.options.fadeAnimation && any3d; 4160 4161 addClass(container, 'leaflet-container' + 4162 (touch ? ' leaflet-touch' : '') + 4163 (retina ? ' leaflet-retina' : '') + 4164 (ielt9 ? ' leaflet-oldie' : '') + 4165 (safari ? ' leaflet-safari' : '') + 4166 (this._fadeAnimated ? ' leaflet-fade-anim' : '')); 4167 4168 var position = getStyle(container, 'position'); 4169 4170 if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') { 4171 container.style.position = 'relative'; 4172 } 4173 4174 this._initPanes(); 4175 4176 if (this._initControlPos) { 4177 this._initControlPos(); 4178 } 4179 }, 4180 4181 _initPanes: function () { 4182 var panes = this._panes = {}; 4183 this._paneRenderers = {}; 4184 4185 // @section 4186 // 4187 // Panes are DOM elements used to control the ordering of layers on the map. You 4188 // can access panes with [`map.getPane`](#map-getpane) or 4189 // [`map.getPanes`](#map-getpanes) methods. New panes can be created with the 4190 // [`map.createPane`](#map-createpane) method. 4191 // 4192 // Every map has the following default panes that differ only in zIndex. 4193 // 4194 // @pane mapPane: HTMLElement = 'auto' 4195 // Pane that contains all other map panes 4196 4197 this._mapPane = this.createPane('mapPane', this._container); 4198 setPosition(this._mapPane, new Point(0, 0)); 4199 4200 // @pane tilePane: HTMLElement = 200 4201 // Pane for `GridLayer`s and `TileLayer`s 4202 this.createPane('tilePane'); 4203 // @pane overlayPane: HTMLElement = 400 4204 // Pane for vectors (`Path`s, like `Polyline`s and `Polygon`s), `ImageOverlay`s and `VideoOverlay`s 4205 this.createPane('shadowPane'); 4206 // @pane shadowPane: HTMLElement = 500 4207 // Pane for overlay shadows (e.g. `Marker` shadows) 4208 this.createPane('overlayPane'); 4209 // @pane markerPane: HTMLElement = 600 4210 // Pane for `Icon`s of `Marker`s 4211 this.createPane('markerPane'); 4212 // @pane tooltipPane: HTMLElement = 650 4213 // Pane for `Tooltip`s. 4214 this.createPane('tooltipPane'); 4215 // @pane popupPane: HTMLElement = 700 4216 // Pane for `Popup`s. 4217 this.createPane('popupPane'); 4218 4219 if (!this.options.markerZoomAnimation) { 4220 addClass(panes.markerPane, 'leaflet-zoom-hide'); 4221 addClass(panes.shadowPane, 'leaflet-zoom-hide'); 4222 } 4223 }, 4224 4225 4226 // private methods that modify map state 4227 4228 // @section Map state change events 4229 _resetView: function (center, zoom) { 4230 setPosition(this._mapPane, new Point(0, 0)); 4231 4232 var loading = !this._loaded; 4233 this._loaded = true; 4234 zoom = this._limitZoom(zoom); 4235 4236 this.fire('viewprereset'); 4237 4238 var zoomChanged = this._zoom !== zoom; 4239 this 4240 ._moveStart(zoomChanged, false) 4241 ._move(center, zoom) 4242 ._moveEnd(zoomChanged); 4243 4244 // @event viewreset: Event 4245 // Fired when the map needs to redraw its content (this usually happens 4246 // on map zoom or load). Very useful for creating custom overlays. 4247 this.fire('viewreset'); 4248 4249 // @event load: Event 4250 // Fired when the map is initialized (when its center and zoom are set 4251 // for the first time). 4252 if (loading) { 4253 this.fire('load'); 4254 } 4255 }, 4256 4257 _moveStart: function (zoomChanged, noMoveStart) { 4258 // @event zoomstart: Event 4259 // Fired when the map zoom is about to change (e.g. before zoom animation). 4260 // @event movestart: Event 4261 // Fired when the view of the map starts changing (e.g. user starts dragging the map). 4262 if (zoomChanged) { 4263 this.fire('zoomstart'); 4264 } 4265 if (!noMoveStart) { 4266 this.fire('movestart'); 4267 } 4268 return this; 4269 }, 4270 4271 _move: function (center, zoom, data) { 4272 if (zoom === undefined) { 4273 zoom = this._zoom; 4274 } 4275 var zoomChanged = this._zoom !== zoom; 4276 4277 this._zoom = zoom; 4278 this._lastCenter = center; 4279 this._pixelOrigin = this._getNewPixelOrigin(center); 4280 4281 // @event zoom: Event 4282 // Fired repeatedly during any change in zoom level, including zoom 4283 // and fly animations. 4284 if (zoomChanged || (data && data.pinch)) { // Always fire 'zoom' if pinching because #3530 4285 this.fire('zoom', data); 4286 } 4287 4288 // @event move: Event 4289 // Fired repeatedly during any movement of the map, including pan and 4290 // fly animations. 4291 return this.fire('move', data); 4292 }, 4293 4294 _moveEnd: function (zoomChanged) { 4295 // @event zoomend: Event 4296 // Fired when the map has changed, after any animations. 4297 if (zoomChanged) { 4298 this.fire('zoomend'); 4299 } 4300 4301 // @event moveend: Event 4302 // Fired when the center of the map stops changing (e.g. user stopped 4303 // dragging the map). 4304 return this.fire('moveend'); 4305 }, 4306 4307 _stop: function () { 4308 cancelAnimFrame(this._flyToFrame); 4309 if (this._panAnim) { 4310 this._panAnim.stop(); 4311 } 4312 return this; 4313 }, 4314 4315 _rawPanBy: function (offset) { 4316 setPosition(this._mapPane, this._getMapPanePos().subtract(offset)); 4317 }, 4318 4319 _getZoomSpan: function () { 4320 return this.getMaxZoom() - this.getMinZoom(); 4321 }, 4322 4323 _panInsideMaxBounds: function () { 4324 if (!this._enforcingBounds) { 4325 this.panInsideBounds(this.options.maxBounds); 4326 } 4327 }, 4328 4329 _checkIfLoaded: function () { 4330 if (!this._loaded) { 4331 throw new Error('Set map center and zoom first.'); 4332 } 4333 }, 4334 4335 // DOM event handling 4336 4337 // @section Interaction events 4338 _initEvents: function (remove$$1) { 4339 this._targets = {}; 4340 this._targets[stamp(this._container)] = this; 4341 4342 var onOff = remove$$1 ? off : on; 4343 4344 // @event click: MouseEvent 4345 // Fired when the user clicks (or taps) the map. 4346 // @event dblclick: MouseEvent 4347 // Fired when the user double-clicks (or double-taps) the map. 4348 // @event mousedown: MouseEvent 4349 // Fired when the user pushes the mouse button on the map. 4350 // @event mouseup: MouseEvent 4351 // Fired when the user releases the mouse button on the map. 4352 // @event mouseover: MouseEvent 4353 // Fired when the mouse enters the map. 4354 // @event mouseout: MouseEvent 4355 // Fired when the mouse leaves the map. 4356 // @event mousemove: MouseEvent 4357 // Fired while the mouse moves over the map. 4358 // @event contextmenu: MouseEvent 4359 // Fired when the user pushes the right mouse button on the map, prevents 4360 // default browser context menu from showing if there are listeners on
4361 // this event. Also fired on mobile when the user holds a single touch 4362 // for a second (also called long press). 4363 // @event keypress: KeyboardEvent 4364 // Fired when the user presses a key from the keyboard while the map is focused. 4365 onOff(this._container, 'click dblclick mousedown mouseup ' + 4366 'mouseover mouseout mousemove contextmenu keypress', this._handleDOMEvent, this); 4367 4368 if (this.options.trackResize) { 4369 onOff(window, 'resize', this._onResize, this); 4370 } 4371 4372 if (any3d && this.options.transform3DLimit) { 4373 (remove$$1 ? this.off : this.on).call(this, 'moveend', this._onMoveEnd); 4374 } 4375 }, 4376 4377 _onResize: function () { 4378 cancelAnimFrame(this._resizeRequest); 4379 this._resizeRequest = requestAnimFrame( 4380 function () { this.invalidateSize({debounceMoveend: true}); }, this); 4381 }, 4382 4383 _onScroll: function () { 4384 this._container.scrollTop = 0; 4385 this._container.scrollLeft = 0; 4386 }, 4387 4388 _onMoveEnd: function () { 4389 var pos = this._getMapPanePos(); 4390 if (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) { 4391 // https://bugzilla.mozilla.org/show_bug.cgi?id=1203873 but Webkit also have 4392 // a pixel offset on very high values, see: http://jsfiddle.net/dg6r5hhb/ 4393 this._resetView(this.getCenter(), this.getZoom()); 4394 } 4395 }, 4396 4397 _findEventTargets: function (e, type) { 4398 var targets = [], 4399 target, 4400 isHover = type === 'mouseout' || type === 'mouseover', 4401 src = e.target || e.srcElement, 4402 dragging = false; 4403 4404 while (src) { 4405 target = this._targets[stamp(src)]; 4406 if (target && (type === 'click' || type === 'preclick') && !e._simulated && this._draggableMoved(target)) { 4407 // Prevent firing click after you just dragged an object. 4408 dragging = true; 4409 break; 4410 } 4411 if (target && target.listens(type, true)) { 4412 if (isHover && !isExternalTarget(src, e)) { break; } 4413 targets.push(target); 4414 if (isHover) { break; } 4415 } 4416 if (src === this._container) { break; } 4417 src = src.parentNode; 4418 } 4419 if (!targets.length && !dragging && !isHover && isExternalTarget(src, e)) { 4420 targets = [this]; 4421 } 4422 return targets; 4423 }, 4424 4425 _handleDOMEvent: function (e) { 4426 if (!this._loaded || skipped(e)) { return; } 4427 4428 var type = e.type; 4429 4430 if (type === 'mousedown' || type === 'keypress') { 4431 // prevents outline when clicking on keyboard-focusable element 4432 preventOutline(e.target || e.srcElement); 4433 } 4434 4435 this._fireDOMEvent(e, type); 4436 }, 4437 4438 _mouseEvents: ['click', 'dblclick', 'mouseover', 'mouseout', 'contextmenu'], 4439 4440 _fireDOMEvent: function (e, type, targets) { 4441 4442 if (e.type === 'click') { 4443 // Fire a synthetic 'preclick' event which propagates up (mainly for closing popups). 4444 // @event preclick: MouseEvent 4445 // Fired before mouse click on the map (sometimes useful when you 4446 // want something to happen on click before any existing click 4447 // handlers start running). 4448 var synth = extend({}, e); 4449 synth.type = 'preclick'; 4450 this._fireDOMEvent(synth, synth.type, targets); 4451 } 4452 4453 if (e._stopped) { return; } 4454 4455 // Find the layer the event is propagating from and its parents. 4456 targets = (targets || []).concat(this._findEventTargets(e, type)); 4457 4458 if (!targets.length) { return; } 4459 4460 var target = targets[0]; 4461 if (type === 'contextmenu' && target.listens(type, true)) { 4462 preventDefault(e); 4463 } 4464 4465 var data = { 4466 originalEvent: e 4467 }; 4468 4469 if (e.type !== 'keypress') { 4470 var isMarker = target.getLatLng && (!target._radius || target._radius <= 10); 4471 data.containerPoint = isMarker ? 4472 this.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e); 4473 data.layerPoint = this.containerPointToLayerPoint(data.containerPoint); 4474 data.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint); 4475 } 4476 4477 for (var i = 0; i < targets.length; i++) { 4478 targets[i].fire(type, data, true); 4479 if (data.originalEvent._stopped || 4480 (targets[i].options.bubblingMouseEvents === false && indexOf(this._mouseEvents, type) !== -1)) { return; } 4481 } 4482 }, 4483 4484 _draggableMoved: function (obj) { 4485 obj = obj.dragging && obj.dragging.enabled() ? obj : this; 4486 return (obj.dragging && obj.dragging.moved()) || (this.boxZoom && this.boxZoom.moved()); 4487 }, 4488 4489 _clearHandlers: function () { 4490 for (var i = 0, len = this._handlers.length; i < len; i++) { 4491 this._handlers[i].disable(); 4492 } 4493 }, 4494 4495 // @section Other Methods 4496 4497 // @method whenReady(fn: Function, context?: Object): this 4498 // Runs the given function `fn` when the map gets initialized with 4499 // a view (center and zoom) and at least one layer, or immediately 4500 // if it's already initialized, optionally passing a function context. 4501 whenReady: function (callback, context) { 4502 if (this._loaded) { 4503 callback.call(context || this, {target: this}); 4504 } else { 4505 this.on('load', callback, context); 4506 } 4507 return this; 4508 }, 4509 4510 4511 // private methods for getting map state 4512 4513 _getMapPanePos: function () { 4514 return getPosition(this._mapPane) || new Point(0, 0); 4515 }, 4516 4517 _moved: function () { 4518 var pos = this._getMapPanePos(); 4519 return pos && !pos.equals([0, 0]); 4520 }, 4521 4522 _getTopLeftPoint: function (center, zoom) { 4523 var pixelOrigin = center && zoom !== undefined ? 4524 this._getNewPixelOrigin(center, zoom) : 4525 this.getPixelOrigin(); 4526 return pixelOrigin.subtract(this._getMapPanePos()); 4527 }, 4528 4529 _getNewPixelOrigin: function (center, zoom) {
vendor: 6,570 bytes, lines 4530-4740
4530 var viewHalf = this.getSize()._divideBy(2); 4531 return this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round(); 4532 }, 4533 4534 _latLngToNewLayerPoint: function (latlng, zoom, center) { 4535 var topLeft = this._getNewPixelOrigin(center, zoom); 4536 return this.project(latlng, zoom)._subtract(topLeft); 4537 }, 4538 4539 _latLngBoundsToNewLayerBounds: function (latLngBounds, zoom, center) { 4540 var topLeft = this._getNewPixelOrigin(center, zoom); 4541 return toBounds([ 4542 this.project(latLngBounds.getSouthWest(), zoom)._subtract(topLeft), 4543 this.project(latLngBounds.getNorthWest(), zoom)._subtract(topLeft), 4544 this.project(latLngBounds.getSouthEast(), zoom)._subtract(topLeft), 4545 this.project(latLngBounds.getNorthEast(), zoom)._subtract(topLeft) 4546 ]); 4547 }, 4548 4549 // layer point of the current center 4550 _getCenterLayerPoint: function () { 4551 return this.containerPointToLayerPoint(this.getSize()._divideBy(2)); 4552 }, 4553 4554 // offset of the specified place to the current center in pixels 4555 _getCenterOffset: function (latlng) { 4556 return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint()); 4557 }, 4558 4559 // adjust center for view to get inside bounds 4560 _limitCenter: function (center, zoom, bounds) { 4561 4562 if (!bounds) { return center; } 4563 4564 var centerPoint = this.project(center, zoom), 4565 viewHalf = this.getSize().divideBy(2), 4566 viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), 4567 offset = this._getBoundsOffset(viewBounds, bounds, zoom); 4568 4569 // If offset is less than a pixel, ignore. 4570 // This prevents unstable projections from getting into 4571 // an infinite loop of tiny offsets. 4572 if (offset.round().equals([0, 0])) { 4573 return center; 4574 } 4575 4576 return this.unproject(centerPoint.add(offset), zoom); 4577 }, 4578 4579 // adjust offset for view to get inside bounds 4580 _limitOffset: function (offset, bounds) { 4581 if (!bounds) { return offset; } 4582 4583 var viewBounds = this.getPixelBounds(), 4584 newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset)); 4585 4586 return offset.add(this._getBoundsOffset(newBounds, bounds)); 4587 }, 4588 4589 // returns offset needed for pxBounds to get inside maxBounds at a specified zoom 4590 _getBoundsOffset: function (pxBounds, maxBounds, zoom) { 4591 var projectedMaxBounds = toBounds( 4592 this.project(maxBounds.getNorthEast(), zoom), 4593 this.project(maxBounds.getSouthWest(), zoom) 4594 ), 4595 minOffset = projectedMaxBounds.min.subtract(pxBounds.min), 4596 maxOffset = projectedMaxBounds.max.subtract(pxBounds.max), 4597 4598 dx = this._rebound(minOffset.x, -maxOffset.x), 4599 dy = this._rebound(minOffset.y, -maxOffset.y); 4600 4601 return new Point(dx, dy); 4602 }, 4603 4604 _rebound: function (left, right) { 4605 return left + right > 0 ? 4606 Math.round(left - right) / 2 : 4607 Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right)); 4608 }, 4609 4610 _limitZoom: function (zoom) { 4611 var min = this.getMinZoom(), 4612 max = this.getMaxZoom(), 4613 snap = any3d ? this.options.zoomSnap : 1; 4614 if (snap) { 4615 zoom = Math.round(zoom / snap) * snap; 4616 } 4617 return Math.max(min, Math.min(max, zoom)); 4618 }, 4619 4620 _onPanTransitionStep: function () { 4621 this.fire('move'); 4622 }, 4623 4624 _onPanTransitionEnd: function () { 4625 removeClass(this._mapPane, 'leaflet-pan-anim'); 4626 this.fire('moveend'); 4627 }, 4628 4629 _tryAnimatedPan: function (center, options) { 4630 // difference between the new and current centers in pixels 4631 var offset = this._getCenterOffset(center)._trunc(); 4632 4633 // don't animate too far unless animate: true specified in options 4634 if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; } 4635 4636 this.panBy(offset, options); 4637 4638 return true; 4639 }, 4640 4641 _createAnimProxy: function () { 4642 4643 var proxy = this._proxy = create$1('div', 'leaflet-proxy leaflet-zoom-animated'); 4644 this._panes.mapPane.appendChild(proxy); 4645 4646 this.on('zoomanim', function (e) { 4647 var prop = TRANSFORM, 4648 transform = this._proxy.style[prop]; 4649 4650 setTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1)); 4651 4652 // workaround for case when transform is the same and so transitionend event is not fired 4653 if (transform === this._proxy.style[prop] && this._animatingZoom) { 4654 this._onZoomTransitionEnd(); 4655 } 4656 }, this); 4657 4658 this.on('load moveend', function () { 4659 var c = this.getCenter(), 4660 z = this.getZoom(); 4661 setTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1)); 4662 }, this); 4663 4664 this._on('unload', this._destroyAnimProxy, this); 4665 }, 4666 4667 _destroyAnimProxy: function () { 4668 remove(this._proxy); 4669 delete this._proxy; 4670 }, 4671 4672 _catchTransitionEnd: function (e) { 4673 if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) { 4674 this._onZoomTransitionEnd(); 4675 } 4676 }, 4677 4678 _nothingToAnimate: function () { 4679 return !this._container.getElementsByClassName('leaflet-zoom-animated').length; 4680 }, 4681 4682 _tryAnimatedZoom: function (center, zoom, options) { 4683 4684 if (this._animatingZoom) { return true; } 4685 4686 options = options || {}; 4687 4688 // don't animate if disabled, not supported or zoom difference is too large 4689 if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || 4690 Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; } 4691 4692 // offset is the pixel coords of the zoom origin relative to the current center 4693 var scale = this.getZoomScale(zoom), 4694 offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale); 4695 4696 // don't animate if the zoom origin isn't within one screen from the current center, unless forced 4697 if (options.animate !== true && !this.getSize().contains(offset)) { return false; } 4698 4699 requestAnimFrame(function () { 4700 this 4701 ._moveStart(true, false) 4702 ._animateZoom(center, zoom, true); 4703 }, this); 4704 4705 return true; 4706 }, 4707 4708 _animateZoom: function (center, zoom, startAnim, noUpdate) { 4709 if (!this._mapPane) { return; } 4710 4711 if (startAnim) { 4712 this._animatingZoom = true; 4713 4714 // remember what center/zoom to set after animation 4715 this._animateToCenter = center; 4716 this._animateToZoom = zoom; 4717 4718 addClass(this._mapPane, 'leaflet-zoom-anim'); 4719 } 4720 4721 // @event zoomanim: ZoomAnimEvent 4722 // Fired on every frame of a zoom animation 4723 this.fire('zoomanim', { 4724 center: center, 4725 zoom: zoom, 4726 noUpdate: noUpdate 4727 }); 4728 4729 // Work around webkit not firing 'transitionend', see https://github.com/Leaflet/Leaflet/issues/3689, 2693 4730 setTimeout(bind(this._onZoomTransitionEnd, this), 250); 4731 }, 4732 4733 _onZoomTransitionEnd: function () { 4734 if (!this._animatingZoom) { return; } 4735 4736 if (this._mapPane) { 4737 removeClass(this._mapPane, 'leaflet-zoom-anim'); 4738 } 4739 4740 this._animatingZoom = false;
4741 4742 this._move(this._animateToCenter, this._animateToZoom); 4743 4744 // This anim frame should prevent an obscure iOS webkit tile loading race condition. 4745 requestAnimFrame(function () { 4746 this._moveEnd(true); 4747 }, this); 4748 } 4749}); 4750 4751// @section 4752 4753// @factory L.map(id: String, options?: Map options) 4754// Instantiates a map object given the DOM ID of a `<div>` element 4755// and optionally an object literal with `Map options`. 4756// 4757// @alternative 4758// @factory L.map(el: HTMLElement, options?: Map options) 4759// Instantiates a map object given an instance of a `<div>` HTML element 4760// and optionally an object literal with `Map options`. 4761function createMap(id, options) { 4762 return new Map(id, options); 4763} 4764 4765/* 4766 * @class Control 4767 * @aka L.Control 4768 * @inherits Class 4769 * 4770 * L.Control is a base class for implementing map controls. Handles positioning. 4771 * All other controls extend from this class. 4772 */ 4773 4774var Control = Class.extend({ 4775 // @section 4776 // @aka Control options 4777 options: { 4778 // @option position: String = 'topright' 4779 // The position of the control (one of the map corners). Possible values are `'topleft'`, 4780 // `'topright'`, `'bottomleft'` or `'bottomright'` 4781 position: 'topright' 4782 }, 4783 4784 initialize: function (options) { 4785 setOptions(this, options); 4786 }, 4787 4788 /* @section 4789 * Classes extending L.Control will inherit the following methods: 4790 * 4791 * @method getPosition: string 4792 * Returns the position of the control. 4793 */ 4794 getPosition: function () { 4795 return this.options.position; 4796 }, 4797 4798 // @method setPosition(position: string): this 4799 // Sets the position of the control. 4800 setPosition: function (position) { 4801 var map = this._map; 4802 4803 if (map) { 4804 map.removeControl(this); 4805 } 4806 4807 this.options.position = position; 4808 4809 if (map) { 4810 map.addControl(this); 4811 } 4812 4813 return this; 4814 }, 4815 4816 // @method getContainer: HTMLElement 4817 // Returns the HTMLElement that contains the control. 4818 getContainer: function () { 4819 return this._container; 4820 }, 4821 4822 // @method addTo(map: Map): this 4823 // Adds the control to the given map. 4824 addTo: function (map) { 4825 this.remove(); 4826 this._map = map; 4827 4828 var container = this._container = this.onAdd(map), 4829 pos = this.getPosition(), 4830 corner = map._controlCorners[pos]; 4831 4832 addClass(container, 'leaflet-control'); 4833 4834 if (pos.indexOf('bottom') !== -1) { 4835 corner.insertBefore(container, corner.firstChild); 4836 } else { 4837 corner.appendChild(container); 4838 } 4839 4840 return this; 4841 }, 4842 4843 // @method remove: this 4844 // Removes the control from the map it is currently active on. 4845 remove: function () { 4846 if (!this._map) { 4847 return this; 4848 } 4849 4850 remove(this._container); 4851 4852 if (this.onRemove) { 4853 this.onRemove(this._map); 4854 } 4855 4856 this._map = null; 4857 4858 return this; 4859 }, 4860 4861 _refocusOnMap: function (e) { 4862 // if map exists and event is not a keyboard event 4863 if (this._map && e && e.screenX > 0 && e.screenY > 0) { 4864 this._map.getContainer().focus(); 4865 } 4866 } 4867}); 4868
vendor: 24,826 bytes, lines 4869-5784
4869var control = function (options) { 4870 return new Control(options); 4871}; 4872 4873/* @section Extension methods 4874 * @uninheritable 4875 * 4876 * Every control should extend from `L.Control` and (re-)implement the following methods. 4877 * 4878 * @method onAdd(map: Map): HTMLElement 4879 * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo). 4880 * 4881 * @method onRemove(map: Map) 4882 * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove). 4883 */ 4884 4885/* @namespace Map 4886 * @section Methods for Layers and Controls 4887 */ 4888Map.include({ 4889 // @method addControl(control: Control): this 4890 // Adds the given control to the map 4891 addControl: function (control) { 4892 control.addTo(this); 4893 return this; 4894 }, 4895 4896 // @method removeControl(control: Control): this 4897 // Removes the given control from the map 4898 removeControl: function (control) { 4899 control.remove(); 4900 return this; 4901 }, 4902 4903 _initControlPos: function () { 4904 var corners = this._controlCorners = {}, 4905 l = 'leaflet-', 4906 container = this._controlContainer = 4907 create$1('div', l + 'control-container', this._container); 4908 4909 function createCorner(vSide, hSide) { 4910 var className = l + vSide + ' ' + l + hSide; 4911 4912 corners[vSide + hSide] = create$1('div', className, container); 4913 } 4914 4915 createCorner('top', 'left'); 4916 createCorner('top', 'right'); 4917 createCorner('bottom', 'left'); 4918 createCorner('bottom', 'right'); 4919 }, 4920 4921 _clearControlPos: function () { 4922 for (var i in this._controlCorners) { 4923 remove(this._controlCorners[i]); 4924 } 4925 remove(this._controlContainer); 4926 delete this._controlCorners; 4927 delete this._controlContainer; 4928 } 4929}); 4930 4931/* 4932 * @class Control.Layers 4933 * @aka L.Control.Layers 4934 * @inherits Control 4935 * 4936 * 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`. 4937 * 4938 * @example 4939 * 4940 * ```js 4941 * var baseLayers = { 4942 * "Mapbox": mapbox, 4943 * "OpenStreetMap": osm 4944 * }; 4945 * 4946 * var overlays = { 4947 * "Marker": marker, 4948 * "Roads": roadsLayer 4949 * }; 4950 * 4951 * L.control.layers(baseLayers, overlays).addTo(map); 4952 * ``` 4953 * 4954 * The `baseLayers` and `overlays` parameters are object literals with layer names as keys and `Layer` objects as values: 4955 * 4956 * ```js 4957 * { 4958 * "<someName1>": layer1, 4959 * "<someName2>": layer2 4960 * } 4961 * ``` 4962 * 4963 * The layer names can contain HTML, which allows you to add additional styling to the items: 4964 * 4965 * ```js 4966 * {"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>": myLayer} 4967 * ``` 4968 */ 4969 4970var Layers = Control.extend({ 4971 // @section 4972 // @aka Control.Layers options 4973 options: { 4974 // @option collapsed: Boolean = true 4975 // If `true`, the control will be collapsed into an icon and expanded on mouse hover or touch. 4976 collapsed: true, 4977 position: 'topright', 4978 4979 // @option autoZIndex: Boolean = true 4980 // 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. 4981 autoZIndex: true, 4982 4983 // @option hideSingleBase: Boolean = false 4984 // If `true`, the base layers in the control will be hidden when there is only one. 4985 hideSingleBase: false, 4986 4987 // @option sortLayers: Boolean = false 4988 // Whether to sort the layers. When `false`, layers will keep the order 4989 // in which they were added to the control. 4990 sortLayers: false, 4991 4992 // @option sortFunction: Function = * 4993 // A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 4994 // that will be used for sorting the layers, when `sortLayers` is `true`. 4995 // The function receives both the `L.Layer` instances and their names, as in 4996 // `sortFunction(layerA, layerB, nameA, nameB)`. 4997 // By default, it sorts layers alphabetically by their name. 4998 sortFunction: function (layerA, layerB, nameA, nameB) { 4999 return nameA < nameB ? -1 : (nameB < nameA ? 1 : 0); 5000 } 5001 }, 5002 5003 initialize: function (baseLayers, overlays, options) { 5004 setOptions(this, options); 5005 5006 this._layerControlInputs = []; 5007 this._layers = []; 5008 this._lastZIndex = 0; 5009 this._handlingClick = false; 5010 5011 for (var i in baseLayers) { 5012 this._addLayer(baseLayers[i], i); 5013 } 5014 5015 for (i in overlays) { 5016 this._addLayer(overlays[i], i, true); 5017 } 5018 }, 5019 5020 onAdd: function (map) { 5021 this._initLayout(); 5022 this._update(); 5023 5024 this._map = map; 5025 map.on('zoomend', this._checkDisabledLayers, this); 5026 5027 for (var i = 0; i < this._layers.length; i++) { 5028 this._layers[i].layer.on('add remove', this._onLayerChange, this); 5029 } 5030 5031 return this._container; 5032 }, 5033 5034 addTo: function (map) { 5035 Control.prototype.addTo.call(this, map); 5036 // Trigger expand after Layers Control has been inserted into DOM so that is now has an actual height. 5037 return this._expandIfNotCollapsed(); 5038 }, 5039 5040 onRemove: function () { 5041 this._map.off('zoomend', this._checkDisabledLayers, this); 5042 5043 for (var i = 0; i < this._layers.length; i++) { 5044 this._layers[i].layer.off('add remove', this._onLayerChange, this); 5045 } 5046 }, 5047 5048 // @method addBaseLayer(layer: Layer, name: String): this 5049 // Adds a base layer (radio button entry) with the given name to the control. 5050 addBaseLayer: function (layer, name) { 5051 this._addLayer(layer, name); 5052 return (this._map) ? this._update() : this; 5053 }, 5054 5055 // @method addOverlay(layer: Layer, name: String): this 5056 // Adds an overlay (checkbox entry) with the given name to the control. 5057 addOverlay: function (layer, name) { 5058 this._addLayer(layer, name, true); 5059 return (this._map) ? this._update() : this; 5060 }, 5061 5062 // @method removeLayer(layer: Layer): this 5063 // Remove the given layer from the control. 5064 removeLayer: function (layer) { 5065 layer.off('add remove', this._onLayerChange, this); 5066 5067 var obj = this._getLayer(stamp(layer)); 5068 if (obj) { 5069 this._layers.splice(this._layers.indexOf(obj), 1); 5070 } 5071 return (this._map) ? this._update() : this; 5072 }, 5073 5074 // @method expand(): this 5075 // Expand the control container if collapsed. 5076 expand: function () { 5077 addClass(this._container, 'leaflet-control-layers-expanded'); 5078 this._form.style.height = null; 5079 var acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50); 5080 if (acceptableHeight < this._form.clientHeight) { 5081 addClass(this._form, 'leaflet-control-layers-scrollbar'); 5082 this._form.style.height = acceptableHeight + 'px'; 5083 } else { 5084 removeClass(this._form, 'leaflet-control-layers-scrollbar'); 5085 } 5086 this._checkDisabledLayers(); 5087 return this; 5088 }, 5089 5090 // @method collapse(): this 5091 // Collapse the control container if expanded. 5092 collapse: function () { 5093 removeClass(this._container, 'leaflet-control-layers-expanded'); 5094 return this; 5095 }, 5096 5097 _initLayout: function () { 5098 var className = 'leaflet-control-layers', 5099 container = this._container = create$1('div', className), 5100 collapsed = this.options.collapsed; 5101 5102 // makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released 5103 container.setAttribute('aria-haspopup', true); 5104 5105 disableClickPropagation(container); 5106 disableScrollPropagation(container); 5107 5108 var form = this._form = create$1('form', className + '-list'); 5109 5110 if (collapsed) { 5111 this._map.on('click', this.collapse, this); 5112 5113 if (!android) { 5114 on(container, { 5115 mouseenter: this.expand, 5116 mouseleave: this.collapse 5117 }, this); 5118 } 5119 } 5120 5121 var link = this._layersLink = create$1('a', className + '-toggle', container); 5122 link.href = '#'; 5123 link.title = 'Layers'; 5124 5125 if (touch) { 5126 on(link, 'click', stop); 5127 on(link, 'click', this.expand, this); 5128 } else { 5129 on(link, 'focus', this.expand, this); 5130 } 5131 5132 if (!collapsed) { 5133 this.expand(); 5134 } 5135 5136 this._baseLayersList = create$1('div', className + '-base', form); 5137 this._separator = create$1('div', className + '-separator', form); 5138 this._overlaysList = create$1('div', className + '-overlays', form); 5139 5140 container.appendChild(form); 5141 }, 5142 5143 _getLayer: function (id) { 5144 for (var i = 0; i < this._layers.length; i++) { 5145 5146 if (this._layers[i] && stamp(this._layers[i].layer) === id) { 5147 return this._layers[i]; 5148 } 5149 } 5150 }, 5151 5152 _addLayer: function (layer, name, overlay) { 5153 if (this._map) { 5154 layer.on('add remove', this._onLayerChange, this); 5155 } 5156 5157 this._layers.push({ 5158 layer: layer, 5159 name: name, 5160 overlay: overlay 5161 }); 5162 5163 if (this.options.sortLayers) { 5164 this._layers.sort(bind(function (a, b) { 5165 return this.options.sortFunction(a.layer, b.layer, a.name, b.name); 5166 }, this)); 5167 } 5168 5169 if (this.options.autoZIndex && layer.setZIndex) { 5170 this._lastZIndex++; 5171 layer.setZIndex(this._lastZIndex); 5172 } 5173 5174 this._expandIfNotCollapsed(); 5175 }, 5176 5177 _update: function () { 5178 if (!this._container) { return this; } 5179 5180 empty(this._baseLayersList); 5181 empty(this._overlaysList); 5182 5183 this._layerControlInputs = []; 5184 var baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0; 5185 5186 for (i = 0; i < this._layers.length; i++) { 5187 obj = this._layers[i]; 5188 this._addItem(obj); 5189 overlaysPresent = overlaysPresent || obj.overlay; 5190 baseLayersPresent = baseLayersPresent || !obj.overlay; 5191 baseLayersCount += !obj.overlay ? 1 : 0; 5192 } 5193 5194 // Hide base layers section if there's only one layer. 5195 if (this.options.hideSingleBase) { 5196 baseLayersPresent = baseLayersPresent && baseLayersCount > 1; 5197 this._baseLayersList.style.display = baseLayersPresent ? '' : 'none'; 5198 } 5199 5200 this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; 5201 5202 return this; 5203 }, 5204 5205 _onLayerChange: function (e) { 5206 if (!this._handlingClick) { 5207 this._update(); 5208 } 5209 5210 var obj = this._getLayer(stamp(e.target)); 5211 5212 // @namespace Map 5213 // @section Layer events 5214 // @event baselayerchange: LayersControlEvent 5215 // Fired when the base layer is changed through the [layer control](#control-layers). 5216 // @event overlayadd: LayersControlEvent 5217 // Fired when an overlay is selected through the [layer control](#control-layers). 5218 // @event overlayremove: LayersControlEvent 5219 // Fired when an overlay is deselected through the [layer control](#control-layers). 5220 // @namespace Control.Layers 5221 var type = obj.overlay ? 5222 (e.type === 'add' ? 'overlayadd' : 'overlayremove') : 5223 (e.type === 'add' ? 'baselayerchange' : null); 5224 5225 if (type) { 5226 this._map.fire(type, obj); 5227 } 5228 }, 5229 5230 // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) 5231 _createRadioElement: function (name, checked) { 5232 5233 var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + 5234 name + '"' + (checked ? ' checked="checked"' : '') + '/>'; 5235 5236 var radioFragment = document.createElement('div'); 5237 radioFragment.innerHTML = radioHtml; 5238 5239 return radioFragment.firstChild; 5240 }, 5241 5242 _addItem: function (obj) { 5243 var label = document.createElement('label'), 5244 checked = this._map.hasLayer(obj.layer), 5245 input; 5246 5247 if (obj.overlay) { 5248 input = document.createElement('input'); 5249 input.type = 'checkbox'; 5250 input.className = 'leaflet-control-layers-selector'; 5251 input.defaultChecked = checked; 5252 } else { 5253 input = this._createRadioElement('leaflet-base-layers', checked); 5254 } 5255 5256 this._layerControlInputs.push(input); 5257 input.layerId = stamp(obj.layer); 5258 5259 on(input, 'click', this._onInputClick, this); 5260 5261 var name = document.createElement('span'); 5262 name.innerHTML = ' ' + obj.name; 5263 5264 // Helps from preventing layer control flicker when checkboxes are disabled 5265 // https://github.com/Leaflet/Leaflet/issues/2771 5266 var holder = document.createElement('div'); 5267 5268 label.appendChild(holder); 5269 holder.appendChild(input); 5270 holder.appendChild(name); 5271 5272 var container = obj.overlay ? this._overlaysList : this._baseLayersList; 5273 container.appendChild(label); 5274 5275 this._checkDisabledLayers(); 5276 return label; 5277 }, 5278 5279 _onInputClick: function () { 5280 var inputs = this._layerControlInputs, 5281 input, layer; 5282 var addedLayers = [], 5283 removedLayers = []; 5284 5285 this._handlingClick = true; 5286 5287 for (var i = inputs.length - 1; i >= 0; i--) { 5288 input = inputs[i]; 5289 layer = this._getLayer(input.layerId).layer; 5290 5291 if (input.checked) { 5292 addedLayers.push(layer); 5293 } else if (!input.checked) { 5294 removedLayers.push(layer); 5295 } 5296 } 5297 5298 // Bugfix issue 2318: Should remove all old layers before readding new ones 5299 for (i = 0; i < removedLayers.length; i++) { 5300 if (this._map.hasLayer(removedLayers[i])) { 5301 this._map.removeLayer(removedLayers[i]); 5302 } 5303 } 5304 for (i = 0; i < addedLayers.length; i++) { 5305 if (!this._map.hasLayer(addedLayers[i])) { 5306 this._map.addLayer(addedLayers[i]); 5307 } 5308 } 5309 5310 this._handlingClick = false; 5311 5312 this._refocusOnMap(); 5313 }, 5314 5315 _checkDisabledLayers: function () { 5316 var inputs = this._layerControlInputs, 5317 input, 5318 layer, 5319 zoom = this._map.getZoom(); 5320 5321 for (var i = inputs.length - 1; i >= 0; i--) { 5322 input = inputs[i]; 5323 layer = this._getLayer(input.layerId).layer; 5324 input.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) || 5325 (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom); 5326 5327 } 5328 }, 5329 5330 _expandIfNotCollapsed: function () { 5331 if (this._map && !this.options.collapsed) { 5332 this.expand(); 5333 } 5334 return this; 5335 }, 5336 5337 _expand: function () { 5338 // Backward compatibility, remove me in 1.1. 5339 return this.expand(); 5340 }, 5341 5342 _collapse: function () { 5343 // Backward compatibility, remove me in 1.1. 5344 return this.collapse(); 5345 } 5346 5347}); 5348 5349 5350// @factory L.control.layers(baselayers?: Object, overlays?: Object, options?: Control.Layers options) 5351// Creates an attribution 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. 5352var layers = function (baseLayers, overlays, options) { 5353 return new Layers(baseLayers, overlays, options); 5354}; 5355 5356/* 5357 * @class Control.Zoom 5358 * @aka L.Control.Zoom 5359 * @inherits Control 5360 * 5361 * 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`. 5362 */ 5363 5364var Zoom = Control.extend({ 5365 // @section 5366 // @aka Control.Zoom options 5367 options: { 5368 position: 'topleft', 5369 5370 // @option zoomInText: String = '+' 5371 // The text set on the 'zoom in' button. 5372 zoomInText: '+', 5373 5374 // @option zoomInTitle: String = 'Zoom in' 5375 // The title set on the 'zoom in' button. 5376 zoomInTitle: 'Zoom in', 5377 5378 // @option zoomOutText: String = '−' 5379 // The text set on the 'zoom out' button. 5380 zoomOutText: '−', 5381 5382 // @option zoomOutTitle: String = 'Zoom out' 5383 // The title set on the 'zoom out' button. 5384 zoomOutTitle: 'Zoom out' 5385 }, 5386 5387 onAdd: function (map) { 5388 var zoomName = 'leaflet-control-zoom', 5389 container = create$1('div', zoomName + ' leaflet-bar'), 5390 options = this.options; 5391 5392 this._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle, 5393 zoomName + '-in', container, this._zoomIn); 5394 this._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle, 5395 zoomName + '-out', container, this._zoomOut); 5396 5397 this._updateDisabled(); 5398 map.on('zoomend zoomlevelschange', this._updateDisabled, this); 5399 5400 return container; 5401 }, 5402 5403 onRemove: function (map) { 5404 map.off('zoomend zoomlevelschange', this._updateDisabled, this); 5405 }, 5406 5407 disable: function () { 5408 this._disabled = true; 5409 this._updateDisabled(); 5410 return this; 5411 }, 5412 5413 enable: function () { 5414 this._disabled = false; 5415 this._updateDisabled(); 5416 return this; 5417 }, 5418 5419 _zoomIn: function (e) { 5420 if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) { 5421 this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1)); 5422 } 5423 }, 5424 5425 _zoomOut: function (e) { 5426 if (!this._disabled && this._map._zoom > this._map.getMinZoom()) { 5427 this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1)); 5428 } 5429 }, 5430 5431 _createButton: function (html, title, className, container, fn) { 5432 var link = create$1('a', className, container); 5433 link.innerHTML = html; 5434 link.href = '#'; 5435 link.title = title; 5436 5437 /* 5438 * Will force screen readers like VoiceOver to read this as "Zoom in - button" 5439 */ 5440 link.setAttribute('role', 'button'); 5441 link.setAttribute('aria-label', title); 5442 5443 disableClickPropagation(link); 5444 on(link, 'click', stop); 5445 on(link, 'click', fn, this); 5446 on(link, 'click', this._refocusOnMap, this); 5447 5448 return link; 5449 }, 5450 5451 _updateDisabled: function () { 5452 var map = this._map, 5453 className = 'leaflet-disabled'; 5454 5455 removeClass(this._zoomInButton, className); 5456 removeClass(this._zoomOutButton, className); 5457 5458 if (this._disabled || map._zoom === map.getMinZoom()) { 5459 addClass(this._zoomOutButton, className); 5460 } 5461 if (this._disabled || map._zoom === map.getMaxZoom()) { 5462 addClass(this._zoomInButton, className); 5463 } 5464 } 5465}); 5466 5467// @namespace Map 5468// @section Control options 5469// @option zoomControl: Boolean = true 5470// Whether a [zoom control](#control-zoom) is added to the map by default. 5471Map.mergeOptions({ 5472 zoomControl: true 5473}); 5474 5475Map.addInitHook(function () { 5476 if (this.options.zoomControl) { 5477 // @section Controls 5478 // @property zoomControl: Control.Zoom 5479 // The default zoom control (only available if the 5480 // [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map). 5481 this.zoomControl = new Zoom(); 5482 this.addControl(this.zoomControl); 5483 } 5484}); 5485 5486// @namespace Control.Zoom 5487// @factory L.control.zoom(options: Control.Zoom options) 5488// Creates a zoom control 5489var zoom = function (options) { 5490 return new Zoom(options); 5491}; 5492 5493/* 5494 * @class Control.Scale 5495 * @aka L.Control.Scale 5496 * @inherits Control 5497 * 5498 * 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`. 5499 * 5500 * @example 5501 * 5502 * ```js 5503 * L.control.scale().addTo(map); 5504 * ``` 5505 */ 5506 5507var Scale = Control.extend({ 5508 // @section 5509 // @aka Control.Scale options 5510 options: { 5511 position: 'bottomleft', 5512 5513 // @option maxWidth: Number = 100 5514 // Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500). 5515 maxWidth: 100, 5516 5517 // @option metric: Boolean = True 5518 // Whether to show the metric scale line (m/km). 5519 metric: true, 5520 5521 // @option imperial: Boolean = True 5522 // Whether to show the imperial scale line (mi/ft). 5523 imperial: true 5524 5525 // @option updateWhenIdle: Boolean = false 5526 // If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)). 5527 }, 5528 5529 onAdd: function (map) { 5530 var className = 'leaflet-control-scale', 5531 container = create$1('div', className), 5532 options = this.options; 5533 5534 this._addScales(options, className + '-line', container); 5535 5536 map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); 5537 map.whenReady(this._update, this); 5538 5539 return container; 5540 }, 5541 5542 onRemove: function (map) { 5543 map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); 5544 }, 5545 5546 _addScales: function (options, className, container) { 5547 if (options.metric) { 5548 this._mScale = create$1('div', className, container); 5549 } 5550 if (options.imperial) { 5551 this._iScale = create$1('div', className, container); 5552 } 5553 }, 5554 5555 _update: function () { 5556 var map = this._map, 5557 y = map.getSize().y / 2; 5558 5559 var maxMeters = map.distance( 5560 map.containerPointToLatLng([0, y]), 5561 map.containerPointToLatLng([this.options.maxWidth, y])); 5562 5563 this._updateScales(maxMeters); 5564 }, 5565 5566 _updateScales: function (maxMeters) { 5567 if (this.options.metric && maxMeters) { 5568 this._updateMetric(maxMeters); 5569 } 5570 if (this.options.imperial && maxMeters) { 5571 this._updateImperial(maxMeters); 5572 } 5573 }, 5574 5575 _updateMetric: function (maxMeters) { 5576 var meters = this._getRoundNum(maxMeters), 5577 label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; 5578 5579 this._updateScale(this._mScale, label, meters / maxMeters); 5580 }, 5581 5582 _updateImperial: function (maxMeters) { 5583 var maxFeet = maxMeters * 3.2808399, 5584 maxMiles, miles, feet; 5585 5586 if (maxFeet > 5280) { 5587 maxMiles = maxFeet / 5280; 5588 miles = this._getRoundNum(maxMiles); 5589 this._updateScale(this._iScale, miles + ' mi', miles / maxMiles); 5590 5591 } else { 5592 feet = this._getRoundNum(maxFeet); 5593 this._updateScale(this._iScale, feet + ' ft', feet / maxFeet); 5594 } 5595 }, 5596 5597 _updateScale: function (scale, text, ratio) { 5598 scale.style.width = Math.round(this.options.maxWidth * ratio) + 'px'; 5599 scale.innerHTML = text; 5600 }, 5601 5602 _getRoundNum: function (num) { 5603 var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), 5604 d = num / pow10; 5605 5606 d = d >= 10 ? 10 : 5607 d >= 5 ? 5 : 5608 d >= 3 ? 3 : 5609 d >= 2 ? 2 : 1; 5610 5611 return pow10 * d; 5612 } 5613}); 5614 5615 5616// @factory L.control.scale(options?: Control.Scale options) 5617// Creates an scale control with the given options. 5618var scale = function (options) { 5619 return new Scale(options); 5620}; 5621 5622/* 5623 * @class Control.Attribution 5624 * @aka L.Control.Attribution 5625 * @inherits Control 5626 * 5627 * 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. 5628 */ 5629 5630var Attribution = Control.extend({ 5631 // @section 5632 // @aka Control.Attribution options 5633 options: { 5634 position: 'bottomright', 5635 5636 // @option prefix: String = 'Leaflet' 5637 // The HTML text shown before the attributions. Pass `false` to disable. 5638 prefix: '<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>' 5639 }, 5640 5641 initialize: function (options) { 5642 setOptions(this, options); 5643 5644 this._attributions = {}; 5645 }, 5646 5647 onAdd: function (map) { 5648 map.attributionControl = this; 5649 this._container = create$1('div', 'leaflet-control-attribution'); 5650 disableClickPropagation(this._container); 5651 5652 // TODO ugly, refactor 5653 for (var i in map._layers) { 5654 if (map._layers[i].getAttribution) { 5655 this.addAttribution(map._layers[i].getAttribution()); 5656 } 5657 } 5658 5659 this._update(); 5660 5661 return this._container; 5662 }, 5663 5664 // @method setPrefix(prefix: String): this 5665 // Sets the text before the attributions. 5666 setPrefix: function (prefix) { 5667 this.options.prefix = prefix; 5668 this._update(); 5669 return this; 5670 }, 5671 5672 // @method addAttribution(text: String): this 5673 // Adds an attribution text (e.g. `'Vector data © Mapbox'`). 5674 addAttribution: function (text) { 5675 if (!text) { return this; } 5676 5677 if (!this._attributions[text]) { 5678 this._attributions[text] = 0; 5679 } 5680 this._attributions[text]++; 5681 5682 this._update(); 5683 5684 return this; 5685 }, 5686 5687 // @method removeAttribution(text: String): this 5688 // Removes an attribution text. 5689 removeAttribution: function (text) { 5690 if (!text) { return this; } 5691 5692 if (this._attributions[text]) { 5693 this._attributions[text]--; 5694 this._update(); 5695 } 5696 5697 return this; 5698 }, 5699 5700 _update: function () { 5701 if (!this._map) { return; } 5702 5703 var attribs = []; 5704 5705 for (var i in this._attributions) { 5706 if (this._attributions[i]) { 5707 attribs.push(i); 5708 } 5709 } 5710 5711 var prefixAndAttribs = []; 5712 5713 if (this.options.prefix) { 5714 prefixAndAttribs.push(this.options.prefix); 5715 } 5716 if (attribs.length) { 5717 prefixAndAttribs.push(attribs.join(', ')); 5718 } 5719 5720 this._container.innerHTML = prefixAndAttribs.join(' | '); 5721 } 5722}); 5723 5724// @namespace Map 5725// @section Control options 5726// @option attributionControl: Boolean = true 5727// Whether a [attribution control](#control-attribution) is added to the map by default. 5728Map.mergeOptions({ 5729 attributionControl: true 5730}); 5731 5732Map.addInitHook(function () { 5733 if (this.options.attributionControl) { 5734 new Attribution().addTo(this); 5735 } 5736}); 5737 5738// @namespace Control.Attribution 5739// @factory L.control.attribution(options: Control.Attribution options) 5740// Creates an attribution control. 5741var attribution = function (options) { 5742 return new Attribution(options); 5743}; 5744 5745Control.Layers = Layers; 5746Control.Zoom = Zoom; 5747Control.Scale = Scale; 5748Control.Attribution = Attribution; 5749 5750control.layers = layers; 5751control.zoom = zoom; 5752control.scale = scale; 5753control.attribution = attribution; 5754 5755/* 5756 L.Handler is a base class for handler classes that are used internally to inject 5757 interaction features like dragging to classes like Map and Marker. 5758*/ 5759 5760// @class Handler 5761// @aka L.Handler 5762// Abstract class for map interaction handlers 5763 5764var Handler = Class.extend({ 5765 initialize: function (map) { 5766 this._map = map; 5767 }, 5768 5769 // @method enable(): this 5770 // Enables the handler 5771 enable: function () { 5772 if (this._enabled) { return this; } 5773 5774 this._enabled = true; 5775 this.addHooks(); 5776 return this; 5777 }, 5778 5779 // @method disable(): this 5780 // Disables the handler 5781 disable: function () { 5782 if (!this._enabled) { return this; } 5783 5784 this._enabled = false;
5785 this.removeHooks(); 5786 return this; 5787 }, 5788 5789 // @method enabled(): Boolean 5790 // Returns `true` if the handler is enabled 5791 enabled: function () { 5792 return !!this._enabled; 5793 } 5794 5795 // @section Extension methods 5796 // Classes inheriting from `Handler` must implement the two following methods: 5797 // @method addHooks() 5798 // Called when the handler is enabled, should add event hooks. 5799 // @method removeHooks() 5800 // Called when the handler is disabled, should remove the event hooks added previously. 5801}); 5802 5803// @section There is static function which can be called without instantiating L.Handler: 5804// @function addTo(map: Map, name: String): this 5805// Adds a new Handler to the given map with the given name. 5806Handler.addTo = function (map, name) { 5807 map.addHandler(name, this); 5808 return this; 5809}; 5810 5811var Mixin = {Events: Events}; 5812 5813/* 5814 * @class Draggable 5815 * @aka L.Draggable 5816 * @inherits Evented 5817 * 5818 * A class for making DOM elements draggable (including touch support). 5819 * Used internally for map and marker dragging. Only works for elements 5820 * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition). 5821 * 5822 * @example 5823 * ```js 5824 * var draggable = new L.Draggable(elementToDrag); 5825 * draggable.enable(); 5826 * ``` 5827 */ 5828 5829var START = touch ? 'touchstart mousedown' : 'mousedown'; 5830var END = { 5831 mousedown: 'mouseup', 5832 touchstart: 'touchend', 5833 pointerdown: 'touchend', 5834 MSPointerDown: 'touchend' 5835}; 5836var MOVE = { 5837 mousedown: 'mousemove', 5838 touchstart: 'touchmove', 5839 pointerdown: 'touchmove', 5840 MSPointerDown: 'touchmove' 5841}; 5842 5843 5844var Draggable = Evented.extend({ 5845 5846 options: { 5847 // @section 5848 // @aka Draggable options 5849 // @option clickTolerance: Number = 3 5850 // The max number of pixels a user can shift the mouse pointer during a click 5851 // for it to be considered a valid click (as opposed to a mouse drag). 5852 clickTolerance: 3 5853 }, 5854 5855 // @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options) 5856 // Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default). 5857 initialize: function (element, dragStartTarget, preventOutline$$1, options) { 5858 setOptions(this, options); 5859 5860 this._element = element; 5861 this._dragStartTarget = dragStartTarget || element; 5862 this._preventOutline = preventOutline$$1; 5863 }, 5864 5865 // @method enable() 5866 // Enables the dragging ability 5867 enable: function () { 5868 if (this._enabled) { return; } 5869 5870 on(this._dragStartTarget, START, this._onDown, this); 5871 5872 this._enabled = true; 5873 }, 5874 5875 // @method disable() 5876 // Disables the dragging ability 5877 disable: function () { 5878 if (!this._enabled) { return; } 5879 5880 // If we're currently dragging this draggable, 5881 // disabling it counts as first ending the drag. 5882 if (Draggable._dragging === this) { 5883 this.finishDrag(); 5884 } 5885 5886 off(this._dragStartTarget, START, this._onDown, this); 5887 5888 this._enabled = false; 5889 this._moved = false; 5890 }, 5891 5892 _onDown: function (e) { 5893 // Ignore simulated events, since we handle both touch and 5894 // mouse explicitly; otherwise we risk getting duplicates of 5895 // touch events, see #4315. 5896 // Also ignore the event if disabled; this happens in IE11 5897 // under some circumstances, see #3666. 5898 if (e._simulated || !this._enabled) { return; } 5899 5900 this._moved = false; 5901 5902 if (hasClass(this._element, 'leaflet-zoom-anim')) { return; } 5903 5904 if (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; } 5905 Draggable._dragging = this; // Prevent dragging multiple objects at once. 5906 5907 if (this._preventOutline) { 5908 preventOutline(this._element); 5909 } 5910 5911 disableImageDrag(); 5912 disableTextSelection(); 5913 5914 if (this._moving) { return; } 5915 5916 // @event down: Event 5917 // Fired when a drag is about to start. 5918 this.fire('down'); 5919 5920 var first = e.touches ? e.touches[0] : e, 5921 sizedParent = getSizedParentNode(this._element); 5922 5923 this._startPoint = new Point(first.clientX, first.clientY); 5924 5925 // Cache the scale, so that we can continuously compensate for it during drag (_onMove). 5926 this._parentScale = getScale(sizedParent); 5927 5928 on(document, MOVE[e.type], this._onMove, this); 5929 on(document, END[e.type], this._onUp, this); 5930 }, 5931 5932 _onMove: function (e) { 5933 // Ignore simulated events, since we handle both touch and 5934 // mouse explicitly; otherwise we risk getting duplicates of 5935 // touch events, see #4315. 5936 // Also ignore the event if disabled; this happens in IE11 5937 // under some circumstances, see #3666. 5938 if (e._simulated || !this._enabled) { return; } 5939 5940 if (e.touches && e.touches.length > 1) { 5941 this._moved = true; 5942 return; 5943 } 5944 5945 var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e), 5946 offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint); 5947 5948 if (!offset.x && !offset.y) { return; } 5949 if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; } 5950 5951 // We assume that the parent container's position, border and scale do not change for the duration of the drag. 5952 // Therefore there is no need to account for the position and border (they are eliminated by the subtraction) 5953 // and we can use the cached value for the scale. 5954 offset.x /= this._parentScale.x; 5955 offset.y /= this._parentScale.y; 5956 5957 preventDefault(e); 5958 5959 if (!this._moved) { 5960 // @event dragstart: Event 5961 // Fired when a drag starts 5962 this.fire('dragstart'); 5963 5964 this._moved = true; 5965 this._startPos = getPosition(this._element).subtract(offset); 5966 5967 addClass(document.body, 'leaflet-dragging'); 5968 5969 this._lastTarget = e.target || e.srcElement; 5970 // IE and Edge do not give the <use> element, so fetch it 5971 // if necessary 5972 if ((window.SVGElementInstance) && (this._lastTarget instanceof SVGElementInstance)) { 5973 this._lastTarget = this._lastTarget.correspondingUseElement; 5974 } 5975 addClass(this._lastTarget, 'leaflet-drag-target'); 5976 } 5977 5978 this._newPos = this._startPos.add(offset); 5979 this._moving = true; 5980
5981 cancelAnimFrame(this._animRequest); 5982 this._lastEvent = e; 5983 this._animRequest = requestAnimFrame(this._updatePosition, this, true); 5984 }, 5985 5986 _updatePosition: function () { 5987 var e = {originalEvent: this._lastEvent}; 5988 5989 // @event predrag: Event 5990 // Fired continuously during dragging *before* each corresponding 5991 // update of the element's position. 5992 this.fire('predrag', e); 5993 setPosition(this._element, this._newPos); 5994 5995 // @event drag: Event 5996 // Fired continuously during dragging. 5997 this.fire('drag', e); 5998 }, 5999 6000 _onUp: function (e) { 6001 // Ignore simulated events, since we handle both touch and 6002 // mouse explicitly; otherwise we risk getting duplicates of 6003 // touch events, see #4315. 6004 // Also ignore the event if disabled; this happens in IE11 6005 // under some circumstances, see #3666. 6006 if (e._simulated || !this._enabled) { return; } 6007 this.finishDrag(); 6008 }, 6009 6010 finishDrag: function () { 6011 removeClass(document.body, 'leaflet-dragging'); 6012 6013 if (this._lastTarget) { 6014 removeClass(this._lastTarget, 'leaflet-drag-target'); 6015 this._lastTarget = null; 6016 } 6017 6018 for (var i in MOVE) { 6019 off(document, MOVE[i], this._onMove, this); 6020 off(document, END[i], this._onUp, this); 6021 } 6022 6023 enableImageDrag(); 6024 enableTextSelection(); 6025 6026 if (this._moved && this._moving) { 6027 // ensure drag is not fired after dragend 6028 cancelAnimFrame(this._animRequest); 6029 6030 // @event dragend: DragEndEvent 6031 // Fired when the drag ends. 6032 this.fire('dragend', { 6033 distance: this._newPos.distanceTo(this._startPos) 6034 }); 6035 } 6036 6037 this._moving = false; 6038 Draggable._dragging = false; 6039 } 6040 6041}); 6042 6043/* 6044 * @namespace LineUtil 6045 * 6046 * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast. 6047 */ 6048 6049// Simplify polyline with vertex reduction and Douglas-Peucker simplification. 6050// Improves rendering performance dramatically by lessening the number of points to draw. 6051 6052// @function simplify(points: Point[], tolerance: Number): Point[] 6053// Dramatically reduces the number of points in a polyline while retaining 6054// its shape and returns a new array of simplified points, using the 6055// [Douglas-Peucker algorithm](http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm). 6056// Used for a huge performance boost when processing/displaying Leaflet polylines for 6057// each zoom level and also reducing visual noise. tolerance affects the amount of 6058// simplification (lesser value means higher quality but slower and with more points). 6059// Also released as a separated micro-library [Simplify.js](http://mourner.github.com/simplify-js/). 6060function simplify(points, tolerance) { 6061 if (!tolerance || !points.length) { 6062 return points.slice(); 6063 } 6064 6065 var sqTolerance = tolerance * tolerance; 6066 6067 // stage 1: vertex reduction 6068 points = _reducePoints(points, sqTolerance); 6069 6070 // stage 2: Douglas-Peucker simplification 6071 points = _simplifyDP(points, sqTolerance); 6072 6073 return points; 6074} 6075 6076// @function pointToSegmentDistance(p: Point, p1: Point, p2: Point): Number 6077// Returns the distance between point `p` and segment `p1` to `p2`. 6078function pointToSegmentDistance(p, p1, p2) { 6079 return Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true)); 6080} 6081 6082// @function closestPointOnSegment(p: Point, p1: Point, p2: Point): Number 6083// Returns the closest point from a point `p` on a segment `p1` to `p2`. 6084function closestPointOnSegment(p, p1, p2) { 6085 return _sqClosestPointOnSegment(p, p1, p2); 6086} 6087 6088// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm 6089function _simplifyDP(points, sqTolerance) { 6090 6091 var len = points.length, 6092 ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array, 6093 markers = new ArrayConstructor(len); 6094 6095 markers[0] = markers[len - 1] = 1; 6096 6097 _simplifyDPStep(points, markers, sqTolerance, 0, len - 1); 6098 6099 var i, 6100 newPoints = []; 6101 6102 for (i = 0; i < len; i++) { 6103 if (markers[i]) { 6104 newPoints.push(points[i]); 6105 } 6106 } 6107 6108 return newPoints; 6109} 6110 6111function _simplifyDPStep(points, markers, sqTolerance, first, last) { 6112 6113 var maxSqDist = 0, 6114 index, i, sqDist; 6115 6116 for (i = first + 1; i <= last - 1; i++) { 6117 sqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true); 6118 6119 if (sqDist > maxSqDist) { 6120 index = i; 6121 maxSqDist = sqDist; 6122 } 6123 } 6124 6125 if (maxSqDist > sqTolerance) { 6126 markers[index] = 1; 6127 6128 _simplifyDPStep(points, markers, sqTolerance, first, index); 6129 _simplifyDPStep(points, markers, sqTolerance, index, last); 6130 } 6131} 6132 6133// reduce points that are too close to each other to a single point 6134function _reducePoints(points, sqTolerance) { 6135 var reducedPoints = [points[0]]; 6136 6137 for (var i = 1, prev = 0, len = points.length; i < len; i++) { 6138 if (_sqDist(points[i], points[prev]) > sqTolerance) { 6139 reducedPoints.push(points[i]); 6140 prev = i; 6141 } 6142 } 6143 if (prev < len - 1) { 6144 reducedPoints.push(points[len - 1]); 6145 } 6146 return reducedPoints; 6147} 6148 6149var _lastCode; 6150 6151// @function clipSegment(a: Point, b: Point, bounds: Bounds, useLastCode?: Boolean, roun
vendor: 66,773 bytes, lines 6151-8662
6151d?: Boolean): Point[]|Boolean 6152// Clips the segment a to b by rectangular bounds with the 6153// [Cohen-Sutherland algorithm](https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm) 6154// (modifying the segment points directly!). Used by Leaflet to only show polyline 6155// points that are on the screen or near, increasing performance. 6156function clipSegment(a, b, bounds, useLastCode, round) { 6157 var codeA = useLastCode ? _lastCode : _getBitCode(a, bounds), 6158 codeB = _getBitCode(b, bounds), 6159 6160 codeOut, p, newCode; 6161 6162 // save 2nd code to avoid calculating it on the next segment 6163 _lastCode = codeB; 6164 6165 while (true) { 6166 // if a,b is inside the clip window (trivial accept) 6167 if (!(codeA | codeB)) { 6168 return [a, b]; 6169 } 6170 6171 // if a,b is outside the clip window (trivial reject) 6172 if (codeA & codeB) { 6173 return false; 6174 } 6175 6176 // other cases 6177 codeOut = codeA || codeB; 6178 p = _getEdgeIntersection(a, b, codeOut, bounds, round); 6179 newCode = _getBitCode(p, bounds); 6180 6181 if (codeOut === codeA) { 6182 a = p; 6183 codeA = newCode; 6184 } else { 6185 b = p; 6186 codeB = newCode; 6187 } 6188 } 6189} 6190 6191function _getEdgeIntersection(a, b, code, bounds, round) { 6192 var dx = b.x - a.x, 6193 dy = b.y - a.y, 6194 min = bounds.min, 6195 max = bounds.max, 6196 x, y; 6197 6198 if (code & 8) { // top 6199 x = a.x + dx * (max.y - a.y) / dy; 6200 y = max.y; 6201 6202 } else if (code & 4) { // bottom 6203 x = a.x + dx * (min.y - a.y) / dy; 6204 y = min.y; 6205 6206 } else if (code & 2) { // right 6207 x = max.x; 6208 y = a.y + dy * (max.x - a.x) / dx; 6209 6210 } else if (code & 1) { // left 6211 x = min.x; 6212 y = a.y + dy * (min.x - a.x) / dx; 6213 } 6214 6215 return new Point(x, y, round); 6216} 6217 6218function _getBitCode(p, bounds) { 6219 var code = 0; 6220 6221 if (p.x < bounds.min.x) { // left 6222 code |= 1; 6223 } else if (p.x > bounds.max.x) { // right 6224 code |= 2; 6225 } 6226 6227 if (p.y < bounds.min.y) { // bottom 6228 code |= 4; 6229 } else if (p.y > bounds.max.y) { // top 6230 code |= 8; 6231 } 6232 6233 return code; 6234} 6235 6236// square distance (to avoid unnecessary Math.sqrt calls) 6237function _sqDist(p1, p2) { 6238 var dx = p2.x - p1.x, 6239 dy = p2.y - p1.y; 6240 return dx * dx + dy * dy; 6241} 6242 6243// return closest point on segment or distance to that point 6244function _sqClosestPointOnSegment(p, p1, p2, sqDist) { 6245 var x = p1.x, 6246 y = p1.y, 6247 dx = p2.x - x, 6248 dy = p2.y - y, 6249 dot = dx * dx + dy * dy, 6250 t; 6251 6252 if (dot > 0) { 6253 t = ((p.x - x) * dx + (p.y - y) * dy) / dot; 6254 6255 if (t > 1) { 6256 x = p2.x; 6257 y = p2.y; 6258 } else if (t > 0) { 6259 x += dx * t; 6260 y += dy * t; 6261 } 6262 } 6263 6264 dx = p.x - x; 6265 dy = p.y - y; 6266 6267 return sqDist ? dx * dx + dy * dy : new Point(x, y); 6268} 6269 6270 6271// @function isFlat(latlngs: LatLng[]): Boolean 6272// Returns true if `latlngs` is a flat array, false is nested. 6273function isFlat(latlngs) { 6274 return !isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined'); 6275} 6276 6277function _flat(latlngs) { 6278 console.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.'); 6279 return isFlat(latlngs); 6280} 6281 6282 6283var LineUtil = (Object.freeze || Object)({ 6284 simplify: simplify, 6285 pointToSegmentDistance: pointToSegmentDistance, 6286 closestPointOnSegment: closestPointOnSegment, 6287 clipSegment: clipSegment, 6288 _getEdgeIntersection: _getEdgeIntersection, 6289 _getBitCode: _getBitCode, 6290 _sqClosestPointOnSegment: _sqClosestPointOnSegment, 6291 isFlat: isFlat, 6292 _flat: _flat 6293}); 6294 6295/* 6296 * @namespace PolyUtil 6297 * Various utility functions for polygon geometries. 6298 */ 6299 6300/* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[] 6301 * 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)). 6302 * Used by Leaflet to only show polygon points that are on the screen or near, increasing 6303 * performance. Note that polygon points needs different algorithm for clipping 6304 * than polyline, so there's a separate method for it. 6305 */ 6306function clipPolygon(points, bounds, round) { 6307 var clippedPoints, 6308 edges = [1, 4, 2, 8], 6309 i, j, k, 6310 a, b, 6311 len, edge, p; 6312 6313 for (i = 0, len = points.length; i < len; i++) { 6314 points[i]._code = _getBitCode(points[i], bounds); 6315 } 6316 6317 // for each edge (left, bottom, right, top) 6318 for (k = 0; k < 4; k++) { 6319 edge = edges[k]; 6320 clippedPoints = []; 6321 6322 for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { 6323 a = points[i]; 6324 b = points[j]; 6325 6326 // if a is inside the clip window 6327 if (!(a._code & edge)) { 6328 // if b is outside the clip window (a->b goes out of screen) 6329 if (b._code & edge) { 6330 p = _getEdgeIntersection(b, a, edge, bounds, round); 6331 p._code = _getBitCode(p, bounds); 6332 clippedPoints.push(p); 6333 } 6334 clippedPoints.push(a); 6335 6336 // else if b is inside the clip window (a->b enters the screen) 6337 } else if (!(b._code & edge)) { 6338 p = _getEdgeIntersection(b, a, edge, bounds, round); 6339 p._code = _getBitCode(p, bounds); 6340 clippedPoints.push(p); 6341 } 6342 } 6343 points = clippedPoints; 6344 } 6345 6346 return points; 6347} 6348 6349 6350var PolyUtil = (Object.freeze || Object)({ 6351 clipPolygon: clipPolygon 6352}); 6353 6354/* 6355 * @namespace Projection 6356 * @section 6357 * Leaflet comes with a set of already defined Projections out of the box: 6358 * 6359 * @projection L.Projection.LonLat 6360 * 6361 * Equirectangular, or Plate Carree projection â the most simple projection, 6362 * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as 6363 * latitude. Also suitable for flat worlds, e.g. game maps. Used by the 6364 * `EPSG:4326` and `Simple` CRS. 6365 */ 6366 6367var LonLat = { 6368 project: function (latlng) { 6369 return new Point(latlng.lng, latlng.lat); 6370 }, 6371 6372 unproject: function (point) { 6373 return new LatLng(point.y, point.x); 6374 }, 6375 6376 bounds: new Bounds([-180, -90], [180, 90]) 6377}; 6378 6379/* 6380 * @namespace Projection 6381 * @projection L.Projection.Mercator 6382 * 6383 * Elliptical Mercator projection â more complex than Spherical Mercator. Takes into account that Earth is a geoid, not a perfect sphere. Used by the EPSG:3395 CRS. 6384 */ 6385 6386var Mercator = { 6387 R: 6378137, 6388 R_MINOR: 6356752.314245179, 6389 6390 bounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]), 6391 6392 project: function (latlng) { 6393 var d = Math.PI / 180, 6394 r = this.R, 6395 y = latlng.lat * d, 6396 tmp = this.R_MINOR / r, 6397 e = Math.sqrt(1 - tmp * tmp), 6398 con = e * Math.sin(y); 6399 6400 var ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2); 6401 y = -r * Math.log(Math.max(ts, 1E-10)); 6402 6403 return new Point(latlng.lng * d * r, y); 6404 }, 6405 6406 unproject: function (point) { 6407 var d = 180 / Math.PI, 6408 r = this.R, 6409 tmp = this.R_MINOR / r, 6410 e = Math.sqrt(1 - tmp * tmp), 6411 ts = Math.exp(-point.y / r), 6412 phi = Math.PI / 2 - 2 * Math.atan(ts); 6413 6414 for (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) { 6415 con = e * Math.sin(phi); 6416 con = Math.pow((1 - con) / (1 + con), e / 2); 6417 dphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi; 6418 phi += dphi; 6419 } 6420 6421 return new LatLng(phi * d, point.x * d / r); 6422 } 6423}; 6424 6425/* 6426 * @class Projection 6427 6428 * An object with methods for projecting geographical coordinates of the world onto 6429 * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection). 6430 6431 * @property bounds: Bounds 6432 * The bounds (specified in CRS units) where the projection is valid 6433 6434 * @method project(latlng: LatLng): Point 6435 * Projects geographical coordinates into a 2D point. 6436 * Only accepts actual `L.LatLng` instances, not arrays. 6437 6438 * @method unproject(point: Point): LatLng 6439 * The inverse of `project`. Projects a 2D point into a geographical location. 6440 * Only accepts actual `L.Point` instances, not arrays. 6441 6442 * Note that the projection instances do not inherit from Leafet's `Class` object, 6443 * and can't be instantiated. Also, new classes can't inherit from them, 6444 * and methods can't be added to them with the `include` function. 6445 6446 */ 6447 6448 6449 6450 6451var index = (Object.freeze || Object)({ 6452 LonLat: LonLat, 6453 Mercator: Mercator, 6454 SphericalMercator: SphericalMercator 6455}); 6456 6457/* 6458 * @namespace CRS 6459 * @crs L.CRS.EPSG3395 6460 * 6461 * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection. 6462 */ 6463var EPSG3395 = extend({}, Earth, { 6464 code: 'EPSG:3395', 6465 projection: Mercator, 6466 6467 transformation: (function () { 6468 var scale = 0.5 / (Math.PI * Mercator.R); 6469 return toTransformation(scale, 0.5, -scale, 0.5); 6470 }()) 6471}); 6472 6473/* 6474 * @namespace CRS 6475 * @crs L.CRS.EPSG4326 6476 * 6477 * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection. 6478 * 6479 * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic), 6480 * which is a breaking change from 0.7.x behaviour. If you are using a `TileLayer` 6481 * with this CRS, ensure that there are two 256x256 pixel tiles covering the 6482 * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90), 6483 * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set. 6484 */ 6485 6486var EPSG4326 = extend({}, Earth, { 6487 code: 'EPSG:4326', 6488 projection: LonLat, 6489 transformation: toTransformation(1 / 180, 1, -1 / 180, 0.5) 6490}); 6491 6492/* 6493 * @namespace CRS 6494 * @crs L.CRS.Simple 6495 * 6496 * A simple CRS that maps longitude and latitude into `x` and `y` directly. 6497 * May be used for maps of flat surfaces (e.g. game maps). Note that the `y` 6498 * axis should still be inverted (going from bottom to top). `distance()` returns 6499 * simple euclidean distance. 6500 */ 6501 6502var Simple = extend({}, CRS, { 6503 projection: LonLat, 6504 transformation: toTransformation(1, 0, -1, 0), 6505 6506 scale: function (zoom) { 6507 return Math.pow(2, zoom); 6508 }, 6509 6510 zoom: function (scale) { 6511 return Math.log(scale) / Math.LN2; 6512 }, 6513 6514 distance: function (latlng1, latlng2) { 6515 var dx = latlng2.lng - latlng1.lng, 6516 dy = latlng2.lat - latlng1.lat; 6517 6518 return Math.sqrt(dx * dx + dy * dy); 6519 }, 6520 6521 infinite: true 6522}); 6523 6524CRS.Earth = Earth; 6525CRS.EPSG3395 = EPSG3395; 6526CRS.EPSG3857 = EPSG3857; 6527CRS.EPSG900913 = EPSG900913; 6528CRS.EPSG4326 = EPSG4326; 6529CRS.Simple = Simple; 6530 6531/* 6532 * @class Layer 6533 * @inherits Evented 6534 * @aka L.Layer 6535 * @aka ILayer 6536 * 6537 * A set of methods from the Layer base class that all Leaflet layers use. 6538 * Inherits all methods, options and events from `L.Evented`. 6539 * 6540 * @example 6541 * 6542 * ```js 6543 * var layer = L.Marker(latlng).addTo(map); 6544 * layer.addTo(map); 6545 * layer.remove(); 6546 * ``` 6547 * 6548 * @event add: Event 6549 * Fired after the layer is added to a map 6550 * 6551 * @event remove: Event 6552 * Fired after the layer is removed from a map 6553 */ 6554 6555 6556var Layer = Evented.extend({ 6557 6558 // Classes extending `L.Layer` will inherit the following options: 6559 options: { 6560 // @option pane: String = 'overlayPane' 6561 // 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. 6562 pane: 'overlayPane', 6563 6564 // @option attribution: String = null 6565 // String to be shown in the attribution control, describes the layer data, e.g. "© Mapbox". 6566 attribution: null, 6567 6568 bubblingMouseEvents: true 6569 }, 6570 6571 /* @section 6572 * Classes extending `L.Layer` will inherit the following methods: 6573 * 6574 * @method addTo(map: Map|LayerGroup): this 6575 * Adds the layer to the given map or layer group. 6576 */ 6577 addTo: function (map) { 6578 map.addLayer(this); 6579 return this; 6580 }, 6581 6582 // @method remove: this 6583 // Removes the layer from the map it is currently active on. 6584 remove: function () { 6585 return this.removeFrom(this._map || this._mapToAdd); 6586 }, 6587 6588 // @method removeFrom(map: Map): this 6589 // Removes the layer from the given map 6590 removeFrom: function (obj) { 6591 if (obj) { 6592 obj.removeLayer(this); 6593 } 6594 return this; 6595 }, 6596 6597 // @method getPane(name? : String): HTMLElement 6598 // Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer. 6599 getPane: function (name) { 6600 return this._map.getPane(name ? (this.options[name] || name) : this.options.pane); 6601 }, 6602 6603 addInteractiveTarget: function (targetEl) { 6604 this._map._targets[stamp(targetEl)] = this; 6605 return this; 6606 }, 6607 6608 removeInteractiveTarget: function (targetEl) { 6609 delete this._map._targets[stamp(targetEl)]; 6610 return this; 6611 }, 6612 6613 // @method getAttribution: String 6614 // Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution). 6615 getAttribution: function () { 6616 return this.options.attribution; 6617 }, 6618 6619 _layerAdd: function (e) { 6620 var map = e.target; 6621 6622 // check in case layer gets added and then removed before the map is ready 6623 if (!map.hasLayer(this)) { return; } 6624 6625 this._map = map; 6626 this._zoomAnimated = map._zoomAnimated; 6627 6628 if (this.getEvents) { 6629 var events = this.getEvents(); 6630 map.on(events, this); 6631 this.once('remove', function () { 6632 map.off(events, this); 6633 }, this); 6634 } 6635 6636 this.onAdd(map); 6637 6638 if (this.getAttribution && map.attributionControl) { 6639 map.attributionControl.addAttribution(this.getAttribution()); 6640 } 6641 6642 this.fire('add'); 6643 map.fire('layeradd', {layer: this}); 6644 } 6645}); 6646 6647/* @section Extension methods 6648 * @uninheritable 6649 * 6650 * Every layer should extend from `L.Layer` and (re-)implement the following methods. 6651 * 6652 * @method onAdd(map: Map): this 6653 * 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). 6654 * 6655 * @method onRemove(map: Map): this 6656 * 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). 6657 * 6658 * @method getEvents(): Object 6659 * 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. 6660 * 6661 * @method getAttribution(): String 6662 * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible. 6663 * 6664 * @method beforeAdd(map: Map): this 6665 * 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. 6666 */ 6667 6668 6669/* @namespace Map 6670 * @section Layer events 6671 * 6672 * @event layeradd: LayerEvent 6673 * Fired when a new layer is added to the map. 6674 * 6675 * @event layerremove: LayerEvent 6676 * Fired when some layer is removed from the map 6677 * 6678 * @section Methods for Layers and Controls 6679 */ 6680Map.include({ 6681 // @method addLayer(layer: Layer): this 6682 // Adds the given layer to the map 6683 addLayer: function (layer) { 6684 if (!layer._layerAdd) { 6685 throw new Error('The provided object is not a Layer.'); 6686 } 6687 6688 var id = stamp(layer); 6689 if (this._layers[id]) { return this; } 6690 this._layers[id] = layer; 6691 6692 layer._mapToAdd = this; 6693 6694 if (layer.beforeAdd) { 6695 layer.beforeAdd(this); 6696 } 6697 6698 this.whenReady(layer._layerAdd, layer); 6699 6700 return this; 6701 }, 6702 6703 // @method removeLayer(layer: Layer): this 6704 // Removes the given layer from the map. 6705 removeLayer: function (layer) { 6706 var id = stamp(layer); 6707 6708 if (!this._layers[id]) { return this; } 6709 6710 if (this._loaded) { 6711 layer.onRemove(this); 6712 } 6713 6714 if (layer.getAttribution && this.attributionControl) { 6715 this.attributionControl.removeAttribution(layer.getAttribution()); 6716 } 6717 6718 delete this._layers[id]; 6719 6720 if (this._loaded) { 6721 this.fire('layerremove', {layer: layer}); 6722 layer.fire('remove'); 6723 } 6724 6725 layer._map = layer._mapToAdd = null; 6726 6727 return this; 6728 }, 6729 6730 // @method hasLayer(layer: Layer): Boolean 6731 // Returns `true` if the given layer is currently added to the map 6732 hasLayer: function (layer) { 6733 return !!layer && (stamp(layer) in this._layers); 6734 }, 6735 6736 /* @method eachLayer(fn: Function, context?: Object): this 6737 * Iterates over the layers of the map, optionally specifying context of the iterator function. 6738 * ``` 6739 * map.eachLayer(function(layer){ 6740 * layer.bindPopup('Hello'); 6741 * }); 6742 * ``` 6743 */ 6744 eachLayer: function (method, context) { 6745 for (var i in this._layers) { 6746 method.call(context, this._layers[i]); 6747 } 6748 return this; 6749 }, 6750 6751 _addLayers: function (layers) { 6752 layers = layers ? (isArray(layers) ? layers : [layers]) : []; 6753 6754 for (var i = 0, len = layers.length; i < len; i++) { 6755 this.addLayer(layers[i]); 6756 } 6757 }, 6758 6759 _addZoomLimit: function (layer) { 6760 if (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) { 6761 this._zoomBoundLayers[stamp(layer)] = layer; 6762 this._updateZoomLevels(); 6763 } 6764 }, 6765 6766 _removeZoomLimit: function (layer) { 6767 var id = stamp(layer); 6768 6769 if (this._zoomBoundLayers[id]) { 6770 delete this._zoomBoundLayers[id]; 6771 this._updateZoomLevels(); 6772 } 6773 }, 6774 6775 _updateZoomLevels: function () { 6776 var minZoom = Infinity, 6777 maxZoom = -Infinity, 6778 oldZoomSpan = this._getZoomSpan(); 6779 6780 for (var i in this._zoomBoundLayers) { 6781 var options = this._zoomBoundLayers[i].options; 6782 6783 minZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom); 6784 maxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom); 6785 } 6786 6787 this._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom; 6788 this._layersMinZoom = minZoom === Infinity ? undefined : minZoom; 6789 6790 // @section Map state change events 6791 // @event zoomlevelschange: Event 6792 // Fired when the number of zoomlevels on the map is changed due 6793 // to adding or removing a layer. 6794 if (oldZoomSpan !== this._getZoomSpan()) { 6795 this.fire('zoomlevelschange'); 6796 } 6797 6798 if (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) { 6799 this.setZoom(this._layersMaxZoom); 6800 } 6801 if (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) { 6802 this.setZoom(this._layersMinZoom); 6803 } 6804 } 6805}); 6806 6807/* 6808 * @class LayerGroup 6809 * @aka L.LayerGroup 6810 * @inherits Layer 6811 * 6812 * Used to group several layers and handle them as one. If you add it to the map, 6813 * any layers added or removed from the group will be added/removed on the map as 6814 * well. Extends `Layer`. 6815 * 6816 * @example 6817 * 6818 * ```js 6819 * L.layerGroup([marker1, marker2]) 6820 * .addLayer(polyline) 6821 * .addTo(map); 6822 * ``` 6823 */ 6824 6825var LayerGroup = Layer.extend({ 6826 6827 initialize: function (layers, options) { 6828 setOptions(this, options); 6829 6830 this._layers = {}; 6831 6832 var i, len; 6833 6834 if (layers) { 6835 for (i = 0, len = layers.length; i < len; i++) { 6836 this.addLayer(layers[i]); 6837 } 6838 } 6839 }, 6840 6841 // @method addLayer(layer: Layer): this 6842 // Adds the given layer to the group. 6843 addLayer: function (layer) { 6844 var id = this.getLayerId(layer); 6845 6846 this._layers[id] = layer; 6847 6848 if (this._map) { 6849 this._map.addLayer(layer); 6850 } 6851 6852 return this; 6853 }, 6854 6855 // @method removeLayer(layer: Layer): this 6856 // Removes the given layer from the group. 6857 // @alternative 6858 // @method removeLayer(id: Number): this 6859 // Removes the layer with the given internal ID from the group. 6860 removeLayer: function (layer) { 6861 var id = layer in this._layers ? layer : this.getLayerId(layer); 6862 6863 if (this._map && this._layers[id]) { 6864 this._map.removeLayer(this._layers[id]); 6865 } 6866 6867 delete this._layers[id]; 6868 6869 return this; 6870 }, 6871 6872 // @method hasLayer(layer: Layer): Boolean 6873 // Returns `true` if the given layer is currently added to the group. 6874 // @alternative 6875 // @method hasLayer(id: Number): Boolean 6876 // Returns `true` if the given internal ID is currently added to the group. 6877 hasLayer: function (layer) { 6878 return !!layer && (layer in this._layers || this.getLayerId(layer) in this._layers); 6879 }, 6880 6881 // @method clearLayers(): this 6882 // Removes all the layers from the group. 6883 clearLayers: function () { 6884 return this.eachLayer(this.removeLayer, this); 6885 }, 6886 6887 // @method invoke(methodName: String, â¦): this 6888 // Calls `methodName` on every layer contained in this group, passing any 6889 // additional parameters. Has no effect if the layers contained do not 6890 // implement `methodName`. 6891 invoke: function (methodName) { 6892 var args = Array.prototype.slice.call(arguments, 1), 6893 i, layer; 6894 6895 for (i in this._layers) { 6896 layer = this._layers[i]; 6897 6898 if (layer[methodName]) { 6899 layer[methodName].apply(layer, args); 6900 } 6901 } 6902 6903 return this; 6904 }, 6905 6906 onAdd: function (map) { 6907 this.eachLayer(map.addLayer, map); 6908 }, 6909 6910 onRemove: function (map) { 6911 this.eachLayer(map.removeLayer, map); 6912 }, 6913 6914 // @method eachLayer(fn: Function, context?: Object): this 6915 // Iterates over the layers of the group, optionally specifying context of the iterator function. 6916 // ```js 6917 // group.eachLayer(function (layer) { 6918 // layer.bindPopup('Hello'); 6919 // }); 6920 // ``` 6921 eachLayer: function (method, context) { 6922 for (var i in this._layers) { 6923 method.call(context, this._layers[i]); 6924 } 6925 return this; 6926 }, 6927 6928 // @method getLayer(id: Number): Layer 6929 // Returns the layer with the given internal ID. 6930 getLayer: function (id) { 6931 return this._layers[id]; 6932 }, 6933 6934 // @method getLayers(): Layer[] 6935 // Returns an array of all the layers added to the group. 6936 getLayers: function () { 6937 var layers = []; 6938 this.eachLayer(layers.push, layers); 6939 return layers; 6940 }, 6941 6942 // @method setZIndex(zIndex: Number): this 6943 // Calls `setZIndex` on every layer contained in this group, passing the z-index. 6944 setZIndex: function (zIndex) { 6945 return this.invoke('setZIndex', zIndex); 6946 }, 6947 6948 // @method getLayerId(layer: Layer): Number 6949 // Returns the internal ID for a layer 6950 getLayerId: function (layer) { 6951 return stamp(layer); 6952 } 6953}); 6954 6955 6956// @factory L.layerGroup(layers?: Layer[], options?: Object) 6957// Create a layer group, optionally given an initial set of layers and an `options` object. 6958var layerGroup = function (layers, options) { 6959 return new LayerGroup(layers, options); 6960}; 6961 6962/* 6963 * @class FeatureGroup 6964 * @aka L.FeatureGroup 6965 * @inherits LayerGroup 6966 * 6967 * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers: 6968 * * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip)) 6969 * * Events are propagated to the `FeatureGroup`, so if the group has an event 6970 * handler, it will handle events from any of the layers. This includes mouse events 6971 * and custom events. 6972 * * Has `layeradd` and `layerremove` events 6973 * 6974 * @example 6975 * 6976 * ```js 6977 * L.featureGroup([marker1, marker2, polyline]) 6978 * .bindPopup('Hello world!') 6979 * .on('click', function() { alert('Clicked on a member of the group!'); }) 6980 * .addTo(map); 6981 * ``` 6982 */ 6983 6984var FeatureGroup = LayerGroup.extend({ 6985 6986 addLayer: function (layer) { 6987 if (this.hasLayer(layer)) { 6988 return this; 6989 } 6990 6991 layer.addEventParent(this); 6992 6993 LayerGroup.prototype.addLayer.call(this, layer); 6994 6995 // @event layeradd: LayerEvent 6996 // Fired when a layer is added to this `FeatureGroup` 6997 return this.fire('layeradd', {layer: layer}); 6998 }, 6999 7000 removeLayer: function (layer) { 7001 if (!this.hasLayer(layer)) { 7002 return this; 7003 } 7004 if (layer in this._layers) { 7005 layer = this._layers[layer]; 7006 } 7007 7008 layer.removeEventParent(this); 7009 7010 LayerGroup.prototype.removeLayer.call(this, layer); 7011 7012 // @event layerremove: LayerEvent 7013 // Fired when a layer is removed from this `FeatureGroup` 7014 return this.fire('layerremove', {layer: layer}); 7015 }, 7016 7017 // @method setStyle(style: Path options): this 7018 // Sets the given path options to each layer of the group that has a `setStyle` method. 7019 setStyle: function (style) { 7020 return this.invoke('setStyle', style); 7021 }, 7022 7023 // @method bringToFront(): this 7024 // Brings the layer group to the top of all other layers 7025 bringToFront: function () { 7026 return this.invoke('bringToFront'); 7027 }, 7028 7029 // @method bringToBack(): this 7030 // Brings the layer group to the back of all other layers 7031 bringToBack: function () { 7032 return this.invoke('bringToBack'); 7033 }, 7034 7035 // @method getBounds(): LatLngBounds 7036 // Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children). 7037 getBounds: function () { 7038 var bounds = new LatLngBounds(); 7039 7040 for (var id in this._layers) { 7041 var layer = this._layers[id]; 7042 bounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng()); 7043 } 7044 return bounds; 7045 } 7046}); 7047 7048// @factory L.featureGroup(layers: Layer[]) 7049// Create a feature group, optionally given an initial set of layers. 7050var featureGroup = function (layers) { 7051 return new FeatureGroup(layers); 7052}; 7053 7054/* 7055 * @class Icon 7056 * @aka L.Icon 7057 * 7058 * Represents an icon to provide when creating a marker. 7059 * 7060 * @example 7061 * 7062 * ```js 7063 * var myIcon = L.icon({ 7064 * iconUrl: 'my-icon.png', 7065 * iconRetinaUrl: '[email protected]', 7066 * iconSize: [38, 95], 7067 * iconAnchor: [22, 94], 7068 * popupAnchor: [-3, -76], 7069 * shadowUrl: 'my-icon-shadow.png', 7070 * shadowRetinaUrl: '[email protected]', 7071 * shadowSize: [68, 95], 7072 * shadowAnchor: [22, 94] 7073 * }); 7074 * 7075 * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map); 7076 * ``` 7077 * 7078 * `L.Icon.Default` extends `L.Icon` and is the blue icon Leaflet uses for markers by default. 7079 * 7080 */ 7081 7082var Icon = Class.extend({ 7083 7084 /* @section 7085 * @aka Icon options 7086 * 7087 * @option iconUrl: String = null 7088 * **(required)** The URL to the icon image (absolute or relative to your script path). 7089 * 7090 * @option iconRetinaUrl: String = null 7091 * The URL to a retina sized version of the icon image (absolute or relative to your 7092 * script path). Used for Retina screen devices. 7093 * 7094 * @option iconSize: Point = null 7095 * Size of the icon image in pixels. 7096 * 7097 * @option iconAnchor: Point = null 7098 * The coordinates of the "tip" of the icon (relative to its top left corner). The icon 7099 * will be aligned so that this point is at the marker's geographical location. Centered 7100 * by default if size is specified, also can be set in CSS with negative margins. 7101 * 7102 * @option popupAnchor: Point = [0, 0] 7103 * The coordinates of the point from which popups will "open", relative to the icon anchor. 7104 * 7105 * @option tooltipAnchor: Point = [0, 0] 7106 * The coordinates of the point from which tooltips will "open", relative to the icon anchor. 7107 * 7108 * @option shadowUrl: String = null 7109 * The URL to the icon shadow image. If not specified, no shadow image will be created. 7110 * 7111 * @option shadowRetinaUrl: String = null 7112 * 7113 * @option shadowSize: Point = null 7114 * Size of the shadow image in pixels. 7115 * 7116 * @option shadowAnchor: Point = null 7117 * The coordinates of the "tip" of the shadow (relative to its top left corner) (the same 7118 * as iconAnchor if not specified). 7119 * 7120 * @option className: String = '' 7121 * A custom class name to assign to both icon and shadow images. Empty by default. 7122 */ 7123 7124 options: { 7125 popupAnchor: [0, 0], 7126 tooltipAnchor: [0, 0] 7127 }, 7128 7129 initialize: function (options) { 7130 setOptions(this, options); 7131 }, 7132 7133 // @method createIcon(oldIcon?: HTMLElement): HTMLElement 7134 // Called internally when the icon has to be shown, returns a `<img>` HTML element 7135 // styled according to the options. 7136 createIcon: function (oldIcon) { 7137 return this._createIcon('icon', oldIcon); 7138 }, 7139 7140 // @method createShadow(oldIcon?: HTMLElement): HTMLElement 7141 // As `createIcon`, but for the shadow beneath it. 7142 createShadow: function (oldIcon) { 7143 return this._createIcon('shadow', oldIcon); 7144 }, 7145 7146 _createIcon: function (name, oldIcon) { 7147 var src = this._getIconUrl(name); 7148 7149 if (!src) { 7150 if (name === 'icon') { 7151 throw new Error('iconUrl not set in Icon options (see the docs).'); 7152 } 7153 return null; 7154 } 7155 7156 var img = this._createImg(src, oldIcon && oldIcon.tagName === 'IMG' ? oldIcon : null); 7157 this._setIconStyles(img, name); 7158 7159 return img; 7160 }, 7161 7162 _setIconStyles: function (img, name) { 7163 var options = this.options; 7164 var sizeOption = options[name + 'Size']; 7165 7166 if (typeof sizeOption === 'number') { 7167 sizeOption = [sizeOption, sizeOption]; 7168 } 7169 7170 var size = toPoint(sizeOption), 7171 anchor = toPoint(name === 'shadow' && options.shadowAnchor || options.iconAnchor || 7172 size && size.divideBy(2, true)); 7173 7174 img.className = 'leaflet-marker-' + name + ' ' + (options.className || ''); 7175 7176 if (anchor) { 7177 img.style.marginLeft = (-anchor.x) + 'px'; 7178 img.style.marginTop = (-anchor.y) + 'px'; 7179 } 7180 7181 if (size) { 7182 img.style.width = size.x + 'px'; 7183 img.style.height = size.y + 'px'; 7184 } 7185 }, 7186 7187 _createImg: function (src, el) { 7188 el = el || document.createElement('img'); 7189 el.src = src; 7190 return el; 7191 }, 7192 7193 _getIconUrl: function (name) { 7194 return retina && this.options[name + 'RetinaUrl'] || this.options[name + 'Url']; 7195 } 7196}); 7197 7198 7199// @factory L.icon(options: Icon options) 7200// Creates an icon instance with the given options. 7201function icon(options) { 7202 return new Icon(options); 7203} 7204 7205/* 7206 * @miniclass Icon.Default (Icon) 7207 * @aka L.Icon.Default 7208 * @section 7209 * 7210 * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when 7211 * no icon is specified. Points to the blue marker image distributed with Leaflet 7212 * releases. 7213 * 7214 * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options` 7215 * (which is a set of `Icon options`). 7216 * 7217 * If you want to _completely_ replace the default icon, override the 7218 * `L.Marker.prototype.options.icon` with your own icon instead. 7219 */ 7220 7221var IconDefault = Icon.extend({ 7222 7223 options: { 7224 iconUrl: 'marker-icon.png', 7225 iconRetinaUrl: 'marker-icon-2x.png', 7226 shadowUrl: 'marker-shadow.png', 7227 iconSize: [25, 41], 7228 iconAnchor: [12, 41], 7229 popupAnchor: [1, -34], 7230 tooltipAnchor: [16, -28], 7231 shadowSize: [41, 41] 7232 }, 7233 7234 _getIconUrl: function (name) { 7235 if (!IconDefault.imagePath) { // Deprecated, backwards-compatibility only 7236 IconDefault.imagePath = this._detectIconPath(); 7237 } 7238 7239 // @option imagePath: String 7240 // `Icon.Default` will try to auto-detect the location of the 7241 // blue icon images. If you are placing these images in a non-standard 7242 // way, set this option to point to the right path. 7243 return (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name); 7244 }, 7245 7246 _detectIconPath: function () { 7247 var el = create$1('div', 'leaflet-default-icon-path', document.body); 7248 var path = getStyle(el, 'background-image') || 7249 getStyle(el, 'backgroundImage'); // IE8 7250 7251 document.body.removeChild(el); 7252 7253 if (path === null || path.indexOf('url') !== 0) { 7254 path = ''; 7255 } else { 7256 path = path.replace(/^url\(["']?/, '').replace(/marker-icon\.png["']?\)$/, ''); 7257 } 7258 7259 return path; 7260 } 7261}); 7262 7263/* 7264 * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable. 7265 */ 7266 7267 7268/* @namespace Marker 7269 * @section Interaction handlers 7270 * 7271 * 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: 7272 * 7273 * ```js 7274 * marker.dragging.disable(); 7275 * ``` 7276 * 7277 * @property dragging: Handler 7278 * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)). 7279 */ 7280 7281var MarkerDrag = Handler.extend({ 7282 initialize: function (marker) { 7283 this._marker = marker; 7284 }, 7285 7286 addHooks: function () { 7287 var icon = this._marker._icon; 7288 7289 if (!this._draggable) { 7290 this._draggable = new Draggable(icon, icon, true); 7291 } 7292 7293 this._draggable.on({ 7294 dragstart: this._onDragStart, 7295 predrag: this._onPreDrag, 7296 drag: this._onDrag, 7297 dragend: this._onDragEnd 7298 }, this).enable(); 7299 7300 addClass(icon, 'leaflet-marker-draggable'); 7301 }, 7302 7303 removeHooks: function () { 7304 this._draggable.off({ 7305 dragstart: this._onDragStart, 7306 predrag: this._onPreDrag, 7307 drag: this._onDrag, 7308 dragend: this._onDragEnd 7309 }, this).disable(); 7310 7311 if (this._marker._icon) { 7312 removeClass(this._marker._icon, 'leaflet-marker-draggable'); 7313 } 7314 }, 7315 7316 moved: function () { 7317 return this._draggable && this._draggable._moved; 7318 }, 7319 7320 _adjustPan: function (e) { 7321 var marker = this._marker, 7322 map = marker._map, 7323 speed = this._marker.options.autoPanSpeed, 7324 padding = this._marker.options.autoPanPadding, 7325 iconPos = getPosition(marker._icon), 7326 bounds = map.getPixelBounds(), 7327 origin = map.getPixelOrigin(); 7328 7329 var panBounds = toBounds( 7330 bounds.min._subtract(origin).add(padding), 7331 bounds.max._subtract(origin).subtract(padding) 7332 ); 7333 7334 if (!panBounds.contains(iconPos)) { 7335 // Compute incremental movement 7336 var movement = toPoint( 7337 (Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) - 7338 (Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x), 7339 7340 (Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) - 7341 (Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y) 7342 ).multiplyBy(speed); 7343 7344 map.panBy(movement, {animate: false}); 7345 7346 this._draggable._newPos._add(movement); 7347 this._draggable._startPos._add(movement); 7348 7349 setPosition(marker._icon, this._draggable._newPos); 7350 this._onDrag(e); 7351 7352 this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e)); 7353 } 7354 }, 7355 7356 _onDragStart: function () { 7357 // @section Dragging events 7358 // @event dragstart: Event 7359 // Fired when the user starts dragging the marker. 7360 7361 // @event movestart: Event 7362 // Fired when the marker starts moving (because of dragging). 7363 7364 this._oldLatLng = this._marker.getLatLng(); 7365 this._marker 7366 .closePopup() 7367 .fire('movestart') 7368 .fire('dragstart'); 7369 }, 7370 7371 _onPreDrag: function (e) { 7372 if (this._marker.options.autoPan) { 7373 cancelAnimFrame(this._panRequest); 7374 this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e)); 7375 } 7376 }, 7377 7378 _onDrag: function (e) { 7379 var marker = this._marker, 7380 shadow = marker._shadow, 7381 iconPos = getPosition(marker._icon), 7382 latlng = marker._map.layerPointToLatLng(iconPos); 7383 7384 // update shadow position 7385 if (shadow) { 7386 setPosition(shadow, iconPos); 7387 } 7388 7389 marker._latlng = latlng; 7390 e.latlng = latlng; 7391 e.oldLatLng = this._oldLatLng; 7392 7393 // @event drag: Event 7394 // Fired repeatedly while the user drags the marker. 7395 marker 7396 .fire('move', e) 7397 .fire('drag', e); 7398 }, 7399 7400 _onDragEnd: function (e) { 7401 // @event dragend: DragEndEvent 7402 // Fired when the user stops dragging the marker. 7403 7404 cancelAnimFrame(this._panRequest); 7405 7406 // @event moveend: Event 7407 // Fired when the marker stops moving (because of dragging). 7408 delete this._oldLatLng; 7409 this._marker 7410 .fire('moveend') 7411 .fire('dragend', e); 7412 } 7413}); 7414 7415/* 7416 * @class Marker 7417 * @inherits Interactive layer 7418 * @aka L.Marker 7419 * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`. 7420 * 7421 * @example 7422 * 7423 * ```js 7424 * L.marker([50.5, 30.5]).addTo(map); 7425 * ``` 7426 */ 7427 7428var Marker = Layer.extend({ 7429 7430 // @section 7431 // @aka Marker options 7432 options: { 7433 // @option icon: Icon = * 7434 // Icon instance to use for rendering the marker. 7435 // See [Icon documentation](#L.Icon) for details on how to customize the marker icon. 7436 // If not specified, a common instance of `L.Icon.Default` is used. 7437 icon: new IconDefault(), 7438 7439 // Option inherited from "Interactive layer" abstract class 7440 interactive: true, 7441 7442 // @option keyboard: Boolean = true 7443 // Whether the marker can be tabbed to with a keyboard and clicked by pressing enter. 7444 keyboard: true, 7445 7446 // @option title: String = '' 7447 // Text for the browser tooltip that appear on marker hover (no tooltip by default). 7448 title: '', 7449 7450 // @option alt: String = '' 7451 // Text for the `alt` attribute of the icon image (useful for accessibility). 7452 alt: '', 7453 7454 // @option zIndexOffset: Number = 0 7455 // 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). 7456 zIndexOffset: 0, 7457 7458 // @option opacity: Number = 1.0 7459 // The opacity of the marker. 7460 opacity: 1, 7461 7462 // @option riseOnHover: Boolean = false 7463 // If `true`, the marker will get on top of others when you hover the mouse over it. 7464 riseOnHover: false, 7465 7466 // @option riseOffset: Number = 250 7467 // The z-index offset used for the `riseOnHover` feature. 7468 riseOffset: 250, 7469 7470 // @option pane: String = 'markerPane' 7471 // `Map pane` where the markers icon will be added. 7472 pane: 'markerPane', 7473 7474 // @option bubblingMouseEvents: Boolean = false 7475 // When `true`, a mouse event on this marker will trigger the same event on the map 7476 // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used). 7477 bubblingMouseEvents: false, 7478 7479 // @section Draggable marker options 7480 // @option draggable: Boolean = false 7481 // Whether the marker is draggable with mouse/touch or not. 7482 draggable: false, 7483 7484 // @option autoPan: Boolean = false 7485 // Whether to pan the map when dragging this marker near its edge or not. 7486 autoPan: false, 7487 7488 // @option autoPanPadding: Point = Point(50, 50) 7489 // Distance (in pixels to the left/right and to the top/bottom) of the 7490 // map edge to start panning the map. 7491 autoPanPadding: [50, 50], 7492 7493 // @option autoPanSpeed: Number = 10 7494 // Number of pixels the map should pan by. 7495 autoPanSpeed: 10 7496 }, 7497 7498 /* @section 7499 * 7500 * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods: 7501 */ 7502 7503 initialize: function (latlng, options) { 7504 setOptions(this, options); 7505 this._latlng = toLatLng(latlng); 7506 }, 7507 7508 onAdd: function (map) { 7509 this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation; 7510 7511 if (this._zoomAnimated) { 7512 map.on('zoomanim', this._animateZoom, this); 7513 } 7514 7515 this._initIcon(); 7516 this.update(); 7517 }, 7518 7519 onRemove: function (map) { 7520 if (this.dragging && this.dragging.enabled()) { 7521 this.options.draggable = true; 7522 this.dragging.removeHooks(); 7523 } 7524 delete this.dragging; 7525 7526 if (this._zoomAnimated) { 7527 map.off('zoomanim', this._animateZoom, this); 7528 } 7529 7530 this._removeIcon(); 7531 this._removeShadow(); 7532 }, 7533 7534 getEvents: function () { 7535 return { 7536 zoom: this.update, 7537 viewreset: this.update 7538 }; 7539 }, 7540 7541 // @method getLatLng: LatLng 7542 // Returns the current geographical position of the marker. 7543 getLatLng: function () { 7544 return this._latlng; 7545 }, 7546 7547 // @method setLatLng(latlng: LatLng): this 7548 // Changes the marker position to the given point. 7549 setLatLng: function (latlng) { 7550 var oldLatLng = this._latlng; 7551 this._latlng = toLatLng(latlng); 7552 this.update(); 7553 7554 // @event move: Event 7555 // 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`. 7556 return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng}); 7557 }, 7558 7559 // @method setZIndexOffset(offset: Number): this 7560 // Changes the [zIndex offset](#marker-zindexoffset) of the marker. 7561 setZIndexOffset: function (offset) { 7562 this.options.zIndexOffset = offset; 7563 return this.update(); 7564 }, 7565 7566 // @method setIcon(icon: Icon): this 7567 // Changes the marker icon. 7568 setIcon: function (icon) { 7569 7570 this.options.icon = icon; 7571 7572 if (this._map) { 7573 this._initIcon(); 7574 this.update(); 7575 } 7576 7577 if (this._popup) { 7578 this.bindPopup(this._popup, this._popup.options); 7579 } 7580 7581 return this; 7582 }, 7583 7584 getElement: function () { 7585 return this._icon; 7586 }, 7587 7588 update: function () { 7589 7590 if (this._icon && this._map) { 7591 var pos = this._map.latLngToLayerPoint(this._latlng).round(); 7592 this._setPos(pos); 7593 } 7594 7595 return this; 7596 }, 7597 7598 _initIcon: function () { 7599 var options = this.options, 7600 classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide'); 7601 7602 var icon = options.icon.createIcon(this._icon), 7603 addIcon = false; 7604 7605 // if we're not reusing the icon, remove the old one and init new one 7606 if (icon !== this._icon) { 7607 if (this._icon) { 7608 this._removeIcon(); 7609 } 7610 addIcon = true; 7611 7612 if (options.title) { 7613 icon.title = options.title; 7614 } 7615 7616 if (icon.tagName === 'IMG') { 7617 icon.alt = options.alt || ''; 7618 } 7619 } 7620 7621 addClass(icon, classToAdd); 7622 7623 if (options.keyboard) { 7624 icon.tabIndex = '0'; 7625 } 7626 7627 this._icon = icon; 7628 7629 if (options.riseOnHover) { 7630 this.on({ 7631 mouseover: this._bringToFront, 7632 mouseout: this._resetZIndex 7633 }); 7634 } 7635 7636 var newShadow = options.icon.createShadow(this._shadow), 7637 addShadow = false; 7638 7639 if (newShadow !== this._shadow) { 7640 this._removeShadow(); 7641 addShadow = true; 7642 } 7643 7644 if (newShadow) { 7645 addClass(newShadow, classToAdd); 7646 newShadow.alt = ''; 7647 } 7648 this._shadow = newShadow; 7649 7650 7651 if (options.opacity < 1) { 7652 this._updateOpacity(); 7653 } 7654 7655 7656 if (addIcon) { 7657 this.getPane().appendChild(this._icon); 7658 } 7659 this._initInteraction(); 7660 if (newShadow && addShadow) { 7661 this.getPane('shadowPane').appendChild(this._shadow); 7662 } 7663 }, 7664 7665 _removeIcon: function () { 7666 if (this.options.riseOnHover) { 7667 this.off({ 7668 mouseover: this._bringToFront, 7669 mouseout: this._resetZIndex 7670 }); 7671 } 7672 7673 remove(this._icon); 7674 this.removeInteractiveTarget(this._icon); 7675 7676 this._icon = null; 7677 }, 7678 7679 _removeShadow: function () { 7680 if (this._shadow) { 7681 remove(this._shadow); 7682 } 7683 this._shadow = null; 7684 }, 7685 7686 _setPos: function (pos) { 7687 setPosition(this._icon, pos); 7688 7689 if (this._shadow) { 7690 setPosition(this._shadow, pos); 7691 } 7692 7693 this._zIndex = pos.y + this.options.zIndexOffset; 7694 7695 this._resetZIndex(); 7696 }, 7697 7698 _updateZIndex: function (offset) { 7699 this._icon.style.zIndex = this._zIndex + offset; 7700 }, 7701 7702 _animateZoom: function (opt) { 7703 var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); 7704 7705 this._setPos(pos); 7706 }, 7707 7708 _initInteraction: function () { 7709 7710 if (!this.options.interactive) { return; } 7711 7712 addClass(this._icon, 'leaflet-interactive'); 7713 7714 this.addInteractiveTarget(this._icon); 7715 7716 if (MarkerDrag) { 7717 var draggable = this.options.draggable; 7718 if (this.dragging) { 7719 draggable = this.dragging.enabled(); 7720 this.dragging.disable(); 7721 } 7722 7723 this.dragging = new MarkerDrag(this); 7724 7725 if (draggable) { 7726 this.dragging.enable(); 7727 } 7728 } 7729 }, 7730 7731 // @method setOpacity(opacity: Number): this 7732 // Changes the opacity of the marker. 7733 setOpacity: function (opacity) { 7734 this.options.opacity = opacity; 7735 if (this._map) { 7736 this._updateOpacity(); 7737 } 7738 7739 return this; 7740 }, 7741 7742 _updateOpacity: function () { 7743 var opacity = this.options.opacity; 7744 7745 setOpacity(this._icon, opacity); 7746 7747 if (this._shadow) { 7748 setOpacity(this._shadow, opacity); 7749 } 7750 }, 7751 7752 _bringToFront: function () { 7753 this._updateZIndex(this.options.riseOffset); 7754 }, 7755 7756 _resetZIndex: function () { 7757 this._updateZIndex(0); 7758 }, 7759 7760 _getPopupAnchor: function () { 7761 return this.options.icon.options.popupAnchor; 7762 }, 7763 7764 _getTooltipAnchor: function () { 7765 return this.options.icon.options.tooltipAnchor; 7766 } 7767}); 7768 7769 7770// factory L.marker(latlng: LatLng, options? : Marker options) 7771 7772// @factory L.marker(latlng: LatLng, options? : Marker options) 7773// Instantiates a Marker object given a geographical point and optionally an options object. 7774function marker(latlng, options) { 7775 return new Marker(latlng, options); 7776} 7777 7778/* 7779 * @class Path 7780 * @aka L.Path 7781 * @inherits Interactive layer 7782 * 7783 * An abstract class that contains options and constants shared between vector 7784 * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`. 7785 */ 7786 7787var Path = Layer.extend({ 7788 7789 // @section 7790 // @aka Path options 7791 options: { 7792 // @option stroke: Boolean = true 7793 // Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles. 7794 stroke: true, 7795 7796 // @option color: String = '#3388ff' 7797 // Stroke color 7798 color: '#3388ff', 7799 7800 // @option weight: Number = 3 7801 // Stroke width in pixels 7802 weight: 3, 7803 7804 // @option opacity: Number = 1.0 7805 // Stroke opacity 7806 opacity: 1, 7807 7808 // @option lineCap: String= 'round' 7809 // A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke. 7810 lineCap: 'round', 7811 7812 // @option lineJoin: String = 'round' 7813 // A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke. 7814 lineJoin: 'round', 7815 7816 // @option dashArray: String = null 7817 // 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). 7818 dashArray: null, 7819 7820 // @option dashOffset: String = null 7821 // 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). 7822 dashOffset: null, 7823 7824 // @option fill: Boolean = depends 7825 // Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles. 7826 fill: false, 7827 7828 // @option fillColor: String = * 7829 // Fill color. Defaults to the value of the [`color`](#path-color) option 7830 fillColor: null, 7831 7832 // @option fillOpacity: Number = 0.2 7833 // Fill opacity. 7834 fillOpacity: 0.2, 7835 7836 // @option fillRule: String = 'evenodd' 7837 // A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined. 7838 fillRule: 'evenodd', 7839 7840 // className: '', 7841 7842 // Option inherited from "Interactive layer" abstract class 7843 interactive: true, 7844 7845 // @option bubblingMouseEvents: Boolean = true 7846 // When `true`, a mouse event on this path will trigger the same event on the map 7847 // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used). 7848 bubblingMouseEvents: true 7849 }, 7850 7851 beforeAdd: function (map) { 7852 // Renderer is set here because we need to call renderer.getEvents 7853 // before this.getEvents. 7854 this._renderer = map.getRenderer(this); 7855 }, 7856 7857 onAdd: function () { 7858 this._renderer._initPath(this); 7859 this._reset(); 7860 this._renderer._addPath(this); 7861 }, 7862 7863 onRemove: function () { 7864 this._renderer._removePath(this); 7865 }, 7866 7867 // @method redraw(): this 7868 // Redraws the layer. Sometimes useful after you changed the coordinates that the path uses. 7869 redraw: function () { 7870 if (this._map) { 7871 this._renderer._updatePath(this); 7872 } 7873 return this; 7874 }, 7875 7876 // @method setStyle(style: Path options): this 7877 // Changes the appearance of a Path based on the options in the `Path options` object. 7878 setStyle: function (style) { 7879 setOptions(this, style); 7880 if (this._renderer) { 7881 this._renderer._updateStyle(this); 7882 } 7883 return this; 7884 }, 7885 7886 // @method bringToFront(): this 7887 // Brings the layer to the top of all path layers. 7888 bringToFront: function () { 7889 if (this._renderer) { 7890 this._renderer._bringToFront(this); 7891 } 7892 return this; 7893 }, 7894 7895 // @method bringToBack(): this 7896 // Brings the layer to the bottom of all path layers. 7897 bringToBack: function () { 7898 if (this._renderer) { 7899 this._renderer._bringToBack(this); 7900 } 7901 return this; 7902 }, 7903 7904 getElement: function () { 7905 return this._path; 7906 }, 7907 7908 _reset: function () { 7909 // defined in child classes 7910 this._project(); 7911 this._update(); 7912 }, 7913 7914 _clickTolerance: function () { 7915 // used when doing hit detection for Canvas layers 7916 return (this.options.stroke ? this.options.weight / 2 : 0) + this._renderer.options.tolerance; 7917 } 7918}); 7919 7920/* 7921 * @class CircleMarker 7922 * @aka L.CircleMarker 7923 * @inherits Path 7924 * 7925 * A circle of a fixed size with radius specified in pixels. Extends `Path`. 7926 */ 7927 7928var CircleMarker = Path.extend({ 7929 7930 // @section 7931 // @aka CircleMarker options 7932 options: { 7933 fill: true, 7934 7935 // @option radius: Number = 10 7936 // Radius of the circle marker, in pixels 7937 radius: 10 7938 }, 7939 7940 initialize: function (latlng, options) { 7941 setOptions(this, options); 7942 this._latlng = toLatLng(latlng); 7943 this._radius = this.options.radius; 7944 }, 7945 7946 // @method setLatLng(latLng: LatLng): this 7947 // Sets the position of a circle marker to a new location. 7948 setLatLng: function (latlng) { 7949 this._latlng = toLatLng(latlng); 7950 this.redraw(); 7951 return this.fire('move', {latlng: this._latlng}); 7952 }, 7953 7954 // @method getLatLng(): LatLng 7955 // Returns the current geographical position of the circle marker 7956 getLatLng: function () { 7957 return this._latlng; 7958 }, 7959 7960 // @method setRadius(radius: Number): this 7961 // Sets the radius of a circle marker. Units are in pixels. 7962 setRadius: function (radius) { 7963 this.options.radius = this._radius = radius; 7964 return this.redraw(); 7965 }, 7966 7967 // @method getRadius(): Number 7968 // Returns the current radius of the circle 7969 getRadius: function () { 7970 return this._radius; 7971 }, 7972 7973 setStyle : function (options) { 7974 var radius = options && options.radius || this._radius; 7975 Path.prototype.setStyle.call(this, options); 7976 this.setRadius(radius); 7977 return this; 7978 }, 7979 7980 _project: function () { 7981 this._point = this._map.latLngToLayerPoint(this._latlng); 7982 this._updateBounds(); 7983 }, 7984 7985 _updateBounds: function () { 7986 var r = this._radius, 7987 r2 = this._radiusY || r, 7988 w = this._clickTolerance(), 7989 p = [r + w, r2 + w]; 7990 this._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p)); 7991 }, 7992 7993 _update: function () { 7994 if (this._map) { 7995 this._updatePath(); 7996 } 7997 }, 7998 7999 _updatePath: function () { 8000 this._renderer._updateCircle(this); 8001 }, 8002 8003 _empty: function () { 8004 return this._radius && !this._renderer._bounds.intersects(this._pxBounds); 8005 }, 8006 8007 // Needed by the `Canvas` renderer for interactivity 8008 _containsPoint: function (p) { 8009 return p.distanceTo(this._point) <= this._radius + this._clickTolerance(); 8010 } 8011}); 8012 8013 8014// @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options) 8015// Instantiates a circle marker object given a geographical point, and an optional options object. 8016function circleMarker(latlng, options) { 8017 return new CircleMarker(latlng, options); 8018} 8019 8020/* 8021 * @class Circle 8022 * @aka L.Circle 8023 * @inherits CircleMarker 8024 * 8025 * A class for drawing circle overlays on a map. Extends `CircleMarker`. 8026 * 8027 * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion). 8028 * 8029 * @example 8030 * 8031 * ```js 8032 * L.circle([50.5, 30.5], {radius: 200}).addTo(map); 8033 * ``` 8034 */ 8035 8036var Circle = CircleMarker.extend({ 8037 8038 initialize: function (latlng, options, legacyOptions) { 8039 if (typeof options === 'number') { 8040 // Backwards compatibility with 0.7.x factory (latlng, radius, options?) 8041 options = extend({}, legacyOptions, {radius: options}); 8042 } 8043 setOptions(this, options); 8044 this._latlng = toLatLng(latlng); 8045 8046 if (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); } 8047 8048 // @section 8049 // @aka Circle options 8050 // @option radius: Number; Radius of the circle, in meters. 8051 this._mRadius = this.options.radius; 8052 }, 8053 8054 // @method setRadius(radius: Number): this 8055 // Sets the radius of a circle. Units are in meters. 8056 setRadius: function (radius) { 8057 this._mRadius = radius; 8058 return this.redraw(); 8059 }, 8060 8061 // @method getRadius(): Number 8062 // Returns the current radius of a circle. Units are in meters. 8063 getRadius: function () { 8064 return this._mRadius; 8065 }, 8066 8067 // @method getBounds(): LatLngBounds 8068 // Returns the `LatLngBounds` of the path. 8069 getBounds: function () { 8070 var half = [this._radius, this._radiusY || this._radius]; 8071 8072 return new LatLngBounds( 8073 this._map.layerPointToLatLng(this._point.subtract(half)), 8074 this._map.layerPointToLatLng(this._point.add(half))); 8075 }, 8076 8077 setStyle: Path.prototype.setStyle, 8078 8079 _project: function () { 8080 8081 var lng = this._latlng.lng, 8082 lat = this._latlng.lat, 8083 map = this._map, 8084 crs = map.options.crs; 8085 8086 if (crs.distance === Earth.distance) { 8087 var d = Math.PI / 180, 8088 latR = (this._mRadius / Earth.R) / d, 8089 top = map.project([lat + latR, lng]), 8090 bottom = map.project([lat - latR, lng]), 8091 p = top.add(bottom).divideBy(2), 8092 lat2 = map.unproject(p).lat, 8093 lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) / 8094 (Math.cos(lat * d) * Math.cos(lat2 * d))) / d; 8095 8096 if (isNaN(lngR) || lngR === 0) { 8097 lngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425 8098 } 8099 8100 this._point = p.subtract(map.getPixelOrigin()); 8101 this._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x; 8102 this._radiusY = p.y - top.y; 8103 8104 } else { 8105 var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0])); 8106 8107 this._point = map.latLngToLayerPoint(this._latlng); 8108 this._radius = this._point.x - map.latLngToLayerPoint(latlng2).x; 8109 } 8110 8111 this._updateBounds(); 8112 } 8113}); 8114 8115// @factory L.circle(latlng: LatLng, options?: Circle options) 8116// Instantiates a circle object given a geographical point, and an options object 8117// which contains the circle radius. 8118// @alternative 8119// @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options) 8120// Obsolete way of instantiating a circle, for compatibility with 0.7.x code. 8121// Do not use in new applications or plugins. 8122function circle(latlng, options, legacyOptions) { 8123 return new Circle(latlng, options, legacyOptions); 8124} 8125 8126/* 8127 * @class Polyline 8128 * @aka L.Polyline 8129 * @inherits Path 8130 * 8131 * A class for drawing polyline overlays on a map. Extends `Path`. 8132 * 8133 * @example 8134 * 8135 * ```js 8136 * // create a red polyline from an array of LatLng points 8137 * var latlngs = [ 8138 * [45.51, -122.68], 8139 * [37.77, -122.43], 8140 * [34.04, -118.2] 8141 * ]; 8142 * 8143 * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map); 8144 * 8145 * // zoom the map to the polyline 8146 * map.fitBounds(polyline.getBounds()); 8147 * ``` 8148 * 8149 * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape: 8150 * 8151 * ```js 8152 * // create a red polyline from an array of arrays of LatLng points 8153 * var latlngs = [ 8154 * [[45.51, -122.68], 8155 * [37.77, -122.43], 8156 * [34.04, -118.2]], 8157 * [[40.78, -73.91], 8158 * [41.83, -87.62], 8159 * [32.76, -96.72]] 8160 * ]; 8161 * ``` 8162 */ 8163 8164 8165var Polyline = Path.extend({ 8166 8167 // @section 8168 // @aka Polyline options 8169 options: { 8170 // @option smoothFactor: Number = 1.0 8171 // How much to simplify the polyline on each zoom level. More means 8172 // better performance and smoother look, and less means more accurate representation. 8173 smoothFactor: 1.0, 8174 8175 // @option noClip: Boolean = false 8176 // Disable polyline clipping. 8177 noClip: false 8178 }, 8179 8180 initialize: function (latlngs, options) { 8181 setOptions(this, options); 8182 this._setLatLngs(latlngs); 8183 }, 8184 8185 // @method getLatLngs(): LatLng[] 8186 // Returns an array of the points in the path, or nested arrays of points in case of multi-polyline. 8187 getLatLngs: function () { 8188 return this._latlngs; 8189 }, 8190 8191 // @method setLatLngs(latlngs: LatLng[]): this 8192 // Replaces all the points in the polyline with the given array of geographical points. 8193 setLatLngs: function (latlngs) { 8194 this._setLatLngs(latlngs); 8195 return this.redraw(); 8196 }, 8197 8198 // @method isEmpty(): Boolean 8199 // Returns `true` if the Polyline has no LatLngs. 8200 isEmpty: function () { 8201 return !this._latlngs.length; 8202 }, 8203 8204 // @method closestLayerPoint(p: Point): Point 8205 // Returns the point closest to `p` on the Polyline. 8206 closestLayerPoint: function (p) { 8207 var minDistance = Infinity, 8208 minPoint = null, 8209 closest = _sqClosestPointOnSegment, 8210 p1, p2; 8211 8212 for (var j = 0, jLen = this._parts.length; j < jLen; j++) { 8213 var points = this._parts[j]; 8214 8215 for (var i = 1, len = points.length; i < len; i++) { 8216 p1 = points[i - 1]; 8217 p2 = points[i]; 8218 8219 var sqDist = closest(p, p1, p2, true); 8220 8221 if (sqDist < minDistance) { 8222 minDistance = sqDist; 8223 minPoint = closest(p, p1, p2); 8224 } 8225 } 8226 } 8227 if (minPoint) { 8228 minPoint.distance = Math.sqrt(minDistance); 8229 } 8230 return minPoint; 8231 }, 8232 8233 // @method getCenter(): LatLng 8234 // Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline. 8235 getCenter: function () { 8236 // throws error when not yet added to map as this center calculation requires projected coordinates 8237 if (!this._map) { 8238 throw new Error('Must add layer to map before using getCenter()'); 8239 } 8240 8241 var i, halfDist, segDist, dist, p1, p2, ratio, 8242 points = this._rings[0], 8243 len = points.length; 8244 8245 if (!len) { return null; } 8246 8247 // polyline centroid algorithm; only uses the first ring if there are multiple 8248 8249 for (i = 0, halfDist = 0; i < len - 1; i++) { 8250 halfDist += points[i].distanceTo(points[i + 1]) / 2; 8251 } 8252 8253 // The line is so small in the current view that all points are on the same pixel. 8254 if (halfDist === 0) { 8255 return this._map.layerPointToLatLng(points[0]); 8256 } 8257 8258 for (i = 0, dist = 0; i < len - 1; i++) { 8259 p1 = points[i]; 8260 p2 = points[i + 1]; 8261 segDist = p1.distanceTo(p2); 8262 dist += segDist; 8263 8264 if (dist > halfDist) { 8265 ratio = (dist - halfDist) / segDist; 8266 return this._map.layerPointToLatLng([ 8267 p2.x - ratio * (p2.x - p1.x), 8268 p2.y - ratio * (p2.y - p1.y) 8269 ]); 8270 } 8271 } 8272 }, 8273 8274 // @method getBounds(): LatLngBounds 8275 // Returns the `LatLngBounds` of the path. 8276 getBounds: function () { 8277 return this._bounds; 8278 }, 8279 8280 // @method addLatLng(latlng: LatLng, latlngs? LatLng[]): this 8281 // Adds a given point to the polyline. By default, adds to the first ring of 8282 // the polyline in case of a multi-polyline, but can be overridden by passing 8283 // a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)). 8284 addLatLng: function (latlng, latlngs) { 8285 latlngs = latlngs || this._defaultShape(); 8286 latlng = toLatLng(latlng); 8287 latlngs.push(latlng); 8288 this._bounds.extend(latlng); 8289 return this.redraw(); 8290 }, 8291 8292 _setLatLngs: function (latlngs) { 8293 this._bounds = new LatLngBounds(); 8294 this._latlngs = this._convertLatLngs(latlngs); 8295 }, 8296 8297 _defaultShape: function () { 8298 return isFlat(this._latlngs) ? this._latlngs : this._latlngs[0]; 8299 }, 8300 8301 // recursively convert latlngs input into actual LatLng instances; calculate bounds along the way 8302 _convertLatLngs: function (latlngs) { 8303 var result = [], 8304 flat = isFlat(latlngs); 8305 8306 for (var i = 0, len = latlngs.length; i < len; i++) { 8307 if (flat) { 8308 result[i] = toLatLng(latlngs[i]); 8309 this._bounds.extend(result[i]); 8310 } else { 8311 result[i] = this._convertLatLngs(latlngs[i]); 8312 } 8313 } 8314 8315 return result; 8316 }, 8317 8318 _project: function () { 8319 var pxBounds = new Bounds(); 8320 this._rings = []; 8321 this._projectLatlngs(this._latlngs, this._rings, pxBounds); 8322 8323 var w = this._clickTolerance(), 8324 p = new Point(w, w); 8325 8326 if (this._bounds.isValid() && pxBounds.isValid()) { 8327 pxBounds.min._subtract(p); 8328 pxBounds.max._add(p); 8329 this._pxBounds = pxBounds; 8330 } 8331 }, 8332 8333 // recursively turns latlngs into a set of rings with projected coordinates 8334 _projectLatlngs: function (latlngs, result, projectedBounds) { 8335 var flat = latlngs[0] instanceof LatLng, 8336 len = latlngs.length, 8337 i, ring; 8338 8339 if (flat) { 8340 ring = []; 8341 for (i = 0; i < len; i++) { 8342 ring[i] = this._map.latLngToLayerPoint(latlngs[i]); 8343 projectedBounds.extend(ring[i]); 8344 } 8345 result.push(ring); 8346 } else { 8347 for (i = 0; i < len; i++) { 8348 this._projectLatlngs(latlngs[i], result, projectedBounds); 8349 } 8350 } 8351 }, 8352 8353 // clip polyline by renderer bounds so that we have less to render for performance 8354 _clipPoints: function () { 8355 var bounds = this._renderer._bounds; 8356 8357 this._parts = []; 8358 if (!this._pxBounds || !this._pxBounds.intersects(bounds)) { 8359 return; 8360 } 8361 8362 if (this.options.noClip) { 8363 this._parts = this._rings; 8364 return; 8365 } 8366 8367 var parts = this._parts, 8368 i, j, k, len, len2, segment, points; 8369 8370 for (i = 0, k = 0, len = this._rings.length; i < len; i++) { 8371 points = this._rings[i]; 8372 8373 for (j = 0, len2 = points.length; j < len2 - 1; j++) { 8374 segment = clipSegment(points[j], points[j + 1], bounds, j, true); 8375 8376 if (!segment) { continue; } 8377 8378 parts[k] = parts[k] || []; 8379 parts[k].push(segment[0]); 8380 8381 // if segment goes out of screen, or it's the last one, it's the end of the line part 8382 if ((segment[1] !== points[j + 1]) || (j === len2 - 2)) { 8383 parts[k].push(segment[1]); 8384 k++; 8385 } 8386 } 8387 } 8388 }, 8389 8390 // simplify each clipped part of the polyline for performance 8391 _simplifyPoints: function () { 8392 var parts = this._parts, 8393 tolerance = this.options.smoothFactor; 8394 8395 for (var i = 0, len = parts.length; i < len; i++) { 8396 parts[i] = simplify(parts[i], tolerance); 8397 } 8398 }, 8399 8400 _update: function () { 8401 if (!this._map) { return; } 8402 8403 this._clipPoints(); 8404 this._simplifyPoints(); 8405 this._updatePath(); 8406 }, 8407 8408 _updatePath: function () { 8409 this._renderer._updatePoly(this); 8410 }, 8411 8412 // Needed by the `Canvas` renderer for interactivity 8413 _containsPoint: function (p, closed) { 8414 var i, j, k, len, len2, part, 8415 w = this._clickTolerance(); 8416 8417 if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; } 8418 8419 // hit detection for polylines 8420 for (i = 0, len = this._parts.length; i < len; i++) { 8421 part = this._parts[i]; 8422 8423 for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { 8424 if (!closed && (j === 0)) { continue; } 8425 8426 if (pointToSegmentDistance(p, part[k], part[j]) <= w) { 8427 return true; 8428 } 8429 } 8430 } 8431 return false; 8432 } 8433}); 8434 8435// @factory L.polyline(latlngs: LatLng[], options?: Polyline options) 8436// Instantiates a polyline object given an array of geographical points and 8437// optionally an options object. You can create a `Polyline` object with 8438// multiple separate lines (`MultiPolyline`) by passing an array of arrays 8439// of geographic points. 8440function polyline(latlngs, options) { 8441 return new Polyline(latlngs, options); 8442} 8443 8444// Retrocompat. Allow plugins to support Leaflet versions before and after 1.1. 8445Polyline._flat = _flat; 8446 8447/* 8448 * @class Polygon 8449 * @aka L.Polygon 8450 * @inherits Polyline 8451 * 8452 * A class for drawing polygon overlays on a map. Extends `Polyline`. 8453 * 8454 * 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. 8455 * 8456 * 8457 * @example 8458 * 8459 * ```js 8460 * // create a red polygon from an array of LatLng points 8461 * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]]; 8462 * 8463 * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map); 8464 * 8465 * // zoom the map to the polygon 8466 * map.fitBounds(polygon.getBounds()); 8467 * ``` 8468 * 8469 * 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: 8470 * 8471 * ```js 8472 * var latlngs = [ 8473 * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring 8474 * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole 8475 * ]; 8476 * ``` 8477 * 8478 * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape. 8479 * 8480 * ```js 8481 * var latlngs = [ 8482 * [ // first polygon 8483 * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring 8484 * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole 8485 * ], 8486 * [ // second polygon 8487 * [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]] 8488 * ] 8489 * ]; 8490 * ``` 8491 */ 8492 8493var Polygon = Polyline.extend({ 8494 8495 options: { 8496 fill: true 8497 }, 8498 8499 isEmpty: function () { 8500 return !this._latlngs.length || !this._latlngs[0].length; 8501 }, 8502 8503 getCenter: function () { 8504 // throws error when not yet added to map as this center calculation requires projected coordinates 8505 if (!this._map) { 8506 throw new Error('Must add layer to map before using getCenter()'); 8507 } 8508 8509 var i, j, p1, p2, f, area, x, y, center, 8510 points = this._rings[0], 8511 len = points.length; 8512 8513 if (!len) { return null; } 8514 8515 // polygon centroid algorithm; only uses the first ring if there are multiple 8516 8517 area = x = y = 0; 8518 8519 for (i = 0, j = len - 1; i < len; j = i++) { 8520 p1 = points[i]; 8521 p2 = points[j]; 8522 8523 f = p1.y * p2.x - p2.y * p1.x; 8524 x += (p1.x + p2.x) * f; 8525 y += (p1.y + p2.y) * f; 8526 area += f * 3; 8527 } 8528 8529 if (area === 0) { 8530 // Polygon is so small that all points are on same pixel. 8531 center = points[0]; 8532 } else { 8533 center = [x / area, y / area]; 8534 } 8535 return this._map.layerPointToLatLng(center); 8536 }, 8537 8538 _convertLatLngs: function (latlngs) { 8539 var result = Polyline.prototype._convertLatLngs.call(this, latlngs), 8540 len = result.length; 8541 8542 // remove last point if it equals first one 8543 if (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) { 8544 result.pop(); 8545 } 8546 return result; 8547 }, 8548 8549 _setLatLngs: function (latlngs) { 8550 Polyline.prototype._setLatLngs.call(this, latlngs); 8551 if (isFlat(this._latlngs)) { 8552 this._latlngs = [this._latlngs]; 8553 } 8554 }, 8555 8556 _defaultShape: function () { 8557 return isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0]; 8558 }, 8559 8560 _clipPoints: function () { 8561 // polygons need a different clipping algorithm so we redefine that 8562 8563 var bounds = this._renderer._bounds, 8564 w = this.options.weight, 8565 p = new Point(w, w); 8566 8567 // increase clip padding by stroke width to avoid stroke on clip edges 8568 bounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p)); 8569 8570 this._parts = []; 8571 if (!this._pxBounds || !this._pxBounds.intersects(bounds)) { 8572 return; 8573 } 8574 8575 if (this.options.noClip) { 8576 this._parts = this._rings; 8577 return; 8578 } 8579 8580 for (var i = 0, len = this._rings.length, clipped; i < len; i++) { 8581 clipped = clipPolygon(this._rings[i], bounds, true); 8582 if (clipped.length) { 8583 this._parts.push(clipped); 8584 } 8585 } 8586 }, 8587 8588 _updatePath: function () { 8589 this._renderer._updatePoly(this, true); 8590 }, 8591 8592 // Needed by the `Canvas` renderer for interactivity 8593 _containsPoint: function (p) { 8594 var inside = false, 8595 part, p1, p2, i, j, k, len, len2; 8596 8597 if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; } 8598 8599 // ray casting algorithm for detecting if point is in polygon 8600 for (i = 0, len = this._parts.length; i < len; i++) { 8601 part = this._parts[i]; 8602 8603 for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { 8604 p1 = part[j]; 8605 p2 = part[k]; 8606 8607 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)) { 8608 inside = !inside; 8609 } 8610 } 8611 } 8612 8613 // also check if it's on polygon stroke 8614 return inside || Polyline.prototype._containsPoint.call(this, p, true); 8615 } 8616 8617}); 8618 8619 8620// @factory L.polygon(latlngs: LatLng[], options?: Polyline options) 8621function polygon(latlngs, options) { 8622 return new Polygon(latlngs, options); 8623} 8624 8625/* 8626 * @class GeoJSON 8627 * @aka L.GeoJSON 8628 * @inherits FeatureGroup 8629 * 8630 * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse 8631 * GeoJSON data and display it on the map. Extends `FeatureGroup`. 8632 * 8633 * @example 8634 * 8635 * ```js 8636 * L.geoJSON(data, { 8637 * style: function (feature) { 8638 * return {color: feature.properties.color}; 8639 * } 8640 * }).bindPopup(function (layer) { 8641 * return layer.feature.properties.description; 8642 * }).addTo(map); 8643 * ``` 8644 */ 8645 8646var GeoJSON = FeatureGroup.extend({ 8647 8648 /* @section 8649 * @aka GeoJSON options 8650 * 8651 * @option pointToLayer: Function = * 8652 * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally 8653 * called when data is added, passing the GeoJSON point feature and its `LatLng`. 8654 * The default is to spawn a default `Marker`: 8655 * ```js 8656 * function(geoJsonPoint, latlng) { 8657 * return L.marker(latlng); 8658 * } 8659 * ``` 8660 * 8661 * @option style: Function = * 8662 * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,
8663 * called internally when data is added. 8664 * The default value is to not override any defaults: 8665 * ```js 8666 * function (geoJsonFeature) { 8667 * return {} 8668 * } 8669 * ``` 8670 * 8671 * @option onEachFeature: Function = * 8672 * A `Function` that will be called once for each created `Feature`, after it has 8673 * been created and styled. Useful for attaching events and popups to features. 8674 * The default is to do nothing with the newly created layers: 8675 * ```js 8676 * function (feature, layer) {} 8677 * ``` 8678 * 8679 * @option filter: Function = * 8680 * A `Function` that will be used to decide whether to include a feature or not. 8681 * The default is to include all features: 8682 * ```js 8683 * function (geoJsonFeature) { 8684 * return true; 8685 * } 8686 * ``` 8687 * Note: dynamically changing the `filter` option will have effect only on newly 8688 * added data. It will _not_ re-evaluate already included features. 8689 * 8690 * @option coordsToLatLng: Function = * 8691 * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s. 8692 * The default is the `coordsToLatLng` static method. 8693 */ 8694 8695 initialize: function (geojson, options) { 8696 setOptions(this, options); 8697 8698 this._layers = {}; 8699 8700 if (geojson) { 8701 this.addData(geojson); 8702 } 8703 }, 8704 8705 // @method addData( <GeoJSON> data ): this 8706 // Adds a GeoJSON object to the layer. 8707 addData: function (geojson) { 8708 var features = isArray(geojson) ? geojson : geojson.features, 8709 i, len, feature; 8710 8711 if (features) { 8712 for (i = 0, len = features.length; i < len; i++) { 8713 // only add this if geometry or geometries are set and not null 8714 feature = features[i]; 8715 if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { 8716 this.addData(feature); 8717 } 8718 } 8719 return this; 8720 } 8721 8722 var options = this.options; 8723 8724 if (options.filter && !options.filter(geojson)) { return this; } 8725 8726 var layer = geometryToLayer(geojson, options); 8727 if (!layer) { 8728 return this; 8729 } 8730 layer.feature = asFeature(geojson); 8731 8732 layer.defaultOptions = layer.options; 8733 this.resetStyle(layer); 8734 8735 if (options.onEachFeature) { 8736 options.onEachFeature(geojson, layer); 8737 } 8738 8739 return this.addLayer(layer); 8740 }, 8741 8742 // @method resetStyle( <Path> layer ): this 8743 // Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events. 8744 resetStyle: function (layer) { 8745 // reset any custom styles 8746 layer.options = extend({}, layer.defaultOptions); 8747 this._setLayerStyle(layer, this.options.style); 8748 return this; 8749 }, 8750 8751 // @method setStyle( <Function> style ): this 8752 // Changes styles of GeoJSON vector layers with the given style function. 8753 setStyle: function (style) { 8754 return this.eachLayer(function (layer) { 8755 this._setLayerStyle(layer, style); 8756 }, this); 8757 }, 8758 8759 _setLayerStyle: function (layer, style) { 8760 if (typeof style === 'function') { 8761 style = style(layer.feature); 8762 } 8763 if (layer.setStyle) { 8764 layer.setStyle(style); 8765 } 8766 } 8767}); 8768 8769// @section 8770// There are several static functions which can be called without instantiating L.GeoJSON: 8771 8772// @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer 8773// Creates a `Layer` from a given GeoJSON feature. Can use a custom 8774// [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng) 8775// functions if provided as options. 8776function geometryToLayer(geojson, options) { 8777 8778 var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, 8779 coords = geometry ? geometry.coordinates : null, 8780 layers = [], 8781 pointToLayer = options && options.pointToLayer, 8782 _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng, 8783 latlng, latlngs, i, len; 8784 8785 if (!coords && !geometry) { 8786 return null; 8787 } 8788 8789 switch (geometry.type) { 8790 case 'Point': 8791 latlng = _coordsToLatLng(coords); 8792 return pointToLayer ? pointToLayer(geojson, latlng) : new Marker(latlng); 8793 8794 case 'MultiPoint': 8795 for (i = 0, len = coords.length; i < len; i++) { 8796 latlng = _coordsToLatLng(coords[i]); 8797 layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new Marker(latlng)); 8798 } 8799 return new FeatureGroup(layers); 8800 8801 case 'LineString': 8802 case 'MultiLineString': 8803 latlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng); 8804 return new Polyline(latlngs, options); 8805 8806 case 'Polygon': 8807 case 'MultiPolygon': 8808 latlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng); 8809 return new Polygon(latlngs, options); 8810 8811 case 'GeometryCollection': 8812 for (i = 0, len = geometry.geometries.length; i < len; i++) { 8813 var layer = geometryToLayer({ 8814 geometry: geometry.geometries[i], 8815 type: 'Feature', 8816 properties: geojson.properties 8817 }, options); 8818 8819 if (layer) { 8820 layers.push(layer); 8821 } 8822 } 8823 return new FeatureGroup(layers); 8824 8825 default: 8826 throw new Error('Invalid GeoJSON object.'); 8827 } 8828} 8829 8830// @function coordsToLatLng(coords: Array): LatLng 8831// Creates a `LatLng` object from an array of 2 numbers (longitude, latitude) 8832// or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points. 8833function coordsToLatLng(coords) {
vendor: 12,744 bytes, lines 8834-9296
8834 return new LatLng(coords[1], coords[0], coords[2]); 8835} 8836 8837// @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array 8838// Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array. 8839// `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default). 8840// Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function. 8841function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) { 8842 var latlngs = []; 8843 8844 for (var i = 0, len = coords.length, latlng; i < len; i++) { 8845 latlng = levelsDeep ? 8846 coordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) : 8847 (_coordsToLatLng || coordsToLatLng)(coords[i]); 8848 8849 latlngs.push(latlng); 8850 } 8851 8852 return latlngs; 8853} 8854 8855// @function latLngToCoords(latlng: LatLng, precision?: Number): Array 8856// Reverse of [`coordsToLatLng`](#geojson-coordstolatlng) 8857function latLngToCoords(latlng, precision) { 8858 precision = typeof precision === 'number' ? precision : 6; 8859 return latlng.alt !== undefined ? 8860 [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] : 8861 [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)]; 8862} 8863 8864// @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array 8865// Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs) 8866// `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. 8867function latLngsToCoords(latlngs, levelsDeep, closed, precision) { 8868 var coords = []; 8869 8870 for (var i = 0, len = latlngs.length; i < len; i++) { 8871 coords.push(levelsDeep ? 8872 latLngsToCoords(latlngs[i], levelsDeep - 1, closed, precision) : 8873 latLngToCoords(latlngs[i], precision)); 8874 } 8875 8876 if (!levelsDeep && closed) { 8877 coords.push(coords[0]); 8878 } 8879 8880 return coords; 8881} 8882 8883function getFeature(layer, newGeometry) { 8884 return layer.feature ? 8885 extend({}, layer.feature, {geometry: newGeometry}) : 8886 asFeature(newGeometry); 8887} 8888 8889// @function asFeature(geojson: Object): Object 8890// Normalize GeoJSON geometries/features into GeoJSON features. 8891function asFeature(geojson) { 8892 if (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') { 8893 return geojson; 8894 } 8895 8896 return { 8897 type: 'Feature', 8898 properties: {}, 8899 geometry: geojson 8900 }; 8901} 8902 8903var PointToGeoJSON = { 8904 toGeoJSON: function (precision) { 8905 return getFeature(this, { 8906 type: 'Point', 8907 coordinates: latLngToCoords(this.getLatLng(), precision) 8908 }); 8909 } 8910}; 8911 8912// @namespace Marker 8913// @method toGeoJSON(): Object 8914// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature). 8915Marker.include(PointToGeoJSON); 8916 8917// @namespace CircleMarker 8918// @method toGeoJSON(): Object 8919// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature). 8920Circle.include(PointToGeoJSON); 8921CircleMarker.include(PointToGeoJSON); 8922 8923 8924// @namespace Polyline 8925// @method toGeoJSON(): Object 8926// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature). 8927Polyline.include({ 8928 toGeoJSON: function (precision) { 8929 var multi = !isFlat(this._latlngs); 8930 8931 var coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision); 8932 8933 return getFeature(this, { 8934 type: (multi ? 'Multi' : '') + 'LineString', 8935 coordinates: coords 8936 }); 8937 } 8938}); 8939 8940// @namespace Polygon 8941// @method toGeoJSON(): Object 8942// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature). 8943Polygon.include({ 8944 toGeoJSON: function (precision) { 8945 var holes = !isFlat(this._latlngs), 8946 multi = holes && !isFlat(this._latlngs[0]); 8947 8948 var coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision); 8949 8950 if (!holes) { 8951 coords = [coords]; 8952 } 8953 8954 return getFeature(this, { 8955 type: (multi ? 'Multi' : '') + 'Polygon', 8956 coordinates: coords 8957 }); 8958 } 8959}); 8960 8961 8962// @namespace LayerGroup 8963LayerGroup.include({ 8964 toMultiPoint: function (precision) { 8965 var coords = []; 8966 8967 this.eachLayer(function (layer) { 8968 coords.push(layer.toGeoJSON(precision).geometry.coordinates); 8969 }); 8970 8971 return getFeature(this, { 8972 type: 'MultiPoint', 8973 coordinates: coords 8974 }); 8975 }, 8976 8977 // @method toGeoJSON(): Object 8978 // Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`). 8979 toGeoJSON: function (precision) { 8980 8981 var type = this.feature && this.feature.geometry && this.feature.geometry.type; 8982 8983 if (type === 'MultiPoint') { 8984 return this.toMultiPoint(precision); 8985 } 8986 8987 var isGeometryCollection = type === 'GeometryCollection', 8988 jsons = []; 8989 8990 this.eachLayer(function (layer) { 8991 if (layer.toGeoJSON) { 8992 var json = layer.toGeoJSON(precision); 8993 if (isGeometryCollection) { 8994 jsons.push(json.geometry); 8995 } else { 8996 var feature = asFeature(json); 8997 // Squash nested feature collections 8998 if (feature.type === 'FeatureCollection') { 8999 jsons.push.apply(jsons, feature.features); 9000 } else { 9001 jsons.push(feature); 9002 } 9003 } 9004 } 9005 }); 9006 9007 if (isGeometryCollection) { 9008 return getFeature(this, { 9009 geometries: jsons, 9010 type: 'GeometryCollection' 9011 }); 9012 } 9013 9014 return { 9015 type: 'FeatureCollection', 9016 features: jsons 9017 }; 9018 } 9019}); 9020 9021// @namespace GeoJSON 9022// @factory L.geoJSON(geojson?: Object, options?: GeoJSON options) 9023// Creates a GeoJSON layer. Optionally accepts an object in 9024// [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map 9025// (you can alternatively add it later with `addData` method) and an `options` object. 9026function geoJSON(geojson, options) { 9027 return new GeoJSON(geojson, options); 9028} 9029 9030// Backward compatibility. 9031var geoJson = geoJSON; 9032 9033/* 9034 * @class ImageOverlay 9035 * @aka L.ImageOverlay 9036 * @inherits Interactive layer 9037 * 9038 * Used to load and display a single image over specific bounds of the map. Extends `Layer`. 9039 * 9040 * @example 9041 * 9042 * ```js 9043 * var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg', 9044 * imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]]; 9045 * L.imageOverlay(imageUrl, imageBounds).addTo(map); 9046 * ``` 9047 */ 9048 9049var ImageOverlay = Layer.extend({ 9050 9051 // @section 9052 // @aka ImageOverlay options 9053 options: { 9054 // @option opacity: Number = 1.0 9055 // The opacity of the image overlay. 9056 opacity: 1, 9057 9058 // @option alt: String = '' 9059 // Text for the `alt` attribute of the image (useful for accessibility). 9060 alt: '', 9061 9062 // @option interactive: Boolean = false 9063 // If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered. 9064 interactive: false, 9065 9066 // @option crossOrigin: Boolean|String = false 9067 // Whether the crossOrigin attribute will be added to the image. 9068 // 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. 9069 // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values. 9070 crossOrigin: false, 9071 9072 // @option errorOverlayUrl: String = '' 9073 // URL to the overlay image to show in place of the overlay that failed to load. 9074 errorOverlayUrl: '', 9075 9076 // @option zIndex: Number = 1 9077 // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer. 9078 zIndex: 1, 9079 9080 // @option className: String = '' 9081 // A custom class name to assign to the image. Empty by default. 9082 className: '' 9083 }, 9084 9085 initialize: function (url, bounds, options) { // (String, LatLngBounds, Object) 9086 this._url = url; 9087 this._bounds = toLatLngBounds(bounds); 9088 9089 setOptions(this, options); 9090 }, 9091 9092 onAdd: function () { 9093 if (!this._image) { 9094 this._initImage(); 9095 9096 if (this.options.opacity < 1) { 9097 this._updateOpacity(); 9098 } 9099 } 9100 9101 if (this.options.interactive) { 9102 addClass(this._image, 'leaflet-interactive'); 9103 this.addInteractiveTarget(this._image); 9104 } 9105 9106 this.getPane().appendChild(this._image); 9107 this._reset(); 9108 }, 9109 9110 onRemove: function () { 9111 remove(this._image); 9112 if (this.options.interactive) { 9113 this.removeInteractiveTarget(this._image); 9114 } 9115 }, 9116 9117 // @method setOpacity(opacity: Number): this 9118 // Sets the opacity of the overlay. 9119 setOpacity: function (opacity) { 9120 this.options.opacity = opacity; 9121 9122 if (this._image) { 9123 this._updateOpacity(); 9124 } 9125 return this; 9126 }, 9127 9128 setStyle: function (styleOpts) { 9129 if (styleOpts.opacity) { 9130 this.setOpacity(styleOpts.opacity); 9131 } 9132 return this; 9133 }, 9134 9135 // @method bringToFront(): this 9136 // Brings the layer to the top of all overlays. 9137 bringToFront: function () { 9138 if (this._map) { 9139 toFront(this._image); 9140 } 9141 return this; 9142 }, 9143 9144 // @method bringToBack(): this 9145 // Brings the layer to the bottom of all overlays. 9146 bringToBack: function () { 9147 if (this._map) { 9148 toBack(this._image); 9149 } 9150 return this; 9151 }, 9152 9153 // @method setUrl(url: String): this 9154 // Changes the URL of the image. 9155 setUrl: function (url) { 9156 this._url = url; 9157 9158 if (this._image) { 9159 this._image.src = url; 9160 } 9161 return this; 9162 }, 9163 9164 // @method setBounds(bounds: LatLngBounds): this 9165 // Update the bounds that this ImageOverlay covers 9166 setBounds: function (bounds) { 9167 this._bounds = toLatLngBounds(bounds); 9168 9169 if (this._map) { 9170 this._reset(); 9171 } 9172 return this; 9173 }, 9174 9175 getEvents: function () { 9176 var events = { 9177 zoom: this._reset, 9178 viewreset: this._reset 9179 }; 9180 9181 if (this._zoomAnimated) { 9182 events.zoomanim = this._animateZoom; 9183 } 9184 9185 return events; 9186 }, 9187 9188 // @method setZIndex(value: Number): this 9189 // Changes the [zIndex](#imageoverlay-zindex) of the image overlay. 9190 setZIndex: function (value) { 9191 this.options.zIndex = value; 9192 this._updateZIndex(); 9193 return this; 9194 }, 9195 9196 // @method getBounds(): LatLngBounds 9197 // Get the bounds that this ImageOverlay covers 9198 getBounds: function () { 9199 return this._bounds; 9200 }, 9201 9202 // @method getElement(): HTMLElement 9203 // Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement) 9204 // used by this overlay. 9205 getElement: function () { 9206 return this._image; 9207 }, 9208 9209 _initImage: function () { 9210 var wasElementSupplied = this._url.tagName === 'IMG'; 9211 var img = this._image = wasElementSupplied ? this._url : create$1('img'); 9212 9213 addClass(img, 'leaflet-image-layer'); 9214 if (this._zoomAnimated) { addClass(img, 'leaflet-zoom-animated'); } 9215 if (this.options.className) { addClass(img, this.options.className); } 9216 9217 img.onselectstart = falseFn; 9218 img.onmousemove = falseFn; 9219 9220 // @event load: Event 9221 // Fired when the ImageOverlay layer has loaded its image 9222 img.onload = bind(this.fire, this, 'load'); 9223 img.onerror = bind(this._overlayOnError, this, 'error'); 9224 9225 if (this.options.crossOrigin || this.options.crossOrigin === '') { 9226 img.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin; 9227 } 9228 9229 if (this.options.zIndex) { 9230 this._updateZIndex(); 9231 } 9232 9233 if (wasElementSupplied) { 9234 this._url = img.src; 9235 return; 9236 } 9237 9238 img.src = this._url; 9239 img.alt = this.options.alt; 9240 }, 9241 9242 _animateZoom: function (e) { 9243 var scale = this._map.getZoomScale(e.zoom), 9244 offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min; 9245 9246 setTransform(this._image, offset, scale); 9247 }, 9248 9249 _reset: function () { 9250 var image = this._image, 9251 bounds = new Bounds( 9252 this._map.latLngToLayerPoint(this._bounds.getNorthWest()), 9253 this._map.latLngToLayerPoint(this._bounds.getSouthEast())), 9254 size = bounds.getSize(); 9255 9256 setPosition(image, bounds.min); 9257 9258 image.style.width = size.x + 'px'; 9259 image.style.height = size.y + 'px'; 9260 }, 9261 9262 _updateOpacity: function () { 9263 setOpacity(this._image, this.options.opacity); 9264 }, 9265 9266 _updateZIndex: function () { 9267 if (this._image && this.options.zIndex !== undefined && this.options.zIndex !== null) { 9268 this._image.style.zIndex = this.options.zIndex; 9269 } 9270 }, 9271 9272 _overlayOnError: function () { 9273 // @event error: Event 9274 // Fired when the ImageOverlay layer fails to load its image 9275 this.fire('error'); 9276 9277 var errorUrl = this.options.errorOverlayUrl; 9278 if (errorUrl && this._url !== errorUrl) { 9279 this._url = errorUrl; 9280 this._image.src = errorUrl; 9281 } 9282 } 9283}); 9284 9285// @factory L.imageOverlay(imageUrl: String, bounds: LatLngBounds, options?: ImageOverlay options) 9286// Instantiates an image overlay object given the URL of the image and the 9287// geographical bounds it is tied to. 9288var imageOverlay = function (url, bounds, options) { 9289 return new ImageOverlay(url, bounds, options); 9290}; 9291 9292/* 9293 * @class VideoOverlay 9294 * @aka L.VideoOverlay 9295 * @inherits ImageOverlay 9296 *
9297 * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`. 9298 * 9299 * A video overlay uses the [`<video>`](https://developer.mozilla.org/docs/Web/HTML/Element/video) 9300 * HTML5 element. 9301 * 9302 * @example 9303 * 9304 * ```js 9305 * var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm', 9306 * videoBounds = [[ 32, -130], [ 13, -100]]; 9307 * L.videoOverlay(videoUrl, videoBounds ).addTo(map); 9308 * ``` 9309 */ 9310 9311var VideoOverlay = ImageOverlay.extend({ 9312 9313 // @section 9314 // @aka VideoOverlay options 9315 options: { 9316 // @option autoplay: Boolean = true 9317 // Whether the video starts playing automatically when loaded. 9318 autoplay: true, 9319 9320 // @option loop: Boolean = true 9321 // Whether the video will loop back to the beginning when played. 9322 loop: true 9323 }, 9324 9325 _initImage: function () { 9326 var wasElementSupplied = this._url.tagName === 'VIDEO'; 9327 var vid = this._image = wasElementSupplied ? this._url : create$1('video'); 9328 9329 addClass(vid, 'leaflet-image-layer'); 9330 if (this._zoomAnimated) { addClass(vid, 'leaflet-zoom-animated'); } 9331 9332 vid.onselectstart = falseFn; 9333 vid.onmousemove = falseFn; 9334 9335 // @event load: Event 9336 // Fired when the video has finished loading the first frame 9337 vid.onloadeddata = bind(this.fire, this, 'load'); 9338 9339 if (wasElementSupplied) { 9340 var sourceElements = vid.getElementsByTagName('source'); 9341 var sources = []; 9342 for (var j = 0; j < sourceElements.length; j++) { 9343 sources.push(sourceElements[j].src); 9344 } 9345 9346 this._url = (sourceElements.length > 0) ? sources : [vid.src]; 9347 return; 9348 } 9349 9350 if (!isArray(this._url)) { this._url = [this._url]; } 9351 9352 vid.autoplay = !!this.options.autoplay; 9353 vid.loop = !!this.options.loop; 9354 for (var i = 0; i < this._url.length; i++) { 9355 var source = create$1('source'); 9356 source.src = this._url[i]; 9357 vid.appendChild(source); 9358 } 9359 } 9360 9361 // @method getElement(): HTMLVideoElement 9362 // Returns the instance of [`HTMLVideoElement`](https://developer.mozilla.org/docs/Web/API/HTMLVideoElement) 9363 // used by this overlay. 9364}); 9365 9366 9367// @factory L.videoOverlay(video: String|Array|HTMLVideoElement, bounds: LatLngBounds, options?: VideoOverlay options) 9368// Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the 9369// geographical bounds it is tied to. 9370 9371function videoOverlay(video, bounds, options) { 9372 return new VideoOverlay(video, bounds, options); 9373} 9374 9375/* 9376 * @class DivOverlay 9377 * @inherits Layer 9378 * @aka L.DivOverlay 9379 * Base model for L.Popup and L.Tooltip. Inherit from it for custom popup like plugins. 9380 */ 9381 9382// @namespace DivOverlay 9383var DivOverlay = Layer.extend({ 9384 9385 // @section 9386 // @aka DivOverlay options 9387 options: { 9388 // @option offset: Point = Point(0, 7) 9389 // The offset of the popup position. Useful to control the anchor 9390 // of the popup when opening it on some overlays. 9391 offset: [0, 7], 9392 9393 // @option className: String = '' 9394 // A custom CSS class name to assign to the popup. 9395 className: '', 9396 9397 // @option pane: String = 'popupPane' 9398 // `Map pane` where the popup will be added. 9399 pane: 'popupPane' 9400 }, 9401 9402 initialize: function (options, source) { 9403 setOptions(this, options); 9404 9405 this._source = source; 9406 }, 9407 9408 onAdd: function (map) { 9409 this._zoomAnimated = map._zoomAnimated; 9410 9411 if (!this._container) { 9412 this._initLayout(); 9413 } 9414 9415 if (map._fadeAnimated) { 9416 setOpacity(this._container, 0); 9417 } 9418 9419 clearTimeout(this._removeTimeout); 9420 this.getPane().appendChild(this._container); 9421 this.update(); 9422 9423 if (map._fadeAnimated) { 9424 setOpacity(this._container, 1); 9425 } 9426 9427 this.bringToFront(); 9428 }, 9429 9430 onRemove: function (map) { 9431 if (map._fadeAnimated) { 9432 setOpacity(this._container, 0); 9433 this._removeTimeout = setTimeout(bind(remove, undefined, this._container), 200); 9434 } else { 9435 remove(this._container); 9436 } 9437 }, 9438 9439 // @namespace Popup 9440 // @method getLatLng: LatLng 9441 // Returns the geographical point of popup. 9442 getLatLng: function () { 9443 return this._latlng; 9444 }, 9445 9446 // @method setLatLng(latlng: LatLng): this 9447 // Sets the geographical point where the popup will open. 9448 setLatLng: function (latlng) { 9449 this._latlng = toLatLng(latlng); 9450 if (this._map) { 9451 this._updatePosition(); 9452 this._adjustPan(); 9453 } 9454 return this; 9455 }, 9456 9457 // @method getContent: String|HTMLElement 9458 // Returns the content of the popup. 9459 getContent: function () { 9460 return this._content; 9461 }, 9462 9463 // @method setContent(htmlContent: String|HTMLElement|Function): this
vendor: 3,443 bytes, lines 9464-9593
9464 // 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. 9465 setContent: function (content) { 9466 this._content = content; 9467 this.update(); 9468 return this; 9469 }, 9470 9471 // @method getElement: String|HTMLElement 9472 // Alias for [getContent()](#popup-getcontent) 9473 getElement: function () { 9474 return this._container; 9475 }, 9476 9477 // @method update: null 9478 // Updates the popup content, layout and position. Useful for updating the popup after something inside changed, e.g. image loaded. 9479 update: function () { 9480 if (!this._map) { return; } 9481 9482 this._container.style.visibility = 'hidden'; 9483 9484 this._updateContent(); 9485 this._updateLayout(); 9486 this._updatePosition(); 9487 9488 this._container.style.visibility = ''; 9489 9490 this._adjustPan(); 9491 }, 9492 9493 getEvents: function () { 9494 var events = { 9495 zoom: this._updatePosition, 9496 viewreset: this._updatePosition 9497 }; 9498 9499 if (this._zoomAnimated) { 9500 events.zoomanim = this._animateZoom; 9501 } 9502 return events; 9503 }, 9504 9505 // @method isOpen: Boolean 9506 // Returns `true` when the popup is visible on the map. 9507 isOpen: function () { 9508 return !!this._map && this._map.hasLayer(this); 9509 }, 9510 9511 // @method bringToFront: this 9512 // Brings this popup in front of other popups (in the same map pane). 9513 bringToFront: function () { 9514 if (this._map) { 9515 toFront(this._container); 9516 } 9517 return this; 9518 }, 9519 9520 // @method bringToBack: this 9521 // Brings this popup to the back of other popups (in the same map pane). 9522 bringToBack: function () { 9523 if (this._map) { 9524 toBack(this._container); 9525 } 9526 return this; 9527 }, 9528 9529 _updateContent: function () { 9530 if (!this._content) { return; } 9531 9532 var node = this._contentNode; 9533 var content = (typeof this._content === 'function') ? this._content(this._source || this) : this._content; 9534 9535 if (typeof content === 'string') { 9536 node.innerHTML = content; 9537 } else { 9538 while (node.hasChildNodes()) { 9539 node.removeChild(node.firstChild); 9540 } 9541 node.appendChild(content); 9542 } 9543 this.fire('contentupdate'); 9544 }, 9545 9546 _updatePosition: function () { 9547 if (!this._map) { return; } 9548 9549 var pos = this._map.latLngToLayerPoint(this._latlng), 9550 offset = toPoint(this.options.offset), 9551 anchor = this._getAnchor(); 9552 9553 if (this._zoomAnimated) { 9554 setPosition(this._container, pos.add(anchor)); 9555 } else { 9556 offset = offset.add(pos).add(anchor); 9557 } 9558 9559 var bottom = this._containerBottom = -offset.y, 9560 left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x; 9561 9562 // bottom position the popup in case the height of the popup changes (images loading etc) 9563 this._container.style.bottom = bottom + 'px'; 9564 this._container.style.left = left + 'px'; 9565 }, 9566 9567 _getAnchor: function () { 9568 return [0, 0]; 9569 } 9570 9571}); 9572 9573/* 9574 * @class Popup 9575 * @inherits DivOverlay 9576 * @aka L.Popup 9577 * Used to open popups in certain places of the map. Use [Map.openPopup](#map-openpopup) to 9578 * open popups while making sure that only one popup is open at one time 9579 * (recommended for usability), or use [Map.addLayer](#map-addlayer) to open as many as you want. 9580 * 9581 * @example 9582 * 9583 * If you want to just bind a popup to marker click and then open it, it's really easy: 9584 * 9585 * ```js 9586 * marker.bindPopup(popupContent).openPopup(); 9587 * ``` 9588 * Path overlays like polylines also have a `bindPopup` method. 9589 * Here's a more complicated way to open a popup on a map: 9590 * 9591 * ```js 9592 * var popup = L.popup() 9593 * .setLatLng(latlng)
9594 * .setContent('<p>Hello world!<br />This is a nice popup.</p>') 9595 * .openOn(map); 9596 * ``` 9597 */ 9598 9599 9600// @namespace Popup 9601var Popup = DivOverlay.extend({ 9602 9603 // @section 9604 // @aka Popup options 9605 options: { 9606 // @option maxWidth: Number = 300 9607 // Max width of the popup, in pixels. 9608 maxWidth: 300, 9609 9610 // @option minWidth: Number = 50 9611 // Min width of the popup, in pixels. 9612 minWidth: 50, 9613 9614 // @option maxHeight: Number = null 9615 // If set, creates a scrollable container of the given height 9616 // inside a popup if its content exceeds it. 9617 maxHeight: null, 9618 9619 // @option autoPan: Boolean = true 9620 // Set it to `false` if you don't want the map to do panning animation 9621 // to fit the opened popup. 9622 autoPan: true, 9623 9624 // @option autoPanPaddingTopLeft: Point = null 9625 // The margin between the popup and the top left corner of the map 9626 // view after autopanning was performed. 9627 autoPanPaddingTopLeft: null, 9628 9629 // @option autoPanPaddingBottomRight: Point = null 9630 // The margin between the popup and the bottom right corner of the map 9631 // view after autopanning was performed. 9632 autoPanPaddingBottomRight: null, 9633 9634 // @option autoPanPadding: Point = Point(5, 5) 9635 // Equivalent of setting both top left and bottom right autopan padding to the same value. 9636 autoPanPadding: [5, 5], 9637 9638 // @option keepInView: Boolean = false 9639 // Set it to `true` if you want to prevent users from panning the popup 9640 // off of the screen while it is open. 9641 keepInView: false, 9642 9643 // @option closeButton: Boolean = true 9644 // Controls the presence of a close button in the popup. 9645 closeButton: true, 9646 9647 // @option autoClose: Boolean = true 9648 // Set it to `false` if you want to override the default behavior of 9649 // the popup closing when another popup is opened. 9650 autoClose: true, 9651 9652 // @option closeOnEscapeKey: Boolean = true 9653 // Set it to `false` if you want to override the default behavior of 9654 // the ESC key for closing of the popup. 9655 closeOnEscapeKey: true, 9656 9657 // @option closeOnClick: Boolean = * 9658 // Set it if you want to override the default behavior of the popup closing when user clicks 9659 // on the map. Defaults to the map's [`closePopupOnClick`](#map-closepopuponclick) option. 9660 9661 // @option className: String = '' 9662 // A custom CSS class name to assign to the popup. 9663 className: '' 9664 }, 9665 9666 // @namespace Popup 9667 // @method openOn(map: Map): this 9668 // Adds the popup to the map and closes the previous one. The same as `map.openPopup(popup)`. 9669 openOn: function (map) { 9670 map.openPopup(this); 9671 return this; 9672 }, 9673 9674 onAdd: function (map) { 9675 DivOverlay.prototype.onAdd.call(this, map); 9676 9677 // @namespace Map 9678 // @section Popup events 9679 // @event popupopen: PopupEvent 9680 // Fired when a popup is opened in the map 9681 map.fire('popupopen', {popup: this}); 9682 9683 if (this._source) { 9684 // @namespace Layer 9685 // @section Popup events 9686 // @event popupopen: PopupEvent 9687 // Fired when a popup bound to this layer is opened 9688 this._source.fire('popupopen', {popup: this}, true); 9689 // For non-path layers, we toggle the popup when clicking 9690 // again the layer, so prevent the map to reopen it. 9691 if (!(this._source instanceof Path)) { 9692 this._source.on('preclick', stopPropagation); 9693 } 9694 } 9695 }, 9696 9697 onRemove: function (map) { 9698 DivOverlay.prototype.onRemove.call(this, map); 9699 9700 // @namespace Map 9701 // @section Popup events 9702 // @event popupclose: PopupEvent 9703 // Fired when a popup in the map is closed 9704 map.fire('popupclose', {popup: this}); 9705 9706 if (this._source) { 9707 // @namespace Layer 9708 // @section Popup events 9709 // @event popupclose: PopupEvent 9710 // Fired when a popup bound to this layer is closed 9711 this._source.fire('popupclose', {popup: this}, true); 9712 if (!(this._source instanceof Path)) { 9713 this._source.off('preclick', stopPropagation); 9714 } 9715 } 9716 }, 9717 9718 getEvents: function () { 9719 var events = DivOverlay.prototype.getEvents.call(this); 9720 9721 if (this.options.closeOnClick !== undefined ? this.options.closeOnClick : this._map.options.closePopupOnClick) { 9722 events.preclick = this._close; 9723 } 9724 9725 if (this.options.keepInView) { 9726 events.moveend = this._adjustPan; 9727 } 9728 9729 return events; 9730 }, 9731 9732 _close: function () { 9733 if (this._map) { 9734 this._map.closePopup(this); 9735 } 9736 }, 9737 9738 _initLayout: function () { 9739 var prefix = 'leaflet-popup', 9740 container = this._container = create$1('div', 9741 prefix + ' ' + (this.options.className || '') + 9742 ' leaflet-zoom-animated'); 9743 9744 var wrapper = this._wrapper = create$1('div', prefix + '-content-wrapper', container); 9745 this._contentNode = create$1('div', prefix + '-content', wrapper); 9746 9747 disableClickPropagation(wrapper); 9748 disableScrollPropagation(this._contentNode); 9749 on(wrapper, 'contextmenu', stopPropagation); 9750 9751 this._tipContainer = create$1('div', prefix + '-tip-container', container); 9752 this._tip = create$1('div', prefix + '-tip', this._tipContainer); 9753 9754 if (this.options.closeButton) { 9755 var closeButton = this._closeButton = create$1('a', prefix + '-close-button', container); 9756 closeButton.href = '#close'; 9757 closeButton.innerHTML = '×'; 9758 9759 on(closeButton, 'click', this._onCloseButtonClick, this); 9760 } 9761 }, 9762 9763 _updateLayout: function () { 9764 var container = this._contentNode, 9765 style = container.style; 9766 9767 style.width = ''; 9768 style.whiteSpace = 'nowrap'; 9769 9770 var width = container.offsetWidth; 9771 width = Math.min(width, this.options.maxWidth); 9772 width = Math.max(width, this.options.minWidth); 9773 9774 style.width = (width + 1) + 'px'; 9775 style.whiteSpace = ''; 9776 9777 style.height = ''; 9778 9779 var height = container.offsetHeight, 9780 maxHeight = this.options.maxHeight, 9781 scrolledClass = 'leaflet-popup-scrolled'; 9782 9783 if (maxHeight && height > maxHeight) { 9784 style.height = maxHeight + 'px'; 9785 addClass(container, scrolledClass); 9786 } else { 9787 removeClass(container, scrolledClass); 9788 } 9789 9790 this._containerWidth = this._container.offsetWidth; 9791 }, 9792 9793 _animateZoom: function (e) { 9794 var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center), 9795 anchor = this._getAnchor(); 9796 setPosition(this._container, pos.add(anchor)); 9797 }, 9798 9799 _adjustPan: function () { 9800 if (!this.options.autoPan || (this._map._panAnim && this._map._panAnim._inProgress)) { return; } 9801 9802 var map = this._map, 9803 marginBottom = parseInt(getStyle(this._container, 'marginBottom'), 10) || 0, 9804 containerHeight = this._container.offsetHeight + marginBottom, 9805 containerWidth = this._containerWidth, 9806 layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom); 9807 9808 layerPos._add(getPosition(this._container)); 9809 9810 var containerPos = map.layerPointToContainerPoint(layerPos), 9811 padding = toPoint(this.options.autoPanPadding), 9812 paddingTL = toPoint(this.options.autoPanPaddingTopLeft || padding), 9813 paddingBR = toPoint(this.options.autoPanPaddingBottomRight || padding), 9814 size = map.getSize(), 9815 dx = 0, 9816 dy = 0; 9817 9818 if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right 9819 dx = containerPos.x + containerWidth - size.x + paddingBR.x; 9820 } 9821 if (containerPos.x - dx - paddingTL.x < 0) { // left 9822 dx = containerPos.x - paddingTL.x; 9823 } 9824 if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom 9825 dy = containerPos.y + containerHeight - size.y + paddingBR.y; 9826 } 9827 if (containerPos.y - dy - paddingTL.y < 0) { // top 9828 dy = containerPos.y - paddingTL.y; 9829 } 9830 9831 // @namespace Map 9832 // @section Popup events 9833 // @event autopanstart: Event 9834 // Fired when the map starts autopanning when opening a popup. 9835 if (dx || dy) { 9836 map 9837 .fire('autopanstart') 9838 .panBy([dx, dy]); 9839 } 9840 }, 9841 9842 _onCloseButtonClick: function (e) { 9843 this._close(); 9844 stop(e); 9845 }, 9846 9847 _getAnchor: function () { 9848 // Where should we anchor the popup on the source layer? 9849 return toPoint(this._source && this._source._getPopupAnchor ? this._source._getPopupAnchor() : [0, 0]); 9850 } 9851 9852}); 9853 9854// @namespace Popup 9855// @factory L.popup(options?: Popup options, source?: Layer) 9856// 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. 9857var popup = function (options, source) { 9858 return new Popup(options, source); 9859}; 9860 9861 9862/* @namespace Map 9863 * @section Interaction Options 9864 * @option closePopupOnClick: Boolean = true 9865 * Set it to `false` if you don't want popups to close when user clicks the map. 9866 */ 9867Map.mergeOptions({ 9868 closePopupOnClick: true 9869}); 9870 9871 9872// @namespace Map 9873// @section Methods for Layers and Controls 9874Map.include({ 9875 // @method openPopup(popup: Popup): this 9876 // Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability). 9877 // @alternative 9878 // @method openPopup(content: String|HTMLElement, latlng: LatLng, options?: Popup options): this 9879 // Creates a popup with the specified content and options and opens it in the given point on a map. 9880 openPopup: function (popup, latlng, options) { 9881 if (!(popup instanceof Popup)) { 9882 popup = new Popup(options).setContent(popup); 9883 } 9884 9885 if (latlng) { 9886 popup.setLatLng(latlng); 9887 } 9888 9889 if (this.hasLayer(popup)) { 9890 return this; 9891 } 9892 9893 if (this._popup && this._popup.options.autoClose) { 9894 this.closePopup(); 9895 } 9896 9897 this._popup = popup; 9898 return this.addLayer(popup); 9899 }, 9900 9901 // @method closePopup(popup?: Popup): this 9902 // Closes the popup previously opened with [openPopup](#map-openpopup) (or the given one). 9903 closePopup: function (popup) { 9904 if (!popup || popup === this._popup) { 9905 popup = this._popup; 9906 this._popup = null; 9907 } 9908 if (popup) { 9909 this.removeLayer(popup); 9910 } 9911 return this; 9912 } 9913}); 9914 9915/* 9916 * @namespace Layer 9917 * @section Popup methods example 9918 * 9919 * All layers share a set of methods convenient for binding popups to it. 9920 * 9921 * ```js 9922 * var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map); 9923 * layer.openPopup(); 9924 * layer.closePopup(); 9925 * ``` 9926 * 9927 * 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. 9928 */ 9929 9930// @section Popup methods 9931Layer.include({ 9932 9933 // @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this 9934 // Binds a popup to the layer with the passed `content` and sets up the 9935 // necessary event listeners. If a `Function` is passed it will receive 9936 // the layer as the first argument and should return a `String` or `HTMLElement`. 9937 bindPopup: function (content, options) { 9938 9939 if (content instanceof Popup) { 9940 setOptions(content, options); 9941 this._popup = content; 9942 content._source = this; 9943 } else { 9944 if (!this._popup || options) { 9945 this._popup = new Popup(options, this); 9946 } 9947 this._popup.setContent(content); 9948 } 9949 9950 if (!this._popupHandlersAdded) { 9951 this.on({ 9952 click: this._openPopup, 9953 keypress: this._onKeyPress, 9954 remove: this.closePopup,
9955 move: this._movePopup 9956 }); 9957 this._popupHandlersAdded = true; 9958 } 9959 9960 return this; 9961 }, 9962 9963 // @method unbindPopup(): this 9964 // Removes the popup previously bound with `bindPopup`. 9965 unbindPopup: function () { 9966 if (this._popup) { 9967 this.off({ 9968 click: this._openPopup, 9969 keypress: this._onKeyPress, 9970 remove: this.closePopup, 9971 move: this._movePopup 9972 }); 9973 this._popupHandlersAdded = false; 9974 this._popup = null; 9975 } 9976 return this; 9977 }, 9978 9979 // @method openPopup(latlng?: LatLng): this 9980 // Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed. 9981 openPopup: function (layer, latlng) { 9982 if (!(layer instanceof Layer)) { 9983 latlng = layer; 9984 layer = this; 9985 } 9986 9987 if (layer instanceof FeatureGroup) { 9988 for (var id in this._layers) { 9989 layer = this._layers[id]; 9990 break; 9991 } 9992 } 9993 9994 if (!latlng) { 9995 latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng(); 9996 } 9997 9998 if (this._popup && this._map) { 9999 // set popup source to this layer 10000 this._popup._source = layer; 10001 10002 // update the popup (content, layout, ect...) 10003 this._popup.update(); 10004 10005 // open the popup on the map 10006 this._map.openPopup(this._popup, latlng); 10007 } 10008 10009 return this; 10010 }, 10011 10012 // @method closePopup(): this 10013 // Closes the popup bound to this layer if it is open. 10014 closePopup: function () { 10015 if (this._popup) { 10016 this._popup._close(); 10017 } 10018 return this; 10019 }, 10020 10021 // @method togglePopup(): this 10022 // Opens or closes the popup bound to this layer depending on its current state. 10023 togglePopup: function (target) { 10024 if (this._popup) { 10025 if (this._popup._map) { 10026 this.closePopup(); 10027 } else { 10028 this.openPopup(target); 10029 } 10030 } 10031 return this; 10032 }, 10033 10034 // @method isPopupOpen(): boolean 10035 // Returns `true` if the popup bound to this layer is currently open. 10036 isPopupOpen: function () { 10037 return (this._popup ? this._popup.isOpen() : false); 10038 }, 10039 10040 // @method setPopupContent(content: String|HTMLElement|Popup): this 10041 // Sets the content of the popup bound to this layer. 10042 setPopupContent: function (content) { 10043 if (this._popup) { 10044 this._popup.setContent(content); 10045 } 10046 return this; 10047 }, 10048 10049 // @method getPopup(): Popup 10050 // Returns the popup bound to this layer. 10051 getPopup: function () { 10052 return this._popup; 10053 }, 10054 10055 _openPopup: function (e) { 10056 var layer = e.layer || e.target; 10057 10058 if (!this._popup) { 10059 return; 10060 } 10061 10062 if (!this._map) { 10063 return; 10064 } 10065 10066 // prevent map click 10067 stop(e); 10068 10069 // if this inherits from Path its a vector and we can just 10070 // open the popup at the new location 10071 if (layer instanceof Path) { 10072 this.openPopup(e.layer || e.target, e.latlng); 10073 return; 10074 } 10075 10076 // otherwise treat it like a marker and figure out 10077 // if we should toggle it open/closed 10078 if (this._map.hasLayer(this._popup) && this._popup._source === layer) { 10079 this.closePopup(); 10080 } else { 10081 this.openPopup(layer, e.latlng); 10082 } 10083 }, 10084 10085 _movePopup: function (e) { 10086 this._popup.setLatLng(e.latlng); 10087 }, 10088 10089 _onKeyPress: function (e) { 10090 if (e.originalEvent.keyCode === 13) { 10091 this._openPopup(e); 10092 } 10093 } 10094}); 10095 10096/* 10097 * @class Tooltip 10098 * @inherits DivOverlay 10099 * @aka L.Tooltip 10100 * Used to display small texts on top of map layers. 10101 * 10102 * @example 10103 * 10104 * ```js 10105 * marker.bindTooltip("my tooltip text").openTooltip(); 10106 * ``` 10107 * Note about tooltip offset. Leaflet takes two options in consideration 10108 * for computing tooltip offsetting: 10109 * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip. 10110 * Add a positive x offset to move the tooltip to the right, and a positive y offset to 10111 * move it to the bottom. Negatives will move to the left and top. 10112 * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You 10113 * should adapt this value if you use a custom icon. 10114 */ 10115 10116 10117// @namespace Tooltip 10118var Tooltip = DivOverlay.extend({ 10119 10120 // @section 10121 // @aka Tooltip options 10122 options: { 10123 // @option pane: String = 'tooltipPane' 10124 // `Map pane` where the tooltip will be added. 10125 pane: 'tooltipPane', 10126 10127 // @option offset: Point = Point(0, 0) 10128 // Optional offset of the tooltip position. 10129 offset: [0, 0], 10130 10131 // @option direction: String = 'auto' 10132 // Direction where to open the tooltip. Possible values are: `right`, `left`, 10133 // `top`, `bottom`, `center`, `auto`. 10134 // `auto` will dynamically switch between `right` and `left` according to the tooltip 10135 // position on the map. 10136 direction: 'auto', 10137 10138 // @option permanent: Boolean = false 10139 // Whether to open the tooltip permanently or only on mouseover. 10140 permanent: false, 10141 10142 // @option sticky: Boolean = false 10143 // If true, the tooltip will follow the mouse instead of being fixed at the feature center.
10144 sticky: false, 10145 10146 // @option interactive: Boolean = false 10147 // If true, the tooltip will listen to the feature events. 10148 interactive: false, 10149 10150 // @option opacity: Number = 0.9 10151 // Tooltip container opacity. 10152 opacity: 0.9 10153 }, 10154 10155 onAdd: function (map) { 10156 DivOverlay.prototype.onAdd.call(this, map); 10157 this.setOpacity(this.options.opacity); 10158 10159 // @namespace Map 10160 // @section Tooltip events 10161 // @event tooltipopen: TooltipEvent 10162 // Fired when a tooltip is opened in the map. 10163 map.fire('tooltipopen', {tooltip: this}); 10164 10165 if (this._source) { 10166 // @namespace Layer 10167 // @section Tooltip events 10168 // @event tooltipopen: TooltipEvent 10169 // Fired when a tooltip bound to this layer is opened. 10170 this._source.fire('tooltipopen', {tooltip: this}, true); 10171 } 10172 }, 10173 10174 onRemove: function (map) { 10175 DivOverlay.prototype.onRemove.call(this, map); 10176 10177 // @namespace Map 10178 // @section Tooltip events 10179 // @event tooltipclose: TooltipEvent 10180 // Fired when a tooltip in the map is closed. 10181 map.fire('tooltipclose', {tooltip: this}); 10182 10183 if (this._source) { 10184 // @namespace Layer 10185 // @section Tooltip events 10186 // @event tooltipclose: TooltipEvent 10187 // Fired when a tooltip bound to this layer is closed. 10188 this._source.fire('tooltipclose', {tooltip: this}, true); 10189 } 10190 }, 10191 10192 getEvents: function () { 10193 var events = DivOverlay.prototype.getEvents.call(this); 10194 10195 if (touch && !this.options.permanent) { 10196 events.preclick = this._close; 10197 } 10198 10199 return events; 10200 }, 10201 10202 _close: function () { 10203 if (this._map) { 10204 this._map.closeTooltip(this); 10205 } 10206 }, 10207 10208 _initLayout: function () { 10209 var prefix = 'leaflet-tooltip', 10210 className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide'); 10211 10212 this._contentNode = this._container = create$1('div', className); 10213 }, 10214 10215 _updateLayout: function () {}, 10216 10217 _adjustPan: function () {}, 10218 10219 _setPosition: function (pos) { 10220 var map = this._map, 10221 container = this._container, 10222 centerPoint = map.latLngToContainerPoint(map.getCenter()), 10223 tooltipPoint = map.layerPointToContainerPoint(pos), 10224 direction = this.options.direction, 10225 tooltipWidth = container.offsetWidth, 10226 tooltipHeight = container.offsetHeight, 10227 offset = toPoint(this.options.offset), 10228 anchor = this._getAnchor(); 10229 10230 if (direction === 'top') { 10231 pos = pos.add(toPoint(-tooltipWidth / 2 + offset.x, -tooltipHeight + offset.y + anchor.y, true)); 10232 } else if (direction === 'bottom') { 10233 pos = pos.subtract(toPoint(tooltipWidth / 2 - offset.x, -offset.y, true)); 10234 } else if (direction === 'center') { 10235 pos = pos.subtract(toPoint(tooltipWidth / 2 + offset.x, tooltipHeight / 2 - anchor.y + offset.y, true)); 10236 } else if (direction === 'right' || direction === 'auto' && tooltipPoint.x < centerPoint.x) { 10237 direction = 'right'; 10238 pos = pos.add(toPoint(offset.x + anchor.x, anchor.y - tooltipHeight / 2 + offset.y, true)); 10239 } else { 10240 direction = 'left'; 10241 pos = pos.subtract(toPoint(tooltipWidth + anchor.x - offset.x, tooltipHeight / 2 - anchor.y - offset.y, true)); 10242 } 10243 10244 removeClass(container, 'leaflet-tooltip-right'); 10245 removeClass(container, 'leaflet-tooltip-left'); 10246 removeClass(container, 'leaflet-tooltip-top'); 10247 removeClass(container, 'leaflet-tooltip-bottom'); 10248 addClass(container, 'leaflet-tooltip-' + direction); 10249 setPosition(container, pos); 10250 }, 10251 10252 _updatePosition: function () { 10253 var pos = this._map.latLngToLayerPoint(this._latlng); 10254 this._setPosition(pos); 10255 }, 10256 10257 setOpacity: function (opacity) { 10258 this.options.opacity = opacity; 10259 10260 if (this._container) { 10261 setOpacity(this._container, opacity); 10262 } 10263 }, 10264 10265 _animateZoom: function (e) { 10266 var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center); 10267 this._setPosition(pos); 10268 }, 10269 10270 _getAnchor: function () { 10271 // Where should we anchor the tooltip on the source layer? 10272 return toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]); 10273 } 10274 10275}); 10276 10277// @namespace Tooltip 10278// @factory L.tooltip(options?: Tooltip options, source?: Layer) 10279// 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. 10280var tooltip = function (options, source) { 10281 return new Tooltip(options, source); 10282}; 10283 10284// @namespace Map 10285// @section Methods for Layers and Controls 10286Map.include({ 10287 10288 // @method openTooltip(tooltip: Tooltip): this 10289 // Opens the specified tooltip. 10290 // @alternative 10291 // @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this 10292 // Creates a tooltip with the specified content and options and open it. 10293 openTooltip: function (tooltip, latlng, options) { 10294 if (!(tooltip instanceof Tooltip)) { 10295 tooltip = new Tooltip(options).setContent(tooltip); 10296 } 10297 10298 if (latlng) { 10299 tooltip.setLatLng(latlng); 10300 } 10301 10302 if (this.hasLayer(tooltip)) { 10303 return this; 10304 } 10305 10306 return this.addLayer(tooltip); 10307 }, 10308 10309 // @method closeTooltip(tooltip?: Tooltip): this 10310 // Closes the tooltip given as parameter. 10311 closeTooltip: function (tooltip) { 10312 if (tooltip) { 10313 this.removeLayer(tooltip); 10314 } 10315 return this; 10316 } 10317 10318}); 10319 10320/* 10321 * @namespace Layer 10322 * @section Tooltip methods example 10323 * 10324 * All layers share a set of methods convenient for binding tooltips to it. 10325 * 10326 * ```js 10327 * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map); 10328 * layer.openTooltip(); 10329 * layer.closeTooltip(); 10330 * ``` 10331 */ 10332 10333// @section Tooltip methods 10334Layer.include({ 10335 10336 // @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this 10337 // Binds a tooltip to the layer with the passed `content` and sets up the 10338 // necessary event listeners. If a `Function` is passed it will receive 10339 // the layer as the first argument and should return a `String` or `HTMLElement`. 10340 bindTooltip: function (content, options) { 10341 10342 if (content instanceof Tooltip) { 10343 setOptions(content, options); 10344 this._tooltip = content; 10345 content._source = this; 10346 } else { 10347 if (!this._tooltip || options) { 10348 this._tooltip = new Tooltip(options, this); 10349 } 10350 this._tooltip.setContent(content); 10351 10352 } 10353 10354 this._initTooltipInteractions(); 10355 10356 if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) { 10357 this.openTooltip(); 10358 } 10359 10360 return this; 10361 }, 10362 10363 // @method unbindTooltip(): this 10364 // Removes the tooltip previously bound with `bindTooltip`. 10365 unbindTooltip: function () { 10366 if (this._tooltip) { 10367 this._initTooltipInteractions(true); 10368 this.closeTooltip(); 10369 this._tooltip = null; 10370 } 10371 return this; 10372 }, 10373 10374 _initTooltipInteractions: function (remove$$1) { 10375 if (!remove$$1 && this._tooltipHandlersAdded) { return; } 10376 var onOff = remove$$1 ? 'off' : 'on', 10377 events = { 10378 remove: this.closeTooltip, 10379 move: this._moveTooltip 10380 }; 10381 if (!this._tooltip.options.permanent) { 10382 events.mouseover = this._openTooltip; 10383 events.mouseout = this.closeTooltip; 10384 if (this._tooltip.options.sticky) { 10385 events.mousemove = this._moveTooltip; 10386 } 10387 if (touch) { 10388 events.click = this._openTooltip; 10389 } 10390 } else { 10391 events.add = this._openTooltip; 10392 } 10393 this[onOff](events); 10394 this._tooltipHandlersAdded = !remove$$1; 10395 }, 10396 10397 // @method openTooltip(latlng?: LatLng): this 10398 // Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed. 10399 openTooltip: function (layer, latlng) { 10400 if (!(layer instanceof Layer)) { 10401 latlng = layer; 10402 layer = this; 10403 } 10404 10405 if (layer instanceof FeatureGroup) { 10406 for (var id in this._layers) { 10407 layer = this._layers[id]; 10408 break; 10409 } 10410 } 10411 10412 if (!latlng) { 10413 latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng(); 10414 } 10415 10416 if (this._tooltip && this._map) { 10417 10418 // set tooltip source to this layer 10419 this._tooltip._source = layer; 10420 10421 // update the tooltip (content, layout, ect...) 10422 this._tooltip.update(); 10423 10424 // open the tooltip on the map 10425 this._map.openTooltip(this._tooltip, latlng); 10426 10427 // Tooltip container may not be defined if not permanent and never 10428 // opened. 10429 if (this._tooltip.options.interactive && this._tooltip._container) { 10430 addClass(this._tooltip._container, 'leaflet-clickable'); 10431 this.addInteractiveTarget(this._tooltip._container); 10432 } 10433 } 10434 10435 return this; 10436 }, 10437 10438 // @method closeTooltip(): this 10439 // Closes the tooltip bound to this layer if it is open. 10440 closeTooltip: function () { 10441 if (this._tooltip) { 10442 this._tooltip._close(); 10443 if (this._tooltip.options.interactive && this._tooltip._container) { 10444 removeClass(this._tooltip._container, 'leaflet-clickable'); 10445 this.removeInteractiveTarget(this._tooltip._container); 10446 } 10447 } 10448 return this; 10449 }, 10450 10451 // @method toggleTooltip(): this 10452 // Opens or closes the tooltip bound to this layer depending on its current state. 10453 toggleTooltip: function (target) { 10454 if (this._tooltip) { 10455 if (this._tooltip._map) { 10456 this.closeTooltip(); 10457 } else { 10458 this.openTooltip(target); 10459 } 10460 } 10461 return this; 10462 }, 10463 10464 // @method isTooltipOpen(): boolean 10465 // Returns `true` if the tooltip bound to this layer is currently open. 10466 isTooltipOpen: function () { 10467 return this._tooltip.isOpen(); 10468 }, 10469 10470 // @method setTooltipContent(content: String|HTMLElement|Tooltip): this
10471 // Sets the content of the tooltip bound to this layer. 10472 setTooltipContent: function (content) { 10473 if (this._tooltip) { 10474 this._tooltip.setContent(content); 10475 } 10476 return this; 10477 }, 10478 10479 // @method getTooltip(): Tooltip 10480 // Returns the tooltip bound to this layer. 10481 getTooltip: function () { 10482 return this._tooltip; 10483 }, 10484 10485 _openTooltip: function (e) { 10486 var layer = e.layer || e.target; 10487 10488 if (!this._tooltip || !this._map) { 10489 return; 10490 } 10491 this.openTooltip(layer, this._tooltip.options.sticky ? e.latlng : undefined); 10492 }, 10493 10494 _moveTooltip: function (e) { 10495 var latlng = e.latlng, containerPoint, layerPoint; 10496 if (this._tooltip.options.sticky && e.originalEvent) { 10497 containerPoint = this._map.mouseEventToContainerPoint(e.originalEvent); 10498 layerPoint = this._map.containerPointToLayerPoint(containerPoint); 10499 latlng = this._map.layerPointToLatLng(layerPoint); 10500 } 10501 this._tooltip.setLatLng(latlng); 10502 } 10503}); 10504 10505/* 10506 * @class DivIcon 10507 * @aka L.DivIcon 10508 * @inherits Icon 10509 * 10510 * Represents a lightweight icon for markers that uses a simple `<div>` 10511 * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options. 10512 * 10513 * @example 10514 * ```js 10515 * var myIcon = L.divIcon({className: 'my-div-icon'}); 10516 * // you can set .my-div-icon styles in CSS 10517 * 10518 * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map); 10519 * ``` 10520 * 10521 * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow. 10522 */ 10523 10524var DivIcon = Icon.extend({ 10525 options: { 10526 // @section 10527 // @aka DivIcon options 10528 iconSize: [12, 12], // also can be set through CSS 10529 10530 // iconAnchor: (Point), 10531 // popupAnchor: (Point), 10532 10533 // @option html: String = '' 10534 // Custom HTML code to put inside the div element, empty by default. 10535 html: false, 10536 10537 // @option bgPos: Point = [0, 0] 10538 // Optional relative position of the background, in pixels 10539 bgPos: null, 10540 10541 className: 'leaflet-div-icon' 10542 }, 10543 10544 createIcon: function (oldIcon) { 10545 var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'), 10546 options = this.options; 10547 10548 div.innerHTML = options.html !== false ? options.html : ''; 10549 10550 if (options.bgPos) { 10551 var bgPos = toPoint(options.bgPos); 10552 div.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px'; 10553 } 10554 this._setIconStyles(div, 'icon'); 10555 10556 return div; 10557 }, 10558 10559 createShadow: function () { 10560 return null; 10561 } 10562}); 10563 10564// @factory L.divIcon(options: DivIcon options) 10565// Creates a `DivIcon` instance with the given options. 10566function divIcon(options) { 10567 return new DivIcon(options); 10568} 10569 10570Icon.Default = IconDefault; 10571 10572/* 10573 * @class GridLayer 10574 * @inherits Layer 10575 * @aka L.GridLayer 10576 * 10577 * Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces `TileLayer.Canvas`. 10578 * 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. 10579 * 10580 * 10581 * @section Synchronous usage 10582 * @example 10583 * 10584 * 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. 10585 * 10586 * ```js 10587 * var CanvasLayer = L.GridLayer.extend({ 10588 * createTile: function(coords){ 10589 * // create a <canvas> element for drawing 10590 * var tile = L.DomUtil.create('canvas', 'leaflet-tile'); 10591 * 10592 * // setup tile width and height according to the options 10593 * var size = this.getTileSize(); 10594 * tile.width = size.x; 10595 * tile.height = size.y; 10596 * 10597 * // get a canvas context and draw something on it using coords.x, coords.y and coords.z 10598 * var ctx = tile.getContext('2d'); 10599 * 10600 * // return the tile so it can be rendered on screen 10601 * return tile; 10602 * } 10603 * }); 10604 * ``` 10605 * 10606 * @section Asynchronous usage 10607 * @example 10608 * 10609 * 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. 10610 * 10611 * ```js 10612 * var CanvasLayer = L.GridLayer.extend({ 10613 * createTile: function(coords, done){ 10614 * var error; 10615 * 10616 * // create a <canvas> element for drawing 10617 * var tile = L.DomUtil.create('canvas', 'leaflet-tile'); 10618 * 10619 * // setup tile width and height according to the options 10620 * var size = this.getTileSize(); 10621 * tile.width = size.x; 10622 * tile.height = size.y; 10623 * 10624 * // draw something asynchronously and pass the tile to the done() callback 10625 * setTimeout(function() { 10626 * done(error, tile); 10627 * }, 1000); 10628 * 10629 * return tile; 10630 * } 10631 * }); 10632 * ``` 10633 * 10634 * @section 10635 */ 10636 10637 10638var GridLayer = Layer.extend({ 10639 10640 // @section 10641 // @aka GridLayer options 10642 options: {
vendor: 44,535 bytes, lines 10643-12272
10643 // @option tileSize: Number|Point = 256 10644 // Width and height of tiles in the grid. Use a number if width and height are equal, or `L.point(width, height)` otherwise. 10645 tileSize: 256, 10646 10647 // @option opacity: Number = 1.0 10648 // Opacity of the tiles. Can be used in the `createTile()` function. 10649 opacity: 1, 10650 10651 // @option updateWhenIdle: Boolean = (depends) 10652 // Load new tiles only when panning ends. 10653 // `true` by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. 10654 // `false` otherwise in order to display new tiles _during_ panning, since it is easy to pan outside the 10655 // [`keepBuffer`](#gridlayer-keepbuffer) option in desktop browsers. 10656 updateWhenIdle: mobile, 10657 10658 // @option updateWhenZooming: Boolean = true 10659 // 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. 10660 updateWhenZooming: true, 10661 10662 // @option updateInterval: Number = 200 10663 // Tiles will not update more than once every `updateInterval` milliseconds when panning. 10664 updateInterval: 200, 10665 10666 // @option zIndex: Number = 1 10667 // The explicit zIndex of the tile layer. 10668 zIndex: 1, 10669 10670 // @option bounds: LatLngBounds = undefined 10671 // If set, tiles will only be loaded inside the set `LatLngBounds`. 10672 bounds: null, 10673 10674 // @option minZoom: Number = 0 10675 // The minimum zoom level down to which this layer will be displayed (inclusive). 10676 minZoom: 0, 10677 10678 // @option maxZoom: Number = undefined 10679 // The maximum zoom level up to which this layer will be displayed (inclusive). 10680 maxZoom: undefined, 10681 10682 // @option maxNativeZoom: Number = undefined 10683 // Maximum zoom number the tile source has available. If it is specified, 10684 // the tiles on all zoom levels higher than `maxNativeZoom` will be loaded 10685 // from `maxNativeZoom` level and auto-scaled. 10686 maxNativeZoom: undefined, 10687 10688 // @option minNativeZoom: Number = undefined 10689 // Minimum zoom number the tile source has available. If it is specified, 10690 // the tiles on all zoom levels lower than `minNativeZoom` will be loaded 10691 // from `minNativeZoom` level and auto-scaled. 10692 minNativeZoom: undefined, 10693 10694 // @option noWrap: Boolean = false 10695 // Whether the layer is wrapped around the antimeridian. If `true`, the 10696 // GridLayer will only be displayed once at low zoom levels. Has no 10697 // effect when the [map CRS](#map-crs) doesn't wrap around. Can be used 10698 // in combination with [`bounds`](#gridlayer-bounds) to prevent requesting 10699 // tiles outside the CRS limits. 10700 noWrap: false, 10701 10702 // @option pane: String = 'tilePane' 10703 // `Map pane` where the grid layer will be added. 10704 pane: 'tilePane', 10705 10706 // @option className: String = '' 10707 // A custom class name to assign to the tile layer. Empty by default. 10708 className: '', 10709 10710 // @option keepBuffer: Number = 2 10711 // When panning the map, keep this many rows and columns of tiles before unloading them. 10712 keepBuffer: 2 10713 }, 10714 10715 initialize: function (options) { 10716 setOptions(this, options); 10717 }, 10718 10719 onAdd: function () { 10720 this._initContainer(); 10721 10722 this._levels = {}; 10723 this._tiles = {}; 10724 10725 this._resetView(); 10726 this._update(); 10727 }, 10728 10729 beforeAdd: function (map) { 10730 map._addZoomLimit(this); 10731 }, 10732 10733 onRemove: function (map) { 10734 this._removeAllTiles(); 10735 remove(this._container); 10736 map._removeZoomLimit(this); 10737 this._container = null; 10738 this._tileZoom = undefined; 10739 }, 10740 10741 // @method bringToFront: this 10742 // Brings the tile layer to the top of all tile layers. 10743 bringToFront: function () { 10744 if (this._map) { 10745 toFront(this._container); 10746 this._setAutoZIndex(Math.max); 10747 } 10748 return this; 10749 }, 10750 10751 // @method bringToBack: this 10752 // Brings the tile layer to the bottom of all tile layers. 10753 bringToBack: function () { 10754 if (this._map) { 10755 toBack(this._container); 10756 this._setAutoZIndex(Math.min); 10757 } 10758 return this; 10759 }, 10760 10761 // @method getContainer: HTMLElement 10762 // Returns the HTML element that contains the tiles for this layer. 10763 getContainer: function () { 10764 return this._container; 10765 }, 10766 10767 // @method setOpacity(opacity: Number): this 10768 // Changes the [opacity](#gridlayer-opacity) of the grid layer. 10769 setOpacity: function (opacity) { 10770 this.options.opacity = opacity; 10771 this._updateOpacity(); 10772 return this; 10773 }, 10774 10775 // @method setZIndex(zIndex: Number): this 10776 // Changes the [zIndex](#gridlayer-zindex) of the grid layer. 10777 setZIndex: function (zIndex) { 10778 this.options.zIndex = zIndex; 10779 this._updateZIndex(); 10780 10781 return this; 10782 }, 10783 10784 // @method isLoading: Boolean 10785 // Returns `true` if any tile in the grid layer has not finished loading. 10786 isLoading: function () { 10787 return this._loading; 10788 }, 10789 10790 // @method redraw: this 10791 // Causes the layer to clear all the tiles and request them again. 10792 redraw: function () { 10793 if (this._map) { 10794 this._removeAllTiles(); 10795 this._update(); 10796 } 10797 return this; 10798 }, 10799 10800 getEvents: function () { 10801 var events = { 10802 viewprereset: this._invalidateAll, 10803 viewreset: this._resetView, 10804 zoom: this._resetView, 10805 moveend: this._onMoveEnd 10806 }; 10807 10808 if (!this.options.updateWhenIdle) { 10809 // update tiles on move, but not more often than once per given interval 10810 if (!this._onMove) { 10811 this._onMove = throttle(this._onMoveEnd, this.options.updateInterval, this); 10812 } 10813 10814 events.move = this._onMove; 10815 } 10816 10817 if (this._zoomAnimated) { 10818 events.zoomanim = this._animateZoom; 10819 } 10820 10821 return events; 10822 }, 10823 10824 // @section Extension methods 10825 // Layers extending `GridLayer` shall reimplement the following method. 10826 // @method createTile(coords: Object, done?: Function): HTMLElement 10827 // Called only internally, must be overridden by classes extending `GridLayer`. 10828 // Returns the `HTMLElement` corresponding to the given `coords`. If the `done` callback 10829 // is specified, it must be called when the tile has finished loading and drawing. 10830 createTile: function () { 10831 return document.createElement('div'); 10832 }, 10833 10834 // @section 10835 // @method getTileSize: Point 10836 // Normalizes the [tileSize option](#gridlayer-tilesize) into a point. Used by the `createTile()` method. 10837 getTileSize: function () { 10838 var s = this.options.tileSize; 10839 return s instanceof Point ? s : new Point(s, s); 10840 }, 10841 10842 _updateZIndex: function () { 10843 if (this._container && this.options.zIndex !== undefined && this.options.zIndex !== null) { 10844 this._container.style.zIndex = this.options.zIndex; 10845 } 10846 }, 10847 10848 _setAutoZIndex: function (compare) { 10849 // go through all other layers of the same pane, set zIndex to max + 1 (front) or min - 1 (back) 10850 10851 var layers = this.getPane().children, 10852 edgeZIndex = -compare(-Infinity, Infinity); // -Infinity for max, Infinity for min 10853 10854 for (var i = 0, len = layers.length, zIndex; i < len; i++) { 10855 10856 zIndex = layers[i].style.zIndex; 10857 10858 if (layers[i] !== this._container && zIndex) { 10859 edgeZIndex = compare(edgeZIndex, +zIndex); 10860 } 10861 } 10862 10863 if (isFinite(edgeZIndex)) { 10864 this.options.zIndex = edgeZIndex + compare(-1, 1); 10865 this._updateZIndex(); 10866 } 10867 }, 10868 10869 _updateOpacity: function () { 10870 if (!this._map) { return; } 10871 10872 // IE doesn't inherit filter opacity properly, so we're forced to set it on tiles 10873 if (ielt9) { return; } 10874 10875 setOpacity(this._container, this.options.opacity); 10876 10877 var now = +new Date(), 10878 nextFrame = false, 10879 willPrune = false; 10880 10881 for (var key in this._tiles) { 10882 var tile = this._tiles[key]; 10883 if (!tile.current || !tile.loaded) { continue; } 10884 10885 var fade = Math.min(1, (now - tile.loaded) / 200); 10886 10887 setOpacity(tile.el, fade); 10888 if (fade < 1) { 10889 nextFrame = true; 10890 } else { 10891 if (tile.active) { 10892 willPrune = true; 10893 } else { 10894 this._onOpaqueTile(tile); 10895 } 10896 tile.active = true; 10897 } 10898 } 10899 10900 if (willPrune && !this._noPrune) { this._pruneTiles(); } 10901 10902 if (nextFrame) { 10903 cancelAnimFrame(this._fadeFrame); 10904 this._fadeFrame = requestAnimFrame(this._updateOpacity, this); 10905 } 10906 }, 10907 10908 _onOpaqueTile: falseFn, 10909 10910 _initContainer: function () { 10911 if (this._container) { return; } 10912 10913 this._container = create$1('div', 'leaflet-layer ' + (this.options.className || '')); 10914 this._updateZIndex(); 10915 10916 if (this.options.opacity < 1) { 10917 this._updateOpacity(); 10918 } 10919 10920 this.getPane().appendChild(this._container); 10921 }, 10922 10923 _updateLevels: function () { 10924 10925 var zoom = this._tileZoom, 10926 maxZoom = this.options.maxZoom; 10927 10928 if (zoom === undefined) { return undefined; } 10929 10930 for (var z in this._levels) { 10931 if (this._levels[z].el.children.length || z === zoom) { 10932 this._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom - z); 10933 this._onUpdateLevel(z); 10934 } else { 10935 remove(this._levels[z].el); 10936 this._removeTilesAtZoom(z); 10937 this._onRemoveLevel(z); 10938 delete this._levels[z]; 10939 } 10940 } 10941 10942 var level = this._levels[zoom], 10943 map = this._map; 10944 10945 if (!level) { 10946 level = this._levels[zoom] = {}; 10947 10948 level.el = create$1('div', 'leaflet-tile-container leaflet-zoom-animated', this._container); 10949 level.el.style.zIndex = maxZoom; 10950 10951 level.origin = map.project(map.unproject(map.getPixelOrigin()), zoom).round(); 10952 level.zoom = zoom; 10953 10954 this._setZoomTransform(level, map.getCenter(), map.getZoom()); 10955 10956 // force the browser to consider the newly added element for transition 10957 falseFn(level.el.offsetWidth); 10958 10959 this._onCreateLevel(level); 10960 } 10961 10962 this._level = level; 10963 10964 return level; 10965 }, 10966 10967 _onUpdateLevel: falseFn, 10968 10969 _onRemoveLevel: falseFn, 10970 10971 _onCreateLevel: falseFn, 10972 10973 _pruneTiles: function () { 10974 if (!this._map) { 10975 return; 10976 } 10977 10978 var key, tile; 10979 10980 var zoom = this._map.getZoom(); 10981 if (zoom > this.options.maxZoom || 10982 zoom < this.options.minZoom) { 10983 this._removeAllTiles(); 10984 return; 10985 } 10986 10987 for (key in this._tiles) { 10988 tile = this._tiles[key]; 10989 tile.retain = tile.current; 10990 } 10991 10992 for (key in this._tiles) { 10993 tile = this._tiles[key]; 10994 if (tile.current && !tile.active) { 10995 var coords = tile.coords; 10996 if (!this._retainParent(coords.x, coords.y, coords.z, coords.z - 5)) { 10997 this._retainChildren(coords.x, coords.y, coords.z, coords.z + 2); 10998 } 10999 } 11000 } 11001 11002 for (key in this._tiles) { 11003 if (!this._tiles[key].retain) { 11004 this._removeTile(key); 11005 } 11006 } 11007 }, 11008 11009 _removeTilesAtZoom: function (zoom) { 11010 for (var key in this._tiles) { 11011 if (this._tiles[key].coords.z !== zoom) { 11012 continue; 11013 } 11014 this._removeTile(key); 11015 } 11016 }, 11017 11018 _removeAllTiles: function () { 11019 for (var key in this._tiles) { 11020 this._removeTile(key); 11021 } 11022 }, 11023 11024 _invalidateAll: function () { 11025 for (var z in this._levels) { 11026 remove(this._levels[z].el); 11027 this._onRemoveLevel(z); 11028 delete this._levels[z]; 11029 } 11030 this._removeAllTiles(); 11031 11032 this._tileZoom = undefined; 11033 }, 11034 11035 _retainParent: function (x, y, z, minZoom) { 11036 var x2 = Math.floor(x / 2), 11037 y2 = Math.floor(y / 2), 11038 z2 = z - 1, 11039 coords2 = new Point(+x2, +y2); 11040 coords2.z = +z2; 11041 11042 var key = this._tileCoordsToKey(coords2), 11043 tile = this._tiles[key]; 11044 11045 if (tile && tile.active) { 11046 tile.retain = true; 11047 return true; 11048 11049 } else if (tile && tile.loaded) { 11050 tile.retain = true; 11051 } 11052 11053 if (z2 > minZoom) { 11054 return this._retainParent(x2, y2, z2, minZoom); 11055 } 11056 11057 return false; 11058 }, 11059 11060 _retainChildren: function (x, y, z, maxZoom) { 11061 11062 for (var i = 2 * x; i < 2 * x + 2; i++) { 11063 for (var j = 2 * y; j < 2 * y + 2; j++) { 11064 11065 var coords = new Point(i, j); 11066 coords.z = z + 1; 11067 11068 var key = this._tileCoordsToKey(coords), 11069 tile = this._tiles[key]; 11070 11071 if (tile && tile.active) { 11072 tile.retain = true; 11073 continue; 11074 11075 } else if (tile && tile.loaded) { 11076 tile.retain = true; 11077 } 11078 11079 if (z + 1 < maxZoom) { 11080 this._retainChildren(i, j, z + 1, maxZoom); 11081 } 11082 } 11083 } 11084 }, 11085 11086 _resetView: function (e) { 11087 var animating = e && (e.pinch || e.flyTo); 11088 this._setView(this._map.getCenter(), this._map.getZoom(), animating, animating); 11089 }, 11090 11091 _animateZoom: function (e) { 11092 this._setView(e.center, e.zoom, true, e.noUpdate); 11093 }, 11094 11095 _clampZoom: function (zoom) { 11096 var options = this.options; 11097 11098 if (undefined !== options.minNativeZoom && zoom < options.minNativeZoom) { 11099 return options.minNativeZoom; 11100 } 11101 11102 if (undefined !== options.maxNativeZoom && options.maxNativeZoom < zoom) { 11103 return options.maxNativeZoom; 11104 } 11105 11106 return zoom; 11107 }, 11108 11109 _setView: function (center, zoom, noPrune, noUpdate) { 11110 var tileZoom = this._clampZoom(Math.round(zoom)); 11111 if ((this.options.maxZoom !== undefined && tileZoom > this.options.maxZoom) || 11112 (this.options.minZoom !== undefined && tileZoom < this.options.minZoom)) { 11113 tileZoom = undefined; 11114 } 11115 11116 var tileZoomChanged = this.options.updateWhenZooming && (tileZoom !== this._tileZoom); 11117 11118 if (!noUpdate || tileZoomChanged) { 11119 11120 this._tileZoom = tileZoom; 11121 11122 if (this._abortLoading) { 11123 this._abortLoading(); 11124 } 11125 11126 this._updateLevels(); 11127 this._resetGrid(); 11128 11129 if (tileZoom !== undefined) { 11130 this._update(center); 11131 } 11132 11133 if (!noPrune) { 11134 this._pruneTiles(); 11135 } 11136 11137 // Flag to prevent _updateOpacity from pruning tiles during 11138 // a zoom anim or a pinch gesture 11139 this._noPrune = !!noPrune; 11140 } 11141 11142 this._setZoomTransforms(center, zoom); 11143 }, 11144 11145 _setZoomTransforms: function (center, zoom) { 11146 for (var i in this._levels) { 11147 this._setZoomTransform(this._levels[i], center, zoom); 11148 } 11149 }, 11150 11151 _setZoomTransform: function (level, center, zoom) { 11152 var scale = this._map.getZoomScale(zoom, level.zoom), 11153 translate = level.origin.multiplyBy(scale) 11154 .subtract(this._map._getNewPixelOrigin(center, zoom)).round(); 11155 11156 if (any3d) { 11157 setTransform(level.el, translate, scale); 11158 } else { 11159 setPosition(level.el, translate); 11160 } 11161 }, 11162 11163 _resetGrid: function () { 11164 var map = this._map, 11165 crs = map.options.crs, 11166 tileSize = this._tileSize = this.getTileSize(), 11167 tileZoom = this._tileZoom; 11168 11169 var bounds = this._map.getPixelWorldBounds(this._tileZoom); 11170 if (bounds) { 11171 this._globalTileRange = this._pxBoundsToTileRange(bounds); 11172 } 11173 11174 this._wrapX = crs.wrapLng && !this.options.noWrap && [ 11175 Math.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x), 11176 Math.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y) 11177 ]; 11178 this._wrapY = crs.wrapLat && !this.options.noWrap && [ 11179 Math.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x), 11180 Math.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y) 11181 ]; 11182 }, 11183 11184 _onMoveEnd: function () { 11185 if (!this._map || this._map._animatingZoom) { return; } 11186 11187 this._update(); 11188 }, 11189 11190 _getTiledPixelBounds: function (center) { 11191 var map = this._map, 11192 mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(), 11193 scale = map.getZoomScale(mapZoom, this._tileZoom), 11194 pixelCenter = map.project(center, this._tileZoom).floor(), 11195 halfSize = map.getSize().divideBy(scale * 2); 11196 11197 return new Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize)); 11198 }, 11199 11200 // Private method to load tiles in the grid's active zoom level according to map bounds 11201 _update: function (center) { 11202 var map = this._map; 11203 if (!map) { return; } 11204 var zoom = this._clampZoom(map.getZoom()); 11205 11206 if (center === undefined) { center = map.getCenter(); } 11207 if (this._tileZoom === undefined) { return; } // if out of minzoom/maxzoom 11208 11209 var pixelBounds = this._getTiledPixelBounds(center), 11210 tileRange = this._pxBoundsToTileRange(pixelBounds), 11211 tileCenter = tileRange.getCenter(), 11212 queue = [], 11213 margin = this.options.keepBuffer, 11214 noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([margin, -margin]), 11215 tileRange.getTopRight().add([margin, -margin])); 11216 11217 // Sanity check: panic if the tile range contains Infinity somewhere. 11218 if (!(isFinite(tileRange.min.x) && 11219 isFinite(tileRange.min.y) && 11220 isFinite(tileRange.max.x) && 11221 isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); } 11222 11223 for (var key in this._tiles) { 11224 var c = this._tiles[key].coords; 11225 if (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) { 11226 this._tiles[key].current = false; 11227 } 11228 } 11229 11230 // _update just loads more tiles. If the tile zoom level differs too much 11231 // from the map's, let _setView reset levels and prune old tiles. 11232 if (Math.abs(zoom - this._tileZoom) > 1) { this._setView(center, zoom); return; } 11233 11234 // create a queue of coordinates to load tiles from 11235 for (var j = tileRange.min.y; j <= tileRange.max.y; j++) { 11236 for (var i = tileRange.min.x; i <= tileRange.max.x; i++) { 11237 var coords = new Point(i, j); 11238 coords.z = this._tileZoom; 11239 11240 if (!this._isValidTile(coords)) { continue; } 11241 11242 var tile = this._tiles[this._tileCoordsToKey(coords)]; 11243 if (tile) { 11244 tile.current = true; 11245 } else { 11246 queue.push(coords); 11247 } 11248 } 11249 } 11250 11251 // sort tile queue to load tiles in order of their distance to center 11252 queue.sort(function (a, b) { 11253 return a.distanceTo(tileCenter) - b.distanceTo(tileCenter); 11254 }); 11255 11256 if (queue.length !== 0) { 11257 // if it's the first batch of tiles to load 11258 if (!this._loading) { 11259 this._loading = true; 11260 // @event loading: Event 11261 // Fired when the grid layer starts loading tiles. 11262 this.fire('loading'); 11263 } 11264 11265 // create DOM fragment to append tiles in one batch 11266 var fragment = document.createDocumentFragment(); 11267 11268 for (i = 0; i < queue.length; i++) { 11269 this._addTile(queue[i], fragment); 11270 } 11271 11272 this._level.el.appendChild(fragment); 11273 } 11274 }, 11275 11276 _isValidTile: function (coords) { 11277 var crs = this._map.options.crs; 11278 11279 if (!crs.infinite) { 11280 // don't load tile if it's out of bounds and not wrapped 11281 var bounds = this._globalTileRange; 11282 if ((!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x)) || 11283 (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))) { return false; } 11284 } 11285 11286 if (!this.options.bounds) { return true; } 11287 11288 // don't load tile if it doesn't intersect the bounds in options 11289 var tileBounds = this._tileCoordsToBounds(coords); 11290 return toLatLngBounds(this.options.bounds).overlaps(tileBounds); 11291 }, 11292 11293 _keyToBounds: function (key) { 11294 return this._tileCoordsToBounds(this._keyToTileCoords(key)); 11295 }, 11296 11297 _tileCoordsToNwSe: function (coords) { 11298 var map = this._map, 11299 tileSize = this.getTileSize(), 11300 nwPoint = coords.scaleBy(tileSize), 11301 sePoint = nwPoint.add(tileSize), 11302 nw = map.unproject(nwPoint, coords.z), 11303 se = map.unproject(sePoint, coords.z); 11304 return [nw, se]; 11305 }, 11306 11307 // converts tile coordinates to its geographical bounds 11308 _tileCoordsToBounds: function (coords) { 11309 var bp = this._tileCoordsToNwSe(coords), 11310 bounds = new LatLngBounds(bp[0], bp[1]); 11311 11312 if (!this.options.noWrap) { 11313 bounds = this._map.wrapLatLngBounds(bounds); 11314 } 11315 return bounds; 11316 }, 11317 // converts tile coordinates to key for the tile cache 11318 _tileCoordsToKey: function (coords) { 11319 return coords.x + ':' + coords.y + ':' + coords.z; 11320 }, 11321 11322 // converts tile cache key to coordinates 11323 _keyToTileCoords: function (key) { 11324 var k = key.split(':'), 11325 coords = new Point(+k[0], +k[1]); 11326 coords.z = +k[2]; 11327 return coords; 11328 }, 11329 11330 _removeTile: function (key) { 11331 var tile = this._tiles[key]; 11332 if (!tile) { return; } 11333 11334 remove(tile.el); 11335 11336 delete this._tiles[key]; 11337 11338 // @event tileunload: TileEvent 11339 // Fired when a tile is removed (e.g. when a tile goes off the screen). 11340 this.fire('tileunload', { 11341 tile: tile.el, 11342 coords: this._keyToTileCoords(key) 11343 }); 11344 }, 11345 11346 _initTile: function (tile) { 11347 addClass(tile, 'leaflet-tile'); 11348 11349 var tileSize = this.getTileSize(); 11350 tile.style.width = tileSize.x + 'px'; 11351 tile.style.height = tileSize.y + 'px'; 11352 11353 tile.onselectstart = falseFn; 11354 tile.onmousemove = falseFn; 11355 11356 // update opacity on tiles in IE7-8 because of filter inheritance problems 11357 if (ielt9 && this.options.opacity < 1) { 11358 setOpacity(tile, this.options.opacity); 11359 } 11360 11361 // without this hack, tiles disappear after zoom on Chrome for Android 11362 // https://github.com/Leaflet/Leaflet/issues/2078 11363 if (android && !android23) { 11364 tile.style.WebkitBackfaceVisibility = 'hidden'; 11365 } 11366 }, 11367 11368 _addTile: function (coords, container) { 11369 var tilePos = this._getTilePos(coords), 11370 key = this._tileCoordsToKey(coords); 11371 11372 var tile = this.createTile(this._wrapCoords(coords), bind(this._tileReady, this, coords)); 11373 11374 this._initTile(tile); 11375 11376 // if createTile is defined with a second argument ("done" callback), 11377 // we know that tile is async and will be ready later; otherwise 11378 if (this.createTile.length < 2) { 11379 // mark tile as ready, but delay one frame for opacity animation to happen 11380 requestAnimFrame(bind(this._tileReady, this, coords, null, tile)); 11381 } 11382 11383 setPosition(tile, tilePos); 11384 11385 // save tile in cache 11386 this._tiles[key] = { 11387 el: tile, 11388 coords: coords, 11389 current: true 11390 }; 11391 11392 container.appendChild(tile); 11393 // @event tileloadstart: TileEvent 11394 // Fired when a tile is requested and starts loading. 11395 this.fire('tileloadstart', { 11396 tile: tile, 11397 coords: coords 11398 }); 11399 }, 11400 11401 _tileReady: function (coords, err, tile) { 11402 if (err) { 11403 // @event tileerror: TileErrorEvent 11404 // Fired when there is an error loading a tile. 11405 this.fire('tileerror', { 11406 error: err, 11407 tile: tile, 11408 coords: coords 11409 }); 11410 } 11411 11412 var key = this._tileCoordsToKey(coords); 11413 11414 tile = this._tiles[key]; 11415 if (!tile) { return; } 11416 11417 tile.loaded = +new Date(); 11418 if (this._map._fadeAnimated) { 11419 setOpacity(tile.el, 0); 11420 cancelAnimFrame(this._fadeFrame); 11421 this._fadeFrame = requestAnimFrame(this._updateOpacity, this); 11422 } else { 11423 tile.active = true; 11424 this._pruneTiles(); 11425 } 11426 11427 if (!err) { 11428 addClass(tile.el, 'leaflet-tile-loaded'); 11429 11430 // @event tileload: TileEvent 11431 // Fired when a tile loads. 11432 this.fire('tileload', { 11433 tile: tile.el, 11434 coords: coords 11435 }); 11436 } 11437 11438 if (this._noTilesToLoad()) { 11439 this._loading = false; 11440 // @event load: Event 11441 // Fired when the grid layer loaded all visible tiles. 11442 this.fire('load'); 11443 11444 if (ielt9 || !this._map._fadeAnimated) { 11445 requestAnimFrame(this._pruneTiles, this); 11446 } else { 11447 // Wait a bit more than 0.2 secs (the duration of the tile fade-in) 11448 // to trigger a pruning. 11449 setTimeout(bind(this._pruneTiles, this), 250); 11450 } 11451 } 11452 }, 11453 11454 _getTilePos: function (coords) { 11455 return coords.scaleBy(this.getTileSize()).subtract(this._level.origin); 11456 }, 11457 11458 _wrapCoords: function (coords) { 11459 var newCoords = new Point( 11460 this._wrapX ? wrapNum(coords.x, this._wrapX) : coords.x, 11461 this._wrapY ? wrapNum(coords.y, this._wrapY) : coords.y); 11462 newCoords.z = coords.z; 11463 return newCoords; 11464 }, 11465 11466 _pxBoundsToTileRange: function (bounds) { 11467 var tileSize = this.getTileSize(); 11468 return new Bounds( 11469 bounds.min.unscaleBy(tileSize).floor(), 11470 bounds.max.unscaleBy(tileSize).ceil().subtract([1, 1])); 11471 }, 11472 11473 _noTilesToLoad: function () { 11474 for (var key in this._tiles) { 11475 if (!this._tiles[key].loaded) { return false; } 11476 } 11477 return true; 11478 } 11479}); 11480 11481// @factory L.gridLayer(options?: GridLayer options) 11482// Creates a new instance of GridLayer with the supplied options. 11483function gridLayer(options) { 11484 return new GridLayer(options); 11485} 11486 11487/* 11488 * @class TileLayer 11489 * @inherits GridLayer 11490 * @aka L.TileLayer 11491 * Used to load and display tile layers on the map. Extends `GridLayer`. 11492 * 11493 * @example 11494 * 11495 * ```js 11496 * L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map); 11497 * ``` 11498 * 11499 * @section URL template 11500 * @example 11501 * 11502 * A string of the following form: 11503 * 11504 * ``` 11505 * 'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png' 11506 * ``` 11507 * 11508 * `{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. 11509 * 11510 * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this: 11511 * 11512 * ``` 11513 * L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'}); 11514 * ``` 11515 */ 11516 11517 11518var TileLayer = GridLayer.extend({ 11519 11520 // @section 11521 // @aka TileLayer options 11522 options: { 11523 // @option minZoom: Number = 0 11524 // The minimum zoom level down to which this layer will be displayed (inclusive). 11525 minZoom: 0, 11526 11527 // @option maxZoom: Number = 18 11528 // The maximum zoom level up to which this layer will be displayed (inclusive). 11529 maxZoom: 18, 11530 11531 // @option subdomains: String|String[] = 'abc' 11532 // 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. 11533 subdomains: 'abc', 11534 11535 // @option errorTileUrl: String = '' 11536 // URL to the tile image to show in place of the tile that failed to load. 11537 errorTileUrl: '', 11538 11539 // @option zoomOffset: Number = 0 11540 // The zoom number used in tile URLs will be offset with this value. 11541 zoomOffset: 0, 11542 11543 // @option tms: Boolean = false 11544 // If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services). 11545 tms: false, 11546 11547 // @option zoomReverse: Boolean = false 11548 // If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`) 11549 zoomReverse: false, 11550 11551 // @option detectRetina: Boolean = false 11552 // 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. 11553 detectRetina: false, 11554 11555 // @option crossOrigin: Boolean|String = false 11556 // Whether the crossOrigin attribute will be added to the tiles. 11557 // 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. 11558 // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values. 11559 crossOrigin: false 11560 }, 11561 11562 initialize: function (url, options) { 11563 11564 this._url = url; 11565 11566 options = setOptions(this, options); 11567 11568 // detecting retina displays, adjusting tileSize and zoom levels 11569 if (options.detectRetina && retina && options.maxZoom > 0) { 11570 11571 options.tileSize = Math.floor(options.tileSize / 2); 11572 11573 if (!options.zoomReverse) { 11574 options.zoomOffset++; 11575 options.maxZoom--; 11576 } else { 11577 options.zoomOffset--; 11578 options.minZoom++; 11579 } 11580 11581 options.minZoom = Math.max(0, options.minZoom); 11582 } 11583 11584 if (typeof options.subdomains === 'string') { 11585 options.subdomains = options.subdomains.split(''); 11586 } 11587 11588 // for https://github.com/Leaflet/Leaflet/issues/137 11589 if (!android) { 11590 this.on('tileunload', this._onTileRemove); 11591 } 11592 }, 11593 11594 // @method setUrl(url: String, noRedraw?: Boolean): this 11595 // Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`). 11596 setUrl: function (url, noRedraw) { 11597 this._url = url; 11598 11599 if (!noRedraw) { 11600 this.redraw(); 11601 } 11602 return this; 11603 }, 11604 11605 // @method createTile(coords: Object, done?: Function): HTMLElement 11606 // Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile) 11607 // to return an `<img>` HTML element with the appropriate image URL given `coords`. The `done` 11608 // callback is called when the tile has been loaded. 11609 createTile: function (coords, done) { 11610 var tile = document.createElement('img'); 11611 11612 on(tile, 'load', bind(this._tileOnLoad, this, done, tile)); 11613 on(tile, 'error', bind(this._tileOnError, this, done, tile)); 11614 11615 if (this.options.crossOrigin || this.options.crossOrigin === '') { 11616 tile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin; 11617 } 11618 11619 /* 11620 Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons 11621 http://www.w3.org/TR/WCAG20-TECHS/H67 11622 */ 11623 tile.alt = ''; 11624 11625 /* 11626 Set role="presentation" to force screen readers to ignore this 11627 https://www.w3.org/TR/wai-aria/roles#textalternativecomputation 11628 */ 11629 tile.setAttribute('role', 'presentation'); 11630 11631 tile.src = this.getTileUrl(coords); 11632 11633 return tile; 11634 }, 11635 11636 // @section Extension methods 11637 // @uninheritable 11638 // Layers extending `TileLayer` might reimplement the following method. 11639 // @method getTileUrl(coords: Object): String 11640 // Called only internally, returns the URL for a tile given its coordinates. 11641 // Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes. 11642 getTileUrl: function (coords) { 11643 var data = { 11644 r: retina ? '@2x' : '', 11645 s: this._getSubdomain(coords), 11646 x: coords.x, 11647 y: coords.y, 11648 z: this._getZoomForUrl() 11649 }; 11650 if (this._map && !this._map.options.crs.infinite) { 11651 var invertedY = this._globalTileRange.max.y - coords.y; 11652 if (this.options.tms) { 11653 data['y'] = invertedY; 11654 } 11655 data['-y'] = invertedY; 11656 } 11657 11658 return template(this._url, extend(data, this.options)); 11659 }, 11660 11661 _tileOnLoad: function (done, tile) { 11662 // For https://github.com/Leaflet/Leaflet/issues/3332 11663 if (ielt9) { 11664 setTimeout(bind(done, this, null, tile), 0); 11665 } else { 11666 done(null, tile); 11667 } 11668 }, 11669 11670 _tileOnError: function (done, tile, e) { 11671 var errorUrl = this.options.errorTileUrl; 11672 if (errorUrl && tile.getAttribute('src') !== errorUrl) { 11673 tile.src = errorUrl; 11674 } 11675 done(e, tile); 11676 }, 11677 11678 _onTileRemove: function (e) { 11679 e.tile.onload = null; 11680 }, 11681 11682 _getZoomForUrl: function () { 11683 var zoom = this._tileZoom, 11684 maxZoom = this.options.maxZoom, 11685 zoomReverse = this.options.zoomReverse, 11686 zoomOffset = this.options.zoomOffset; 11687 11688 if (zoomReverse) { 11689 zoom = maxZoom - zoom; 11690 } 11691 11692 return zoom + zoomOffset; 11693 }, 11694 11695 _getSubdomain: function (tilePoint) { 11696 var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length; 11697 return this.options.subdomains[index]; 11698 }, 11699 11700 // stops loading all tiles in the background layer 11701 _abortLoading: function () { 11702 var i, tile; 11703 for (i in this._tiles) { 11704 if (this._tiles[i].coords.z !== this._tileZoom) { 11705 tile = this._tiles[i].el; 11706 11707 tile.onload = falseFn; 11708 tile.onerror = falseFn; 11709 11710 if (!tile.complete) { 11711 tile.src = emptyImageUrl; 11712 remove(tile); 11713 delete this._tiles[i]; 11714 } 11715 } 11716 } 11717 }, 11718 11719 _removeTile: function (key) { 11720 var tile = this._tiles[key]; 11721 if (!tile) { return; } 11722 11723 // Cancels any pending http requests associated with the tile 11724 // unless we're on Android's stock browser, 11725 // see https://github.com/Leaflet/Leaflet/issues/137 11726 if (!androidStock) { 11727 tile.el.setAttribute('src', emptyImageUrl); 11728 } 11729 11730 return GridLayer.prototype._removeTile.call(this, key); 11731 }, 11732 11733 _tileReady: function (coords, err, tile) { 11734 if (!this._map || (tile && tile.getAttribute('src') === emptyImageUrl)) { 11735 return; 11736 } 11737 11738 return GridLayer.prototype._tileReady.call(this, coords, err, tile); 11739 } 11740}); 11741 11742 11743// @factory L.tilelayer(urlTemplate: String, options?: TileLayer options) 11744// Instantiates a tile layer object given a `URL template` and optionally an options object. 11745 11746function tileLayer(url, options) { 11747 return new TileLayer(url, options); 11748} 11749 11750/* 11751 * @class TileLayer.WMS 11752 * @inherits TileLayer 11753 * @aka L.TileLayer.WMS 11754 * Used to display [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services as tile layers on the map. Extends `TileLayer`. 11755 * 11756 * @example 11757 * 11758 * ```js 11759 * var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", { 11760 * layers: 'nexrad-n0r-900913', 11761 * format: 'image/png', 11762 * transparent: true, 11763 * attribution: "Weather data © 2012 IEM Nexrad" 11764 * }); 11765 * ``` 11766 */ 11767 11768var TileLayerWMS = TileLayer.extend({ 11769 11770 // @section 11771 // @aka TileLayer.WMS options 11772 // If any custom options not documented here are used, they will be sent to the 11773 // WMS server as extra parameters in each request URL. This can be useful for 11774 // [non-standard vendor WMS parameters](http://docs.geoserver.org/stable/en/user/services/wms/vendor.html). 11775 defaultWmsParams: { 11776 service: 'WMS', 11777 request: 'GetMap', 11778 11779 // @option layers: String = '' 11780 // **(required)** Comma-separated list of WMS layers to show. 11781 layers: '', 11782 11783 // @option styles: String = '' 11784 // Comma-separated list of WMS styles. 11785 styles: '', 11786 11787 // @option format: String = 'image/jpeg' 11788 // WMS image format (use `'image/png'` for layers with transparency). 11789 format: 'image/jpeg', 11790 11791 // @option transparent: Boolean = false 11792 // If `true`, the WMS service will return images with transparency. 11793 transparent: false, 11794 11795 // @option version: String = '1.1.1' 11796 // Version of the WMS service to use 11797 version: '1.1.1' 11798 }, 11799 11800 options: { 11801 // @option crs: CRS = null 11802 // Coordinate Reference System to use for the WMS requests, defaults to 11803 // map CRS. Don't change this if you're not sure what it means. 11804 crs: null, 11805 11806 // @option uppercase: Boolean = false 11807 // If `true`, WMS request parameter keys will be uppercase. 11808 uppercase: false 11809 }, 11810 11811 initialize: function (url, options) { 11812 11813 this._url = url; 11814 11815 var wmsParams = extend({}, this.defaultWmsParams); 11816 11817 // all keys that are not TileLayer options go to WMS params 11818 for (var i in options) { 11819 if (!(i in this.options)) { 11820 wmsParams[i] = options[i]; 11821 } 11822 } 11823 11824 options = setOptions(this, options); 11825 11826 var realRetina = options.detectRetina && retina ? 2 : 1; 11827 var tileSize = this.getTileSize(); 11828 wmsParams.width = tileSize.x * realRetina; 11829 wmsParams.height = tileSize.y * realRetina; 11830 11831 this.wmsParams = wmsParams; 11832 }, 11833 11834 onAdd: function (map) { 11835 11836 this._crs = this.options.crs || map.options.crs; 11837 this._wmsVersion = parseFloat(this.wmsParams.version); 11838 11839 var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs'; 11840 this.wmsParams[projectionKey] = this._crs.code; 11841 11842 TileLayer.prototype.onAdd.call(this, map); 11843 }, 11844 11845 getTileUrl: function (coords) { 11846 11847 var tileBounds = this._tileCoordsToNwSe(coords), 11848 crs = this._crs, 11849 bounds = toBounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])), 11850 min = bounds.min, 11851 max = bounds.max, 11852 bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ? 11853 [min.y, min.x, max.y, max.x] : 11854 [min.x, min.y, max.x, max.y]).join(','), 11855 url = TileLayer.prototype.getTileUrl.call(this, coords); 11856 return url + 11857 getParamString(this.wmsParams, url, this.options.uppercase) + 11858 (this.options.uppercase ? '&BBOX=' : '&bbox=') + bbox; 11859 }, 11860 11861 // @method setParams(params: Object, noRedraw?: Boolean): this 11862 // Merges an object with the new parameters and re-requests tiles on the current screen (unless `noRedraw` was set to true). 11863 setParams: function (params, noRedraw) { 11864 11865 extend(this.wmsParams, params); 11866 11867 if (!noRedraw) { 11868 this.redraw(); 11869 } 11870 11871 return this; 11872 } 11873}); 11874 11875 11876// @factory L.tileLayer.wms(baseUrl: String, options: TileLayer.WMS options) 11877// Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object. 11878function tileLayerWMS(url, options) { 11879 return new TileLayerWMS(url, options); 11880} 11881 11882TileLayer.WMS = TileLayerWMS; 11883tileLayer.wms = tileLayerWMS; 11884 11885/* 11886 * @class Renderer 11887 * @inherits Layer 11888 * @aka L.Renderer 11889 * 11890 * Base class for vector renderer implementations (`SVG`, `Canvas`). Handles the 11891 * DOM container of the renderer, its bounds, and its zoom animation. 11892 * 11893 * A `Renderer` works as an implicit layer group for all `Path`s - the renderer 11894 * itself can be added or removed to the map. All paths use a renderer, which can 11895 * be implicit (the map will decide the type of renderer and use it automatically) 11896 * or explicit (using the [`renderer`](#path-renderer) option of the path). 11897 * 11898 * Do not use this class directly, use `SVG` and `Canvas` instead. 11899 * 11900 * @event update: Event 11901 * Fired when the renderer updates its bounds, center and zoom, for example when 11902 * its map has moved 11903 */ 11904 11905var Renderer = Layer.extend({ 11906 11907 // @section 11908 // @aka Renderer options 11909 options: { 11910 // @option padding: Number = 0.1 11911 // How much to extend the clip area around the map view (relative to its size) 11912 // e.g. 0.1 would be 10% of map view in each direction 11913 padding: 0.1, 11914 11915 // @option tolerance: Number = 0 11916 // How much to extend click tolerance round a path/object on the map 11917 tolerance : 0 11918 }, 11919 11920 initialize: function (options) { 11921 setOptions(this, options); 11922 stamp(this); 11923 this._layers = this._layers || {}; 11924 }, 11925 11926 onAdd: function () { 11927 if (!this._container) { 11928 this._initContainer(); // defined by renderer implementations 11929 11930 if (this._zoomAnimated) { 11931 addClass(this._container, 'leaflet-zoom-animated'); 11932 } 11933 } 11934 11935 this.getPane().appendChild(this._container); 11936 this._update(); 11937 this.on('update', this._updatePaths, this); 11938 }, 11939 11940 onRemove: function () { 11941 this.off('update', this._updatePaths, this); 11942 this._destroyContainer(); 11943 }, 11944 11945 getEvents: function () { 11946 var events = { 11947 viewreset: this._reset, 11948 zoom: this._onZoom, 11949 moveend: this._update, 11950 zoomend: this._onZoomEnd 11951 }; 11952 if (this._zoomAnimated) { 11953 events.zoomanim = this._onAnimZoom; 11954 } 11955 return events; 11956 }, 11957 11958 _onAnimZoom: function (ev) { 11959 this._updateTransform(ev.center, ev.zoom); 11960 }, 11961 11962 _onZoom: function () { 11963 this._updateTransform(this._map.getCenter(), this._map.getZoom()); 11964 }, 11965 11966 _updateTransform: function (center, zoom) { 11967 var scale = this._map.getZoomScale(zoom, this._zoom), 11968 position = getPosition(this._container), 11969 viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding), 11970 currentCenterPoint = this._map.project(this._center, zoom), 11971 destCenterPoint = this._map.project(center, zoom), 11972 centerOffset = destCenterPoint.subtract(currentCenterPoint), 11973 11974 topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(viewHalf).subtract(centerOffset); 11975 11976 if (any3d) { 11977 setTransform(this._container, topLeftOffset, scale); 11978 } else { 11979 setPosition(this._container, topLeftOffset); 11980 } 11981 }, 11982 11983 _reset: function () { 11984 this._update(); 11985 this._updateTransform(this._center, this._zoom); 11986 11987 for (var id in this._layers) { 11988 this._layers[id]._reset(); 11989 } 11990 }, 11991 11992 _onZoomEnd: function () { 11993 for (var id in this._layers) { 11994 this._layers[id]._project(); 11995 } 11996 }, 11997 11998 _updatePaths: function () { 11999 for (var id in this._layers) { 12000 this._layers[id]._update(); 12001 } 12002 }, 12003 12004 _update: function () { 12005 // Update pixel bounds of renderer container (for positioning/sizing/clipping later) 12006 // Subclasses are responsible of firing the 'update' event. 12007 var p = this.options.padding, 12008 size = this._map.getSize(), 12009 min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round(); 12010 12011 this._bounds = new Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round()); 12012 12013 this._center = this._map.getCenter(); 12014 this._zoom = this._map.getZoom(); 12015 } 12016}); 12017 12018/* 12019 * @class Canvas 12020 * @inherits Renderer 12021 * @aka L.Canvas 12022 * 12023 * Allows vector layers to be displayed with [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API). 12024 * Inherits `Renderer`. 12025 * 12026 * Due to [technical limitations](http://caniuse.com/#search=canvas), Canvas is not 12027 * available in all web browsers, notably IE8, and overlapping geometries might 12028 * not display properly in some edge cases. 12029 * 12030 * @example 12031 * 12032 * Use Canvas by default for all paths in the map: 12033 * 12034 * ```js 12035 * var map = L.map('map', { 12036 * renderer: L.canvas() 12037 * }); 12038 * ``` 12039 * 12040 * Use a Canvas renderer with extra padding for specific vector geometries: 12041 * 12042 * ```js 12043 * var map = L.map('map'); 12044 * var myRenderer = L.canvas({ padding: 0.5 }); 12045 * var line = L.polyline( coordinates, { renderer: myRenderer } ); 12046 * var circle = L.circle( center, { renderer: myRenderer } ); 12047 * ``` 12048 */ 12049 12050var Canvas = Renderer.extend({ 12051 getEvents: function () { 12052 var events = Renderer.prototype.getEvents.call(this); 12053 events.viewprereset = this._onViewPreReset; 12054 return events; 12055 }, 12056 12057 _onViewPreReset: function () { 12058 // Set a flag so that a viewprereset+moveend+viewreset only updates&redraws once 12059 this._postponeUpdatePaths = true; 12060 }, 12061 12062 onAdd: function () { 12063 Renderer.prototype.onAdd.call(this); 12064 12065 // Redraw vectors since canvas is cleared upon removal, 12066 // in case of removing the renderer itself from the map. 12067 this._draw(); 12068 }, 12069 12070 _initContainer: function () { 12071 var container = this._container = document.createElement('canvas'); 12072 12073 on(container, 'mousemove', throttle(this._onMouseMove, 32, this), this); 12074 on(container, 'click dblclick mousedown mouseup contextmenu', this._onClick, this); 12075 on(container, 'mouseout', this._handleMouseOut, this); 12076 12077 this._ctx = container.getContext('2d'); 12078 }, 12079 12080 _destroyContainer: function () { 12081 cancelAnimFrame(this._redrawRequest); 12082 delete this._ctx; 12083 remove(this._container); 12084 off(this._container); 12085 delete this._container; 12086 }, 12087 12088 _updatePaths: function () { 12089 if (this._postponeUpdatePaths) { return; } 12090 12091 var layer; 12092 this._redrawBounds = null; 12093 for (var id in this._layers) { 12094 layer = this._layers[id]; 12095 layer._update(); 12096 } 12097 this._redraw(); 12098 }, 12099 12100 _update: function () { 12101 if (this._map._animatingZoom && this._bounds) { return; } 12102 12103 this._drawnLayers = {}; 12104 12105 Renderer.prototype._update.call(this); 12106 12107 var b = this._bounds, 12108 container = this._container, 12109 size = b.getSize(), 12110 m = retina ? 2 : 1; 12111 12112 setPosition(container, b.min); 12113 12114 // set canvas size (also clearing it); use double size on retina 12115 container.width = m * size.x; 12116 container.height = m * size.y; 12117 container.style.width = size.x + 'px'; 12118 container.style.height = size.y + 'px'; 12119 12120 if (retina) { 12121 this._ctx.scale(2, 2); 12122 } 12123 12124 // translate so we use the same path coordinates after canvas element moves 12125 this._ctx.translate(-b.min.x, -b.min.y); 12126 12127 // Tell paths to redraw themselves 12128 this.fire('update'); 12129 }, 12130 12131 _reset: function () { 12132 Renderer.prototype._reset.call(this); 12133 12134 if (this._postponeUpdatePaths) { 12135 this._postponeUpdatePaths = false; 12136 this._updatePaths(); 12137 } 12138 }, 12139 12140 _initPath: function (layer) { 12141 this._updateDashArray(layer); 12142 this._layers[stamp(layer)] = layer; 12143 12144 var order = layer._order = { 12145 layer: layer, 12146 prev: this._drawLast, 12147 next: null 12148 }; 12149 if (this._drawLast) { this._drawLast.next = order; } 12150 this._drawLast = order; 12151 this._drawFirst = this._drawFirst || this._drawLast; 12152 }, 12153 12154 _addPath: function (layer) { 12155 this._requestRedraw(layer); 12156 }, 12157 12158 _removePath: function (layer) { 12159 var order = layer._order; 12160 var next = order.next; 12161 var prev = order.prev; 12162 12163 if (next) { 12164 next.prev = prev; 12165 } else { 12166 this._drawLast = prev; 12167 } 12168 if (prev) { 12169 prev.next = next; 12170 } else { 12171 this._drawFirst = next; 12172 } 12173 12174 delete this._drawnLayers[layer._leaflet_id]; 12175 12176 delete layer._order; 12177 12178 delete this._layers[stamp(layer)]; 12179 12180 this._requestRedraw(layer); 12181 }, 12182 12183 _updatePath: function (layer) { 12184 // Redraw the union of the layer's old pixel 12185 // bounds and the new pixel bounds. 12186 this._extendRedrawBounds(layer); 12187 layer._project(); 12188 layer._update(); 12189 // The redraw will extend the redraw bounds 12190 // with the new pixel bounds. 12191 this._requestRedraw(layer); 12192 }, 12193 12194 _updateStyle: function (layer) { 12195 this._updateDashArray(layer); 12196 this._requestRedraw(layer); 12197 }, 12198 12199 _updateDashArray: function (layer) { 12200 if (typeof layer.options.dashArray === 'string') { 12201 var parts = layer.options.dashArray.split(/[, ]+/), 12202 dashArray = [], 12203 i; 12204 for (i = 0; i < parts.length; i++) { 12205 dashArray.push(Number(parts[i])); 12206 } 12207 layer.options._dashArray = dashArray; 12208 } else { 12209 layer.options._dashArray = layer.options.dashArray; 12210 } 12211 }, 12212 12213 _requestRedraw: function (layer) { 12214 if (!this._map) { return; } 12215 12216 this._extendRedrawBounds(layer); 12217 this._redrawRequest = this._redrawRequest || requestAnimFrame(this._redraw, this); 12218 }, 12219 12220 _extendRedrawBounds: function (layer) { 12221 if (layer._pxBounds) { 12222 var padding = (layer.options.weight || 0) + 1; 12223 this._redrawBounds = this._redrawBounds || new Bounds(); 12224 this._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding])); 12225 this._redrawBounds.extend(layer._pxBounds.max.add([padding, padding])); 12226 } 12227 }, 12228 12229 _redraw: function () { 12230 this._redrawRequest = null; 12231 12232 if (this._redrawBounds) { 12233 this._redrawBounds.min._floor(); 12234 this._redrawBounds.max._ceil(); 12235 } 12236 12237 this._clear(); // clear layers in redraw bounds 12238 this._draw(); // draw layers 12239 12240 this._redrawBounds = null; 12241 }, 12242 12243 _clear: function () { 12244 var bounds = this._redrawBounds; 12245 if (bounds) { 12246 var size = bounds.getSize(); 12247 this._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y); 12248 } else { 12249 this._ctx.clearRect(0, 0, this._container.width, this._container.height); 12250 } 12251 }, 12252 12253 _draw: function () { 12254 var layer, bounds = this._redrawBounds; 12255 this._ctx.save(); 12256 if (bounds) { 12257 var size = bounds.getSize(); 12258 this._ctx.beginPath(); 12259 this._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y); 12260 this._ctx.clip(); 12261 } 12262 12263 this._drawing = true; 12264 12265 for (var order = this._drawFirst; order; order = order.next) { 12266 layer = order.layer; 12267 if (!bounds || (layer._pxBounds && layer._pxBounds.intersects(bounds))) { 12268 layer._updatePath(); 12269 } 12270 } 12271 12272 this._drawing = false;
12273 12274 this._ctx.restore(); // Restore state before clipping. 12275 }, 12276 12277 _updatePoly: function (layer, closed) { 12278 if (!this._drawing) { return; } 12279 12280 var i, j, len2, p, 12281 parts = layer._parts, 12282 len = parts.length, 12283 ctx = this._ctx; 12284 12285 if (!len) { return; } 12286 12287 this._drawnLayers[layer._leaflet_id] = layer; 12288 12289 ctx.beginPath(); 12290 12291 for (i = 0; i < len; i++) { 12292 for (j = 0, len2 = parts[i].length; j < len2; j++) { 12293 p = parts[i][j]; 12294 ctx[j ? 'lineTo' : 'moveTo'](p.x, p.y); 12295 } 12296 if (closed) { 12297 ctx.closePath(); 12298 } 12299 } 12300 12301 this._fillStroke(ctx, layer); 12302 12303 // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature 12304 }, 12305 12306 _updateCircle: function (layer) { 12307 12308 if (!this._drawing || layer._empty()) { return; } 12309 12310 var p = layer._point, 12311 ctx = this._ctx, 12312 r = Math.max(Math.round(layer._radius), 1), 12313 s = (Math.max(Math.round(layer._radiusY), 1) || r) / r; 12314 12315 this._drawnLayers[layer._leaflet_id] = layer; 12316 12317 if (s !== 1) { 12318 ctx.save(); 12319 ctx.scale(1, s); 12320 } 12321 12322 ctx.beginPath(); 12323 ctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false); 12324 12325 if (s !== 1) { 12326 ctx.restore(); 12327 } 12328 12329 this._fillStroke(ctx, layer); 12330 }, 12331 12332 _fillStroke: function (ctx, layer) { 12333 var options = layer.options; 12334 12335 if (options.fill) { 12336 ctx.globalAlpha = options.fillOpacity; 12337 ctx.fillStyle = options.fillColor || options.color; 12338 ctx.fill(options.fillRule || 'evenodd'); 12339 } 12340 12341 if (options.stroke && options.weight !== 0) { 12342 if (ctx.setLineDash) { 12343 ctx.setLineDash(layer.options && layer.options._dashArray || []); 12344 } 12345 ctx.globalAlpha = options.opacity; 12346 ctx.lineWidth = options.weight; 12347 ctx.strokeStyle = options.color; 12348 ctx.lineCap = options.lineCap; 12349 ctx.lineJoin = options.lineJoin; 12350 ctx.stroke(); 12351 } 12352 }, 12353 12354 // Canvas obviously doesn't have mouse events for individual drawn objects, 12355 // so we emulate that by calculating what's under the mouse on mousemove/click manually 12356 12357 _onClick: function (e) { 12358 var point = this._map.mouseEventToLayerPoint(e), layer, clickedLayer; 12359 12360 for (var order = this._drawFirst; order; order = order.next) { 12361 layer = order.layer; 12362 if (layer.options.interactive && layer._containsPoint(point) && !this._map._draggableMoved(layer)) { 12363 clickedLayer = layer; 12364 } 12365 } 12366 if (clickedLayer) { 12367 fakeStop(e); 12368 this._fireEvent([clickedLayer], e); 12369 } 12370 }, 12371 12372 _onMouseMove: function (e) { 12373 if (!this._map || this._map.dragging.moving() || this._map._animatingZoom) { return; } 12374 12375 var point = this._map.mouseEventToLayerPoint(e); 12376 this._handleMouseHover(e, point); 12377 }, 12378 12379 12380 _handleMouseOut: function (e) { 12381 var layer = this._hoveredLayer; 12382 if (layer) { 12383 // if we're leaving the layer, fire mouseout 12384 removeClass(this._container, 'leaflet-interactive'); 12385 this._fireEvent([layer], e, 'mouseout'); 12386 this._hoveredLayer = null; 12387 } 12388 }, 12389 12390 _handleMouseHover: function (e, point) { 12391 var layer, candidateHoveredLayer; 12392 12393 for (var order = this._drawFirst; order; order = order.next) { 12394 layer = order.layer; 12395 if (layer.options.interactive && layer._containsPoint(point)) { 12396 candidateHoveredLayer = layer; 12397 } 12398 } 12399 12400 if (candidateHoveredLayer !== this._hoveredLayer) { 12401 this._handleMouseOut(e); 12402 12403 if (candidateHoveredLayer) { 12404 addClass(this._container, 'leaflet-interactive'); // change cursor 12405 this._fireEvent([candidateHoveredLayer], e, 'mouseover'); 12406 this._hoveredLayer = candidateHoveredLayer; 12407 } 12408 } 12409 12410 if (this._hoveredLayer) { 12411 this._fireEvent([this._hoveredLayer], e); 12412 } 12413 }, 12414 12415 _fireEvent: function (layers, e, type) { 12416 this._map._fireDOMEvent(e, type || e.type, layers); 12417 }, 12418 12419 _bringToFront: function (layer) { 12420 var order = layer._order; 12421 var next = order.next; 12422 var prev = order.prev; 12423 12424 if (next) { 12425 next.prev = prev; 12426 } else { 12427 // Already last 12428 return; 12429 } 12430 if (prev) { 12431 prev.next = next; 12432 } else if (next) { 12433 // Update first entry unless this is the 12434 // single entry 12435 this._drawFirst = next; 12436 } 12437 12438 order.prev = this._drawLast; 12439 this._drawLast.next = order; 12440 12441 order.next = null; 12442 this._drawLast = order; 12443 12444 this._requestRedraw(layer); 12445 }, 12446 12447 _bringToBack: function (layer) { 12448 var order = layer._order; 12449 var next = order.next; 12450 var prev = order.prev; 12451 12452 if (prev) { 12453 prev.next = next; 12454 } else { 12455 // Already first 12456 return; 12457 } 12458 if (next) { 12459 next.prev = prev; 12460 } else if (prev) { 12461 // Update last entry unless this is the 12462 // single entry 12463 this._drawLast = prev; 12464 } 12465 12466 order.prev = null; 12467 12468 order.next = this._drawFirst; 12469 this._drawFirst.prev = order; 12470 this._drawFirst = order; 12471 12472 this._requestRedraw(layer); 12473 } 12474}); 12475 12476// @factory L.canvas(options?: Renderer options) 12477// Creates a Canvas renderer with the given options. 12478function canvas$1(options) { 12479 return canvas ? new Canvas(options) : null; 12480} 12481 12482/* 12483 * Thanks to Dmitry Baranovsky and his Raphael library for inspiration! 12484 */ 12485 12486 12487var vmlCreate = (function () { 12488 try { 12489 document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml'); 12490 return function (name) { 12491 return document.createElement('<lvml:' + name + ' class="lvml">'); 12492 }; 12493 } catch (e) { 12494 return function (name) { 12495 return document.createElement('<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">'); 12496 }; 12497 } 12498})(); 12499 12500 12501/* 12502 * @class SVG 12503 * 12504 * Although SVG is not available on IE7 and IE8, these browsers support [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language), and the SVG renderer will fall back to VML in this case. 12505 *
vendor: 27,130 bytes, lines 12506-13536
12506 * VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility 12507 * with old versions of Internet Explorer. 12508 */ 12509 12510// mixin to redefine some SVG methods to handle VML syntax which is similar but with some differences 12511var vmlMixin = { 12512 12513 _initContainer: function () { 12514 this._container = create$1('div', 'leaflet-vml-container'); 12515 }, 12516 12517 _update: function () { 12518 if (this._map._animatingZoom) { return; } 12519 Renderer.prototype._update.call(this); 12520 this.fire('update'); 12521 }, 12522 12523 _initPath: function (layer) { 12524 var container = layer._container = vmlCreate('shape'); 12525 12526 addClass(container, 'leaflet-vml-shape ' + (this.options.className || '')); 12527 12528 container.coordsize = '1 1'; 12529 12530 layer._path = vmlCreate('path'); 12531 container.appendChild(layer._path); 12532 12533 this._updateStyle(layer); 12534 this._layers[stamp(layer)] = layer; 12535 }, 12536 12537 _addPath: function (layer) { 12538 var container = layer._container; 12539 this._container.appendChild(container); 12540 12541 if (layer.options.interactive) { 12542 layer.addInteractiveTarget(container); 12543 } 12544 }, 12545 12546 _removePath: function (layer) { 12547 var container = layer._container; 12548 remove(container); 12549 layer.removeInteractiveTarget(container); 12550 delete this._layers[stamp(layer)]; 12551 }, 12552 12553 _updateStyle: function (layer) { 12554 var stroke = layer._stroke, 12555 fill = layer._fill, 12556 options = layer.options, 12557 container = layer._container; 12558 12559 container.stroked = !!options.stroke; 12560 container.filled = !!options.fill; 12561 12562 if (options.stroke) { 12563 if (!stroke) { 12564 stroke = layer._stroke = vmlCreate('stroke'); 12565 } 12566 container.appendChild(stroke); 12567 stroke.weight = options.weight + 'px'; 12568 stroke.color = options.color; 12569 stroke.opacity = options.opacity; 12570 12571 if (options.dashArray) { 12572 stroke.dashStyle = isArray(options.dashArray) ? 12573 options.dashArray.join(' ') : 12574 options.dashArray.replace(/( *, *)/g, ' '); 12575 } else { 12576 stroke.dashStyle = ''; 12577 } 12578 stroke.endcap = options.lineCap.replace('butt', 'flat'); 12579 stroke.joinstyle = options.lineJoin; 12580 12581 } else if (stroke) { 12582 container.removeChild(stroke); 12583 layer._stroke = null; 12584 } 12585 12586 if (options.fill) { 12587 if (!fill) { 12588 fill = layer._fill = vmlCreate('fill'); 12589 } 12590 container.appendChild(fill); 12591 fill.color = options.fillColor || options.color; 12592 fill.opacity = options.fillOpacity; 12593 12594 } else if (fill) { 12595 container.removeChild(fill); 12596 layer._fill = null; 12597 } 12598 }, 12599 12600 _updateCircle: function (layer) { 12601 var p = layer._point.round(), 12602 r = Math.round(layer._radius), 12603 r2 = Math.round(layer._radiusY || r); 12604 12605 this._setPath(layer, layer._empty() ? 'M0 0' : 12606 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360)); 12607 }, 12608 12609 _setPath: function (layer, path) { 12610 layer._path.v = path; 12611 }, 12612 12613 _bringToFront: function (layer) { 12614 toFront(layer._container); 12615 }, 12616 12617 _bringToBack: function (layer) { 12618 toBack(layer._container); 12619 } 12620}; 12621 12622var create$2 = vml ? vmlCreate : svgCreate; 12623 12624/* 12625 * @class SVG 12626 * @inherits Renderer 12627 * @aka L.SVG 12628 * 12629 * Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG). 12630 * Inherits `Renderer`. 12631 * 12632 * Due to [technical limitations](http://caniuse.com/#search=svg), SVG is not 12633 * available in all web browsers, notably Android 2.x and 3.x. 12634 * 12635 * Although SVG is not available on IE7 and IE8, these browsers support 12636 * [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language) 12637 * (a now deprecated technology), and the SVG renderer will fall back to VML in 12638 * this case. 12639 * 12640 * @example 12641 * 12642 * Use SVG by default for all paths in the map: 12643 * 12644 * ```js 12645 * var map = L.map('map', { 12646 * renderer: L.svg() 12647 * }); 12648 * ``` 12649 * 12650 * Use a SVG renderer with extra padding for specific vector geometries: 12651 * 12652 * ```js 12653 * var map = L.map('map'); 12654 * var myRenderer = L.svg({ padding: 0.5 }); 12655 * var line = L.polyline( coordinates, { renderer: myRenderer } ); 12656 * var circle = L.circle( center, { renderer: myRenderer } ); 12657 * ``` 12658 */ 12659 12660var SVG = Renderer.extend({ 12661 12662 getEvents: function () { 12663 var events = Renderer.prototype.getEvents.call(this); 12664 events.zoomstart = this._onZoomStart; 12665 return events; 12666 }, 12667 12668 _initContainer: function () { 12669 this._container = create$2('svg'); 12670 12671 // makes it possible to click through svg root; we'll reset it back in individual paths 12672 this._container.setAttribute('pointer-events', 'none'); 12673 12674 this._rootGroup = create$2('g'); 12675 this._container.appendChild(this._rootGroup); 12676 }, 12677 12678 _destroyContainer: function () { 12679 remove(this._container); 12680 off(this._container); 12681 delete this._container; 12682 delete this._rootGroup; 12683 delete this._svgSize; 12684 }, 12685 12686 _onZoomStart: function () { 12687 // Drag-then-pinch interactions might mess up the center and zoom. 12688 // In this case, the easiest way to prevent this is re-do the renderer 12689 // bounds and padding when the zooming starts. 12690 this._update(); 12691 }, 12692 12693 _update: function () { 12694 if (this._map._animatingZoom && this._bounds) { return; } 12695 12696 Renderer.prototype._update.call(this); 12697 12698 var b = this._bounds, 12699 size = b.getSize(), 12700 container = this._container; 12701 12702 // set size of svg-container if changed 12703 if (!this._svgSize || !this._svgSize.equals(size)) { 12704 this._svgSize = size; 12705 container.setAttribute('width', size.x); 12706 container.setAttribute('height', size.y); 12707 } 12708 12709 // movement: update container viewBox so that we don't have to change coordinates of individual layers 12710 setPosition(container, b.min); 12711 container.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' ')); 12712 12713 this.fire('update'); 12714 }, 12715 12716 // methods below are called by vector layers implementations 12717 12718 _initPath: function (layer) { 12719 var path = layer._path = create$2('path'); 12720 12721 // @namespace Path 12722 // @option className: String = null 12723 // Custom class name set on an element. Only for SVG renderer. 12724 if (layer.options.className) { 12725 addClass(path, layer.options.className); 12726 } 12727 12728 if (layer.options.interactive) { 12729 addClass(path, 'leaflet-interactive'); 12730 } 12731 12732 this._updateStyle(layer); 12733 this._layers[stamp(layer)] = layer; 12734 }, 12735 12736 _addPath: function (layer) { 12737 if (!this._rootGroup) { this._initContainer(); } 12738 this._rootGroup.appendChild(layer._path); 12739 layer.addInteractiveTarget(layer._path); 12740 }, 12741 12742 _removePath: function (layer) { 12743 remove(layer._path); 12744 layer.removeInteractiveTarget(layer._path); 12745 delete this._layers[stamp(layer)]; 12746 }, 12747 12748 _updatePath: function (layer) { 12749 layer._project(); 12750 layer._update(); 12751 }, 12752 12753 _updateStyle: function (layer) { 12754 var path = layer._path, 12755 options = layer.options; 12756 12757 if (!path) { return; } 12758 12759 if (options.stroke) { 12760 path.setAttribute('stroke', options.color); 12761 path.setAttribute('stroke-opacity', options.opacity); 12762 path.setAttribute('stroke-width', options.weight); 12763 path.setAttribute('stroke-linecap', options.lineCap); 12764 path.setAttribute('stroke-linejoin', options.lineJoin); 12765 12766 if (options.dashArray) { 12767 path.setAttribute('stroke-dasharray', options.dashArray); 12768 } else { 12769 path.removeAttribute('stroke-dasharray'); 12770 } 12771 12772 if (options.dashOffset) { 12773 path.setAttribute('stroke-dashoffset', options.dashOffset); 12774 } else { 12775 path.removeAttribute('stroke-dashoffset'); 12776 } 12777 } else { 12778 path.setAttribute('stroke', 'none'); 12779 } 12780 12781 if (options.fill) { 12782 path.setAttribute('fill', options.fillColor || options.color); 12783 path.setAttribute('fill-opacity', options.fillOpacity); 12784 path.setAttribute('fill-rule', options.fillRule || 'evenodd'); 12785 } else { 12786 path.setAttribute('fill', 'none'); 12787 } 12788 }, 12789 12790 _updatePoly: function (layer, closed) { 12791 this._setPath(layer, pointsToPath(layer._parts, closed)); 12792 }, 12793 12794 _updateCircle: function (layer) { 12795 var p = layer._point, 12796 r = Math.max(Math.round(layer._radius), 1), 12797 r2 = Math.max(Math.round(layer._radiusY), 1) || r, 12798 arc = 'a' + r + ',' + r2 + ' 0 1,0 '; 12799 12800 // drawing a circle with two half-arcs 12801 var d = layer._empty() ? 'M0 0' : 12802 'M' + (p.x - r) + ',' + p.y + 12803 arc + (r * 2) + ',0 ' + 12804 arc + (-r * 2) + ',0 '; 12805 12806 this._setPath(layer, d); 12807 }, 12808 12809 _setPath: function (layer, path) { 12810 layer._path.setAttribute('d', path); 12811 }, 12812 12813 // SVG does not have the concept of zIndex so we resort to changing the DOM order of elements 12814 _bringToFront: function (layer) { 12815 toFront(layer._path); 12816 }, 12817 12818 _bringToBack: function (layer) { 12819 toBack(layer._path); 12820 } 12821}); 12822 12823if (vml) { 12824 SVG.include(vmlMixin); 12825} 12826 12827// @namespace SVG 12828// @factory L.svg(options?: Renderer options) 12829// Creates a SVG renderer with the given options. 12830function svg$1(options) { 12831 return svg || vml ? new SVG(options) : null; 12832} 12833 12834Map.include({ 12835 // @namespace Map; @method getRenderer(layer: Path): Renderer 12836 // Returns the instance of `Renderer` that should be used to render the given 12837 // `Path`. It will ensure that the `renderer` options of the map and paths 12838 // are respected, and that the renderers do exist on the map. 12839 getRenderer: function (layer) { 12840 // @namespace Path; @option renderer: Renderer 12841 // Use this specific instance of `Renderer` for this path. Takes 12842 // precedence over the map's [default renderer](#map-renderer). 12843 var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer; 12844 12845 if (!renderer) { 12846 renderer = this._renderer = this._createRenderer(); 12847 } 12848 12849 if (!this.hasLayer(renderer)) { 12850 this.addLayer(renderer); 12851 } 12852 return renderer; 12853 }, 12854 12855 _getPaneRenderer: function (name) { 12856 if (name === 'overlayPane' || name === undefined) { 12857 return false; 12858 } 12859 12860 var renderer = this._paneRenderers[name]; 12861 if (renderer === undefined) { 12862 renderer = this._createRenderer({pane: name}); 12863 this._paneRenderers[name] = renderer; 12864 } 12865 return renderer; 12866 }, 12867 12868 _createRenderer: function (options) { 12869 // @namespace Map; @option preferCanvas: Boolean = false 12870 // Whether `Path`s should be rendered on a `Canvas` renderer. 12871 // By default, all `Path`s are rendered in a `SVG` renderer. 12872 return (this.options.preferCanvas && canvas$1(options)) || svg$1(options); 12873 } 12874}); 12875 12876/* 12877 * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object. 12878 */ 12879 12880/* 12881 * @class Rectangle 12882 * @aka L.Rectangle 12883 * @inherits Polygon 12884 * 12885 * A class for drawing rectangle overlays on a map. Extends `Polygon`. 12886 * 12887 * @example 12888 * 12889 * ```js 12890 * // define rectangle geographical bounds 12891 * var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]]; 12892 * 12893 * // create an orange rectangle 12894 * L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map); 12895 * 12896 * // zoom the map to the rectangle bounds 12897 * map.fitBounds(bounds); 12898 * ``` 12899 * 12900 */ 12901 12902 12903var Rectangle = Polygon.extend({ 12904 initialize: function (latLngBounds, options) { 12905 Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options); 12906 }, 12907 12908 // @method setBounds(latLngBounds: LatLngBounds): this 12909 // Redraws the rectangle with the passed bounds. 12910 setBounds: function (latLngBounds) { 12911 return this.setLatLngs(this._boundsToLatLngs(latLngBounds)); 12912 }, 12913 12914 _boundsToLatLngs: function (latLngBounds) { 12915 latLngBounds = toLatLngBounds(latLngBounds); 12916 return [ 12917 latLngBounds.getSouthWest(), 12918 latLngBounds.getNorthWest(), 12919 latLngBounds.getNorthEast(), 12920 latLngBounds.getSouthEast() 12921 ]; 12922 } 12923}); 12924 12925 12926// @factory L.rectangle(latLngBounds: LatLngBounds, options?: Polyline options) 12927function rectangle(latLngBounds, options) { 12928 return new Rectangle(latLngBounds, options); 12929} 12930 12931SVG.create = create$2; 12932SVG.pointsToPath = pointsToPath; 12933 12934GeoJSON.geometryToLayer = geometryToLayer; 12935GeoJSON.coordsToLatLng = coordsToLatLng; 12936GeoJSON.coordsToLatLngs = coordsToLatLngs; 12937GeoJSON.latLngToCoords = latLngToCoords; 12938GeoJSON.latLngsToCoords = latLngsToCoords; 12939GeoJSON.getFeature = getFeature; 12940GeoJSON.asFeature = asFeature; 12941 12942/* 12943 * L.Handler.BoxZoom is used to add shift-drag zoom interaction to the map 12944 * (zoom to a selected bounding box), enabled by default. 12945 */ 12946 12947// @namespace Map 12948// @section Interaction Options 12949Map.mergeOptions({ 12950 // @option boxZoom: Boolean = true 12951 // Whether the map can be zoomed to a rectangular area specified by 12952 // dragging the mouse while pressing the shift key. 12953 boxZoom: true 12954}); 12955 12956var BoxZoom = Handler.extend({ 12957 initialize: function (map) { 12958 this._map = map; 12959 this._container = map._container; 12960 this._pane = map._panes.overlayPane; 12961 this._resetStateTimeout = 0; 12962 map.on('unload', this._destroy, this); 12963 }, 12964 12965 addHooks: function () { 12966 on(this._container, 'mousedown', this._onMouseDown, this); 12967 }, 12968 12969 removeHooks: function () { 12970 off(this._container, 'mousedown', this._onMouseDown, this); 12971 }, 12972 12973 moved: function () { 12974 return this._moved; 12975 }, 12976 12977 _destroy: function () { 12978 remove(this._pane); 12979 delete this._pane; 12980 }, 12981 12982 _resetState: function () { 12983 this._resetStateTimeout = 0; 12984 this._moved = false; 12985 }, 12986 12987 _clearDeferredResetState: function () { 12988 if (this._resetStateTimeout !== 0) { 12989 clearTimeout(this._resetStateTimeout); 12990 this._resetStateTimeout = 0; 12991 } 12992 }, 12993 12994 _onMouseDown: function (e) { 12995 if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; } 12996 12997 // Clear the deferred resetState if it hasn't executed yet, otherwise it 12998 // will interrupt the interaction and orphan a box element in the container. 12999 this._clearDeferredResetState(); 13000 this._resetState(); 13001 13002 disableTextSelection(); 13003 disableImageDrag(); 13004 13005 this._startPoint = this._map.mouseEventToContainerPoint(e); 13006 13007 on(document, { 13008 contextmenu: stop, 13009 mousemove: this._onMouseMove, 13010 mouseup: this._onMouseUp, 13011 keydown: this._onKeyDown 13012 }, this); 13013 }, 13014 13015 _onMouseMove: function (e) { 13016 if (!this._moved) { 13017 this._moved = true; 13018 13019 this._box = create$1('div', 'leaflet-zoom-box', this._container); 13020 addClass(this._container, 'leaflet-crosshair'); 13021 13022 this._map.fire('boxzoomstart'); 13023 } 13024 13025 this._point = this._map.mouseEventToContainerPoint(e); 13026 13027 var bounds = new Bounds(this._point, this._startPoint), 13028 size = bounds.getSize(); 13029 13030 setPosition(this._box, bounds.min); 13031 13032 this._box.style.width = size.x + 'px'; 13033 this._box.style.height = size.y + 'px'; 13034 }, 13035 13036 _finish: function () { 13037 if (this._moved) { 13038 remove(this._box); 13039 removeClass(this._container, 'leaflet-crosshair'); 13040 } 13041 13042 enableTextSelection(); 13043 enableImageDrag(); 13044 13045 off(document, { 13046 contextmenu: stop, 13047 mousemove: this._onMouseMove, 13048 mouseup: this._onMouseUp, 13049 keydown: this._onKeyDown 13050 }, this); 13051 }, 13052 13053 _onMouseUp: function (e) { 13054 if ((e.which !== 1) && (e.button !== 1)) { return; } 13055 13056 this._finish(); 13057 13058 if (!this._moved) { return; } 13059 // Postpone to next JS tick so internal click event handling 13060 // still see it as "moved". 13061 this._clearDeferredResetState(); 13062 this._resetStateTimeout = setTimeout(bind(this._resetState, this), 0); 13063 13064 var bounds = new LatLngBounds( 13065 this._map.containerPointToLatLng(this._startPoint), 13066 this._map.containerPointToLatLng(this._point)); 13067 13068 this._map 13069 .fitBounds(bounds) 13070 .fire('boxzoomend', {boxZoomBounds: bounds}); 13071 }, 13072 13073 _onKeyDown: function (e) { 13074 if (e.keyCode === 27) { 13075 this._finish(); 13076 } 13077 } 13078}); 13079 13080// @section Handlers 13081// @property boxZoom: Handler 13082// Box (shift-drag with mouse) zoom handler. 13083Map.addInitHook('addHandler', 'boxZoom', BoxZoom); 13084 13085/* 13086 * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default. 13087 */ 13088 13089// @namespace Map 13090// @section Interaction Options 13091 13092Map.mergeOptions({ 13093 // @option doubleClickZoom: Boolean|String = true 13094 // Whether the map can be zoomed in by double clicking on it and 13095 // zoomed out by double clicking while holding shift. If passed 13096 // `'center'`, double-click zoom will zoom to the center of the 13097 // view regardless of where the mouse was. 13098 doubleClickZoom: true 13099}); 13100 13101var DoubleClickZoom = Handler.extend({ 13102 addHooks: function () { 13103 this._map.on('dblclick', this._onDoubleClick, this); 13104 }, 13105 13106 removeHooks: function () { 13107 this._map.off('dblclick', this._onDoubleClick, this); 13108 }, 13109 13110 _onDoubleClick: function (e) { 13111 var map = this._map, 13112 oldZoom = map.getZoom(), 13113 delta = map.options.zoomDelta, 13114 zoom = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta; 13115 13116 if (map.options.doubleClickZoom === 'center') { 13117 map.setZoom(zoom); 13118 } else { 13119 map.setZoomAround(e.containerPoint, zoom); 13120 } 13121 } 13122}); 13123 13124// @section Handlers 13125// 13126// Map properties include interaction handlers that allow you to control 13127// interaction behavior in runtime, enabling or disabling certain features such 13128// as dragging or touch zoom (see `Handler` methods). For example: 13129// 13130// ```js 13131// map.doubleClickZoom.disable(); 13132// ``` 13133// 13134// @property doubleClickZoom: Handler 13135// Double click zoom handler. 13136Map.addInitHook('addHandler', 'doubleClickZoom', DoubleClickZoom); 13137 13138/* 13139 * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default. 13140 */ 13141 13142// @namespace Map 13143// @section Interaction Options 13144Map.mergeOptions({ 13145 // @option dragging: Boolean = true 13146 // Whether the map be draggable with mouse/touch or not. 13147 dragging: true, 13148 13149 // @section Panning Inertia Options 13150 // @option inertia: Boolean = * 13151 // If enabled, panning of the map will have an inertia effect where 13152 // the map builds momentum while dragging and continues moving in 13153 // the same direction for some time. Feels especially nice on touch 13154 // devices. Enabled by default unless running on old Android devices. 13155 inertia: !android23, 13156 13157 // @option inertiaDeceleration: Number = 3000 13158 // The rate with which the inertial movement slows down, in pixels/second². 13159 inertiaDeceleration: 3400, // px/s^2 13160 13161 // @option inertiaMaxSpeed: Number = Infinity 13162 // Max speed of the inertial movement, in pixels/second. 13163 inertiaMaxSpeed: Infinity, // px/s 13164 13165 // @option easeLinearity: Number = 0.2 13166 easeLinearity: 0.2, 13167 13168 // TODO refactor, move to CRS 13169 // @option worldCopyJump: Boolean = false 13170 // With this option enabled, the map tracks when you pan to another "copy" 13171 // of the world and seamlessly jumps to the original one so that all overlays 13172 // like markers and vector layers are still visible. 13173 worldCopyJump: false, 13174 13175 // @option maxBoundsViscosity: Number = 0.0 13176 // If `maxBounds` is set, this option will control how solid the bounds 13177 // are when dragging the map around. The default value of `0.0` allows the 13178 // user to drag outside the bounds at normal speed, higher values will 13179 // slow down map dragging outside bounds, and `1.0` makes the bounds fully 13180 // solid, preventing the user from dragging outside the bounds. 13181 maxBoundsViscosity: 0.0 13182}); 13183 13184var Drag = Handler.extend({ 13185 addHooks: function () { 13186 if (!this._draggable) { 13187 var map = this._map; 13188 13189 this._draggable = new Draggable(map._mapPane, map._container); 13190 13191 this._draggable.on({ 13192 dragstart: this._onDragStart, 13193 drag: this._onDrag, 13194 dragend: this._onDragEnd 13195 }, this); 13196 13197 this._draggable.on('predrag', this._onPreDragLimit, this); 13198 if (map.options.worldCopyJump) { 13199 this._draggable.on('predrag', this._onPreDragWrap, this); 13200 map.on('zoomend', this._onZoomEnd, this); 13201 13202 map.whenReady(this._onZoomEnd, this); 13203 } 13204 } 13205 addClass(this._map._container, 'leaflet-grab leaflet-touch-drag'); 13206 this._draggable.enable(); 13207 this._positions = []; 13208 this._times = []; 13209 }, 13210 13211 removeHooks: function () { 13212 removeClass(this._map._container, 'leaflet-grab'); 13213 removeClass(this._map._container, 'leaflet-touch-drag'); 13214 this._draggable.disable(); 13215 }, 13216 13217 moved: function () { 13218 return this._draggable && this._draggable._moved; 13219 }, 13220 13221 moving: function () { 13222 return this._draggable && this._draggable._moving; 13223 }, 13224 13225 _onDragStart: function () { 13226 var map = this._map; 13227 13228 map._stop(); 13229 if (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) { 13230 var bounds = toLatLngBounds(this._map.options.maxBounds); 13231 13232 this._offsetLimit = toBounds( 13233 this._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1), 13234 this._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1) 13235 .add(this._map.getSize())); 13236 13237 this._viscosity = Math.min(1.0, Math.max(0.0, this._map.options.maxBoundsViscosity)); 13238 } else { 13239 this._offsetLimit = null; 13240 } 13241 13242 map 13243 .fire('movestart') 13244 .fire('dragstart'); 13245 13246 if (map.options.inertia) { 13247 this._positions = []; 13248 this._times = []; 13249 } 13250 }, 13251 13252 _onDrag: function (e) { 13253 if (this._map.options.inertia) { 13254 var time = this._lastTime = +new Date(), 13255 pos = this._lastPos = this._draggable._absPos || this._draggable._newPos; 13256 13257 this._positions.push(pos); 13258 this._times.push(time); 13259 13260 this._prunePositions(time); 13261 } 13262 13263 this._map 13264 .fire('move', e) 13265 .fire('drag', e); 13266 }, 13267 13268 _prunePositions: function (time) { 13269 while (this._positions.length > 1 && time - this._times[0] > 50) { 13270 this._positions.shift(); 13271 this._times.shift(); 13272 } 13273 }, 13274 13275 _onZoomEnd: function () { 13276 var pxCenter = this._map.getSize().divideBy(2), 13277 pxWorldCenter = this._map.latLngToLayerPoint([0, 0]); 13278 13279 this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x; 13280 this._worldWidth = this._map.getPixelWorldBounds().getSize().x; 13281 }, 13282 13283 _viscousLimit: function (value, threshold) { 13284 return value - (value - threshold) * this._viscosity; 13285 }, 13286 13287 _onPreDragLimit: function () { 13288 if (!this._viscosity || !this._offsetLimit) { return; } 13289 13290 var offset = this._draggable._newPos.subtract(this._draggable._startPos); 13291 13292 var limit = this._offsetLimit; 13293 if (offset.x < limit.min.x) { offset.x = this._viscousLimit(offset.x, limit.min.x); } 13294 if (offset.y < limit.min.y) { offset.y = this._viscousLimit(offset.y, limit.min.y); } 13295 if (offset.x > limit.max.x) { offset.x = this._viscousLimit(offset.x, limit.max.x); } 13296 if (offset.y > limit.max.y) { offset.y = this._viscousLimit(offset.y, limit.max.y); } 13297 13298 this._draggable._newPos = this._draggable._startPos.add(offset); 13299 }, 13300 13301 _onPreDragWrap: function () { 13302 // TODO refactor to be able to adjust map pane position after zoom 13303 var worldWidth = this._worldWidth, 13304 halfWidth = Math.round(worldWidth / 2), 13305 dx = this._initialWorldOffset, 13306 x = this._draggable._newPos.x, 13307 newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, 13308 newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, 13309 newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2; 13310 13311 this._draggable._absPos = this._draggable._newPos.clone(); 13312 this._draggable._newPos.x = newX; 13313 }, 13314 13315 _onDragEnd: function (e) { 13316 var map = this._map, 13317 options = map.options, 13318 13319 noInertia = !options.inertia || this._times.length < 2; 13320 13321 map.fire('dragend', e); 13322 13323 if (noInertia) { 13324 map.fire('moveend'); 13325 13326 } else { 13327 this._prunePositions(+new Date()); 13328 13329 var direction = this._lastPos.subtract(this._positions[0]), 13330 duration = (this._lastTime - this._times[0]) / 1000, 13331 ease = options.easeLinearity, 13332 13333 speedVector = direction.multiplyBy(ease / duration), 13334 speed = speedVector.distanceTo([0, 0]), 13335 13336 limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), 13337 limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), 13338 13339 decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease), 13340 offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round(); 13341 13342 if (!offset.x && !offset.y) { 13343 map.fire('moveend'); 13344 13345 } else { 13346 offset = map._limitOffset(offset, map.options.maxBounds); 13347 13348 requestAnimFrame(function () { 13349 map.panBy(offset, { 13350 duration: decelerationDuration, 13351 easeLinearity: ease, 13352 noMoveStart: true, 13353 animate: true 13354 }); 13355 }); 13356 } 13357 } 13358 } 13359}); 13360 13361// @section Handlers 13362// @property dragging: Handler 13363// Map dragging handler (by both mouse and touch). 13364Map.addInitHook('addHandler', 'dragging', Drag); 13365 13366/* 13367 * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default. 13368 */ 13369 13370// @namespace Map 13371// @section Keyboard Navigation Options 13372Map.mergeOptions({ 13373 // @option keyboard: Boolean = true 13374 // Makes the map focusable and allows users to navigate the map with keyboard 13375 // arrows and `+`/`-` keys. 13376 keyboard: true, 13377 13378 // @option keyboardPanDelta: Number = 80 13379 // Amount of pixels to pan when pressing an arrow key. 13380 keyboardPanDelta: 80 13381}); 13382 13383var Keyboard = Handler.extend({ 13384 13385 keyCodes: { 13386 left: [37], 13387 right: [39], 13388 down: [40], 13389 up: [38], 13390 zoomIn: [187, 107, 61, 171], 13391 zoomOut: [189, 109, 54, 173] 13392 }, 13393 13394 initialize: function (map) { 13395 this._map = map; 13396 13397 this._setPanDelta(map.options.keyboardPanDelta); 13398 this._setZoomDelta(map.options.zoomDelta); 13399 }, 13400 13401 addHooks: function () { 13402 var container = this._map._container; 13403 13404 // make the container focusable by tabbing 13405 if (container.tabIndex <= 0) { 13406 container.tabIndex = '0'; 13407 } 13408 13409 on(container, { 13410 focus: this._onFocus, 13411 blur: this._onBlur, 13412 mousedown: this._onMouseDown 13413 }, this); 13414 13415 this._map.on({ 13416 focus: this._addHooks, 13417 blur: this._removeHooks 13418 }, this); 13419 }, 13420 13421 removeHooks: function () { 13422 this._removeHooks(); 13423 13424 off(this._map._container, { 13425 focus: this._onFocus, 13426 blur: this._onBlur, 13427 mousedown: this._onMouseDown 13428 }, this); 13429 13430 this._map.off({ 13431 focus: this._addHooks, 13432 blur: this._removeHooks 13433 }, this); 13434 }, 13435 13436 _onMouseDown: function () { 13437 if (this._focused) { return; } 13438 13439 var body = document.body, 13440 docEl = document.documentElement, 13441 top = body.scrollTop || docEl.scrollTop, 13442 left = body.scrollLeft || docEl.scrollLeft; 13443 13444 this._map._container.focus(); 13445 13446 window.scrollTo(left, top); 13447 }, 13448 13449 _onFocus: function () { 13450 this._focused = true; 13451 this._map.fire('focus'); 13452 }, 13453 13454 _onBlur: function () { 13455 this._focused = false; 13456 this._map.fire('blur'); 13457 }, 13458 13459 _setPanDelta: function (panDelta) { 13460 var keys = this._panKeys = {}, 13461 codes = this.keyCodes, 13462 i, len; 13463 13464 for (i = 0, len = codes.left.length; i < len; i++) { 13465 keys[codes.left[i]] = [-1 * panDelta, 0]; 13466 } 13467 for (i = 0, len = codes.right.length; i < len; i++) { 13468 keys[codes.right[i]] = [panDelta, 0]; 13469 } 13470 for (i = 0, len = codes.down.length; i < len; i++) { 13471 keys[codes.down[i]] = [0, panDelta]; 13472 } 13473 for (i = 0, len = codes.up.length; i < len; i++) { 13474 keys[codes.up[i]] = [0, -1 * panDelta]; 13475 } 13476 }, 13477 13478 _setZoomDelta: function (zoomDelta) { 13479 var keys = this._zoomKeys = {}, 13480 codes = this.keyCodes, 13481 i, len; 13482 13483 for (i = 0, len = codes.zoomIn.length; i < len; i++) { 13484 keys[codes.zoomIn[i]] = zoomDelta; 13485 } 13486 for (i = 0, len = codes.zoomOut.length; i < len; i++) { 13487 keys[codes.zoomOut[i]] = -zoomDelta; 13488 } 13489 }, 13490 13491 _addHooks: function () { 13492 on(document, 'keydown', this._onKeyDown, this); 13493 }, 13494 13495 _removeHooks: function () { 13496 off(document, 'keydown', this._onKeyDown, this); 13497 }, 13498 13499 _onKeyDown: function (e) { 13500 if (e.altKey || e.ctrlKey || e.metaKey) { return; } 13501 13502 var key = e.keyCode, 13503 map = this._map, 13504 offset; 13505 13506 if (key in this._panKeys) { 13507 if (!map._panAnim || !map._panAnim._inProgress) { 13508 offset = this._panKeys[key]; 13509 if (e.shiftKey) { 13510 offset = toPoint(offset).multiplyBy(3); 13511 } 13512 13513 map.panBy(offset); 13514 13515 if (map.options.maxBounds) { 13516 map.panInsideBounds(map.options.maxBounds); 13517 } 13518 } 13519 } else if (key in this._zoomKeys) { 13520 map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]); 13521 13522 } else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) { 13523 map.closePopup(); 13524 13525 } else { 13526 return; 13527 } 13528 13529 stop(e); 13530 } 13531}); 13532 13533// @section Handlers 13534// @section Handlers 13535// @property keyboard: Handler 13536// Keyboard navigation handler.
13537Map.addInitHook('addHandler', 'keyboard', Keyboard); 13538 13539/* 13540 * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map. 13541 */ 13542 13543// @namespace Map 13544// @section Interaction Options 13545Map.mergeOptions({ 13546 // @section Mousewheel options 13547 // @option scrollWheelZoom: Boolean|String = true 13548 // Whether the map can be zoomed by using the mouse wheel. If passed `'center'`, 13549 // it will zoom to the center of the view regardless of where the mouse was. 13550 scrollWheelZoom: true, 13551 13552 // @option wheelDebounceTime: Number = 40 13553 // Limits the rate at which a wheel can fire (in milliseconds). By default 13554 // user can't zoom via wheel more often than once per 40 ms. 13555 wheelDebounceTime: 40, 13556 13557 // @option wheelPxPerZoomLevel: Number = 60 13558 // How many scroll pixels (as reported by [L.DomEvent.getWheelDelta](#domevent-getwheeldelta)) 13559 // mean a change of one full zoom level. Smaller values will make wheel-zooming 13560 // faster (and vice versa). 13561 wheelPxPerZoomLevel: 60 13562}); 13563 13564var ScrollWheelZoom = Handler.extend({ 13565 addHooks: function () { 13566 on(this._map._container, 'mousewheel', this._onWheelScroll, this); 13567 13568 this._delta = 0; 13569 }, 13570 13571 removeHooks: function () { 13572 off(this._map._container, 'mousewheel', this._onWheelScroll, this); 13573 }, 13574 13575 _onWheelScroll: function (e) { 13576 var delta = getWheelDelta(e); 13577 13578 var debounce = this._map.options.wheelDebounceTime; 13579 13580 this._delta += delta; 13581 this._lastMousePos = this._map.mouseEventToContainerPoint(e); 13582 13583 if (!this._startTime) { 13584 this._startTime = +new Date(); 13585 } 13586 13587 var left = Math.max(debounce - (+new Date() - this._startTime), 0); 13588 13589 clearTimeout(this._timer); 13590 this._timer = setTimeout(bind(this._performZoom, this), left); 13591 13592 stop(e); 13593 }, 13594 13595 _performZoom: function () { 13596 var map = this._map, 13597 zoom = map.getZoom(), 13598 snap = this._map.options.zoomSnap || 0; 13599 13600 map._stop(); // stop panning and fly animations if any 13601 13602 // map the delta with a sigmoid function to -4..4 range leaning on -1..1 13603 var d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4), 13604 d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2, 13605 d4 = snap ? Math.ceil(d3 / snap) * snap : d3, 13606 delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom; 13607 13608 this._delta = 0; 13609 this._startTime = null; 13610 13611 if (!delta) { return; } 13612 13613 if (map.options.scrollWheelZoom === 'center') { 13614 map.setZoom(zoom + delta); 13615 } else { 13616 map.setZoomAround(this._lastMousePos, zoom + delta); 13617 } 13618 } 13619}); 13620 13621// @section Handlers 13622// @property scrollWheelZoom: Handler 13623// Scroll wheel zoom handler. 13624Map.addInitHook('addHandler', 'scrollWheelZoom', ScrollWheelZoom); 13625 13626/* 13627 * L.Map.Tap is used to enable mobile hacks like quick taps and long hold. 13628 */ 13629 13630// @namespace Map 13631// @section Interaction Options 13632Map.mergeOptions({ 13633 // @section Touch interaction options 13634 // @option tap: Boolean = true 13635 // Enables mobile hacks for supporting instant taps (fixing 200ms click 13636 // delay on iOS/Android) and touch holds (fired as `contextmenu` events). 13637 tap: true, 13638 13639 // @option tapTolerance: Number = 15 13640 // The max number of pixels a user can shift his finger during touch 13641 // for it to be considered a valid tap. 13642 tapTolerance: 15 13643}); 13644 13645var Tap = Handler.extend({ 13646 addHooks: function () { 13647 on(this._map._container, 'touchstart', this._onDown, this); 13648 }, 13649 13650 removeHooks: function () { 13651 off(this._map._container, 'touchstart', this._onDown, this); 13652 }, 13653 13654 _onDown: function (e) { 13655 if (!e.touches) { return; } 13656 13657 preventDefault(e); 13658 13659 this._fireClick = true; 13660 13661 // don't simulate click or track longpress if more than 1 touch 13662 if (e.touches.length > 1) { 13663 this._fireClick = false; 13664 clearTimeout(this._holdTimeout); 13665 return; 13666 } 13667 13668 var first = e.touches[0], 13669 el = first.target; 13670 13671 this._startPos = this._newPos = new Point(first.clientX, first.clientY); 13672 13673 // if touching a link, highlight it 13674 if (el.tagName && el.tagName.toLowerCase() === 'a') { 13675 addClass(el, 'leaflet-active'); 13676 } 13677 13678 // simulate long hold but setting a timeout 13679 this._holdTimeout = setTimeout(bind(function () { 13680 if (this._isTapValid()) { 13681 this._fireClick = false; 13682 this._onUp(); 13683 this._simulateEvent('contextmenu', first); 13684 } 13685 }, this), 1000); 13686 13687 this._simulateEvent('mousedown', first); 13688 13689 on(document, { 13690 touchmove: this._onMove, 13691 touchend: this._onUp 13692 }, this); 13693 }, 13694 13695 _onUp: function (e) { 13696 clearTimeout(this._holdTimeout); 13697 13698 off(document, { 13699 touchmove: this._onMove, 13700 touchend: this._onUp 13701 }, this); 13702 13703 if (this._fireClick && e && e.changedTouches) { 13704 13705 var first = e.changedTouches[0], 13706 el = first.target; 13707 13708 if (el && el.tagName && el.tagName.toLowerCase() === 'a') { 13709 removeClass(el, 'leaflet-active'); 13710 } 13711 13712 this._simulateEvent('mouseup', first); 13713 13714 // simulate click if the touch didn't move too much 13715 if (this._isTapValid()) { 13716 this._simulateEvent('click', first); 13717 } 13718 } 13719 }, 13720 13721 _isTapValid: function () { 13722 return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance; 13723 }, 13724 13725 _onMove: function (e) { 13726 var first = e.touches[0]; 13727 this._newPos = new Point(first.clientX, first.clientY); 13728 this._simulateEvent('mousemove', first); 13729 }, 13730 13731 _simulateEvent: function (type, e) { 13732 var simulatedEvent = document.createEvent('MouseEvents'); 13733 13734 simulatedEvent._simulated = true; 13735 e.target._simulatedClick = true; 13736 13737 simulatedEvent.initMouseEvent( 13738 type, true, true, window, 1, 13739 e.screenX, e.screenY, 13740 e.clientX, e.clientY, 13741 false, false, false, false, 0, null); 13742 13743 e.target.dispatchEvent(simulatedEvent); 13744 } 13745}); 13746 13747// @section Handlers 13748// @property tap: Handler 13749// Mobile touch hacks (quick tap and touch hold) handler. 13750if (touch && !pointer) { 13751 Map.addInitHook('addHandler', 'tap', Tap); 13752} 13753 13754/* 13755 * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supp
vendor: 4,276 bytes, lines 13755-13895
13755orted mobile browsers. 13756 */ 13757 13758// @namespace Map 13759// @section Interaction Options 13760Map.mergeOptions({ 13761 // @section Touch interaction options 13762 // @option touchZoom: Boolean|String = * 13763 // Whether the map can be zoomed by touch-dragging with two fingers. If 13764 // passed `'center'`, it will zoom to the center of the view regardless of 13765 // where the touch events (fingers) were. Enabled for touch-capable web 13766 // browsers except for old Androids. 13767 touchZoom: touch && !android23, 13768 13769 // @option bounceAtZoomLimits: Boolean = true 13770 // Set it to false if you don't want the map to zoom beyond min/max zoom 13771 // and then bounce back when pinch-zooming. 13772 bounceAtZoomLimits: true 13773}); 13774 13775var TouchZoom = Handler.extend({ 13776 addHooks: function () { 13777 addClass(this._map._container, 'leaflet-touch-zoom'); 13778 on(this._map._container, 'touchstart', this._onTouchStart, this); 13779 }, 13780 13781 removeHooks: function () { 13782 removeClass(this._map._container, 'leaflet-touch-zoom'); 13783 off(this._map._container, 'touchstart', this._onTouchStart, this); 13784 }, 13785 13786 _onTouchStart: function (e) { 13787 var map = this._map; 13788 if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; } 13789 13790 var p1 = map.mouseEventToContainerPoint(e.touches[0]), 13791 p2 = map.mouseEventToContainerPoint(e.touches[1]); 13792 13793 this._centerPoint = map.getSize()._divideBy(2); 13794 this._startLatLng = map.containerPointToLatLng(this._centerPoint); 13795 if (map.options.touchZoom !== 'center') { 13796 this._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2)); 13797 } 13798 13799 this._startDist = p1.distanceTo(p2); 13800 this._startZoom = map.getZoom(); 13801 13802 this._moved = false; 13803 this._zooming = true; 13804 13805 map._stop(); 13806 13807 on(document, 'touchmove', this._onTouchMove, this); 13808 on(document, 'touchend', this._onTouchEnd, this); 13809 13810 preventDefault(e); 13811 }, 13812 13813 _onTouchMove: function (e) { 13814 if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; } 13815 13816 var map = this._map, 13817 p1 = map.mouseEventToContainerPoint(e.touches[0]), 13818 p2 = map.mouseEventToContainerPoint(e.touches[1]), 13819 scale = p1.distanceTo(p2) / this._startDist; 13820 13821 this._zoom = map.getScaleZoom(scale, this._startZoom); 13822 13823 if (!map.options.bounceAtZoomLimits && ( 13824 (this._zoom < map.getMinZoom() && scale < 1) || 13825 (this._zoom > map.getMaxZoom() && scale > 1))) { 13826 this._zoom = map._limitZoom(this._zoom); 13827 } 13828 13829 if (map.options.touchZoom === 'center') { 13830 this._center = this._startLatLng; 13831 if (scale === 1) { return; } 13832 } else { 13833 // Get delta from pinch to center, so centerLatLng is delta applied to initial pinchLatLng 13834 var delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint); 13835 if (scale === 1 && delta.x === 0 && delta.y === 0) { return; } 13836 this._center = map.unproject(map.project(this._pinchStartLatLng, this._zoom).subtract(delta), this._zoom); 13837 } 13838 13839 if (!this._moved) { 13840 map._moveStart(true, false); 13841 this._moved = true; 13842 } 13843 13844 cancelAnimFrame(this._animRequest); 13845 13846 var moveFn = bind(map._move, map, this._center, this._zoom, {pinch: true, round: false}); 13847 this._animRequest = requestAnimFrame(moveFn, this, true); 13848 13849 preventDefault(e); 13850 }, 13851 13852 _onTouchEnd: function () { 13853 if (!this._moved || !this._zooming) { 13854 this._zooming = false; 13855 return; 13856 } 13857 13858 this._zooming = false; 13859 cancelAnimFrame(this._animRequest); 13860 13861 off(document, 'touchmove', this._onTouchMove); 13862 off(document, 'touchend', this._onTouchEnd); 13863 13864 // Pinch updates GridLayers' levels only when zoomSnap is off, so zoomSnap becomes noUpdate. 13865 if (this._map.options.zoomAnimation) { 13866 this._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap); 13867 } else { 13868 this._map._resetView(this._center, this._map._limitZoom(this._zoom)); 13869 } 13870 } 13871}); 13872 13873// @section Handlers 13874// @property touchZoom: Handler 13875// Touch zoom handler. 13876Map.addInitHook('addHandler', 'touchZoom', TouchZoom); 13877 13878Map.BoxZoom = BoxZoom; 13879Map.DoubleClickZoom = DoubleClickZoom; 13880Map.Drag = Drag; 13881Map.Keyboard = Keyboard; 13882Map.ScrollWheelZoom = ScrollWheelZoom; 13883Map.Tap = Tap; 13884Map.TouchZoom = TouchZoom; 13885 13886Object.freeze = freeze; 13887 13888exports.version = version; 13889exports.Control = Control; 13890exports.control = control; 13891exports.Browser = Browser; 13892exports.Evented = Evented; 13893exports.Mixin = Mixin; 13894exports.Util = Util; 13895exports.Class = Class;
13896exports.Handler = Handler; 13897exports.extend = extend; 13898exports.bind = bind; 13899exports.stamp = stamp; 13900exports.setOptions = setOptions; 13901exports.DomEvent = DomEvent; 13902exports.DomUtil = DomUtil; 13903exports.PosAnimation = PosAnimation; 13904exports.Draggable = Draggable; 13905exports.LineUtil = LineUtil; 13906exports.PolyUtil = PolyUtil; 13907exports.Point = Point; 13908exports.point = toPoint; 13909exports.Bounds = Bounds; 13910exports.bounds = toBounds; 13911exports.Transformation = Transformation; 13912exports.transformation = toTransformation; 13913exports.Projection = index; 13914exports.LatLng = LatLng; 13915exports.latLng = toLatLng; 13916exports.LatLngBounds = LatLngBounds; 13917exports.latLngBounds = toLatLngBounds; 13918exports.CRS = CRS; 13919exports.GeoJSON = GeoJSON; 13920exports.geoJSON = geoJSON; 13921exports.geoJson = geoJson; 13922exports.Layer = Layer; 13923exports.LayerGroup = LayerGroup; 13924exports.layerGroup = layerGroup; 13925exports.FeatureGroup = FeatureGroup; 13926exports.featureGroup = featureGroup; 13927exports.ImageOverlay = ImageOverlay; 13928exports.imageOverlay = imageOverlay; 13929exports.VideoOverlay = VideoOverlay; 13930exports.videoOverlay = videoOverlay; 13931exports.DivOverlay = DivOverlay; 13932exports.Popup = Popup; 13933exports.popup = popup; 13934exports.Tooltip = Tooltip; 13935exports.tooltip = tooltip; 13936exports.Icon = Icon; 13937exports.icon = icon; 13938exports.DivIcon = DivIcon; 13939exports.divIcon = divIcon; 13940exports.Marker = Marker; 13941exports.marker = marker; 13942exports.TileLayer = TileLayer; 13943exports.tileLayer = tileLayer; 13944exports.GridLayer = GridLayer; 13945exports.gridLayer = gridLayer; 13946exports.SVG = SVG; 13947exports.svg = svg$1; 13948exports.Renderer = Renderer; 13949exports.Canvas = Canvas; 13950exports.canvas = canvas$1; 13951exports.Path = Path; 13952exports.CircleMarker = CircleMarker; 13953exports.circleMarker = circleMarker; 13954exports.Circle = Circle; 13955exports.circle = circle; 13956exports.Polyline = Polyline; 13957exports.polyline = polyline; 13958exports.Polygon = Polygon; 13959exports.polygon = polygon; 13960exports.Rectangle = Rectangle; 13961exports.rectangle = rectangle; 13962exports.Map = Map; 13963exports.map = createMap; 13964 13965var oldL = window.L; 13966exports.noConflict = function() { 13967 window.L = oldL; 13968 return this; 13969} 13970 13971// Always export us to window global (see #2364) 13972window.L = exports; 13973 13974}))); 13975//# sourceMappingURL=leaflet-src.js.map 13976 13977!function(r){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=r();else if("function"==typeof define&&define.amd)define([],r);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.omnivore=r()}}(function(){var r;return function r(e,t,n){function o(u,a){if(!t[u]){if(!e[u]){var s="function"==typeof require&&require;if(!a&&s)return s(u,!0);if(i)return i(u,!0);var f=new Error("Cannot find module '"+u+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[u]={exports:{}};e[u][0].call(c.exports,function(r){var t=e[u][1][r];return o(t?t:r)},c,c.exports,r,e,t,n)}return t[u].exports}for(var i="function"==typeof require&&require,u=0;u<n.length;u++)o(n[u]);return o}({1:[function(r,e,t){function n(r,e){"setGeoJSON"in r?r.setGeoJSON(e):"addData"in r&&r.addData(e)}function o(r,e,t){var o=t||L.geoJson();return y(r,function(r,e){return r?o.fire("error",{error:r}):(n(o,JSON.parse(e.responseText)),void o.fire("ready"))}),o}function i(r,e,t){function n(r,t){return r?o.fire("error",{error:r}):(l(t.responseText,e,o),void o.fire("ready"))}var o=t||L.geoJson();return y(r,n),o}function u(r,e,t){function n(r,t){function n(){i=!0}var i;return r?o.fire("error",{error:r}):(o.on("error",n),p(t.responseText,e,o),o.off("error",n),void(i||o.fire("ready")))}var o=t||L.geoJson();return y(r,n),o}function a(r,e,t){function n(r,t){function n(){i=!0}var i;return r?o.fire("error",{error:r}):(o.on("error",n),h(t.responseXML||t.responseText,e,o),o.off("error",n),void(i||o.fire("ready")))}var o=t||L.geoJson();return y(r,n),o}function s(r,e,t){function n(r,t){function n(){i=!0}var i;return r?o.fire("error",{error:r}):(o.on("error",n),g(t.responseXML||t.responseText,e,o),o.off("error",n),void(i||o.fire("ready")))}var o=t||L.geoJson();return y(r,n),o}function f(r,e,t){function n(r,t){return r?o.fire("error",{error:r}):(v(t.responseText,e,o),void o.fire("ready"))}var o=t||L.geoJson();return y(r,n),o}function c(r,e,t){function n(r,t){return r?o.fire("error",{error:r}):(d(t.responseText,e,o),void o.fire("ready"))}var o=t||L.geoJson();return y(r,n),o}function l(r,e,t){var o="string"==typeof r?JSON.parse(r):r;t=t||L.geoJson();for(var i in o.objects){var u=S.feature(o,o.objects[i]);u.features?n(t,u.features):n(t,u)}return t}function p(r,e,t){function o(r,e){return r?t.fire("error",{error:r}):void n(t,e)}return t=t||L.geoJson(),e=e||{},x.csv2geojson(r,e,o),t}function h(r,e,t){var o=m(r);
13977if(!o)return t.fire("error",{error:"Could not parse GPX"});t=t||L.geoJson();var i=T.gpx(o);return n(t,i),t}function g(r,e,t){var o=m(r);if(!o)return t.fire("error",{error:"Could not parse KML"});t=t||L.geoJson();var i=T.kml(o);return n(t,i),t}function d(r,e,t){t=t||L.geoJson(),e=e||{};for(var o=E.decode(r,e.precision),i={type:"LineString",coordinates:[]},u=0;u<o.length;u++)i.coordinates[u]=[o[u][1],o[u][0]];return n(t,i),t}function v(r,e,t){t=t||L.geoJson();var o=w(r);return n(t,o),t}function m(r){return"string"==typeof r?(new DOMParser).parseFromString(r,"text/xml"):r}var y=r("corslite"),x=r("csv2geojson"),w=r("wellknown"),E=r("polyline"),S=r("topojson"),T=r("togeojson");e.exports.polyline=c,e.exports.polyline.parse=d,e.exports.geojson=o,e.exports.topojson=i,e.exports.topojson.parse=l,e.exports.csv=u,e.exports.csv.parse=p,e.exports.gpx=a,e.exports.gpx.parse=h,e.exports.kml=s,e.exports.kml.parse=g,e.exports.wkt=f,e.exports.wkt.parse=v},{corslite:4,csv2geojson:5,polyline:8,togeojson:9,topojson:10,wellknown:11}],2:[function(r,e,t){},{}],3:[function(r,e,t){function n(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function i(r){if(l===setTimeout)return setTimeout(r,0);if((l===n||!l)&&setTimeout)return l=setTimeout,setTimeout(r,0);try{return l(r,0)}catch(e){try{return l.call(null,r,0)}catch(e){return l.call(this,r,0)}}}function u(r){if(p===clearTimeout)return clearTimeout(r);if((p===o||!p)&&clearTimeout)return p=clearTimeout,clearTimeout(r);try{return p(r)}catch(e){try{return p.call(null,r)}catch(e){return p.call(this,r)}}}function a(){v&&g&&(v=!1,g.length?d=g.concat(d):m=-1,d.length&&s())}function s(){if(!v){var r=i(a);v=!0;for(var e=d.length;e;){for(g=d,d=[];++m<e;)g&&g[m].run();m=-1,e=d.length}g=null,v=!1,u(r)}}function f(r,e){this.fun=r,this.array=e}function c(){}var l,p,h=e.exports={};!function(){try{l="function"==typeof setTimeout?setTimeout:n}catch(r){l=n}try{p="function"==typeof clearTimeout?clearTimeout:o}catch(r){p=o}}();var g,d=[],v=!1,m=-1;h.nextTick=function(r){var e=new Array(arguments.length-1);if(arguments.length>1)for(var t=1;t<arguments.length;t++)e[t-1]=arguments[t];d.push(new f(r,e)),1!==d.length||v||i(s)},f.prototype.run=function(){this.fun.apply(null,this.array)},h.title="browser",h.browser=!0,h.env={},h.argv=[],h.version="",h.versions={},h.on=c,h.addListener=c,h.once=c,h.off=c,h.removeListener=c,h.removeAllListeners=c,h.emit=c,h.binding=function(r){throw new Error("process.binding is not supported")},h.cwd=function(){return"/"},h.chdir=function(r){throw new Error("process.chdir is not supported")},h.umask=function(){return 0}},{}],4:[function(r,e,t){function n(r,e,t){function n(r){return r>=200&&r<300||304===r}function o(){void 0===a.status||n(a.status)?e.call(a,null,a):e.call(a,a,null)}var i=!1;if("undefined"==typeof window.XMLHttpRequest)return e(Error("Browser not supported"));if("undefined"==typeof t){var u=r.match(/^\s*https?:\/\/[^\/]*/);t=u&&u[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var a=new window.XMLHttpRequest;if(t&&!("withCredentials"in a)){a=new window.XDomainRequest;var s=e;e=function(){if(i)s.apply(this,arguments);else{var r=this,e=arguments;setTimeout(function(){s.apply(r,e)},0)}}}return"onload"in a?a.onload=o:a.onreadystatechange=function(){4===a.readyState&&o()},a.onerror=function(r){e.call(this,r||!0,null),e=function(){}},a.onprogress=function(){},a.ontimeout=function(r){e.call(this,r,null),e=function(){}},a.onabort=function(r){e.call(this,r,null),e=function(){}},a.open("GET",r,!0),a.send(null),i=!0,a}"undefined"!=typeof e&&(e.exports=n)},{}],5:[function(r,e,t){"use strict";function n(r,e){var t,n,o;for(var i in r)n=i.match(e),n&&(!t||n[0].length/i.length>o)&&(o=n[0].length/i.length,t=i);return t}function o(r){return n(r,m)}function i(r){return n(r,y)}function u(r){return!!r.match(m)}function a(r){return!!r.match(y)}function s(r){return"object"==typeof r?Object.keys(r).length:0}function f(r){var e=[",",";","\t","|"],t=[];return e.forEach(function(e){var n=d.dsvFormat(e).parse(r);if(n.length>=1){for(var o=s(n[0]),i=0;i<n.length;i++)if(s(n[i])!==o)return;t.push({delimiter:e,arity:Object.keys(n[0]).length})}}),t.length?t.sort(function(r,e){return e.arity-r.arity})[0].delimiter:null}function c(r){return delete r.columns,r}function l(r){var e=f(r);return e?c(d.dsvFormat(e).parse(r)):null}function p(r,e,t){t||(t=e,e={}),e.delimiter=e.delimiter||",";var n=e.latfield||"",u=e.lonfield||"",a=e.crs||"",s=[],c={type:"FeatureCollection",features:s};if(""!==a&&(c.crs={type:"name",properties:{name:a}}),"auto"===e.delimiter&&"string"==typeof r&&(e.delimiter=f(r),!e.delimiter))return void t({type:"Error",message:"Could not autodetect delimiter"});var l="string"==typeof r?d.dsvFormat(e.delimiter).parse(r):r;if(!l.length)return void t(null,c);var p,h=[];n||(n=o(l[0])),u||(u=i(l[0]));var g=!n||!u;if(g){for(p=0;p<l.length;p++)s.push({type:"Feature",properties:l[p],geometry:null});return void t(h.length?h:null,c)}for(p=0;p<l.length;p++)if(void 0!==l[p][u]&&void 0!==l[p][n]){var m,y,x,w=l[p][u],L=l[p][n];x=v(w,"EW"),x&&(w=x),x=v(L,"NS"),x&&(L=x),m=parseFloat(w),y=parseFloat(L),isNaN(m)||isNaN(y)?h.push({message:"A row contained an invali
13977d value for latitude or longitude",row:l[p],index:p}):(e.includeLatLon||(delete l[p][u],delete l[p][n]),s.push({type:"Feature",properties:l[p],geometry:{type:"Point",coordinates:[parseFloat(m),parseFloat(y)]}}))}t(h.length?h:null,c)}function h(r){for(var e=r.features,t={type:"Feature",geometry:{type:"LineString",coordinates:[]}},n=0;n<e.length;n++)t.geometry.coordinates.push(e[n].geometry.coordinates);return t.properties=e.reduce(function(r,e){for(var t in e.properties)r[t]||(r[t]=[]),r[t].push(e.properties[t]);return r},{}),{type:"FeatureCollection",features:[t]}}function g(r){for(var e=r.features,t={type:"Feature",geometry:{type:"Polygon",coordinates:[[]]}},n=0;n<e.length;n++)t.geometry.coordinates[0].push(e[n].geometry.coordinates);return t.properties=e.reduce(function(r,e){for(var t in e.properties)r[t]||(r[t]=[]),r[t].push(e.properties[t]);return r},{}),{type:"FeatureCollection",features:[t]}}var d=r("d3-dsv"),v=r("sexagesimal"),m=/(Lat)(itude)?/gi,y=/(L)(on|ng)(gitude)?/i;e.exports={isLon:a,isLat:u,guessLatHeader:o,guessLonHeader:i,csv:d.csvParse,tsv:d.tsvParse,dsv:d,auto:l,csv2geojson:p,toLine:h,toPolygon:g}},{"d3-dsv":6,sexagesimal:7}],6:[function(e,t,n){!function(e,o){"object"==typeof n&&"undefined"!=typeof t?o(n):"function"==typeof r&&r.amd?r(["exports"],o):o(e.d3=e.d3||{})}(this,function(r){"use strict";function e(r){return new Function("d","return {"+r.map(function(r,e){return JSON.stringify(r)+": d["+e+"]"}).join(",")+"}")}function t(r,t){var n=e(r);return function(e,o){return t(n(e),o,r)}}function n(r){var e=Object.create(null),t=[];return r.forEach(function(r){for(var n in r)n in e||t.push(e[n]=n)}),t}function o(r){function o(r,n){var o,u,a=i(r,function(r,i){return o?o(r,i-1):(u=r,void(o=n?t(r,n):e(r)))});return a.columns=u,a}function i(r,e){function t(){if(f>=s)return u;if(o)return o=!1,i;var e,t=f;if(34===r.charCodeAt(t)){for(var n=t;n++<s;)if(34===r.charCodeAt(n)){if(34!==r.charCodeAt(n+1))break;++n}return f=n+2,e=r.charCodeAt(n+1),13===e?(o=!0,10===r.charCodeAt(n+2)&&++f):10===e&&(o=!0),r.slice(t+1,n).replace(/""/g,'"')}for(;f<s;){var a=1;if(e=r.charCodeAt(f++),10===e)o=!0;else if(13===e)o=!0,10===r.charCodeAt(f)&&(++f,++a);else if(e!==l)continue;return r.slice(t,f-a)}return r.slice(t)}for(var n,o,i={},u={},a=[],s=r.length,f=0,c=0;(n=t())!==u;){for(var p=[];n!==i&&n!==u;)p.push(n),n=t();e&&null==(p=e(p,c++))||a.push(p)}return a}function u(e,t){return null==t&&(t=n(e)),[t.map(f).join(r)].concat(e.map(function(e){return t.map(function(r){return f(e[r])}).join(r)})).join("\n")}function a(r){return r.map(s).join("\n")}function s(e){return e.map(f).join(r)}function f(r){return null==r?"":c.test(r+="")?'"'+r.replace(/\"/g,'""')+'"':r}var c=new RegExp('["'+r+"\n]"),l=r.charCodeAt(0);return{parse:o,parseRows:i,format:u,formatRows:a}}var i=o(","),u=i.parse,a=i.parseRows,s=i.format,f=i.formatRows,c=o("\t"),l=c.parse,p=c.parseRows,h=c.format,g=c.formatRows;r.dsvFormat=o,r.csvParse=u,r.csvParseRows=a,r.csvFormat=s,r.csvFormatRows=f,r.tsvParse=l,r.tsvParseRows=p,r.tsvFormat=h,r.tsvFormatRows=g,Object.defineProperty(r,"__esModule",{value:!0})})},{}],7:[function(r,e,t){function n(r,e){return a(r,e).val}function o(r){return i(r.lat,"lat")+" "+i(r.lon,"lon")}function i(r,e){var t=u(r,e);return t.whole+"ð "+(t.minutes?t.minutes+"' ":"")+(t.seconds?t.seconds+'" ':"")+t.dir}function u(r,e){var t={lat:["N","S"],lon:["E","W"]}[e]||"",n=t[r>=0?0:1],o=Math.abs(r),i=Math.floor(o),u=o-i,a=60*u,s=Math.floor(a),f=Math.floor(60*(a-s));return{whole:i,minutes:s,seconds:f,dir:n}}function a(r,e,t){if(e||(e="NSEW"),"string"!=typeof r)return{val:null,regex:t};t=t||/[\s\,]*([\-|\ââ¬â|\ââ¬â¢]?[0-9.]+)ð? *(?:([0-9.]+)['ââ¬â¢Ã¢â¬Â²Ã¢â¬Ë] *)?(?:([0-9.]+)(?:''|"|ââ¬Â|ââ¬Â³) *)?([NSEW])?/gi;var n=t.exec(r);return n?n[4]&&e.indexOf(n[4])===-1?{val:null,regex:t}:{val:((n[1]?parseFloat(n[1]):0)+(n[2]?parseFloat(n[2])/60:0)+(n[3]?parseFloat(n[3])/3600:0))*(n[4]&&"S"===n[4]||"W"===n[4]?-1:1),regex:t,raw:n[0],dim:n[4]}:{val:null,regex:t}}function s(r,e){r=r.trim();var t=a(r,e);if(null===t.val)return null;var n=a(r,e,t.regex);return null===n.val?null:t.raw+n.raw!==r?null:t.dim?f(t.val,n.val,t.dim):[t.val,n.val]}function f(r,e,t){return"N"===t||"S"===t?[r,e]:"W"===t||"E"===t?[e,r]:void 0}e.exports=n,e.exports.pair=s,e.exports.format=i,e.exports.formatPair=o,e.exports.coordToDMS=u},{}],8:[function(r,e,t){"use strict";function n(r,e){r=Math.round(r*e),r<<=1,r<0&&(r=~r);for(var t="";r>=32;)t+=String.fromCharCode((32|31&r)+63),r>>=5;return t+=String.fromCharCode(r+63)}function o(r){for(var e=[],t=0;t<r.length;t++)e.push(r[t].slice().reverse());return e}var i={};i.decode=function(r,e){for(var t,n,o=0,i=0,u=0,a=[],s=0,f=0,c=null,l=Math.pow(10,e||5);o<r.length;){c=null,s=0,f=0;do c=r.charCodeAt(o++)-63,f|=(31&c)<<s,s+=5;while(c>=32);t=1&f?~(f>>1):f>>1,s=f=0;do c=r.charCodeAt(o++)-63,f|=(31&c)<<s,s+=5;while(c>=32);n=1&f?~(f>>1):f>>1,i+=t,u+=n,a.push([i/l,u/l])}return a},i.encode=function(r,e){if(!r.length)return"";for(var t=Math.pow(10,e||5),o=n(r[0][0],t)+n(r[0][1],t),i=1;i<r.length;i++){var u=r[i],a=r[i-1];o+=n(u[0]-a[0],t),o+=n(u[1]-a[1],t)}return o},i.fromGeoJSON=function(r,e){if(r&&"Feature"===r.type&&(r=r.geometry),!r||"LineString"!==r.type)throw new Error("Input must be a GeoJSON LineString");return i.encode(o(r.coordinates),e)},i.toGeoJSON=function(r,e){var t=i.decode(r,e);return{type:"LineString",coordinates:o(t)}},"object"==typeof e&&e.exports&&(e.exports=i)},{}],9:[function(r,e,t){(function(n){var o=function(){"use strict";function e(r){if(!r||!r.length)return 0;for(var e=0,t=0;e<r.length;e++)t=(t<<5)-t+r.charCodeAt(e)|0;return t}function o(r,e){return r.getElementsByTagName(e)}function i(r,e){return r.getAttribute(e)}function u(r,e){return parseFloat(i(r,e))}function a(r,e){var t=o(r,e);return t.length?t[0]:null}function s(r){return r.normalize&&r.normalize(),r}function f(r){for(var e=0,t=[];e<r.length;e++)t[e]=parseFloat(r[e]);return t}function c(r){var e={};for(var t in r)r[t]&&(e[t]=r[t]);return e}function l(r){return r&&s(r),r&&r.textContent||""}function p(r){return f(r.replace(y,"").split(","))}function h(r){for(var e=r.replace(x,"").split(w),t=[],n=0;n<e.length;n++)t.push(p(e[n]));return t}function g(r){var e,t=[u(r,"lon"),u(r,"lat")],n=a(r,"ele"),o=a(r,"gpxtpx:hr")||a(r,"hr"),i=a(r,"time");return n&&(e=parseFloat(l(n)),isNaN(e)||t.push(e)),{coordinates:t,time:i?l(i):null,heartRate:o?parseFloat(l(o)):null}}function d(){return{type:"FeatureCollection",features:[]}}function v(r){return void 0!==r.xml?r.xml:m.serializeToString(r)}var m,y=/\s*/g,x=/^\s*|\s*$/g,w=/\s+/;"undefined"!=typeof XMLSerializer?m=new XMLSerializer:"object"!=typeof t||"object"!=typeof n||n.browser||(m=new(r("xmldom").XMLSerializer));var L={kml:function(r){function t(r){var e,t;return r=r||"","#"===r.substr(0,1)&&(r=r.substr(1)),6!==r.length&&3!==r.length||(e=r),8===r.length&&(t=parseInt(r.substr(0,2),16)/255,e="#"+r.substr(2)),[e,isNaN(t)?void 0:t]}function n(r){return f(r.split(" "))}function u(r){var e=o(r,"coord","gx"),t=[],i=[];0===e.length&&(e=o(r,"gx:coord"));for(var u=0;u<e.length;u++)t.push(n(l(e[u])));for(var a=o(r,"when"),s=0;s<a.length;s++)i.push(l(a[s]));return{coords:t,times:i}}function s(r){var e,t,n,i,f,c=[],g=[];if(a(r,"MultiGeometry"))return s(a(r,"MultiGeometry"));if(a(r,"MultiTrack"))return s(a(r,"MultiTrack"));if(a(r,"gx:MultiTrack"))return s(a(r,"gx:MultiTrack"));for(n=0;n<y.length;n++)if(t=o(r,y[n]))for(i=0;i<t.length;i++)if(e=t[i],"Point"===y[n])c.push({type:"Point",coordinates:p(l(a(e,"coordinates")))});else if("LineString"===y[n])c.push({type:"LineString",coordinates:h(l(a(e,"coordinates")))});else if("Polygon"===y[n]){var d=o(e,"LinearRing"),v=[];for(f=0;f<d.length;f++)v.push(h(l(a(d[f],"coordinates"))));c.push({type:"Polygon",coordinates:v})}else if("Track"===y[n]||"gx:Track"===y[n]){var m=u(e);c.push({type:"LineString",coordinates:m.coords}
13977),m.times.length&&g.push(m.times)}return{geoms:c,coordTimes:g}}function c(r){var e,n=s(r),u={},f=l(a(r,"name")),c=l(a(r,"styleUrl")),p=l(a(r,"description")),h=a(r,"TimeSpan"),g=a(r,"ExtendedData"),d=a(r,"LineStyle"),v=a(r,"PolyStyle");if(!n.geoms.length)return[];if(f&&(u.name=f),"#"!==c[0]&&(c="#"+c),c&&m[c]&&(u.styleUrl=c,u.styleHash=m[c]),p&&(u.description=p),h){var y=l(a(h,"begin")),x=l(a(h,"end"));u.timespan={begin:y,end:x}}if(d){var w=t(l(a(d,"color"))),L=w[0],E=w[1],S=parseFloat(l(a(d,"width")));L&&(u.stroke=L),isNaN(E)||(u["stroke-opacity"]=E),isNaN(S)||(u["stroke-width"]=S)}if(v){var T=t(l(a(v,"color"))),M=T[0],P=T[1],N=l(a(v,"fill")),b=l(a(v,"outline"));M&&(u.fill=M),isNaN(P)||(u["fill-opacity"]=P),N&&(u["fill-opacity"]="1"===N?1:0),b&&(u["stroke-opacity"]="1"===b?1:0)}if(g){var F=o(g,"Data"),j=o(g,"SimpleData");for(e=0;e<F.length;e++)u[F[e].getAttribute("name")]=l(a(F[e],"value"));for(e=0;e<j.length;e++)u[j[e].getAttribute("name")]=l(j[e])}n.coordTimes.length&&(u.coordTimes=1===n.coordTimes.length?n.coordTimes[0]:n.coordTimes);var C={type:"Feature",geometry:1===n.geoms.length?n.geoms[0]:{type:"GeometryCollection",geometries:n.geoms},properties:u};return i(r,"id")&&(C.id=i(r,"id")),[C]}for(var g=d(),m={},y=["Polygon","LineString","Point","Track","gx:Track"],x=o(r,"Placemark"),w=o(r,"Style"),L=o(r,"StyleMap"),E=0;E<w.length;E++)m["#"+i(w[E],"id")]=e(v(w[E])).toString(16);for(var S=0;S<L.length;S++)m["#"+i(L[S],"id")]=e(v(L[S])).toString(16);for(var T=0;T<x.length;T++)g.features=g.features.concat(c(x[T]));return g},gpx:function(r){function e(r,e){var t=o(r,e),n=[],i=[],u=[],a=t.length;if(a<2)return{};for(var s=0;s<a;s++){var f=g(t[s]);n.push(f.coordinates),f.time&&i.push(f.time),f.heartRate&&u.push(f.heartRate)}return{line:n,times:i,heartRates:u}}function t(r){for(var t,n=o(r,"trkseg"),i=[],a=[],s=[],f=0;f<n.length;f++)t=e(n[f],"trkpt"),t.line&&i.push(t.line),t.times&&t.times.length&&a.push(t.times),t.heartRates&&t.heartRates.length&&s.push(t.heartRates);if(0!==i.length){var c=u(r);return a.length&&(c.coordTimes=1===i.length?a[0]:a),s.length&&(c.heartRates=1===i.length?s[0]:s),{type:"Feature",properties:c,geometry:{type:1===i.length?"LineString":"MultiLineString",coordinates:1===i.length?i[0]:i}}}}function n(r){var t=e(r,"rtept");if(t.line){var n={type:"Feature",properties:u(r),geometry:{type:"LineString",coordinates:t.line}};return n}}function i(r){var e=u(r);return e.sym=l(a(r,"sym")),{type:"Feature",properties:e,geometry:{type:"Point",coordinates:g(r).coordinates}}}function u(r){var e,t=["name","desc","author","copyright","link","time","keywords"],n={};for(e=0;e<t.length;e++)n[t[e]]=l(a(r,t[e]));return c(n)}var s,f,p=o(r,"trk"),h=o(r,"rte"),v=o(r,"wpt"),m=d();for(s=0;s<p.length;s++)f=t(p[s]),f&&m.features.push(f);for(s=0;s<h.length;s++)f=n(h[s]),f&&m.features.push(f);for(s=0;s<v.length;s++)m.features.push(i(v[s]));return m}};return L}();"undefined"!=typeof e&&(e.exports=o)}).call(this,r("_process"))},{_process:3,xmldom:2}],10:[function(e,t,n){!function(e,o){"object"==typeof n&&"undefined"!=typeof t?o(n):"function"==typeof r&&r.amd?r(["exports"],o):o(e.topojson=e.topojson||{})}(this,function(r){"use strict";function e(){}function t(r){if(!r)return e;var t,n,o=r.scale[0],i=r.scale[1],u=r.translate[0],a=r.translate[1];return function(r,e){e||(t=n=0),r[0]=(t+=r[0])*o+u,r[1]=(n+=r[1])*i+a}}function n(r){if(!r)return e;var t,n,o=r.scale[0],i=r.scale[1],u=r.translate[0],a=r.translate[1];return function(r,e){e||(t=n=0);var s=Math.round((r[0]-u)/o),f=Math.round((r[1]-a)/i);r[0]=s-t,r[1]=f-n,t=s,n=f}}function o(r,e){for(var t,n=r.length,o=n-e;o<--n;)t=r[o],r[o++]=r[n],r[n]=t}function i(r,e){for(var t=0,n=r.length;t<n;){var o=t+n>>>1;r[o]<e?t=o+1:n=o}return t}function u(r,e){return"GeometryCollection"===e.type?{type:"FeatureCollection",features:e.geometries.map(function(e){return a(r,e)})}:a(r,e)}function a(r,e){var t={type:"Feature",id:e.id,properties:e.properties||{},geometry:s(r,e)};return null==e.id&&delete t.id,t}function s(r,e){function n(r,e){e.length&&e.pop();for(var t,n=l[r<0?~r:r],i=0,u=n.length;i<u;++i)e.push(t=n[i].slice()),c(t,i);r<0&&o(e,u)}function i(r){return r=r.slice(),c(r,0),r}function u(r){for(var e=[],t=0,o=r.length;t<o;++t)n(r[t],e);return e.length<2&&e.push(e[0].slice()),e}function a(r){for(var e=u(r);e.length<4;)e.push(e[0].slice());return e}function s(r){return r.map(a)}function f(r){var e=r.type;return"GeometryCollection"===e?{type:e,geometries:r.geometries.map(f)}:e in p?{type:e,coordinates:p[e](r)}:null}var c=t(r.transform),l=r.arcs,p={Point:function(r){return i(r.coordinates)}
13977,MultiPoint:function(r){return r.coordinates.map(i)},LineString:function(r){return u(r.arcs)},MultiLineString:function(r){return r.arcs.map(u)},Polygon:function(r){return s(r.arcs)},MultiPolygon:function(r){return r.arcs.map(s)}};return f(e)}function f(r,e){function t(e){var t,n=r.arcs[e<0?~e:e],o=n[0];return r.transform?(t=[0,0],n.forEach(function(r){t[0]+=r[0],t[1]+=r[1]})):t=n[n.length-1],e<0?[t,o]:[o,t]}function n(r,e){for(var t in r){var n=r[t];delete e[n.start],delete n.start,delete n.end,n.forEach(function(r){o[r<0?~r:r]=1}),a.push(n)}}var o={},i={},u={},a=[],s=-1;return e.forEach(function(t,n){var o,i=r.arcs[t<0?~t:t];i.length<3&&!i[1][0]&&!i[1][1]&&(o=e[++s],e[s]=t,e[n]=o)}),e.forEach(function(r){var e,n,o=t(r),a=o[0],s=o[1];if(e=u[a])if(delete u[e.end],e.push(r),e.end=s,n=i[s]){delete i[n.start];var f=n===e?e:e.concat(n);i[f.start=e.start]=u[f.end=n.end]=f}else i[e.start]=u[e.end]=e;else if(e=i[s])if(delete i[e.start],e.unshift(r),e.start=a,n=u[a]){delete u[n.end];var c=n===e?e:n.concat(e);i[c.start=n.start]=u[c.end=e.end]=c}else i[e.start]=u[e.end]=e;else e=[r],i[e.start=a]=u[e.end=s]=e}),n(u,i),n(i,u),e.forEach(function(r){o[r<0?~r:r]||a.push([r])}),a}function c(r){return s(r,l.apply(this,arguments))}function l(r,e,t){function n(r){var e=r<0?~r:r;(c[e]||(c[e]=[])).push({i:r,g:s})}function o(r){r.forEach(n)}function i(r){r.forEach(o)}function u(r){"GeometryCollection"===r.type?r.geometries.forEach(u):r.type in l&&(s=r,l[r.type](r.arcs))}var a=[];if(arguments.length>1){var s,c=[],l={LineString:o,MultiLineString:i,Polygon:i,MultiPolygon:function(r){r.forEach(i)}};u(e),c.forEach(arguments.length<3?function(r){a.push(r[0].i)}:function(r){t(r[0].g,r[r.length-1].g)&&a.push(r[0].i)})}else for(var p=0,h=r.arcs.length;p<h;++p)a.push(p);return{type:"MultiLineString",arcs:f(r,a)}}function p(r){var e=r[0],t=r[1],n=r[2];return Math.abs((e[0]-n[0])*(t[1]-e[1])-(e[0]-t[0])*(n[1]-e[1]))}function h(r){for(var e,t=-1,n=r.length,o=r[n-1],i=0;++t<n;)e=o,o=r[t],i+=e[0]*o[1]-e[1]*o[0];return i/2}function g(r){return s(r,d.apply(this,arguments))}function d(r,e){function t(r){r.forEach(function(e){e.forEach(function(e){(o[e=e<0?~e:e]||(o[e]=[])).push(r)})}),i.push(r)}function n(e){return Math.abs(h(s(r,{type:"Polygon",arcs:[e]}).coordinates[0]))}var o={},i=[],u=[];return e.forEach(function(r){"Polygon"===r.type?t(r.arcs):"MultiPolygon"===r.type&&r.arcs.forEach(t)}),i.forEach(function(r){if(!r._){var e=[],t=[r];for(r._=1,u.push(e);r=t.pop();)e.push(r),r.forEach(function(r){r.forEach(function(r){o[r<0?~r:r].forEach(function(r){r._||(r._=1,t.push(r))})})})}}
13977),i.forEach(function(r){delete r._}),{type:"MultiPolygon",arcs:u.map(function(e){var t,i=[];if(e.forEach(function(r){r.forEach(function(r){r.forEach(function(r){o[r<0?~r:r].length<2&&i.push(r)})})}),i=f(r,i),(t=i.length)>1)for(var u,a,s=1,c=n(i[0]);s<t;++s)(u=n(i[s]))>c&&(a=i[0],i[0]=i[s],i[s]=a,c=u);return i})}}function v(r){function e(r,e){r.forEach(function(r){r<0&&(r=~r);var t=o[r];t?t.push(e):o[r]=[e]})}function t(r,t){r.forEach(function(r){e(r,t)})}function n(r,e){"GeometryCollection"===r.type?r.geometries.forEach(function(r){n(r,e)}):r.type in a&&a[r.type](r.arcs,e)}var o={},u=r.map(function(){return[]}),a={LineString:e,MultiLineString:t,Polygon:t,MultiPolygon:function(r,e){r.forEach(function(r){t(r,e)})}};r.forEach(n);for(var s in o)for(var f=o[s],c=f.length,l=0;l<c;++l)for(var p=l+1;p<c;++p){var h,g=f[l],d=f[p];(h=u[g])[s=i(h,d)]!==d&&h.splice(s,0,d),(h=u[d])[s=i(h,g)]!==g&&h.splice(s,0,g)}return u}function m(r,e){return r[1][2]-e[1][2]}function y(){function r(r,e){for(;e>0;){var t=(e+1>>1)-1,o=n[t];if(m(r,o)>=0)break;n[o._=e]=o,n[r._=e=t]=r}}function e(r,e){for(;;){var t=e+1<<1,i=t-1,u=e,a=n[u];if(i<o&&m(n[i],a)<0&&(a=n[u=i]),t<o&&m(n[t],a)<0&&(a=n[u=t]),u===e)break;n[a._=e]=a,n[r._=e=u]=r}}var t={},n=[],o=0;return t.push=function(e){return r(n[e._=o]=e,o++),o},t.pop=function(){if(!(o<=0)){var r,t=n[0];return--o>0&&(r=n[o],e(n[r._=0]=r,0)),t}},t.remove=function(t){var i,u=t._;if(n[u]===t)return u!==--o&&(i=n[o],(m(i,t)<0?r:e)(n[i._=u]=i,u)),u},t}function x(r,e){function o(r){a.remove(r),r[1][2]=e(r),a.push(r)}var i=t(r.transform),u=n(r.transform),a=y();return e||(e=p),r.arcs.forEach(function(r){var t,n,s,f,c=[],l=0;for(n=0,s=r.length;n<s;++n)f=r[n],i(r[n]=[f[0],f[1],1/0],n);for(n=1,s=r.length-1;n<s;++n)t=r.slice(n-1,n+2),t[1][2]=e(t),c.push(t),a.push(t);for(n=0,s=c.length;n<s;++n)t=c[n],t.previous=c[n-1],t.next=c[n+1];for(;t=a.pop();){var p=t.previous,h=t.next;t[1][2]<l?t[1][2]=l:l=t[1][2],p&&(p.next=h,p[2]=t[2],o(p)),h&&(h.previous=p,h[0]=t[0],o(h))}r.forEach(u)}),r}var w="1.6.26";r.version=w,r.mesh=c,r.meshArcs=l,r.merge=g,r.mergeArcs=d,r.feature=u,r.neighbors=v,r.presimplify=x})},{}],11:[function(r,e,t){function n(r){function e(r){var e=v.substring(y).match(r);return e?(y+=e[0].length,e[0]):null}function t(r){return r&&m.match(/\d+/)&&(r.crs={type:"name",properties:{name:"urn:ogc:def:crs:EPSG::"+m}}),r}function n(){e(/^\s*/)}function o(){n();for(var r,t=0,o=[],i=[o],a=o;r=e(/^(\()/)||e(/^(\))/)||e(/^(\,)/)||e(u);){if("("===r)i.push(a),a=[],i[i.length-1].push(a),t++;else if(")"===r){if(0===a.length)return null;if(a=i.pop(),!a)return null;if(t--,0===t)break}else if(","===r)a=[],i[i.length-1].push(a);else{if(r.split(/\s/g).some(isNaN))return null;Array.prototype.push.apply(a,r.split(/\s/g).map(parseFloat))}n()}return 0!==t?null:o}function i(){for(var r,t,o=[];t=e(u)||e(/^(\,)/);)","===t?(o.push(r),r=[]):t.split(/\s/g).some(isNaN)||(r||(r=[]),Array.prototype.push.apply(r,t.split(/\s/g).map(parseFloat))),n();return r?(o.push(r),o.length?o:null):null}function a(){if(!e(/^(point)/i))return null;if(n(),!e(/^(\()/))return null;var r=i();return r?(n(),e(/^(\))/)?{type:"Point",coordinates:r[0]}:null):null}function s(){if(!e(/^(multipoint)/i))return null;n();var r=v.substring(v.indexOf("(")+1,v.length-1).replace(/\(/g,"").replace(/\)/g,"");v="MULTIPOINT ("+r+")";var t=o();return t?(n(),{type:"MultiPoint",coordinates:t}):null}function f(){if(!e(/^(multilinestring)/i))return null;n();var r=o();return r?(n(),{type:"MultiLineString",coordinates:r}):null}function c(){if(!e(/^(linestring)/i))return null;if(n(),!e(/^(\()/))return null;var r=i();return r&&e(/^(\))/)?{type:"LineString",coordinates:r}:null}function l(){if(!e(/^(polygon)/i))return null;n();var r=o();return r?{type:"Polygon",coordinates:r}:null}function p(){if(!e(/^(multipolygon)/i))return null;n();var r=o();return r?{type:"MultiPolygon",coordinates:r}:null}function h(){var r,t=[];if(!e(/^(geometrycollection)/i))return null;if(n(),!e(/^(\()/))return null;for(;r=g();)t.push(r),n(),e(/^(\,)/),n();return e(/^(\))/)?{type:"GeometryCollection",geometries:t}:null}function g(){return a()||c()||l()||s()||f()||p()||h()}var d=r.split(";"),v=d.pop(),m=(d.shift()||"").split("=").pop(),y=0;return t(g())}function o(r){function e(r){return r.join(" ")}function t(r){return r.map(e).join(", ")}function n(r){return r.map(t).map(u).join(", ")}function i(r){return r.map(n).map(u).join(", ")}function u(r){return"("+r+")"}switch("Feature"===r.type&&(r=r.geometry),r.type){case"Point":return"POINT ("+e(r.coordinates)+")";case"LineString":return"LINESTRING ("+t(r.coordinates)+")";case"Polygon":return"POLYGON ("+n(r.coordinates)+")";case"MultiPoint":return"MULTIPOINT ("+t(r.coordinates)+")";case"MultiPolygon":return"MULTIPOLYGON ("+i(r.coordinates)+")";case"MultiLineString":return"MULTILINESTRING ("+n(r.coordinates)+")";case"GeometryCollection":return"GEOMETRYCOLLECTION ("+r.geometries.map(o).join(", ")+")";default:throw new Error("stringify requires a valid GeoJSON Feature or geometry object as input")}}
13977e.exports=n,e.exports.parse=n,e.exports.stringify=o;var i=/[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/,u=new RegExp("^"+i.source+"(\\s"+i.source+"){1,}")},{}]},{},[1])(1)}); 13978 13979!function(a,t){"function"==typeof define&&define.amd?define(["leaflet"],t):"object"==typeof modules&&module.exports?module.exports=t(require("leaflet")):t(L)}(0,function(u){"use strict";return u.TileLayer.Provider=u.TileLayer.extend({initialize:function(a,t){var o=u.TileLayer.Provider.providers,e=a.split("."),r=e[0],i=e[1];if(!o[r])throw"No such provider ("+r+")";var n={url:o[r].url,options:o[r].options};if(i&&"variants"in o[r]){if(!(i in o[r].variants))throw"No such variant of "+r+" ("+i+")";var s,p=o[r].variants[i];s="string"==typeof p?{variant:p}:p.options,n={url:p.url||n.url,options:u.Util.extend({},n.options,s)}}var l=function(a){return-1===a.indexOf("{attribution.")?a:a.replace(/\{attribution.(\w*)\}/,function(a,t){return l(o[t].options.attribution)})};n.options.attribution=l(n.options.attribution);var m=u.Util.extend({},n.options,t);u.TileLayer.prototype.initialize.call(this,n.url,m)}}),u.TileLayer.Provider.providers={OpenStreetMap:{url:"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",options:{maxZoom:19,attribution:'© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'},variants:{Mapnik:{},BlackAndWhite:{url:"http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png",options:{maxZoom:18}},DE:{url:"https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png",options:{maxZoom:18}},CH:{url:"https://tile.osm.ch/switzerland/{z}/{x}/{y}.png",options:{maxZoom:18,bounds:[[45,5],[48,11]]}},France:{url:"https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png",options:{maxZoom:20,attribution:"© Openstreetmap France | {attribution.OpenStreetMap}"}},HOT:{url:"https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",options:{attribution:'{attribution.OpenStreetMap}, Tiles courtesy of <a href="http://hot.openstreetmap.org/" target="_blank">Humanitarian OpenStreetMap Team</a>'}},BZH:{url:"https://tile.openstreetmap.bzh/br/{z}/{x}/{y}.png",options:{attribution:'{attribution.OpenStreetMap}, Tiles courtesy of <a href="http://www.openstreetmap.bzh/" target="_blank">Breton OpenStreetMap Team</a>',bounds:[[46.2,-5.5],[50,.7]]}}}},OpenInfraMap:{url:"https://tiles-{s}.openinframap.org/{variant}/{z}/{x}/{y}.png",options:{maxZoom:18,attribution:'{attribution.OpenStreetMap}, <a href="http://www.openinframap.org/about.html">About OpenInfraMap</a>'},variants:{Power:"power",Telecom:"telecoms",Petroleum:"petroleum",Water:"water"}},OpenSeaMap:{url:"https://tiles.openseamap.org/seamark/{z}/{x}/{y}.png",options:{attribution:'Map data: © <a href="http://www.openseamap.org">OpenSeaMap</a> contributors'}},OpenPtMap:{url:"http://openptmap.org/tiles/{z}/{x}/{y}.png",options:{maxZoom:17,attribution:'Map data: © <a href="http://www.openptmap.org">OpenPtMap</a> contributors'}},OpenTopoMap:{url:"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",options:{maxZoom:17,attribution:'Map data: {attribution.OpenStreetMap}, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'}},OpenRailwayMap:{url:"https://{s}.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png",options:{maxZoom:19,attribution:'Map data: {attribution.OpenStreetMap} | Map style: © <a href="https://www.OpenRailwayMap.org">OpenRailwayMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'}},OpenFireMap:{url:"http://openfiremap.org/hytiles/{z}/{x}/{y}.png",options:{maxZoom:19,attribution:'Map data: {attribution.OpenStreetMap} | Map style: © <a href="http://www.openfiremap.org">OpenFireMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'}},SafeCast:{url:"https://s3.amazonaws.com/te512.safecast.org/{z}/{x}/{y}.png",options:{maxZoom:16,attribution:'Map data: {attribution.OpenStreetMap} | Map style: © <a href="https://blog.safecast.org/about/">SafeCast</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'}},Thunderforest:{url:"https://{s}.tile.thunderforest.com/{variant}/{z}/{x}/{y}.png?apikey={apikey}",options:{attribution:'© <a href="http://www.thunderforest.com/">Thunderforest</a>, {attribution.OpenStreetMap}',variant:"cycle",apikey:"<insert your api key here>",maxZoom:22},variants:{OpenCycleMap:"cycle",Transport:{options:{variant:"transport"}},TransportDark:{options:{variant:"transport-dark"}},SpinalMap:{options:{variant:"spinal-map"}},Landscape:"landscape",Outdoors:"outdoors",Pioneer:"pioneer"}},OpenMapSurfer:{url:"https://korona.geog.uni-heidelberg.de/tiles/{variant}/x={x}&y={y}&z={z}",options:{maxZoom:20,variant:"roads",attribution:'Imagery from <a href="http://giscience.uni-hd.de/">GIScience Research Group @ University of Heidelberg</a> — Map data {attribution.OpenStreetMap}'},variants:{Roads:"roads",AdminBounds:{options:{variant:"adminb",maxZoom:19}},Grayscale:{options:{variant:"roadsg",maxZoom:19}}}},Hydda:{url:"https://{s}.tile.openstreetmap.se/hydda/{variant}/{z}/{x}/{y}.png",options:{maxZoom:18,variant:"full",attribution:'Tiles courtesy of <a href="http://openstreetmap.se/" target="_blank">
13979OpenStreetMap Sweden</a> — Map data {attribution.OpenStreetMap}'},variants:{Full:"full",Base:"base",RoadsAndLabels:"roads_and_labels"}},MapBox:{url:"https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}{r}.png?access_token={accessToken}",options:{attribution:'Imagery from <a href="http://mapbox.com/about/maps/">MapBox</a> — Map data {attribution.OpenStreetMap}',subdomains:"abcd",id:"streets",accessToken:"<insert your access token here>"}},Stamen:{url:"https://stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}{r}.{ext}",options:{attribution:'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> — Map data {attribution.OpenStreetMap}',subdomains:"abcd",minZoom:0,maxZoom:20,variant:"toner",ext:"png"},variants:{Toner:"toner",TonerBackground:"toner-background",TonerHybrid:"toner-hybrid",TonerLines:"toner-lines",TonerLabels:"toner-labels",TonerLite:"toner-lite",Watercolor:{url:"https://stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}.{ext}",options:{variant:"watercolor",minZoom:1,maxZoom:16}},Terrain:{options:{variant:"terrain",minZoom:0,maxZoom:18}},TerrainBackground:{options:{variant:"terrain-background",minZoom:0,maxZoom:18}},TopOSMRelief:{url:"https://stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}.{ext}",options:{variant:"toposm-color-relief",ext:"jpg",bounds:[[22,-132],[51,-56]]}},TopOSMFeatures:{options:{variant:"toposm-features",bounds:[[22,-132],[51,-56]],opacity:.9}}}},Esri:{url:"https://server.arcgisonline.com/ArcGIS/rest/services/{variant}/MapServer/tile/{z}/{y}/{x}",options:{variant:"World_Street_Map",attribution:"Tiles © Esri"},variants:{WorldStreetMap:{options:{attribution:"{attribution.Esri} — Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012"}},DeLorme:{options:{variant:"Specialty/DeLorme_World_Base_Map",minZoom:1,maxZoom:11,attribution:"{attribution.Esri} — Copyright: ©2012 DeLorme"}},WorldTopoMap:{options:{variant:"World_Topo_Map",attribution:"{attribution.Esri} — Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community"}},WorldImagery:{options:{variant:"World_Imagery",attribution:"{attribution.Esri} — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"}},WorldTerrain:{options:{variant:"World_Terrain_Base",maxZoom:13,attribution:"{attribution.Esri} — Source: USGS, Esri, TANA, DeLorme, and NPS"}},WorldShadedRelief:{options:{variant:"World_Shaded_Relief",maxZoom:13,attribution:"{attribution.Esri} — Source: Esri"}},WorldPhysical:{options:{variant:"World_Physical_Map",maxZoom:8,attribution:"{attribution.Esri} — Source: US National Park Service"}},OceanBasemap:{options:{variant:"Ocean_Basemap",maxZoom:13,attribution:"{attribution.Esri} — Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri"}},NatGeoWorldMap:{options:{variant:"NatGeo_World_Map",maxZoom:16,attribution:"{attribution.Esri} — National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC"}},WorldGrayCanvas:{options:{variant:"Canvas/World_Light_Gray_Base",maxZoom:16,attribution:"{attribution.Esri} — Esri, DeLorme, NAVTEQ"}}}},OpenWeatherMap:{url:"http://{s}.tile.openweathermap.org/map/{variant}/{z}/{x}/{y}.png?appid={apiKey}",options:{maxZoom:19,attribution:'Map data © <a href="http://openweathermap.org">OpenWeatherMap</a>',apiKey:"<insert your api key here>",opacity:.5},variants:{Clouds:"clouds",CloudsClassic:"clouds_cls",Precipitation:"precipitation",PrecipitationClassic:"precipitation_cls",Rain:"rain",RainClassic:"rain_cls",Pressure:"pressure",PressureContour:"pressure_cntr",Wind:"wind",Temperature:"temp",Snow:"snow"}},HERE:{url:"https://{s}.{base}.maps.cit.api.here.com/maptile/2.1/{type}/{mapID}/{variant}/{z}/{x}/{y}/{size}/{format}?app_id={app_id}&app_code={app_code}&lg={language}",options:{attribution:'Map © 1987-2014 <a href="http://developer.here.com">HERE</a>',subdomains:"1234",mapID:"newest",app_id:"<insert your app_id here>",app_code:"<insert your app_code here>",base:"base",variant:"normal.day",maxZoom:20,type:"maptile",language:"eng",format:"png8",size:"256"},variants:{normalDay:"normal.day",normalDayCustom:"normal.day.custom",normalDayGrey:"normal.day.grey",normalDayMobile:"normal.day.mobile",normalDayGreyMobile:"normal.day.grey.mobile",normalDayTransit:"normal.day.transit",normalDayTransitMobile:"normal.day.transit.mobile",normalNight:"normal.night",normalNightMobile:"normal.night.mobile",normalNightGrey:"normal.night.grey",normalNightGreyMobile:"normal.night.grey.mobile",basicMap:{options:{type:"basetile"}},mapLabels:{options:{type:"labeltile",format:"png"}},trafficFlow:{options:{base:"traffic",type:"flowtile"}},carnavDayGrey:"carnav.day.grey",hybridDay:{options:{base:"aerial",variant:"hybrid.day"}},hybridDayMobile:{options:{base:"aerial",variant:"hybrid.day.mobile"}},pedestrianDay:"pedestrian.day",pedestrianNight:"pedestrian.night",satelliteDay:{options:{base:"aerial",variant:"satellite.day"}},terrainDay:{options:{base:"aerial",variant:"terrain.day"}},terrainDayMobile:{options:{base:"aerial",variant:"terrain.day.mobile"}}}},FreeMapSK:{url:"http://t{s}.freemap.sk/T/{z}/{x}/{y}.jpeg",options:{minZoom:8,maxZoom:16,subdomains:"1234",bounds:[[47.204642,15.996093],[49.830896,22.576904]],attribution:'{attribution.OpenStreetMap}, vizualization CC-By-SA 2.0 <a href="http://freemap.sk">Freemap.sk</a>'}},MtbMap:{url:"http://tile.mtbmap.cz/mtbmap_tiles/{z}/{x}/{y}.png",options:{attribution:"{attribution.OpenStreetMap} & USGS"}},CartoDB:{url:"https://cartodb-basemaps-{s}.global.ssl.fastly.net/{variant}/{z}/{x}/{y}{r}.png",options:{attribution:'{attribution.OpenStreetMap} © <a href="http://cartodb.com/attributions">CartoDB</a>',subdomains:"abcd",maxZoom:19,variant:"light_all"},variants:{Positron:"light_all",PositronNoLabels:"light_nolabels",PositronOnlyLabels:"light_only_labels",DarkMatter:"dark_all",DarkMatterNoLabels:"dark_nolabels",DarkMatterOnlyLabels:"dark_only_labels",Voyager:"rastertiles/voyager",VoyagerNoLabels:"rastertiles/voyager_nolabels",VoyagerOnlyLabels:"rastertiles/voyager_only_labels",VoyagerLabelsUnder:"rastertiles/voyager_labels_under"}},HikeBike:{url:"http://{s}.tiles.wmflabs.org/{variant}/{z}/{x}/{y}.png",options:{maxZoom:19,attribution:"{attribution.OpenStreetMap}",variant:"hikebike"},variants:{HikeBike:{}
vendor: 3,114 bytes, line 13979
13979,HillShading:{options:{maxZoom:15,variant:"hillshading"}}}},BasemapAT:{url:"https://maps{s}.wien.gv.at/basemap/{variant}/normal/google3857/{z}/{y}/{x}.{format}",options:{maxZoom:19,attribution:'Datenquelle: <a href="https://www.basemap.at">basemap.at</a>',subdomains:["","1","2","3","4"],format:"png",bounds:[[46.35877,8.782379],[49.037872,17.189532]],variant:"geolandbasemap"},variants:{basemap:{options:{maxZoom:20,variant:"geolandbasemap"}},grau:"bmapgrau",overlay:"bmapoverlay",highdpi:{options:{variant:"bmaphidpi",format:"jpeg"}},orthofoto:{options:{maxZoom:20,variant:"bmaporthofoto30cm",format:"jpeg"}}}},nlmaps:{url:"https://geodata.nationaalgeoregister.nl/tiles/service/wmts/{variant}/EPSG:3857/{z}/{x}/{y}.png",options:{minZoom:6,maxZoom:19,bounds:[[50.5,3.25],[54,7.6]],attribution:'Kaartgegevens © <a href="kadaster.nl">Kadaster</a>'},variants:{standaard:"brtachtergrondkaart",pastel:"brtachtergrondkaartpastel",grijs:"brtachtergrondkaartgrijs",luchtfoto:{url:"https://geodata.nationaalgeoregister.nl/luchtfoto/rgb/wmts/1.0.0/2016_ortho25/EPSG:3857/{z}/{x}/{y}.png"}}},NASAGIBS:{url:"https://map1.vis.earthdata.nasa.gov/wmts-webmerc/{variant}/default/{time}/{tilematrixset}{maxZoom}/{z}/{y}/{x}.{format}",options:{attribution:'Imagery provided by services from the Global Imagery Browse Services (GIBS), operated by the NASA/GSFC/Earth Science Data and Information System (<a href="https://earthdata.nasa.gov">ESDIS</a>) with funding provided by NASA/HQ.',bounds:[[-85.0511287776,-179.999999975],[85.0511287776,179.999999975]],minZoom:1,maxZoom:9,format:"jpg",time:"",tilematrixset:"GoogleMapsCompatible_Level"},variants:{ModisTerraTrueColorCR:"MODIS_Terra_CorrectedReflectance_TrueColor",ModisTerraBands367CR:"MODIS_Terra_CorrectedReflectance_Bands367",ViirsEarthAtNight2012:{options:{variant:"VIIRS_CityLights_2012",maxZoom:8}},ModisTerraLSTDay:{options:{variant:"MODIS_Terra_Land_Surface_Temp_Day",format:"png",maxZoom:7,opacity:.75}},ModisTerraSnowCover:{options:{variant:"MODIS_Terra_Snow_Cover",format:"png",maxZoom:8,opacity:.75}},ModisTerraAOD:{options:{variant:"MODIS_Terra_Aerosol",format:"png",maxZoom:6,opacity:.75}},ModisTerraChlorophyll:{options:{variant:"MODIS_Terra_Chlorophyll_A",format:"png",maxZoom:7,opacity:.75}}}},NLS:{url:"https://nls-{s}.tileserver.com/nls/{z}/{x}/{y}.jpg",options:{attribution:'<a href="http://geo.nls.uk/maps/">National Library of Scotland Historic Maps</a>',bounds:[[49.6,-12],[61.7,3]],minZoom:1,maxZoom:18,subdomains:"0123"}},JusticeMap:{url:"http://www.justicemap.org/tile/{size}/{variant}/{z}/{x}/{y}.png",options:{attribution:'<a href="http://www.justicemap.org/terms.php">Justice Map</a>',size:"county",bounds:[[14,-180],[72,-56]]},variants:{income:"income",americanIndian:"indian",asian:"asian",black:"black",hispanic:"hispanic",multi:"multi",nonWhite:"nonwhite",white:"white",plurality:"plural"}},Wikimedia:{url:"https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}{r}.png",options:{attribution:'<a href="https://wikimediafoundation.org/wiki/Maps_Terms_of_Use">Wikimedia</a>',minZoom:1,maxZoom:19}},GeoportailFrance:{url:"https://wxs.ign.fr/{apikey}
13979/geoportail/wmts?REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&STYLE={style}&TILEMATRIXSET=PM&FORMAT={format}&LAYER={variant}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}",options:{attribution:'<a target="_blank" href="https://www.geoportail.gouv.fr/">Geoportail France</a>',bounds:[[-75,-180],[81,180]],minZoom:2,maxZoom:18,apikey:"choisirgeoportail",format:"image/jpeg",style:"normal",variant:"GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD"},variants:{parcels:{options:{variant:"CADASTRALPARCELS.PARCELS",maxZoom:20,style:"bdparcellaire",format:"image/png"}},ignMaps:"GEOGRAPHICALGRIDSYSTEMS.MAPS",maps:"GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD",orthos:{options:{maxZoom:19,variant:"ORTHOIMAGERY.ORTHOPHOTOS"}}}}},u.tileLayer.provider=function(a,t){return new u.TileLayer.Provider(a,t)},u}); 13980!function(t){function o(e){var t={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return n&&(t[Symbol.iterator]=function(){return t}),t}function i(t){return encodeURIComponent(t).replace(/%20/g,"+")}function r(t){return decodeURIComponent(t).replace(/\+/g," ")}var s,e,n=function(){try{return!!Symbol.iterator}catch(t){return!1}}();"URLSearchParams"in t&&"a=1"===new URLSearchParams("?a=1").toString()||((e=(s=function(t){if(Object.defineProperty(this,"_entries",{writable:!0,value:{}}),"string"==typeof t)""!==t&&this._fromString(t);else if(t instanceof s){var n=this;t.forEach(function(t,e){n.append(e,t)})}else{if(null===t||"object"!=typeof t)throw new TypeError("Unsupported input's type for URLSearchParams");if("[object Array]"===Object.prototype.toString.call(t))for(var e=0;e<t.length;e++){var o=t[e];if("[object Array]"!==Object.prototype.toString.call(o)&&2===o.length)throw new TypeError("Expected [string, any] as entry at index "+e+" of URLSearchParams's input");this.append(o[0],o[1])}else for(var i in t)t.hasOwnProperty(i)&&this.append(i,t[i])}}).prototype).append=function(t,e){t in this._entries?this._entries[t].push(String(e)):this._entries[t]=[String(e)]},e.delete=function(t){delete this._entries[t]},e.get=function(t){return t in this._entries?this._entries[t][0]:null},e.getAll=function(t){return t in this._entries?this._entries[t].slice(0):[]},e.has=function(t){return t in this._entries},e.set=function(t,e){this._entries[t]=[String(e)]},e.forEach=function(t,e){var n;for(var o in this._entries)if(this._entries.hasOwnProperty(o)){n=this._entries[o];for(var i=0;i<n.length;i++)t.call(e,n[i],o,this)}},e.keys=function(){var n=[];return this.forEach(function(t,e){n.push(e)}),o(n)},e.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),o(e)},e.entries=function(){var n=[];return this.forEach(function(t,e){n.push([e,t])}),o(n)},n&&(e[Symbol.iterator]=e.entries),e.toString=function(){var n=[];return this.forEach(function(t,e){n.push(i(e)+"="+i(t))}),n.join("&")},t.URLSearchParams=s);var a=URLSearchParams.prototype;"function"!=typeof a.sort&&(a.sort=function(){var n=this,o=[];this.forEach(function(t,e){o.push([e,t]),n._entries||n.delete(e)}),o.sort(function(t,e){return t[0]<e[0]?-1:t[0]>e[0]?1:0}),n._entries&&(n._entries={});for(var t=0;t<o.length;t++)this.append(o[t][0],o[t][1])}),"function"!=typeof a._fromString&&Object.defineProperty(a,"_fromString",{enumerable:!1,configurable:!1,writable:!1,value:function(t){if(this._entries)this._entries={};else{var n=this;this.searchParams.forEach(function(t,e){n.delete(e)})}for(var e,o=(t=t.replace(/^\?/,"")).split("&"),i=0;i<o.length;i++)e=o[i].split("="),this.append(r(e[0]),1<e.length?r(e[1]):"")}})}("undefined"!=typeof global?global:"undefined"!=typeof window?window:"undefined"!=typeof self?self:this),function(h){var e,n;function t(t,e){"string"!=typeof t&&(t=String(t));var n,o=document;if(e&&(void 0===h.location||e!==h.location.href)){(n=(o=document.implementation.createHTMLDocument("")).createElement("base")).href=e,o.head.appendChild(n);try{if(0!==n.href.indexOf(e))throw new Error(n.href)}catch(t){throw new Error("URL unable to set base "+e+" due to "+t)}}var i=o.createElement("a");if(i.href=t,n&&(o.body.appendChild(i),i.href=i.href),":"===i.protocol||!/:/.test(i.href))throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:i});
13980var r=new URLSearchParams(this.search),s=!0,a=!0,p=this;["append","delete","set"].forEach(function(t){var e=r[t];r[t]=function(){e.apply(r,arguments),s&&(a=!1,p.search=r.toString(),a=!0)}}),Object.defineProperty(this,"searchParams",{value:r,enumerable:!0});var u=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==u&&(u=this.search,a&&(s=!1,this.searchParams._fromString(this.search),s=!0))}})}if(function(){try{var t=new URL("b","http://a");return t.pathname="c%20d","http://a/c%20d"===t.href&&t.searchParams}catch(t){return!1}}()||(e=h.URL,n=t.prototype,["hash","host","hostname","port","protocol"].forEach(function(t){!function(e){Object.defineProperty(n,e,{get:function(){return this._anchorElement[e]},set:function(t){this._anchorElement[e]=t},enumerable:!0})}(t)}),Object.defineProperty(n,"search",{get:function(){return this._anchorElement.search},set:function(t){this._anchorElement.search=t,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(n,{toString:{get:function(){var t=this;return function(){return t.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(t){this._anchorElement.href=t,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(t){this._anchorElement.pathname=t},enumerable:!0},origin:{get:function(){var t={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],e=this._anchorElement.port!=t&&""!==this._anchorElement.port;return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(e?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(t){},enumerable:!0},username:{get:function(){return""},set:function(t){},enumerable:!0}}),t.createObjectURL=function(t){return e.createObjectURL.apply(e,arguments)},t.revokeObjectURL=function(t){return e.revokeObjectURL.apply(e,arguments)},h.URL=t),void 0!==h.location&&!("origin"in h.location)){function o(){return h.location.protocol+"//"+h.location.hostname+(h.location.port?":"+h.location.port:"")}try{Object.defineProperty(h.location,"origin",{get:o,enumerable:!0})}catch(t){setInterval(function(){h.location.origin=o()},100)}}}("undefined"!=typeof global?global:"undefined"!=typeof window?window:"undefined"!=typeof self?self:this),L.Contao=L.Evented.extend({statics:{ATTRIBUTION:' | <a href="https://netzmacht.de/contao-leaflet" title="Powered by Leaflet extension for Contao CMS developed by netzmacht David Molineus">netzmacht</a>'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,e){return this.maps[t]=e,this.fire("map:added",{id:t,map:e}),this},getMap:function(t){return void 0===this.maps[t]?null:this.maps[t]},addIcon:function(t,e){return this.icons[t]=e,this.fire("icon:added",{id:t,icon:e}),this},loadIcons:function(t){for(var e=0;e<t.length;e++){var n;n="extraMarkers.icon"===t[e].type?L.ExtraMarkers.icon(t[e].options):L[t[e].type](t[e].options),this.addIcon(t[e].id,n)}},getIcon:function(t){return void 0===this.icons[t]?null:this.icons[t]},load:function(t,e,n,o,i){var r=this.createRequestUrl(t,i);return this.loadFile(r,e,n,o,i)},loadUrl:function(t,e,n,o,i){t=this.applyFilterToUrl(t,i);var r=omnivore[e](t,n,o);return i&&(L.stamp(r),i.options.dynamicLoad&&"fit"==r.options.boundsMode&&(r.options.requestUrl=t,i.on("moveend",r.refreshData,r),i.on("layerremove",function(t){t.layer===r&&i.off("moveend",r.updateBounds,r)})),i.fire("dataloading",{layer:r}),r.on("ready",function(){i.calculateFeatureBounds(r),i.fire("dataload",{layer:r})}),r.on("error",function(){i.fire("dataload",{layer:r})})),r},loadFile:function(t,e,n,o,i){return this.loadUrl(t,e,n,o,i)},pointToLayer:function(t,e){var n="marker",o=null;if(t.properties&&(t.properties.bounds=!0,t.properties.type&&(n=t.properties.type),t.properties.arguments&&(o=L[n].apply(L[n],t.properties.arguments),L.Util.setOptions(o,t.properties.options))),null===o&&(o=L[n](e,t.properties.options)),t.properties){if(t.properties.radius&&o.setRadius(t.properties.radius),t.properties.icon){var i=this.getIcon(t.properties.icon);i&&o.setIcon(i)}this.bindPopupFromFeature(o,t)}return this.fire("point:added",{marker:o,feature:t,latlng:e,type:n}),o},onEachFeature:function(t,e){t.properties&&(L.Util.setOptions(e,t.properties.options),this.bindPopupFromFeature(e,t),this.fire("feature:added",{feature:t,layer:e}))},bindPopupFromFeature:function(t,e){e.properties&&(e.properties.popup?t.bindPopup(e.properties.popup,e.properties.popupOptions):e.properties.popupContent&&t.bindPopup(e.properties.popupContent,e.properties.popupOptions))},setGeoJsonListeners:function(t){t&&t.prototype&&(t.prototype.options={pointToLayer:this.pointToLayer.bind(this),onEachFeature:this.onEachFeature.bind(this)})},createRequestUrl:function(t,e){var n,o="leaflet",i=document.location.search.substr(1).split("&");if(t=encodeURIComponent(t),""==i)t=document.location.pathname+"?"+[o,t].join("=");else{for(var r,s=i.length;s--;)if((r=i[s].split("="))[0]==o){r[1]=t,i[s]=r.join("=");break}s<0&&(i[i.length]=[o,t].join("=")),t=document.location.pathname+"?"+i.join("&")}return e&&e.options.dynamicLoad&&(t+="&f=bbox&v=",t+=(n=e.getBounds()).getSouth()+","+n.getWest(),t+=","+n.getNorth()+","+n.getEast()),t},applyFilterToUrl:function(t,e){var n,o,i;return e&&e.options.dynamicLoad?(t=new URL(t),o=new URLSearchParams(t.search),n=(i=e.getBounds()).getSouth()+","+i.getWest(),n+=","+i.getNorth()+","+i.getEast(),o.set("filter","bbox"),o.set("values",n),t.search=o.toString(),t.toString()):t}}
13980),L.contao=new L.Contao,L.Control.Attribution.addInitHook(function(){this.options.prefix+=L.Contao.ATTRIBUTION}),L.Control.Attribution.include({setPrefix:function(t){return-1===t.indexOf(L.Contao.ATTRIBUTION)&&(t+=L.Contao.ATTRIBUTION),this.options.prefix=t,this._update(),this}}),L.GeoJSON.include({refreshData:function(t){var e=L.geoJson(),n=this;e.on("ready",function(){var t,e=n.getLayers();for(t=0;t<e.length;t++)n.removeLayer(e[t]);for(e=this.getLayers(),t=0;t<e.length;t++)this.removeLayer(e[t]),n.addLayer(e[t])}),omnivore.geojson(L.contao.applyFilterToUrl(this.options.requestUrl,t.target),null,e)}}),L.Map.include({_dynamicBounds:null,calculateFeatureBounds:function(t,e){if(t){if(!this.options.adjustBounds&&!e)return;this._scanForBounds(t)}else this.eachLayer(this._scanForBounds,this);this._dynamicBounds&&this.fitBounds(this._dynamicBounds,this.getBoundsOptions())},getBoundsOptions:function(){return options={},this.options.boundsPadding?options.padding=this.options.boundsPadding:(this.options.boundsPaddingTopLeft&&(options.paddingTopLeft=this.options.boundsPaddingTopLeft),this.options.boundsPaddingBottomRight&&(options.paddingBottomRight=this.options.boundsPaddingBottomRight)),options},_scanForBounds:function(t){var e;!t.feature||t.feature.properties&&t.feature.properties.ignoreForBounds?L.MarkerClusterGroup&&t instanceof L.MarkerClusterGroup&&t.options.boundsMode&&"extend"==t.options.boundsMode?(e=t.getBounds()).isValid()&&(this._dynamicBounds?this._dynamicBounds.extend(e):this._dynamicBounds=L.latLngBounds(e.getSouthWest
13980(),e.getNorthEast())):(!t.options||t.options&&t.options.boundsMode&&!t.options.ignoreForBounds)&&t.eachLayer&&t.eachLayer(this._scanForBounds,this):t.getBounds?(e=t.getBounds()).isValid()&&(this._dynamicBounds?this._dynamicBounds.extend(e):this._dynamicBounds=L.latLngBounds(e.getSouthWest(),e.getNorthEast())):t.getLatLng&&(e=t.getLatLng(),this._dynamicBounds?this._dynamicBounds.extend(e):this._dynamicBounds=L.latLngBounds(e,e))}}),L.LatLngBounds.prototype.toOverpassBBoxString=function(){var t=this._southWest,e=this._northEast;return[t.lat,t.lng,e.lat,e.lng].join(",")},L.OverPassLayer=L.FeatureGroup.extend({options:{minZoom:0,endpoint:"//overpass-api.de/api/",query:"(node(BBOX)[organic];node(BBOX)[second_hand];);out qt;",amenityIcons:{}},initialize:function(t){t.pointToLayer||(t.pointToLayer=this.pointToLayer),t.onEachFeature||(t.onEachFeature=this.onEachFeature),L.Util.setOptions(this,t),this.options.dynamicLoad=!!this.options.query.match(/BBOX/g),this._layer=L.geoJson(),this._layers={},this.addLayer(this._layer)},refreshData:function(){if(!(this._map.getZoom()<this.options.minZoom)){var t=this._map.getBounds().toOverpassBBoxString(),e=this.options.query.replace(/(BBOX)/g,t),n=this.options.endpoint+"interpreter?data=[out:json];"+e;this._map.fire("dataloading",{layer:this}),this.request(n,function(t,e){var n=JSON.parse(e.response),o=osmtogeojson(n),i=L.geoJson(o,{pointToLayer:this.options.pointToLayer.bind(this),onEachFeature:this.options.onEachFeature.bind(this)});if(this.addLayer(i),this.removeLayer(this._layer),this._layer=i,"extend"===this.options.boundsMode&&i.getBounds().isValid()){var r=this._map.getBounds();r=r.extend(i.getBounds()),this._map.fitBounds(r,this._map.getBoundsOptions())}this._map.fire("dataload",{layer:this})}.bind(this))}},onAdd:function(t){"fit"===this.options.boundsMode&&this.options.dynamicLoad&&t.on("moveend",this.refreshData,this),this.refreshData()},pointToLayer:function(t,e){var n=null,o=L.marker(e,t.properties.options);return t.properties&&(t.properties.radius&&o.setRadius(t.properties.radius),t.properties.icon?n=this._map.getIcon(t.properties.icon):t.properties.tags&&t.properties.tags.amenity&&this.options.amenityIcons[t.properties.tags.amenity]&&(n=L.contao.getIcon(this.options.amenityIcons[t.properties.tags.amenity])),n&&o.setIcon(n)),this.options.overpassPopup&&o.bindPopup(this.options.overpassPopup(t,o)),this._map.fire("point:added",{marker:o,feature:t,latlng:e,type:"marker"}),o},onEachFeature:function(t,e){t.properties&&(L.Util.setOptions(e,t.properties.options),this.options.overpassPopup&&e.bindPopup(this.options.overpassPopup(t,e)),this._map.fire("feature:added",{feature:t,layer:e}))},request:function(t,e,n){var o=!1;if(void 0===window.XMLHttpRequest)return e(Error("Browser not supported"));if(void 0===n){var i=t.match(/^\s*https?:\/\/[^\/]*/);n=i&&i[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var r=new window.XMLHttpRequest;if(n&&!("withCredentials"in r)){r=new window.XDomainRequest;var s=e;e=function(){if(o)s.apply(this,arguments);else{var t=this,e=arguments;setTimeout(function(){s.apply(t,e)},0)}}}function a(){void 0===r.status||function(t){return 200<=t&&t<300||304===t}(r.status)?e.call(r,null,r):e.call(r,r,null)}return"onload"in r?r.onload=a:r.onreadystatechange=function(){4===r.readyState&&a()},r.onerror=function(t){e.call(this,t||!0,null),e=function(){}},r.onprogress=function(){},r.ontimeout=function(t){e.call(this,t,null),e=function(){}},r.onabort=function(t){e.call(this,t,null),e=function(){}},r.open("GET",t,!0),r.send(null),o=!0,r}});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.